diff --git a/.drone.yml b/.drone.yml index 26221a5f9..a5ebc2ad1 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1,7 +1,8 @@ --- + kind: pipeline type: docker -name: EQEmulator Server Linux CI +name: Build Linux # Limits how many of these builds can run on the drone runner at a time, this isn't about cores concurrency: @@ -10,18 +11,88 @@ concurrency: volumes: - name: cache host: - path: /var/lib/cache + path: /var/lib/cache-release steps: - - name: server-build - # Source build script https://github.com/Akkadius/akk-stack/blob/master/containers/eqemu-server/Dockerfile#L20 + - name: Build Linux X64 image: akkadius/eqemu-server:v11 + 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: - - sudo chown eqemu:eqemu /drone/src/ * -R - - sudo chown eqemu:eqemu /home/eqemu/.ccache/ * -R - - git submodule init && git submodule update && mkdir -p build && cd build && cmake -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_LUA=ON -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING="-O0 -g -DNDEBUG" -G 'Unix Makefiles' .. && make -j$((`nproc`-4)) - - curl https://raw.githubusercontent.com/Akkadius/eqemu-install-v2/master/eqemu_config.json --output eqemu_config.json - - ./bin/tests + - ./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 + + diff --git a/.gitignore b/.gitignore index 40075fa6c..e19929979 100644 --- a/.gitignore +++ b/.gitignore @@ -62,4 +62,12 @@ compile_flags.txt .cache/ # vscode generated settings -.vscode/ \ No newline at end of file +.vscode/ + +# Build pipeline +!utils/scripts/build/ +!utils/scripts/build/should-release/should-release +!utils/scripts/build/should-release/should-release.exe + +# CMake Files +cmake-build-relwithdebinfo/* diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..7089f4ea4 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,1068 @@ +## [22.4.5] - 03/03/2023 + +### Bots + +* Add additional Heroic Sta/Wis/Int bonuses for Bots. ([#3013](https://github.com/EQEmu/Server/pull/3013)) @Aeadoin 2023-03-01 +* Cleanup AI_IdleCastCheck Logic ([#3004](https://github.com/EQEmu/Server/pull/3004)) @Aeadoin 2023-02-26 + +### Code + +* Delete unused zone/skills.h ([#3007](https://github.com/EQEmu/Server/pull/3007)) @Kinglykrab 2023-02-27 +* Remove DumpPacketProfile() from client.h ([#3000](https://github.com/EQEmu/Server/pull/3000)) @Kinglykrab 2023-02-26 +* Remove GetCombinedAC_TEST() from client.h ([#2999](https://github.com/EQEmu/Server/pull/2999)) @Kinglykrab 2023-02-26 +* Remove GetDamageMultiplier() from client.h ([#3001](https://github.com/EQEmu/Server/pull/3001)) @Kinglykrab 2023-02-26 +* Remove NumberOfAvailableTitles() from titles.h ([#3006](https://github.com/EQEmu/Server/pull/3006)) @Kinglykrab 2023-02-27 +* Remove ReturnItemPacket from client.h/inventory.cpp ([#3002](https://github.com/EQEmu/Server/pull/3002)) @Kinglykrab 2023-02-26 +* Remove class EGNode from mob.h ([#3003](https://github.com/EQEmu/Server/pull/3003)) @Kinglykrab 2023-02-26 +* Remove unused ClientFactory in client.h ([#2998](https://github.com/EQEmu/Server/pull/2998)) @Kinglykrab 2023-02-26 +* Remove unused iterator from LoadCharacterDisciplines ([#3012](https://github.com/EQEmu/Server/pull/3012)) @Aeadoin 2023-03-02 + +### Crash + +* Fix crash in CheckTradeskillLoreConflict ([#3009](https://github.com/EQEmu/Server/pull/3009)) @Aeadoin 2023-02-28 + +### Fixes + +* Account for bad data in Tradeskill Recipe Entries ([#2991](https://github.com/EQEmu/Server/pull/2991)) @Aeadoin 2023-02-25 +* Fix DoAnim quest method default speed ([#3016](https://github.com/EQEmu/Server/pull/3016)) @Kinglykrab 2023-03-01 +* Fix an issue where EVENT_TIMER timers would not be cleaned up after zone ([#3018](https://github.com/EQEmu/Server/pull/3018)) @noudess 2023-03-03 +* Fix for Discipline Loading from Database causing issues with slot_ids ([#3008](https://github.com/EQEmu/Server/pull/3008)) @Aeadoin 2023-02-28 +* Fix for Lore Components where component is returned. ([#3005](https://github.com/EQEmu/Server/pull/3005)) @Aeadoin 2023-02-27 +* Fix issue where quest saylink responses would occur before the NPC's response ([#3010](https://github.com/EQEmu/Server/pull/3010)) @Akkadius 2023-03-01 +* Fix log messages when players join channel ([#2992](https://github.com/EQEmu/Server/pull/2992)) @Valorith 2023-03-03 +* Fix npcfeature and playerfeature ([#3017](https://github.com/EQEmu/Server/pull/3017)) @Kinglykrab 2023-03-02 + +### Quest API + +* Add GetDefaultRaceSize() to Perl/Lua ([#2993](https://github.com/EQEmu/Server/pull/2993)) @Kinglykrab 2023-02-27 +* Add HasSpecialAbilities() to Perl/Lua ([#2994](https://github.com/EQEmu/Server/pull/2994)) @Kinglykrab 2023-02-27 +* Add IsBerserk() to Perl/Lua ([#2997](https://github.com/EQEmu/Server/pull/2997)) @Kinglykrab 2023-03-01 +* Add IsFindable() and IsTrackable() to Perl/Lua ([#2996](https://github.com/EQEmu/Server/pull/2996)) @Kinglykrab 2023-03-01 +* Add IsUnderwaterOnly() to Perl/Lua ([#2995](https://github.com/EQEmu/Server/pull/2995)) @Kinglykrab 2023-03-01 + +## [22.4.4] - 02/24/2023 + +### Bots + +* Add Caster Range Command, and IsValidSpellRange Checks ([#2942](https://github.com/EQEmu/Server/pull/2942)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-23 +* Cleanup BotDatabase::LoadBuffs ([#2981](https://github.com/EQEmu/Server/pull/2981)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-24 +* Verify Bots Group Integrity on join ([#2980](https://github.com/EQEmu/Server/pull/2980)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-23 + +### Commands + +* Cleanup #peekinv Command ([#2969](https://github.com/EQEmu/Server/pull/2969)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-23 + +### Doors + +* Fix doors triggering invalid zone fetches of dest_zone of "none" ([#2985](https://github.com/EQEmu/Server/pull/2985)) ([Akkadius](https://github.com/Akkadius)) 2023-02-24 + +### Fixes + +* Adjust database manifest to include .sql extension ([Akkadius](https://github.com/Akkadius)) 2023-02-25 +* Correct Mend reuse time and add reduction support. ([#2972](https://github.com/EQEmu/Server/pull/2972)) ([nytmyr](https://github.com/nytmyr)) 2023-02-23 +* Fix Beneficial Target of Target procs ([#2987](https://github.com/EQEmu/Server/pull/2987)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-24 +* Fix for undefined MySQL library behavior. ([#2834](https://github.com/EQEmu/Server/pull/2834)) ([KimLS](https://github.com/KimLS)) 2023-02-25 + +### Pathing + +* Improve roambox logic ([#2983](https://github.com/EQEmu/Server/pull/2983)) ([Akkadius](https://github.com/Akkadius)) 2023-02-24 +* More z-clip improvements, Wurm and Spectral Iksar race adjustments ([#2988](https://github.com/EQEmu/Server/pull/2988)) ([Akkadius](https://github.com/Akkadius)) 2023-02-25 +* Smoother pathing z-correction ([#2982](https://github.com/EQEmu/Server/pull/2982)) ([Akkadius](https://github.com/Akkadius)) 2023-02-24 + +### Player Events + +* Add QS processing, mutex tweaks ([#2984](https://github.com/EQEmu/Server/pull/2984)) ([Akkadius](https://github.com/Akkadius)) 2023-02-25 + +### Quest API + +* Add IsAutoAttackEnabled() to Perl/Lua ([#2979](https://github.com/EQEmu/Server/pull/2979)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-23 +* Add IsAutoFireEnabled() to Perl/Lua ([#2978](https://github.com/EQEmu/Server/pull/2978)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-23 +* Fix EVENT_TIMER crash when entity is no longer available ([#2986](https://github.com/EQEmu/Server/pull/2986)) ([Akkadius](https://github.com/Akkadius)) 2023-02-24 + +### Scaling + +* Add support for zone ID and instance version to NPC Scaling ([#2968](https://github.com/EQEmu/Server/pull/2968)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-25 + +### Tradeskills + +* Fix for Lore Conflict ([#2977](https://github.com/EQEmu/Server/pull/2977)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-24 + +## [22.4.3] - 02/21/2023 + +### Bots + +* Change HasBotItem(item_id) to return slot_id instead of bool. ([#2966](https://github.com/EQEmu/Server/pull/2966)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-19 +* Change SaveTimers to Replace instead of Insert. ([#2951](https://github.com/EQEmu/Server/pull/2951)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-18 +* Fix output of ^spells while ^Enforcespellsettings is enabled ([#2959](https://github.com/EQEmu/Server/pull/2959)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-18 + +### Crash + +* Fix crash with EVENT_UNEQUIP_ITEM_BOT ([#2973](https://github.com/EQEmu/Server/pull/2973)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-20 +* Fix world crash in player event processing ([#2960](https://github.com/EQEmu/Server/pull/2960)) ([Akkadius](https://github.com/Akkadius)) 2023-02-18 + +### Database + +* Address deadlock in player events ([#2974](https://github.com/EQEmu/Server/pull/2974)) ([Akkadius](https://github.com/Akkadius)) 2023-02-21 + +### Fixes + +* Fix MIR LDoN Theme Items on LDoN Merchants ([#2971](https://github.com/EQEmu/Server/pull/2971)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-20 +* Fix OOCMute not functioning ([#2970](https://github.com/EQEmu/Server/pull/2970)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-20 + +### Pathing + +* Improvements to z-clipping, z-recovery and z-calculations ([#2975](https://github.com/EQEmu/Server/pull/2975)) ([Akkadius](https://github.com/Akkadius)) 2023-02-21 + +### Pets + +* Client Pet summoned by NPC should not change guard location. ([#2967](https://github.com/EQEmu/Server/pull/2967)) ([noudess](https://github.com/noudess)) 2023-02-19 + +### Player Events + +* Create new event ITEM_CREATION ([#2944](https://github.com/EQEmu/Server/pull/2944)) ([Akkadius](https://github.com/Akkadius)) 2023-02-18 + +### Quest API + +* Add client->SignalClient() overload to Perl ([#2963](https://github.com/EQEmu/Server/pull/2963)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-19 +* Fix Perl SetSimpleRoamBox Overloads ([#2961](https://github.com/EQEmu/Server/pull/2961)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-19 + +### Reload API + +* Add world handlers for certain opcodes ([#2958](https://github.com/EQEmu/Server/pull/2958)) ([Akkadius](https://github.com/Akkadius)) 2023-02-18 + +### SQL + +* Add date to optional Drakkin Guktan Faction Update ([#2965](https://github.com/EQEmu/Server/pull/2965)) ([joligario](https://github.com/joligario)) 2023-02-19 + +## [22.4.2] - 02/18/2023 + +### Content + +* Added optional SQL 2023_02_17_fix_sseru_mischief_doors.sql to fix sseru/mischief doors ([#2955](https://github.com/EQEmu/Server/pull/2955)) ([Akkadius](https://github.com/Akkadius)) 2023-02-18 + +### Logging + +* Remove noisy raid/group/forage errors ([#2952](https://github.com/EQEmu/Server/pull/2952)) ([Akkadius](https://github.com/Akkadius)) 2023-02-18 + +### MySQL + +* Add keepalives to UCS and Loginserver ([#2953](https://github.com/EQEmu/Server/pull/2953)) ([Akkadius](https://github.com/Akkadius)) 2023-02-18 + +### Player Events + +* Add logging category to hold processing batch logs ([#2954](https://github.com/EQEmu/Server/pull/2954)) ([Akkadius](https://github.com/Akkadius)) 2023-02-18 + +### Tradeskills + +* Fix regression caused by #2932 ([#2956](https://github.com/EQEmu/Server/pull/2956)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-18 + +## [22.4.1] - 02/17/2023 + +### Bots + +* Set Taunt to enabled for SK/Paladin Bots by Default. ([#2941](https://github.com/EQEmu/Server/pull/2941)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-17 + +### DevTools + +* Fix NPC targetting dev tools display window ([#2943](https://github.com/EQEmu/Server/pull/2943)) ([Akkadius](https://github.com/Akkadius)) 2023-02-17 + +### Fixes + +* Issue with AssignRaidToInstance that was using the groups repository instead of raid ([#2947](https://github.com/EQEmu/Server/pull/2947)) ([Akkadius](https://github.com/Akkadius)) 2023-02-17 +* Missing comma in schema list breaking dumps ([Akkadius](https://github.com/Akkadius)) 2023-02-17 + +### Player Events + +* Fix issue with item instances not being validated properly before accessing causing crashes on handin ([#2945](https://github.com/EQEmu/Server/pull/2945)) ([Akkadius](https://github.com/Akkadius)) 2023-02-17 +* Fix rare out of bound issue when loading event types ([#2946](https://github.com/EQEmu/Server/pull/2946)) ([Akkadius](https://github.com/Akkadius)) 2023-02-17 +* Turn off KILLED_NPC (trash) off by default ([#2948](https://github.com/EQEmu/Server/pull/2948)) ([Akkadius](https://github.com/Akkadius)) 2023-02-17 + +## [22.4.0] - 02/17/2023 + +### Bots + +* Add Additional HeroicAgi/Dex Modifiers. ([#2838](https://github.com/EQEmu/Server/pull/2838)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-07 +* Add Additional HeroicStr modifiers. ([#2837](https://github.com/EQEmu/Server/pull/2837)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-07 +* Add IsBot() to methods in attack.cpp where applicable. ([#2840](https://github.com/EQEmu/Server/pull/2840)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-09 +* Add Lore Check for Augments. ([#2874](https://github.com/EQEmu/Server/pull/2874)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-12 +* Add Pet Power Support for Temp Pets. ([#2853](https://github.com/EQEmu/Server/pull/2853)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-11 +* Add Support for TryTriggerOnCastFocusEffect ([#2864](https://github.com/EQEmu/Server/pull/2864)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-13 +* Add TotalDominationBonus modifiers. ([#2852](https://github.com/EQEmu/Server/pull/2852)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-09 +* ST_AreaClientOnly spells to land on Bots ([#2849](https://github.com/EQEmu/Server/pull/2849)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-09 +* Update ResistSpell to use temp_level_diff client formula ([#2851](https://github.com/EQEmu/Server/pull/2851)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-09 + +### Bots & Mercenaries + +* Add 100% Hit chance if sitting while attacked. ([#2839](https://github.com/EQEmu/Server/pull/2839)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-07 +* Add Support for TrySympatheticProc ([#2866](https://github.com/EQEmu/Server/pull/2866)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-13 + +### CI + +* Fix Windows stderr not bubbling properly ([#2925](https://github.com/EQEmu/Server/pull/2925)) ([Akkadius](https://github.com/Akkadius)) 2023-02-14 + +### Code + +* Add IsOfClientBot() virtual method. ([#2845](https://github.com/EQEmu/Server/pull/2845)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-07 +* Doors EVENT_CLICK_DOOR syntax adjustment ([Akkadius](https://github.com/Akkadius)) 2023-02-14 +* Remove Unused Mod Hooks ([#2856](https://github.com/EQEmu/Server/pull/2856)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 + +### Crash + +* Crash fix where invalid input to #heromodel would crash zone ([#2937](https://github.com/EQEmu/Server/pull/2937)) ([Akkadius](https://github.com/Akkadius)) 2023-02-15 +* Fix Bot Crash in Bot::Bot Constructor. ([#2868](https://github.com/EQEmu/Server/pull/2868)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-12 +* Fix Crash in FindType ([#2867](https://github.com/EQEmu/Server/pull/2867)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-13 +* Fix crash in Mob::CommonDamage when attacker was null ([#2872](https://github.com/EQEmu/Server/pull/2872)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-13 +* Fix crash issue with dropping items and order of operations ([#2939](https://github.com/EQEmu/Server/pull/2939)) ([joligario](https://github.com/joligario)) 2023-02-16 +* Fix issue where long short names overflow file_name ([Akkadius](https://github.com/Akkadius)) 2023-02-09 +* Fix potential crash in Mob::CommonDamage ([#2848](https://github.com/EQEmu/Server/pull/2848)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-09 + +### Doors + +* Fix issue where NPC's wouldn't open doors because door param overflow ([#2934](https://github.com/EQEmu/Server/pull/2934)) ([Akkadius](https://github.com/Akkadius)) 2023-02-15 + +### Feature + +* Add IsOfClientBotMerc() virtual method. ([#2843](https://github.com/EQEmu/Server/pull/2843)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-07 + +### Fixes + +* Another doors fix ([Akkadius](https://github.com/Akkadius)) 2023-02-14 +* Fix CheckNumHitsRemaining() with 1H Blunt ([#2846](https://github.com/EQEmu/Server/pull/2846)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-07 +* Fix Door opening regression caused by #2880 ([Akkadius](https://github.com/Akkadius)) 2023-02-14 +* Fix EVENT_SPELL_EFFECT_TRANSLOCATE_COMPLETE regression caused by #2897 ([#2928](https://github.com/EQEmu/Server/pull/2928)) ([Akkadius](https://github.com/Akkadius)) 2023-02-14 +* Fix HP_EVENT regression ([#2927](https://github.com/EQEmu/Server/pull/2927)) ([Akkadius](https://github.com/Akkadius)) 2023-02-14 +* Fix crash in EVENT_DISCOVER_ITEM ([#2933](https://github.com/EQEmu/Server/pull/2933)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-15 +* Fix crash where dropped items crash Lua logic ([#2936](https://github.com/EQEmu/Server/pull/2936)) ([Akkadius](https://github.com/Akkadius)) 2023-02-15 +* Fix for interrupting item casts to no longer lock the client if cast time of item greater than 0 ([#2921](https://github.com/EQEmu/Server/pull/2921)) ([Natedog2012](https://github.com/Natedog2012)) 2023-02-13 +* Fix issue where Lore groundspawn pickups will desync ROF2+ ([#2929](https://github.com/EQEmu/Server/pull/2929)) ([Akkadius](https://github.com/Akkadius)) 2023-02-14 +* Fix issue with EVENT_HP firing regression from #2904 ([#2924](https://github.com/EQEmu/Server/pull/2924)) ([Akkadius](https://github.com/Akkadius)) 2023-02-14 +* Replace uses of SPELL_UNKNOWN with IsValidSpell() ([#2938](https://github.com/EQEmu/Server/pull/2938)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-16 +* Self Only Spells will no longer check target level or buff restrictions ([#2931](https://github.com/EQEmu/Server/pull/2931)) ([noudess](https://github.com/noudess)) 2023-02-15 + +### Groundspawns + +* Fix issue where groundspawns appear floating high off the ground ([#2930](https://github.com/EQEmu/Server/pull/2930)) ([Akkadius](https://github.com/Akkadius)) 2023-02-15 + +### Logging + +* Add raw opcode when emu translated opcode is not found (OP_Unknown) via (C->S) ([#2847](https://github.com/EQEmu/Server/pull/2847)) ([Akkadius](https://github.com/Akkadius)) 2023-02-08 +* Implement Player Event Logging system ([#2833](https://github.com/EQEmu/Server/pull/2833)) ([Akkadius](https://github.com/Akkadius)) 2023-02-13 + +### Quest API + +* (Performance) Check equip or scale item events exist before export and execute ([#2898](https://github.com/EQEmu/Server/pull/2898)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event EVENT_AA_BUY or EVENT_AA_GAIN exist before export and execute ([#2892](https://github.com/EQEmu/Server/pull/2892)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event EVENT_AGGRO, EVENT_ATTACK, or EVENT_COMBAT exist before export and execute ([#2901](https://github.com/EQEmu/Server/pull/2901)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event EVENT_COMBINE, EVENT_COMBINE_SUCCESS, EVENT_COMBINE_FAILURE, or EVENT_COMBINE_VALIDATE exist before export and execute ([#2896](https://github.com/EQEmu/Server/pull/2896)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event EVENT_DEATH, EVENT_DEATH_COMPLETE, or EVENT_DEATH_ZONE exist before export and execute ([#2909](https://github.com/EQEmu/Server/pull/2909)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event EVENT_ENVIRONMENTAL_DAMAGE exists before export and execute ([#2899](https://github.com/EQEmu/Server/pull/2899)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event EVENT_FEIGN_DEATH exists before export and execute ([#2916](https://github.com/EQEmu/Server/pull/2916)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event EVENT_ITEM_TICK or EVENT_WEAPON_PROC exist before export and execute ([#2914](https://github.com/EQEmu/Server/pull/2914)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event EVENT_LANGUAGE_SKILL_UP, EVENT_SKILL_UP, or EVENT_USE_SKILL exist before export and execute ([#2894](https://github.com/EQEmu/Server/pull/2894)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event EVENT_PAYLOAD or EVENT_SIGNAL exist before export and execute ([#2902](https://github.com/EQEmu/Server/pull/2902)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event EVENT_SLAY exists before export and execute ([#2910](https://github.com/EQEmu/Server/pull/2910)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event EVENT_WAYPOINT_ARRIVE or EVENT_WAYPOINT_DEPART exist before export and execute ([#2905](https://github.com/EQEmu/Server/pull/2905)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event exists before export and execute EVENT_AGGRO_SAY, EVENT_SAY, and EVENT_PROXIMITY_SAY ([#2882](https://github.com/EQEmu/Server/pull/2882)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event exists before export and execute EVENT_BOT_CREATE ([#2886](https://github.com/EQEmu/Server/pull/2886)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event exists before export and execute EVENT_CLICK_DOOR and EVENT_CLICK_OBJECT ([#2880](https://github.com/EQEmu/Server/pull/2880)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event exists before export and execute EVENT_DESPAWN and EVENT_DESPAWN_ZONE ([#2887](https://github.com/EQEmu/Server/pull/2887)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event exists before export and execute EVENT_DISCOVER_ITEM ([#2912](https://github.com/EQEmu/Server/pull/2912)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event exists before export and execute EVENT_DUEL_LOSE and EVENT_DUEL_WIN ([#2915](https://github.com/EQEmu/Server/pull/2915)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event exists before export and execute EVENT_ENTER_ZONE and EVENT_ZONE ([#2900](https://github.com/EQEmu/Server/pull/2900)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event exists before export and execute EVENT_GM_COMMAND ([#2890](https://github.com/EQEmu/Server/pull/2890)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event exists before export and execute EVENT_GROUP_CHANGE ([#2884](https://github.com/EQEmu/Server/pull/2884)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event exists before export and execute EVENT_HP ([#2904](https://github.com/EQEmu/Server/pull/2904)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event exists before export and execute EVENT_KILLED_MERIT ([#2911](https://github.com/EQEmu/Server/pull/2911)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event exists before export and execute EVENT_LEVEL_UP and EVENT_LEVEL_DOWN ([#2889](https://github.com/EQEmu/Server/pull/2889)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event exists before export and execute EVENT_POPUP_RESPONSE ([#2881](https://github.com/EQEmu/Server/pull/2881)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event exists before export and execute EVENT_RESPAWN ([#2917](https://github.com/EQEmu/Server/pull/2917)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event exists before export and execute EVENT_TICK ([#2919](https://github.com/EQEmu/Server/pull/2919)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event exists before export and execute EVENT_TIMER ([#2903](https://github.com/EQEmu/Server/pull/2903)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event exists before export and execute EVENT_TRADE ([#2906](https://github.com/EQEmu/Server/pull/2906)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event exists before export and execute EVENT_UNHANDLED_OPCODE ([#2918](https://github.com/EQEmu/Server/pull/2918)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event exists before export and execute EVENT_WARP ([#2907](https://github.com/EQEmu/Server/pull/2907)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event exists before export and execute area events ([#2888](https://github.com/EQEmu/Server/pull/2888)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check merchant events exist before export and execute ([#2893](https://github.com/EQEmu/Server/pull/2893)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check spell or cast events exist before export and execute ([#2897](https://github.com/EQEmu/Server/pull/2897)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check task events exist before export and execute ([#2883](https://github.com/EQEmu/Server/pull/2883)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event exists before export and execute EVENT_CONNECT and EVENT_DISCONNECT ([#2913](https://github.com/EQEmu/Server/pull/2913)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* (Performance) Check event exists before export and execute EVENT_TEST_BUFF ([#2920](https://github.com/EQEmu/Server/pull/2920)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* Add $target export to EVENT_INSPECT in Perl ([#2891](https://github.com/EQEmu/Server/pull/2891)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* Add Additional XP Events EVENT_AA_EXP_GAIN, EVENT_EXP_GAIN ([#2865](https://github.com/EQEmu/Server/pull/2865)) ([Valorith](https://github.com/Valorith)) 2023-02-13 +* Add EVENT_DESTROY_ITEM_CLIENT to Perl/Lua. ([#2871](https://github.com/EQEmu/Server/pull/2871)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* Add EVENT_DROP_ITEM_CLIENT to Perl/Lua ([#2869](https://github.com/EQEmu/Server/pull/2869)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* Add Recipe-based methods to Perl/Lua. ([#2844](https://github.com/EQEmu/Server/pull/2844)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-08 +* Export $door to EVENT_CLICKDOOR in Perl ([#2861](https://github.com/EQEmu/Server/pull/2861)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-11 +* Export $hate_entity to EVENT_HATE_LIST in Perl ([#2885](https://github.com/EQEmu/Server/pull/2885)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* Export $item and $augment to augment events in Perl ([#2895](https://github.com/EQEmu/Server/pull/2895)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* Export $item and $corpse to EVENT_LOOT and EVENT_LOOT_ZONE in Perl ([#2878](https://github.com/EQEmu/Server/pull/2878)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* Export $item to Client/Bot Equip Events in Perl ([#2860](https://github.com/EQEmu/Server/pull/2860)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-11 +* Export $item to EVENT_DISCOVER_ITEM in Perl ([#2863](https://github.com/EQEmu/Server/pull/2863)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-11 +* Export $item to EVENT_PLAYER_PICKUP in Perl. ([#2875](https://github.com/EQEmu/Server/pull/2875)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* Export $item to Fishing and Forage Events in Perl ([#2876](https://github.com/EQEmu/Server/pull/2876)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* Export $killed_npc to EVENT_NPC_SLAY to Perl ([#2879](https://github.com/EQEmu/Server/pull/2879)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* Export $object to EVENT_CLICK_OBJECT in Perl ([#2862](https://github.com/EQEmu/Server/pull/2862)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-11 +* Export $spawned to EVENT_SPAWN_ZONE in Perl ([#2877](https://github.com/EQEmu/Server/pull/2877)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* Export target to EVENT_TARGET_CHANGE in Perl/Lua. ([#2870](https://github.com/EQEmu/Server/pull/2870)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* Export targets to EVENT_CONSIDER and EVENT_CONSIDER_CORPSE ([#2908](https://github.com/EQEmu/Server/pull/2908)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 +* Fix SetSimpleRoamBox in Perl to have optional params again ([#2935](https://github.com/EQEmu/Server/pull/2935)) ([Akkadius](https://github.com/Akkadius)) 2023-02-15 + +### Rules + +* Add Group/Raid Experience Rules ([#2850](https://github.com/EQEmu/Server/pull/2850)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-13 + +### Tradeskills + +* Check if combine would result in lore conflict ([#2932](https://github.com/EQEmu/Server/pull/2932)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-16 + +### Windows + +* Fix MSVC compilation bug via workaround ([#2926](https://github.com/EQEmu/Server/pull/2926)) ([Akkadius](https://github.com/Akkadius)) 2023-02-14 + +## [22.3.0] - 02/06/2023 + +### Bots + +* Add GetAugmentIDsBySlotID & AddItem with table ref Methods. ([#2805](https://github.com/EQEmu/Server/pull/2805)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-29 + +### Commands + +* #list now searches without case sensitivity ([#2825](https://github.com/EQEmu/Server/pull/2825)) ([Akkadius](https://github.com/Akkadius)) 2023-02-06 +* Remove extraneous else from #weather ([#2819](https://github.com/EQEmu/Server/pull/2819)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-01 + +### Crash + +* Fix IsUnderwaterOnly crash where npc data references can be stale ([#2830](https://github.com/EQEmu/Server/pull/2830)) ([Akkadius](https://github.com/Akkadius)) 2023-02-06 +* Fix command crash with #npcedit weapon when second weapon not passed ni ([#2829](https://github.com/EQEmu/Server/pull/2829)) ([Akkadius](https://github.com/Akkadius)) 2023-02-06 +* Fix crash in bot command botdyearmor ([#2832](https://github.com/EQEmu/Server/pull/2832)) ([Akkadius](https://github.com/Akkadius)) 2023-02-06 + +### DB Updates + +* Add Windows MySQL path auto detection for users where the path is not found ([#2836](https://github.com/EQEmu/Server/pull/2836)) ([Akkadius](https://github.com/Akkadius)) 2023-02-06 + +### Doors + +* Have NPCs trigger double doors ([#2821](https://github.com/EQEmu/Server/pull/2821)) ([Akkadius](https://github.com/Akkadius)) 2023-02-06 +* Remove door dev tools spam on client controlled doors ([#2824](https://github.com/EQEmu/Server/pull/2824)) ([Akkadius](https://github.com/Akkadius)) 2023-02-06 + +### Feature + +* Add Min/Max Status to Merchants ([#2806](https://github.com/EQEmu/Server/pull/2806)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-29 + +### Fixes + +* #reload aa will now refresh the AA table properly for every client when changes are made ([#2814](https://github.com/EQEmu/Server/pull/2814)) ([Natedog2012](https://github.com/Natedog2012)) 2023-01-31 +* #reload static should now properly fill the entity_lists for… ([#2815](https://github.com/EQEmu/Server/pull/2815)) ([Natedog2012](https://github.com/Natedog2012)) 2023-01-31 +* BuffLevelRestrictions were restricting group buffs if mob targeted ([#2809](https://github.com/EQEmu/Server/pull/2809)) ([noudess](https://github.com/noudess)) 2023-01-29 +* Fix does_augment_fit_slot method. ([#2817](https://github.com/EQEmu/Server/pull/2817)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-01 +* Fix NPC ghosting at safe coordinates ([#2823](https://github.com/EQEmu/Server/pull/2823)) ([Akkadius](https://github.com/Akkadius)) 2023-02-06 +* Fixing % based mob see invis ([#2802](https://github.com/EQEmu/Server/pull/2802)) ([fryguy503](https://github.com/fryguy503)) 2023-01-29 +* Resolve issue with max buff count being 25 in ROF2. ([#2800](https://github.com/EQEmu/Server/pull/2800)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-28 + +### Hotfix + +* Post revert build fix for https://github.com/EQEmu/Server/commit/54050924d81d1f83268fe01f9c2b36fe10626601 ([Akkadius](https://github.com/Akkadius)) 2023-02-01 + +### Lua + +* Resolve stoi Exception ([#2736](https://github.com/EQEmu/Server/pull/2736)) ([Akkadius](https://github.com/Akkadius)) 2023-02-06 + +### Pathing + +* Improvements to handling tight corridors pathing, clipping detection and recovery ([#2826](https://github.com/EQEmu/Server/pull/2826)) ([Akkadius](https://github.com/Akkadius)) 2023-02-06 + +### Quest API + +* Add Augment Slot support to does_augment_fit ([#2813](https://github.com/EQEmu/Server/pull/2813)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-31 +* Add EVENT_DAMAGE_GIVEN and EVENT_DAMAGE_TAKEN to Perl/Lua. ([#2804](https://github.com/EQEmu/Server/pull/2804)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-29 +* Add EVENT_ITEM_CLICK_CLIENT and EVENT_ITEM_CLICK_CAST_CLIENT to Perl/Lua. ([#2810](https://github.com/EQEmu/Server/pull/2810)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-30 +* Add EVENT_TASKACCEPTED to Player scope ([#2822](https://github.com/EQEmu/Server/pull/2822)) ([Valorith](https://github.com/Valorith)) 2023-02-06 +* Add GetItemCooldown to return the time remaining on items… ([#2811](https://github.com/EQEmu/Server/pull/2811)) ([Natedog2012](https://github.com/Natedog2012)) 2023-01-30 +* Add LDoN Methods to Perl/Lua ([#2799](https://github.com/EQEmu/Server/pull/2799)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-29 +* Add Override Parameters to ScaleNPC() in Perl/Lua. ([#2816](https://github.com/EQEmu/Server/pull/2816)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-01 +* Add rule AlternateAugmentationSealer for using a different bagtype ([#2831](https://github.com/EQEmu/Server/pull/2831)) ([Natedog2012](https://github.com/Natedog2012)) 2023-02-06 +* Default ScaleNPC to always scale. ([#2818](https://github.com/EQEmu/Server/pull/2818)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-06 + +### Readme + +* Update build badges with Drone ([Akkadius](https://github.com/Akkadius)) 2023-01-29 + +### Rules + +* Add rule to ignore name filter on chat channel creation. ([#2820](https://github.com/EQEmu/Server/pull/2820)) ([Valorith](https://github.com/Valorith)) 2023-02-06 +* Added rule to bypass level based haste caps ([#2835](https://github.com/EQEmu/Server/pull/2835)) ([jcr4990](https://github.com/jcr4990)) 2023-02-06 +* Fix rule updates that affected bot booting checks ([#2841](https://github.com/EQEmu/Server/pull/2841)) ([Akkadius](https://github.com/Akkadius)) 2023-02-06 + +### Tasks + +* Implement alternate currency rewards ([#2827](https://github.com/EQEmu/Server/pull/2827)) ([Akkadius](https://github.com/Akkadius)) 2023-02-06 + +## [22.2.0] - 01/27/2023 + +### Bots + +* Add EVENT_UNEQUIP_ITEM_BOT & EVENT_EQUIP_ITEM_BOT ([#2796](https://github.com/EQEmu/Server/pull/2796)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-27 +* ^create and ^viewcombos popup messages fix. ([#2797](https://github.com/EQEmu/Server/pull/2797)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-26 + +### Code Cleanup + +* Cleanup #door Command. ([#2783](https://github.com/EQEmu/Server/pull/2783)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-24 + +### Crash + +* Fix crash issue with log formatting during character creation ([#2798](https://github.com/EQEmu/Server/pull/2798)) ([Akkadius](https://github.com/Akkadius)) 2023-01-27 + +### Feature + +* ResetItemCooldown added to lua/perl and fix item re-cast times to show properly ([#2793](https://github.com/EQEmu/Server/pull/2793)) ([Natedog2012](https://github.com/Natedog2012)) 2023-01-26 + +### Git + +* Add CMake Files to .gitignore ([#2792](https://github.com/EQEmu/Server/pull/2792)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-25 + +## [22.1.2] - 01/24/2023 + +### CI/CD + +* Build / Release Pipeline Changes ([#2788](https://github.com/EQEmu/Server/pull/2788)) ([Akkadius](https://github.com/Akkadius)) 2023-01-24 + +### Code Cleanup + +* Cleanup #door Command. ([#2783](https://github.com/EQEmu/Server/pull/2783)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-24 + +### Crash + +* Fix rarer world crash issue where scheduler database was not available ([#2789](https://github.com/EQEmu/Server/pull/2789)) ([Akkadius](https://github.com/Akkadius)) 2023-01-24 + +### Fixes + +* Fix nullptr spell in BCSpells::Load() ([#2790](https://github.com/EQEmu/Server/pull/2790)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-24 +* Remove duplicate logic in GetActSpellHealing reducing HOT criticals ([#2786](https://github.com/EQEmu/Server/pull/2786)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-24 + +## [22.1.1] - 01/23/2023 + +### Fixes + +* Fix botgrouplist to display unique entries. ([#2785](https://github.com/EQEmu/Server/pull/2785)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-23 +* Fix scenario where dereferenced object could be null. ([#2784](https://github.com/EQEmu/Server/pull/2784)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-23 + +## [22.1.0] - 01/22/2023 + +This is a first release using the new build system. Changelog entry representative of last year. Subsequent releases will consist of incremental changes since the last release. + +### AA + +* Fix AA tables dump ([#2769](https://github.com/EQEmu/Server/pull/2769)) ([Akkadius](https://github.com/Akkadius)) 2023-01-22 + +### Appveyor + +* Remove bots preprocessor ([Akkadius](https://github.com/Akkadius)) 2023-01-20 + +### Bot/Merc + +* Cleanup methods, and virtual overrides. ([#2734](https://github.com/EQEmu/Server/pull/2734)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-15 + +### Bots + +* Add Bot Command Reloading ([#2773](https://github.com/EQEmu/Server/pull/2773)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-22 +* Add Bot-specific Spell Settings. ([#2553](https://github.com/EQEmu/Server/pull/2553)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-27 +* Add Buff support for Bards under AI_IdleCastChecks ([#2590](https://github.com/EQEmu/Server/pull/2590)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-28 +* Add Data Bucket support to Bot Spell Entries. ([#2505](https://github.com/EQEmu/Server/pull/2505)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-06 +* Add EVENT_TRADE Support to Bots. ([#2560](https://github.com/EQEmu/Server/pull/2560)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-25 +* Add Event_Trade Support for ^inventorygive Command ([#2628](https://github.com/EQEmu/Server/pull/2628)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-11 +* Add Expansion Bitmask Quest APIs. ([#2523](https://github.com/EQEmu/Server/pull/2523)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-16 +* Add GetBotOwnerByBotID Method ([#2715](https://github.com/EQEmu/Server/pull/2715)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-11 +* Add Melee Support for Casting, Cleanup Bot Casting Logic ([#2571](https://github.com/EQEmu/Server/pull/2571)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-25 +* Add Quest API Methods ([#2631](https://github.com/EQEmu/Server/pull/2631)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-12 +* Add Quest API Support for Limits. ([#2522](https://github.com/EQEmu/Server/pull/2522)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-17 +* Add Rule Allowing Bots to Equip Any Race Items ([#2578](https://github.com/EQEmu/Server/pull/2578)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-26 +* Add Support for AA bonuses that were missing. ([#2764](https://github.com/EQEmu/Server/pull/2764)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-20 +* Add Support for Bots to receive Auras, and other AoE Buffs. ([#2586](https://github.com/EQEmu/Server/pull/2586)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-27 +* Add Virtual Override for Bot::Attack ([#2771](https://github.com/EQEmu/Server/pull/2771)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-20 +* Add give/remove saylinks to ^itemuse. ([#2503](https://github.com/EQEmu/Server/pull/2503)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-10-30 +* Add support for Bot scripting. ([#2515](https://github.com/EQEmu/Server/pull/2515)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-17 +* Apply Spells:IgnoreSpellDmgLvlRestriction to bots ([#2024](https://github.com/EQEmu/Server/pull/2024)) ([catapultam-habeo](https://github.com/catapultam-habeo)) 2022-03-07 +* Bot::PerformTradeWithClient Cleanup. ([#2084](https://github.com/EQEmu/Server/pull/2084)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-01 +* Cleanup Bot Spell Functions, reduce reliance on NPC Functions/Attributes ([#2495](https://github.com/EQEmu/Server/pull/2495)) ([Aeadoin](https://github.com/Aeadoin)) 2022-10-29 +* Cleanup Fast Rest Regen ([#2626](https://github.com/EQEmu/Server/pull/2626)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-07 +* Cleanup Say Event Parse. ([#2557](https://github.com/EQEmu/Server/pull/2557)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-20 +* Cleanup Spell Settings Commands ([#2607](https://github.com/EQEmu/Server/pull/2607)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-04 +* Cleanup ^inventoryremove, ^inventorylist, and ^list Commands and bot groups. ([#2273](https://github.com/EQEmu/Server/pull/2273)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-07-03 +* Cleanup and remove preprocessors. ([#2757](https://github.com/EQEmu/Server/pull/2757)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-20 +* Cleanup various Bot Spell Focus methods ([#2649](https://github.com/EQEmu/Server/pull/2649)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-16 +* Convert Load, Save, SaveNew, and Delete to Repositories. ([#2614](https://github.com/EQEmu/Server/pull/2614)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-04 +* Expanded Bot Spell Settings List. ([#2606](https://github.com/EQEmu/Server/pull/2606)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-03 +* Fix Bot Spell Type "In Combat Buffs" ([#2711](https://github.com/EQEmu/Server/pull/2711)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-08 +* Fix Gender not saving as GetBaseGender on BotSave ([#2639](https://github.com/EQEmu/Server/pull/2639)) ([nytmyr](https://github.com/nytmyr)) 2022-12-13 +* Fix Slow Query in QueryNameAvailablity ([#2781](https://github.com/EQEmu/Server/pull/2781)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-22 +* Fix ^dyearmor command math. ([#2081](https://github.com/EQEmu/Server/pull/2081)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-04-30 +* Fix bot spawn when bot id = char_id ([#1984](https://github.com/EQEmu/Server/pull/1984)) ([neckkola](https://github.com/neckkola)) 2022-03-07 +* Hotfix for possible crash. ([#2539](https://github.com/EQEmu/Server/pull/2539)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14 +* Melee Bot Support for Spell Settings Commands ([#2599](https://github.com/EQEmu/Server/pull/2599)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-01 +* Move Bot Spell Loading process to constructor from calcbotstats() ([#2583](https://github.com/EQEmu/Server/pull/2583)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-27 +* Optimize inventory loading. ([#2588](https://github.com/EQEmu/Server/pull/2588)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-28 +* Post pre-processor fixes ([#2770](https://github.com/EQEmu/Server/pull/2770)) ([Akkadius](https://github.com/Akkadius)) 2023-01-20 +* Resolve incorrect values on Bot Creation ([#2644](https://github.com/EQEmu/Server/pull/2644)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-14 +* Restrict Bot Groups from spawning while Feigned. ([#2761](https://github.com/EQEmu/Server/pull/2761)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-19 +* Save Bot Toggle Archer Setting between Loads. ([#2612](https://github.com/EQEmu/Server/pull/2612)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-04 +* Update Bot Heal & Damage methods to more closely match Clients + Bugfixes ([#2045](https://github.com/EQEmu/Server/pull/2045)) ([catapultam-habeo](https://github.com/catapultam-habeo)) 2022-03-11 +* Update Bot Logic to ignore ST_TargetsTarget when buffing ([#2584](https://github.com/EQEmu/Server/pull/2584)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-27 + +### C++20 + +* Arithmetic on different enums is deprecated ([#2752](https://github.com/EQEmu/Server/pull/2752)) ([mackal](https://github.com/mackal)) 2023-01-17 +* Enable C++20 + Fixes + FMT 9.1 ([#2664](https://github.com/EQEmu/Server/pull/2664)) ([Akkadius](https://github.com/Akkadius)) 2022-12-21 + +### Code + +* Removed vscode setting ([#2753](https://github.com/EQEmu/Server/pull/2753)) ([xackery](https://github.com/xackery)) 2023-01-17 + +### Code Cleanup + +* Add Validation to varchar number item fields. ([#2241](https://github.com/EQEmu/Server/pull/2241)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-04 +* Cleanup #kick message. ([#2164](https://github.com/EQEmu/Server/pull/2164)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-10 +* Cleanup Haste references and Lua API calls for unsigned to signed. ([#2240](https://github.com/EQEmu/Server/pull/2240)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-04 +* Cleanup code smells and compiler warnings in common/shareddb ([#2270](https://github.com/EQEmu/Server/pull/2270)) ([Quintinon](https://github.com/Quintinon)) 2022-07-03 +* Cleanup magic numbers ([#2662](https://github.com/EQEmu/Server/pull/2662)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-20 +* Cleanup spell and max level bucket logic. ([#2181](https://github.com/EQEmu/Server/pull/2181)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-28 +* Extra Space in NPC::AISpellsList(). ([#2555](https://github.com/EQEmu/Server/pull/2555)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-20 +* Fix unintended copies in zone/zonedb.cpp by changing auto to auto& ([#2271](https://github.com/EQEmu/Server/pull/2271)) ([Quintinon](https://github.com/Quintinon)) 2022-07-03 +* Make use of std::abs where possible. ([#2739](https://github.com/EQEmu/Server/pull/2739)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-15 +* Merge Client::Attack and Bot::Attack into Mob::Attack ([#2756](https://github.com/EQEmu/Server/pull/2756)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-20 +* Move Client::Undye() to client.cpp from #path Command. ([#2188](https://github.com/EQEmu/Server/pull/2188)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-21 +* Possible issues with variable/parameter name equality. ([#2161](https://github.com/EQEmu/Server/pull/2161)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-10 +* Quest API push methods using invalid types. ([#2172](https://github.com/EQEmu/Server/pull/2172)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-16 +* Remove Unused EQEMU_DEPOP_INVALIDATES_CACHE ([#2292](https://github.com/EQEmu/Server/pull/2292)) ([Akkadius](https://github.com/Akkadius)) 2022-07-14 +* Remove this-> in code where its implied ([#2088](https://github.com/EQEmu/Server/pull/2088)) ([Akkadius](https://github.com/Akkadius)) 2022-05-01 +* Remove unused basic_functions.h ([#2729](https://github.com/EQEmu/Server/pull/2729)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-13 +* Remove unused maxskill.h. ([#2728](https://github.com/EQEmu/Server/pull/2728)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-13 +* Remove unused methods. ([#2171](https://github.com/EQEmu/Server/pull/2171)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-15 +* Remove unusued Max Item ID Constant ([#2528](https://github.com/EQEmu/Server/pull/2528)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-08 +* Remove use of bzero since it is deprecated for memset ([#2295](https://github.com/EQEmu/Server/pull/2295)) ([Akkadius](https://github.com/Akkadius)) 2022-07-14 +* Resharper Warnings ([#2235](https://github.com/EQEmu/Server/pull/2235)) ([Quintinon](https://github.com/Quintinon)) 2022-06-01 +* Resolve some warnings in loginserver/world_server.cpp ([#2347](https://github.com/EQEmu/Server/pull/2347)) ([mackal](https://github.com/mackal)) 2022-07-31 +* Rework Lua QuestReward to not use try/catch blocks ([#2417](https://github.com/EQEmu/Server/pull/2417)) ([mackal](https://github.com/mackal)) 2022-09-03 +* Send eqstr message in AddAAPoints ([#2507](https://github.com/EQEmu/Server/pull/2507)) ([hgtw](https://github.com/hgtw)) 2022-10-29 +* Update to EQEmu #2253 to clean up message strings ([#2279](https://github.com/EQEmu/Server/pull/2279)) ([fryguy503](https://github.com/fryguy503)) 2022-07-03 +* Zone Data Loading Refactor ([#2388](https://github.com/EQEmu/Server/pull/2388)) ([Akkadius](https://github.com/Akkadius)) 2022-09-01 + +### Commands + +* #bind Typo. ([#2196](https://github.com/EQEmu/Server/pull/2196)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-23 +* #ginfo Cleanup. ([#1955](https://github.com/EQEmu/Server/pull/1955)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-03 +* #reload Command Overhaul. ([#2162](https://github.com/EQEmu/Server/pull/2162)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-10 +* #reload level_mods could cause Non-Booted zones to crash. ([#2670](https://github.com/EQEmu/Server/pull/2670)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-24 +* Add #bugs Command. ([#2559](https://github.com/EQEmu/Server/pull/2559)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22 +* Add #feature Command. ([#2142](https://github.com/EQEmu/Server/pull/2142)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06 +* Add #findcharacter Command. ([#2692](https://github.com/EQEmu/Server/pull/2692)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-03 +* Add #findrecipe and #viewrecipe Commands. ([#2401](https://github.com/EQEmu/Server/pull/2401)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-31 +* Add #setanon Command ([#2690](https://github.com/EQEmu/Server/pull/2690)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-03 +* Add #suspendmulti Command. ([#2619](https://github.com/EQEmu/Server/pull/2619)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-11 +* Add BestZ and Region Data to #loc ([#2245](https://github.com/EQEmu/Server/pull/2245)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-05 +* Add additional #peqzone functionality. ([#2085](https://github.com/EQEmu/Server/pull/2085)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-01 +* Add max_hp back to #modifynpcstat command. ([#2638](https://github.com/EQEmu/Server/pull/2638)) ([nytmyr](https://github.com/nytmyr)) 2022-12-13 +* Adding movespeed to #showstats output ([#2596](https://github.com/EQEmu/Server/pull/2596)) ([fryguy503](https://github.com/fryguy503)) 2022-11-30 +* Bug fix for #logs command. ([#2008](https://github.com/EQEmu/Server/pull/2008)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-17 +* Cleanup #ai Command. ([#1980](https://github.com/EQEmu/Server/pull/1980)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-11 +* Cleanup #appearanceeffects Command. ([#2777](https://github.com/EQEmu/Server/pull/2777)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-22 +* Cleanup #attack Command. ([#2103](https://github.com/EQEmu/Server/pull/2103)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-04 +* Cleanup #ban, #ipban, #flag, #kick, #setlsinfo, and #setpass Commands. ([#2104](https://github.com/EQEmu/Server/pull/2104)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-08 +* Cleanup #chat Command. ([#2581](https://github.com/EQEmu/Server/pull/2581)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-27 +* Cleanup #corpsefix Command. ([#2197](https://github.com/EQEmu/Server/pull/2197)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-27 +* Cleanup #cvs Command. ([#2153](https://github.com/EQEmu/Server/pull/2153)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-08 +* Cleanup #date Command. ([#2228](https://github.com/EQEmu/Server/pull/2228)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-01 +* Cleanup #dbspawn2 Command. ([#2493](https://github.com/EQEmu/Server/pull/2493)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-10-30 +* Cleanup #delacct Command. ([#2567](https://github.com/EQEmu/Server/pull/2567)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22 +* Cleanup #depop Command. ([#2536](https://github.com/EQEmu/Server/pull/2536)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14 +* Cleanup #depopzone Command. ([#2537](https://github.com/EQEmu/Server/pull/2537)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14 +* Cleanup #devtools Command. ([#2538](https://github.com/EQEmu/Server/pull/2538)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14 +* Cleanup #doanim Command. ([#2540](https://github.com/EQEmu/Server/pull/2540)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14 +* Cleanup #emote Command. ([#2535](https://github.com/EQEmu/Server/pull/2535)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14 +* Cleanup #emotesearch and #emoteview Command. ([#2494](https://github.com/EQEmu/Server/pull/2494)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-10-30 +* Cleanup #emptyinventory Command. ([#2219](https://github.com/EQEmu/Server/pull/2219)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-29 +* Cleanup #findaliases and #help Commands. ([#2204](https://github.com/EQEmu/Server/pull/2204)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-27 +* Cleanup #findclass and #findrace Commands. ([#2211](https://github.com/EQEmu/Server/pull/2211)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-27 +* Cleanup #flagedit Command. ([#1968](https://github.com/EQEmu/Server/pull/1968)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-10 +* Cleanup #freeze and #unfreeze Commands. ([#2102](https://github.com/EQEmu/Server/pull/2102)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-04 +* Cleanup #gassign Command. ([#2101](https://github.com/EQEmu/Server/pull/2101)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06 +* Cleanup #gearup Command. ([#2589](https://github.com/EQEmu/Server/pull/2589)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-27 +* Cleanup #getvariable Command. ([#2100](https://github.com/EQEmu/Server/pull/2100)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-04 +* Cleanup #guild Command ([#2693](https://github.com/EQEmu/Server/pull/2693)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-04 +* Cleanup #hatelist Command. ([#1976](https://github.com/EQEmu/Server/pull/1976)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-10 +* Cleanup #heromodel Command. ([#2566](https://github.com/EQEmu/Server/pull/2566)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22 +* Cleanup #kill Command. ([#2195](https://github.com/EQEmu/Server/pull/2195)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-23 +* Cleanup #level Command. ([#2203](https://github.com/EQEmu/Server/pull/2203)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-27 +* Cleanup #logs Command. ([#1969](https://github.com/EQEmu/Server/pull/1969)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-10 +* Cleanup #makepet Command. ([#2105](https://github.com/EQEmu/Server/pull/2105)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #modifynpcstat Command. ([#2499](https://github.com/EQEmu/Server/pull/2499)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-10-30 +* Cleanup #motd Command. ([#2190](https://github.com/EQEmu/Server/pull/2190)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-23 +* Cleanup #name Command. ([#1977](https://github.com/EQEmu/Server/pull/1977)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-10 +* Cleanup #netstats Command. ([#1970](https://github.com/EQEmu/Server/pull/1970)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-10 +* Cleanup #npcedit Command. ([#2582](https://github.com/EQEmu/Server/pull/2582)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-27 +* Cleanup #npcedit, #lastname, #title, and #titlesuffix Commands. ([#2215](https://github.com/EQEmu/Server/pull/2215)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-28 +* Cleanup #npceditmass command. ([#1957](https://github.com/EQEmu/Server/pull/1957)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-03 +* Cleanup #npcemote Command. ([#2106](https://github.com/EQEmu/Server/pull/2106)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #npcloot Command. ([#1974](https://github.com/EQEmu/Server/pull/1974)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-11 +* Cleanup #npcsay and #npcshout Commands. ([#2107](https://github.com/EQEmu/Server/pull/2107)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #npcspecialattk Command. ([#2108](https://github.com/EQEmu/Server/pull/2108)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #npctype_cache Command. ([#2109](https://github.com/EQEmu/Server/pull/2109)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #npctypespawn Command. ([#2110](https://github.com/EQEmu/Server/pull/2110)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #nudge Command. ([#2220](https://github.com/EQEmu/Server/pull/2220)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-29 +* Cleanup #oocmute Command. ([#2191](https://github.com/EQEmu/Server/pull/2191)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-27 +* Cleanup #opcode Command. ([#2547](https://github.com/EQEmu/Server/pull/2547)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-16 +* Cleanup #profanity Command. ([#2113](https://github.com/EQEmu/Server/pull/2113)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #push Command. ([#2114](https://github.com/EQEmu/Server/pull/2114)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #qglobal Command. ([#2115](https://github.com/EQEmu/Server/pull/2115)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #randomizefeatures Command. ([#2118](https://github.com/EQEmu/Server/pull/2118)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #refreshgroup Command. ([#2119](https://github.com/EQEmu/Server/pull/2119)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #reloadaa Command. ([#2120](https://github.com/EQEmu/Server/pull/2120)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #reloadallrules Command. ([#2121](https://github.com/EQEmu/Server/pull/2121)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #reloadlevelmods Command. ([#2122](https://github.com/EQEmu/Server/pull/2122)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #reloadmerchants Command. ([#2123](https://github.com/EQEmu/Server/pull/2123)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #reloadperlexportsettings Command. ([#2124](https://github.com/EQEmu/Server/pull/2124)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #reloadrulesworld Command. ([#2128](https://github.com/EQEmu/Server/pull/2128)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #reloadstatic Command. ([#2130](https://github.com/EQEmu/Server/pull/2130)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #reloadtitles Command. ([#2125](https://github.com/EQEmu/Server/pull/2125)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #reloadtraps Command. ([#2126](https://github.com/EQEmu/Server/pull/2126)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #reloadworld and #repop Command. ([#2127](https://github.com/EQEmu/Server/pull/2127)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #reloadzps Command. ([#2129](https://github.com/EQEmu/Server/pull/2129)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #resetaa Command. ([#2132](https://github.com/EQEmu/Server/pull/2132)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #resetaa_timer Command. ([#2131](https://github.com/EQEmu/Server/pull/2131)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #resetdisc_timer Command. ([#2133](https://github.com/EQEmu/Server/pull/2133)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06 +* Cleanup #revoke Command. ([#2134](https://github.com/EQEmu/Server/pull/2134)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #roambox Command. ([#2135](https://github.com/EQEmu/Server/pull/2135)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06 +* Cleanup #rules Command. ([#2593](https://github.com/EQEmu/Server/pull/2593)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-10 +* Cleanup #save Command. ([#2136](https://github.com/EQEmu/Server/pull/2136)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06 +* Cleanup #scale Command. ([#2591](https://github.com/EQEmu/Server/pull/2591)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-05 +* Cleanup #scribespell and #scribespells Commands. ([#2534](https://github.com/EQEmu/Server/pull/2534)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14 +* Cleanup #sensetrap Command. ([#2137](https://github.com/EQEmu/Server/pull/2137)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #serverinfo Command. ([#2568](https://github.com/EQEmu/Server/pull/2568)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22 +* Cleanup #serverrules Command. ([#2139](https://github.com/EQEmu/Server/pull/2139)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06 +* Cleanup #setlanguage Command. ([#2464](https://github.com/EQEmu/Server/pull/2464)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-10-13 +* Cleanup #setskillall Command. ([#1992](https://github.com/EQEmu/Server/pull/1992)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-15 +* Cleanup #shownpcgloballoot and #showzonegloballoot Command. ([#2141](https://github.com/EQEmu/Server/pull/2141)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06 +* Cleanup #showskills Command. ([#1994](https://github.com/EQEmu/Server/pull/1994)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-15 +* Cleanup #spawneditmass Command. ([#2229](https://github.com/EQEmu/Server/pull/2229)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-04 +* Cleanup #spawnfix Command. ([#2143](https://github.com/EQEmu/Server/pull/2143)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06 +* Cleanup #spawnstatus Command. ([#2144](https://github.com/EQEmu/Server/pull/2144)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06 +* Cleanup #summon Command. ([#2145](https://github.com/EQEmu/Server/pull/2145)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-06 +* Cleanup #summonburiedplayercorpse Command. ([#2146](https://github.com/EQEmu/Server/pull/2146)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #suspend Command. ([#2564](https://github.com/EQEmu/Server/pull/2564)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22 +* Cleanup #task Command. ([#2071](https://github.com/EQEmu/Server/pull/2071)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-04-14 +* Cleanup #time and #timezone Command. ([#2147](https://github.com/EQEmu/Server/pull/2147)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #timers Command. ([#2562](https://github.com/EQEmu/Server/pull/2562)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22 +* Cleanup #trapinfo Command. ([#2148](https://github.com/EQEmu/Server/pull/2148)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #ucs Command. ([#2149](https://github.com/EQEmu/Server/pull/2149)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Cleanup #undye and #undyeme Commands. ([#1966](https://github.com/EQEmu/Server/pull/1966)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-10 +* Cleanup #unscribespell Command. ([#1998](https://github.com/EQEmu/Server/pull/1998)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-16 +* Cleanup #untraindisc Command. ([#1996](https://github.com/EQEmu/Server/pull/1996)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-16 +* Cleanup #version Command. ([#1967](https://github.com/EQEmu/Server/pull/1967)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-10 +* Cleanup #worldwide command. ([#2021](https://github.com/EQEmu/Server/pull/2021)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-01 +* Cleanup #xtargets Command. ([#2545](https://github.com/EQEmu/Server/pull/2545)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-17 +* Cleanup #zone and #zoneinstance Commands. ([#2202](https://github.com/EQEmu/Server/pull/2202)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-27 +* Command Status Reload and Helper Method ([#2377](https://github.com/EQEmu/Server/pull/2377)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-20 +* Consolidate #lock and #unlock Commands into #serverlock. ([#2193](https://github.com/EQEmu/Server/pull/2193)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-23 +* Fix #copycharacter command crash ([#2446](https://github.com/EQEmu/Server/pull/2446)) ([Akkadius](https://github.com/Akkadius)) 2022-09-25 +* Fix #killallnpcs from crashing ([#2037](https://github.com/EQEmu/Server/pull/2037)) ([Akkadius](https://github.com/Akkadius)) 2022-03-07 +* Fix Flymode Command Help Prompt ([#2669](https://github.com/EQEmu/Server/pull/2669)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-23 +* Fix typos in #ban and #ipban Commands. ([#2209](https://github.com/EQEmu/Server/pull/2209)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-26 +* Make #damage require a target ([#2426](https://github.com/EQEmu/Server/pull/2426)) ([hgtw](https://github.com/hgtw)) 2022-09-05 +* Nested Command Aliases ([#2636](https://github.com/EQEmu/Server/pull/2636)) ([Akkadius](https://github.com/Akkadius)) 2022-12-15 +* Remove #guildapprove, #guildcreate, and #guildlist Commands ([#2775](https://github.com/EQEmu/Server/pull/2775)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-22 +* Remove #iteminfo Command. ([#2565](https://github.com/EQEmu/Server/pull/2565)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22 +* Remove #profiledump and #profilereset Commands. ([#2546](https://github.com/EQEmu/Server/pull/2546)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-16 +* Remove #undyeme Command. ([#2776](https://github.com/EQEmu/Server/pull/2776)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-22 +* Remove unused #bestz and #pf Commands. ([#2112](https://github.com/EQEmu/Server/pull/2112)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Remove unused/broken #deletegraveyard and #setgraveyard Commands. ([#2198](https://github.com/EQEmu/Server/pull/2198)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-23 + +### Diawind + +* Plus sign markdown fix ([#2727](https://github.com/EQEmu/Server/pull/2727)) ([Akkadius](https://github.com/Akkadius)) 2023-01-12 + +### Feature + +* AA Cap Limit ([#2423](https://github.com/EQEmu/Server/pull/2423)) ([fryguy503](https://github.com/fryguy503)) 2022-10-13 +* Add "Keeps Sold Items" Flag to NPCs ([#2671](https://github.com/EQEmu/Server/pull/2671)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-25 +* Add Experience Gain Toggle. ([#2676](https://github.com/EQEmu/Server/pull/2676)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-30 +* Add Guild Chat to Console. ([#2387](https://github.com/EQEmu/Server/pull/2387)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-22 +* Add Hate Override for Heals ([#2485](https://github.com/EQEmu/Server/pull/2485)) ([Aeadoin](https://github.com/Aeadoin)) 2022-10-14 +* Add Rule to Disable Group EXP Modifier. ([#2741](https://github.com/EQEmu/Server/pull/2741)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-15 +* Add Support for "Show Mine Only" Filters ([#2484](https://github.com/EQEmu/Server/pull/2484)) ([Aeadoin](https://github.com/Aeadoin)) 2022-10-13 +* Add Type 49545 to Spell Resistrictions ([#2436](https://github.com/EQEmu/Server/pull/2436)) ([Aeadoin](https://github.com/Aeadoin)) 2022-09-20 +* Add humanoid and non-wielded restrictions to pick pocket ([#2276](https://github.com/EQEmu/Server/pull/2276)) ([noudess](https://github.com/noudess)) 2022-07-03 +* Add player /inspect quest event ([#2508](https://github.com/EQEmu/Server/pull/2508)) ([hgtw](https://github.com/hgtw)) 2022-10-29 +* Add special ability to block /open ([#2506](https://github.com/EQEmu/Server/pull/2506)) ([hgtw](https://github.com/hgtw)) 2022-10-29 +* Allow Focus Effects to be Filtered out. ([#2447](https://github.com/EQEmu/Server/pull/2447)) ([Aeadoin](https://github.com/Aeadoin)) 2022-09-25 +* Allow pets to zone with permanent (buffdurationformula 50) buffs to maintain them through zone transitions ([#2035](https://github.com/EQEmu/Server/pull/2035)) ([catapultam-habeo](https://github.com/catapultam-habeo)) 2022-03-07 +* Bind Wound and Forage while mounted. ([#2257](https://github.com/EQEmu/Server/pull/2257)) ([fryguy503](https://github.com/fryguy503)) 2022-07-03 +* Change #scribespells to be aware of spellgroups & ranks ([#2501](https://github.com/EQEmu/Server/pull/2501)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-06 +* Change GetSkillDmgAmt to int32 ([#2364](https://github.com/EQEmu/Server/pull/2364)) ([Aeadoin](https://github.com/Aeadoin)) 2022-08-10 +* Change Lifetap Emotes to be filterable. ([#2454](https://github.com/EQEmu/Server/pull/2454)) ([Aeadoin](https://github.com/Aeadoin)) 2022-09-29 +* Change Mana Costs to use Signed Int ([#2384](https://github.com/EQEmu/Server/pull/2384)) ([Aeadoin](https://github.com/Aeadoin)) 2022-08-21 +* Change mana_used to int32 ([#2321](https://github.com/EQEmu/Server/pull/2321)) ([Aeadoin](https://github.com/Aeadoin)) 2022-07-30 +* Client Checksum Verification (Resubmit old 1678) ([#1922](https://github.com/EQEmu/Server/pull/1922)) ([noudess](https://github.com/noudess)) 2022-03-07 +* EQ2-style implied targeting for spells. ([#2032](https://github.com/EQEmu/Server/pull/2032)) ([catapultam-habeo](https://github.com/catapultam-habeo)) 2022-03-07 +* Faction Association ([#2408](https://github.com/EQEmu/Server/pull/2408)) ([mackal](https://github.com/mackal)) 2022-09-03 +* GM State Change Persistance ([#2328](https://github.com/EQEmu/Server/pull/2328)) ([fryguy503](https://github.com/fryguy503)) 2022-07-31 +* Implement Heroic Strikethrough to NPCs ([#2395](https://github.com/EQEmu/Server/pull/2395)) ([Aeadoin](https://github.com/Aeadoin)) 2022-08-31 +* Implement OP_CashReward ([#2307](https://github.com/EQEmu/Server/pull/2307)) ([mackal](https://github.com/mackal)) 2022-07-15 +* Instance Version Specific Experience Modifiers ([#2376](https://github.com/EQEmu/Server/pull/2376)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-20 +* NPCs with bows and arrows do ranged attacks ([#2322](https://github.com/EQEmu/Server/pull/2322)) ([mackal](https://github.com/mackal)) 2022-07-30 +* Soft Delete Bots on Character Soft Delete ([#2467](https://github.com/EQEmu/Server/pull/2467)) ([Aeadoin](https://github.com/Aeadoin)) 2022-10-13 +* Spell Ranks will now work with AllowSpellMemorizeFromItem Rule ([#2475](https://github.com/EQEmu/Server/pull/2475)) ([Aeadoin](https://github.com/Aeadoin)) 2022-10-13 +* Update HateMod used by SPA 114 to Int32. ([#2428](https://github.com/EQEmu/Server/pull/2428)) ([Aeadoin](https://github.com/Aeadoin)) 2022-09-08 + +### Fixes + +* #npcstats command displaying incorrect faction ([#2710](https://github.com/EQEmu/Server/pull/2710)) ([noudess](https://github.com/noudess)) 2023-01-08 +* #peqzone no longer bypass Handle_OP_ZoneChange ([#2063](https://github.com/EQEmu/Server/pull/2063)) ([Natedog2012](https://github.com/Natedog2012)) 2022-03-19 +* #scribespells triggered error on mysql keyword rank ([#2779](https://github.com/EQEmu/Server/pull/2779)) ([noudess](https://github.com/noudess)) 2023-01-21 +* #tune command various fixes ([#2046](https://github.com/EQEmu/Server/pull/2046)) ([KayenEQ](https://github.com/KayenEQ)) 2022-03-11 +* Add Complete Heal Spell back to IsCompleteHealSpell Method ([#2722](https://github.com/EQEmu/Server/pull/2722)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-11 +* Add SE_MakeDrunk to avoid error message. ([#2601](https://github.com/EQEmu/Server/pull/2601)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-01 +* Add omitted function call in UCS ([#2768](https://github.com/EQEmu/Server/pull/2768)) ([Valorith](https://github.com/Valorith)) 2023-01-20 +* Add required distance to CoTH before aggro wipe ([#2253](https://github.com/EQEmu/Server/pull/2253)) ([fryguy503](https://github.com/fryguy503)) 2022-07-03 +* Adjustment for nullptr crash ([#2232](https://github.com/EQEmu/Server/pull/2232)) ([Akkadius](https://github.com/Akkadius)) 2022-06-01 +* Alleviate some lag with crosszone/worldwide spell casting. ([#2016](https://github.com/EQEmu/Server/pull/2016)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-21 +* Allow High Level Spells to be Unmemorized. ([#2641](https://github.com/EQEmu/Server/pull/2641)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-14 +* Allow Songs to be scribed from scrolls ([#2460](https://github.com/EQEmu/Server/pull/2460)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-10-12 +* AltCurrencySelectItemReply_Struct was not handled correctly. ([#2702](https://github.com/EQEmu/Server/pull/2702)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-04 +* Any use of TempName left old clean_name. ([#1946](https://github.com/EQEmu/Server/pull/1946)) ([noudess](https://github.com/noudess)) 2022-01-26 +* Avoid erase in discord queue range loop ([#2411](https://github.com/EQEmu/Server/pull/2411)) ([hgtw](https://github.com/hgtw)) 2022-09-03 +* Bandolier didn't recognize source weapon on cursor ([#2026](https://github.com/EQEmu/Server/pull/2026)) ([noudess](https://github.com/noudess)) 2022-03-07 +* Bard Invisible causing display issues. ([#2067](https://github.com/EQEmu/Server/pull/2067)) ([KayenEQ](https://github.com/KayenEQ)) 2022-04-01 +* Bard update fixes 1 ([#1982](https://github.com/EQEmu/Server/pull/1982)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-09 +* Bazaar Search MYSQL Error ([#2252](https://github.com/EQEmu/Server/pull/2252)) ([fryguy503](https://github.com/fryguy503)) 2022-06-08 +* Blocked spells max spell id increased ([#2207](https://github.com/EQEmu/Server/pull/2207)) ([Isaaru](https://github.com/Isaaru)) 2022-05-25 +* Boats should never get FixZ'd ([#2246](https://github.com/EQEmu/Server/pull/2246)) ([noudess](https://github.com/noudess)) 2022-07-02 +* Clamp Item Ldon Sell Back Rates. ([#2592](https://github.com/EQEmu/Server/pull/2592)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-30 +* Clear title/suffix bug fix. ([#2068](https://github.com/EQEmu/Server/pull/2068)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-04-02 +* Correct (probably) unintended bitwise AND instead of logical AND ([#2239](https://github.com/EQEmu/Server/pull/2239)) ([Quintinon](https://github.com/Quintinon)) 2022-06-02 +* Correct type signed/unsigned int when reading item from database in shareddb ([#2269](https://github.com/EQEmu/Server/pull/2269)) ([Quintinon](https://github.com/Quintinon)) 2022-06-15 +* Data Bucket Permanent Duration String ([#2624](https://github.com/EQEmu/Server/pull/2624)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-06 +* Delete NpcType Struct returned by Bot::CreateDefaultNPCTypeStructForBot() when unused ([#2267](https://github.com/EQEmu/Server/pull/2267)) ([Quintinon](https://github.com/Quintinon)) 2022-06-18 +* Do not allow /open to be used on traps or auras, causes crash ([#1951](https://github.com/EQEmu/Server/pull/1951)) ([KayenEQ](https://github.com/KayenEQ)) 2022-01-30 +* Doors::GetSize() Perl Croak Typo. ([#2027](https://github.com/EQEmu/Server/pull/2027)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-04 +* EVENT_ENTER_AREA/EVENT_LEAVE_AREA. ([#2698](https://github.com/EQEmu/Server/pull/2698)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-02 +* Edge case AA reset timer issue fixes ([#1995](https://github.com/EQEmu/Server/pull/1995)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-14 +* Fix #door Save ([#2699](https://github.com/EQEmu/Server/pull/2699)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-02 +* Fix #findaa and GetAAName(). ([#2774](https://github.com/EQEmu/Server/pull/2774)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-22 +* Fix #zone 0. ([#2691](https://github.com/EQEmu/Server/pull/2691)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-01 +* Fix Aug Clicks where item has no click effect. ([#2725](https://github.com/EQEmu/Server/pull/2725)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-12 +* Fix Bot "Failed to Load" Messages. ([#2719](https://github.com/EQEmu/Server/pull/2719)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-11 +* Fix Bot Group Loading ([#2780](https://github.com/EQEmu/Server/pull/2780)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-22 +* Fix Bot ^spellsettingsadd command ([#2603](https://github.com/EQEmu/Server/pull/2603)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-01 +* Fix Duplicate Silent Saylink Messages ([#2386](https://github.com/EQEmu/Server/pull/2386)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-22 +* Fix EntityList::GetBotListByCharacterID() ([#2569](https://github.com/EQEmu/Server/pull/2569)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22 +* Fix Flag Updating with SetGMStatus() in Lua. ([#2554](https://github.com/EQEmu/Server/pull/2554)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-20 +* Fix Group XP not working. ([#2748](https://github.com/EQEmu/Server/pull/2748)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-17 +* Fix HP Regen Per Second. ([#2206](https://github.com/EQEmu/Server/pull/2206)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-25 +* Fix IDFile Crash with spaces or invalid data. ([#2597](https://github.com/EQEmu/Server/pull/2597)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-01 +* Fix IP Exemptions. ([#2189](https://github.com/EQEmu/Server/pull/2189)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-28 +* Fix Instance Repository ([#2598](https://github.com/EQEmu/Server/pull/2598)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-01 +* Fix Legacy Combat Lua Script ([#2226](https://github.com/EQEmu/Server/pull/2226)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-31 +* Fix MovePC in #zone and #zoneinstance Commands. ([#2236](https://github.com/EQEmu/Server/pull/2236)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-01 +* Fix NPC Reference in EVENT_SPAWN ([#2712](https://github.com/EQEmu/Server/pull/2712)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-08 +* Fix ST_TargetsTarget Spells with Restrictions ([#2746](https://github.com/EQEmu/Server/pull/2746)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-15 +* Fix Silent Saylinks Sending Message to Others. ([#2389](https://github.com/EQEmu/Server/pull/2389)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-22 +* Fix Spell Bucket and Spell Global Logic Checks. ([#2285](https://github.com/EQEmu/Server/pull/2285)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-07-05 +* Fix Spellinfo Command to work with SpellIDs above int16 ([#2437](https://github.com/EQEmu/Server/pull/2437)) ([Aeadoin](https://github.com/Aeadoin)) 2022-09-20 +* Fix Strings::Money Missing Conditions. ([#2383](https://github.com/EQEmu/Server/pull/2383)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-21 +* Fix Swarm Pet Flurry/Rampages Messages ([#2444](https://github.com/EQEmu/Server/pull/2444)) ([Aeadoin](https://github.com/Aeadoin)) 2022-09-25 +* Fix bot compile locking client on server enter. ([#2210](https://github.com/EQEmu/Server/pull/2210)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-26 +* Fix bot guild removal. ([#2194](https://github.com/EQEmu/Server/pull/2194)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-23 +* Fix botgrouplist to display unique entries. ([#2785](https://github.com/EQEmu/Server/pull/2785)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-23 +* Fix bots equipping augments. ([#2772](https://github.com/EQEmu/Server/pull/2772)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-22 +* Fix case-sensitivity in #suspend Command. ([#2613](https://github.com/EQEmu/Server/pull/2613)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-05 +* Fix duplicate and missing messages due to innate in spells ([#2170](https://github.com/EQEmu/Server/pull/2170)) ([noudess](https://github.com/noudess)) 2022-05-20 +* Fix empty spawned merchants ([#2275](https://github.com/EQEmu/Server/pull/2275)) ([hgtw](https://github.com/hgtw)) 2022-06-28 +* Fix for Bot command casting ([#1990](https://github.com/EQEmu/Server/pull/1990)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-12 +* Fix for PR1954 target restriction with npcpc_only_flag from groupbuffs ([#1986](https://github.com/EQEmu/Server/pull/1986)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-10 +* Fix for being able to skill up on corspe. ([#2058](https://github.com/EQEmu/Server/pull/2058)) ([noudess](https://github.com/noudess)) 2022-03-19 +* Fix for castspell command ([#2010](https://github.com/EQEmu/Server/pull/2010)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-18 +* Fix issue where #advnpcspawn addspawn does not add spawn sometimes. ([#2247](https://github.com/EQEmu/Server/pull/2247)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-07 +* Fix issue where you can set your title to titles you don't have. ([#1917](https://github.com/EQEmu/Server/pull/1917)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-01-30 +* Fix issue with Bot::LoadAndSpawnAllZonedBots. ([#2733](https://github.com/EQEmu/Server/pull/2733)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-15 +* Fix issue with mobs summoning PCs into ceilings ([#1921](https://github.com/EQEmu/Server/pull/1921)) ([noudess](https://github.com/noudess)) 2022-01-30 +* Fix loading world shared task state ([#2398](https://github.com/EQEmu/Server/pull/2398)) ([hgtw](https://github.com/hgtw)) 2022-08-28 +* Fix luamod GetExperienceForKill return value ([Cole-SoD](https://github.com/Cole-SoD)) 2023-01-12 +* Fix memory leak in ucs ([#2409](https://github.com/EQEmu/Server/pull/2409)) ([hgtw](https://github.com/hgtw)) 2022-09-03 +* Fix miscellaneous memory leaks related to EQApplicationPacket and it's pBuffer ([#2262](https://github.com/EQEmu/Server/pull/2262)) ([Quintinon](https://github.com/Quintinon)) 2022-07-03 +* Fix null pointer crash on zones that have not booted a zone yet with #reload commands or anything that calls GetZoneDescription ([#2231](https://github.com/EQEmu/Server/pull/2231)) ([Akkadius](https://github.com/Akkadius)) 2022-06-01 +* Fix possible crash in ProcessSpecialAbilities. ([#2630](https://github.com/EQEmu/Server/pull/2630)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-11 +* Fix possible crash with zone name methods. ([#2055](https://github.com/EQEmu/Server/pull/2055)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-13 +* Fix possible issue where variables have the same name. ([#2156](https://github.com/EQEmu/Server/pull/2156)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-08 +* Fix quest::updatespawntimer() Perl croak. ([#1947](https://github.com/EQEmu/Server/pull/1947)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-01-26 +* Fix recipient sound (vtell) on non-player races ([#2066](https://github.com/EQEmu/Server/pull/2066)) ([noudess](https://github.com/noudess)) 2022-04-02 +* Fix scenario where dereferenced object could be null. ([#2784](https://github.com/EQEmu/Server/pull/2784)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-23 +* Fix stack leaks in Lua events #2254 ([hgtw](https://github.com/hgtw)) 2022-06-09 +* Fix trading with bots when in an illusion. ([#2645](https://github.com/EQEmu/Server/pull/2645)) ([nytmyr](https://github.com/nytmyr)) 2022-12-15 +* Fix two invalid data accesses in zone/client.cpp ([#2238](https://github.com/EQEmu/Server/pull/2238)) ([Quintinon](https://github.com/Quintinon)) 2022-06-07 +* Fixed Spell Logic for Bot Nukes ([#2481](https://github.com/EQEmu/Server/pull/2481)) ([Aeadoin](https://github.com/Aeadoin)) 2022-10-13 +* Fixed message on promote/demote permissions check. ([#2700](https://github.com/EQEmu/Server/pull/2700)) ([Valorith](https://github.com/Valorith)) 2023-01-02 +* Fixed several instances of incorrect comparision - & executes after == ([#2025](https://github.com/EQEmu/Server/pull/2025)) ([noudess](https://github.com/noudess)) 2022-03-07 +* Force NPCs to respect special ability 24 and 50 when set on player pets ([#2059](https://github.com/EQEmu/Server/pull/2059)) ([Natedog2012](https://github.com/Natedog2012)) 2022-03-16 +* Free return value of ZoneDatabase::LoadTraderItemWithCharges() ([#2264](https://github.com/EQEmu/Server/pull/2264)) ([Quintinon](https://github.com/Quintinon)) 2022-06-18 +* Hacker_Str was causing sql errors - Non Escaped ([#2251](https://github.com/EQEmu/Server/pull/2251)) ([fryguy503](https://github.com/fryguy503)) 2022-06-08 +* Handle memory leaks from return value of Client::GetTraderItems() ([#2266](https://github.com/EQEmu/Server/pull/2266)) ([Quintinon](https://github.com/Quintinon)) 2022-07-03 +* Handle_OP_AugmentItem could cause Zone crash ([#2750](https://github.com/EQEmu/Server/pull/2750)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-17 +* HasPet() Zone Crashes ([#2744](https://github.com/EQEmu/Server/pull/2744)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-15 +* Illusions will now properly display armor to other clients when they zone in. ([#1958](https://github.com/EQEmu/Server/pull/1958)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-04 +* Instrument Mods should not affect spells that change model size. ([#2072](https://github.com/EQEmu/Server/pull/2072)) ([KayenEQ](https://github.com/KayenEQ)) 2022-04-13 +* Invisible will display as dropped now on air pets when they attack. ([#2042](https://github.com/EQEmu/Server/pull/2042)) ([KayenEQ](https://github.com/KayenEQ)) 2022-03-07 +* IsDamage test for lifetap was not complete. ([#2213](https://github.com/EQEmu/Server/pull/2213)) ([noudess](https://github.com/noudess)) 2022-05-27 +* Limit merchant temp item list to zone and instance ([#2346](https://github.com/EQEmu/Server/pull/2346)) ([mackal](https://github.com/mackal)) 2022-07-31 +* Lua GetBlockNextSpell() no return. ([#2151](https://github.com/EQEmu/Server/pull/2151)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Make Perl TakeMoneyFromPP int64 ([#2158](https://github.com/EQEmu/Server/pull/2158)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-08 +* Missing break ([#2031](https://github.com/EQEmu/Server/pull/2031)) ([KayenEQ](https://github.com/KayenEQ)) 2022-03-04 +* Move EVENT_SPAWN for adding NPCs back to original spot, also add NPCs… ([#2749](https://github.com/EQEmu/Server/pull/2749)) ([Natedog2012](https://github.com/Natedog2012)) 2023-01-17 +* NPC Constructor was passing hp_regen_per_second out of order to Mob(). ([#2681](https://github.com/EQEmu/Server/pull/2681)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-29 +* NPC::CountItem and Corpse::CountItem 0 Charge Item Fix. ([#1959](https://github.com/EQEmu/Server/pull/1959)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-04 +* NPC::GetNPCStat has no default return. ([#2150](https://github.com/EQEmu/Server/pull/2150)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* NPCs were getting weapon proc added twice ([#2277](https://github.com/EQEmu/Server/pull/2277)) ([noudess](https://github.com/noudess)) 2022-07-07 +* Objects::GetTiltX() and Objects::GetTiltY() Perl Croak Typos. ([#2028](https://github.com/EQEmu/Server/pull/2028)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-04 +* PR 1982 ([#1985](https://github.com/EQEmu/Server/pull/1985)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-10 +* PR 2032 would lock client on casting fail as written ([#2038](https://github.com/EQEmu/Server/pull/2038)) ([KayenEQ](https://github.com/KayenEQ)) 2022-03-07 +* Remove StringUtilTest::EscapeStringMemoryTest ([#2310](https://github.com/EQEmu/Server/pull/2310)) ([mackal](https://github.com/mackal)) 2022-07-15 +* Remove Unnecessary Attack Log ([#2643](https://github.com/EQEmu/Server/pull/2643)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-14 +* Remove unnecessary log messages. ([#2642](https://github.com/EQEmu/Server/pull/2642)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-14 +* Removed Lua Event Argument Dispatch. ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-01 +* Resolve Warning due to Virtual Mob Method GetInv() ([#2650](https://github.com/EQEmu/Server/pull/2650)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-19 +* Resolve XP Calculation Bug introduced w/ recent Rule addition ([#2703](https://github.com/EQEmu/Server/pull/2703)) ([Valorith](https://github.com/Valorith)) 2023-01-07 +* Resolve logic error in Raid::QueueClients ([#2404](https://github.com/EQEmu/Server/pull/2404)) ([mackal](https://github.com/mackal)) 2022-09-01 +* Resolve subroutine redefinition due to bot methods. ([#2117](https://github.com/EQEmu/Server/pull/2117)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Restore missing messages for lifetap and dmg spells. ([#2057](https://github.com/EQEmu/Server/pull/2057)) ([noudess](https://github.com/noudess)) 2022-04-14 +* Shared Memory Faction Association Typo ([#2419](https://github.com/EQEmu/Server/pull/2419)) ([mackal](https://github.com/mackal)) 2022-09-03 +* Spell Buckets/Globals SQL Escape. ([#2019](https://github.com/EQEmu/Server/pull/2019)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-26 +* Spell Buckets/Globals did not allow string-based values. ([#2043](https://github.com/EQEmu/Server/pull/2043)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-09 +* Stop skill ups on Charmed NPCs. ([#2249](https://github.com/EQEmu/Server/pull/2249)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-10 +* Summon Companion causing pets to warps away. ([#1972](https://github.com/EQEmu/Server/pull/1972)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-08 +* Touch Of Vinitras was ignoring pet DT rule ([#2469](https://github.com/EQEmu/Server/pull/2469)) ([Aeadoin](https://github.com/Aeadoin)) 2022-10-03 +* Tradeskill Autocombine MinSkill ([#2260](https://github.com/EQEmu/Server/pull/2260)) ([fryguy503](https://github.com/fryguy503)) 2022-06-10 +* Tradeskill Item 0 Error ([#2256](https://github.com/EQEmu/Server/pull/2256)) ([fryguy503](https://github.com/fryguy503)) 2022-06-10 +* Zone Flags Regression ([#2760](https://github.com/EQEmu/Server/pull/2760)) ([Akkadius](https://github.com/Akkadius)) 2023-01-19 +* checking casting_spell_slot before its defined is bad ([#2013](https://github.com/EQEmu/Server/pull/2013)) ([KayenEQ](https://github.com/KayenEQ)) 2022-02-20 +* manifest for db version 9176 had incorrect field name ([#2062](https://github.com/EQEmu/Server/pull/2062)) ([noudess](https://github.com/noudess)) 2022-03-19 +* quest::MovePCInstance() Arguments Fix. ([#2020](https://github.com/EQEmu/Server/pull/2020)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-27 + +### Hotfix + +* Add Bazaar portal discs to SQL ([Akkadius](https://github.com/Akkadius)) 2022-09-05 +* Add discord_webhooks to server tables ([Akkadius](https://github.com/Akkadius)) 2022-07-03 +* Blocks are nested too deeply. ([#2689](https://github.com/EQEmu/Server/pull/2689)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-01 +* Cleanup #questerrors Command. ([#2116](https://github.com/EQEmu/Server/pull/2116)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-07 +* Compiling fails on FMT 9.1 with Bots ([#2665](https://github.com/EQEmu/Server/pull/2665)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-21 +* Correct database call to point to the content_db connection ([Akkadius](https://github.com/Akkadius)) 2022-06-12 +* Corrected misnamed Database Query file for Experience Toggle ([#2683](https://github.com/EQEmu/Server/pull/2683)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-31 +* Faction associations file naming / lock consistency ([Akkadius](https://github.com/Akkadius)) 2022-09-05 +* Fix DB version merge ([Akkadius](https://github.com/Akkadius)) 2022-05-08 +* Fix door click crash issue if destination zone doesn't exist ([Akkadius](https://github.com/Akkadius)) 2023-01-20 +* Fix issue with Bot Loading with 0 Health causing buffs to be lost. ([#2552](https://github.com/EQEmu/Server/pull/2552)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-18 +* Fix lua mod load path ([Akkadius](https://github.com/Akkadius)) 2022-09-29 +* Fix merge issue ([Akkadius](https://github.com/Akkadius)) 2022-07-14 +* Fix path load ordering for CLI commands ([Akkadius](https://github.com/Akkadius)) 2022-10-16 +* Fix potential race for crash dumps (Linux) ([Akkadius](https://github.com/Akkadius)) 2022-07-31 +* Fix regression caused by #2129 ([Akkadius](https://github.com/Akkadius)) 2022-05-09 +* Flipped positive / negative values for legacy_combat.lua ([Akkadius](https://github.com/Akkadius)) 2022-06-09 +* Force collation on conversion script ([Akkadius](https://github.com/Akkadius)) 2022-09-28 +* Instances Repository Fix ([#2576](https://github.com/EQEmu/Server/pull/2576)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-26 +* Login Server failing to compile on Windows. ([#2758](https://github.com/EQEmu/Server/pull/2758)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-19 +* Lua Parser Needs Lua_ItemInst ([#2696](https://github.com/EQEmu/Server/pull/2696)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-01 +* Make sure we have a proper split size before assuming we can split it ([Akkadius](https://github.com/Akkadius)) 2023-01-20 +* Move discord_webhooks to state tables because we don't want webhooks being exported ([Akkadius](https://github.com/Akkadius)) 2022-07-03 +* Possible windows compile fix ([Akkadius](https://github.com/Akkadius)) 2022-07-07 +* Possible windows compile fix take 2 ([Akkadius](https://github.com/Akkadius)) 2022-07-07 +* Remove appveyor fetch bots ([Akkadius](https://github.com/Akkadius)) 2023-01-21 +* Remove expansion field from account for those who have it ([#2357](https://github.com/EQEmu/Server/pull/2357)) ([Akkadius](https://github.com/Akkadius)) 2022-08-01 +* Resolve Zone Crashing when grouped with Bots. ([#2747](https://github.com/EQEmu/Server/pull/2747)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-16 +* Resolve issue with Bot Casting after zoning. ([#2617](https://github.com/EQEmu/Server/pull/2617)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-04 +* Return weather_type_map ([Akkadius](https://github.com/Akkadius)) 2022-10-14 +* SQL Update ([Akkadius](https://github.com/Akkadius)) 2022-07-31 +* Shared Memory Protection Fixes ([Akkadius](https://github.com/Akkadius)) 2022-07-27 +* Windows compile fix take 3 (final) ([Akkadius](https://github.com/Akkadius)) 2022-07-07 +* fix manifest ([Akkadius](https://github.com/Akkadius)) 2022-07-16 + +### Logging + +* Add stack trace in code paths that shouldn't occur ([#2453](https://github.com/EQEmu/Server/pull/2453)) ([Akkadius](https://github.com/Akkadius)) 2022-09-28 +* Cleanup AI Logging Events ([#2615](https://github.com/EQEmu/Server/pull/2615)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-04 +* Fix log messages to final damage values ([#2056](https://github.com/EQEmu/Server/pull/2056)) ([noudess](https://github.com/noudess)) 2022-03-14 +* Fix zoning log typo ([#2478](https://github.com/EQEmu/Server/pull/2478)) ([Akkadius](https://github.com/Akkadius)) 2022-10-11 +* Force crash logs to always be on regardless of setting ([#2762](https://github.com/EQEmu/Server/pull/2762)) ([Akkadius](https://github.com/Akkadius)) 2023-01-20 +* Improvements to GM Say Logging ([#2765](https://github.com/EQEmu/Server/pull/2765)) ([Akkadius](https://github.com/Akkadius)) 2023-01-20 +* Logging Improvements ([#2755](https://github.com/EQEmu/Server/pull/2755)) ([Akkadius](https://github.com/Akkadius)) 2023-01-18 +* More AI Logging Cleanup ([#2616](https://github.com/EQEmu/Server/pull/2616)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-10 +* Netcode Logging Unify ([#2443](https://github.com/EQEmu/Server/pull/2443)) ([Akkadius](https://github.com/Akkadius)) 2022-09-28 +* Remove function prefixes ([#2766](https://github.com/EQEmu/Server/pull/2766)) ([Akkadius](https://github.com/Akkadius)) 2023-01-20 +* Remove loginserver unhandled error ([#2458](https://github.com/EQEmu/Server/pull/2458)) ([Akkadius](https://github.com/Akkadius)) 2022-09-29 +* Reset stream so we don't bold the whole line ([Akkadius](https://github.com/Akkadius)) 2023-01-18 +* Table Injection - Member Variable Cleanup ([#2281](https://github.com/EQEmu/Server/pull/2281)) ([Akkadius](https://github.com/Akkadius)) 2022-07-07 +* Update BUILD_LOGGING=false Blank Aliases ([#2083](https://github.com/EQEmu/Server/pull/2083)) ([Akkadius](https://github.com/Akkadius)) 2022-05-01 + +### Luamod + +* Add CalcSpellEffectValue_formula to luamods ([#2721](https://github.com/EQEmu/Server/pull/2721)) ([Natedog2012](https://github.com/Natedog2012)) 2023-01-11 + +### Mercs + +* Add Mercenary Support ([#2745](https://github.com/EQEmu/Server/pull/2745)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-17 + +### Optimization + +* Handle channel name filter checks in memory ([#2767](https://github.com/EQEmu/Server/pull/2767)) ([Valorith](https://github.com/Valorith)) 2023-01-20 + +### QS + +* Database class name change ([#2743](https://github.com/EQEmu/Server/pull/2743)) ([Akkadius](https://github.com/Akkadius)) 2023-01-15 + +### Quest API + +* Add AddAISpellEffect(spell_effect_id, base_value, limit_value, max_value) and RemoveAISpellEffect(spell_effect_id) to Lua. ([#1981](https://github.com/EQEmu/Server/pull/1981)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-09 +* Add AddItem() to Perl/Lua. ([#2054](https://github.com/EQEmu/Server/pull/2054)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-13 +* Add AddPlatinum(), GetCarriedPlatinum() and TakePlatinum() to Perl/Lua. ([#2079](https://github.com/EQEmu/Server/pull/2079)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-04-30 +* Add Area Damage Methods to Perl/Lua. ([#2549](https://github.com/EQEmu/Server/pull/2549)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-17 +* Add Augment Slot Type/Visible to GetItemStat ([#2686](https://github.com/EQEmu/Server/pull/2686)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-01 +* Add Bot Methods to Lua. ([#2731](https://github.com/EQEmu/Server/pull/2731)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-14 +* Add Bot::Camp() to Perl/Lua. ([#2718](https://github.com/EQEmu/Server/pull/2718)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-11 +* Add BuffCount() Overloads to Perl/Lua. ([#2679](https://github.com/EQEmu/Server/pull/2679)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-29 +* Add CampAllBots() to Perl/Lua. ([#2732](https://github.com/EQEmu/Server/pull/2732)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-14 +* Add Charges/Augment/Attuned Support to Varlink. ([#2685](https://github.com/EQEmu/Server/pull/2685)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-01 +* Add CheckNameFilter to Perl/Lua. ([#2175](https://github.com/EQEmu/Server/pull/2175)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-20 +* Add Client Augment Events to Perl/Lua. ([#2735](https://github.com/EQEmu/Server/pull/2735)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-15 +* Add Client Spell Methods to Perl/Lua. ([#2550](https://github.com/EQEmu/Server/pull/2550)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22 +* Add CloneAppearance() to Perl/Lua. ([#2531](https://github.com/EQEmu/Server/pull/2531)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14 +* Add CopyHateList() to Perl/Lua. ([#2623](https://github.com/EQEmu/Server/pull/2623)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-06 +* Add Corpse::AddItem overloads for Lua ([#2509](https://github.com/EQEmu/Server/pull/2509)) ([hgtw](https://github.com/hgtw)) 2022-10-29 +* Add Despawn Events to Perl/Lua. ([#2707](https://github.com/EQEmu/Server/pull/2707)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-07 +* Add DoAnim Overloads to Perl/Lua. ([#2627](https://github.com/EQEmu/Server/pull/2627)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-10 +* Add DoAugmentSlotsMatch() to Perl/Lua. ([#2687](https://github.com/EQEmu/Server/pull/2687)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-01 +* Add DoesAugmentFit() to Perl/Lua. ([#2688](https://github.com/EQEmu/Server/pull/2688)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-01 +* Add Door Methods to Perl/Lua. ([#2724](https://github.com/EQEmu/Server/pull/2724)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-12 +* Add EVENT_AA_BUY and EVENT_AA_GAIN to Perl/Lua. ([#2504](https://github.com/EQEmu/Server/pull/2504)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-05 +* Add EVENT_BOT_CREATE to Perl/Lua ([#2713](https://github.com/EQEmu/Server/pull/2713)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-09 +* Add EVENT_CAST_ON exports to EVENT_CAST and EVENT_CAST_BEGIN. ([#2051](https://github.com/EQEmu/Server/pull/2051)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-12 +* Add EVENT_EQUIP_ITEM_CLIENT and EVENT_UNEQUIP_ITEM_CLIENT to Perl/Lua. ([#2015](https://github.com/EQEmu/Server/pull/2015)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-23 +* Add EVENT_GM_COMMAND to Perl/Lua. ([#2634](https://github.com/EQEmu/Server/pull/2634)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-11 +* Add EVENT_LEVEL_DOWN to Perl/Lua. ([#2620](https://github.com/EQEmu/Server/pull/2620)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-11 +* Add EVENT_PAYLOAD to Perl/Lua. ([#2611](https://github.com/EQEmu/Server/pull/2611)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-04 +* Add EVENT_SKILL_UP & EVENT_LANGUAGE_SKILL_UP to Perl/Lua ([#2076](https://github.com/EQEmu/Server/pull/2076)) ([nytmyr](https://github.com/nytmyr)) 2022-04-25 +* Add Entity Variable Methods to Perl/Lua. ([#2609](https://github.com/EQEmu/Server/pull/2609)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-04 +* Add Fling Overloads to Perl/Lua. ([#2622](https://github.com/EQEmu/Server/pull/2622)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-06 +* Add GetAugmentIDsBySlotID() to Perl/Lua. ([#2673](https://github.com/EQEmu/Server/pull/2673)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-25 +* Add GetAverageLevel() to Perl/Lua. ([#2524](https://github.com/EQEmu/Server/pull/2524)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14 +* Add GetBotItem() and GetBotItemIDBySlot() to Perl/Lua. ([#2350](https://github.com/EQEmu/Server/pull/2350)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-07-31 +* Add GetBotListByCharacterID() to Perl/Lua. ([#2069](https://github.com/EQEmu/Server/pull/2069)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-04-02 +* Add GetBotListByClientName() Class Overload to Perl/Lua. ([#2577](https://github.com/EQEmu/Server/pull/2577)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-26 +* Add GetBotListByClientName(client_name) to Perl/Lua. ([#2064](https://github.com/EQEmu/Server/pull/2064)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-23 +* Add GetEnvironmentalDamageName() to Perl/Lua. ([#1964](https://github.com/EQEmu/Server/pull/1964)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-10 +* Add GetGMStatus() to Perl/Lua. ([#2448](https://github.com/EQEmu/Server/pull/2448)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-09-28 +* Add GetGuildPublicNote() to Perl/Lua. ([#2608](https://github.com/EQEmu/Server/pull/2608)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-04 +* Add GetHealAmount() and GetSpellDamage() to Perl/Lua. ([#2165](https://github.com/EQEmu/Server/pull/2165)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-11 +* Add GetLeader() and GetLeaderName() to Perl/Lua. ([#2701](https://github.com/EQEmu/Server/pull/2701)) ([Valorith](https://github.com/Valorith)) 2023-01-04 +* Add GetLowestLevel() to Perl. ([#2517](https://github.com/EQEmu/Server/pull/2517)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-05 +* Add GetRandomBot() to Perl/Lua ([#2543](https://github.com/EQEmu/Server/pull/2543)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-16 +* Add GetRandomClient(), GetRandomMob() and GetRandomNPC() overloads to Perl/Lua. ([#2541](https://github.com/EQEmu/Server/pull/2541)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14 +* Add GetRandomMob() and GetRandomNPC() to Perl/Lua. ([#2006](https://github.com/EQEmu/Server/pull/2006)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-17 +* Add GetSkillDmgAmt() to Perl. ([#2365](https://github.com/EQEmu/Server/pull/2365)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-10 +* Add GetUltimateOwner() to Perl/Lua. ([#2516](https://github.com/EQEmu/Server/pull/2516)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-05 +* Add Goto Player Teleport Methods. ([#2379](https://github.com/EQEmu/Server/pull/2379)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-20 +* Add Group/Raid Overloads to Perl/Lua. ([#2587](https://github.com/EQEmu/Server/pull/2587)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-27 +* Add Group/Raid overloads to Perl/Lua. ([#2526](https://github.com/EQEmu/Server/pull/2526)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14 +* Add HasBotSpellEntry() to Perl/Lua. ([#2563](https://github.com/EQEmu/Server/pull/2563)) ([Aeadoin](https://github.com/Aeadoin)) 2022-11-25 +* Add Hotzone Methods to Perl/Lua. ([#2558](https://github.com/EQEmu/Server/pull/2558)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22 +* Add Instance ID/Version exports to EVENT_ZONE. ([#2502](https://github.com/EQEmu/Server/pull/2502)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-05 +* Add Instance Methods to Perl/Lua. ([#2573](https://github.com/EQEmu/Server/pull/2573)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-26 +* Add IsAttackAllowed() to Perl/Lua. ([#2672](https://github.com/EQEmu/Server/pull/2672)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-25 +* Add IsRaining() and IsSnowing() to Perl/Lua. ([#2477](https://github.com/EQEmu/Server/pull/2477)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-10-14 +* Add IsRareSpawn() to Perl/Lua. ([#2338](https://github.com/EQEmu/Server/pull/2338)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-07-30 +* Add Lua handlers for zone controller events ([#2514](https://github.com/EQEmu/Server/pull/2514)) ([hgtw](https://github.com/hgtw)) 2022-11-05 +* Add Marquee methods to Perl/Lua. ([#2544](https://github.com/EQEmu/Server/pull/2544)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-16 +* Add MaxSkills() to Perl/Lua. ([#2621](https://github.com/EQEmu/Server/pull/2621)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-06 +* Add Merchant Events to Perl/Lua. ([#2452](https://github.com/EQEmu/Server/pull/2452)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-09-28 +* Add Mob Hate Methods to Perl/Lua. ([#2548](https://github.com/EQEmu/Server/pull/2548)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-16 +* Add Overloads to MoveZone Methods in Perl/Lua. ([#2551](https://github.com/EQEmu/Server/pull/2551)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-22 +* Add Owner methods to Perl/Lua. ([#2542](https://github.com/EQEmu/Server/pull/2542)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14 +* Add Popup methods to Perl/Lua. ([#2533](https://github.com/EQEmu/Server/pull/2533)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14 +* Add Proximity Range Methods to Perl/Lua. ([#2572](https://github.com/EQEmu/Server/pull/2572)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-26 +* Add RandomizeFeature() overloads to Perl/Lua. ([#2532](https://github.com/EQEmu/Server/pull/2532)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14 +* Add Recipe Methods ([#2393](https://github.com/EQEmu/Server/pull/2393)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-23 +* Add ResetAlternateAdvancementRank() to Perl/Lua. ([#2510](https://github.com/EQEmu/Server/pull/2510)) ([hgtw](https://github.com/hgtw)) 2022-10-29 +* Add ResetDecayTimer() to Perl/Lua. ([#2520](https://github.com/EQEmu/Server/pull/2520)) ([hgtw](https://github.com/hgtw)) 2022-11-06 +* Add SendGMCommand() to Perl/Lua. ([#2527](https://github.com/EQEmu/Server/pull/2527)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14 +* Add SendPath() to Perl/Lua. ([#2740](https://github.com/EQEmu/Server/pull/2740)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-15 +* Add SignalAllBotsByOwnerName() to Perl/Lua. ([#2730](https://github.com/EQEmu/Server/pull/2730)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-13 +* Add SplitMoney() with Client splitter to Perl. ([#2525](https://github.com/EQEmu/Server/pull/2525)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-14 +* Add TaskSelector to Perl/Lua. ([#2177](https://github.com/EQEmu/Server/pull/2177)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-15 +* Add Time String to Seconds Method to Perl/Lua. ([#2580](https://github.com/EQEmu/Server/pull/2580)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-27 +* Add TrackNPC to Perl/Lua. ([#2272](https://github.com/EQEmu/Server/pull/2272)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-29 +* Add WearChange Overloads to Perl/Lua. ([#2600](https://github.com/EQEmu/Server/pull/2600)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-01 +* Add Zone Flag Methods to Perl/Lua. ([#2574](https://github.com/EQEmu/Server/pull/2574)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-26 +* Add apis to end shared tasks ([#2521](https://github.com/EQEmu/Server/pull/2521)) ([hgtw](https://github.com/hgtw)) 2022-11-06 +* Add caster_id and caster_level export to EVENT_CAST_ON in Perl/Lua. ([#2049](https://github.com/EQEmu/Server/pull/2049)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-11 +* Add commify to Perl/Lua. ([#2099](https://github.com/EQEmu/Server/pull/2099)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-03 +* Add inventory->CountItemEquippedByID(item_id) and inventory->HasItemEquippedByID(item_id) to Perl/Lua. ([#1963](https://github.com/EQEmu/Server/pull/1963)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-02-06 +* Add missing methods/package.adds to Perl API. ([#2287](https://github.com/EQEmu/Server/pull/2287)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-07-05 +* Add multiple inventory method short hands to client. ([#2078](https://github.com/EQEmu/Server/pull/2078)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-04-30 +* Add option to Ignore Mods to CalcEXP ([#2704](https://github.com/EQEmu/Server/pull/2704)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-06 +* Adjustment to depop_all function. ([#2595](https://github.com/EQEmu/Server/pull/2595)) ([fryguy503](https://github.com/fryguy503)) 2022-11-30 +* Allow CreateInstance to be used without a Client initiator. ([#2399](https://github.com/EQEmu/Server/pull/2399)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-28 +* Allow EVENT_ZONE to be parsed as non-zero to prevent zoning. ([#2052](https://github.com/EQEmu/Server/pull/2052)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-12 +* Allow scripts to prevent door click ([#2327](https://github.com/EQEmu/Server/pull/2327)) ([hgtw](https://github.com/hgtw)) 2022-07-27 +* Cleanup Proximity Events ([#2697](https://github.com/EQEmu/Server/pull/2697)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-02 +* Cleanup Signal Methods in Perl/Lua. ([#2604](https://github.com/EQEmu/Server/pull/2604)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-04 +* Expand Bot quest API functionality. ([#2096](https://github.com/EQEmu/Server/pull/2096)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-04 +* Expand SaveGuardSpot ([#2258](https://github.com/EQEmu/Server/pull/2258)) ([fryguy503](https://github.com/fryguy503)) 2022-06-10 +* Export corpse in EVENT_DEATH_COMPLETE ([#2519](https://github.com/EQEmu/Server/pull/2519)) ([hgtw](https://github.com/hgtw)) 2022-11-06 +* Export killed XYZH to EVENT_DEATH_ZONE in Perl. ([#2050](https://github.com/EQEmu/Server/pull/2050)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-03-12 +* Fix Lua Door/Object Create Methods. ([#2633](https://github.com/EQEmu/Server/pull/2633)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-12-11 +* Fix Perl EVENT_HP double parsing in Spire. ([#2585](https://github.com/EQEmu/Server/pull/2585)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-11-27 +* Fix lua task selector count when over max ([#2353](https://github.com/EQEmu/Server/pull/2353)) ([hgtw](https://github.com/hgtw)) 2022-07-31 +* Fix missing arg in perl set_proximity ([#2291](https://github.com/EQEmu/Server/pull/2291)) ([hgtw](https://github.com/hgtw)) 2022-07-09 +* Fix parameters in some Perl worldwide methods. ([#2224](https://github.com/EQEmu/Server/pull/2224)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-31 +* Let HasQuestSub check encounters ([#2435](https://github.com/EQEmu/Server/pull/2435)) ([hgtw](https://github.com/hgtw)) 2022-09-20 +* Perl Doors Fix. ([#2288](https://github.com/EQEmu/Server/pull/2288)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-07-05 +* Perl Money Fixes. ([#2098](https://github.com/EQEmu/Server/pull/2098)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-04 +* Send delivered task items in trade events ([#2518](https://github.com/EQEmu/Server/pull/2518)) ([hgtw](https://github.com/hgtw)) 2022-11-06 +* Use Floating Point for CameraEffect Intensity ([#2337](https://github.com/EQEmu/Server/pull/2337)) ([hgtw](https://github.com/hgtw)) 2022-07-31 +* Use binding library for perl apis ([#2216](https://github.com/EQEmu/Server/pull/2216)) ([hgtw](https://github.com/hgtw)) 2022-07-04 + +### Rules + +* Add Backstab Rules ([#2666](https://github.com/EQEmu/Server/pull/2666)) ([Valorith](https://github.com/Valorith)) 2022-12-21 +* Add Frontal Stun Immunity Rules. ([#2217](https://github.com/EQEmu/Server/pull/2217)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-07 +* Add Keep Level on Death ([#2319](https://github.com/EQEmu/Server/pull/2319)) ([trentdm](https://github.com/trentdm)) 2022-07-30 +* Add LDoN Loot Count Modifier Rule ([#2694](https://github.com/EQEmu/Server/pull/2694)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-03 +* Add ManaOnDeath and EndurOnDeath ([#2661](https://github.com/EQEmu/Server/pull/2661)) ([fryguy503](https://github.com/fryguy503)) 2022-12-20 +* Add Rule to Disable NPC Last Names. ([#2227](https://github.com/EQEmu/Server/pull/2227)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-04 +* Add Rule to Enable Tells with #hideme ([#2358](https://github.com/EQEmu/Server/pull/2358)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-08-04 +* Add Rule to allow Assassinate on non-Humanoid body types. ([#2331](https://github.com/EQEmu/Server/pull/2331)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-07-29 +* Add Rule to allow Headshots on non-Humanoid body types. ([#2329](https://github.com/EQEmu/Server/pull/2329)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-07-29 +* Add Rules to disable various item functionalities and cleanup data types. ([#2225](https://github.com/EQEmu/Server/pull/2225)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-06-01 +* Add Spells:BuffsFadeOnDeath. ([#2200](https://github.com/EQEmu/Server/pull/2200)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-27 +* Add Spells:IllusionsAlwaysPersist. ([#2199](https://github.com/EQEmu/Server/pull/2199)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-27 +* Add Toggle for Warrior Shielding ([#2496](https://github.com/EQEmu/Server/pull/2496)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-10-22 +* Add adjustment for zone forage. ([#2330](https://github.com/EQEmu/Server/pull/2330)) ([fryguy503](https://github.com/fryguy503)) 2022-07-30 +* Add rule for NPC Level Based Buff Restrictions. ([#2708](https://github.com/EQEmu/Server/pull/2708)) ([noudess](https://github.com/noudess)) 2023-01-15 +* Add rule to allow players to permanently save chat channels to database, up to a limit. ([#2706](https://github.com/EQEmu/Server/pull/2706)) ([Valorith](https://github.com/Valorith)) 2023-01-19 +* Change TradeskillUp Rules to be Floats ([#2674](https://github.com/EQEmu/Server/pull/2674)) ([Aeadoin](https://github.com/Aeadoin)) 2022-12-25 +* Cleanup all unused rules. ([#2184](https://github.com/EQEmu/Server/pull/2184)) ([Kinglykrab](https://github.com/Kinglykrab)) 2022-05-23 +* Rule Gate Pet Zoning ([#2625](https://github.com/EQEmu/Server/pull/2625)) ([fryguy503](https://github.com/fryguy503)) 2022-12-07 +* Rule to allow cap on % XP gain per kill ([#2667](https://github.com/EQEmu/Server/pull/2667)) ([Valorith](https://github.com/Valorith)) 2022-12-25 +* Update logic checks everywhere for FVNoDropFlag. ([#2179](https://github.com/EQEmu/Server/pull/2179)) ([Quintinon](https://github.com/Quintinon)) 2022-07-30 + +### SQL + +* Bugs Table Migration (#2602) ([#2559](https://github.com/EQEmu/Server/pull/2559)) ([joligario](https://github.com/joligario)) 2022-12-01 +* Update 2023_01_15_merc_data.sql ([#2763](https://github.com/EQEmu/Server/pull/2763)) ([joligario](https://github.com/joligario)) 2023-01-20 + +### UCS + +* Auto Client Reconnection ([#2154](https://github.com/EQEmu/Server/pull/2154)) ([Akkadius](https://github.com/Akkadius)) 2022-05-08 + +### Websocket + +* Fix cpp20/gcc11 compile failure ([#2737](https://github.com/EQEmu/Server/pull/2737)) ([Akkadius](https://github.com/Akkadius)) 2023-01-15 + +### Zone Flags + +* Use database connection, not content connection ([#2759](https://github.com/EQEmu/Server/pull/2759)) ([Akkadius](https://github.com/Akkadius)) 2023-01-19 diff --git a/CMakeLists.txt b/CMakeLists.txt index 5428e6c06..edc57094b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,7 @@ IF(MSVC) ADD_DEFINITIONS(-D_HAS_AUTO_PTR_ETC) # for Luabind on C++17 SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") + ADD_DEFINITIONS( "/W0 /D_CRT_SECURE_NO_WARNINGS /wd4005 /wd4996 /nologo /Os") ELSE(MSVC) ADD_DEFINITIONS(-DHAS_UNION_SEMUN) ENDIF(MSVC) diff --git a/README.md b/README.md index 225c246ab..59e525af6 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # EQEmulator Core Server -|Travis CI (Linux)|Appveyor (Windows x86) |Appveyor (Windows x64) | -|:---:|:---:|:---:| -|[![Linux CI](https://travis-ci.org/EQEmu/Server.svg?branch=master)](https://travis-ci.org/EQEmu/Server) |[![Build status](https://ci.appveyor.com/api/projects/status/v3utuu0dttm2cqd0?svg=true)](https://ci.appveyor.com/project/KimLS/server) |[![Build status](https://ci.appveyor.com/api/projects/status/scr25kmntx36c1ub?svg=true)](https://ci.appveyor.com/project/KimLS/server-87crp) | +| Drone (Linux x64) | Drone (Windows x64) | +|:---:|:---:| +|[![Build Status](http://drone.akkadius.com/api/badges/EQEmu/Server/status.svg)](http://drone.akkadius.com/EQEmu/Server) |[![Build Status](http://drone.akkadius.com/api/badges/EQEmu/Server/status.svg)](http://drone.akkadius.com/EQEmu/Server) | *** diff --git a/appveyor-bots.yml b/appveyor-bots.yml deleted file mode 100644 index 63f40abe1..000000000 --- a/appveyor-bots.yml +++ /dev/null @@ -1,21 +0,0 @@ -version: 1.0.{build} -branches: - only: - - master -image: Visual Studio 2017 -configuration: RelWithDebInfo -clone_folder: c:\projects\eqemu -init: -- ps: git config --global core.autocrlf input -cache: c:\tools\vcpkg\installed\ -before_build: -- ps: "$wc = New-Object System.Net.WebClient\n$wc.DownloadFile(\"http://strawberryperl.com/download/5.26.2.1/strawberry-perl-5.26.2.1-64bit-portable.zip\", \"c:\\projects\\eqemu\\strawberry-perl-5.26.2.1-64bit-portable.zip\")\ncd c:\\projects\\eqemu\n7z x c:/projects/eqemu/strawberry-perl-5.26.2.1-64bit-portable.zip -oc:/projects/eqemu/strawberry-perl-portable -y\n(Get-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h).replace('#define PERL_STATIC_INLINE static __inline__', '#define PERL_STATIC_INLINE static __inline') | Set-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h\nvcpkg install boost-geometry:x64-windows boost-dynamic-bitset:x64-windows luajit:x64-windows libsodium:x64-windows libmysql:x64-windows openssl:x64-windows zlib:x64-windows \nmkdir build\ncd build\ncmake -G \"Visual Studio 15 2017 Win64\" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -DPERL_EXECUTABLE=\"C:/projects/eqemu/strawberry-perl-portable/perl/bin/perl.exe\" -DPERL_INCLUDE_PATH=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE\" -DPERL_LIBRARY=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/libperl526.a\" -DCMAKE_TOOLCHAIN_FILE=\"c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake\" .." -build: - project: C:\projects\eqemu\build\EQEmu.sln - parallel: true - verbosity: minimal -after_build: -- cmd: >- - 7z a build_x64-bots.zip C:\projects\eqemu\build\bin\RelWithDebInfo\*.exe C:\projects\eqemu\build\bin\RelWithDebInfo\*.dll C:\projects\eqemu\build\bin\RelWithDebInfo\*.pdb C:\projects\eqemu\build\libs\zlibng\RelWithDebInfo\*.dll - - appveyor PushArtifact build_x64-bots.zip diff --git a/appveyor-no-bots.yml b/appveyor-no-bots.yml deleted file mode 100644 index 962f15cab..000000000 --- a/appveyor-no-bots.yml +++ /dev/null @@ -1,21 +0,0 @@ -version: 1.0.{build} -branches: - only: - - master -image: Visual Studio 2017 -configuration: RelWithDebInfo -clone_folder: c:\projects\eqemu -init: -- ps: git config --global core.autocrlf input -cache: c:\tools\vcpkg\installed\ -before_build: -- ps: "$wc = New-Object System.Net.WebClient\n$wc.DownloadFile(\"http://strawberryperl.com/download/5.26.2.1/strawberry-perl-5.26.2.1-64bit-portable.zip\", \"c:\\projects\\eqemu\\strawberry-perl-5.26.2.1-64bit-portable.zip\")\ncd c:\\projects\\eqemu\n7z x c:/projects/eqemu/strawberry-perl-5.26.2.1-64bit-portable.zip -oc:/projects/eqemu/strawberry-perl-portable -y\n(Get-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h).replace('#define PERL_STATIC_INLINE static __inline__', '#define PERL_STATIC_INLINE static __inline') | Set-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h\nvcpkg install boost-geometry:x64-windows boost-dynamic-bitset:x64-windows luajit:x64-windows libsodium:x64-windows libmysql:x64-windows openssl:x64-windows zlib:x64-windows \nmkdir build\ncd build\ncmake -G \"Visual Studio 15 2017 Win64\" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -DPERL_EXECUTABLE=\"C:/projects/eqemu/strawberry-perl-portable/perl/bin/perl.exe\" -DPERL_INCLUDE_PATH=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE\" -DPERL_LIBRARY=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/libperl526.a\" -DCMAKE_TOOLCHAIN_FILE=\"c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake\" .." -build: - project: C:\projects\eqemu\build\EQEmu.sln - parallel: true - verbosity: minimal -after_build: -- cmd: >- - 7z a build_x64-no-bots.zip C:\projects\eqemu\build\bin\RelWithDebInfo\*.exe C:\projects\eqemu\build\bin\RelWithDebInfo\*.dll C:\projects\eqemu\build\bin\RelWithDebInfo\*.pdb C:\projects\eqemu\build\libs\zlibng\RelWithDebInfo\*.dll - - appveyor PushArtifact build_x64-no-bots.zip diff --git a/client_files/export/main.cpp b/client_files/export/main.cpp index 505a4ac05..08e203722 100644 --- a/client_files/export/main.cpp +++ b/client_files/export/main.cpp @@ -86,7 +86,7 @@ int main(int argc, char **argv) return 1; } } else { - content_db.SetMysql(database.getMySQL()); + content_db.SetMySQL(database); } LogSys.SetDatabase(&database) @@ -183,7 +183,7 @@ bool SkillUsable(SharedDatabase *db, int skill_id, int class_id) } auto row = results.begin(); - if (row[0] && atoi(row[0]) > 0) { + if (row[0] && Strings::ToInt(row[0]) > 0) { return true; } @@ -207,7 +207,7 @@ int GetSkill(SharedDatabase *db, int skill_id, int class_id, int level) } auto row = results.begin(); - return atoi(row[0]); + return Strings::ToInt(row[0]); } void ExportSkillCaps(SharedDatabase *db) diff --git a/client_files/import/main.cpp b/client_files/import/main.cpp index c80ed8194..c1859be0e 100644 --- a/client_files/import/main.cpp +++ b/client_files/import/main.cpp @@ -83,7 +83,7 @@ int main(int argc, char **argv) { return 1; } } else { - content_db.SetMysql(database.getMySQL()); + content_db.SetMySQL(database); } LogSys.SetDatabase(&database) @@ -241,10 +241,10 @@ void ImportSkillCaps(SharedDatabase *db) { } int class_id, skill_id, level, cap; - class_id = atoi(split[0].c_str()); - skill_id = atoi(split[1].c_str()); - level = atoi(split[2].c_str()); - cap = atoi(split[3].c_str()); + class_id = Strings::ToInt(split[0].c_str()); + skill_id = Strings::ToInt(split[1].c_str()); + level = Strings::ToInt(split[2].c_str()); + cap = Strings::ToInt(split[3].c_str()); std::string sql = StringFormat("INSERT INTO skill_caps(class, skillID, level, cap) VALUES(%d, %d, %d, %d)", class_id, skill_id, level, cap); @@ -280,16 +280,16 @@ void ImportBaseData(SharedDatabase *db) { int level, class_id; double hp, mana, end, unk1, unk2, hp_fac, mana_fac, end_fac; - level = atoi(split[0].c_str()); - class_id = atoi(split[1].c_str()); - hp = atof(split[2].c_str()); - mana = atof(split[3].c_str()); - end = atof(split[4].c_str()); - unk1 = atof(split[5].c_str()); - unk2 = atof(split[6].c_str()); - hp_fac = atof(split[7].c_str()); - mana_fac = atof(split[8].c_str()); - end_fac = atof(split[9].c_str()); + level = Strings::ToInt(split[0].c_str()); + class_id = Strings::ToInt(split[1].c_str()); + hp = Strings::ToFloat(split[2].c_str()); + mana = Strings::ToFloat(split[3].c_str()); + end = Strings::ToFloat(split[4].c_str()); + unk1 = Strings::ToFloat(split[5].c_str()); + unk2 = Strings::ToFloat(split[6].c_str()); + hp_fac = Strings::ToFloat(split[7].c_str()); + mana_fac = Strings::ToFloat(split[8].c_str()); + end_fac = Strings::ToFloat(split[9].c_str()); sql = StringFormat("INSERT INTO base_data(level, class, hp, mana, end, unk1, unk2, hp_fac, " "mana_fac, end_fac) VALUES(%d, %d, %f, %f, %f, %f, %f, %f, %f, %f)", @@ -339,8 +339,8 @@ void ImportDBStrings(SharedDatabase *db) { int id, type; std::string value; - id = atoi(split[0].c_str()); - type = atoi(split[1].c_str()); + id = Strings::ToInt(split[0].c_str()); + type = Strings::ToInt(split[1].c_str()); if(split.size() >= 3) { value = ::Strings::Escape(split[2]); diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index b9b4fa21c..0f9fe6aa6 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -33,9 +33,11 @@ SET(common_sources eq_stream_proxy.cpp eqtime.cpp event_sub.cpp + events/player_event_logs.cpp + events/player_event_discord_formatter.cpp expedition_lockout_timer.cpp extprofile.cpp - discord_manager.cpp + discord/discord_manager.cpp faction.cpp file.cpp guild_base.cpp @@ -198,7 +200,6 @@ SET(repositories repositories/base/base_dynamic_zones_repository.h repositories/base/base_dynamic_zone_members_repository.h repositories/base/base_dynamic_zone_templates_repository.h - repositories/base/base_eventlog_repository.h repositories/base/base_expeditions_repository.h repositories/base/base_expedition_lockouts_repository.h repositories/base/base_faction_association_repository.h @@ -218,7 +219,6 @@ SET(repositories repositories/base/base_guilds_repository.h repositories/base/base_guild_ranks_repository.h repositories/base/base_guild_relations_repository.h - repositories/base/base_hackers_repository.h repositories/base/base_horses_repository.h repositories/base/base_instance_list_repository.h repositories/base/base_instance_list_player_repository.h @@ -264,6 +264,8 @@ SET(repositories repositories/base/base_pets_equipmentset_repository.h repositories/base/base_pets_equipmentset_entries_repository.h repositories/base/base_player_titlesets_repository.h + repositories/base/base_player_event_log_settings_repository.h + repositories/base/base_player_event_logs_repository.h repositories/base/base_quest_globals_repository.h repositories/base/base_raid_details_repository.h repositories/base/base_raid_members_repository.h @@ -376,7 +378,6 @@ SET(repositories repositories/dynamic_zones_repository.h repositories/dynamic_zone_members_repository.h repositories/dynamic_zone_templates_repository.h - repositories/eventlog_repository.h repositories/expeditions_repository.h repositories/expedition_lockouts_repository.h repositories/faction_association_repository.h @@ -396,7 +397,6 @@ SET(repositories repositories/guilds_repository.h repositories/guild_ranks_repository.h repositories/guild_relations_repository.h - repositories/hackers_repository.h repositories/horses_repository.h repositories/instance_list_repository.h repositories/instance_list_player_repository.h @@ -442,6 +442,8 @@ SET(repositories repositories/pets_equipmentset_repository.h repositories/pets_equipmentset_entries_repository.h repositories/player_titlesets_repository.h + repositories/player_event_log_settings_repository.h + repositories/player_event_logs_repository.h repositories/quest_globals_repository.h repositories/raid_details_repository.h repositories/raid_members_repository.h @@ -507,7 +509,7 @@ SET(common_headers dbcore.h deity.h discord/discord.h - discord_manager.h + discord/discord_manager.h dynamic_zone_base.h emu_constants.h emu_limits.h @@ -530,6 +532,9 @@ SET(common_headers eq_stream_locator.h eq_stream_proxy.h eqtime.h + events/player_event_logs.h + events/player_event_discord_formatter.h + events/player_events.h errmsg.h event_sub.h expedition_lockout_timer.h @@ -608,6 +613,7 @@ SET(common_headers event/event_loop.h event/task.h event/timer.h + json/json_archive_single_line.h json/json.h json/json-forwards.h net/console_server.h @@ -661,8 +667,7 @@ SET(common_headers StackWalker/StackWalker.h util/memory_stream.h util/directory.h - util/uuid.h - ) + util/uuid.h) SOURCE_GROUP(Event FILES event/event_loop.h diff --git a/common/crash.cpp b/common/crash.cpp index 8fc7323e8..e5d4d993b 100644 --- a/common/crash.cpp +++ b/common/crash.cpp @@ -3,13 +3,96 @@ #include "crash.h" #include "strings.h" #include "process/process.h" +#include "http/httplib.h" +#include "http/uri.h" +#include "json/json.h" +#include "version.h" +#include "eqemu_config.h" +#include "serverinfo.h" +#include "rulesys.h" +#include "platform.h" #include +#include #if WINDOWS #define popen _popen #endif +void SendCrashReport(const std::string &crash_report) +{ + // can configure multiple endpoints if need be + std::vector endpoints = { + "http://spire.akkadius.com/api/v1/analytics/server-crash-report", +// "http://localhost:3010/api/v1/analytics/server-crash-report", // development + }; + + auto config = EQEmuConfig::get(); + for (auto &e: endpoints) { + uri u(e); + + std::string base_url = fmt::format("{}://{}", u.get_scheme(), u.get_host()); + if (u.get_port()) { + base_url += fmt::format(":{}", u.get_port()); + } + + // client + httplib::Client r(base_url); + r.set_connection_timeout(1, 0); + r.set_read_timeout(1, 0); + r.set_write_timeout(1, 0); + httplib::Headers headers = { + {"Content-Type", "application/json"} + }; + + // os info + auto os = EQ::GetOS(); + auto cpus = EQ::GetCPUs(); + auto process_id = EQ::GetPID(); + auto rss = EQ::GetRSS() / 1048576.0; + auto uptime = static_cast(EQ::GetUptime()); + + // payload + Json::Value p; + p["platform_name"] = GetPlatformName(); + p["crash_report"] = crash_report; + p["server_version"] = CURRENT_VERSION; + p["compile_date"] = COMPILE_DATE; + p["compile_time"] = COMPILE_TIME; + p["server_name"] = config->LongName; + p["server_short_name"] = config->ShortName; + p["uptime"] = uptime; + p["os_machine"] = os.machine; + p["os_release"] = os.release; + p["os_version"] = os.version; + p["os_sysname"] = os.sysname; + p["process_id"] = process_id; + p["rss_memory"] = rss; + p["cpus"] = cpus.size(); + p["origination_info"] = ""; + + if (!LogSys.origination_info.zone_short_name.empty()) { + p["origination_info"] = fmt::format( + "{} ({}) instance_id [{}]", + LogSys.origination_info.zone_short_name, + LogSys.origination_info.zone_long_name, + LogSys.origination_info.instance_id + ); + } + + std::stringstream payload; + payload << p; + + if (auto res = r.Post(e, payload.str(), "application/json")) { + if (res->status == 200) { + LogInfo("Sent crash report"); + } + else { + LogError("Failed to send crash report to [{}]", e); + } + } + } +} #if defined(_WINDOWS) && defined(CRASH_LOGGING) #include "StackWalker.h" @@ -21,22 +104,30 @@ public: EQEmuStackWalker(DWORD dwProcessId, HANDLE hProcess) : StackWalker(dwProcessId, hProcess) { } virtual void OnOutput(LPCSTR szText) { char buffer[4096]; - for(int i = 0; i < 4096; ++i) { - if(szText[i] == 0) { + for (int i = 0; i < 4096; ++i) { + if (szText[i] == 0) { buffer[i] = '\0'; break; } - if(szText[i] == '\n' || szText[i] == '\r') { + if (szText[i] == '\n' || szText[i] == '\r') { buffer[i] = ' '; - } else { + } + else { buffer[i] = szText[i]; } } + std::string line = buffer; + _lines.push_back(line); + Log(Logs::General, Logs::Crash, buffer); StackWalker::OnOutput(szText); } + + const std::vector& const GetLines() { return _lines; } +private: + std::vector _lines; }; LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo) @@ -110,7 +201,20 @@ LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo) if(EXCEPTION_STACK_OVERFLOW != ExceptionInfo->ExceptionRecord->ExceptionCode) { - EQEmuStackWalker sw; sw.ShowCallstack(GetCurrentThread(), ExceptionInfo->ContextRecord); + EQEmuStackWalker sw; + sw.ShowCallstack(GetCurrentThread(), ExceptionInfo->ContextRecord); + + if (RuleB(Analytics, CrashReporting)) { + std::string crash_report; + auto& lines = sw.GetLines(); + + for (auto& line : lines) { + crash_report += line; + crash_report += "\n"; + } + + SendCrashReport(crash_report); + } } return EXCEPTION_EXECUTE_HANDLER; @@ -181,12 +285,18 @@ void print_trace() } std::ifstream input(temp_output_file); + std::string crash_report; for (std::string line; getline(input, line);) { LogCrash("{}", line); + crash_report += fmt::format("{}\n", line); } std::remove(temp_output_file.c_str()); + if (RuleB(Analytics, CrashReporting)) { + SendCrashReport(crash_report); + } + exit(1); } diff --git a/common/cron/croncpp.h b/common/cron/croncpp.h index 5a22a7f72..3034dc952 100644 --- a/common/cron/croncpp.h +++ b/common/cron/croncpp.h @@ -313,7 +313,7 @@ namespace cron { try { - return static_cast(std::stoul(text.data())); + return static_cast(Strings::ToUnsignedInt(text.data())); } catch (std::exception const & ex) { diff --git a/common/database.cpp b/common/database.cpp index a93cb7669..407268c89 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -121,10 +121,10 @@ uint32 Database::CheckLogin(const char* name, const char* password, const char * auto row = results.begin(); - auto id = std::stoul(row[0]); + auto id = Strings::ToUnsignedInt(row[0]); if (oStatus) { - *oStatus = std::stoi(row[1]); + *oStatus = Strings::ToInt(row[1]); } return id; @@ -202,11 +202,11 @@ int16 Database::CheckStatus(uint32 account_id) } auto row = results.begin(); - int16 status = std::stoi(row[0]); + int16 status = Strings::ToInt(row[0]); int32 date_diff = 0; if (row[1]) { - date_diff = std::stoi(row[1]); + date_diff = Strings::ToInt(row[1]); } if (date_diff > 0) { @@ -345,7 +345,7 @@ bool Database::ReserveName(uint32 account_id, char* name) { std::string query = StringFormat("SELECT `account_id`, `name` FROM `character_data` WHERE `name` = '%s'", name); auto results = QueryDatabase(query); for (auto row = results.begin(); row != results.end(); ++row) { - if (row[0] && atoi(row[0]) > 0){ + if (row[0] && Strings::ToInt(row[0]) > 0){ LogInfo("Account: [{}] tried to request name: [{}], but it is already taken", account_id, name); return false; } @@ -387,7 +387,7 @@ bool Database::DeleteCharacter(char *character_name) std::string query = StringFormat("SELECT `id` from `character_data` WHERE `name` = '%s'", character_name); auto results = QueryDatabase(query); for (auto row = results.begin(); row != results.end(); ++row) { - character_id = atoi(row[0]); + character_id = Strings::ToInt(row[0]); } if (character_id <= 0) { @@ -787,7 +787,7 @@ uint32 Database::GetCharacterID(const char *name) { auto row = results.begin(); if (results.RowCount() == 1) { - return atoi(row[0]); + return Strings::ToInt(row[0]); } return 0; } @@ -812,10 +812,10 @@ uint32 Database::GetAccountIDByChar(const char* charname, uint32* oCharID) { auto row = results.begin(); - uint32 accountId = atoi(row[0]); + uint32 accountId = Strings::ToInt(row[0]); if (oCharID) - *oCharID = atoi(row[1]); + *oCharID = Strings::ToInt(row[1]); return accountId; } @@ -832,7 +832,7 @@ uint32 Database::GetAccountIDByChar(uint32 char_id) { return 0; auto row = results.begin(); - return atoi(row[0]); + return Strings::ToInt(row[0]); } uint32 Database::GetAccountIDByName(std::string account_name, std::string loginserver, int16* status, uint32* lsid) { @@ -852,14 +852,14 @@ uint32 Database::GetAccountIDByName(std::string account_name, std::string logins } auto row = results.begin(); - auto account_id = std::stoul(row[0]); + auto account_id = Strings::ToUnsignedInt(row[0]); if (status) { - *status = static_cast(std::stoi(row[1])); + *status = static_cast(Strings::ToInt(row[1])); } if (lsid) { - *lsid = row[2] ? std::stoul(row[2]) : 0; + *lsid = row[2] ? Strings::ToUnsignedInt(row[2]) : 0; } return account_id; @@ -880,7 +880,7 @@ void Database::GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID strcpy(name, row[0]); if (row[1] && oLSAccountID) { - *oLSAccountID = atoi(row[1]); + *oLSAccountID = Strings::ToInt(row[1]); } } @@ -968,7 +968,7 @@ bool Database::LoadVariables() { std::string key, value; for (auto row = results.begin(); row != results.end(); ++row) { - varcache.last_update = atoi(row[2]); // ahh should we be comparing if this is newer? + varcache.last_update = Strings::ToInt(row[2]); // ahh should we be comparing if this is newer? key = row[0]; value = row[1]; std::transform(std::begin(key), std::end(key), std::begin(key), ::tolower); // keys are lower case, DB doesn't have to be @@ -1052,15 +1052,15 @@ bool Database::GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zon auto row = results.begin(); if(graveyard_zoneid != nullptr) - *graveyard_zoneid = atoi(row[0]); + *graveyard_zoneid = Strings::ToInt(row[0]); if(graveyard_x != nullptr) - *graveyard_x = atof(row[1]); + *graveyard_x = Strings::ToFloat(row[1]); if(graveyard_y != nullptr) - *graveyard_y = atof(row[2]); + *graveyard_y = Strings::ToFloat(row[2]); if(graveyard_z != nullptr) - *graveyard_z = atof(row[3]); + *graveyard_z = Strings::ToFloat(row[3]); if(graveyard_heading != nullptr) - *graveyard_heading = atof(row[4]); + *graveyard_heading = Strings::ToFloat(row[4]); return true; } @@ -1168,13 +1168,13 @@ uint32 Database::GetAccountIDFromLSID( } for (auto row = results.begin(); row != results.end(); ++row) { - account_id = std::stoi(row[0]); + account_id = Strings::ToInt(row[0]); if (in_account_name) { strcpy(in_account_name, row[1]); } if (in_status) { - *in_status = std::stoi(row[2]); + *in_status = Strings::ToInt(row[2]); } } @@ -1198,7 +1198,7 @@ void Database::GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus) { if (oAccountName) strcpy(oAccountName, row[0]); if (oStatus) - *oStatus = atoi(row[1]); + *oStatus = Strings::ToInt(row[1]); } void Database::ClearMerchantTemp(){ @@ -1244,7 +1244,7 @@ uint8 Database::GetServerType() { return 0; auto row = results.begin(); - return atoi(row[0]); + return Strings::ToInt(row[0]); } bool Database::MoveCharacterToZone(uint32 character_id, uint32 zone_id) @@ -1281,44 +1281,6 @@ bool Database::MoveCharacterToZone(const char *charname, uint32 zone_id) return results.RowsAffected() != 0; } -bool Database::SetHackerFlag(const char* accountname, const char* charactername, const char* hacked) { - std::string query = StringFormat("INSERT INTO `hackers` (account, name, hacked) values('%s','%s','%s')", accountname, charactername, hacked); - auto results = QueryDatabase(query); - - if (!results.Success()) { - return false; - } - - return results.RowsAffected() != 0; -} - -bool Database::SetMQDetectionFlag(const char* accountname, const char* charactername, const char* hacked, const char* zone) { - //Utilize the "hacker" table, but also give zone information. - std::string query = StringFormat("INSERT INTO hackers(account,name,hacked,zone) values('%s','%s','%s','%s')", accountname, charactername, hacked, zone); - auto results = QueryDatabase(query); - - if (!results.Success()) - { - return false; - } - - return results.RowsAffected() != 0; -} - -bool Database::SetMQDetectionFlag(const char* accountname, const char* charactername, const std::string &hacked, const char* zone) { - //Utilize the "hacker" table, but also give zone information. - auto query = fmt::format("INSERT INTO hackers(account, name, hacked, zone) values('{}', '{}', '{}', '{}')", - accountname, charactername, hacked, zone); - auto results = QueryDatabase(query); - - if (!results.Success()) - { - return false; - } - - return results.RowsAffected() != 0; -} - uint8 Database::GetRaceSkill(uint8 skillid, uint8 in_race) { uint16 race_cap = 0; @@ -1334,7 +1296,7 @@ uint8 Database::GetRaceSkill(uint8 skillid, uint8 in_race) return 0; auto row = results.begin(); - return atoi(row[0]); + return Strings::ToInt(row[0]); } uint8 Database::GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 in_level) @@ -1350,12 +1312,12 @@ uint8 Database::GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 if (results.Success() && results.RowsAffected() != 0) { auto row = results.begin(); - skill_level = atoi(row[0]); - skill_formula = atoi(row[1]); - skill_cap = atoi(row[2]); - if (atoi(row[3]) > skill_cap) - skill_cap2 = (atoi(row[3])-skill_cap)/10; //Split the post-50 skill cap into difference between pre-50 cap and post-50 cap / 10 to determine amount of points per level. - skill_cap3 = atoi(row[4]); + skill_level = Strings::ToInt(row[0]); + skill_formula = Strings::ToInt(row[1]); + skill_cap = Strings::ToInt(row[2]); + if (Strings::ToInt(row[3]) > skill_cap) + skill_cap2 = (Strings::ToInt(row[3])-skill_cap)/10; //Split the post-50 skill cap into difference between pre-50 cap and post-50 cap / 10 to determine amount of points per level. + skill_cap3 = Strings::ToInt(row[4]); } int race_skill = GetRaceSkill(skillid,in_race); @@ -1400,10 +1362,10 @@ uint32 Database::GetCharacterInfo(std::string character_name, uint32 *account_id } auto row = results.begin(); - auto character_id = std::stoul(row[0]); - *account_id = std::stoul(row[1]); - *zone_id = std::stoul(row[2]); - *instance_id = std::stoul(row[3]); + auto character_id = Strings::ToUnsignedInt(row[0]); + *account_id = Strings::ToUnsignedInt(row[1]); + *zone_id = Strings::ToUnsignedInt(row[2]); + *instance_id = Strings::ToUnsignedInt(row[3]); return character_id; } @@ -1526,7 +1488,7 @@ uint32 Database::GetGroupID(const char* name){ auto row = results.begin(); - return atoi(row[0]); + return Strings::ToInt(row[0]); } std::string Database::GetGroupLeaderForLogin(std::string character_name) { @@ -1540,7 +1502,7 @@ std::string Database::GetGroupLeaderForLogin(std::string character_name) { if (results.Success() && results.RowCount()) { auto row = results.begin(); - group_id = std::stoul(row[0]); + group_id = Strings::ToUnsignedInt(row[0]); } if (!group_id) { @@ -1629,7 +1591,7 @@ char *Database::GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* mainta strcpy(mentoree, row[5]); if (mentor_percent) - *mentor_percent = atoi(row[6]); + *mentor_percent = Strings::ToInt(row[6]); if(GLAA && results.LengthOfColumn(7) == sizeof(GroupLeadershipAA_Struct)) memcpy(GLAA, row[7], sizeof(GroupLeadershipAA_Struct)); @@ -1676,7 +1638,7 @@ uint8 Database::GetAgreementFlag(uint32 acctid) { auto row = results.begin(); - return atoi(row[0]); + return Strings::ToInt(row[0]); } void Database::SetAgreementFlag(uint32 acctid) { @@ -1762,7 +1724,7 @@ uint32 Database::GetRaidID(const char* name) } if (row[0]) // would it ever be possible to have a null here? - return atoi(row[0]); + return Strings::ToInt(row[0]); return 0; } @@ -1845,7 +1807,7 @@ void Database::GetGroupLeadershipInfo(uint32 gid, uint32 rid, char *maintank, strcpy(mentoree, row[4]); if (mentor_percent) - *mentor_percent = atoi(row[5]); + *mentor_percent = Strings::ToInt(row[5]); if (GLAA && results.LengthOfColumn(6) == sizeof(GroupLeadershipAA_Struct)) memcpy(GLAA, row[6], sizeof(GroupLeadershipAA_Struct)); @@ -2018,16 +1980,16 @@ bool Database::GetAdventureStats(uint32 char_id, AdventureStats_Struct *as) auto row = results.begin(); - as->success.guk = atoi(row[0]); - as->success.mir = atoi(row[1]); - as->success.mmc = atoi(row[2]); - as->success.ruj = atoi(row[3]); - as->success.tak = atoi(row[4]); - as->failure.guk = atoi(row[5]); - as->failure.mir = atoi(row[6]); - as->failure.mmc = atoi(row[7]); - as->failure.ruj = atoi(row[8]); - as->failure.tak = atoi(row[9]); + as->success.guk = Strings::ToInt(row[0]); + as->success.mir = Strings::ToInt(row[1]); + as->success.mmc = Strings::ToInt(row[2]); + as->success.ruj = Strings::ToInt(row[3]); + as->success.tak = Strings::ToInt(row[4]); + as->failure.guk = Strings::ToInt(row[5]); + as->failure.mir = Strings::ToInt(row[6]); + as->failure.mmc = Strings::ToInt(row[7]); + as->failure.ruj = Strings::ToInt(row[8]); + as->failure.tak = Strings::ToInt(row[9]); as->failure.total = as->failure.guk + as->failure.mir + as->failure.mmc + as->failure.ruj + as->failure.tak; as->success.total = as->success.guk + as->success.mir + as->success.mmc + as->success.ruj + as->success.tak; @@ -2046,7 +2008,7 @@ uint32 Database::GetGuildIDByCharID(uint32 character_id) return 0; auto row = results.begin(); - return atoi(row[0]); + return Strings::ToInt(row[0]); } uint32 Database::GetGroupIDByCharID(uint32 character_id) @@ -2068,7 +2030,7 @@ uint32 Database::GetGroupIDByCharID(uint32 character_id) return 0; auto row = results.begin(); - return atoi(row[0]); + return Strings::ToInt(row[0]); } uint32 Database::GetRaidIDByCharID(uint32 character_id) { @@ -2082,7 +2044,7 @@ uint32 Database::GetRaidIDByCharID(uint32 character_id) { ); auto results = QueryDatabase(query); for (auto row = results.begin(); row != results.end(); ++row) { - return atoi(row[0]); + return Strings::ToInt(row[0]); } return 0; } @@ -2096,7 +2058,7 @@ int Database::CountInvSnapshots() { auto row = results.begin(); - int64 count = atoll(row[0]); + int64 count = Strings::ToBigInt(row[0]); if (count > 2147483647) return -2; if (count < 0) @@ -2132,12 +2094,12 @@ struct TimeOfDay_Struct Database::LoadTime(time_t &realtime) else{ auto row = results.begin(); - eqTime.minute = atoi(row[0]); - eqTime.hour = atoi(row[1]); - eqTime.day = atoi(row[2]); - eqTime.month = atoi(row[3]); - eqTime.year = atoi(row[4]); - realtime = atoi(row[5]); + eqTime.minute = Strings::ToInt(row[0]); + eqTime.hour = Strings::ToInt(row[1]); + eqTime.day = Strings::ToInt(row[2]); + eqTime.month = Strings::ToInt(row[3]); + eqTime.year = Strings::ToInt(row[4]); + realtime = Strings::ToInt(row[5]); } return eqTime; @@ -2164,7 +2126,7 @@ int Database::GetIPExemption(std::string account_ip) { } auto row = results.begin(); - return std::stoi(row[0]); + return Strings::ToInt(row[0]); } void Database::SetIPExemption(std::string account_ip, int exemption_amount) { @@ -2178,7 +2140,7 @@ void Database::SetIPExemption(std::string account_ip, int exemption_amount) { auto results = QueryDatabase(query); if (results.Success() && results.RowCount()) { auto row = results.begin(); - exemption_id = std::stoul(row[0]); + exemption_id = Strings::ToUnsignedInt(row[0]); } query = fmt::format( @@ -2204,7 +2166,7 @@ int Database::GetInstanceID(uint32 char_id, uint32 zone_id) { if (results.Success() && results.RowCount() > 0) { auto row = results.begin(); - return atoi(row[0]);; + return Strings::ToInt(row[0]);; } return 0; diff --git a/common/database.h b/common/database.h index 33ec0e474..10120c109 100644 --- a/common/database.h +++ b/common/database.h @@ -34,8 +34,6 @@ #include #include -//atoi is not uint32 or uint32 safe!!!! -#define atoul(str) strtoul(str, nullptr, 10) class MySQLRequestResult; class Client; @@ -108,9 +106,6 @@ public: bool MoveCharacterToZone(uint32 character_id, uint32 zone_id); bool ReserveName(uint32 account_id, char *name); bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct *pp); - bool SetHackerFlag(const char *accountname, const char *charactername, const char *hacked); - bool SetMQDetectionFlag(const char *accountname, const char *charactername, const char *hacked, const char *zone); - bool SetMQDetectionFlag(const char *accountname, const char *charactername, const std::string &hacked, const char *zone); bool UpdateName(const char *oldname, const char *newname); bool CopyCharacter( const std::string& source_character_name, diff --git a/common/database_conversions.cpp b/common/database_conversions.cpp index e52786b0b..bcb987107 100644 --- a/common/database_conversions.cpp +++ b/common/database_conversions.cpp @@ -476,10 +476,11 @@ bool Database::CheckDatabaseConversions() { CheckDatabaseConvertPPDeblob(); CheckDatabaseConvertCorpseDeblob(); - RuleManager::Instance()->LoadRules(this, "default", false); + auto *r = RuleManager::Instance(); + r->LoadRules(this, "default", false); if (!RuleB(Bots, Enabled) && DoesTableExist("bot_data")) { LogInfo("Bot tables found but rule not enabled, enabling"); - RuleManager::Instance()->SetRule("Bots:Enabled", "true", this, true, true); + r->SetRule("Bots:Enabled", "true", this, true, true); } /* Run EQEmu Server script (Checks for database updates) */ @@ -529,7 +530,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){ rquery = StringFormat("SELECT COUNT(`id`) FROM `character_`"); results = QueryDatabase(rquery); for (auto row = results.begin(); row != results.end(); ++row) { - number_of_characters = atoi(row[0]); + number_of_characters = Strings::ToInt(row[0]); printf("Number of Characters in Database: %i \n", number_of_characters); } @@ -928,19 +929,19 @@ bool Database::CheckDatabaseConvertPPDeblob(){ for (auto row = results.begin(); row != results.end(); ++row) { char_iter_count++; - squery = StringFormat("SELECT `id`, `profile`, `name`, `level`, `account_id`, `firstlogon`, `lfg`, `lfp`, `mailkey`, `xtargets`, `inspectmessage`, `extprofile` FROM `character_` WHERE `id` = %i", atoi(row[0])); + squery = StringFormat("SELECT `id`, `profile`, `name`, `level`, `account_id`, `firstlogon`, `lfg`, `lfp`, `mailkey`, `xtargets`, `inspectmessage`, `extprofile` FROM `character_` WHERE `id` = %i", Strings::ToInt(row[0])); auto results2 = QueryDatabase(squery); auto row2 = results2.begin(); pp = (Convert::PlayerProfile_Struct*)row2[1]; e_pp = (ExtendedProfile_Struct*)row2[11]; - character_id = atoi(row[0]); - account_id = atoi(row2[4]); + character_id = Strings::ToInt(row[0]); + account_id = Strings::ToInt(row2[4]); /* Convert some data from the character_ table that is still relevant */ - firstlogon = atoi(row2[5]); - lfg = atoi(row2[6]); - lfp = atoi(row2[7]); + firstlogon = Strings::ToInt(row2[5]); + lfg = Strings::ToInt(row2[6]); + lfp = Strings::ToInt(row2[7]); mailkey = row2[8]; - xtargets = atoi(row2[9]); + xtargets = Strings::ToInt(row2[9]); inspectmessage = row2[10]; /* Verify PP Integrity */ @@ -1566,7 +1567,7 @@ bool Database::CheckDatabaseConvertCorpseDeblob(){ rquery = StringFormat("SELECT DISTINCT charid FROM character_corpses"); results = QueryDatabase(rquery); for (auto row = results.begin(); row != results.end(); ++row) { - std::string squery = StringFormat("SELECT id, charname, data, time_of_death, is_rezzed FROM character_corpses WHERE `charid` = %i", atoi(row[0])); + std::string squery = StringFormat("SELECT id, charname, data, time_of_death, is_rezzed FROM character_corpses WHERE `charid` = %i", Strings::ToInt(row[0])); auto results2 = QueryDatabase(squery); for (auto row2 = results2.begin(); row2 != results2.end(); ++row2) { in_datasize = results2.LengthOfColumn(2); @@ -1598,7 +1599,7 @@ bool Database::CheckDatabaseConvertCorpseDeblob(){ c_type = "NULL"; continue; } - std::cout << "Converting Corpse: [OK] [" << c_type << "]: " << "ID: " << atoi(row2[0]) << std::endl; + std::cout << "Converting Corpse: [OK] [" << c_type << "]: " << "ID: " << Strings::ToInt(row2[0]) << std::endl; if (is_sof){ scquery = StringFormat("UPDATE `character_corpses` SET \n" @@ -1669,7 +1670,7 @@ bool Database::CheckDatabaseConvertCorpseDeblob(){ dbpc->item_tint[6].color, dbpc->item_tint[7].color, dbpc->item_tint[8].color, - atoi(row2[0]) + Strings::ToInt(row2[0]) ); if (scquery != ""){ auto sc_results = QueryDatabase(scquery); } @@ -1681,7 +1682,7 @@ bool Database::CheckDatabaseConvertCorpseDeblob(){ scquery = StringFormat("REPLACE INTO `character_corpse_items` \n" " (corpse_id, equip_slot, item_id, charges, aug_1, aug_2, aug_3, aug_4, aug_5, aug_6, attuned) \n" " VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n", - atoi(row2[0]), + Strings::ToInt(row2[0]), dbpc->items[i].equipSlot, dbpc->items[i].item_id, dbpc->items[i].charges, @@ -1697,7 +1698,7 @@ bool Database::CheckDatabaseConvertCorpseDeblob(){ } else{ scquery = scquery + StringFormat(", (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n", - atoi(row2[0]), + Strings::ToInt(row2[0]), dbpc->items[i].equipSlot, dbpc->items[i].item_id, dbpc->items[i].charges, @@ -1777,7 +1778,7 @@ bool Database::CheckDatabaseConvertCorpseDeblob(){ dbpc_c->item_tint[6].color, dbpc_c->item_tint[7].color, dbpc_c->item_tint[8].color, - atoi(row2[0]) + Strings::ToInt(row2[0]) ); if (scquery != ""){ auto sc_results = QueryDatabase(scquery); } @@ -1790,7 +1791,7 @@ bool Database::CheckDatabaseConvertCorpseDeblob(){ scquery = StringFormat("REPLACE INTO `character_corpse_items` \n" " (corpse_id, equip_slot, item_id, charges, aug_1, aug_2, aug_3, aug_4, aug_5, aug_6, attuned) \n" " VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n", - atoi(row2[0]), + Strings::ToInt(row2[0]), dbpc_c->items[i].equipSlot, dbpc_c->items[i].item_id, dbpc_c->items[i].charges, @@ -1806,7 +1807,7 @@ bool Database::CheckDatabaseConvertCorpseDeblob(){ } else{ scquery = scquery + StringFormat(", (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n", - atoi(row2[0]), + Strings::ToInt(row2[0]), dbpc_c->items[i].equipSlot, dbpc_c->items[i].item_id, dbpc_c->items[i].charges, diff --git a/common/database_instances.cpp b/common/database_instances.cpp index 27945a4aa..36e6a7893 100644 --- a/common/database_instances.cpp +++ b/common/database_instances.cpp @@ -167,8 +167,8 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id) auto row = results.begin(); - if (atoi(row[0]) <= max) { - instance_id = atoi(row[0]); + if (Strings::ToInt(row[0]) <= max) { + instance_id = Strings::ToInt(row[0]); return true; } @@ -194,7 +194,7 @@ bool Database::GetUnusedInstanceID(uint16 &instance_id) max_reserved_instance_id++; for (auto row : results) { - if (max_reserved_instance_id < std::stoul(row[0])) { + if (max_reserved_instance_id < Strings::ToUnsignedInt(row[0])) { instance_id = max_reserved_instance_id; return true; } @@ -301,7 +301,7 @@ uint16 Database::GetInstanceID(uint32 zone_id, uint32 character_id, int16 versio auto row = results.begin(); - return static_cast(std::stoul(row[0])); + return static_cast(Strings::ToUnsignedInt(row[0])); } std::vector Database::GetInstanceIDs(uint32 zone_id, uint32 character_id) @@ -328,7 +328,7 @@ std::vector Database::GetInstanceIDs(uint32 zone_id, uint32 character_id } for (auto row : results) { - l.push_back(static_cast(std::stoul(row[0]))); + l.push_back(static_cast(Strings::ToUnsignedInt(row[0]))); } return l; @@ -409,7 +409,7 @@ void Database::AssignRaidToInstance(uint32 raid_id, uint32 instance_id) auto zone_id = GetInstanceZoneID(instance_id); auto version = GetInstanceVersion(instance_id); - auto l = GroupIdRepository::GetWhere( + auto l = RaidMembersRepository::GetWhere( *this, fmt::format( "raidid = {}", diff --git a/common/database_schema.h b/common/database_schema.h index af88774be..3f6e7434e 100644 --- a/common/database_schema.h +++ b/common/database_schema.h @@ -321,13 +321,11 @@ namespace DatabaseSchema { "discord_webhooks", "dynamic_zone_members", "dynamic_zones", - "eventlog", "expedition_lockouts", "expeditions", "gm_ips", "group_id", "group_leaders", - "hackers", "instance_list", "ip_exemptions", "item_tick", @@ -343,6 +341,8 @@ namespace DatabaseSchema { "respawn_times", "saylink", "server_scheduled_events", + "player_event_log_settings", + "player_event_logs", "shared_task_activity_state", "shared_task_dynamic_zones", "shared_task_members", diff --git a/common/dbcore.cpp b/common/dbcore.cpp index 3aa62c402..9b9108f0c 100644 --- a/common/dbcore.cpp +++ b/common/dbcore.cpp @@ -34,14 +34,16 @@ DBcore::DBcore() { - mysql_init(&mysql); - pHost = nullptr; - pUser = nullptr; - pPassword = nullptr; - pDatabase = nullptr; - pCompress = false; - pSSL = false; - pStatus = Closed; + mysql = mysql_init(nullptr); + mysqlOwner = true; + pHost = nullptr; + pUser = nullptr; + pPassword = nullptr; + pDatabase = nullptr; + pCompress = false; + pSSL = false; + pStatus = Closed; + m_mutex = new Mutex; } DBcore::~DBcore() @@ -51,16 +53,10 @@ DBcore::~DBcore() * are re-using the default database connection pointer when we dont have an * external configuration setup ex: (content_database) */ - std::string mysql_connection_host; - if (mysql.host) { - mysql_connection_host = mysql.host; + if (mysqlOwner) { + mysql_close(mysql); } - if (GetOriginHost() != mysql_connection_host) { - return; - } - - mysql_close(&mysql); safe_delete_array(pHost); safe_delete_array(pUser); safe_delete_array(pPassword); @@ -70,17 +66,18 @@ DBcore::~DBcore() // Sends the MySQL server a keepalive void DBcore::ping() { - if (!MDatabase.trylock()) { + if (!m_mutex->trylock()) { // well, if's it's locked, someone's using it. If someone's using it, it doesnt need a keepalive return; } - mysql_ping(&mysql); - MDatabase.unlock(); + mysql_ping(mysql); + m_mutex->unlock(); } MySQLRequestResult DBcore::QueryDatabase(std::string query, bool retryOnFailureOnce) { - return QueryDatabase(query.c_str(), query.length(), retryOnFailureOnce); + auto r = QueryDatabase(query.c_str(), query.length(), retryOnFailureOnce); + return r; } bool DBcore::DoesTableExist(std::string table_name) @@ -95,18 +92,16 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo BenchTimer timer; timer.reset(); - LockMutex lock(&MDatabase); + LockMutex lock(m_mutex); // Reconnect if we are not connected before hand. if (pStatus != Connected) { Open(); } - - // request query. != 0 indicates some kind of error. - if (mysql_real_query(&mysql, query, querylen) != 0) { - unsigned int errorNumber = mysql_errno(&mysql); + if (mysql_real_query(mysql, query, querylen) != 0) { + unsigned int errorNumber = mysql_errno(mysql); if (errorNumber == CR_SERVER_GONE_ERROR) { pStatus = Error; @@ -130,26 +125,26 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo auto errorBuffer = new char[MYSQL_ERRMSG_SIZE]; - snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql)); + snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(mysql), mysql_error(mysql)); - return MySQLRequestResult(nullptr, 0, 0, 0, 0, (uint32) mysql_errno(&mysql), errorBuffer); + return MySQLRequestResult(nullptr, 0, 0, 0, 0, (uint32) mysql_errno(mysql), errorBuffer); } auto errorBuffer = new char[MYSQL_ERRMSG_SIZE]; - snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql)); + snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(mysql), mysql_error(mysql)); /** * Error logging */ - if (mysql_errno(&mysql) > 0 && strlen(query) > 0) { - LogMySQLError("[{}] [{}]\n[{}]", mysql_errno(&mysql), mysql_error(&mysql), query); + if (mysql_errno(mysql) > 0 && strlen(query) > 0) { + LogMySQLError("[{}] [{}]\n[{}]", mysql_errno(mysql), mysql_error(mysql), query); } - return MySQLRequestResult(nullptr, 0, 0, 0, 0, mysql_errno(&mysql), errorBuffer); + return MySQLRequestResult(nullptr, 0, 0, 0, 0, mysql_errno(mysql), errorBuffer); } // successful query. get results. - MYSQL_RES *res = mysql_store_result(&mysql); + MYSQL_RES *res = mysql_store_result(mysql); uint32 rowCount = 0; if (res != nullptr) { @@ -158,10 +153,10 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo MySQLRequestResult requestResult( res, - (uint32) mysql_affected_rows(&mysql), + (uint32) mysql_affected_rows(mysql), rowCount, - (uint32) mysql_field_count(&mysql), - (uint32) mysql_insert_id(&mysql) + (uint32) mysql_field_count(mysql), + (uint32) mysql_insert_id(mysql) ); if (LogSys.log_settings[Logs::MySQLQuery].is_category_enabled == 1) { @@ -207,7 +202,7 @@ uint32 DBcore::DoEscapeString(char *tobuf, const char *frombuf, uint32 fromlen) { // No good reason to lock the DB, we only need it in the first place to check char encoding. // LockMutex lock(&MDatabase); - return mysql_real_escape_string(&mysql, tobuf, frombuf, fromlen); + return mysql_real_escape_string(mysql, tobuf, frombuf, fromlen); } bool DBcore::Open( @@ -222,7 +217,7 @@ bool DBcore::Open( bool iSSL ) { - LockMutex lock(&MDatabase); + LockMutex lock(m_mutex); safe_delete_array(pHost); safe_delete_array(pUser); safe_delete_array(pPassword); @@ -242,13 +237,13 @@ bool DBcore::Open(uint32 *errnum, char *errbuf) if (errbuf) { errbuf[0] = 0; } - LockMutex lock(&MDatabase); + LockMutex lock(m_mutex); if (GetStatus() == Connected) { return true; } if (GetStatus() == Error) { - mysql_close(&mysql); - mysql_init(&mysql); // Initialize structure again + mysql_close(mysql); + mysql_init(mysql); // Initialize structure again } if (!pHost) { return false; @@ -265,7 +260,7 @@ bool DBcore::Open(uint32 *errnum, char *errbuf) if (pSSL) { flags |= CLIENT_SSL; } - if (mysql_real_connect(&mysql, pHost, pUser, pPassword, pDatabase, pPort, 0, flags)) { + if (mysql_real_connect(mysql, pHost, pUser, pPassword, pDatabase, pPort, 0, flags)) { pStatus = Connected; std::string connected_origin_host = pHost; @@ -275,21 +270,16 @@ bool DBcore::Open(uint32 *errnum, char *errbuf) } else { if (errnum) { - *errnum = mysql_errno(&mysql); + *errnum = mysql_errno(mysql); } if (errbuf) { - snprintf(errbuf, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql)); + snprintf(errbuf, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(mysql), mysql_error(mysql)); } pStatus = Error; return false; } } -void DBcore::SetMysql(MYSQL *mysql) -{ - DBcore::mysql = *mysql; -} - const std::string &DBcore::GetOriginHost() const { return origin_host; @@ -299,3 +289,19 @@ void DBcore::SetOriginHost(const std::string &origin_host) { DBcore::origin_host = origin_host; } + +std::string DBcore::Escape(const std::string& s) +{ + const std::size_t s_len = s.length(); + std::vector temp((s_len * 2) + 1, '\0'); + mysql_real_escape_string(mysql, temp.data(), s.c_str(), s_len); + + return temp.data(); +} + +void DBcore::SetMutex(Mutex *mutex) +{ + safe_delete(m_mutex); + + DBcore::m_mutex = mutex; +} diff --git a/common/dbcore.h b/common/dbcore.h index 8e8e6b46b..c1e28bb42 100644 --- a/common/dbcore.h +++ b/common/dbcore.h @@ -12,6 +12,7 @@ #include #include +#include class DBcore { public: @@ -27,16 +28,22 @@ public: void TransactionBegin(); void TransactionCommit(); void TransactionRollback(); + std::string Escape(const std::string& s); uint32 DoEscapeString(char *tobuf, const char *frombuf, uint32 fromlen); void ping(); - MYSQL *getMySQL() { return &mysql; } - void SetMysql(MYSQL *mysql); const std::string &GetOriginHost() const; void SetOriginHost(const std::string &origin_host); bool DoesTableExist(std::string table_name); + void SetMySQL(const DBcore &o) + { + mysql = o.mysql; + mysqlOwner = false; + } + void SetMutex(Mutex *mutex); + protected: bool Open( const char *iHost, @@ -53,10 +60,13 @@ protected: private: bool Open(uint32 *errnum = nullptr, char *errbuf = nullptr); - MYSQL mysql; - Mutex MDatabase; + MYSQL* mysql; + bool mysqlOwner; + Mutex *m_mutex; eStatus pStatus; + std::mutex m_query_lock{}; + std::string origin_host; char *pHost; diff --git a/common/discord/discord.cpp b/common/discord/discord.cpp index 294f51c65..e06311035 100644 --- a/common/discord/discord.cpp +++ b/common/discord/discord.cpp @@ -1,22 +1,17 @@ +#include +#include #include "discord.h" #include "../http/httplib.h" #include "../json/json.h" #include "../strings.h" #include "../eqemu_logsys.h" +#include "../events/player_event_logs.h" constexpr int MAX_RETRIES = 10; void Discord::SendWebhookMessage(const std::string &message, const std::string &webhook_url) { - // validate - if (webhook_url.empty()) { - LogDiscord("[webhook_url] is empty"); - return; - } - - // validate - if (webhook_url.find("http://") == std::string::npos && webhook_url.find("https://") == std::string::npos) { - LogDiscord("[webhook_url] [{}] does not contain a valid http/s prefix.", webhook_url); + if (!ValidateWebhookUrl(webhook_url)) { return; } @@ -28,7 +23,7 @@ void Discord::SendWebhookMessage(const std::string &message, const std::string & std::string endpoint = Strings::Replace(webhook_url, base_url, ""); // client - httplib::Client cli(base_url.c_str()); + httplib::Client cli(base_url); cli.set_connection_timeout(0, 15000000); // 15 sec cli.set_read_timeout(15, 0); // 15 seconds cli.set_write_timeout(15, 0); // 15 seconds @@ -46,9 +41,9 @@ void Discord::SendWebhookMessage(const std::string &message, const std::string & int retries = 0; int retry_timer = 1000; while (retry) { - if (auto res = cli.Post(endpoint.c_str(), payload.str(), "application/json")) { + if (auto res = cli.Post(endpoint, payload.str(), "application/json")) { if (res->status != 200 && res->status != 204) { - LogError("Code [{}] Error [{}]", res->status, res->body); + LogError("[Discord Client] Code [{}] Error [{}]", res->status, res->body); } if (res->status == 429) { if (!res->body.empty()) { @@ -62,7 +57,7 @@ void Discord::SendWebhookMessage(const std::string &message, const std::string & LogDiscord("JSON serialization failure [{}] via [{}]", ex.what(), res->body); } - retry_timer = std::stoi(response["retry_after"].asString()) + 500; + retry_timer = Strings::ToInt(response["retry_after"].asString()) + 500; } LogDiscord("Rate limited... retrying message in [{}ms]", retry_timer); @@ -81,6 +76,74 @@ void Discord::SendWebhookMessage(const std::string &message, const std::string & } } +void Discord::SendPlayerEventMessage( + const PlayerEvent::PlayerEventContainer &e, + const std::string &webhook_url +) +{ + if (!ValidateWebhookUrl(webhook_url)) { + return; + } + + auto s = Strings::Split(webhook_url, '/'); + + // url + std::string base_url = fmt::format("{}//{}", s[0], s[2]); + std::string endpoint = Strings::Replace(webhook_url, base_url, ""); + + // client + httplib::Client cli(base_url); + cli.set_connection_timeout(0, 15000000); // 15 sec + cli.set_read_timeout(15, 0); // 15 seconds + cli.set_write_timeout(15, 0); // 15 seconds + httplib::Headers headers = { + {"Content-Type", "application/json"} + }; + + std::string payload = PlayerEventLogs::GetDiscordPayloadFromEvent(e); + if (payload.empty()) { + return; + } + + bool retry = true; + int retries = 0; + int retry_timer = 1000; + while (retry) { + if (auto res = cli.Post(endpoint, payload, "application/json")) { + if (res->status != 200 && res->status != 204) { + LogError("Code [{}] Error [{}]", res->status, res->body); + } + if (res->status == 429) { + if (!res->body.empty()) { + std::stringstream ss(res->body); + Json::Value response; + + try { + ss >> response; + } + catch (std::exception const &ex) { + LogDiscord("JSON serialization failure [{}] via [{}]", ex.what(), res->body); + } + + retry_timer = Strings::ToInt(response["retry_after"].asString()) + 500; + } + + LogDiscord("Rate limited... retrying message in [{}ms]", retry_timer); + std::this_thread::sleep_for(std::chrono::milliseconds(retry_timer + 500)); + } + if (res->status == 204) { + retry = false; + } + if (retries > MAX_RETRIES) { + LogDiscord("Retries exceeded for player event message"); + retry = false; + } + + retries++; + } + } +} + std::string Discord::FormatDiscordMessage(uint16 category_id, const std::string &message) { if (category_id == Logs::LogCategory::MySQLQuery) { @@ -89,3 +152,20 @@ std::string Discord::FormatDiscordMessage(uint16 category_id, const std::string return message + "\n"; } + +bool Discord::ValidateWebhookUrl(const std::string &webhook_url) +{ + // validate + if (webhook_url.empty()) { + LogDiscord("[webhook_url] is empty"); + return false; + } + + // validate + if (!Strings::Contains(webhook_url, "http://") && !Strings::Contains(webhook_url, "https://")) { + LogDiscord("[webhook_url] [{}] does not contain a valid http/s prefix.", webhook_url); + return false; + } + + return true; +} diff --git a/common/discord/discord.h b/common/discord/discord.h index d4ebc73f1..5cc59202a 100644 --- a/common/discord/discord.h +++ b/common/discord/discord.h @@ -4,11 +4,16 @@ #include #include "../types.h" +#include "../http/httplib.h" +#include "../repositories/player_event_logs_repository.h" +#include "../events/player_events.h" class Discord { public: static void SendWebhookMessage(const std::string& message, const std::string& webhook_url); static std::string FormatDiscordMessage(uint16 category_id, const std::string& message); + static void SendPlayerEventMessage(const PlayerEvent::PlayerEventContainer& e, const std::string &webhook_url); + static bool ValidateWebhookUrl(const std::string &webhook_url); }; diff --git a/common/discord_manager.cpp b/common/discord/discord_manager.cpp similarity index 83% rename from common/discord_manager.cpp rename to common/discord/discord_manager.cpp index aac1dadcc..e8691e763 100644 --- a/common/discord_manager.cpp +++ b/common/discord/discord_manager.cpp @@ -1,7 +1,6 @@ #include "discord_manager.h" -#include "../common/discord/discord.h" -#include "../common/eqemu_logsys.h" -#include "../common/strings.h" +#include "../../common/discord/discord.h" +#include "../events/player_event_logs.h" void DiscordManager::QueueWebhookMessage(uint32 webhook_id, const std::string &message) { @@ -55,7 +54,6 @@ void DiscordManager::ProcessMessageQueue() message = ""; } } - // final flush if (!message.empty()) { Discord::SendWebhookMessage( @@ -67,3 +65,11 @@ void DiscordManager::ProcessMessageQueue() webhook_message_queue.clear(); webhook_queue_lock.unlock(); } + +void DiscordManager::QueuePlayerEventMessage(const PlayerEvent::PlayerEventContainer& e) +{ + auto w = player_event_logs.GetDiscordWebhookUrlFromEventType(e.player_event_log.event_type_id); + if (!w.empty()) { + Discord::SendPlayerEventMessage(e, w); + } +} diff --git a/common/discord_manager.h b/common/discord/discord_manager.h similarity index 64% rename from common/discord_manager.h rename to common/discord/discord_manager.h index cc3573630..f577d994f 100644 --- a/common/discord_manager.h +++ b/common/discord/discord_manager.h @@ -4,12 +4,15 @@ #include #include #include -#include "../common/types.h" +#include "../../common/types.h" +#include "../repositories/player_event_logs_repository.h" +#include "../events/player_events.h" class DiscordManager { public: void QueueWebhookMessage(uint32 webhook_id, const std::string& message); void ProcessMessageQueue(); + void QueuePlayerEventMessage(const PlayerEvent::PlayerEventContainer& e); private: std::mutex webhook_queue_lock{}; std::map> webhook_message_queue{}; diff --git a/common/eq_constants.h b/common/eq_constants.h index ce65ab59b..ae2cce84b 100644 --- a/common/eq_constants.h +++ b/common/eq_constants.h @@ -79,6 +79,8 @@ #define ANIM_DEATH 0x73 #define ANIM_LOOT 0x69 +constexpr int16 RECAST_TYPE_UNLINKED_ITEM = -1; + typedef enum { eaStanding = 0, eaSitting, //1 @@ -1015,15 +1017,32 @@ enum Anonymity : uint8 Roleplaying }; -enum ZoningMessage : int8 -{ - ZoneNoMessage = 0, - ZoneSuccess = 1, - ZoneNotReady = -1, - ZoneValidPC = -2, - ZoneStoryZone = -3, - ZoneNoExpansion = -6, +enum ZoningMessage : int8 { + ZoneNoMessage = 0, + ZoneSuccess = 1, + ZoneNotReady = -1, + ZoneValidPC = -2, + ZoneStoryZone = -3, + ZoneNoExpansion = -6, ZoneNoExperience = -7 }; +enum class RecipeCountType : uint8 +{ + Component, + Container, + Fail, + Salvage, + Success +}; + +#define ALT_CURRENCY_ID_RADIANT 4 +#define ALT_CURRENCY_ID_EBON 5 + +enum ResurrectionActions +{ + Decline, + Accept +}; + #endif /*COMMON_EQ_CONSTANTS_H*/ diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 979c8b86e..cd26fe79a 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -29,7 +29,7 @@ #include "textures.h" -static const uint32 BUFF_COUNT = 25; +static const uint32 BUFF_COUNT = 42; static const uint32 PET_BUFF_COUNT = 30; static const uint32 MAX_MERC = 100; static const uint32 MAX_MERC_GRADES = 10; @@ -3632,17 +3632,19 @@ struct LevelAppearance_Struct { //Sends a little graphic on level up }; struct MerchantList { - uint32 id; - uint32 slot; - uint32 item; - int16 faction_required; - int8 level_required; - uint16 alt_currency_cost; - uint32 classes_required; - uint8 probability; + uint32 id; + uint32 slot; + uint32 item; + int16 faction_required; + int8 level_required; + uint8 min_status; + uint8 max_status; + uint16 alt_currency_cost; + uint32 classes_required; + uint8 probability; std::string bucket_name; std::string bucket_value; - uint8 bucket_comparison; + uint8 bucket_comparison; }; struct TempMerchantList { @@ -4545,7 +4547,7 @@ struct ItemVerifyReply_Struct { struct ItemRecastDelay_Struct { /*000*/ uint32 recast_delay; // in seconds /*004*/ uint32 recast_type; -/*008*/ uint32 unknown008; +/*008*/ bool ignore_casting_requirement; //Ignores recast times allows items to be reset? /*012*/ }; diff --git a/common/eqemu_config.cpp b/common/eqemu_config.cpp index 85161ba8a..b258be2e3 100644 --- a/common/eqemu_config.cpp +++ b/common/eqemu_config.cpp @@ -19,6 +19,7 @@ #include "../common/global_define.h" #include "eqemu_config.h" #include "misc_functions.h" +#include "strings.h" #include #include @@ -33,13 +34,13 @@ void EQEmuConfig::parse_config() LongName = _root["server"]["world"].get("longname", "").asString(); WorldAddress = _root["server"]["world"].get("address", "").asString(); LocalAddress = _root["server"]["world"].get("localaddress", "").asString(); - MaxClients = atoi(_root["server"]["world"].get("maxclients", "-1").asString().c_str()); + MaxClients = Strings::ToInt(_root["server"]["world"].get("maxclients", "-1").asString().c_str()); SharedKey = _root["server"]["world"].get("key", "").asString(); LoginCount = 0; if (_root["server"]["world"]["loginserver"].isObject()) { LoginHost = _root["server"]["world"]["loginserver"].get("host", "login.eqemulator.net").asString(); - LoginPort = atoi(_root["server"]["world"]["loginserver"].get("port", "5998").asString().c_str()); + LoginPort = Strings::ToInt(_root["server"]["world"]["loginserver"].get("port", "5998").asString().c_str()); LoginLegacy = false; if (_root["server"]["world"]["loginserver"].get("legacy", "0").asString() == "1") { LoginLegacy = true; } LoginAccount = _root["server"]["world"]["loginserver"].get("account", "").asString(); @@ -62,7 +63,7 @@ void EQEmuConfig::parse_config() auto loginconfig = new LoginConfig; loginconfig->LoginHost = _root["server"]["world"][str].get("host", "login.eqemulator.net").asString(); - loginconfig->LoginPort = atoi(_root["server"]["world"][str].get("port", "5998").asString().c_str()); + loginconfig->LoginPort = Strings::ToInt(_root["server"]["world"][str].get("port", "5998").asString().c_str()); loginconfig->LoginAccount = _root["server"]["world"][str].get("account", "").asString(); loginconfig->LoginPassword = _root["server"]["world"][str].get("password", "").asString(); @@ -85,15 +86,15 @@ void EQEmuConfig::parse_config() Locked = false; if (_root["server"]["world"].get("locked", "false").asString() == "true") { Locked = true; } WorldIP = _root["server"]["world"]["tcp"].get("host", "127.0.0.1").asString(); - WorldTCPPort = atoi(_root["server"]["world"]["tcp"].get("port", "9000").asString().c_str()); + WorldTCPPort = Strings::ToInt(_root["server"]["world"]["tcp"].get("port", "9000").asString().c_str()); TelnetIP = _root["server"]["world"]["telnet"].get("ip", "127.0.0.1").asString(); - TelnetTCPPort = atoi(_root["server"]["world"]["telnet"].get("port", "9001").asString().c_str()); + TelnetTCPPort = Strings::ToInt(_root["server"]["world"]["telnet"].get("port", "9001").asString().c_str()); TelnetEnabled = false; if (_root["server"]["world"]["telnet"].get("enabled", "false").asString() == "true") { TelnetEnabled = true; } WorldHTTPMimeFile = _root["server"]["world"]["http"].get("mimefile", "mime.types").asString(); - WorldHTTPPort = atoi(_root["server"]["world"]["http"].get("port", "9080").asString().c_str()); + WorldHTTPPort = Strings::ToInt(_root["server"]["world"]["http"].get("port", "9080").asString().c_str()); WorldHTTPEnabled = false; if (_root["server"]["world"]["http"].get("enabled", "false").asString() == "true") { @@ -108,9 +109,9 @@ void EQEmuConfig::parse_config() * UCS */ ChatHost = _root["server"]["chatserver"].get("host", "eqchat.eqemulator.net").asString(); - ChatPort = atoi(_root["server"]["chatserver"].get("port", "7778").asString().c_str()); + ChatPort = Strings::ToInt(_root["server"]["chatserver"].get("port", "7778").asString().c_str()); MailHost = _root["server"]["mailserver"].get("host", "eqmail.eqemulator.net").asString(); - MailPort = atoi(_root["server"]["mailserver"].get("port", "7778").asString().c_str()); + MailPort = Strings::ToInt(_root["server"]["mailserver"].get("port", "7778").asString().c_str()); /** * Database @@ -118,7 +119,7 @@ void EQEmuConfig::parse_config() DatabaseUsername = _root["server"]["database"].get("username", "eq").asString(); DatabasePassword = _root["server"]["database"].get("password", "eq").asString(); DatabaseHost = _root["server"]["database"].get("host", "localhost").asString(); - DatabasePort = atoi(_root["server"]["database"].get("port", "3306").asString().c_str()); + DatabasePort = Strings::ToInt(_root["server"]["database"].get("port", "3306").asString().c_str()); DatabaseDB = _root["server"]["database"].get("db", "eq").asString(); /** @@ -127,14 +128,14 @@ void EQEmuConfig::parse_config() ContentDbUsername = _root["server"]["content_database"].get("username", "").asString(); ContentDbPassword = _root["server"]["content_database"].get("password", "").asString(); ContentDbHost = _root["server"]["content_database"].get("host", "").asString(); - ContentDbPort = atoi(_root["server"]["content_database"].get("port", 0).asString().c_str()); + ContentDbPort = Strings::ToInt(_root["server"]["content_database"].get("port", 0).asString().c_str()); ContentDbName = _root["server"]["content_database"].get("db", "").asString(); /** * QS */ QSDatabaseHost = _root["server"]["qsdatabase"].get("host", "localhost").asString(); - QSDatabasePort = atoi(_root["server"]["qsdatabase"].get("port", "3306").asString().c_str()); + QSDatabasePort = Strings::ToInt(_root["server"]["qsdatabase"].get("port", "3306").asString().c_str()); QSDatabaseUsername = _root["server"]["qsdatabase"].get("username", "eq").asString(); QSDatabasePassword = _root["server"]["qsdatabase"].get("password", "eq").asString(); QSDatabaseDB = _root["server"]["qsdatabase"].get("db", "eq").asString(); @@ -142,9 +143,9 @@ void EQEmuConfig::parse_config() /** * Zones */ - DefaultStatus = atoi(_root["server"]["zones"].get("defaultstatus", 0).asString().c_str()); - ZonePortLow = atoi(_root["server"]["zones"]["ports"].get("low", "7000").asString().c_str()); - ZonePortHigh = atoi(_root["server"]["zones"]["ports"].get("high", "7999").asString().c_str()); + DefaultStatus = Strings::ToInt(_root["server"]["zones"].get("defaultstatus", 0).asString().c_str()); + ZonePortLow = Strings::ToInt(_root["server"]["zones"]["ports"].get("low", "7000").asString().c_str()); + ZonePortHigh = Strings::ToInt(_root["server"]["zones"]["ports"].get("high", "7999").asString().c_str()); /** * Files @@ -174,10 +175,10 @@ void EQEmuConfig::parse_config() /** * Launcher */ - RestartWait = atoi(_root["server"]["launcher"]["timers"].get("restart", "10000").asString().c_str()); - TerminateWait = atoi(_root["server"]["launcher"]["timers"].get("reterminate", "10000").asString().c_str()); - InitialBootWait = atoi(_root["server"]["launcher"]["timers"].get("initial", "20000").asString().c_str()); - ZoneBootInterval = atoi(_root["server"]["launcher"]["timers"].get("interval", "2000").asString().c_str()); + RestartWait = Strings::ToInt(_root["server"]["launcher"]["timers"].get("restart", "10000").asString().c_str()); + TerminateWait = Strings::ToInt(_root["server"]["launcher"]["timers"].get("reterminate", "10000").asString().c_str()); + InitialBootWait = Strings::ToInt(_root["server"]["launcher"]["timers"].get("initial", "20000").asString().c_str()); + ZoneBootInterval = Strings::ToInt(_root["server"]["launcher"]["timers"].get("interval", "2000").asString().c_str()); #ifdef WIN32 ZoneExe = _root["server"]["launcher"].get("exe", "zone.exe").asString(); #else diff --git a/common/eqemu_logsys.h b/common/eqemu_logsys.h index 0c8ec1ae3..bea481a29 100644 --- a/common/eqemu_logsys.h +++ b/common/eqemu_logsys.h @@ -136,6 +136,7 @@ namespace Logs { PacketServerToServer, Bugs, QuestErrors, + PlayerEvents, MaxCategoryID /* Don't Remove this */ }; @@ -230,7 +231,8 @@ namespace Logs { "Packet C->S", "Packet S->S", "Bugs", - "QuestErrors" + "QuestErrors", + "PlayerEvents", }; } diff --git a/common/eqemu_logsys_log_aliases.h b/common/eqemu_logsys_log_aliases.h index 4db8b6edc..3b4c0960d 100644 --- a/common/eqemu_logsys_log_aliases.h +++ b/common/eqemu_logsys_log_aliases.h @@ -784,6 +784,16 @@ OutF(LogSys, Logs::Detail, Logs::QuestErrors, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) +#define LogPlayerEvents(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::PlayerEvents))\ + OutF(LogSys, Logs::General, Logs::PlayerEvents, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogPlayerEventsDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::PlayerEvents))\ + OutF(LogSys, Logs::Detail, Logs::PlayerEvents, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + #define Log(debug_level, log_category, message, ...) do {\ if (LogSys.IsLogEnabled(debug_level, log_category))\ LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ diff --git a/common/events/player_event_discord_formatter.cpp b/common/events/player_event_discord_formatter.cpp new file mode 100644 index 000000000..791c6c02d --- /dev/null +++ b/common/events/player_event_discord_formatter.cpp @@ -0,0 +1,1343 @@ +#include "player_event_discord_formatter.h" +#include "../repositories/character_data_repository.h" +#include "../json/json_archive_single_line.h" +#include +#include +#include +#include + +std::string PlayerEventDiscordFormatter::GetCurrentTimestamp() +{ + time_t now; + time(&now); + char buf[sizeof "2011-10-08T07:07:09Z"]; + strftime(buf, sizeof buf, "%FT%TZ", gmtime(&now)); + std::string timestamp = buf; + return timestamp; +} + +void PlayerEventDiscordFormatter::BuildDiscordField( + std::vector *f, + const std::string &name, + const std::string &value, + bool is_inline +) +{ + if (value.empty()) { + return; + } + + f->emplace_back( + DiscordField{ + .name = name, + .value = value, + .is_inline = is_inline, + } + ); +} + +void PlayerEventDiscordFormatter::BuildBaseEmbed( + std::vector *e, + const std::vector &f, + const PlayerEvent::PlayerEventContainer c +) +{ + auto d = DiscordEmbed{}; + d.fields = f; + d.author = DiscordAuthor{ + .name = fmt::format( + "[Player Event] {}", + PlayerEvent::EventName[c.player_event_log.event_type_id] + ), + }; + // d.timestamp = GetCurrentTimestamp() + + e->emplace_back(d); +} + +std::string PlayerEventDiscordFormatter::FormatEventSay( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::SayEvent &e +) +{ + std::vector f = {}; + BuildDiscordField(&f, "Message", e.message); + BuildDiscordField(&f, "Target", e.target); + + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + + auto root = BuildDiscordWebhook(c, embeds); + + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatGMCommand( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::GMCommandEvent &e +) +{ + std::vector f = {}; + BuildDiscordField(&f, "Message", e.message); + if (e.target != "NONE") { + BuildDiscordField(&f, "Target", e.target); + } + + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + + auto root = BuildDiscordWebhook(c, embeds); + + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatWithNodata(const PlayerEvent::PlayerEventContainer &c) +{ + std::vector f = {}; + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatMerchantPurchaseEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::MerchantPurchaseEvent &e +) +{ + std::vector f = {}; + BuildDiscordField(&f, "Merchant", fmt::format("{} ({}) NPC ID ({})", e.merchant_name, e.merchant_type, e.npc_id)); + BuildDiscordField(&f, "Item", fmt::format("{} ({}) x({})", e.item_name, e.item_id, e.charges)); + BuildDiscordField( + &f, + "Cost", + fmt::format( + ":moneybag: {}", + Strings::Money((e.cost / 1000), (e.cost / 100) % 10, (e.cost / 10) % 10, e.cost % 10))); + BuildDiscordField( + &f, + "Player Balance", + fmt::format( + ":moneybag: [{}] \n:gem: Currency [{}]", + Strings::Commify(std::to_string(e.player_money_balance)), + e.player_currency_balance + ) + ); + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatMerchantSellEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::MerchantSellEvent &e +) +{ + std::vector f = {}; + BuildDiscordField(&f, "Merchant", fmt::format("{} ({}) NPC ID ({})", e.merchant_name, e.merchant_type, e.npc_id)); + BuildDiscordField(&f, "Item", fmt::format("{} ({}) x({})", e.item_name, e.item_id, e.charges)); + BuildDiscordField( + &f, + "Cost", + fmt::format( + ":moneybag: {}", + Strings::Money((e.cost / 1000), (e.cost / 100) % 10, (e.cost / 10) % 10, e.cost % 10))); + BuildDiscordField( + &f, + "Player Balance", + fmt::format( + ":moneybag: [{}] \n:gem: Currency [{}]", + Strings::Commify(std::to_string(e.player_money_balance)), + e.player_currency_balance + ) + ); + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatZoningEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::ZoningEvent &e +) +{ + std::string instance_id_info; + std::string instance_version_info; + + if (e.to_instance_id > 0 || e.from_instance_id > 0) { + instance_id_info = fmt::format("Instance ID: ({}) :arrow_right: ({})", e.from_instance_id, e.to_instance_id); + } + + if (e.from_instance_version > 0 || e.to_instance_version > 0) { + instance_version_info = fmt::format( + "Instance Version: ({}) :arrow_right: ({})", + e.from_instance_version, + e.to_instance_version + ); + } + + std::vector f = {}; + BuildDiscordField( + &f, + "Zoning Information", + fmt::format( + "Zone: {} ({}) ({}) :arrow_right: {} ({}) ({})\n{}\n{}", + e.from_zone_long_name, + e.from_zone_short_name, + e.from_zone_id, + e.to_zone_long_name, + e.to_zone_short_name, + e.to_zone_id, + instance_id_info, + instance_version_info + ) + ); + + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatAAGainedEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::AAGainedEvent &e +) +{ + std::vector f = {}; + BuildDiscordField( + &f, + "Points Gained", + fmt::format( + "AA Gained ({})", + e.aa_gained + ) + ); + + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatAAPurchasedEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::AAPurchasedEvent &e +) +{ + std::string aa_info; + if (e.aa_previous_id != -1 || e.aa_next_id != -1) { + aa_info = fmt::format("AA Previous ID ({}) \nAA Next ID ({})", e.aa_previous_id, e.aa_next_id); + } + + std::vector f = {}; + BuildDiscordField( + &f, + "AA Purchased", + fmt::format( + "AA ID ({}) \nAA Cost ({}) \n{}", + e.aa_id, e.aa_cost, aa_info + ) + ); + + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatForageSuccessEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::ForageSuccessEvent &e +) +{ + std::vector f = {}; + BuildDiscordField( + &f, + "Foraged Item", + fmt::format( + "Item ID ({}) \nItem Name ({})", + e.item_id, e.item_name + ) + ); + + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatDestroyItemEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::DestroyItemEvent &e +) +{ + std::vector f = {}; + BuildDiscordField( + &f, + "Destroyed Item", + fmt::format( + "{} ({}) \nCharges ({}) \nReason ({})", + e.item_name, e.item_id, e.charges, e.reason + ) + ); + + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatLevelGainedEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::LevelGainedEvent &e +) +{ + std::vector f = {}; + BuildDiscordField( + &f, + "Level Information", + fmt::format( + "From ({}) > ({}) \nLevels Gained ({})", + e.from_level, e.to_level, e.levels_gained + ) + ); + + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatLevelLostEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::LevelLostEvent &e +) +{ + std::vector f = {}; + BuildDiscordField( + &f, + "Level Information", + fmt::format( + "From ({}) > ({}) \nLevels Lost ({})", + e.from_level, e.to_level, e.levels_lost + ) + ); + + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatLootItemEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::LootItemEvent &e +) +{ + std::vector f = {}; + BuildDiscordField( + &f, + "Looted Item", + fmt::format( + "{} ({})\nCharges: {}\nNPC: {} ({})", + e.item_name, + e.item_id, + e.charges, + e.corpse_name, + e.npc_id + ) + ); + + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + + +std::string PlayerEventDiscordFormatter::FormatGroundSpawnPickupEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::GroundSpawnPickupEvent &e +) +{ + std::vector f = {}; + BuildDiscordField( + &f, + "Picked Up Item", + fmt::format( + "{} ({})", + e.item_name, e.item_id + ) + ); + + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatSkillUpEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::SkillUpEvent &e +) +{ + std::string target_info; + if (e.against_who.length()) { + if (e.against_who == c.player_event.character_name) { + target_info = fmt::format("Target: Self"); + } + else { + target_info = fmt::format("Target: {}", e.against_who); + } + } + + std::vector f = {}; + BuildDiscordField( + &f, + "Skill Information", + fmt::format( + "Skill: {} \nLevel: ({}/{}) \n{}", + e.skill_id, e.value, e.max_skill, target_info + ) + ); + + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatTaskAcceptEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::TaskAcceptEvent &e +) +{ + + std::vector f = {}; + BuildDiscordField( + &f, + "Task Information", + fmt::format( + "{} ({}) \n {} ({})", + e.task_name, e.task_id, e.npc_name, e.npc_id + ) + ); + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatTaskCompleteEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::TaskCompleteEvent &e +) +{ + std::vector f = {}; + BuildDiscordField( + &f, + "Task Information", + fmt::format( + "{} ({}) \nActivity ID ({}) \nDone ({})", + e.task_name, e.task_id, e.activity_id, e.done_count + ) + ); + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatTaskUpdateEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::TaskUpdateEvent &e +) +{ + std::vector f = {}; + BuildDiscordField( + &f, + "Task Information", + fmt::format( + "{} ({}) \nActivity ID ({}) \nDone ({})", + e.task_name, e.task_id, e.activity_id, e.done_count + ) + ); + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatResurrectAcceptEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::ResurrectAcceptEvent &e +) +{ + std::vector f = {}; + BuildDiscordField( + &f, + "Resurrect Information", + fmt::format( + "From: {} \nSpell: {} ({})", + e.resurrecter_name, e.spell_name, e.spell_id + ) + ); + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatCombineEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::CombineEvent &e +) +{ + std::vector f = {}; + BuildDiscordField( + &f, + "Combine Information", + fmt::format( + "{} ({}) \n Made ({})", + e.recipe_name, e.recipe_id, e.made_count + ) + ); + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatFishSuccessEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::FishSuccessEvent &e +) +{ + std::vector f = {}; + BuildDiscordField( + &f, + "Fishing Information", + fmt::format( + "{} ({})", + e.item_name, e.item_id + ) + ); + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatDeathEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::DeathEvent &e +) +{ + std::string killer_info; + if (e.killer_id) { + killer_info = fmt::format("Killer: {} ({})", e.killer_name, e.killer_id); + } + + std::string spell_info; + if (e.spell_id < MAX_SPELL_DB_ID_VAL) { + spell_info = fmt::format("Spell: {} ({})", e.spell_name, e.spell_id); + } + + std::string skill_info; + if (e.skill_id) { + skill_info = fmt::format("Skill: {} ({})", e.skill_name, e.skill_id); + } + + std::vector f = {}; + BuildDiscordField( + &f, + "Death Information", + fmt::format( + "{} \nDamage: {} \n {} \n {}", + killer_info, e.damage, spell_info, skill_info + ) + ); + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatNPCHandinEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::HandinEvent &e +) +{ + std::string handin_items_info; + if (!e.handin_items.empty()) { + for (const auto &h: e.handin_items) { + handin_items_info += fmt::format( + "{} ({}){}{}\n", + h.item_name, + h.item_id, + h.charges > 1 ? fmt::format(" Charges: {}", h.charges) : "", + h.attuned ? " (Attuned)" : "" + ); + } + } + + std::string return_items_info; + if (!e.return_items.empty()) { + for (const auto &r: e.return_items) { + return_items_info += fmt::format( + "{} ({}){}{}\n", + r.item_name, + r.item_id, + r.charges > 1 ? fmt::format(" Charges: {}", r.charges) : "", + r.attuned ? " (Attuned)" : "" + ); + } + } + + std::string handin_money_info; + if (e.handin_money.platinum) { + handin_money_info += fmt::format( + ":moneybag: {} Platinum\n", + Strings::Commify(std::to_string(e.handin_money.platinum)) + ); + } + + if (e.handin_money.gold) { + handin_money_info += fmt::format( + ":moneybag: {} Gold\n", + Strings::Commify(std::to_string(e.handin_money.gold)) + ); + } + + if (e.handin_money.silver) { + handin_money_info += fmt::format( + ":moneybag: {} Silver\n", + Strings::Commify(std::to_string(e.handin_money.silver)) + ); + } + + if (e.handin_money.copper) { + handin_money_info += fmt::format( + ":moneybag: {} Copper", + Strings::Commify(std::to_string(e.handin_money.copper)) + ); + } + + + std::string return_money_info; + if (e.return_money.platinum) { + return_money_info += fmt::format( + ":moneybag: {} Platinum\n", + Strings::Commify(std::to_string(e.return_money.platinum)) + ); + } + + if (e.return_money.gold) { + return_money_info += fmt::format( + ":moneybag: {} Gold\n", + Strings::Commify(std::to_string(e.return_money.gold)) + ); + } + + if (e.return_money.silver) { + return_money_info += fmt::format( + ":moneybag: {} Silver\n", + Strings::Commify(std::to_string(e.return_money.silver)) + ); + } + + if (e.return_money.copper) { + return_money_info += fmt::format( + ":moneybag: {} Copper", + Strings::Commify(std::to_string(e.return_money.copper)) + ); + } + + std::vector f = {}; + + if (!handin_items_info.empty()) { + BuildDiscordField( + &f, + "Handin Items", + fmt::format( + "{}", + handin_items_info + ) + ); + } + + if (!handin_money_info.empty()) { + BuildDiscordField( + &f, + "Handin Money", + fmt::format( + "{}", + handin_money_info + ) + ); + } + + if (!return_items_info.empty()) { + BuildDiscordField( + &f, + "Return Items", + fmt::format( + "{}", + return_items_info + ) + ); + } + + if (!return_money_info.empty()) { + BuildDiscordField( + &f, + "Return Money", + fmt::format( + "{}", + return_money_info + ) + ); + } + + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatDiscoverItemEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::DiscoverItemEvent &e +) +{ + std::vector f = {}; + BuildDiscordField( + &f, + "Discovered Item", + fmt::format( + "{} ({})", + e.item_name, e.item_id + ) + ); + + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatDroppedItemEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::DroppedItemEvent &e +) +{ + std::vector f = {}; + BuildDiscordField( + &f, + "Dropped Item", + fmt::format( + "{} ({})\nSlot: {} ({})", + e.item_name, + e.item_id, + EQ::invslot::GetInvPossessionsSlotName(e.slot_id), + e.slot_id + ) + ); + + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatSplitMoneyEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::SplitMoneyEvent &e +) +{ + std::string money_info; + if (e.platinum) { + money_info += fmt::format( + ":moneybag: {} Platinum\n", + Strings::Commify(std::to_string(e.platinum)) + ); + } + + if (e.gold) { + money_info += fmt::format( + ":moneybag: {} Gold\n", + Strings::Commify(std::to_string(e.gold)) + ); + } + + if (e.silver) { + money_info += fmt::format( + ":moneybag: {} Silver\n", + Strings::Commify(std::to_string(e.silver)) + ); + } + + if (e.copper) { + money_info += fmt::format( + ":moneybag: {} Copper\n", + Strings::Commify(std::to_string(e.copper)) + ); + } + + money_info += fmt::format( + ":moneybag: [{}]", + Strings::Commify(std::to_string(e.player_money_balance)) + ); + + std::vector f = {}; + BuildDiscordField( + &f, + "Split Money", + money_info + ); + + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatTraderPurchaseEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::TraderPurchaseEvent &e +) +{ + std::string purchase_info; + + purchase_info += fmt::format( + "Item: {} ({})\n", + e.item_name, + e.item_id + ); + + purchase_info += fmt::format( + "Trader: {} ({})\n", + e.trader_name, + e.trader_id + ); + + purchase_info += fmt::format( + "Price: {} Amount: {} Total: {}\n", + Strings::Commify(std::to_string(e.price)), + e.charges, + Strings::Commify(std::to_string(e.total_cost)) + ); + + purchase_info += fmt::format( + ":moneybag: [{}]\n", + Strings::Commify(std::to_string(e.player_money_balance)) + ); + + std::vector f = {}; + BuildDiscordField( + &f, + "Purchase Information", + purchase_info + ); + + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatTraderSellEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::TraderSellEvent &e +) +{ + std::string sell_info; + + sell_info += fmt::format( + "Item: {} ({})\n", + e.item_name, + e.item_id + ); + + sell_info += fmt::format( + "Buyer: {} ({})\n", + e.buyer_name, + e.buyer_id + ); + + sell_info += fmt::format( + "Price: {} Amount: {} Total: {}\n", + Strings::Commify(std::to_string(e.price)), + e.charges, + Strings::Commify(std::to_string(e.total_cost)) + ); + + sell_info += fmt::format( + ":moneybag: [{}]\n", + Strings::Commify(std::to_string(e.player_money_balance)) + ); + + std::vector f = {}; + BuildDiscordField( + &f, + "Sale Information", + sell_info + ); + + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +std::string PlayerEventDiscordFormatter::FormatTradeEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::TradeEvent &e +) +{ + std::string character_1_item_info; + if (!e.character_1_give_items.empty()) { + for (const auto &i: e.character_1_give_items) { + std::string augment_info; + if (i.aug_1_item_id > 0) { + augment_info += fmt::format( + "Augment 1: {} ({})", + i.aug_1_item_name, + i.aug_1_item_id + ); + } + + if (i.aug_2_item_id > 0) { + augment_info += fmt::format( + "Augment 2: {} ({})", + i.aug_2_item_name, + i.aug_2_item_id + ); + } + + if (i.aug_3_item_id > 0) { + augment_info += fmt::format( + "Augment 3: {} ({})", + i.aug_3_item_name, + i.aug_3_item_id + ); + } + + if (i.aug_4_item_id > 0) { + augment_info += fmt::format( + "Augment 4: {} ({})\n", + i.aug_4_item_name, + i.aug_4_item_id + ); + } + + if (i.aug_5_item_id > 0) { + augment_info += fmt::format( + "Augment 5: {} ({})\n", + i.aug_5_item_name, + i.aug_5_item_id + ); + } + + if (i.aug_6_item_id > 0) { + augment_info += fmt::format( + "Augment 6: {} ({})", + i.aug_6_item_name, + i.aug_6_item_id + ); + } + + character_1_item_info += fmt::format( + "{} ({}){}\nSlot: {} ({}){}\n{}", + i.item_name, + i.item_id, + i.charges > 1 ? fmt::format(" Charges: {}", i.charges) : "", + EQ::invslot::GetInvPossessionsSlotName(i.slot), + i.slot, + i.in_bag ? " (Bagged Item)" : "", + augment_info + ); + } + } + + std::string character_2_item_info; + if (!e.character_2_give_items.empty()) { + for (const auto &i: e.character_2_give_items) { + std::string augment_info; + if (i.aug_1_item_id > 0) { + augment_info += fmt::format( + "Augment 1: {} ({})", + i.aug_1_item_name, + i.aug_1_item_id + ); + } + + if (i.aug_2_item_id > 0) { + augment_info += fmt::format( + "Augment 2: {} ({})", + i.aug_2_item_name, + i.aug_2_item_id + ); + } + + if (i.aug_3_item_id > 0) { + augment_info += fmt::format( + "Augment 3: {} ({})", + i.aug_3_item_name, + i.aug_3_item_id + ); + } + + if (i.aug_4_item_id > 0) { + augment_info += fmt::format( + "Augment 4: {} ({})\n", + i.aug_4_item_name, + i.aug_4_item_id + ); + } + + if (i.aug_5_item_id > 0) { + augment_info += fmt::format( + "Augment 5: {} ({})\n", + i.aug_5_item_name, + i.aug_5_item_id + ); + } + + if (i.aug_6_item_id > 0) { + augment_info += fmt::format( + "Augment 6: {} ({})", + i.aug_6_item_name, + i.aug_6_item_id + ); + } + + character_2_item_info += fmt::format( + "{} ({}){}\nSlot: {} ({}){}\n{}\n", + i.item_name, + i.item_id, + i.charges > 1 ? fmt::format(" Charges: {}", i.charges) : "", + EQ::invslot::GetInvPossessionsSlotName(i.slot), + i.slot, + i.in_bag ? " (Bagged Item)" : "", + augment_info + ); + } + } + + std::string character_1_money_info; + if (e.character_1_give_money.platinum) { + character_1_money_info += fmt::format( + ":moneybag: {} Platinum\n", + Strings::Commify(std::to_string(e.character_1_give_money.platinum)) + ); + } + + if (e.character_1_give_money.gold) { + character_1_money_info += fmt::format( + ":moneybag: {} Gold\n", + Strings::Commify(std::to_string(e.character_1_give_money.gold)) + ); + } + + if (e.character_1_give_money.silver) { + character_1_money_info += fmt::format( + ":moneybag: {} Silver\n", + Strings::Commify(std::to_string(e.character_1_give_money.silver)) + ); + } + + if (e.character_1_give_money.copper) { + character_1_money_info += fmt::format( + ":moneybag: {} Copper", + Strings::Commify(std::to_string(e.character_1_give_money.copper)) + ); + } + + std::string character_2_money_info; + if (e.character_2_give_money.platinum) { + character_2_money_info += fmt::format( + ":moneybag: {} Platinum\n", + Strings::Commify(std::to_string(e.character_2_give_money.platinum)) + ); + } + + if (e.character_2_give_money.gold) { + character_2_money_info += fmt::format( + ":moneybag: {} Gold\n", + Strings::Commify(std::to_string(e.character_2_give_money.gold)) + ); + } + + if (e.character_2_give_money.silver) { + character_2_money_info += fmt::format( + ":moneybag: {} Silver\n", + Strings::Commify(std::to_string(e.character_2_give_money.silver)) + ); + } + + if (e.character_2_give_money.copper) { + character_2_money_info += fmt::format( + ":moneybag: {} Copper", + Strings::Commify(std::to_string(e.character_2_give_money.copper)) + ); + } + + std::vector f = {}; + + if (!character_1_item_info.empty()) { + BuildDiscordField( + &f, + "Character 1 Items", + character_1_item_info + ); + } + + if (!character_1_money_info.empty()) { + BuildDiscordField( + &f, + "Character 1 Money", + character_1_money_info + ); + } + + if (!character_2_item_info.empty()) { + BuildDiscordField( + &f, + "Character 2 Items", + character_2_item_info + ); + } + + if (!character_2_money_info.empty()) { + BuildDiscordField( + &f, + "Character 2 Money", + character_2_money_info + ); + } + + std::vector embeds = {}; + BuildBaseEmbed(&embeds, f, c); + auto root = BuildDiscordWebhook(c, embeds); + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + root.serialize(ar); + } + + return ss.str(); +} + +DiscordWebhook PlayerEventDiscordFormatter::BuildDiscordWebhook( + const PlayerEvent::PlayerEventContainer &p, + std::vector &embeds +) +{ + DiscordWebhook w = DiscordWebhook{ + .embeds = embeds + }; + + std::string instance_info; + if (p.player_event.instance_id > 0) { + instance_info = fmt::format("Instance ID [{}]", p.player_event.instance_id); + } + + std::string guild_info; + if (!p.player_event.guild_name.empty()) { + guild_info = fmt::format(":shield: **Guild** [{}] ({})", p.player_event.guild_name, p.player_event.guild_id); + } + + std::string character = fmt::format( + "{} ({}) {}", + p.player_event.character_name, + p.player_event.character_id, + guild_info + ); + + std::string zone = fmt::format( + "[{}] ({}) ({}) {}", + p.player_event.zone_long_name, + p.player_event.zone_short_name, + p.player_event.zone_id, + instance_info + ); + + w.content = fmt::format(":trident: **Character** {} :map: **Zone** {}", character, zone); + +// w.avatar_url = "https://cdn.discordapp.com/icons/212663220849213441/a_710698e80c111a5674e1ef716d8e3f14.webp?size=96"; + + return w; +} diff --git a/common/events/player_event_discord_formatter.h b/common/events/player_event_discord_formatter.h new file mode 100644 index 000000000..aef518ace --- /dev/null +++ b/common/events/player_event_discord_formatter.h @@ -0,0 +1,214 @@ +#ifndef EQEMU_PLAYER_EVENT_DISCORD_FORMATTER_H +#define EQEMU_PLAYER_EVENT_DISCORD_FORMATTER_H + +#include +#include "player_events.h" +#include "../repositories/base/base_player_event_logs_repository.h" +#include +#include + +struct DiscordField { + std::string name; + std::string value; + bool is_inline; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(name), + CEREAL_NVP(value), + cereal::make_nvp("inline", is_inline) + ); + } +}; + +struct DiscordAuthor { + std::string name; + std::string icon_url; + std::string url; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(name), + CEREAL_NVP(icon_url), + CEREAL_NVP(url) + ); + } +}; + +struct DiscordEmbed { + std::vector fields; + std::string title; + std::string description; + std::string timestamp; + DiscordAuthor author; + + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(fields), + CEREAL_NVP(title), + CEREAL_NVP(description), + CEREAL_NVP(timestamp), + CEREAL_NVP(author) + ); + } +}; + +struct DiscordWebhook { + std::vector embeds; + std::string content; + std::string avatar_url; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(embeds), + CEREAL_NVP(avatar_url), + CEREAL_NVP(content) + ); + } +}; + + +class PlayerEventDiscordFormatter { +public: + static std::string GetCurrentTimestamp(); + static std::string FormatEventSay(const PlayerEvent::PlayerEventContainer &c, const PlayerEvent::SayEvent &e); + static std::string + FormatGMCommand(const PlayerEvent::PlayerEventContainer &c, const PlayerEvent::GMCommandEvent &e); + static void BuildDiscordField( + std::vector *f, + const std::string &name, + const std::string &value, + bool is_inline = true + ); + static void BuildBaseEmbed( + std::vector *e, + const std::vector &f, + PlayerEvent::PlayerEventContainer c + ); + static std::string FormatWithNodata(const PlayerEvent::PlayerEventContainer &c); + + static std::string FormatAAGainedEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::AAGainedEvent &e + ); + static std::string FormatAAPurchasedEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::AAPurchasedEvent &e + ); + static std::string FormatDeathEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::DeathEvent &e + ); + static std::string FormatFishSuccessEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::FishSuccessEvent &e + ); + static std::string FormatForageSuccessEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::ForageSuccessEvent &e + ); + static std::string FormatDestroyItemEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::DestroyItemEvent &e + ); + static std::string FormatDiscoverItemEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::DiscoverItemEvent &e + ); + static std::string FormatDroppedItemEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::DroppedItemEvent &e + ); + static std::string FormatLevelGainedEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::LevelGainedEvent &e + ); + static std::string FormatLevelLostEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::LevelLostEvent &e + ); + static std::string FormatLootItemEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::LootItemEvent &e + ); + static std::string FormatGroundSpawnPickupEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::GroundSpawnPickupEvent &e + ); + static std::string FormatMerchantPurchaseEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::MerchantPurchaseEvent &e + ); + static std::string FormatMerchantSellEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::MerchantSellEvent &e + ); + static std::string FormatNPCHandinEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::HandinEvent &e + ); + static std::string FormatSkillUpEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::SkillUpEvent &e + ); + static std::string FormatTaskAcceptEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::TaskAcceptEvent &e + ); + static std::string FormatTaskCompleteEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::TaskCompleteEvent &e + ); + static std::string FormatTaskUpdateEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::TaskUpdateEvent &e + ); + static std::string FormatTradeEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::TradeEvent &e + ); + static std::string FormatTraderPurchaseEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::TraderPurchaseEvent &e + ); + static std::string FormatTraderSellEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::TraderSellEvent &e + ); + static std::string FormatResurrectAcceptEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::ResurrectAcceptEvent &e + ); + static std::string FormatSplitMoneyEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::SplitMoneyEvent &e + ); + static std::string FormatCombineEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::CombineEvent &e + ); + static std::string FormatZoningEvent( + const PlayerEvent::PlayerEventContainer &c, + const PlayerEvent::ZoningEvent &e + ); + static DiscordWebhook BuildDiscordWebhook( + const PlayerEvent::PlayerEventContainer &p, + std::vector &embeds + ); +}; + + +#endif //EQEMU_PLAYER_EVENT_DISCORD_FORMATTER_H diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp new file mode 100644 index 000000000..8f5cee5a7 --- /dev/null +++ b/common/events/player_event_logs.cpp @@ -0,0 +1,708 @@ +#include +#include "player_event_logs.h" +#include "player_event_discord_formatter.h" +#include "../platform.h" +#include "../rulesys.h" + +const uint32 PROCESS_RETENTION_TRUNCATION_TIMER_INTERVAL = 60 * 60 * 1000; // 1 hour + +// general initialization routine +void PlayerEventLogs::Init() +{ + m_process_batch_events_timer.SetTimer(RuleI(Logging, BatchPlayerEventProcessIntervalSeconds) * 1000); + m_process_retention_truncation_timer.SetTimer(PROCESS_RETENTION_TRUNCATION_TIMER_INTERVAL); + + ValidateDatabaseConnection(); + + // initialize settings array + for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) { + m_settings[i].id = i; + m_settings[i].event_name = PlayerEvent::EventName[i]; + m_settings[i].event_enabled = 1; + m_settings[i].retention_days = 0; + m_settings[i].discord_webhook_id = 0; + } + + SetSettingsDefaults(); + + // initialize settings from database + auto s = PlayerEventLogSettingsRepository::All(*m_database); + std::vector db{}; + db.reserve(s.size()); + for (auto &e: s) { + if (e.id >= PlayerEvent::MAX) { + continue; + } + m_settings[e.id] = e; + db.emplace_back(e.id); + } + + // insert entries that don't exist in database + for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) { + bool is_in_database = std::find(db.begin(), db.end(), i) != db.end(); + bool is_deprecated = Strings::Contains(PlayerEvent::EventName[i], "Deprecated"); + bool is_implemented = !Strings::Contains(PlayerEvent::EventName[i], "Unimplemented"); + + // remove when deprecated + if (is_deprecated && is_in_database) { + LogInfo("[Deprecated] Removing PlayerEvent [{}] ({})", PlayerEvent::EventName[i], i); + PlayerEventLogSettingsRepository::DeleteWhere(*m_database, fmt::format("id = {}", i)); + } + // remove when unimplemented if present + if (!is_implemented && is_in_database) { + LogInfo("[Unimplemented] Removing PlayerEvent [{}] ({})", PlayerEvent::EventName[i], i); + PlayerEventLogSettingsRepository::DeleteWhere(*m_database, fmt::format("id = {}", i)); + } + + bool is_missing_in_database = std::find(db.begin(), db.end(), i) == db.end(); + if (is_missing_in_database && is_implemented && !is_deprecated) { + LogInfo( + "[New] PlayerEvent [{}] ({})", + PlayerEvent::EventName[i], + i + ); + + auto c = PlayerEventLogSettingsRepository::NewEntity(); + c.id = i; + c.event_name = PlayerEvent::EventName[i]; + c.event_enabled = m_settings[i].event_enabled; + c.retention_days = m_settings[i].retention_days; + PlayerEventLogSettingsRepository::InsertOne(*m_database, c); + } + } + + bool processing_in_world = !RuleB(Logging, PlayerEventsQSProcess) && IsWorld(); + bool processing_in_qs = RuleB(Logging, PlayerEventsQSProcess) && IsQueryServ(); + + // on initial boot process truncation + if (processing_in_world || processing_in_qs) { + ProcessRetentionTruncation(); + } +} + +// set the database object, during initialization +PlayerEventLogs *PlayerEventLogs::SetDatabase(Database *db) +{ + m_database = db; + + return this; +} + +// validates whether the connection is valid or not, used in initialization +bool PlayerEventLogs::ValidateDatabaseConnection() +{ + if (!m_database) { + LogError("No database connection"); + return false; + } + + return true; +} + +// determines if the passed in event is enabled or not +// this is used to gate logic or events from firing off +// this is used prior to building the events, we don't want to +// build the events, send them through the stack in a function call +// only to discard them immediately afterwards, very wasteful on resources +// the quest api currently does this +bool PlayerEventLogs::IsEventEnabled(PlayerEvent::EventType event) +{ + return m_settings[event].event_enabled ? m_settings[event].event_enabled : false; +} + +// this processes any current player events on the queue +void PlayerEventLogs::ProcessBatchQueue() +{ + m_batch_queue_lock.lock(); + if (m_record_batch_queue.empty()) { + m_batch_queue_lock.unlock(); + return; + } + + BenchTimer benchmark; + + // flush many + PlayerEventLogsRepository::InsertMany(*m_database, m_record_batch_queue); + LogPlayerEventsDetail( + "Processing batch player event log queue of [{}] took [{}]", + m_record_batch_queue.size(), + benchmark.elapsed() + ); + + // empty + m_record_batch_queue = {}; + m_batch_queue_lock.unlock(); +} + +// adds a player event to the queue +void PlayerEventLogs::AddToQueue(const PlayerEventLogsRepository::PlayerEventLogs &log) +{ + m_batch_queue_lock.lock(); + m_record_batch_queue.emplace_back(log); + m_batch_queue_lock.unlock(); +} + +// fills common event data in the SendEvent function +void PlayerEventLogs::FillPlayerEvent( + const PlayerEvent::PlayerEvent &p, + PlayerEventLogsRepository::PlayerEventLogs &n +) +{ + n.account_id = p.account_id; + n.character_id = p.character_id; + n.zone_id = p.zone_id; + n.instance_id = p.instance_id; + n.x = p.x; + n.y = p.y; + n.z = p.z; + n.heading = p.heading; +} + +// builds the dynamic packet used to ship the player event over the wire +// supports serializing the struct so it can be rebuilt on the other end +std::unique_ptr +PlayerEventLogs::BuildPlayerEventPacket(const PlayerEvent::PlayerEventContainer &e) +{ + EQ::Net::DynamicPacket dyn_pack; + dyn_pack.PutSerialize(0, e); + auto pack_size = sizeof(ServerSendPlayerEvent_Struct) + dyn_pack.Length(); + auto pack = std::make_unique(ServerOP_PlayerEvent, static_cast(pack_size)); + auto buf = reinterpret_cast(pack->pBuffer); + buf->cereal_size = static_cast(dyn_pack.Length()); + memcpy(buf->cereal_data, dyn_pack.Data(), dyn_pack.Length()); + + return pack; +} + +const PlayerEventLogSettingsRepository::PlayerEventLogSettings *PlayerEventLogs::GetSettings() const +{ + return m_settings; +} + +bool PlayerEventLogs::IsEventDiscordEnabled(int32_t event_type_id) +{ + // out of bounds check + if (event_type_id >= PlayerEvent::EventType::MAX) { + return false; + } + + // make sure webhook id is set + if (m_settings[event_type_id].discord_webhook_id == 0) { + return false; + } + + // ensure there is a matching webhook to begin with + if (!LogSys.GetDiscordWebhooks()[m_settings[event_type_id].discord_webhook_id].webhook_url.empty()) { + return true; + } + + return false; +} + +std::string PlayerEventLogs::GetDiscordWebhookUrlFromEventType(int32_t event_type_id) +{ + // out of bounds check + if (event_type_id >= PlayerEvent::EventType::MAX) { + return ""; + } + + // make sure webhook id is set + if (m_settings[event_type_id].discord_webhook_id == 0) { + return ""; + } + + // ensure there is a matching webhook to begin with + if (!LogSys.GetDiscordWebhooks()[m_settings[event_type_id].discord_webhook_id].webhook_url.empty()) { + return LogSys.GetDiscordWebhooks()[m_settings[event_type_id].discord_webhook_id].webhook_url; + } + + return ""; +} + +// GM_COMMAND | [x] Implemented Formatter +// ZONING | [x] Implemented Formatter +// AA_GAIN | [x] Implemented Formatter +// AA_PURCHASE | [x] Implemented Formatter +// FORAGE_SUCCESS | [x] Implemented Formatter +// FORAGE_FAILURE | [x] Implemented Formatter +// FISH_SUCCESS | [x] Implemented Formatter +// FISH_FAILURE | [x] Implemented Formatter +// ITEM_DESTROY | [x] Implemented Formatter +// WENT_ONLINE | [x] Implemented Formatter +// WENT_OFFLINE | [x] Implemented Formatter +// LEVEL_GAIN | [x] Implemented Formatter +// LEVEL_LOSS | [x] Implemented Formatter +// LOOT_ITEM | [x] Implemented Formatter +// MERCHANT_PURCHASE | [x] Implemented Formatter +// MERCHANT_SELL | [x] Implemented Formatter +// GROUP_JOIN | [] Implemented Formatter +// GROUP_LEAVE | [] Implemented Formatter +// RAID_JOIN | [] Implemented Formatter +// RAID_LEAVE | [] Implemented Formatter +// GROUNDSPAWN_PICKUP | [x] Implemented Formatter +// NPC_HANDIN | [x] Implemented Formatter +// SKILL_UP | [x] Implemented Formatter +// TASK_ACCEPT | [x] Implemented Formatter +// TASK_UPDATE | [x] Implemented Formatter +// TASK_COMPLETE | [x] Implemented Formatter +// TRADE | [] Implemented Formatter +// GIVE_ITEM | [] Implemented Formatter +// SAY | [x] Implemented Formatter +// REZ_ACCEPTED | [x] Implemented Formatter +// DEATH | [x] Implemented Formatter +// COMBINE_FAILURE | [x] Implemented Formatter +// COMBINE_SUCCESS | [x] Implemented Formatter +// DROPPED_ITEM | [x] Implemented Formatter +// SPLIT_MONEY | [x] Implemented Formatter +// DZ_JOIN | [] Implemented Formatter +// DZ_LEAVE | [] Implemented Formatter +// TRADER_PURCHASE | [x] Implemented Formatter +// TRADER_SELL | [x] Implemented Formatter +// BANDOLIER_CREATE | [] Implemented Formatter +// BANDOLIER_SWAP | [] Implemented Formatter +// DISCOVER_ITEM | [X] Implemented Formatter + +std::string PlayerEventLogs::GetDiscordPayloadFromEvent(const PlayerEvent::PlayerEventContainer &e) +{ + std::string payload; + switch (e.player_event_log.event_type_id) { + case PlayerEvent::AA_GAIN: { + PlayerEvent::AAGainedEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + payload = PlayerEventDiscordFormatter::FormatAAGainedEvent(e, n); + break; + } + case PlayerEvent::AA_PURCHASE: { + PlayerEvent::AAPurchasedEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + payload = PlayerEventDiscordFormatter::FormatAAPurchasedEvent(e, n); + break; + } + case PlayerEvent::COMBINE_FAILURE: + case PlayerEvent::COMBINE_SUCCESS: { + PlayerEvent::CombineEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + payload = PlayerEventDiscordFormatter::FormatCombineEvent(e, n); + break; + } + case PlayerEvent::DEATH: { + PlayerEvent::DeathEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + payload = PlayerEventDiscordFormatter::FormatDeathEvent(e, n); + break; + } + case PlayerEvent::DISCOVER_ITEM: { + PlayerEvent::DiscoverItemEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + payload = PlayerEventDiscordFormatter::FormatDiscoverItemEvent(e, n); + break; + } + case PlayerEvent::DROPPED_ITEM: { + PlayerEvent::DroppedItemEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + payload = PlayerEventDiscordFormatter::FormatDroppedItemEvent(e, n); + break; + } + case PlayerEvent::FISH_FAILURE: { + payload = PlayerEventDiscordFormatter::FormatWithNodata(e); + break; + } + case PlayerEvent::FISH_SUCCESS: { + PlayerEvent::FishSuccessEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + payload = PlayerEventDiscordFormatter::FormatFishSuccessEvent(e, n); + break; + } + case PlayerEvent::FORAGE_FAILURE: { + payload = PlayerEventDiscordFormatter::FormatWithNodata(e); + break; + } + case PlayerEvent::FORAGE_SUCCESS: { + PlayerEvent::ForageSuccessEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + payload = PlayerEventDiscordFormatter::FormatForageSuccessEvent(e, n); + break; + } + case PlayerEvent::ITEM_DESTROY: { + PlayerEvent::DestroyItemEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + payload = PlayerEventDiscordFormatter::FormatDestroyItemEvent(e, n); + break; + } + case PlayerEvent::LEVEL_GAIN: { + PlayerEvent::LevelGainedEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + payload = PlayerEventDiscordFormatter::FormatLevelGainedEvent(e, n); + break; + } + case PlayerEvent::LEVEL_LOSS: { + PlayerEvent::LevelLostEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + payload = PlayerEventDiscordFormatter::FormatLevelLostEvent(e, n); + break; + } + case PlayerEvent::LOOT_ITEM: { + PlayerEvent::LootItemEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + payload = PlayerEventDiscordFormatter::FormatLootItemEvent(e, n); + break; + } + case PlayerEvent::GROUNDSPAWN_PICKUP: { + PlayerEvent::GroundSpawnPickupEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + payload = PlayerEventDiscordFormatter::FormatGroundSpawnPickupEvent(e, n); + break; + } + case PlayerEvent::NPC_HANDIN: { + PlayerEvent::HandinEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + payload = PlayerEventDiscordFormatter::FormatNPCHandinEvent(e, n); + break; + } + case PlayerEvent::SAY: { + PlayerEvent::SayEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + payload = PlayerEventDiscordFormatter::FormatEventSay(e, n); + break; + } + case PlayerEvent::GM_COMMAND: { + PlayerEvent::GMCommandEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + payload = PlayerEventDiscordFormatter::FormatGMCommand(e, n); + break; + } + case PlayerEvent::SKILL_UP: { + PlayerEvent::SkillUpEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + payload = PlayerEventDiscordFormatter::FormatSkillUpEvent(e, n); + break; + } + case PlayerEvent::SPLIT_MONEY: { + PlayerEvent::SplitMoneyEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + payload = PlayerEventDiscordFormatter::FormatSplitMoneyEvent(e, n); + break; + } + case PlayerEvent::TASK_ACCEPT: { + PlayerEvent::TaskAcceptEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + payload = PlayerEventDiscordFormatter::FormatTaskAcceptEvent(e, n); + break; + } + case PlayerEvent::TASK_COMPLETE: { + PlayerEvent::TaskCompleteEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + payload = PlayerEventDiscordFormatter::FormatTaskCompleteEvent(e, n); + break; + } + case PlayerEvent::TASK_UPDATE: { + PlayerEvent::TaskUpdateEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + payload = PlayerEventDiscordFormatter::FormatTaskUpdateEvent(e, n); + break; + } + case PlayerEvent::TRADE: { + PlayerEvent::TradeEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + payload = PlayerEventDiscordFormatter::FormatTradeEvent(e, n); + break; + } + case PlayerEvent::TRADER_PURCHASE: { + PlayerEvent::TraderPurchaseEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + payload = PlayerEventDiscordFormatter::FormatTraderPurchaseEvent(e, n); + break; + } + case PlayerEvent::TRADER_SELL: { + PlayerEvent::TraderSellEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + payload = PlayerEventDiscordFormatter::FormatTraderSellEvent(e, n); + break; + } + case PlayerEvent::REZ_ACCEPTED: { + PlayerEvent::ResurrectAcceptEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + payload = PlayerEventDiscordFormatter::FormatResurrectAcceptEvent(e, n); + break; + } + case PlayerEvent::WENT_ONLINE: + case PlayerEvent::WENT_OFFLINE: { + payload = PlayerEventDiscordFormatter::FormatWithNodata(e); + break; + } + case PlayerEvent::MERCHANT_PURCHASE: { + PlayerEvent::MerchantPurchaseEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + + payload = PlayerEventDiscordFormatter::FormatMerchantPurchaseEvent(e, n); + break; + } + case PlayerEvent::MERCHANT_SELL: { + PlayerEvent::MerchantSellEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + + payload = PlayerEventDiscordFormatter::FormatMerchantSellEvent(e, n); + break; + } + case PlayerEvent::ZONING: { + PlayerEvent::ZoningEvent n{}; + std::stringstream ss; + { + ss << e.player_event_log.event_data; + cereal::JSONInputArchive ar(ss); + n.serialize(ar); + } + + payload = PlayerEventDiscordFormatter::FormatZoningEvent(e, n); + break; + } + default: { + LogInfo( + "Player event [{}] ({}) Discord formatter not implemented", + e.player_event_log.event_type_name, + e.player_event_log.event_type_id + ); + } + } + + return payload; +} + +// general process function, used in world or QS depending on rule Logging:PlayerEventsQSProcess +void PlayerEventLogs::Process() +{ + if (m_process_batch_events_timer.Check() || m_record_batch_queue.size() >= RuleI(Logging, BatchPlayerEventProcessChunkSize)) { + ProcessBatchQueue(); + } + + if (m_process_retention_truncation_timer.Check()) { + ProcessRetentionTruncation(); + } +} + +void PlayerEventLogs::ProcessRetentionTruncation() +{ + LogInfo("Running truncation"); + + for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) { + if (m_settings[i].retention_days > 0) { + int deleted_count = PlayerEventLogsRepository::DeleteWhere( + *m_database, + fmt::format( + "event_type_id = {} AND created_at < (NOW() - INTERVAL {} DAY)", + i, + m_settings[i].retention_days + ) + ); + + if (deleted_count > 0) { + LogInfo( + "Truncated [{}] events of type [{}] ({}) older than [{}] days", + deleted_count, + PlayerEvent::EventName[i], + i, + m_settings[i].retention_days + ); + } + } + } +} + +void PlayerEventLogs::ReloadSettings() +{ + for (auto &e: PlayerEventLogSettingsRepository::All(*m_database)) { + m_settings[e.id] = e; + } +} + +const int32_t RETENTION_DAYS_DEFAULT = 7; + +void PlayerEventLogs::SetSettingsDefaults() +{ + m_settings[PlayerEvent::GM_COMMAND].event_enabled = 1; + m_settings[PlayerEvent::ZONING].event_enabled = 1; + m_settings[PlayerEvent::AA_GAIN].event_enabled = 1; + m_settings[PlayerEvent::AA_PURCHASE].event_enabled = 1; + m_settings[PlayerEvent::FORAGE_SUCCESS].event_enabled = 0; + m_settings[PlayerEvent::FORAGE_FAILURE].event_enabled = 0; + m_settings[PlayerEvent::FISH_SUCCESS].event_enabled = 0; + m_settings[PlayerEvent::FISH_FAILURE].event_enabled = 0; + m_settings[PlayerEvent::ITEM_DESTROY].event_enabled = 1; + m_settings[PlayerEvent::WENT_ONLINE].event_enabled = 0; + m_settings[PlayerEvent::WENT_OFFLINE].event_enabled = 0; + m_settings[PlayerEvent::LEVEL_GAIN].event_enabled = 1; + m_settings[PlayerEvent::LEVEL_LOSS].event_enabled = 1; + m_settings[PlayerEvent::LOOT_ITEM].event_enabled = 1; + m_settings[PlayerEvent::MERCHANT_PURCHASE].event_enabled = 1; + m_settings[PlayerEvent::MERCHANT_SELL].event_enabled = 1; + m_settings[PlayerEvent::GROUP_JOIN].event_enabled = 0; + m_settings[PlayerEvent::GROUP_LEAVE].event_enabled = 0; + m_settings[PlayerEvent::RAID_JOIN].event_enabled = 0; + m_settings[PlayerEvent::RAID_LEAVE].event_enabled = 0; + m_settings[PlayerEvent::GROUNDSPAWN_PICKUP].event_enabled = 1; + m_settings[PlayerEvent::NPC_HANDIN].event_enabled = 1; + m_settings[PlayerEvent::SKILL_UP].event_enabled = 0; + m_settings[PlayerEvent::TASK_ACCEPT].event_enabled = 1; + m_settings[PlayerEvent::TASK_UPDATE].event_enabled = 1; + m_settings[PlayerEvent::TASK_COMPLETE].event_enabled = 1; + m_settings[PlayerEvent::TRADE].event_enabled = 1; + m_settings[PlayerEvent::GIVE_ITEM].event_enabled = 1; + m_settings[PlayerEvent::SAY].event_enabled = 0; + m_settings[PlayerEvent::REZ_ACCEPTED].event_enabled = 1; + m_settings[PlayerEvent::DEATH].event_enabled = 1; + m_settings[PlayerEvent::COMBINE_FAILURE].event_enabled = 1; + m_settings[PlayerEvent::COMBINE_SUCCESS].event_enabled = 1; + m_settings[PlayerEvent::DROPPED_ITEM].event_enabled = 1; + m_settings[PlayerEvent::SPLIT_MONEY].event_enabled = 1; + m_settings[PlayerEvent::DZ_JOIN].event_enabled = 1; + m_settings[PlayerEvent::DZ_LEAVE].event_enabled = 1; + m_settings[PlayerEvent::TRADER_PURCHASE].event_enabled = 1; + m_settings[PlayerEvent::TRADER_SELL].event_enabled = 1; + m_settings[PlayerEvent::BANDOLIER_CREATE].event_enabled = 0; + m_settings[PlayerEvent::BANDOLIER_SWAP].event_enabled = 0; + m_settings[PlayerEvent::DISCOVER_ITEM].event_enabled = 1; + m_settings[PlayerEvent::POSSIBLE_HACK].event_enabled = 1; + m_settings[PlayerEvent::KILLED_NPC].event_enabled = 0; + m_settings[PlayerEvent::KILLED_NAMED_NPC].event_enabled = 1; + m_settings[PlayerEvent::KILLED_RAID_NPC].event_enabled = 1; + m_settings[PlayerEvent::ITEM_CREATION].event_enabled = 1; + + for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) { + m_settings[i].retention_days = RETENTION_DAYS_DEFAULT; + } +} diff --git a/common/events/player_event_logs.h b/common/events/player_event_logs.h new file mode 100644 index 000000000..814f075ba --- /dev/null +++ b/common/events/player_event_logs.h @@ -0,0 +1,85 @@ +#ifndef EQEMU_PLAYER_EVENT_LOGS_H +#define EQEMU_PLAYER_EVENT_LOGS_H + +#include "../repositories/player_event_log_settings_repository.h" +#include "player_events.h" +#include "../servertalk.h" +#include "../repositories/player_event_logs_repository.h" +#include "../timer.h" +#include "../json/json_archive_single_line.h" +#include +#include + +class PlayerEventLogs { +public: + void Init(); + void ReloadSettings(); + PlayerEventLogs *SetDatabase(Database *db); + bool ValidateDatabaseConnection(); + bool IsEventEnabled(PlayerEvent::EventType event); + + void Process(); + + // batch queue + void AddToQueue(const PlayerEventLogsRepository::PlayerEventLogs &logs); + + // main event record generic function + // can ingest any struct event types + template + std::unique_ptr RecordEvent( + PlayerEvent::EventType t, + const PlayerEvent::PlayerEvent &p, + T e + ) + { + auto n = PlayerEventLogsRepository::NewEntity(); + FillPlayerEvent(p, n); + n.event_type_id = t; + + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + e.serialize(ar); + } + + n.event_type_name = PlayerEvent::EventName[t]; + n.event_data = Strings::Contains(ss.str(), "noop") ? "{}" : ss.str(); + n.created_at = std::time(nullptr); + + auto c = PlayerEvent::PlayerEventContainer{ + .player_event = p, + .player_event_log = n + }; + + return BuildPlayerEventPacket(c); + } + + [[nodiscard]] const PlayerEventLogSettingsRepository::PlayerEventLogSettings *GetSettings() const; + bool IsEventDiscordEnabled(int32_t event_type_id); + std::string GetDiscordWebhookUrlFromEventType(int32_t event_type_id); + + static std::string GetDiscordPayloadFromEvent(const PlayerEvent::PlayerEventContainer &e); +private: + Database *m_database; // reference to database + PlayerEventLogSettingsRepository::PlayerEventLogSettings m_settings[PlayerEvent::EventType::MAX]{}; + + // batch queue is used to record events in batch + std::vector m_record_batch_queue{}; + static void FillPlayerEvent(const PlayerEvent::PlayerEvent &p, PlayerEventLogsRepository::PlayerEventLogs &n); + static std::unique_ptr + BuildPlayerEventPacket(const PlayerEvent::PlayerEventContainer &e); + + // timers + Timer m_process_batch_events_timer; // events processing timer + Timer m_process_retention_truncation_timer; // timer for truncating events based on retention settings + + // processing + std::mutex m_batch_queue_lock{}; + void ProcessBatchQueue(); + void ProcessRetentionTruncation(); + void SetSettingsDefaults(); +}; + +extern PlayerEventLogs player_event_logs; + +#endif //EQEMU_PLAYER_EVENT_LOGS_H diff --git a/common/events/player_events.h b/common/events/player_events.h new file mode 100644 index 000000000..c87872e88 --- /dev/null +++ b/common/events/player_events.h @@ -0,0 +1,971 @@ +#ifndef EQEMU_PLAYER_EVENTS_H +#define EQEMU_PLAYER_EVENTS_H + +#include +#include +#include "../types.h" +#include "../repositories/player_event_logs_repository.h" + +namespace PlayerEvent { + + enum EventType { + GM_COMMAND = 1, + ZONING, + AA_GAIN, + AA_PURCHASE, + FORAGE_SUCCESS, + FORAGE_FAILURE, + FISH_SUCCESS, + FISH_FAILURE, + ITEM_DESTROY, + WENT_ONLINE, + WENT_OFFLINE, + LEVEL_GAIN, + LEVEL_LOSS, + LOOT_ITEM, + MERCHANT_PURCHASE, + MERCHANT_SELL, + GROUP_JOIN, // unimplemented + GROUP_LEAVE, // unimplemented + RAID_JOIN, // unimplemented + RAID_LEAVE, // unimplemented + GROUNDSPAWN_PICKUP, + NPC_HANDIN, + SKILL_UP, + TASK_ACCEPT, + TASK_UPDATE, + TASK_COMPLETE, + TRADE, + GIVE_ITEM, // unimplemented + SAY, + REZ_ACCEPTED, + DEATH, + COMBINE_FAILURE, + COMBINE_SUCCESS, + DROPPED_ITEM, + SPLIT_MONEY, + DZ_JOIN, // unimplemented + DZ_LEAVE, // unimplemented + TRADER_PURCHASE, + TRADER_SELL, + BANDOLIER_CREATE, // unimplemented + BANDOLIER_SWAP, // unimplemented + DISCOVER_ITEM, + POSSIBLE_HACK, + KILLED_NPC, + KILLED_NAMED_NPC, + KILLED_RAID_NPC, + ITEM_CREATION, + MAX // dont remove + }; + + // Don't ever remove items, even if they are deprecated + // If event is deprecated just tag (Deprecated) in the name + // If event is unimplemented just tag (Unimplemented) in the name + // Events don't get saved to the database if unimplemented or deprecated + // Events tagged as deprecated will get automatically removed + static const char *EventName[PlayerEvent::MAX] = { + "None", + "GM Command", + "Zoning", + "AA Gain", + "AA Purchase", + "Forage Success", + "Forage Failure", + "Fish Success", + "Fish Failure", + "Item Destroy", + "Went Online", + "Went Offline", + "Level Gain", + "Level Loss", + "Loot Item", + "Merchant Purchase", + "Merchant Sell", + "Group Join (Unimplemented)", + "Group Leave (Unimplemented)", + "Raid Join (Unimplemented)", + "Raid Leave (Unimplemented)", + "Groundspawn Pickup", + "NPC Handin", + "Skill Up", + "Task Accept", + "Task Update", + "Task Complete", + "Trade", + "Given Item (Unimplemented)", + "Say", + "Rez Accepted", + "Death", + "Combine Failure", + "Combine Success", + "Dropped Item", + "Split Money", + "DZ Join (Unimplemented)", + "DZ Leave (Unimplemented)", + "Trader Purchase", + "Trader Sell", + "Bandolier Create (Unimplemented)", + "Bandolier Swap (Unimplemented)", + "Discover Item", + "Possible Hack", + "Killed NPC", + "Killed Named NPC", + "Killed Raid NPC", + "Item Creation" + }; + + // Generic struct used by all events + struct PlayerEvent { + int64 account_id; + std::string account_name; + int64 character_id; + std::string character_name; + int64 guild_id; + std::string guild_name; + int zone_id; + std::string zone_short_name; + std::string zone_long_name; + int instance_id; + float x; + float y; + float z; + float heading; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(account_id), + CEREAL_NVP(account_name), + CEREAL_NVP(character_id), + CEREAL_NVP(character_name), + CEREAL_NVP(guild_id), + CEREAL_NVP(guild_name), + CEREAL_NVP(zone_id), + CEREAL_NVP(zone_short_name), + CEREAL_NVP(zone_long_name), + CEREAL_NVP(instance_id), + CEREAL_NVP(x), + CEREAL_NVP(y), + CEREAL_NVP(z), + CEREAL_NVP(heading) + ); + } + }; + + // contains metadata in use for things like log/discord formatters + // along with the actual event to be persisted + struct PlayerEventContainer { + PlayerEvent player_event; + PlayerEventLogsRepository::PlayerEventLogs player_event_log; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(player_event), + CEREAL_NVP(player_event_log) + ); + } + }; + + // used in events with no extra data + struct EmptyEvent { + std::string noop; // noop, gets discard upstream + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(noop) + ); + } + }; + + // used in Trade event + struct ItemCreationEvent { + int64 item_id; + std::string item_name; + uint16 to_slot; + int16 charges; + uint32 aug1; + uint32 aug2; + uint32 aug3; + uint32 aug4; + uint32 aug5; + uint32 aug6; + bool attuned; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(item_id), + CEREAL_NVP(item_name), + CEREAL_NVP(to_slot), + CEREAL_NVP(charges), + CEREAL_NVP(aug1), + CEREAL_NVP(aug2), + CEREAL_NVP(aug3), + CEREAL_NVP(aug4), + CEREAL_NVP(aug5), + CEREAL_NVP(aug6), + CEREAL_NVP(attuned) + ); + } + }; + + // used in Trade event + struct TradeItem { + int64 item_id; + std::string item_name; + int32 slot; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(item_id), + CEREAL_NVP(item_name), + CEREAL_NVP(slot) + ); + } + }; + + // used in Trade event + class TradeItemEntry { + public: + uint16 slot; + uint32 item_id; + std::string item_name; + uint16 charges; + uint32 aug_1_item_id; + std::string aug_1_item_name; + uint32 aug_2_item_id; + std::string aug_2_item_name; + uint32 aug_3_item_id; + std::string aug_3_item_name; + uint32 aug_4_item_id; + std::string aug_4_item_name; + uint32 aug_5_item_id; + std::string aug_5_item_name; + uint32 aug_6_item_id; + std::string aug_6_item_name; + bool in_bag; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(slot), + CEREAL_NVP(item_id), + CEREAL_NVP(charges), + CEREAL_NVP(aug_1_item_id), + CEREAL_NVP(aug_2_item_id), + CEREAL_NVP(aug_3_item_id), + CEREAL_NVP(aug_4_item_id), + CEREAL_NVP(aug_5_item_id), + CEREAL_NVP(in_bag) + ); + } + }; + + /** + * Events + */ + struct Money { + int32 platinum; + int32 gold; + int32 silver; + int32 copper; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(platinum), + CEREAL_NVP(gold), + CEREAL_NVP(silver), + CEREAL_NVP(copper) + ); + } + }; + + struct TradeEvent { + uint32 character_1_id; + std::string character_1_name; + uint32 character_2_id; + std::string character_2_name; + Money character_1_give_money; + Money character_2_give_money; + std::vector character_1_give_items; + std::vector character_2_give_items; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(character_1_id), + CEREAL_NVP(character_1_name), + CEREAL_NVP(character_2_id), + CEREAL_NVP(character_2_name), + CEREAL_NVP(character_1_give_money), + CEREAL_NVP(character_2_give_money), + CEREAL_NVP(character_1_give_items), + CEREAL_NVP(character_2_give_items) + ); + } + }; + + struct GMCommandEvent { + std::string message; + std::string target; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(message), + CEREAL_NVP(target) + ); + } + }; + + struct ZoningEvent { + std::string from_zone_long_name; + std::string from_zone_short_name; + int32 from_zone_id; + int32 from_instance_id; + int32 from_instance_version; + std::string to_zone_long_name; + std::string to_zone_short_name; + int32 to_zone_id; + int32 to_instance_id; + int32 to_instance_version; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(from_zone_long_name), + CEREAL_NVP(from_zone_short_name), + CEREAL_NVP(from_zone_id), + CEREAL_NVP(from_instance_id), + CEREAL_NVP(from_instance_version), + CEREAL_NVP(to_zone_long_name), + CEREAL_NVP(to_zone_short_name), + CEREAL_NVP(to_zone_id), + CEREAL_NVP(to_instance_id), + CEREAL_NVP(to_instance_version) + ); + } + }; + + struct AAGainedEvent { + uint32 aa_gained; + + // cereal + template + void serialize(Archive &ar) + { + ar(CEREAL_NVP(aa_gained)); + } + }; + + struct AAPurchasedEvent { + int32 aa_id; + int32 aa_cost; + int32 aa_previous_id; + int32 aa_next_id; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(aa_id), + CEREAL_NVP(aa_cost), + CEREAL_NVP(aa_previous_id), + CEREAL_NVP(aa_next_id) + ); + } + }; + + struct ForageSuccessEvent { + uint32 item_id; + std::string item_name; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(item_id), + CEREAL_NVP(item_name) + ); + } + }; + + struct FishSuccessEvent { + uint32 item_id; + std::string item_name; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(item_id), + CEREAL_NVP(item_name) + ); + } + }; + + struct DestroyItemEvent { + uint32 item_id; + std::string item_name; + int16 charges; + std::string reason; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(item_id), + CEREAL_NVP(item_name), + CEREAL_NVP(reason), + CEREAL_NVP(charges) + ); + } + }; + + struct LevelGainedEvent { + uint32 from_level; + uint8 to_level; + int levels_gained; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(from_level), + CEREAL_NVP(to_level), + CEREAL_NVP(levels_gained) + ); + } + }; + + struct LevelLostEvent { + uint32 from_level; + uint8 to_level; + int levels_lost; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(from_level), + CEREAL_NVP(to_level), + CEREAL_NVP(levels_lost) + ); + } + }; + + struct LootItemEvent { + uint32 item_id; + std::string item_name; + int16 charges; + uint32 npc_id; + std::string corpse_name; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(item_id), + CEREAL_NVP(item_name), + CEREAL_NVP(charges), + CEREAL_NVP(npc_id), + CEREAL_NVP(corpse_name) + ); + } + }; + + struct MerchantPurchaseEvent { + uint32 npc_id; + std::string merchant_name; + uint32 merchant_type; + uint32 item_id; + std::string item_name; + int16 charges; + uint32 cost; + uint32 alternate_currency_id; + uint64 player_money_balance; + uint64 player_currency_balance; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(npc_id), + CEREAL_NVP(merchant_name), + CEREAL_NVP(merchant_type), + CEREAL_NVP(item_id), + CEREAL_NVP(item_name), + CEREAL_NVP(charges), + CEREAL_NVP(cost), + CEREAL_NVP(alternate_currency_id), + CEREAL_NVP(player_money_balance), + CEREAL_NVP(player_currency_balance) + ); + } + }; + + struct MerchantSellEvent { + uint32 npc_id; + std::string merchant_name; + uint32 merchant_type; + uint32 item_id; + std::string item_name; + int16 charges; + uint32 cost; + uint32 alternate_currency_id; + uint64 player_money_balance; + uint64 player_currency_balance; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(npc_id), + CEREAL_NVP(merchant_name), + CEREAL_NVP(merchant_type), + CEREAL_NVP(item_id), + CEREAL_NVP(item_name), + CEREAL_NVP(charges), + CEREAL_NVP(cost), + CEREAL_NVP(alternate_currency_id), + CEREAL_NVP(player_money_balance), + CEREAL_NVP(player_currency_balance) + ); + } + }; + + struct SkillUpEvent { + uint32 skill_id; + int value; + int16 max_skill; + std::string against_who; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(skill_id), + CEREAL_NVP(value), + CEREAL_NVP(max_skill), + CEREAL_NVP(against_who) + ); + } + }; + + struct TaskAcceptEvent { + uint32 npc_id; + std::string npc_name; + uint32 task_id; + std::string task_name; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(npc_id), + CEREAL_NVP(npc_name), + CEREAL_NVP(task_id), + CEREAL_NVP(task_name) + ); + } + }; + + struct TaskUpdateEvent { + uint32 task_id; + std::string task_name; + uint32 activity_id; + uint32 done_count; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(task_id), + CEREAL_NVP(task_name), + CEREAL_NVP(activity_id), + CEREAL_NVP(done_count) + ); + } + }; + + struct TaskCompleteEvent { + uint32 task_id; + std::string task_name; + uint32 activity_id; + uint32 done_count; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(task_id), + CEREAL_NVP(task_name), + CEREAL_NVP(activity_id), + CEREAL_NVP(done_count) + ); + } + }; + + struct GroundSpawnPickupEvent { + uint32 item_id; + std::string item_name; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(item_id), + CEREAL_NVP(item_name) + ); + } + }; + + struct SayEvent { + std::string message; + std::string target; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(message), + CEREAL_NVP(target) + ); + } + }; + + struct ResurrectAcceptEvent { + std::string resurrecter_name; + std::string spell_name; + uint32 spell_id; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(resurrecter_name), + CEREAL_NVP(spell_name), + CEREAL_NVP(spell_id) + ); + } + }; + + struct CombineEvent { + uint32 recipe_id; + std::string recipe_name; + uint32 made_count; + uint32 tradeskill_id; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(recipe_id), + CEREAL_NVP(recipe_name), + CEREAL_NVP(made_count), + CEREAL_NVP(tradeskill_id) + ); + } + }; + + struct DroppedItemEvent { + uint32 item_id; + std::string item_name; + int16 slot_id; + uint32 charges; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(item_id), + CEREAL_NVP(item_name), + CEREAL_NVP(slot_id), + CEREAL_NVP(charges) + ); + } + }; + + struct DeathEvent { + uint32 killer_id; + std::string killer_name; + int64 damage; + uint32 spell_id; + std::string spell_name; + int skill_id; + std::string skill_name; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(killer_id), + CEREAL_NVP(killer_name), + CEREAL_NVP(damage), + CEREAL_NVP(spell_id), + CEREAL_NVP(spell_name), + CEREAL_NVP(skill_id), + CEREAL_NVP(skill_name) + ); + } + }; + + struct SplitMoneyEvent { + uint32 copper; + uint32 silver; + uint32 gold; + uint32 platinum; + uint64 player_money_balance; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(copper), + CEREAL_NVP(silver), + CEREAL_NVP(gold), + CEREAL_NVP(platinum), + CEREAL_NVP(player_money_balance) + ); + } + }; + + struct TraderPurchaseEvent { + uint32 item_id; + std::string item_name; + uint32 trader_id; + std::string trader_name; + uint32 price; + uint32 charges; + uint32 total_cost; + uint64 player_money_balance; + + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(item_id), + CEREAL_NVP(item_name), + CEREAL_NVP(trader_id), + CEREAL_NVP(trader_name), + CEREAL_NVP(price), + CEREAL_NVP(charges), + CEREAL_NVP(total_cost), + CEREAL_NVP(player_money_balance) + ); + } + }; + + struct TraderSellEvent { + uint32 item_id; + std::string item_name; + uint32 buyer_id; + std::string buyer_name; + uint32 price; + uint32 charges; + uint32 total_cost; + uint64 player_money_balance; + + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(item_id), + CEREAL_NVP(item_name), + CEREAL_NVP(buyer_id), + CEREAL_NVP(buyer_name), + CEREAL_NVP(price), + CEREAL_NVP(charges), + CEREAL_NVP(total_cost), + CEREAL_NVP(player_money_balance) + ); + } + }; + + struct DiscoverItemEvent { + uint32 item_id; + std::string item_name; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(item_id), + CEREAL_NVP(item_name) + ); + } + }; + + class HandinEntry { + public: + uint32 item_id; + std::string item_name; + uint16 charges; + bool attuned; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(item_id), + CEREAL_NVP(item_name), + CEREAL_NVP(charges), + CEREAL_NVP(attuned) + ); + } + }; + + class HandinMoney { + public: + uint32 copper; + uint32 silver; + uint32 gold; + uint32 platinum; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(copper), + CEREAL_NVP(silver), + CEREAL_NVP(gold), + CEREAL_NVP(platinum) + ); + } + }; + + struct HandinEvent { + uint32 npc_id; + std::string npc_name; + std::vector handin_items; + HandinMoney handin_money; + std::vector return_items; + HandinMoney return_money; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(npc_id), + CEREAL_NVP(npc_name), + CEREAL_NVP(handin_items), + CEREAL_NVP(handin_money), + CEREAL_NVP(return_items), + CEREAL_NVP(return_money) + ); + } + }; + + struct PossibleHackEvent { + std::string message; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(message) + ); + } + }; + + struct KilledNPCEvent { + uint32 npc_id; + std::string npc_name; + uint32 combat_time_seconds; + uint64 total_damage_per_second_taken; + uint64 total_heal_per_second_taken; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(npc_id), + CEREAL_NVP(npc_name), + CEREAL_NVP(combat_time_seconds), + CEREAL_NVP(total_damage_per_second_taken), + CEREAL_NVP(total_heal_per_second_taken) + ); + } + }; +} + +#endif //EQEMU_PLAYER_EVENTS_H + +#define RecordPlayerEventLog(event_type, event_data) do {\ + if (player_event_logs.IsEventEnabled(event_type)) {\ + worldserver.SendPacket(\ + player_event_logs.RecordEvent(\ + event_type,\ + GetPlayerEvent(),\ + event_data\ + ).get()\ + );\ + }\ +} while (0) + +#define RecordPlayerEventLogWithClient(c, event_type, event_data) do {\ + if (player_event_logs.IsEventEnabled(event_type)) {\ + worldserver.SendPacket(\ + player_event_logs.RecordEvent(\ + event_type,\ + (c)->GetPlayerEvent(),\ + event_data\ + ).get()\ + );\ + }\ +} while (0) diff --git a/common/features.h b/common/features.h index e1ca61f64..9d7a3ecee 100644 --- a/common/features.h +++ b/common/features.h @@ -132,7 +132,7 @@ enum { //reuse times InstillDoubtReuseTime = 9, FishingReuseTime = 11, ForagingReuseTime = 50, - MendReuseTime = 290, + MendReuseTime = 360, BashReuseTime = 5, BackstabReuseTime = 9, KickReuseTime = 5, diff --git a/common/guild_base.cpp b/common/guild_base.cpp index 07322f9e1..911f28651 100644 --- a/common/guild_base.cpp +++ b/common/guild_base.cpp @@ -61,7 +61,7 @@ bool BaseGuildManager::LoadGuilds() { } for (auto row=results.begin();row!=results.end();++row) - _CreateGuild(atoi(row[0]), row[1], atoi(row[2]), atoi(row[3]), row[4], row[5], row[6], row[7]); + _CreateGuild(Strings::ToInt(row[0]), row[1], Strings::ToInt(row[2]), Strings::ToInt(row[3]), row[4], row[5], row[6], row[7]); LogInfo("Loaded [{}] Guilds", Strings::Commify(std::to_string(results.RowCount()))); @@ -75,8 +75,8 @@ bool BaseGuildManager::LoadGuilds() { for (auto row=results.begin();row!=results.end();++row) { - uint32 guild_id = atoi(row[0]); - uint8 rankn = atoi(row[1]); + uint32 guild_id = Strings::ToInt(row[0]); + uint8 rankn = Strings::ToInt(row[1]); if(rankn > GUILD_MAX_RANK) { LogGuilds("Found invalid (too high) rank [{}] for guild [{}], skipping", rankn, guild_id); @@ -131,7 +131,7 @@ bool BaseGuildManager::RefreshGuild(uint32 guild_id) { auto row = results.begin(); - info = _CreateGuild(guild_id, row[0], atoi(row[1]), atoi(row[2]), row[3], row[4], row[5], row[6]); + info = _CreateGuild(guild_id, row[0], Strings::ToInt(row[1]), Strings::ToInt(row[2]), row[3], row[4], row[5], row[6]); query = StringFormat("SELECT guild_id, `rank`, title, can_hear, can_speak, can_invite, can_remove, can_promote, can_demote, can_motd, can_warpeace " "FROM guild_ranks WHERE guild_id=%lu", (unsigned long)guild_id); @@ -144,7 +144,7 @@ bool BaseGuildManager::RefreshGuild(uint32 guild_id) { for (auto row=results.begin();row!=results.end();++row) { - uint8 rankn = atoi(row[1]); + uint8 rankn = Strings::ToInt(row[1]); if(rankn > GUILD_MAX_RANK) { LogGuilds("Found invalid (too high) rank [{}] for guild [{}], skipping", rankn, guild_id); @@ -787,7 +787,7 @@ bool BaseGuildManager::GetBankerFlag(uint32 CharID) auto row = results.begin(); - bool IsBanker = atoi(row[0]); + bool IsBanker = Strings::ToInt(row[0]); return IsBanker; } @@ -817,7 +817,7 @@ bool BaseGuildManager::GetAltFlag(uint32 CharID) auto row = results.begin(); - bool IsAlt = atoi(row[0]); + bool IsAlt = Strings::ToInt(row[0]); return IsAlt; } @@ -873,19 +873,19 @@ bool BaseGuildManager::QueryWithLogging(std::string query, const char *errmsg) { " FROM `character_data` AS c LEFT JOIN `guild_members` AS g ON c.`id` = g.`char_id` " static void ProcessGuildMember(MySQLRequestRow row, CharGuildInfo &into) { //fields from `characer_` - into.char_id = atoi(row[0]); + into.char_id = Strings::ToInt(row[0]); into.char_name = row[1]; - into.class_ = atoi(row[2]); - into.level = atoi(row[3]); - into.time_last_on = atoul(row[4]); - into.zone_id = atoi(row[5]); + into.class_ = Strings::ToInt(row[2]); + into.level = Strings::ToInt(row[3]); + into.time_last_on = Strings::ToUnsignedInt(row[4]); + into.zone_id = Strings::ToInt(row[5]); //fields from `guild_members`, leave at defaults if missing - into.guild_id = row[6] ? atoi(row[6]) : GUILD_NONE; - into.rank = row[7] ? atoi(row[7]) : (GUILD_MAX_RANK+1); + into.guild_id = row[6] ? Strings::ToInt(row[6]) : GUILD_NONE; + into.rank = row[7] ? Strings::ToInt(row[7]) : (GUILD_MAX_RANK+1); into.tribute_enable = row[8] ? (row[8][0] == '0'?false:true) : false; - into.total_tribute = row[9] ? atoi(row[9]) : 0; - into.last_tribute = row[10]? atoul(row[10]) : 0; //timestamp + into.total_tribute = row[9] ? Strings::ToInt(row[9]) : 0; + into.last_tribute = row[10]? Strings::ToUnsignedInt(row[10]) : 0; //timestamp into.banker = row[11]? (row[11][0] == '0'?false:true) : false; into.public_note = row[12]? row[12] : ""; into.alt = row[13]? (row[13][0] == '0'?false:true) : false; @@ -1258,7 +1258,7 @@ uint32 BaseGuildManager::GetGuildIDByCharacterID(uint32 character_id) } auto row = results.begin(); - auto guild_id = std::stoul(row[0]); + auto guild_id = Strings::ToUnsignedInt(row[0]); return guild_id; } diff --git a/common/http/httplib.h b/common/http/httplib.h index e0cae6b72..e212eb09e 100644 --- a/common/http/httplib.h +++ b/common/http/httplib.h @@ -272,6 +272,8 @@ inline const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *asn1) { #include #endif +#include "../strings.h" + /* * Declaration */ @@ -3812,12 +3814,12 @@ inline bool brotli_decompressor::decompress(const char *data, if (std::regex_match(b, e, cm, re_another_range)) { ssize_t first = -1; if (!cm.str(1).empty()) { - first = static_cast(std::stoll(cm.str(1))); + first = static_cast(Strings::ToBigInt(cm.str(1))); } ssize_t last = -1; if (!cm.str(2).empty()) { - last = static_cast(std::stoll(cm.str(2))); + last = static_cast(Strings::ToBigInt(cm.str(2))); } if (first != -1 && last != -1 && first > last) { diff --git a/common/item_instance.cpp b/common/item_instance.cpp index 0b940c8b2..319e37ad2 100644 --- a/common/item_instance.cpp +++ b/common/item_instance.cpp @@ -358,15 +358,27 @@ int8 EQ::ItemInstance::AvailableAugmentSlot(int32 augment_type) const return (i <= invaug::SOCKET_END) ? i : INVALID_INDEX; } -bool EQ::ItemInstance::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const +bool EQ::ItemInstance::IsAugmentSlotAvailable(int32 augment_type, uint8 slot) const { - if (!m_item || !m_item->IsClassCommon()) - return false; + if (!m_item || !m_item->IsClassCommon()) { + return false; + } - if ((!GetItem(slot) && m_item->AugSlotVisible[slot]) && augtype == -1 || (m_item->AugSlotType[slot] && ((1 << (m_item->AugSlotType[slot] - 1)) & augtype))) { + if ( + ( + !GetItem(slot) && + m_item->AugSlotVisible[slot] + ) && + augment_type == -1 || + ( + m_item->AugSlotType[slot] && + ((1 << (m_item->AugSlotType[slot] - 1)) & augment_type) + ) + ) { return true; } - return false; + + return false; } // Retrieve item inside container @@ -598,7 +610,7 @@ bool EQ::ItemInstance::UpdateOrnamentationInfo() { SetOrnamentHeroModel(ornamentItem->HerosForgeModel); if (strlen(ornamentItem->IDFile) > 2) { - SetOrnamentationIDFile(atoi(&ornamentItem->IDFile[2])); + SetOrnamentationIDFile(Strings::ToInt(&ornamentItem->IDFile[2])); } else { diff --git a/common/item_instance.h b/common/item_instance.h index 02832a6e5..89620d0b5 100644 --- a/common/item_instance.h +++ b/common/item_instance.h @@ -101,8 +101,8 @@ namespace EQ // bool IsAugmentable() const; bool AvailableWearSlot(uint32 aug_wear_slots) const; - int8 AvailableAugmentSlot(int32 augtype) const; - bool IsAugmentSlotAvailable(int32 augtype, uint8 slot) const; + int8 AvailableAugmentSlot(int32 augment_type) const; + bool IsAugmentSlotAvailable(int32 augment_type, uint8 slot) const; inline int32 GetAugmentType() const { return ((m_item) ? m_item->AugType : 0); } inline bool IsExpendable() const { return ((m_item) ? ((m_item->Click.Type == item::ItemEffectExpendable) || (m_item->ItemType == item::ItemTypePotion)) : false); } diff --git a/common/json/json_archive_single_line.h b/common/json/json_archive_single_line.h new file mode 100644 index 000000000..18e55f5bd --- /dev/null +++ b/common/json/json_archive_single_line.h @@ -0,0 +1,1010 @@ +/*! \file json.hpp + \brief JSON input and output archives */ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_ARCHIVES_JSON_SL_HPP_ +#define CEREAL_ARCHIVES_JSON_SL_HPP_ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace cereal +{ + // ###################################################################### + //! An output archive designed to save data to JSON + /*! This archive uses RapidJSON to build serialize data to JSON. + + JSON archives provides a human readable output but at decreased + performance (both in time and space) compared to binary archives. + + JSON archives are only guaranteed to finish flushing their contents + upon destruction and should thus be used in an RAII fashion. + + JSON benefits greatly from name-value pairs, which if present, will + name the nodes in the output. If these are not present, each level + of the output will be given an automatically generated delimited name. + + The precision of the output archive controls the number of decimals output + for floating point numbers and should be sufficiently large (i.e. at least 20) + if there is a desire to have binary equality between the numbers output and + those read in. In general you should expect a loss of precision when going + from floating point to text and back. + + JSON archives do not output the size information for any dynamically sized structure + and instead infer it from the number of children for a node. This means that data + can be hand edited for dynamic sized structures and will still be readable. This + is accomplished through the cereal::SizeTag object, which will cause the archive + to output the data as a JSON array (e.g. marked by [] instead of {}), which indicates + that the container is variable sized and may be edited. + + \ingroup Archives */ + class JSONOutputArchiveSingleLine : public OutputArchive, public traits::TextArchive + { + enum class NodeType { StartObject, InObject, StartArray, InArray }; + + using WriteStream = rapidjson::OStreamWrapper; + + public: + /*! @name Common Functionality + Common use cases for directly interacting with an JSONOutputArchive */ + //! @{ + + //! A class containing various advanced options for the JSON archive + class Options + { + public: + //! Default options +// static Options Default(){ return Options(); } + + //! Default options with no indentation + static Options NoIndent(){ return Options( JSONWriterSL::Writer::kDefaultMaxDecimalPlaces, IndentChar::space, 0 ); } + + //! Default options to output a single line + static Options Default(){ return Options( JSONWriterSL::Writer::kDefaultMaxDecimalPlaces, IndentChar::space, 0, true); } + + //! The character to use for indenting + enum class IndentChar : char + { + space = ' ', + tab = '\t', + newline = '\n', + carriage_return = '\r' + }; + + //! Specify specific options for the JSONOutputArchive + /*! @param precision The precision used for floating point numbers + @param indentChar The type of character to indent with + @param indentLength The number of indentChar to use for indentation + (0 corresponds to no indentation) */ + explicit Options( int precision = 324, + IndentChar indentChar = IndentChar::space, + unsigned int indentLength = 4, + bool singleLine = false) : + itsPrecision( precision ), + itsIndentChar( static_cast(indentChar) ), + itsIndentLength( indentLength ), + itsSingleLine( singleLine ) { } + + private: + friend class JSONOutputArchiveSingleLine; + int itsPrecision; + char itsIndentChar; + unsigned int itsIndentLength; + bool itsSingleLine; + }; + + class JSONWriterSL + { + public: + using PrettyWriter = rapidjson::PrettyWriter; + using Writer = rapidjson::Writer; + + explicit JSONWriterSL(WriteStream &stream, const Options & options) { + if ((prettyPrint = !options.itsSingleLine)) { + new(&prettyWriter) PrettyWriter{stream}; + prettyWriter.SetIndent(options.itsIndentChar, options.itsIndentLength); + prettyWriter.SetMaxDecimalPlaces( options.itsPrecision ); + } else { + new(&writer) Writer{stream}; + writer.SetMaxDecimalPlaces( options.itsPrecision ); + } + } + + ~JSONWriterSL() { + if (prettyPrint) + prettyWriter.~PrettyWriter(); + else + writer.~Writer(); + } + + bool Bool(bool b) { return prettyPrint ? prettyWriter.Bool(b) : writer.Bool(b); } + bool Int(int i) { return prettyPrint ? prettyWriter.Int(i) : writer.Int(i); } + bool Uint(unsigned u) { return prettyPrint ? prettyWriter.Uint(u) : writer.Uint(u); } + bool Int64(int64_t i64) { return prettyPrint ? prettyWriter.Int64(i64) : writer.Int64(i64); } + bool Uint64(uint64_t u64) { return prettyPrint ? prettyWriter.Uint64(u64) : writer.Uint64(u64); } + bool Double(double d) { return prettyPrint ? prettyWriter.Double(d) : writer.Double(d); } + bool Null() { return prettyPrint ? prettyWriter.Null() : writer.Null(); } + + bool String(const char* str, unsigned length) { return prettyPrint ? prettyWriter.String(str, length) + : writer.String(str, length); } + bool String(const char* str) { return prettyPrint ? prettyWriter.String(str) + : writer.String(str); } + + bool StartArray() { return prettyPrint ? prettyWriter.StartArray() : writer.StartArray(); } + bool EndArray() { return prettyPrint ? prettyWriter.EndArray() : writer.EndArray(); } + + bool StartObject() { return prettyPrint ? prettyWriter.StartObject() : writer.StartObject(); } + bool EndObject() { return prettyPrint ? prettyWriter.EndObject() : writer.EndObject(); } + + private: + bool prettyPrint; + union { + Writer writer; + PrettyWriter prettyWriter; + }; + }; + + //! Construct, outputting to the provided stream + /*! @param stream The stream to output to. + @param options The JSON specific options to use. See the Options struct + for the values of default parameters */ + JSONOutputArchiveSingleLine(std::ostream & stream, Options const & options = Options::Default() ) : + OutputArchive(this), + itsWriteStream(stream), + itsWriter(itsWriteStream, options), + itsNextName(nullptr) + { + itsNameCounter.push(0); + itsNodeStack.push(NodeType::StartObject); + } + + //! Destructor, flushes the JSON + ~JSONOutputArchiveSingleLine() CEREAL_NOEXCEPT + { + if (itsNodeStack.top() == NodeType::InObject) + itsWriter.EndObject(); + else if (itsNodeStack.top() == NodeType::InArray) + itsWriter.EndArray(); + } + + //! Saves some binary data, encoded as a base64 string, with an optional name + /*! This will create a new node, optionally named, and insert a value that consists of + the data encoded as a base64 string */ + void saveBinaryValue( const void * data, size_t size, const char * name = nullptr ) + { + setNextName( name ); + writeName(); + + auto base64string = base64::encode( reinterpret_cast( data ), size ); + saveValue( base64string ); + }; + + //! @} + /*! @name Internal Functionality + Functionality designed for use by those requiring control over the inner mechanisms of + the JSONOutputArchive */ + //! @{ + + //! Starts a new node in the JSON output + /*! The node can optionally be given a name by calling setNextName prior + to creating the node + + Nodes only need to be started for types that are themselves objects or arrays */ + void startNode() + { + writeName(); + itsNodeStack.push(NodeType::StartObject); + itsNameCounter.push(0); + } + + //! Designates the most recently added node as finished + void finishNode() + { + // if we ended up serializing an empty object or array, writeName + // will never have been called - so start and then immediately end + // the object/array. + // + // We'll also end any object/arrays we happen to be in + switch(itsNodeStack.top()) + { + case NodeType::StartArray: + itsWriter.StartArray(); + case NodeType::InArray: + itsWriter.EndArray(); + break; + case NodeType::StartObject: + itsWriter.StartObject(); + case NodeType::InObject: + itsWriter.EndObject(); + break; + } + + itsNodeStack.pop(); + itsNameCounter.pop(); + } + + //! Sets the name for the next node created with startNode + void setNextName( const char * name ) + { + itsNextName = name; + } + + //! Saves a bool to the current node + void saveValue(bool b) { itsWriter.Bool(b); } + //! Saves an int to the current node + void saveValue(int i) { itsWriter.Int(i); } + //! Saves a uint to the current node + void saveValue(unsigned u) { itsWriter.Uint(u); } + //! Saves an int64 to the current node + void saveValue(int64_t i64) { itsWriter.Int64(i64); } + //! Saves a uint64 to the current node + void saveValue(uint64_t u64) { itsWriter.Uint64(u64); } + //! Saves a double to the current node + void saveValue(double d) { itsWriter.Double(d); } + //! Saves a string to the current node + void saveValue(std::string const & s) { itsWriter.String(s.c_str(), static_cast( s.size() )); } + //! Saves a const char * to the current node + void saveValue(char const * s) { itsWriter.String(s); } + //! Saves a nullptr to the current node + void saveValue(std::nullptr_t) { itsWriter.Null(); } + + private: + // Some compilers/OS have difficulty disambiguating the above for various flavors of longs, so we provide + // special overloads to handle these cases. + + //! 32 bit signed long saving to current node + template ::value> = traits::sfinae> inline + void saveLong(T l){ saveValue( static_cast( l ) ); } + + //! non 32 bit signed long saving to current node + template ::value> = traits::sfinae> inline + void saveLong(T l){ saveValue( static_cast( l ) ); } + + //! 32 bit unsigned long saving to current node + template ::value> = traits::sfinae> inline + void saveLong(T lu){ saveValue( static_cast( lu ) ); } + + //! non 32 bit unsigned long saving to current node + template ::value> = traits::sfinae> inline + void saveLong(T lu){ saveValue( static_cast( lu ) ); } + + public: +#ifdef _MSC_VER + //! MSVC only long overload to current node + void saveValue( unsigned long lu ){ saveLong( lu ); }; +#else // _MSC_VER + //! Serialize a long if it would not be caught otherwise + template ::value, + !std::is_same::value, + !std::is_same::value> = traits::sfinae> inline + void saveValue( T t ){ saveLong( t ); } + + //! Serialize an unsigned long if it would not be caught otherwise + template ::value, + !std::is_same::value, + !std::is_same::value> = traits::sfinae> inline + void saveValue( T t ){ saveLong( t ); } +#endif // _MSC_VER + + //! Save exotic arithmetic as strings to current node + /*! Handles long long (if distinct from other types), unsigned long (if distinct), and long double */ + template ::value, + !std::is_same::value, + !std::is_same::value, + !std::is_same::value, + !std::is_same::value, + (sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long))> = traits::sfinae> inline + void saveValue(T const & t) + { + std::stringstream ss; ss.precision( std::numeric_limits::max_digits10 ); + ss << t; + saveValue( ss.str() ); + } + + //! Write the name of the upcoming node and prepare object/array state + /*! Since writeName is called for every value that is output, regardless of + whether it has a name or not, it is the place where we will do a deferred + check of our node state and decide whether we are in an array or an object. + + The general workflow of saving to the JSON archive is: + + 1. (optional) Set the name for the next node to be created, usually done by an NVP + 2. Start the node + 3. (if there is data to save) Write the name of the node (this function) + 4. (if there is data to save) Save the data (with saveValue) + 5. Finish the node + */ + void writeName() + { + NodeType const & nodeType = itsNodeStack.top(); + + // Start up either an object or an array, depending on state + if(nodeType == NodeType::StartArray) + { + itsWriter.StartArray(); + itsNodeStack.top() = NodeType::InArray; + } + else if(nodeType == NodeType::StartObject) + { + itsNodeStack.top() = NodeType::InObject; + itsWriter.StartObject(); + } + + // Array types do not output names + if(nodeType == NodeType::InArray) return; + + if(itsNextName == nullptr) + { + std::string name = "value" + std::to_string( itsNameCounter.top()++ ) + "\0"; + saveValue(name); + } + else + { + saveValue(itsNextName); + itsNextName = nullptr; + } + } + + //! Designates that the current node should be output as an array, not an object + void makeArray() + { + itsNodeStack.top() = NodeType::StartArray; + } + + //! @} + + private: + WriteStream itsWriteStream; //!< Rapidjson write stream + JSONWriterSL itsWriter; //!< Rapidjson writer + char const * itsNextName; //!< The next name + std::stack itsNameCounter; //!< Counter for creating unique names for unnamed nodes + std::stack itsNodeStack; + }; // JSONOutputArchive + + // ###################################################################### + //! An input archive designed to load data from JSON + /*! This archive uses RapidJSON to read in a JSON archive. + + As with the output JSON archive, the preferred way to use this archive is in + an RAII fashion, ensuring its destruction after all data has been read. + + Input JSON should have been produced by the JSONOutputArchive. Data can + only be added to dynamically sized containers (marked by JSON arrays) - + the input archive will determine their size by looking at the number of child nodes. + Only JSON originating from a JSONOutputArchive is officially supported, but data + from other sources may work if properly formatted. + + The JSONInputArchiveSingleLine does not require that nodes are loaded in the same + order they were saved by JSONOutputArchive. Using name value pairs (NVPs), + it is possible to load in an out of order fashion or otherwise skip/select + specific nodes to load. + + The default behavior of the input archive is to read sequentially starting + with the first node and exploring its children. When a given NVP does + not match the read in name for a node, the archive will search for that + node at the current level and load it if it exists. After loading an out of + order node, the archive will then proceed back to loading sequentially from + its new position. + + Consider this simple example where loading of some data is skipped: + + @code{cpp} + // imagine the input file has someData(1-9) saved in order at the top level node + ar( someData1, someData2, someData3 ); // XML loads in the order it sees in the file + ar( cereal::make_nvp( "hello", someData6 ) ); // NVP given does not + // match expected NVP name, so we search + // for the given NVP and load that value + ar( someData7, someData8, someData9 ); // with no NVP given, loading resumes at its + // current location, proceeding sequentially + @endcode + + \ingroup Archives */ + class JSONInputArchiveSingleLine : public InputArchive, public traits::TextArchive + { + private: + using ReadStream = rapidjson::IStreamWrapper; + typedef rapidjson::GenericValue> JSONValue; + typedef JSONValue::ConstMemberIterator MemberIterator; + typedef JSONValue::ConstValueIterator ValueIterator; + typedef rapidjson::Document::GenericValue GenericValue; + + public: + /*! @name Common Functionality + Common use cases for directly interacting with an JSONInputArchiveSingleLine */ + //! @{ + + //! Construct, reading from the provided stream + /*! @param stream The stream to read from */ + JSONInputArchiveSingleLine(std::istream & stream) : + InputArchive(this), + itsNextName( nullptr ), + itsReadStream(stream) + { + itsDocument.ParseStream<>(itsReadStream); + if (itsDocument.IsArray()) + itsIteratorStack.emplace_back(itsDocument.Begin(), itsDocument.End()); + else + itsIteratorStack.emplace_back(itsDocument.MemberBegin(), itsDocument.MemberEnd()); + } + + ~JSONInputArchiveSingleLine() CEREAL_NOEXCEPT = default; + + //! Loads some binary data, encoded as a base64 string + /*! This will automatically start and finish a node to load the data, and can be called directly by + users. + + Note that this follows the same ordering rules specified in the class description in regards + to loading in/out of order */ + void loadBinaryValue( void * data, size_t size, const char * name = nullptr ) + { + itsNextName = name; + + std::string encoded; + loadValue( encoded ); + auto decoded = base64::decode( encoded ); + + if( size != decoded.size() ) + throw Exception("Decoded binary data size does not match specified size"); + + std::memcpy( data, decoded.data(), decoded.size() ); + itsNextName = nullptr; + }; + + private: + //! @} + /*! @name Internal Functionality + Functionality designed for use by those requiring control over the inner mechanisms of + the JSONInputArchiveSingleLine */ + //! @{ + + //! An internal iterator that handles both array and object types + /*! This class is a variant and holds both types of iterators that + rapidJSON supports - one for arrays and one for objects. */ + class Iterator + { + public: + Iterator() : itsIndex( 0 ), itsType(Null_) {} + + Iterator(MemberIterator begin, MemberIterator end) : + itsMemberItBegin(begin), itsMemberItEnd(end), itsIndex(0), itsType(Member) + { } + + Iterator(ValueIterator begin, ValueIterator end) : + itsValueItBegin(begin), itsValueItEnd(end), itsIndex(0), itsType(Value) + { } + + //! Advance to the next node + Iterator & operator++() + { + ++itsIndex; + return *this; + } + + //! Get the value of the current node + GenericValue const & value() + { + switch(itsType) + { + case Value : return itsValueItBegin[itsIndex]; + case Member: return itsMemberItBegin[itsIndex].value; + default: throw cereal::Exception("Invalid Iterator Type!"); + } + } + + //! Get the name of the current node, or nullptr if it has no name + const char * name() const + { + if( itsType == Member && (itsMemberItBegin + itsIndex) != itsMemberItEnd ) + return itsMemberItBegin[itsIndex].name.GetString(); + else + return nullptr; + } + + //! Adjust our position such that we are at the node with the given name + /*! @throws Exception if no such named node exists */ + inline void search( const char * searchName ) + { + const auto len = std::strlen( searchName ); + size_t index = 0; + for( auto it = itsMemberItBegin; it != itsMemberItEnd; ++it, ++index ) + { + const auto currentName = it->name.GetString(); + if( ( std::strncmp( searchName, currentName, len ) == 0 ) && + ( std::strlen( currentName ) == len ) ) + { + itsIndex = index; + return; + } + } + + throw Exception("JSON Parsing failed - provided NVP (" + std::string(searchName) + ") not found"); + } + + private: + MemberIterator itsMemberItBegin, itsMemberItEnd; //!< The member iterator (object) + ValueIterator itsValueItBegin, itsValueItEnd; //!< The value iterator (array) + size_t itsIndex; //!< The current index of this iterator + enum Type {Value, Member, Null_} itsType; //!< Whether this holds values (array) or members (objects) or nothing + }; + + //! Searches for the expectedName node if it doesn't match the actualName + /*! This needs to be called before every load or node start occurs. This function will + check to see if an NVP has been provided (with setNextName) and if so, see if that name matches the actual + next name given. If the names do not match, it will search in the current level of the JSON for that name. + If the name is not found, an exception will be thrown. + + Resets the NVP name after called. + + @throws Exception if an expectedName is given and not found */ + inline void search() + { + // The name an NVP provided with setNextName() + if( itsNextName ) + { + // The actual name of the current node + auto const actualName = itsIteratorStack.back().name(); + + // Do a search if we don't see a name coming up, or if the names don't match + if( !actualName || std::strcmp( itsNextName, actualName ) != 0 ) + itsIteratorStack.back().search( itsNextName ); + } + + itsNextName = nullptr; + } + + public: + //! Starts a new node, going into its proper iterator + /*! This places an iterator for the next node to be parsed onto the iterator stack. If the next + node is an array, this will be a value iterator, otherwise it will be a member iterator. + + By default our strategy is to start with the document root node and then recursively iterate through + all children in the order they show up in the document. + We don't need to know NVPs to do this; we'll just blindly load in the order things appear in. + + If we were given an NVP, we will search for it if it does not match our the name of the next node + that would normally be loaded. This functionality is provided by search(). */ + void startNode() + { + search(); + + if(itsIteratorStack.back().value().IsArray()) + itsIteratorStack.emplace_back(itsIteratorStack.back().value().Begin(), itsIteratorStack.back().value().End()); + else + itsIteratorStack.emplace_back(itsIteratorStack.back().value().MemberBegin(), itsIteratorStack.back().value().MemberEnd()); + } + + //! Finishes the most recently started node + void finishNode() + { + itsIteratorStack.pop_back(); + ++itsIteratorStack.back(); + } + + //! Retrieves the current node name + /*! @return nullptr if no name exists */ + const char * getNodeName() const + { + return itsIteratorStack.back().name(); + } + + //! Sets the name for the next node created with startNode + void setNextName( const char * name ) + { + itsNextName = name; + } + + //! Loads a value from the current node - small signed overload + template ::value, + sizeof(T) < sizeof(int64_t)> = traits::sfinae> inline + void loadValue(T & val) + { + search(); + + val = static_cast( itsIteratorStack.back().value().GetInt() ); + ++itsIteratorStack.back(); + } + + //! Loads a value from the current node - small unsigned overload + template ::value, + sizeof(T) < sizeof(uint64_t), + !std::is_same::value> = traits::sfinae> inline + void loadValue(T & val) + { + search(); + + val = static_cast( itsIteratorStack.back().value().GetUint() ); + ++itsIteratorStack.back(); + } + + //! Loads a value from the current node - bool overload + void loadValue(bool & val) { search(); val = itsIteratorStack.back().value().GetBool(); ++itsIteratorStack.back(); } + //! Loads a value from the current node - int64 overload + void loadValue(int64_t & val) { search(); val = itsIteratorStack.back().value().GetInt64(); ++itsIteratorStack.back(); } + //! Loads a value from the current node - uint64 overload + void loadValue(uint64_t & val) { search(); val = itsIteratorStack.back().value().GetUint64(); ++itsIteratorStack.back(); } + //! Loads a value from the current node - float overload + void loadValue(float & val) { search(); val = static_cast(itsIteratorStack.back().value().GetDouble()); ++itsIteratorStack.back(); } + //! Loads a value from the current node - double overload + void loadValue(double & val) { search(); val = itsIteratorStack.back().value().GetDouble(); ++itsIteratorStack.back(); } + //! Loads a value from the current node - string overload + void loadValue(std::string & val) { search(); val = itsIteratorStack.back().value().GetString(); ++itsIteratorStack.back(); } + //! Loads a nullptr from the current node + void loadValue(std::nullptr_t&) { search(); CEREAL_RAPIDJSON_ASSERT(itsIteratorStack.back().value().IsNull()); ++itsIteratorStack.back(); } + + // Special cases to handle various flavors of long, which tend to conflict with + // the int32_t or int64_t on various compiler/OS combinations. MSVC doesn't need any of this. +#ifndef _MSC_VER + private: + //! 32 bit signed long loading from current node + template inline + typename std::enable_if::value, void>::type + loadLong(T & l){ loadValue( reinterpret_cast( l ) ); } + + //! non 32 bit signed long loading from current node + template inline + typename std::enable_if::value, void>::type + loadLong(T & l){ loadValue( reinterpret_cast( l ) ); } + + //! 32 bit unsigned long loading from current node + template inline + typename std::enable_if::value, void>::type + loadLong(T & lu){ loadValue( reinterpret_cast( lu ) ); } + + //! non 32 bit unsigned long loading from current node + template inline + typename std::enable_if::value, void>::type + loadLong(T & lu){ loadValue( reinterpret_cast( lu ) ); } + + public: + //! Serialize a long if it would not be caught otherwise + template inline + typename std::enable_if::value && + sizeof(T) >= sizeof(std::int64_t) && + !std::is_same::value, void>::type + loadValue( T & t ){ loadLong(t); } + + //! Serialize an unsigned long if it would not be caught otherwise + template inline + typename std::enable_if::value && + sizeof(T) >= sizeof(std::uint64_t) && + !std::is_same::value, void>::type + loadValue( T & t ){ loadLong(t); } +#endif // _MSC_VER + + private: + //! Convert a string to a long long + void stringToNumber( std::string const & str, long long & val ) { val = std::stoll( str ); } + //! Convert a string to an unsigned long long + void stringToNumber( std::string const & str, unsigned long long & val ) { val = std::stoull( str ); } + //! Convert a string to a long double + void stringToNumber( std::string const & str, long double & val ) { val = std::stold( str ); } + + public: + //! Loads a value from the current node - long double and long long overloads + template ::value, + !std::is_same::value, + !std::is_same::value, + !std::is_same::value, + !std::is_same::value, + (sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long))> = traits::sfinae> + inline void loadValue(T & val) + { + std::string encoded; + loadValue( encoded ); + stringToNumber( encoded, val ); + } + + //! Loads the size for a SizeTag + void loadSize(size_type & size) + { + if (itsIteratorStack.size() == 1) + size = itsDocument.Size(); + else + size = (itsIteratorStack.rbegin() + 1)->value().Size(); + } + + //! @} + + private: + const char * itsNextName; //!< Next name set by NVP + ReadStream itsReadStream; //!< Rapidjson write stream + std::vector itsIteratorStack; //!< 'Stack' of rapidJSON iterators + rapidjson::Document itsDocument; //!< Rapidjson document + }; + + // ###################################################################### + // JSONArchive prologue and epilogue functions + // ###################################################################### + + // ###################################################################### + //! Prologue for NVPs for JSON archives + /*! NVPs do not start or finish nodes - they just set up the names */ + template inline + void prologue(JSONOutputArchiveSingleLine &, NameValuePair const & ) + { } + + //! Prologue for NVPs for JSON archives + template inline + void prologue( JSONInputArchiveSingleLine &, NameValuePair const & ) + { } + + // ###################################################################### + //! Epilogue for NVPs for JSON archives + /*! NVPs do not start or finish nodes - they just set up the names */ + template inline + void epilogue(JSONOutputArchiveSingleLine &, NameValuePair const & ) + { } + + //! Epilogue for NVPs for JSON archives + /*! NVPs do not start or finish nodes - they just set up the names */ + template inline + void epilogue( JSONInputArchiveSingleLine &, NameValuePair const & ) + { } + + // ###################################################################### + //! Prologue for SizeTags for JSON archives + /*! SizeTags are strictly ignored for JSON, they just indicate + that the current node should be made into an array */ + template inline + void prologue(JSONOutputArchiveSingleLine & ar, SizeTag const & ) + { + ar.makeArray(); + } + + //! Prologue for SizeTags for JSON archives + template inline + void prologue( JSONInputArchiveSingleLine &, SizeTag const & ) + { } + + // ###################################################################### + //! Epilogue for SizeTags for JSON archives + /*! SizeTags are strictly ignored for JSON */ + template inline + void epilogue(JSONOutputArchiveSingleLine &, SizeTag const & ) + { } + + //! Epilogue for SizeTags for JSON archives + template inline + void epilogue( JSONInputArchiveSingleLine &, SizeTag const & ) + { } + + // ###################################################################### + //! Prologue for all other types for JSON archives (except minimal types) + /*! Starts a new node, named either automatically or by some NVP, + that may be given data by the type about to be archived + + Minimal types do not start or finish nodes */ + template ::value, + !traits::has_minimal_base_class_serialization::value, + !traits::has_minimal_output_serialization::value> = traits::sfinae> + inline void prologue(JSONOutputArchiveSingleLine & ar, T const & ) + { + ar.startNode(); + } + + //! Prologue for all other types for JSON archives + template ::value, + !traits::has_minimal_base_class_serialization::value, + !traits::has_minimal_input_serialization::value> = traits::sfinae> + inline void prologue( JSONInputArchiveSingleLine & ar, T const & ) + { + ar.startNode(); + } + + // ###################################################################### + //! Epilogue for all other types other for JSON archives (except minimal types) + /*! Finishes the node created in the prologue + + Minimal types do not start or finish nodes */ + template ::value, + !traits::has_minimal_base_class_serialization::value, + !traits::has_minimal_output_serialization::value> = traits::sfinae> + inline void epilogue(JSONOutputArchiveSingleLine & ar, T const & ) + { + ar.finishNode(); + } + + //! Epilogue for all other types other for JSON archives + template ::value, + !traits::has_minimal_base_class_serialization::value, + !traits::has_minimal_input_serialization::value> = traits::sfinae> + inline void epilogue( JSONInputArchiveSingleLine & ar, T const & ) + { + ar.finishNode(); + } + + // ###################################################################### + //! Prologue for arithmetic types for JSON archives + inline + void prologue(JSONOutputArchiveSingleLine & ar, std::nullptr_t const & ) + { + ar.writeName(); + } + + //! Prologue for arithmetic types for JSON archives + inline + void prologue( JSONInputArchiveSingleLine &, std::nullptr_t const & ) + { } + + // ###################################################################### + //! Epilogue for arithmetic types for JSON archives + inline + void epilogue(JSONOutputArchiveSingleLine &, std::nullptr_t const & ) + { } + + //! Epilogue for arithmetic types for JSON archives + inline + void epilogue( JSONInputArchiveSingleLine &, std::nullptr_t const & ) + { } + + // ###################################################################### + //! Prologue for arithmetic types for JSON archives + template ::value> = traits::sfinae> inline + void prologue(JSONOutputArchiveSingleLine & ar, T const & ) + { + ar.writeName(); + } + + //! Prologue for arithmetic types for JSON archives + template ::value> = traits::sfinae> inline + void prologue( JSONInputArchiveSingleLine &, T const & ) + { } + + // ###################################################################### + //! Epilogue for arithmetic types for JSON archives + template ::value> = traits::sfinae> inline + void epilogue(JSONOutputArchiveSingleLine &, T const & ) + { } + + //! Epilogue for arithmetic types for JSON archives + template ::value> = traits::sfinae> inline + void epilogue( JSONInputArchiveSingleLine &, T const & ) + { } + + // ###################################################################### + //! Prologue for strings for JSON archives + template inline + void prologue(JSONOutputArchiveSingleLine & ar, std::basic_string const &) + { + ar.writeName(); + } + + //! Prologue for strings for JSON archives + template inline + void prologue(JSONInputArchiveSingleLine &, std::basic_string const &) + { } + + // ###################################################################### + //! Epilogue for strings for JSON archives + template inline + void epilogue(JSONOutputArchiveSingleLine &, std::basic_string const &) + { } + + //! Epilogue for strings for JSON archives + template inline + void epilogue(JSONInputArchiveSingleLine &, std::basic_string const &) + { } + + // ###################################################################### + // Common JSONArchive serialization functions + // ###################################################################### + //! Serializing NVP types to JSON + template inline + void CEREAL_SAVE_FUNCTION_NAME(JSONOutputArchiveSingleLine & ar, NameValuePair const & t ) + { + ar.setNextName( t.name ); + ar( t.value ); + } + + template inline + void CEREAL_LOAD_FUNCTION_NAME( JSONInputArchiveSingleLine & ar, NameValuePair & t ) + { + ar.setNextName( t.name ); + ar( t.value ); + } + + //! Saving for nullptr to JSON + inline + void CEREAL_SAVE_FUNCTION_NAME(JSONOutputArchiveSingleLine & ar, std::nullptr_t const & t) + { + ar.saveValue( t ); + } + + //! Loading arithmetic from JSON + inline + void CEREAL_LOAD_FUNCTION_NAME(JSONInputArchiveSingleLine & ar, std::nullptr_t & t) + { + ar.loadValue( t ); + } + + //! Saving for arithmetic to JSON + template ::value> = traits::sfinae> inline + void CEREAL_SAVE_FUNCTION_NAME(JSONOutputArchiveSingleLine & ar, T const & t) + { + ar.saveValue( t ); + } + + //! Loading arithmetic from JSON + template ::value> = traits::sfinae> inline + void CEREAL_LOAD_FUNCTION_NAME(JSONInputArchiveSingleLine & ar, T & t) + { + ar.loadValue( t ); + } + + //! saving string to JSON + template inline + void CEREAL_SAVE_FUNCTION_NAME(JSONOutputArchiveSingleLine & ar, std::basic_string const & str) + { + ar.saveValue( str ); + } + + //! loading string from JSON + template inline + void CEREAL_LOAD_FUNCTION_NAME(JSONInputArchiveSingleLine & ar, std::basic_string & str) + { + ar.loadValue( str ); + } + + // ###################################################################### + //! Saving SizeTags to JSON + template inline + void CEREAL_SAVE_FUNCTION_NAME(JSONOutputArchiveSingleLine &, SizeTag const & ) + { + // nothing to do here, we don't explicitly save the size + } + + //! Loading SizeTags from JSON + template inline + void CEREAL_LOAD_FUNCTION_NAME( JSONInputArchiveSingleLine & ar, SizeTag & st ) + { + ar.loadSize( st.size ); + } +} // namespace cereal + +// register archives for polymorphic support +CEREAL_REGISTER_ARCHIVE(cereal::JSONInputArchiveSingleLine) +CEREAL_REGISTER_ARCHIVE(cereal::JSONOutputArchiveSingleLine) + +// tie input and output archives together +CEREAL_SETUP_ARCHIVE_TRAITS(cereal::JSONInputArchiveSingleLine, cereal::JSONOutputArchiveSingleLine) + +#endif // CEREAL_ARCHIVES_JSON_SL_HPP_ diff --git a/common/misc.cpp b/common/misc.cpp index b9dc31d28..61f21a589 100644 --- a/common/misc.cpp +++ b/common/misc.cpp @@ -18,6 +18,7 @@ #include "misc.h" #include "types.h" #include +#include "strings.h" std::map DBFieldNames; @@ -150,7 +151,7 @@ static char *temp=nullptr; return false; } ptr++; - uint32 id = atoi(field[id_pos].c_str()); + uint32 id = Strings::ToInt(field[id_pos].c_str()); items[id]=field; for(i=0;i<10;i++) { diff --git a/common/misc_functions.cpp b/common/misc_functions.cpp index a85ca9c2b..5c1584193 100644 --- a/common/misc_functions.cpp +++ b/common/misc_functions.cpp @@ -21,6 +21,7 @@ #include "misc_functions.h" #include #include +#include "strings.h" #ifndef WIN32 #include @@ -130,7 +131,7 @@ bool ParseAddress(const char* iAddress, uint32* oIP, uint16* oPort, char* errbuf if (*oIP == 0) return false; if (oPort) - *oPort = atoi(sep.arg[1]); + *oPort = Strings::ToInt(sep.arg[1]); return true; } return false; diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index a1ae18505..693b6b46b 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -2095,13 +2095,13 @@ namespace SoF } else { - val = atoi(&emu->lastName[2]); + val = Strings::ToInt(&emu->lastName[2]); } } else { sep[0] = nullptr; - ofs = atoi(&emu->lastName[2]); + ofs = Strings::ToInt(&emu->lastName[2]); sep[0] = '='; if ((sep[1] < '0') || (sep[1] > '9')) { @@ -2109,7 +2109,7 @@ namespace SoF } else { - val = atoi(&sep[1]); + val = Strings::ToInt(&sep[1]); } } diff --git a/common/platform.cpp b/common/platform.cpp index b126e6d33..cdfad9aed 100644 --- a/common/platform.cpp +++ b/common/platform.cpp @@ -22,26 +22,31 @@ EQEmuExePlatform exe_platform = ExePlatformNone; -void RegisterExecutablePlatform(EQEmuExePlatform p) { +void RegisterExecutablePlatform(EQEmuExePlatform p) +{ exe_platform = p; } -const EQEmuExePlatform& GetExecutablePlatform() { +const EQEmuExePlatform &GetExecutablePlatform() +{ return exe_platform; } -/** - * @return - */ -int GetExecutablePlatformInt(){ +int GetExecutablePlatformInt() +{ return exe_platform; } -/** - * Returns platform name by string - * - * @return - */ +bool IsWorld() +{ + return exe_platform == EQEmuExePlatform::ExePlatformWorld; +} + +bool IsQueryServ() +{ + return exe_platform == EQEmuExePlatform::ExePlatformQueryServ; +} + std::string GetPlatformName() { switch (GetExecutablePlatformInt()) { diff --git a/common/platform.h b/common/platform.h index a69738ff6..35569c8bf 100644 --- a/common/platform.h +++ b/common/platform.h @@ -44,5 +44,7 @@ void RegisterExecutablePlatform(EQEmuExePlatform p); const EQEmuExePlatform& GetExecutablePlatform(); int GetExecutablePlatformInt(); std::string GetPlatformName(); +bool IsWorld(); +bool IsQueryServ(); #endif diff --git a/common/ptimer.cpp b/common/ptimer.cpp index e5e5f438e..437f82f86 100644 --- a/common/ptimer.cpp +++ b/common/ptimer.cpp @@ -288,7 +288,7 @@ bool PTimerList::Load(Database *db) { PersistentTimer *cur; for (auto row = results.begin(); row != results.end(); ++row) { - type = atoi(row[0]); + type = Strings::ToInt(row[0]); start_time = strtoul(row[1], nullptr, 10); timer_time = strtoul(row[2], nullptr, 10); enabled = (row[3][0] == '1'); diff --git a/common/repositories/base/base_bot_data_repository.h b/common/repositories/base/base_bot_data_repository.h index da0b67af7..b4d2c47b2 100644 --- a/common/repositories/base/base_bot_data_repository.h +++ b/common/repositories/base/base_bot_data_repository.h @@ -69,6 +69,7 @@ public: int32_t expansion_bitmask; uint8_t enforce_spell_settings; uint8_t archery_setting; + uint32_t caster_range; }; static std::string PrimaryKey() @@ -129,6 +130,7 @@ public: "expansion_bitmask", "enforce_spell_settings", "archery_setting", + "caster_range", }; } @@ -185,6 +187,7 @@ public: "expansion_bitmask", "enforce_spell_settings", "archery_setting", + "caster_range", }; } @@ -275,6 +278,7 @@ public: e.expansion_bitmask = -1; e.enforce_spell_settings = 0; e.archery_setting = 0; + e.caster_range = 0; return e; } @@ -361,6 +365,7 @@ public: e.expansion_bitmask = static_cast(atoi(row[47])); e.enforce_spell_settings = static_cast(strtoul(row[48], nullptr, 10)); e.archery_setting = static_cast(strtoul(row[49], nullptr, 10)); + e.caster_range = static_cast(strtoul(row[50], nullptr, 10)); return e; } @@ -443,6 +448,7 @@ public: v.push_back(columns[47] + " = " + std::to_string(e.expansion_bitmask)); v.push_back(columns[48] + " = " + std::to_string(e.enforce_spell_settings)); v.push_back(columns[49] + " = " + std::to_string(e.archery_setting)); + v.push_back(columns[50] + " = " + std::to_string(e.caster_range)); auto results = db.QueryDatabase( fmt::format( @@ -514,6 +520,7 @@ public: v.push_back(std::to_string(e.expansion_bitmask)); v.push_back(std::to_string(e.enforce_spell_settings)); v.push_back(std::to_string(e.archery_setting)); + v.push_back(std::to_string(e.caster_range)); auto results = db.QueryDatabase( fmt::format( @@ -593,6 +600,7 @@ public: v.push_back(std::to_string(e.expansion_bitmask)); v.push_back(std::to_string(e.enforce_spell_settings)); v.push_back(std::to_string(e.archery_setting)); + v.push_back(std::to_string(e.caster_range)); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } @@ -676,6 +684,7 @@ public: e.expansion_bitmask = static_cast(atoi(row[47])); e.enforce_spell_settings = static_cast(strtoul(row[48], nullptr, 10)); e.archery_setting = static_cast(strtoul(row[49], nullptr, 10)); + e.caster_range = static_cast(strtoul(row[50], nullptr, 10)); all_entries.push_back(e); } @@ -750,6 +759,7 @@ public: e.expansion_bitmask = static_cast(atoi(row[47])); e.enforce_spell_settings = static_cast(strtoul(row[48], nullptr, 10)); e.archery_setting = static_cast(strtoul(row[49], nullptr, 10)); + e.caster_range = static_cast(strtoul(row[50], nullptr, 10)); all_entries.push_back(e); } diff --git a/common/repositories/base/base_eventlog_repository.h b/common/repositories/base/base_eventlog_repository.h deleted file mode 100644 index c2b008106..000000000 --- a/common/repositories/base/base_eventlog_repository.h +++ /dev/null @@ -1,412 +0,0 @@ -/** - * DO NOT MODIFY THIS FILE - * - * This repository was automatically generated and is NOT to be modified directly. - * Any repository modifications are meant to be made to the repository extending the base. - * Any modifications to base repositories are to be made by the generator only - * - * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories - */ - -#ifndef EQEMU_BASE_EVENTLOG_REPOSITORY_H -#define EQEMU_BASE_EVENTLOG_REPOSITORY_H - -#include "../../database.h" -#include "../../strings.h" -#include - -class BaseEventlogRepository { -public: - struct Eventlog { - uint32_t id; - std::string accountname; - uint32_t accountid; - int32_t status; - std::string charname; - std::string target; - std::string time; - std::string descriptiontype; - std::string description; - int32_t event_nid; - }; - - static std::string PrimaryKey() - { - return std::string("id"); - } - - static std::vector Columns() - { - return { - "id", - "accountname", - "accountid", - "status", - "charname", - "target", - "time", - "descriptiontype", - "description", - "event_nid", - }; - } - - static std::vector SelectColumns() - { - return { - "id", - "accountname", - "accountid", - "status", - "charname", - "target", - "time", - "descriptiontype", - "description", - "event_nid", - }; - } - - static std::string ColumnsRaw() - { - return std::string(Strings::Implode(", ", Columns())); - } - - static std::string SelectColumnsRaw() - { - return std::string(Strings::Implode(", ", SelectColumns())); - } - - static std::string TableName() - { - return std::string("eventlog"); - } - - static std::string BaseSelect() - { - return fmt::format( - "SELECT {} FROM {}", - SelectColumnsRaw(), - TableName() - ); - } - - static std::string BaseInsert() - { - return fmt::format( - "INSERT INTO {} ({}) ", - TableName(), - ColumnsRaw() - ); - } - - static Eventlog NewEntity() - { - Eventlog e{}; - - e.id = 0; - e.accountname = ""; - e.accountid = 0; - e.status = 0; - e.charname = ""; - e.target = "None"; - e.time = std::time(nullptr); - e.descriptiontype = ""; - e.description = ""; - e.event_nid = 0; - - return e; - } - - static Eventlog GetEventlog( - const std::vector &eventlogs, - int eventlog_id - ) - { - for (auto &eventlog : eventlogs) { - if (eventlog.id == eventlog_id) { - return eventlog; - } - } - - return NewEntity(); - } - - static Eventlog FindOne( - Database& db, - int eventlog_id - ) - { - auto results = db.QueryDatabase( - fmt::format( - "{} WHERE id = {} LIMIT 1", - BaseSelect(), - eventlog_id - ) - ); - - auto row = results.begin(); - if (results.RowCount() == 1) { - Eventlog e{}; - - e.id = static_cast(strtoul(row[0], nullptr, 10)); - e.accountname = row[1] ? row[1] : ""; - e.accountid = static_cast(strtoul(row[2], nullptr, 10)); - e.status = static_cast(atoi(row[3])); - e.charname = row[4] ? row[4] : ""; - e.target = row[5] ? row[5] : ""; - e.time = row[6] ? row[6] : ""; - e.descriptiontype = row[7] ? row[7] : ""; - e.description = row[8] ? row[8] : ""; - e.event_nid = static_cast(atoi(row[9])); - - return e; - } - - return NewEntity(); - } - - static int DeleteOne( - Database& db, - int eventlog_id - ) - { - auto results = db.QueryDatabase( - fmt::format( - "DELETE FROM {} WHERE {} = {}", - TableName(), - PrimaryKey(), - eventlog_id - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static int UpdateOne( - Database& db, - const Eventlog &e - ) - { - std::vector v; - - auto columns = Columns(); - - v.push_back(columns[1] + " = '" + Strings::Escape(e.accountname) + "'"); - v.push_back(columns[2] + " = " + std::to_string(e.accountid)); - v.push_back(columns[3] + " = " + std::to_string(e.status)); - v.push_back(columns[4] + " = '" + Strings::Escape(e.charname) + "'"); - v.push_back(columns[5] + " = '" + Strings::Escape(e.target) + "'"); - v.push_back(columns[6] + " = '" + Strings::Escape(e.time) + "'"); - v.push_back(columns[7] + " = '" + Strings::Escape(e.descriptiontype) + "'"); - v.push_back(columns[8] + " = '" + Strings::Escape(e.description) + "'"); - v.push_back(columns[9] + " = " + std::to_string(e.event_nid)); - - auto results = db.QueryDatabase( - fmt::format( - "UPDATE {} SET {} WHERE {} = {}", - TableName(), - Strings::Implode(", ", v), - PrimaryKey(), - e.id - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static Eventlog InsertOne( - Database& db, - Eventlog e - ) - { - std::vector v; - - v.push_back(std::to_string(e.id)); - v.push_back("'" + Strings::Escape(e.accountname) + "'"); - v.push_back(std::to_string(e.accountid)); - v.push_back(std::to_string(e.status)); - v.push_back("'" + Strings::Escape(e.charname) + "'"); - v.push_back("'" + Strings::Escape(e.target) + "'"); - v.push_back("'" + Strings::Escape(e.time) + "'"); - v.push_back("'" + Strings::Escape(e.descriptiontype) + "'"); - v.push_back("'" + Strings::Escape(e.description) + "'"); - v.push_back(std::to_string(e.event_nid)); - - auto results = db.QueryDatabase( - fmt::format( - "{} VALUES ({})", - BaseInsert(), - Strings::Implode(",", v) - ) - ); - - if (results.Success()) { - e.id = results.LastInsertedID(); - return e; - } - - e = NewEntity(); - - return e; - } - - static int InsertMany( - Database& db, - const std::vector &entries - ) - { - std::vector insert_chunks; - - for (auto &e: entries) { - std::vector v; - - v.push_back(std::to_string(e.id)); - v.push_back("'" + Strings::Escape(e.accountname) + "'"); - v.push_back(std::to_string(e.accountid)); - v.push_back(std::to_string(e.status)); - v.push_back("'" + Strings::Escape(e.charname) + "'"); - v.push_back("'" + Strings::Escape(e.target) + "'"); - v.push_back("'" + Strings::Escape(e.time) + "'"); - v.push_back("'" + Strings::Escape(e.descriptiontype) + "'"); - v.push_back("'" + Strings::Escape(e.description) + "'"); - v.push_back(std::to_string(e.event_nid)); - - insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); - } - - std::vector v; - - auto results = db.QueryDatabase( - fmt::format( - "{} VALUES {}", - BaseInsert(), - Strings::Implode(",", insert_chunks) - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static std::vector All(Database& db) - { - std::vector all_entries; - - auto results = db.QueryDatabase( - fmt::format( - "{}", - BaseSelect() - ) - ); - - all_entries.reserve(results.RowCount()); - - for (auto row = results.begin(); row != results.end(); ++row) { - Eventlog e{}; - - e.id = static_cast(strtoul(row[0], nullptr, 10)); - e.accountname = row[1] ? row[1] : ""; - e.accountid = static_cast(strtoul(row[2], nullptr, 10)); - e.status = static_cast(atoi(row[3])); - e.charname = row[4] ? row[4] : ""; - e.target = row[5] ? row[5] : ""; - e.time = row[6] ? row[6] : ""; - e.descriptiontype = row[7] ? row[7] : ""; - e.description = row[8] ? row[8] : ""; - e.event_nid = static_cast(atoi(row[9])); - - all_entries.push_back(e); - } - - return all_entries; - } - - static std::vector GetWhere(Database& db, const std::string &where_filter) - { - std::vector all_entries; - - auto results = db.QueryDatabase( - fmt::format( - "{} WHERE {}", - BaseSelect(), - where_filter - ) - ); - - all_entries.reserve(results.RowCount()); - - for (auto row = results.begin(); row != results.end(); ++row) { - Eventlog e{}; - - e.id = static_cast(strtoul(row[0], nullptr, 10)); - e.accountname = row[1] ? row[1] : ""; - e.accountid = static_cast(strtoul(row[2], nullptr, 10)); - e.status = static_cast(atoi(row[3])); - e.charname = row[4] ? row[4] : ""; - e.target = row[5] ? row[5] : ""; - e.time = row[6] ? row[6] : ""; - e.descriptiontype = row[7] ? row[7] : ""; - e.description = row[8] ? row[8] : ""; - e.event_nid = static_cast(atoi(row[9])); - - all_entries.push_back(e); - } - - return all_entries; - } - - static int DeleteWhere(Database& db, const std::string &where_filter) - { - auto results = db.QueryDatabase( - fmt::format( - "DELETE FROM {} WHERE {}", - TableName(), - where_filter - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static int Truncate(Database& db) - { - auto results = db.QueryDatabase( - fmt::format( - "TRUNCATE TABLE {}", - TableName() - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static int64 GetMaxId(Database& db) - { - auto results = db.QueryDatabase( - fmt::format( - "SELECT COALESCE(MAX({}), 0) FROM {}", - PrimaryKey(), - TableName() - ) - ); - - return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); - } - - static int64 Count(Database& db, const std::string &where_filter = "") - { - auto results = db.QueryDatabase( - fmt::format( - "SELECT COUNT(*) FROM {} {}", - TableName(), - (where_filter.empty() ? "" : "WHERE " + where_filter) - ) - ); - - return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); - } - -}; - -#endif //EQEMU_BASE_EVENTLOG_REPOSITORY_H diff --git a/common/repositories/base/base_merchantlist_repository.h b/common/repositories/base/base_merchantlist_repository.h index 014a48919..7c9a3e8da 100644 --- a/common/repositories/base/base_merchantlist_repository.h +++ b/common/repositories/base/base_merchantlist_repository.h @@ -16,6 +16,7 @@ #include "../../strings.h" #include + class BaseMerchantlistRepository { public: struct Merchantlist { @@ -24,6 +25,8 @@ public: int32_t item; int16_t faction_required; uint8_t level_required; + uint8_t min_status; + uint8_t max_status; uint16_t alt_currency_cost; int32_t classes_required; int32_t probability; @@ -49,6 +52,8 @@ public: "item", "faction_required", "level_required", + "min_status", + "max_status", "alt_currency_cost", "classes_required", "probability", @@ -70,6 +75,8 @@ public: "item", "faction_required", "level_required", + "min_status", + "max_status", "alt_currency_cost", "classes_required", "probability", @@ -125,6 +132,8 @@ public: e.item = 0; e.faction_required = -100; e.level_required = 0; + e.min_status = 0; + e.max_status = 255; e.alt_currency_cost = 0; e.classes_required = 65535; e.probability = 100; @@ -160,8 +169,9 @@ public: { auto results = db.QueryDatabase( fmt::format( - "{} WHERE id = {} LIMIT 1", + "{} WHERE {} = {} LIMIT 1", BaseSelect(), + PrimaryKey(), merchantlist_id ) ); @@ -175,16 +185,18 @@ public: e.item = static_cast(atoi(row[2])); e.faction_required = static_cast(atoi(row[3])); e.level_required = static_cast(strtoul(row[4], nullptr, 10)); - e.alt_currency_cost = static_cast(strtoul(row[5], nullptr, 10)); - e.classes_required = static_cast(atoi(row[6])); - e.probability = static_cast(atoi(row[7])); - e.bucket_name = row[8] ? row[8] : ""; - e.bucket_value = row[9] ? row[9] : ""; - e.bucket_comparison = static_cast(strtoul(row[10], nullptr, 10)); - e.min_expansion = static_cast(atoi(row[11])); - e.max_expansion = static_cast(atoi(row[12])); - e.content_flags = row[13] ? row[13] : ""; - e.content_flags_disabled = row[14] ? row[14] : ""; + e.min_status = static_cast(strtoul(row[5], nullptr, 10)); + e.max_status = static_cast(strtoul(row[6], nullptr, 10)); + e.alt_currency_cost = static_cast(strtoul(row[7], nullptr, 10)); + e.classes_required = static_cast(atoi(row[8])); + e.probability = static_cast(atoi(row[9])); + e.bucket_name = row[10] ? row[10] : ""; + e.bucket_value = row[11] ? row[11] : ""; + e.bucket_comparison = static_cast(strtoul(row[12], nullptr, 10)); + e.min_expansion = static_cast(atoi(row[13])); + e.max_expansion = static_cast(atoi(row[14])); + e.content_flags = row[15] ? row[15] : ""; + e.content_flags_disabled = row[16] ? row[16] : ""; return e; } @@ -223,16 +235,18 @@ public: v.push_back(columns[2] + " = " + std::to_string(e.item)); v.push_back(columns[3] + " = " + std::to_string(e.faction_required)); v.push_back(columns[4] + " = " + std::to_string(e.level_required)); - v.push_back(columns[5] + " = " + std::to_string(e.alt_currency_cost)); - v.push_back(columns[6] + " = " + std::to_string(e.classes_required)); - v.push_back(columns[7] + " = " + std::to_string(e.probability)); - v.push_back(columns[8] + " = '" + Strings::Escape(e.bucket_name) + "'"); - v.push_back(columns[9] + " = '" + Strings::Escape(e.bucket_value) + "'"); - v.push_back(columns[10] + " = " + std::to_string(e.bucket_comparison)); - v.push_back(columns[11] + " = " + std::to_string(e.min_expansion)); - v.push_back(columns[12] + " = " + std::to_string(e.max_expansion)); - v.push_back(columns[13] + " = '" + Strings::Escape(e.content_flags) + "'"); - v.push_back(columns[14] + " = '" + Strings::Escape(e.content_flags_disabled) + "'"); + v.push_back(columns[5] + " = " + std::to_string(e.min_status)); + v.push_back(columns[6] + " = " + std::to_string(e.max_status)); + v.push_back(columns[7] + " = " + std::to_string(e.alt_currency_cost)); + v.push_back(columns[8] + " = " + std::to_string(e.classes_required)); + v.push_back(columns[9] + " = " + std::to_string(e.probability)); + v.push_back(columns[10] + " = '" + Strings::Escape(e.bucket_name) + "'"); + v.push_back(columns[11] + " = '" + Strings::Escape(e.bucket_value) + "'"); + v.push_back(columns[12] + " = " + std::to_string(e.bucket_comparison)); + v.push_back(columns[13] + " = " + std::to_string(e.min_expansion)); + v.push_back(columns[14] + " = " + std::to_string(e.max_expansion)); + v.push_back(columns[15] + " = '" + Strings::Escape(e.content_flags) + "'"); + v.push_back(columns[16] + " = '" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( @@ -259,6 +273,8 @@ public: v.push_back(std::to_string(e.item)); v.push_back(std::to_string(e.faction_required)); v.push_back(std::to_string(e.level_required)); + v.push_back(std::to_string(e.min_status)); + v.push_back(std::to_string(e.max_status)); v.push_back(std::to_string(e.alt_currency_cost)); v.push_back(std::to_string(e.classes_required)); v.push_back(std::to_string(e.probability)); @@ -303,6 +319,8 @@ public: v.push_back(std::to_string(e.item)); v.push_back(std::to_string(e.faction_required)); v.push_back(std::to_string(e.level_required)); + v.push_back(std::to_string(e.min_status)); + v.push_back(std::to_string(e.max_status)); v.push_back(std::to_string(e.alt_currency_cost)); v.push_back(std::to_string(e.classes_required)); v.push_back(std::to_string(e.probability)); @@ -351,16 +369,18 @@ public: e.item = static_cast(atoi(row[2])); e.faction_required = static_cast(atoi(row[3])); e.level_required = static_cast(strtoul(row[4], nullptr, 10)); - e.alt_currency_cost = static_cast(strtoul(row[5], nullptr, 10)); - e.classes_required = static_cast(atoi(row[6])); - e.probability = static_cast(atoi(row[7])); - e.bucket_name = row[8] ? row[8] : ""; - e.bucket_value = row[9] ? row[9] : ""; - e.bucket_comparison = static_cast(strtoul(row[10], nullptr, 10)); - e.min_expansion = static_cast(atoi(row[11])); - e.max_expansion = static_cast(atoi(row[12])); - e.content_flags = row[13] ? row[13] : ""; - e.content_flags_disabled = row[14] ? row[14] : ""; + e.min_status = static_cast(strtoul(row[5], nullptr, 10)); + e.max_status = static_cast(strtoul(row[6], nullptr, 10)); + e.alt_currency_cost = static_cast(strtoul(row[7], nullptr, 10)); + e.classes_required = static_cast(atoi(row[8])); + e.probability = static_cast(atoi(row[9])); + e.bucket_name = row[10] ? row[10] : ""; + e.bucket_value = row[11] ? row[11] : ""; + e.bucket_comparison = static_cast(strtoul(row[12], nullptr, 10)); + e.min_expansion = static_cast(atoi(row[13])); + e.max_expansion = static_cast(atoi(row[14])); + e.content_flags = row[15] ? row[15] : ""; + e.content_flags_disabled = row[16] ? row[16] : ""; all_entries.push_back(e); } @@ -390,16 +410,18 @@ public: e.item = static_cast(atoi(row[2])); e.faction_required = static_cast(atoi(row[3])); e.level_required = static_cast(strtoul(row[4], nullptr, 10)); - e.alt_currency_cost = static_cast(strtoul(row[5], nullptr, 10)); - e.classes_required = static_cast(atoi(row[6])); - e.probability = static_cast(atoi(row[7])); - e.bucket_name = row[8] ? row[8] : ""; - e.bucket_value = row[9] ? row[9] : ""; - e.bucket_comparison = static_cast(strtoul(row[10], nullptr, 10)); - e.min_expansion = static_cast(atoi(row[11])); - e.max_expansion = static_cast(atoi(row[12])); - e.content_flags = row[13] ? row[13] : ""; - e.content_flags_disabled = row[14] ? row[14] : ""; + e.min_status = static_cast(strtoul(row[5], nullptr, 10)); + e.max_status = static_cast(strtoul(row[6], nullptr, 10)); + e.alt_currency_cost = static_cast(strtoul(row[7], nullptr, 10)); + e.classes_required = static_cast(atoi(row[8])); + e.probability = static_cast(atoi(row[9])); + e.bucket_name = row[10] ? row[10] : ""; + e.bucket_value = row[11] ? row[11] : ""; + e.bucket_comparison = static_cast(strtoul(row[12], nullptr, 10)); + e.min_expansion = static_cast(atoi(row[13])); + e.max_expansion = static_cast(atoi(row[14])); + e.content_flags = row[15] ? row[15] : ""; + e.content_flags_disabled = row[16] ? row[16] : ""; all_entries.push_back(e); } diff --git a/common/repositories/base/base_npc_scale_global_base_repository.h b/common/repositories/base/base_npc_scale_global_base_repository.h index c8f6642c8..4920ed708 100644 --- a/common/repositories/base/base_npc_scale_global_base_repository.h +++ b/common/repositories/base/base_npc_scale_global_base_repository.h @@ -16,13 +16,16 @@ #include "../../strings.h" #include + class BaseNpcScaleGlobalBaseRepository { public: struct NpcScaleGlobalBase { int32_t type; int32_t level; + std::string zone_id_list; + std::string instance_version_list; int32_t ac; - int32_t hp; + int64_t hp; int32_t accuracy; int32_t slow_mitigation; int32_t attack; @@ -42,10 +45,13 @@ public: int32_t physical_resist; int32_t min_dmg; int32_t max_dmg; - int32_t hp_regen_rate; + int64_t hp_regen_rate; + int64_t hp_regen_per_second; int32_t attack_delay; int32_t spell_scale; int32_t heal_scale; + uint32_t avoidance; + int32_t heroic_strikethrough; std::string special_abilities; }; @@ -59,6 +65,8 @@ public: return { "type", "level", + "zone_id_list", + "instance_version_list", "ac", "hp", "accuracy", @@ -81,9 +89,12 @@ public: "min_dmg", "max_dmg", "hp_regen_rate", + "hp_regen_per_second", "attack_delay", "spell_scale", "heal_scale", + "avoidance", + "heroic_strikethrough", "special_abilities", }; } @@ -93,6 +104,8 @@ public: return { "type", "level", + "zone_id_list", + "instance_version_list", "ac", "hp", "accuracy", @@ -115,9 +128,12 @@ public: "min_dmg", "max_dmg", "hp_regen_rate", + "hp_regen_per_second", "attack_delay", "spell_scale", "heal_scale", + "avoidance", + "heroic_strikethrough", "special_abilities", }; } @@ -159,34 +175,39 @@ public: { NpcScaleGlobalBase e{}; - e.type = 0; - e.level = 0; - e.ac = 0; - e.hp = 0; - e.accuracy = 0; - e.slow_mitigation = 0; - e.attack = 0; - e.strength = 0; - e.stamina = 0; - e.dexterity = 0; - e.agility = 0; - e.intelligence = 0; - e.wisdom = 0; - e.charisma = 0; - e.magic_resist = 0; - e.cold_resist = 0; - e.fire_resist = 0; - e.poison_resist = 0; - e.disease_resist = 0; - e.corruption_resist = 0; - e.physical_resist = 0; - e.min_dmg = 0; - e.max_dmg = 0; - e.hp_regen_rate = 0; - e.attack_delay = 0; - e.spell_scale = 100; - e.heal_scale = 100; - e.special_abilities = ""; + e.type = 0; + e.level = 0; + e.zone_id_list = ""; + e.instance_version_list = ""; + e.ac = 0; + e.hp = 0; + e.accuracy = 0; + e.slow_mitigation = 0; + e.attack = 0; + e.strength = 0; + e.stamina = 0; + e.dexterity = 0; + e.agility = 0; + e.intelligence = 0; + e.wisdom = 0; + e.charisma = 0; + e.magic_resist = 0; + e.cold_resist = 0; + e.fire_resist = 0; + e.poison_resist = 0; + e.disease_resist = 0; + e.corruption_resist = 0; + e.physical_resist = 0; + e.min_dmg = 0; + e.max_dmg = 0; + e.hp_regen_rate = 0; + e.hp_regen_per_second = 0; + e.attack_delay = 0; + e.spell_scale = 100; + e.heal_scale = 100; + e.avoidance = 0; + e.heroic_strikethrough = 0; + e.special_abilities = ""; return e; } @@ -212,8 +233,9 @@ public: { auto results = db.QueryDatabase( fmt::format( - "{} WHERE id = {} LIMIT 1", + "{} WHERE {} = {} LIMIT 1", BaseSelect(), + PrimaryKey(), npc_scale_global_base_id ) ); @@ -222,34 +244,39 @@ public: if (results.RowCount() == 1) { NpcScaleGlobalBase e{}; - e.type = static_cast(atoi(row[0])); - e.level = static_cast(atoi(row[1])); - e.ac = static_cast(atoi(row[2])); - e.hp = static_cast(atoi(row[3])); - e.accuracy = static_cast(atoi(row[4])); - e.slow_mitigation = static_cast(atoi(row[5])); - e.attack = static_cast(atoi(row[6])); - e.strength = static_cast(atoi(row[7])); - e.stamina = static_cast(atoi(row[8])); - e.dexterity = static_cast(atoi(row[9])); - e.agility = static_cast(atoi(row[10])); - e.intelligence = static_cast(atoi(row[11])); - e.wisdom = static_cast(atoi(row[12])); - e.charisma = static_cast(atoi(row[13])); - e.magic_resist = static_cast(atoi(row[14])); - e.cold_resist = static_cast(atoi(row[15])); - e.fire_resist = static_cast(atoi(row[16])); - e.poison_resist = static_cast(atoi(row[17])); - e.disease_resist = static_cast(atoi(row[18])); - e.corruption_resist = static_cast(atoi(row[19])); - e.physical_resist = static_cast(atoi(row[20])); - e.min_dmg = static_cast(atoi(row[21])); - e.max_dmg = static_cast(atoi(row[22])); - e.hp_regen_rate = static_cast(atoi(row[23])); - e.attack_delay = static_cast(atoi(row[24])); - e.spell_scale = static_cast(atoi(row[25])); - e.heal_scale = static_cast(atoi(row[26])); - e.special_abilities = row[27] ? row[27] : ""; + e.type = static_cast(atoi(row[0])); + e.level = static_cast(atoi(row[1])); + e.zone_id_list = row[2] ? row[2] : ""; + e.instance_version_list = row[3] ? row[3] : ""; + e.ac = static_cast(atoi(row[4])); + e.hp = strtoll(row[5], nullptr, 10); + e.accuracy = static_cast(atoi(row[6])); + e.slow_mitigation = static_cast(atoi(row[7])); + e.attack = static_cast(atoi(row[8])); + e.strength = static_cast(atoi(row[9])); + e.stamina = static_cast(atoi(row[10])); + e.dexterity = static_cast(atoi(row[11])); + e.agility = static_cast(atoi(row[12])); + e.intelligence = static_cast(atoi(row[13])); + e.wisdom = static_cast(atoi(row[14])); + e.charisma = static_cast(atoi(row[15])); + e.magic_resist = static_cast(atoi(row[16])); + e.cold_resist = static_cast(atoi(row[17])); + e.fire_resist = static_cast(atoi(row[18])); + e.poison_resist = static_cast(atoi(row[19])); + e.disease_resist = static_cast(atoi(row[20])); + e.corruption_resist = static_cast(atoi(row[21])); + e.physical_resist = static_cast(atoi(row[22])); + e.min_dmg = static_cast(atoi(row[23])); + e.max_dmg = static_cast(atoi(row[24])); + e.hp_regen_rate = strtoll(row[25], nullptr, 10); + e.hp_regen_per_second = strtoll(row[26], nullptr, 10); + e.attack_delay = static_cast(atoi(row[27])); + e.spell_scale = static_cast(atoi(row[28])); + e.heal_scale = static_cast(atoi(row[29])); + e.avoidance = static_cast(strtoul(row[30], nullptr, 10)); + e.heroic_strikethrough = static_cast(atoi(row[31])); + e.special_abilities = row[32] ? row[32] : ""; return e; } @@ -285,32 +312,37 @@ public: v.push_back(columns[0] + " = " + std::to_string(e.type)); v.push_back(columns[1] + " = " + std::to_string(e.level)); - v.push_back(columns[2] + " = " + std::to_string(e.ac)); - v.push_back(columns[3] + " = " + std::to_string(e.hp)); - v.push_back(columns[4] + " = " + std::to_string(e.accuracy)); - v.push_back(columns[5] + " = " + std::to_string(e.slow_mitigation)); - v.push_back(columns[6] + " = " + std::to_string(e.attack)); - v.push_back(columns[7] + " = " + std::to_string(e.strength)); - v.push_back(columns[8] + " = " + std::to_string(e.stamina)); - v.push_back(columns[9] + " = " + std::to_string(e.dexterity)); - v.push_back(columns[10] + " = " + std::to_string(e.agility)); - v.push_back(columns[11] + " = " + std::to_string(e.intelligence)); - v.push_back(columns[12] + " = " + std::to_string(e.wisdom)); - v.push_back(columns[13] + " = " + std::to_string(e.charisma)); - v.push_back(columns[14] + " = " + std::to_string(e.magic_resist)); - v.push_back(columns[15] + " = " + std::to_string(e.cold_resist)); - v.push_back(columns[16] + " = " + std::to_string(e.fire_resist)); - v.push_back(columns[17] + " = " + std::to_string(e.poison_resist)); - v.push_back(columns[18] + " = " + std::to_string(e.disease_resist)); - v.push_back(columns[19] + " = " + std::to_string(e.corruption_resist)); - v.push_back(columns[20] + " = " + std::to_string(e.physical_resist)); - v.push_back(columns[21] + " = " + std::to_string(e.min_dmg)); - v.push_back(columns[22] + " = " + std::to_string(e.max_dmg)); - v.push_back(columns[23] + " = " + std::to_string(e.hp_regen_rate)); - v.push_back(columns[24] + " = " + std::to_string(e.attack_delay)); - v.push_back(columns[25] + " = " + std::to_string(e.spell_scale)); - v.push_back(columns[26] + " = " + std::to_string(e.heal_scale)); - v.push_back(columns[27] + " = '" + Strings::Escape(e.special_abilities) + "'"); + v.push_back(columns[2] + " = '" + Strings::Escape(e.zone_id_list) + "'"); + v.push_back(columns[3] + " = '" + Strings::Escape(e.instance_version_list) + "'"); + v.push_back(columns[4] + " = " + std::to_string(e.ac)); + v.push_back(columns[5] + " = " + std::to_string(e.hp)); + v.push_back(columns[6] + " = " + std::to_string(e.accuracy)); + v.push_back(columns[7] + " = " + std::to_string(e.slow_mitigation)); + v.push_back(columns[8] + " = " + std::to_string(e.attack)); + v.push_back(columns[9] + " = " + std::to_string(e.strength)); + v.push_back(columns[10] + " = " + std::to_string(e.stamina)); + v.push_back(columns[11] + " = " + std::to_string(e.dexterity)); + v.push_back(columns[12] + " = " + std::to_string(e.agility)); + v.push_back(columns[13] + " = " + std::to_string(e.intelligence)); + v.push_back(columns[14] + " = " + std::to_string(e.wisdom)); + v.push_back(columns[15] + " = " + std::to_string(e.charisma)); + v.push_back(columns[16] + " = " + std::to_string(e.magic_resist)); + v.push_back(columns[17] + " = " + std::to_string(e.cold_resist)); + v.push_back(columns[18] + " = " + std::to_string(e.fire_resist)); + v.push_back(columns[19] + " = " + std::to_string(e.poison_resist)); + v.push_back(columns[20] + " = " + std::to_string(e.disease_resist)); + v.push_back(columns[21] + " = " + std::to_string(e.corruption_resist)); + v.push_back(columns[22] + " = " + std::to_string(e.physical_resist)); + v.push_back(columns[23] + " = " + std::to_string(e.min_dmg)); + v.push_back(columns[24] + " = " + std::to_string(e.max_dmg)); + v.push_back(columns[25] + " = " + std::to_string(e.hp_regen_rate)); + v.push_back(columns[26] + " = " + std::to_string(e.hp_regen_per_second)); + v.push_back(columns[27] + " = " + std::to_string(e.attack_delay)); + v.push_back(columns[28] + " = " + std::to_string(e.spell_scale)); + v.push_back(columns[29] + " = " + std::to_string(e.heal_scale)); + v.push_back(columns[30] + " = " + std::to_string(e.avoidance)); + v.push_back(columns[31] + " = " + std::to_string(e.heroic_strikethrough)); + v.push_back(columns[32] + " = '" + Strings::Escape(e.special_abilities) + "'"); auto results = db.QueryDatabase( fmt::format( @@ -334,6 +366,8 @@ public: v.push_back(std::to_string(e.type)); v.push_back(std::to_string(e.level)); + v.push_back("'" + Strings::Escape(e.zone_id_list) + "'"); + v.push_back("'" + Strings::Escape(e.instance_version_list) + "'"); v.push_back(std::to_string(e.ac)); v.push_back(std::to_string(e.hp)); v.push_back(std::to_string(e.accuracy)); @@ -356,9 +390,12 @@ public: v.push_back(std::to_string(e.min_dmg)); v.push_back(std::to_string(e.max_dmg)); v.push_back(std::to_string(e.hp_regen_rate)); + v.push_back(std::to_string(e.hp_regen_per_second)); v.push_back(std::to_string(e.attack_delay)); v.push_back(std::to_string(e.spell_scale)); v.push_back(std::to_string(e.heal_scale)); + v.push_back(std::to_string(e.avoidance)); + v.push_back(std::to_string(e.heroic_strikethrough)); v.push_back("'" + Strings::Escape(e.special_abilities) + "'"); auto results = db.QueryDatabase( @@ -391,6 +428,8 @@ public: v.push_back(std::to_string(e.type)); v.push_back(std::to_string(e.level)); + v.push_back("'" + Strings::Escape(e.zone_id_list) + "'"); + v.push_back("'" + Strings::Escape(e.instance_version_list) + "'"); v.push_back(std::to_string(e.ac)); v.push_back(std::to_string(e.hp)); v.push_back(std::to_string(e.accuracy)); @@ -413,9 +452,12 @@ public: v.push_back(std::to_string(e.min_dmg)); v.push_back(std::to_string(e.max_dmg)); v.push_back(std::to_string(e.hp_regen_rate)); + v.push_back(std::to_string(e.hp_regen_per_second)); v.push_back(std::to_string(e.attack_delay)); v.push_back(std::to_string(e.spell_scale)); v.push_back(std::to_string(e.heal_scale)); + v.push_back(std::to_string(e.avoidance)); + v.push_back(std::to_string(e.heroic_strikethrough)); v.push_back("'" + Strings::Escape(e.special_abilities) + "'"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); @@ -450,34 +492,39 @@ public: for (auto row = results.begin(); row != results.end(); ++row) { NpcScaleGlobalBase e{}; - e.type = static_cast(atoi(row[0])); - e.level = static_cast(atoi(row[1])); - e.ac = static_cast(atoi(row[2])); - e.hp = static_cast(atoi(row[3])); - e.accuracy = static_cast(atoi(row[4])); - e.slow_mitigation = static_cast(atoi(row[5])); - e.attack = static_cast(atoi(row[6])); - e.strength = static_cast(atoi(row[7])); - e.stamina = static_cast(atoi(row[8])); - e.dexterity = static_cast(atoi(row[9])); - e.agility = static_cast(atoi(row[10])); - e.intelligence = static_cast(atoi(row[11])); - e.wisdom = static_cast(atoi(row[12])); - e.charisma = static_cast(atoi(row[13])); - e.magic_resist = static_cast(atoi(row[14])); - e.cold_resist = static_cast(atoi(row[15])); - e.fire_resist = static_cast(atoi(row[16])); - e.poison_resist = static_cast(atoi(row[17])); - e.disease_resist = static_cast(atoi(row[18])); - e.corruption_resist = static_cast(atoi(row[19])); - e.physical_resist = static_cast(atoi(row[20])); - e.min_dmg = static_cast(atoi(row[21])); - e.max_dmg = static_cast(atoi(row[22])); - e.hp_regen_rate = static_cast(atoi(row[23])); - e.attack_delay = static_cast(atoi(row[24])); - e.spell_scale = static_cast(atoi(row[25])); - e.heal_scale = static_cast(atoi(row[26])); - e.special_abilities = row[27] ? row[27] : ""; + e.type = static_cast(atoi(row[0])); + e.level = static_cast(atoi(row[1])); + e.zone_id_list = row[2] ? row[2] : ""; + e.instance_version_list = row[3] ? row[3] : ""; + e.ac = static_cast(atoi(row[4])); + e.hp = strtoll(row[5], nullptr, 10); + e.accuracy = static_cast(atoi(row[6])); + e.slow_mitigation = static_cast(atoi(row[7])); + e.attack = static_cast(atoi(row[8])); + e.strength = static_cast(atoi(row[9])); + e.stamina = static_cast(atoi(row[10])); + e.dexterity = static_cast(atoi(row[11])); + e.agility = static_cast(atoi(row[12])); + e.intelligence = static_cast(atoi(row[13])); + e.wisdom = static_cast(atoi(row[14])); + e.charisma = static_cast(atoi(row[15])); + e.magic_resist = static_cast(atoi(row[16])); + e.cold_resist = static_cast(atoi(row[17])); + e.fire_resist = static_cast(atoi(row[18])); + e.poison_resist = static_cast(atoi(row[19])); + e.disease_resist = static_cast(atoi(row[20])); + e.corruption_resist = static_cast(atoi(row[21])); + e.physical_resist = static_cast(atoi(row[22])); + e.min_dmg = static_cast(atoi(row[23])); + e.max_dmg = static_cast(atoi(row[24])); + e.hp_regen_rate = strtoll(row[25], nullptr, 10); + e.hp_regen_per_second = strtoll(row[26], nullptr, 10); + e.attack_delay = static_cast(atoi(row[27])); + e.spell_scale = static_cast(atoi(row[28])); + e.heal_scale = static_cast(atoi(row[29])); + e.avoidance = static_cast(strtoul(row[30], nullptr, 10)); + e.heroic_strikethrough = static_cast(atoi(row[31])); + e.special_abilities = row[32] ? row[32] : ""; all_entries.push_back(e); } @@ -502,34 +549,39 @@ public: for (auto row = results.begin(); row != results.end(); ++row) { NpcScaleGlobalBase e{}; - e.type = static_cast(atoi(row[0])); - e.level = static_cast(atoi(row[1])); - e.ac = static_cast(atoi(row[2])); - e.hp = static_cast(atoi(row[3])); - e.accuracy = static_cast(atoi(row[4])); - e.slow_mitigation = static_cast(atoi(row[5])); - e.attack = static_cast(atoi(row[6])); - e.strength = static_cast(atoi(row[7])); - e.stamina = static_cast(atoi(row[8])); - e.dexterity = static_cast(atoi(row[9])); - e.agility = static_cast(atoi(row[10])); - e.intelligence = static_cast(atoi(row[11])); - e.wisdom = static_cast(atoi(row[12])); - e.charisma = static_cast(atoi(row[13])); - e.magic_resist = static_cast(atoi(row[14])); - e.cold_resist = static_cast(atoi(row[15])); - e.fire_resist = static_cast(atoi(row[16])); - e.poison_resist = static_cast(atoi(row[17])); - e.disease_resist = static_cast(atoi(row[18])); - e.corruption_resist = static_cast(atoi(row[19])); - e.physical_resist = static_cast(atoi(row[20])); - e.min_dmg = static_cast(atoi(row[21])); - e.max_dmg = static_cast(atoi(row[22])); - e.hp_regen_rate = static_cast(atoi(row[23])); - e.attack_delay = static_cast(atoi(row[24])); - e.spell_scale = static_cast(atoi(row[25])); - e.heal_scale = static_cast(atoi(row[26])); - e.special_abilities = row[27] ? row[27] : ""; + e.type = static_cast(atoi(row[0])); + e.level = static_cast(atoi(row[1])); + e.zone_id_list = row[2] ? row[2] : ""; + e.instance_version_list = row[3] ? row[3] : ""; + e.ac = static_cast(atoi(row[4])); + e.hp = strtoll(row[5], nullptr, 10); + e.accuracy = static_cast(atoi(row[6])); + e.slow_mitigation = static_cast(atoi(row[7])); + e.attack = static_cast(atoi(row[8])); + e.strength = static_cast(atoi(row[9])); + e.stamina = static_cast(atoi(row[10])); + e.dexterity = static_cast(atoi(row[11])); + e.agility = static_cast(atoi(row[12])); + e.intelligence = static_cast(atoi(row[13])); + e.wisdom = static_cast(atoi(row[14])); + e.charisma = static_cast(atoi(row[15])); + e.magic_resist = static_cast(atoi(row[16])); + e.cold_resist = static_cast(atoi(row[17])); + e.fire_resist = static_cast(atoi(row[18])); + e.poison_resist = static_cast(atoi(row[19])); + e.disease_resist = static_cast(atoi(row[20])); + e.corruption_resist = static_cast(atoi(row[21])); + e.physical_resist = static_cast(atoi(row[22])); + e.min_dmg = static_cast(atoi(row[23])); + e.max_dmg = static_cast(atoi(row[24])); + e.hp_regen_rate = strtoll(row[25], nullptr, 10); + e.hp_regen_per_second = strtoll(row[26], nullptr, 10); + e.attack_delay = static_cast(atoi(row[27])); + e.spell_scale = static_cast(atoi(row[28])); + e.heal_scale = static_cast(atoi(row[29])); + e.avoidance = static_cast(strtoul(row[30], nullptr, 10)); + e.heroic_strikethrough = static_cast(atoi(row[31])); + e.special_abilities = row[32] ? row[32] : ""; all_entries.push_back(e); } diff --git a/common/repositories/base/base_hackers_repository.h b/common/repositories/base/base_player_event_log_settings_repository.h similarity index 56% rename from common/repositories/base/base_hackers_repository.h rename to common/repositories/base/base_player_event_log_settings_repository.h index 329c370d8..69156fa72 100644 --- a/common/repositories/base/base_hackers_repository.h +++ b/common/repositories/base/base_player_event_log_settings_repository.h @@ -9,22 +9,21 @@ * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories */ -#ifndef EQEMU_BASE_HACKERS_REPOSITORY_H -#define EQEMU_BASE_HACKERS_REPOSITORY_H +#ifndef EQEMU_BASE_PLAYER_EVENT_LOG_SETTINGS_REPOSITORY_H +#define EQEMU_BASE_PLAYER_EVENT_LOG_SETTINGS_REPOSITORY_H #include "../../database.h" #include "../../strings.h" #include -class BaseHackersRepository { +class BasePlayerEventLogSettingsRepository { public: - struct Hackers { - int32_t id; - std::string account; - std::string name; - std::string hacked; - std::string zone; - std::string date; + struct PlayerEventLogSettings { + int64_t id; + std::string event_name; + int8_t event_enabled; + int32_t retention_days; + int32_t discord_webhook_id; }; static std::string PrimaryKey() @@ -36,11 +35,10 @@ public: { return { "id", - "account", - "name", - "hacked", - "zone", - "date", + "event_name", + "event_enabled", + "retention_days", + "discord_webhook_id", }; } @@ -48,11 +46,10 @@ public: { return { "id", - "account", - "name", - "hacked", - "zone", - "date", + "event_name", + "event_enabled", + "retention_days", + "discord_webhook_id", }; } @@ -68,7 +65,7 @@ public: static std::string TableName() { - return std::string("hackers"); + return std::string("player_event_log_settings"); } static std::string BaseSelect() @@ -89,57 +86,56 @@ public: ); } - static Hackers NewEntity() + static PlayerEventLogSettings NewEntity() { - Hackers e{}; + PlayerEventLogSettings e{}; - e.id = 0; - e.account = ""; - e.name = ""; - e.hacked = ""; - e.zone = ""; - e.date = std::time(nullptr); + e.id = 0; + e.event_name = ""; + e.event_enabled = 0; + e.retention_days = 0; + e.discord_webhook_id = 0; return e; } - static Hackers GetHackers( - const std::vector &hackerss, - int hackers_id + static PlayerEventLogSettings GetPlayerEventLogSettings( + const std::vector &player_event_log_settingss, + int player_event_log_settings_id ) { - for (auto &hackers : hackerss) { - if (hackers.id == hackers_id) { - return hackers; + for (auto &player_event_log_settings : player_event_log_settingss) { + if (player_event_log_settings.id == player_event_log_settings_id) { + return player_event_log_settings; } } return NewEntity(); } - static Hackers FindOne( + static PlayerEventLogSettings FindOne( Database& db, - int hackers_id + int player_event_log_settings_id ) { auto results = db.QueryDatabase( fmt::format( - "{} WHERE id = {} LIMIT 1", + "{} WHERE {} = {} LIMIT 1", BaseSelect(), - hackers_id + PrimaryKey(), + player_event_log_settings_id ) ); auto row = results.begin(); if (results.RowCount() == 1) { - Hackers e{}; + PlayerEventLogSettings e{}; - e.id = static_cast(atoi(row[0])); - e.account = row[1] ? row[1] : ""; - e.name = row[2] ? row[2] : ""; - e.hacked = row[3] ? row[3] : ""; - e.zone = row[4] ? row[4] : ""; - e.date = row[5] ? row[5] : ""; + e.id = strtoll(row[0], nullptr, 10); + e.event_name = row[1] ? row[1] : ""; + e.event_enabled = static_cast(atoi(row[2])); + e.retention_days = static_cast(atoi(row[3])); + e.discord_webhook_id = static_cast(atoi(row[4])); return e; } @@ -149,7 +145,7 @@ public: static int DeleteOne( Database& db, - int hackers_id + int player_event_log_settings_id ) { auto results = db.QueryDatabase( @@ -157,7 +153,7 @@ public: "DELETE FROM {} WHERE {} = {}", TableName(), PrimaryKey(), - hackers_id + player_event_log_settings_id ) ); @@ -166,18 +162,18 @@ public: static int UpdateOne( Database& db, - const Hackers &e + const PlayerEventLogSettings &e ) { std::vector v; auto columns = Columns(); - v.push_back(columns[1] + " = '" + Strings::Escape(e.account) + "'"); - v.push_back(columns[2] + " = '" + Strings::Escape(e.name) + "'"); - v.push_back(columns[3] + " = '" + Strings::Escape(e.hacked) + "'"); - v.push_back(columns[4] + " = '" + Strings::Escape(e.zone) + "'"); - v.push_back(columns[5] + " = '" + Strings::Escape(e.date) + "'"); + v.push_back(columns[0] + " = " + std::to_string(e.id)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.event_name) + "'"); + v.push_back(columns[2] + " = " + std::to_string(e.event_enabled)); + v.push_back(columns[3] + " = " + std::to_string(e.retention_days)); + v.push_back(columns[4] + " = " + std::to_string(e.discord_webhook_id)); auto results = db.QueryDatabase( fmt::format( @@ -192,19 +188,18 @@ public: return (results.Success() ? results.RowsAffected() : 0); } - static Hackers InsertOne( + static PlayerEventLogSettings InsertOne( Database& db, - Hackers e + PlayerEventLogSettings e ) { std::vector v; v.push_back(std::to_string(e.id)); - v.push_back("'" + Strings::Escape(e.account) + "'"); - v.push_back("'" + Strings::Escape(e.name) + "'"); - v.push_back("'" + Strings::Escape(e.hacked) + "'"); - v.push_back("'" + Strings::Escape(e.zone) + "'"); - v.push_back("'" + Strings::Escape(e.date) + "'"); + v.push_back("'" + Strings::Escape(e.event_name) + "'"); + v.push_back(std::to_string(e.event_enabled)); + v.push_back(std::to_string(e.retention_days)); + v.push_back(std::to_string(e.discord_webhook_id)); auto results = db.QueryDatabase( fmt::format( @@ -226,7 +221,7 @@ public: static int InsertMany( Database& db, - const std::vector &entries + const std::vector &entries ) { std::vector insert_chunks; @@ -235,11 +230,10 @@ public: std::vector v; v.push_back(std::to_string(e.id)); - v.push_back("'" + Strings::Escape(e.account) + "'"); - v.push_back("'" + Strings::Escape(e.name) + "'"); - v.push_back("'" + Strings::Escape(e.hacked) + "'"); - v.push_back("'" + Strings::Escape(e.zone) + "'"); - v.push_back("'" + Strings::Escape(e.date) + "'"); + v.push_back("'" + Strings::Escape(e.event_name) + "'"); + v.push_back(std::to_string(e.event_enabled)); + v.push_back(std::to_string(e.retention_days)); + v.push_back(std::to_string(e.discord_webhook_id)); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } @@ -257,9 +251,9 @@ public: return (results.Success() ? results.RowsAffected() : 0); } - static std::vector All(Database& db) + static std::vector All(Database& db) { - std::vector all_entries; + std::vector all_entries; auto results = db.QueryDatabase( fmt::format( @@ -271,14 +265,13 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Hackers e{}; + PlayerEventLogSettings e{}; - e.id = static_cast(atoi(row[0])); - e.account = row[1] ? row[1] : ""; - e.name = row[2] ? row[2] : ""; - e.hacked = row[3] ? row[3] : ""; - e.zone = row[4] ? row[4] : ""; - e.date = row[5] ? row[5] : ""; + e.id = strtoll(row[0], nullptr, 10); + e.event_name = row[1] ? row[1] : ""; + e.event_enabled = static_cast(atoi(row[2])); + e.retention_days = static_cast(atoi(row[3])); + e.discord_webhook_id = static_cast(atoi(row[4])); all_entries.push_back(e); } @@ -286,9 +279,9 @@ public: return all_entries; } - static std::vector GetWhere(Database& db, const std::string &where_filter) + static std::vector GetWhere(Database& db, const std::string &where_filter) { - std::vector all_entries; + std::vector all_entries; auto results = db.QueryDatabase( fmt::format( @@ -301,14 +294,13 @@ public: all_entries.reserve(results.RowCount()); for (auto row = results.begin(); row != results.end(); ++row) { - Hackers e{}; + PlayerEventLogSettings e{}; - e.id = static_cast(atoi(row[0])); - e.account = row[1] ? row[1] : ""; - e.name = row[2] ? row[2] : ""; - e.hacked = row[3] ? row[3] : ""; - e.zone = row[4] ? row[4] : ""; - e.date = row[5] ? row[5] : ""; + e.id = strtoll(row[0], nullptr, 10); + e.event_name = row[1] ? row[1] : ""; + e.event_enabled = static_cast(atoi(row[2])); + e.retention_days = static_cast(atoi(row[3])); + e.discord_webhook_id = static_cast(atoi(row[4])); all_entries.push_back(e); } @@ -369,4 +361,4 @@ public: }; -#endif //EQEMU_BASE_HACKERS_REPOSITORY_H +#endif //EQEMU_BASE_PLAYER_EVENT_LOG_SETTINGS_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_logs_repository.h b/common/repositories/base/base_player_event_logs_repository.h new file mode 100644 index 000000000..8030303a9 --- /dev/null +++ b/common/repositories/base/base_player_event_logs_repository.h @@ -0,0 +1,465 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_PLAYER_EVENT_LOGS_REPOSITORY_H +#define EQEMU_BASE_PLAYER_EVENT_LOGS_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include +#include + +class BasePlayerEventLogsRepository { +public: + struct PlayerEventLogs { + int64_t id; + int64_t account_id; + int64_t character_id; + int32_t zone_id; + int32_t instance_id; + float x; + float y; + float z; + float heading; + int32_t event_type_id; + std::string event_type_name; + std::string event_data; + time_t created_at; + + // cereal + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(id), + CEREAL_NVP(account_id), + CEREAL_NVP(character_id), + CEREAL_NVP(zone_id), + CEREAL_NVP(instance_id), + CEREAL_NVP(x), + CEREAL_NVP(y), + CEREAL_NVP(z), + CEREAL_NVP(heading), + CEREAL_NVP(event_type_id), + CEREAL_NVP(event_type_name), + CEREAL_NVP(event_data), + CEREAL_NVP(created_at) + ); + } + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "account_id", + "character_id", + "zone_id", + "instance_id", + "x", + "y", + "z", + "heading", + "event_type_id", + "event_type_name", + "event_data", + "created_at", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "account_id", + "character_id", + "zone_id", + "instance_id", + "x", + "y", + "z", + "heading", + "event_type_id", + "event_type_name", + "event_data", + "UNIX_TIMESTAMP(created_at)", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("player_event_logs"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static PlayerEventLogs NewEntity() + { + PlayerEventLogs e{}; + + e.id = 0; + e.account_id = 0; + e.character_id = 0; + e.zone_id = 0; + e.instance_id = 0; + e.x = 0; + e.y = 0; + e.z = 0; + e.heading = 0; + e.event_type_id = 0; + e.event_type_name = ""; + e.event_data = ""; + e.created_at = 0; + + return e; + } + + static PlayerEventLogs GetPlayerEventLogs( + const std::vector &player_event_logss, + int player_event_logs_id + ) + { + for (auto &player_event_logs : player_event_logss) { + if (player_event_logs.id == player_event_logs_id) { + return player_event_logs; + } + } + + return NewEntity(); + } + + static PlayerEventLogs FindOne( + Database& db, + int player_event_logs_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + player_event_logs_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + PlayerEventLogs e{}; + + e.id = strtoll(row[0], nullptr, 10); + e.account_id = strtoll(row[1], nullptr, 10); + e.character_id = strtoll(row[2], nullptr, 10); + e.zone_id = static_cast(atoi(row[3])); + e.instance_id = static_cast(atoi(row[4])); + e.x = strtof(row[5], nullptr); + e.y = strtof(row[6], nullptr); + e.z = strtof(row[7], nullptr); + e.heading = strtof(row[8], nullptr); + e.event_type_id = static_cast(atoi(row[9])); + e.event_type_name = row[10] ? row[10] : ""; + e.event_data = row[11] ? row[11] : ""; + e.created_at = strtoll(row[12] ? row[12] : "-1", nullptr, 10); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int player_event_logs_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + player_event_logs_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const PlayerEventLogs &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.account_id)); + v.push_back(columns[2] + " = " + std::to_string(e.character_id)); + v.push_back(columns[3] + " = " + std::to_string(e.zone_id)); + v.push_back(columns[4] + " = " + std::to_string(e.instance_id)); + v.push_back(columns[5] + " = " + std::to_string(e.x)); + v.push_back(columns[6] + " = " + std::to_string(e.y)); + v.push_back(columns[7] + " = " + std::to_string(e.z)); + v.push_back(columns[8] + " = " + std::to_string(e.heading)); + v.push_back(columns[9] + " = " + std::to_string(e.event_type_id)); + v.push_back(columns[10] + " = '" + db.Escape(e.event_type_name) + "'"); + v.push_back(columns[11] + " = '" + db.Escape(e.event_data) + "'"); + v.push_back(columns[12] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static PlayerEventLogs InsertOne( + Database& db, + PlayerEventLogs e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.account_id)); + v.push_back(std::to_string(e.character_id)); + v.push_back(std::to_string(e.zone_id)); + v.push_back(std::to_string(e.instance_id)); + v.push_back(std::to_string(e.x)); + v.push_back(std::to_string(e.y)); + v.push_back(std::to_string(e.z)); + v.push_back(std::to_string(e.heading)); + v.push_back(std::to_string(e.event_type_id)); + v.push_back("'" + db.Escape(e.event_type_name) + "'"); + v.push_back("'" + db.Escape(e.event_data) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.account_id)); + v.push_back(std::to_string(e.character_id)); + v.push_back(std::to_string(e.zone_id)); + v.push_back(std::to_string(e.instance_id)); + v.push_back(std::to_string(e.x)); + v.push_back(std::to_string(e.y)); + v.push_back(std::to_string(e.z)); + v.push_back(std::to_string(e.heading)); + v.push_back(std::to_string(e.event_type_id)); + v.push_back("'" + db.Escape(e.event_type_name) + "'"); + v.push_back("'" + db.Escape(e.event_data) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventLogs e{}; + + e.id = strtoll(row[0], nullptr, 10); + e.account_id = strtoll(row[1], nullptr, 10); + e.character_id = strtoll(row[2], nullptr, 10); + e.zone_id = static_cast(atoi(row[3])); + e.instance_id = static_cast(atoi(row[4])); + e.x = strtof(row[5], nullptr); + e.y = strtof(row[6], nullptr); + e.z = strtof(row[7], nullptr); + e.heading = strtof(row[8], nullptr); + e.event_type_id = static_cast(atoi(row[9])); + e.event_type_name = row[10] ? row[10] : ""; + e.event_data = row[11] ? row[11] : ""; + e.created_at = strtoll(row[12] ? row[12] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventLogs e{}; + + e.id = strtoll(row[0], nullptr, 10); + e.account_id = strtoll(row[1], nullptr, 10); + e.character_id = strtoll(row[2], nullptr, 10); + e.zone_id = static_cast(atoi(row[3])); + e.instance_id = static_cast(atoi(row[4])); + e.x = strtof(row[5], nullptr); + e.y = strtof(row[6], nullptr); + e.z = strtof(row[7], nullptr); + e.heading = strtof(row[8], nullptr); + e.event_type_id = static_cast(atoi(row[9])); + e.event_type_name = row[10] ? row[10] : ""; + e.event_data = row[11] ? row[11] : ""; + e.created_at = strtoll(row[12] ? row[12] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + +}; + +#endif //EQEMU_BASE_PLAYER_EVENT_LOGS_REPOSITORY_H diff --git a/common/repositories/base/base_raid_members_repository.h b/common/repositories/base/base_raid_members_repository.h index 07defda40..3a0d34dcb 100644 --- a/common/repositories/base/base_raid_members_repository.h +++ b/common/repositories/base/base_raid_members_repository.h @@ -16,11 +16,14 @@ #include "../../strings.h" #include + class BaseRaidMembersRepository { public: struct RaidMembers { + uint64_t id; int32_t raidid; int32_t charid; + int32_t bot_id; uint32_t groupid; int8_t _class; int8_t level; @@ -32,14 +35,16 @@ public: static std::string PrimaryKey() { - return std::string("charid"); + return std::string("id"); } static std::vector Columns() { return { + "id", "raidid", "charid", + "bot_id", "groupid", "_class", "level", @@ -53,8 +58,10 @@ public: static std::vector SelectColumns() { return { + "id", "raidid", "charid", + "bot_id", "groupid", "_class", "level", @@ -102,8 +109,10 @@ public: { RaidMembers e{}; + e.id = 0; e.raidid = 0; e.charid = 0; + e.bot_id = 0; e.groupid = 0; e._class = 0; e.level = 0; @@ -121,7 +130,7 @@ public: ) { for (auto &raid_members : raid_memberss) { - if (raid_members.charid == raid_members_id) { + if (raid_members.id == raid_members_id) { return raid_members; } } @@ -136,8 +145,9 @@ public: { auto results = db.QueryDatabase( fmt::format( - "{} WHERE id = {} LIMIT 1", + "{} WHERE {} = {} LIMIT 1", BaseSelect(), + PrimaryKey(), raid_members_id ) ); @@ -146,15 +156,17 @@ public: if (results.RowCount() == 1) { RaidMembers e{}; - e.raidid = static_cast(atoi(row[0])); - e.charid = static_cast(atoi(row[1])); - e.groupid = static_cast(strtoul(row[2], nullptr, 10)); - e._class = static_cast(atoi(row[3])); - e.level = static_cast(atoi(row[4])); - e.name = row[5] ? row[5] : ""; - e.isgroupleader = static_cast(atoi(row[6])); - e.israidleader = static_cast(atoi(row[7])); - e.islooter = static_cast(atoi(row[8])); + e.id = strtoull(row[0], nullptr, 10); + e.raidid = static_cast(atoi(row[1])); + e.charid = static_cast(atoi(row[2])); + e.bot_id = static_cast(atoi(row[3])); + e.groupid = static_cast(strtoul(row[4], nullptr, 10)); + e._class = static_cast(atoi(row[5])); + e.level = static_cast(atoi(row[6])); + e.name = row[7] ? row[7] : ""; + e.isgroupleader = static_cast(atoi(row[8])); + e.israidleader = static_cast(atoi(row[9])); + e.islooter = static_cast(atoi(row[10])); return e; } @@ -188,15 +200,16 @@ public: auto columns = Columns(); - v.push_back(columns[0] + " = " + std::to_string(e.raidid)); - v.push_back(columns[1] + " = " + std::to_string(e.charid)); - v.push_back(columns[2] + " = " + std::to_string(e.groupid)); - v.push_back(columns[3] + " = " + std::to_string(e._class)); - v.push_back(columns[4] + " = " + std::to_string(e.level)); - v.push_back(columns[5] + " = '" + Strings::Escape(e.name) + "'"); - v.push_back(columns[6] + " = " + std::to_string(e.isgroupleader)); - v.push_back(columns[7] + " = " + std::to_string(e.israidleader)); - v.push_back(columns[8] + " = " + std::to_string(e.islooter)); + v.push_back(columns[1] + " = " + std::to_string(e.raidid)); + v.push_back(columns[2] + " = " + std::to_string(e.charid)); + v.push_back(columns[3] + " = " + std::to_string(e.bot_id)); + v.push_back(columns[4] + " = " + std::to_string(e.groupid)); + v.push_back(columns[5] + " = " + std::to_string(e._class)); + v.push_back(columns[6] + " = " + std::to_string(e.level)); + v.push_back(columns[7] + " = '" + Strings::Escape(e.name) + "'"); + v.push_back(columns[8] + " = " + std::to_string(e.isgroupleader)); + v.push_back(columns[9] + " = " + std::to_string(e.israidleader)); + v.push_back(columns[10] + " = " + std::to_string(e.islooter)); auto results = db.QueryDatabase( fmt::format( @@ -204,7 +217,7 @@ public: TableName(), Strings::Implode(", ", v), PrimaryKey(), - e.charid + e.id ) ); @@ -218,8 +231,10 @@ public: { std::vector v; + v.push_back(std::to_string(e.id)); v.push_back(std::to_string(e.raidid)); v.push_back(std::to_string(e.charid)); + v.push_back(std::to_string(e.bot_id)); v.push_back(std::to_string(e.groupid)); v.push_back(std::to_string(e._class)); v.push_back(std::to_string(e.level)); @@ -237,7 +252,7 @@ public: ); if (results.Success()) { - e.charid = results.LastInsertedID(); + e.id = results.LastInsertedID(); return e; } @@ -256,8 +271,10 @@ public: for (auto &e: entries) { std::vector v; + v.push_back(std::to_string(e.id)); v.push_back(std::to_string(e.raidid)); v.push_back(std::to_string(e.charid)); + v.push_back(std::to_string(e.bot_id)); v.push_back(std::to_string(e.groupid)); v.push_back(std::to_string(e._class)); v.push_back(std::to_string(e.level)); @@ -298,15 +315,17 @@ public: for (auto row = results.begin(); row != results.end(); ++row) { RaidMembers e{}; - e.raidid = static_cast(atoi(row[0])); - e.charid = static_cast(atoi(row[1])); - e.groupid = static_cast(strtoul(row[2], nullptr, 10)); - e._class = static_cast(atoi(row[3])); - e.level = static_cast(atoi(row[4])); - e.name = row[5] ? row[5] : ""; - e.isgroupleader = static_cast(atoi(row[6])); - e.israidleader = static_cast(atoi(row[7])); - e.islooter = static_cast(atoi(row[8])); + e.id = strtoull(row[0], nullptr, 10); + e.raidid = static_cast(atoi(row[1])); + e.charid = static_cast(atoi(row[2])); + e.bot_id = static_cast(atoi(row[3])); + e.groupid = static_cast(strtoul(row[4], nullptr, 10)); + e._class = static_cast(atoi(row[5])); + e.level = static_cast(atoi(row[6])); + e.name = row[7] ? row[7] : ""; + e.isgroupleader = static_cast(atoi(row[8])); + e.israidleader = static_cast(atoi(row[9])); + e.islooter = static_cast(atoi(row[10])); all_entries.push_back(e); } @@ -331,15 +350,17 @@ public: for (auto row = results.begin(); row != results.end(); ++row) { RaidMembers e{}; - e.raidid = static_cast(atoi(row[0])); - e.charid = static_cast(atoi(row[1])); - e.groupid = static_cast(strtoul(row[2], nullptr, 10)); - e._class = static_cast(atoi(row[3])); - e.level = static_cast(atoi(row[4])); - e.name = row[5] ? row[5] : ""; - e.isgroupleader = static_cast(atoi(row[6])); - e.israidleader = static_cast(atoi(row[7])); - e.islooter = static_cast(atoi(row[8])); + e.id = strtoull(row[0], nullptr, 10); + e.raidid = static_cast(atoi(row[1])); + e.charid = static_cast(atoi(row[2])); + e.bot_id = static_cast(atoi(row[3])); + e.groupid = static_cast(strtoul(row[4], nullptr, 10)); + e._class = static_cast(atoi(row[5])); + e.level = static_cast(atoi(row[6])); + e.name = row[7] ? row[7] : ""; + e.isgroupleader = static_cast(atoi(row[8])); + e.israidleader = static_cast(atoi(row[9])); + e.islooter = static_cast(atoi(row[10])); all_entries.push_back(e); } diff --git a/common/repositories/character_data_repository.h b/common/repositories/character_data_repository.h index f527e5537..c029b14ea 100644 --- a/common/repositories/character_data_repository.h +++ b/common/repositories/character_data_repository.h @@ -5,6 +5,8 @@ #include "../strings.h" #include "base/base_character_data_repository.h" + + class CharacterDataRepository: public BaseCharacterDataRepository { public: @@ -44,7 +46,6 @@ public: */ // Custom extended repository methods here - }; #endif //EQEMU_CHARACTER_DATA_REPOSITORY_H diff --git a/common/repositories/dynamic_zone_members_repository.h b/common/repositories/dynamic_zone_members_repository.h index 1e25fc950..b1afe41ca 100644 --- a/common/repositories/dynamic_zone_members_repository.h +++ b/common/repositories/dynamic_zone_members_repository.h @@ -172,7 +172,7 @@ public: DELETE FROM {} WHERE dynamic_zone_id IN ({}); ), - TableName(), fmt::join(dynamic_zone_ids, ",") + TableName(), Strings::Join(dynamic_zone_ids, ",") )); } } diff --git a/common/repositories/expedition_lockouts_repository.h b/common/repositories/expedition_lockouts_repository.h index 94dbe155d..4ccae0d39 100644 --- a/common/repositories/expedition_lockouts_repository.h +++ b/common/repositories/expedition_lockouts_repository.h @@ -75,7 +75,7 @@ public: FROM expedition_lockouts WHERE expedition_id IN ({}) ), - fmt::join(expedition_ids, ",") + Strings::Join(expedition_ids, ",") )); all_entries.reserve(results.RowCount()); diff --git a/common/repositories/expeditions_repository.h b/common/repositories/expeditions_repository.h index 502b9bc04..aab6acf5f 100644 --- a/common/repositories/expeditions_repository.h +++ b/common/repositories/expeditions_repository.h @@ -62,7 +62,7 @@ public: std::vector entries; - auto joined_character_names = fmt::format("'{}'", fmt::join(character_names, "','")); + auto joined_character_names = fmt::format("'{}'", Strings::Join(character_names, "','")); auto results = db.QueryDatabase(fmt::format(SQL( SELECT diff --git a/common/repositories/hackers_repository.h b/common/repositories/player_event_log_settings_repository.h similarity index 68% rename from common/repositories/hackers_repository.h rename to common/repositories/player_event_log_settings_repository.h index 516ab0e6f..770db7c3f 100644 --- a/common/repositories/hackers_repository.h +++ b/common/repositories/player_event_log_settings_repository.h @@ -1,11 +1,11 @@ -#ifndef EQEMU_HACKERS_REPOSITORY_H -#define EQEMU_HACKERS_REPOSITORY_H +#ifndef EQEMU_PLAYER_EVENT_LOG_SETTINGS_REPOSITORY_H +#define EQEMU_PLAYER_EVENT_LOG_SETTINGS_REPOSITORY_H #include "../database.h" #include "../strings.h" -#include "base/base_hackers_repository.h" +#include "base/base_player_event_log_settings_repository.h" -class HackersRepository: public BaseHackersRepository { +class PlayerEventLogSettingsRepository: public BasePlayerEventLogSettingsRepository { public: /** @@ -32,10 +32,10 @@ public: * * Example custom methods in a repository * - * HackersRepository::GetByZoneAndVersion(int zone_id, int zone_version) - * HackersRepository::GetWhereNeverExpires() - * HackersRepository::GetWhereXAndY() - * HackersRepository::DeleteWhereXAndY() + * PlayerEventLogSettingsRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * PlayerEventLogSettingsRepository::GetWhereNeverExpires() + * PlayerEventLogSettingsRepository::GetWhereXAndY() + * PlayerEventLogSettingsRepository::DeleteWhereXAndY() * * Most of the above could be covered by base methods, but if you as a developer * find yourself re-using logic for other parts of the code, its best to just make a @@ -47,4 +47,4 @@ public: }; -#endif //EQEMU_HACKERS_REPOSITORY_H +#endif //EQEMU_PLAYER_EVENT_LOG_SETTINGS_REPOSITORY_H diff --git a/common/repositories/eventlog_repository.h b/common/repositories/player_event_logs_repository.h similarity index 71% rename from common/repositories/eventlog_repository.h rename to common/repositories/player_event_logs_repository.h index 83f21fb1a..97a6d6431 100644 --- a/common/repositories/eventlog_repository.h +++ b/common/repositories/player_event_logs_repository.h @@ -1,11 +1,11 @@ -#ifndef EQEMU_EVENTLOG_REPOSITORY_H -#define EQEMU_EVENTLOG_REPOSITORY_H +#ifndef EQEMU_PLAYER_EVENT_LOGS_REPOSITORY_H +#define EQEMU_PLAYER_EVENT_LOGS_REPOSITORY_H #include "../database.h" #include "../strings.h" -#include "base/base_eventlog_repository.h" +#include "base/base_player_event_logs_repository.h" -class EventlogRepository: public BaseEventlogRepository { +class PlayerEventLogsRepository: public BasePlayerEventLogsRepository { public: /** @@ -32,10 +32,10 @@ public: * * Example custom methods in a repository * - * EventlogRepository::GetByZoneAndVersion(int zone_id, int zone_version) - * EventlogRepository::GetWhereNeverExpires() - * EventlogRepository::GetWhereXAndY() - * EventlogRepository::DeleteWhereXAndY() + * PlayerEventLogsRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * PlayerEventLogsRepository::GetWhereNeverExpires() + * PlayerEventLogsRepository::GetWhereXAndY() + * PlayerEventLogsRepository::DeleteWhereXAndY() * * Most of the above could be covered by base methods, but if you as a developer * find yourself re-using logic for other parts of the code, its best to just make a @@ -47,4 +47,4 @@ public: }; -#endif //EQEMU_EVENTLOG_REPOSITORY_H +#endif //EQEMU_PLAYER_EVENT_LOGS_REPOSITORY_H diff --git a/common/rulesys.cpp b/common/rulesys.cpp index f07956572..639df7e48 100644 --- a/common/rulesys.cpp +++ b/common/rulesys.cpp @@ -141,11 +141,11 @@ bool RuleManager::SetRule(const std::string &rule_name, const std::string &rule_ switch (type) { case IntRule: - m_RuleIntValues[index] = atoi(rule_value.c_str()); + m_RuleIntValues[index] = Strings::ToInt(rule_value.c_str()); LogRules("Set rule [{}] to value [{}]", rule_name, m_RuleIntValues[index]); break; case RealRule: - m_RuleRealValues[index] = atof(rule_value.c_str()); + m_RuleRealValues[index] = Strings::ToFloat(rule_value.c_str()); LogRules("Set rule [{}] to value [{:.2f}]", rule_name, m_RuleRealValues[index]); break; case BoolRule: @@ -385,7 +385,16 @@ void RuleManager::_SaveRule(Database *db, RuleType type, uint16 index) { e.rule_value = rule_value; e.notes = rule_notes; - RuleValuesRepository::UpdateOne(*db, e); + db->QueryDatabase( + fmt::format( + "UPDATE rule_values SET rule_value = '{}', notes = '{}' WHERE ruleset_id = {} AND rule_name = '{}'", + rule_value, + Strings::Escape(rule_notes), + e.ruleset_id, + e.rule_name + ) + ); + return; } diff --git a/common/ruletypes.h b/common/ruletypes.h index d30c1be98..b597cfc2c 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -93,6 +93,12 @@ RULE_INT(Character, ItemEnduranceRegenCap, 15, "Limit on endurance regeneration RULE_INT(Character, ItemExtraDmgCap, 150, "Cap for bonuses to melee skills like Bash, Frenzy, etc.") RULE_INT(Character, HasteCap, 100, "Haste cap for non-v3(over haste) haste") RULE_INT(Character, Hastev3Cap, 25, "Haste cap for v3(over haste) haste") +RULE_REAL(Character, HeroicStrengthMultiplier, 1.00, "Multplier scales benefits from Heroic Strength. Grants 25 Base Endurance, 0.05 Endurance Regen, 1 Melee Damage each Hit, and 1 Shield AC per 10 Heroic Strength.") +RULE_REAL(Character, HeroicStaminaMultiplier, 1.00, "Multplier scales benefits from Heroic Stamina. Grants 25 Base Endurance, 0.05 Endurance Regen, 100 Base HP, and 0.5 HP Regen per 10 Heroic Stamina.") +RULE_REAL(Character, HeroicAgilityMultiplier, 1.00, "Multplier scales benefits from Heroic Agility. Grants 25 Base Endurance, 0.05 Endurance Regen, and 1 Avoidance AC per 10 Heroic Agility. (Rule does not change Dodge Chance)") +RULE_REAL(Character, HeroicDexterityMultiplier, 1.00, "Multplier scales benefits from Heroic Dexterity. Grants 25 Base Endurance, 0.05 Endurance Regen, and 1 Archery/Throwing Damage each hit per 10 Heroic Dexterity. (Rule does not change Assassinate/Headshot/Block/Parry/Riposte Chances)") +RULE_REAL(Character, HeroicWisdomMultiplier, 1.00, "Multplier scales benefits from Heroic Wisdom. Grants 250 Base Mana, 1 Mana Regen per 25 Heroic Wisdom.") +RULE_REAL(Character, HeroicIntelligenceMultiplier, 1.00, "Multplier scales benefits from Heroic Intelligence. Grants 250 Base Mana, 1 Mana Regen per 25 Heroic Intelligence.") RULE_INT(Character, SkillUpModifier, 100, "The probability for a skill-up is multiplied by value/100") RULE_BOOL(Character, SharedBankPlat, false, "Shared bank platinum. Off by default to prevent duplication") RULE_BOOL(Character, BindAnywhere, false, "Allows players to bind their soul anywhere in the world") @@ -197,9 +203,15 @@ RULE_BOOL(Character, PetZoneWithOwner, true, "Should Pets Zone with Owner") RULE_BOOL(Character, FullManaOnDeath, true, "On death set mana to full") RULE_BOOL(Character, FullEndurOnDeath, true, "On death set endurance to full") RULE_INT(Character, ExperiencePercentCapPerKill, -1, "Caps the percentage of experience that can be gained per kill. -1 disables the cap; 0 blocks all (non-aa) xp.") -RULE_BOOL(Character, EnableGroupEXPModifier, true, "Enable or disable the group experience modifier based on number of players in group, default is true") +RULE_BOOL(Character, EnableGroupEXPModifier, true, "Enable or disable the group experience modifier in group, default is true") +RULE_BOOL(Character, EnableGroupMemberEXPModifier, true, "Enable or disable the group member experience modifier based on number of players in group, default is true") RULE_REAL(Character, GroupMemberEXPModifier, 0.2, "Sets the group experience modifier per members between 2 and 5, default is 0.2") RULE_REAL(Character, FullGroupEXPModifier, 2.16, "Sets the group experience modifier for a full group, default is 2.16") +RULE_BOOL(Character, IgnoreLevelBasedHasteCaps, false, "Ignores hard coded level based haste caps.") +RULE_BOOL(Character, EnableRaidEXPModifier, true, "Enable or disable the raid experience modifier, default is true") +RULE_BOOL(Character, EnableRaidMemberEXPModifier, true, "Enable or disable the raid experience modifier based on members in raid, default is true") +RULE_BOOL(Character, LeaveCursorMoneyOnCorpse, false, "Enable or disable leaving cursor money on player corpses") +RULE_BOOL(Character, ItemExtraSkillDamageCalcAsPercent, false, "If enabled, apply Item Extra Skill Damage as Percentage-based modifiers") RULE_CATEGORY_END() RULE_CATEGORY(Mercs) @@ -315,8 +327,8 @@ RULE_CATEGORY_END() RULE_CATEGORY(Map) RULE_BOOL(Map, FixPathingZOnSendTo, false, "Try to repair Z coordinates in the SendTo routine as well") RULE_BOOL(Map, FixZWhenPathing, true, "Automatically fix NPC Z coordinates when moving/pathing/engaged (Far less CPU intensive than its predecessor)") -RULE_REAL(Map, DistanceCanTravelBeforeAdjustment, 10.0, "Distance a mob can path before FixZ is called, depends on FixZWhenPathing") RULE_BOOL(Map, MobZVisualDebug, false, "Displays spell effects determining whether or not NPC is hitting Best Z calcs (blue for hit, red for miss)") +RULE_BOOL(Map, MobPathingVisualDebug, false, "Displays nodes in pathing points in realtime to help with visual debugging") RULE_REAL(Map, FixPathingZMaxDeltaSendTo, 20, "At runtime in SendTo: maximum change in Z to allow the BestZ code to apply") RULE_INT(Map, FindBestZHeightAdjust, 1, "Adds this to the current Z before seeking the best Z position") RULE_CATEGORY_END() @@ -339,6 +351,7 @@ RULE_REAL(Watermap, FishingLineStepSize, 1, "Basic step size for fishing calc, t RULE_CATEGORY_END() RULE_CATEGORY(Spells) +RULE_BOOL(Spells, AllowExtraDmgSkill, false, "Allow ExtraDmgSkill from Items, Spells, and AAs to apply ExtraDmgAmt when the ExtraDmgSkill matches the casted Spells Skill Type.") RULE_INT(Spells, BaseCritChance, 0, "Base percentage chance that everyone has to crit a spell") RULE_INT(Spells, BaseCritRatio, 100, "Base percentage bonus to damage on a successful spell crit. 100=2xdamage") RULE_INT(Spells, WizCritLevel, 12, "Level wizards first get spell crits") @@ -430,6 +443,7 @@ RULE_BOOL(Spells, IllusionsAlwaysPersist, false, "Allows Illusions to persist be RULE_BOOL(Spells, UseItemCastMessage, false, "Enable to use the \"item begins to glow\" messages when casting from an item.") RULE_BOOL(Spells, TargetsTargetRequiresCombatRange, true, "Disable to remove combat range requirement from Target's Target Spell Target Type") RULE_BOOL(Spells, NPCBuffLevelRestrictions, false, "Impose BuffLevelRestrictions on NPCs if true") +RULE_BOOL(Spells, ResurrectionEffectsBlock, true, "If enabled, resurrection effects cannot be overwritten.") RULE_CATEGORY_END() RULE_CATEGORY(Combat) @@ -566,6 +580,7 @@ RULE_BOOL(TaskSystem, RecordCompletedOptionalActivities, false, "Record complete RULE_BOOL(TaskSystem, KeepOneRecordPerCompletedTask, true, "Keep only one record per completed task") RULE_BOOL(TaskSystem, EnableTaskProximity, true, "Enable task proximity system") RULE_INT(TaskSystem, RequestCooldownTimerSeconds, 15, "Seconds between allowing characters to request tasks (live-like default: 15 seconds)") +RULE_BOOL(TaskSystem, ExpRewardsIgnoreLevelBasedEXPMods, false, "Rewarding Level Based Exp will ignore Rule LevelBasedEXPMods if true") RULE_INT(TaskSystem, SharedTasksWorldProcessRate, 6000, "Timer interval (milliseconds) that shared tasks are processed in world") RULE_INT(TaskSystem, SharedTasksTerminateTimerMS, 120000, "Delay (milliseconds) until a shared task is terminated if requirements are no longer met after member removal (default: 2 minutes)") RULE_BOOL(TaskSystem, UpdateOneElementPerTask, true, "If true (live-like) task updates only increment the first matching activity. If false all matching elements will be incremented.") @@ -583,6 +598,7 @@ RULE_INT(Range, SongMessages, 75, "The packet range in which song messages are s RULE_INT(Range, ClientPositionUpdates, 300, "Distance in which the own changed position is communicated to other clients") RULE_INT(Range, CriticalDamage, 80, "The packet range in which critical hit messages are sent") RULE_INT(Range, MobCloseScanDistance, 600, "Close scan distance") +RULE_INT(Range, MaxDistanceToClickDoors, 100, "Max distance that a client can click a door from (Client says 'You can't reach that' at roughly 25-50 for most doors)") RULE_CATEGORY_END() RULE_CATEGORY(Bots) @@ -623,6 +639,7 @@ RULE_BOOL(Chat, EnableVoiceMacros, true, "Enable voice macros") RULE_BOOL(Chat, EnableMailKeyIPVerification, true, "Setting whether the authenticity of the client should be verified via its IP address when accessing the InGame mailbox") RULE_BOOL(Chat, EnableAntiSpam, true, "Enable anti-spam system for chat") RULE_BOOL(Chat, SuppressCommandErrors, false, "Do not suppress command errors by default") +RULE_BOOL(Chat, ChannelsIgnoreNameFilter, false, "Ignore name filtering when creating new chat channels") RULE_INT(Chat, MaxPermanentPlayerChannels, 0, "Maximum number of permanent chat channels a player can make. Default 0.") RULE_INT(Chat, MinStatusToBypassAntiSpam, 100, "Minimum status to bypass the anti-spam system") RULE_INT(Chat, MinimumMessagesPerInterval, 4, "Minimum number of chat messages allowed per interval. The karma value is added to this value") @@ -744,6 +761,7 @@ RULE_BOOL(Inventory, DeleteTransformationMold, true, "False if you want mold to RULE_BOOL(Inventory, AllowAnyWeaponTransformation, false, "Weapons can use any weapon transformation") RULE_BOOL(Inventory, TransformSummonedBags, false, "Transforms summoned bags into disenchanted ones instead of deleting") RULE_BOOL(Inventory, AllowMultipleOfSameAugment, false, "Allows multiple of the same augment to be placed in an item via #augmentitem or MQ2, set to true to allow") +RULE_INT(Inventory, AlternateAugmentationSealer, 53, "Allows RoF+ clients to augment items from a special container type") RULE_CATEGORY_END() RULE_CATEGORY(Client) @@ -766,9 +784,16 @@ RULE_INT(Faction, DubiouslyFactionMinimum, -500, "Minimum faction for dubiously" RULE_INT(Faction, ThreateninglyFactionMinimum, -750, "Minimum faction for threateningly") RULE_CATEGORY_END() +RULE_CATEGORY(Analytics) +RULE_BOOL(Analytics, CrashReporting, true, "Automatic crash reporting analytics for EQEmu Server developers") +RULE_CATEGORY_END() + RULE_CATEGORY(Logging) RULE_BOOL(Logging, PrintFileFunctionAndLine, false, "Ex: [World Server] [net.cpp::main:309] Loading variables...") RULE_BOOL(Logging, WorldGMSayLogging, true, "Relay worldserver logging to zone processes via GM say output") +RULE_BOOL(Logging, PlayerEventsQSProcess, false, "Have query server process player events instead of world. Useful when wanting to use a dedicated server and database for processing player events on separate disk") +RULE_INT(Logging, BatchPlayerEventProcessIntervalSeconds, 5, "This is the interval in which player events are processed in world or qs") +RULE_INT(Logging, BatchPlayerEventProcessChunkSize, 10000, "This is the cap of events that can be inserted into the queue before a force flush. This is to keep from hitting MySQL max_allowed_packet and killing the connection") RULE_CATEGORY_END() RULE_CATEGORY(HotReload) diff --git a/common/seperator.h b/common/seperator.h index 7e81f8164..11ddfef26 100644 --- a/common/seperator.h +++ b/common/seperator.h @@ -99,8 +99,9 @@ public: } } ~Seperator() { - for (int i=0; i<=maxargnum; i++) + for (int i=0; i<=maxargnum; i++) { safe_delete_array(arg[i]); + } safe_delete_array(arg); safe_delete_array(argplus); safe_delete_array(msg); diff --git a/common/server_event_scheduler.cpp b/common/server_event_scheduler.cpp index 2fa592b22..039da168f 100644 --- a/common/server_event_scheduler.cpp +++ b/common/server_event_scheduler.cpp @@ -143,6 +143,10 @@ bool ServerEventScheduler::ValidateDatabaseConnection() // this helps inform decisions to tell all zones to reload their events bool ServerEventScheduler::CheckIfEventsChanged() { + if (!m_database) { + return false; + } + auto events = ServerScheduledEventsRepository::GetWhere(*m_database, "deleted_at is null"); // first check if the size changed, if it did this is the easiest step diff --git a/common/servertalk.h b/common/servertalk.h index 904477e21..d26319911 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -281,6 +281,9 @@ #define ServerOP_QSSendQuery 0x5006 #define ServerOP_QSPlayerDropItem 0x5007 +// player events +#define ServerOP_PlayerEvent 0x5100 + enum { CZUpdateType_Character, CZUpdateType_Group, @@ -1308,10 +1311,10 @@ struct Server_Speech_Struct { char message[0]; }; -struct QSTradeItems_Struct { - uint32 from_id; +struct PlayerLogTradeItemsEntry_Struct { + uint32 from_character_id; uint16 from_slot; - uint32 to_id; + uint32 to_character_id; uint16 to_slot; uint32 item_id; uint16 charges; @@ -1322,15 +1325,15 @@ struct QSTradeItems_Struct { uint32 aug_5; }; -struct QSPlayerLogTrade_Struct { - uint32 char1_id; - MoneyUpdate_Struct char1_money; - uint16 char1_count; - uint32 char2_id; - MoneyUpdate_Struct char2_money; - uint16 char2_count; - uint16 _detail_count; - QSTradeItems_Struct items[0]; +struct PlayerLogTrade_Struct { + uint32 character_1_id; + MoneyUpdate_Struct character_1_money; + uint16 character_1_item_count; + uint32 character_2_id; + MoneyUpdate_Struct character_2_money; + uint16 character_2_item_count; + uint16 _detail_count; + PlayerLogTradeItemsEntry_Struct item_entries[0]; }; struct QSDropItems_Struct { @@ -1806,6 +1809,11 @@ struct ServerDzCreateSerialized_Struct { char cereal_data[0]; }; +struct ServerSendPlayerEvent_Struct { + uint32_t cereal_size; + char cereal_data[0]; +}; + struct ServerFlagUpdate_Struct { uint32 account_id; int16 admin; diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 0f949f861..755978287 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -126,7 +126,7 @@ uint32 SharedDatabase::GetTotalTimeEntitledOnAccount(uint32 AccountID) { 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 += atoi(row[0]); + EntitledTime += Strings::ToInt(row[0]); } return EntitledTime; } @@ -228,8 +228,8 @@ bool SharedDatabase::VerifyInventory(uint32 account_id, int16 slot_id, const EQ: auto& row = results.begin(); - const uint32 id = atoi(row[0]); - const uint16 charges = atoi(row[1]); + const uint32 id = Strings::ToInt(row[0]); + const uint16 charges = Strings::ToInt(row[1]); uint16 expect_charges; @@ -436,7 +436,7 @@ int32 SharedDatabase::GetSharedPlatinum(uint32 account_id) auto& row = results.begin(); - return atoi(row[0]); + return Strings::ToInt(row[0]); } bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) { @@ -473,9 +473,9 @@ bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, EQ::InventoryPro for (auto& row = results.begin(); row != results.end(); ++row) { - const int32 itemid = atoi(row[0]); - const int32 charges = atoi(row[1]); - int32 slot = atoi(row[2]); + const int32 itemid = Strings::ToInt(row[0]); + const int32 charges = Strings::ToInt(row[1]); + int32 slot = Strings::ToInt(row[2]); myitem = GetItem(itemid); if(!myitem) @@ -518,17 +518,17 @@ bool SharedDatabase::GetSharedBank(uint32 id, EQ::InventoryProfile *inv, bool is } for (auto& row = results.begin(); row != results.end(); ++row) { - int16 slot_id = static_cast(atoi(row[0])); - uint32 item_id = static_cast(atoi(row[1])); - const int16 charges = static_cast(atoi(row[2])); + int16 slot_id = static_cast(Strings::ToInt(row[0])); + uint32 item_id = static_cast(Strings::ToInt(row[1])); + const int16 charges = static_cast(Strings::ToInt(row[2])); uint32 aug[EQ::invaug::SOCKET_COUNT]; - aug[0] = static_cast(atoi(row[3])); - aug[1] = static_cast(atoi(row[4])); - aug[2] = static_cast(atoi(row[5])); - aug[3] = static_cast(atoi(row[6])); - aug[4] = static_cast(atoi(row[7])); - aug[5] = static_cast(atoi(row[8])); + aug[0] = static_cast(Strings::ToInt(row[3])); + aug[1] = static_cast(Strings::ToInt(row[4])); + aug[2] = static_cast(Strings::ToInt(row[5])); + aug[3] = static_cast(Strings::ToInt(row[6])); + aug[4] = static_cast(Strings::ToInt(row[7])); + aug[5] = static_cast(Strings::ToInt(row[8])); const EQ::ItemData *item = GetItem(item_id); @@ -616,7 +616,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv) const auto bank_size = inv->GetLookup()->InventoryTypeSize.Bank; for (auto& row = results.begin(); row != results.end(); ++row) { - int16 slot_id = atoi(row[0]); + int16 slot_id = Strings::ToInt(row[0]); if (slot_id <= EQ::invslot::POSSESSIONS_END && slot_id >= EQ::invslot::POSSESSIONS_BEGIN) { // Titanium thru UF check if (((static_cast(1) << slot_id) & pmask) == 0) { @@ -645,24 +645,24 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv) } } - uint32 item_id = atoi(row[1]); - const uint16 charges = atoi(row[2]); - const uint32 color = atoul(row[3]); + uint32 item_id = Strings::ToInt(row[1]); + const uint16 charges = Strings::ToInt(row[2]); + const uint32 color = Strings::ToUnsignedInt(row[3]); uint32 aug[EQ::invaug::SOCKET_COUNT]; - aug[0] = std::stoul(row[4]); - aug[1] = std::stoul(row[5]); - aug[2] = std::stoul(row[6]); - aug[3] = std::stoul(row[7]); - aug[4] = std::stoul(row[8]); - aug[5] = std::stoul(row[9]); + aug[0] = Strings::ToUnsignedInt(row[4]); + aug[1] = Strings::ToUnsignedInt(row[5]); + aug[2] = Strings::ToUnsignedInt(row[6]); + aug[3] = Strings::ToUnsignedInt(row[7]); + aug[4] = Strings::ToUnsignedInt(row[8]); + aug[5] = Strings::ToUnsignedInt(row[9]); - const bool instnodrop = (row[10] && static_cast(atoi(row[10]))) ? true : false; + const bool instnodrop = (row[10] && static_cast(Strings::ToInt(row[10]))) ? true : false; - const uint32 ornament_icon = std::stoul(row[12]); - const uint32 ornament_idfile = std::stoul(row[13]); - uint32 ornament_hero_model = std::stoul(row[14]); + const uint32 ornament_icon = Strings::ToUnsignedInt(row[12]); + const uint32 ornament_idfile = Strings::ToUnsignedInt(row[13]); + uint32 ornament_hero_model = Strings::ToUnsignedInt(row[14]); const EQ::ItemData *item = GetItem(item_id); @@ -721,10 +721,14 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv) inst->SetCharges(charges); if (item->RecastDelay) { - if (timestamps.count(item->RecastType)) + if (item->RecastType != RECAST_TYPE_UNLINKED_ITEM && timestamps.count(item->RecastType)) { inst->SetRecastTimestamp(timestamps.at(item->RecastType)); - else + } else if (item->RecastType == RECAST_TYPE_UNLINKED_ITEM && timestamps.count(item->ID)) { + inst->SetRecastTimestamp(timestamps.at(item->ID)); + } + else { inst->SetRecastTimestamp(0); + } } if (item->IsClassCommon()) { @@ -790,23 +794,23 @@ bool SharedDatabase::GetInventory(uint32 account_id, char *name, EQ::InventoryPr } for (auto& row = results.begin(); row != results.end(); ++row) { - int16 slot_id = atoi(row[0]); - uint32 item_id = atoi(row[1]); - const int8 charges = atoi(row[2]); - const uint32 color = atoul(row[3]); + int16 slot_id = Strings::ToInt(row[0]); + uint32 item_id = Strings::ToInt(row[1]); + const int8 charges = Strings::ToInt(row[2]); + const uint32 color = Strings::ToUnsignedInt(row[3]); uint32 aug[EQ::invaug::SOCKET_COUNT]; - aug[0] = static_cast(atoi(row[4])); - aug[1] = static_cast(atoi(row[5])); - aug[2] = static_cast(atoi(row[6])); - aug[3] = static_cast(atoi(row[7])); - aug[4] = static_cast(atoi(row[8])); - aug[5] = static_cast(atoi(row[9])); + aug[0] = static_cast(Strings::ToInt(row[4])); + aug[1] = static_cast(Strings::ToInt(row[5])); + aug[2] = static_cast(Strings::ToInt(row[6])); + aug[3] = static_cast(Strings::ToInt(row[7])); + aug[4] = static_cast(Strings::ToInt(row[8])); + aug[5] = static_cast(Strings::ToInt(row[9])); - const bool instnodrop = (row[10] && static_cast(atoi(row[10]))) ? true : false; - const uint32 ornament_icon = std::stoul(row[12]); - const uint32 ornament_idfile = std::stoul(row[13]); - uint32 ornament_hero_model = std::stoul(row[14]); + const bool instnodrop = (row[10] && static_cast(Strings::ToInt(row[10]))) ? true : false; + const uint32 ornament_icon = Strings::ToUnsignedInt(row[12]); + const uint32 ornament_idfile = Strings::ToUnsignedInt(row[13]); + uint32 ornament_hero_model = Strings::ToUnsignedInt(row[14]); const EQ::ItemData *item = GetItem(item_id); if (!item) @@ -888,7 +892,7 @@ std::map SharedDatabase::GetItemRecastTimestamps(uint32 char_id) return timers; for (auto& row = results.begin(); row != results.end(); ++row) - timers[atoul(row[0])] = atoul(row[1]); + timers[Strings::ToUnsignedInt(row[0])] = Strings::ToUnsignedInt(row[1]); return timers; // RVO or move assigned } @@ -901,7 +905,7 @@ uint32 SharedDatabase::GetItemRecastTimestamp(uint32 char_id, uint32 recast_type return 0; auto& row = results.begin(); - return static_cast(atoul(row[0])); + return static_cast(Strings::ToUnsignedInt(row[0])); } void SharedDatabase::ClearOldRecastTimestamps(uint32 char_id) @@ -929,10 +933,10 @@ void SharedDatabase::GetItemsCount(int32 &item_count, uint32 &max_id) auto& row = results.begin(); if (row[0]) - max_id = atoi(row[0]); + max_id = Strings::ToInt(row[0]); if (row[1]) - item_count = atoi(row[1]); + item_count = Strings::ToInt(row[1]); } bool SharedDatabase::LoadItems(const std::string &prefix) { @@ -1014,188 +1018,188 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ memset(&item, 0, sizeof(EQ::ItemData)); // Unique Identifier - item.ID = std::stoul(row[ItemField::id]); + item.ID = Strings::ToUnsignedInt(row[ItemField::id]); // Name and Lore strn0cpy(item.Name, row[ItemField::name], sizeof(item.Name)); strn0cpy(item.Lore, row[ItemField::lore], sizeof(item.Lore)); // Flags - item.ArtifactFlag = std::stoi(row[ItemField::artifactflag]) ? true : false; - item.Attuneable = disable_attuneable ? false : std::stoi(row[ItemField::attuneable]) ? true : false; - item.BenefitFlag = std::stoi(row[ItemField::benefitflag]) ? true : false; - item.FVNoDrop = std::stoi(row[ItemField::fvnodrop]) ? true : false; - item.Magic = std::stoi(row[ItemField::magic]) ? true : false; - item.NoDrop = disable_no_drop ? static_cast(255) : static_cast(std::stoul(row[ItemField::nodrop])); - item.NoPet = disable_no_pet ? false : std::stoi(row[ItemField::nopet]) ? true : false; - item.NoRent = disable_no_rent ? static_cast(255) : static_cast(std::stoul(row[ItemField::norent])); - item.NoTransfer = disable_no_transfer ? false : std::stoi(row[ItemField::notransfer]) ? true : false; - item.PendingLoreFlag = std::stoi(row[ItemField::pendingloreflag]) ? true : false; - item.QuestItemFlag = std::stoi(row[ItemField::questitemflag]) ? true : false; - item.Stackable = std::stoi(row[ItemField::stackable]) ? true : false; - item.Tradeskills = std::stoi(row[ItemField::tradeskills]) ? true : false; - item.SummonedFlag = std::stoi(row[ItemField::summonedflag]) ? true : false; + item.ArtifactFlag = Strings::ToInt(row[ItemField::artifactflag]) ? true : false; + item.Attuneable = disable_attuneable ? false : Strings::ToInt(row[ItemField::attuneable]) ? true : false; + item.BenefitFlag = Strings::ToInt(row[ItemField::benefitflag]) ? true : false; + item.FVNoDrop = Strings::ToInt(row[ItemField::fvnodrop]) ? true : false; + item.Magic = Strings::ToInt(row[ItemField::magic]) ? true : false; + item.NoDrop = disable_no_drop ? static_cast(255) : static_cast(Strings::ToUnsignedInt(row[ItemField::nodrop])); + item.NoPet = disable_no_pet ? false : Strings::ToInt(row[ItemField::nopet]) ? true : false; + item.NoRent = disable_no_rent ? static_cast(255) : static_cast(Strings::ToUnsignedInt(row[ItemField::norent])); + item.NoTransfer = disable_no_transfer ? false : Strings::ToInt(row[ItemField::notransfer]) ? true : false; + item.PendingLoreFlag = Strings::ToInt(row[ItemField::pendingloreflag]) ? true : false; + item.QuestItemFlag = Strings::ToInt(row[ItemField::questitemflag]) ? true : false; + item.Stackable = Strings::ToInt(row[ItemField::stackable]) ? true : false; + item.Tradeskills = Strings::ToInt(row[ItemField::tradeskills]) ? true : false; + item.SummonedFlag = Strings::ToInt(row[ItemField::summonedflag]) ? true : false; // Lore - item.LoreGroup = disable_lore ? 0 : std::stoi(row[ItemField::loregroup]); + item.LoreGroup = disable_lore ? 0 : Strings::ToInt(row[ItemField::loregroup]); item.LoreFlag = disable_lore ? false : item.LoreGroup != 0; // Type - item.AugType = std::stoul(row[ItemField::augtype]); - item.ItemType = static_cast(std::stoul(row[ItemField::itemtype])); - item.SubType = std::stoi(row[ItemField::subtype]); + item.AugType = Strings::ToUnsignedInt(row[ItemField::augtype]); + item.ItemType = static_cast(Strings::ToUnsignedInt(row[ItemField::itemtype])); + item.SubType = Strings::ToInt(row[ItemField::subtype]); // Miscellaneous - item.ExpendableArrow = static_cast(std::stoul(row[ItemField::expendablearrow])); - item.Light = static_cast(std::stoi(row[ItemField::light])); - item.MaxCharges = static_cast(std::stoi(row[ItemField::maxcharges])); - item.Size = static_cast(std::stoul(row[ItemField::size])); - item.StackSize = static_cast(std::stoi(row[ItemField::stacksize])); - item.Weight = std::stoi(row[ItemField::weight]); + item.ExpendableArrow = static_cast(Strings::ToUnsignedInt(row[ItemField::expendablearrow])); + item.Light = static_cast(Strings::ToInt(row[ItemField::light])); + item.MaxCharges = static_cast(Strings::ToInt(row[ItemField::maxcharges])); + item.Size = static_cast(Strings::ToUnsignedInt(row[ItemField::size])); + item.StackSize = static_cast(Strings::ToInt(row[ItemField::stacksize])); + item.Weight = Strings::ToInt(row[ItemField::weight]); // Potion Belt - item.PotionBelt = disable_potion_belt ? false : std::stoi(row[ItemField::potionbelt]) ? true : false; - item.PotionBeltSlots = disable_potion_belt ? 0 : static_cast(std::stoul(row[ItemField::potionbeltslots])); + item.PotionBelt = disable_potion_belt ? false : Strings::ToInt(row[ItemField::potionbelt]) ? true : false; + item.PotionBeltSlots = disable_potion_belt ? 0 : static_cast(Strings::ToUnsignedInt(row[ItemField::potionbeltslots])); // Merchant - item.Favor = std::stoul(row[ItemField::favor]); - item.GuildFavor = std::stoul(row[ItemField::guildfavor]); - item.Price = std::stoul(row[ItemField::price]); - item.SellRate = std::stof(row[ItemField::sellrate]); + 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]); // Display - item.Color = std::stoul(row[ItemField::color]); - item.EliteMaterial = std::stoul(row[ItemField::elitematerial]); - item.HerosForgeModel = std::stoul(row[ItemField::herosforgemodel]); - item.Icon = std::stoul(row[ItemField::icon]); + 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(std::stoul(row[ItemField::material])); + item.Material = static_cast(Strings::ToUnsignedInt(row[ItemField::material])); // Resists - item.CR = static_cast(EQ::Clamp(std::stoi(row[ItemField::cr]), -128, 127)); - item.DR = static_cast(EQ::Clamp(std::stoi(row[ItemField::dr]), -128, 127)); - item.FR = static_cast(EQ::Clamp(std::stoi(row[ItemField::fr]), -128, 127)); - item.MR = static_cast(EQ::Clamp(std::stoi(row[ItemField::mr]), -128, 127)); - item.PR = static_cast(EQ::Clamp(std::stoi(row[ItemField::pr]), -128, 127)); - item.SVCorruption = static_cast(EQ::Clamp(std::stoi(row[ItemField::svcorruption]), -128, 127)); + item.CR = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::cr]), -128, 127)); + item.DR = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::dr]), -128, 127)); + item.FR = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::fr]), -128, 127)); + item.MR = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::mr]), -128, 127)); + item.PR = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::pr]), -128, 127)); + item.SVCorruption = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::svcorruption]), -128, 127)); // Heroic Resists - item.HeroicCR = std::stoi(row[ItemField::heroic_cr]); - item.HeroicDR = std::stoi(row[ItemField::heroic_dr]); - item.HeroicFR = std::stoi(row[ItemField::heroic_fr]); - item.HeroicMR = std::stoi(row[ItemField::heroic_mr]); - item.HeroicPR = std::stoi(row[ItemField::heroic_pr]); - item.HeroicSVCorrup = std::stoi(row[ItemField::heroic_svcorrup]); + 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]); // Stats - item.AAgi = static_cast(EQ::Clamp(std::stoi(row[ItemField::aagi]), -128, 127)); - item.ACha = static_cast(EQ::Clamp(std::stoi(row[ItemField::acha]), -128, 127)); - item.ADex = static_cast(EQ::Clamp(std::stoi(row[ItemField::adex]), -128, 127)); - item.AInt = static_cast(EQ::Clamp(std::stoi(row[ItemField::aint]), -128, 127)); - item.ASta = static_cast(EQ::Clamp(std::stoi(row[ItemField::asta]), -128, 127)); - item.AStr = static_cast(EQ::Clamp(std::stoi(row[ItemField::astr]), -128, 127)); - item.AWis = static_cast(EQ::Clamp(std::stoi(row[ItemField::awis]), -128, 127)); + item.AAgi = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::aagi]), -128, 127)); + item.ACha = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::acha]), -128, 127)); + item.ADex = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::adex]), -128, 127)); + item.AInt = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::aint]), -128, 127)); + item.ASta = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::asta]), -128, 127)); + item.AStr = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::astr]), -128, 127)); + item.AWis = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::awis]), -128, 127)); // Heroic Stats - item.HeroicAgi = std::stoi(row[ItemField::heroic_agi]); - item.HeroicCha = std::stoi(row[ItemField::heroic_cha]); - item.HeroicDex = std::stoi(row[ItemField::heroic_dex]); - item.HeroicInt = std::stoi(row[ItemField::heroic_int]); - item.HeroicSta = std::stoi(row[ItemField::heroic_sta]); - item.HeroicStr = std::stoi(row[ItemField::heroic_str]); - item.HeroicWis = std::stoi(row[ItemField::heroic_wis]); + 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]); // Health, Mana, and Endurance - item.HP = std::stoi(row[ItemField::hp]); - item.Regen = std::stoi(row[ItemField::regen]); - item.Mana = std::stoi(row[ItemField::mana]); - item.ManaRegen = std::stoi(row[ItemField::manaregen]); - item.Endur = std::stoi(row[ItemField::endur]); - item.EnduranceRegen = std::stoi(row[ItemField::enduranceregen]); + 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]); // Bane Damage - item.BaneDmgAmt = std::stoi(row[ItemField::banedmgamt]); - item.BaneDmgBody = std::stoul(row[ItemField::banedmgbody]); - item.BaneDmgRace = std::stoul(row[ItemField::banedmgrace]); - item.BaneDmgRaceAmt = std::stoul(row[ItemField::banedmgraceamt]); + 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]); // Elemental Damage - item.ElemDmgType = static_cast(std::stoul(row[ItemField::elemdmgtype])); - item.ElemDmgAmt = static_cast(std::stoul(row[ItemField::elemdmgamt])); + item.ElemDmgType = static_cast(Strings::ToUnsignedInt(row[ItemField::elemdmgtype])); + item.ElemDmgAmt = static_cast(Strings::ToUnsignedInt(row[ItemField::elemdmgamt])); // Combat - item.BackstabDmg = std::stoul(row[ItemField::backstabdmg]); - item.Damage = std::stoul(row[ItemField::damage]); - item.Delay = static_cast(std::stoul(row[ItemField::delay])); - item.Range = static_cast(std::stoul(row[ItemField::range])); + item.BackstabDmg = Strings::ToUnsignedInt(row[ItemField::backstabdmg]); + item.Damage = Strings::ToUnsignedInt(row[ItemField::damage]); + item.Delay = static_cast(Strings::ToUnsignedInt(row[ItemField::delay])); + item.Range = static_cast(Strings::ToUnsignedInt(row[ItemField::range])); // Combat Stats - item.AC = std::stoi(row[ItemField::ac]); - item.Accuracy = static_cast(EQ::Clamp(std::stoi(row[ItemField::accuracy]), -128, 127)); - item.Attack = std::stoi(row[ItemField::attack]); - item.Avoidance = static_cast(EQ::Clamp(std::stoi(row[ItemField::avoidance]), -128, 127)); - item.Clairvoyance = std::stoul(row[ItemField::clairvoyance]); - item.CombatEffects = Strings::IsNumber(row[ItemField::combateffects]) ? static_cast(EQ::Clamp(std::stoi(row[ItemField::combateffects]), -128, 127)) : 0; - item.DamageShield = std::stoi(row[ItemField::damageshield]); - item.DotShielding = std::stoi(row[ItemField::dotshielding]); - item.DSMitigation = std::stoul(row[ItemField::dsmitigation]); - item.Haste = std::stoi(row[ItemField::haste]); - item.HealAmt = std::stoi(row[ItemField::healamt]); - item.Purity = std::stoul(row[ItemField::purity]); - item.Shielding = static_cast(EQ::Clamp(std::stoi(row[ItemField::shielding]), -128, 127)); - item.SpellDmg = std::stoi(row[ItemField::spelldmg]); - item.SpellShield = static_cast(EQ::Clamp(std::stoi(row[ItemField::spellshield]), -128, 127)); - item.StrikeThrough = static_cast(EQ::Clamp(std::stoi(row[ItemField::strikethrough]), -128, 127)); - item.StunResist = static_cast(EQ::Clamp(std::stoi(row[ItemField::stunresist]), -128, 127)); + item.AC = Strings::ToInt(row[ItemField::ac]); + item.Accuracy = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::accuracy]), -128, 127)); + item.Attack = Strings::ToInt(row[ItemField::attack]); + item.Avoidance = static_cast(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(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(EQ::Clamp(Strings::ToInt(row[ItemField::shielding]), -128, 127)); + item.SpellDmg = Strings::ToInt(row[ItemField::spelldmg]); + item.SpellShield = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::spellshield]), -128, 127)); + item.StrikeThrough = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::strikethrough]), -128, 127)); + item.StunResist = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::stunresist]), -128, 127)); // Restrictions - item.AugRestrict = std::stoul(row[ItemField::augrestrict]); - item.Classes = std::stoul(row[ItemField::classes]); - item.Deity = std::stoul(row[ItemField::deity]); - item.ItemClass = static_cast(std::stoul(row[ItemField::itemclass])); - item.Races = std::stoul(row[ItemField::races]); - item.RecLevel = static_cast(std::stoul(row[ItemField::reclevel])); - item.RecSkill = static_cast(std::stoul(row[ItemField::recskill])); - item.ReqLevel = static_cast(std::stoul(row[ItemField::reqlevel])); - item.Slots = std::stoul(row[ItemField::slots]); + 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(Strings::ToUnsignedInt(row[ItemField::itemclass])); + item.Races = Strings::ToUnsignedInt(row[ItemField::races]); + item.RecLevel = static_cast(Strings::ToUnsignedInt(row[ItemField::reclevel])); + item.RecSkill = static_cast(Strings::ToUnsignedInt(row[ItemField::recskill])); + item.ReqLevel = static_cast(Strings::ToUnsignedInt(row[ItemField::reqlevel])); + item.Slots = Strings::ToUnsignedInt(row[ItemField::slots]); // Skill Modifier - item.SkillModValue = std::stoi(row[ItemField::skillmodvalue]); - item.SkillModMax = std::stoi(row[ItemField::skillmodmax]); - item.SkillModType = std::stoul(row[ItemField::skillmodtype]); + item.SkillModValue = Strings::ToInt(row[ItemField::skillmodvalue]); + item.SkillModMax = Strings::ToInt(row[ItemField::skillmodmax]); + item.SkillModType = Strings::ToUnsignedInt(row[ItemField::skillmodtype]); // Extra Damage Skill - item.ExtraDmgSkill = std::stoul(row[ItemField::extradmgskill]); - item.ExtraDmgAmt = std::stoul(row[ItemField::extradmgamt]); + item.ExtraDmgSkill = Strings::ToUnsignedInt(row[ItemField::extradmgskill]); + item.ExtraDmgAmt = Strings::ToUnsignedInt(row[ItemField::extradmgamt]); // Bard - item.BardType = std::stoul(row[ItemField::bardtype]); - item.BardValue = std::stoi(row[ItemField::bardvalue]); + item.BardType = Strings::ToUnsignedInt(row[ItemField::bardtype]); + item.BardValue = Strings::ToInt(row[ItemField::bardvalue]); // Faction - item.FactionAmt1 = std::stoi(row[ItemField::factionamt1]); - item.FactionMod1 = std::stoi(row[ItemField::factionmod1]); - item.FactionAmt2 = std::stoi(row[ItemField::factionamt2]); - item.FactionMod2 = std::stoi(row[ItemField::factionmod2]); - item.FactionAmt3 = std::stoi(row[ItemField::factionamt3]); - item.FactionMod3 = std::stoi(row[ItemField::factionmod3]); - item.FactionAmt4 = std::stoi(row[ItemField::factionamt4]); - item.FactionMod4 = std::stoi(row[ItemField::factionmod4]); + 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]); // Augment - item.AugDistiller = std::stoul(row[ItemField::augdistiller]); - item.AugSlotType[0] = static_cast(std::stoul(row[ItemField::augslot1type])); - item.AugSlotVisible[0] = static_cast(std::stoul(row[ItemField::augslot1visible])); - item.AugSlotType[1] = static_cast(std::stoul(row[ItemField::augslot2type])); - item.AugSlotVisible[1] = static_cast(std::stoul(row[ItemField::augslot2visible])); - item.AugSlotType[2] = static_cast(std::stoul(row[ItemField::augslot3type])); - item.AugSlotVisible[2] = static_cast(std::stoul(row[ItemField::augslot3visible])); - item.AugSlotType[3] = static_cast(std::stoul(row[ItemField::augslot4type])); - item.AugSlotVisible[3] = static_cast(std::stoul(row[ItemField::augslot4visible])); - item.AugSlotType[4] = static_cast(std::stoul(row[ItemField::augslot5type])); - item.AugSlotVisible[4] = static_cast(std::stoul(row[ItemField::augslot5visible])); - item.AugSlotType[5] = static_cast(std::stoul(row[ItemField::augslot6type])); - item.AugSlotVisible[5] = static_cast(std::stoul(row[ItemField::augslot6visible])); + item.AugDistiller = Strings::ToUnsignedInt(row[ItemField::augdistiller]); + item.AugSlotType[0] = static_cast(Strings::ToUnsignedInt(row[ItemField::augslot1type])); + item.AugSlotVisible[0] = static_cast(Strings::ToUnsignedInt(row[ItemField::augslot1visible])); + item.AugSlotType[1] = static_cast(Strings::ToUnsignedInt(row[ItemField::augslot2type])); + item.AugSlotVisible[1] = static_cast(Strings::ToUnsignedInt(row[ItemField::augslot2visible])); + item.AugSlotType[2] = static_cast(Strings::ToUnsignedInt(row[ItemField::augslot3type])); + item.AugSlotVisible[2] = static_cast(Strings::ToUnsignedInt(row[ItemField::augslot3visible])); + item.AugSlotType[3] = static_cast(Strings::ToUnsignedInt(row[ItemField::augslot4type])); + item.AugSlotVisible[3] = static_cast(Strings::ToUnsignedInt(row[ItemField::augslot4visible])); + item.AugSlotType[4] = static_cast(Strings::ToUnsignedInt(row[ItemField::augslot5type])); + item.AugSlotVisible[4] = static_cast(Strings::ToUnsignedInt(row[ItemField::augslot5visible])); + item.AugSlotType[5] = static_cast(Strings::ToUnsignedInt(row[ItemField::augslot6type])); + item.AugSlotVisible[5] = static_cast(Strings::ToUnsignedInt(row[ItemField::augslot6visible])); // Augment Unknowns for (uint8 i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) { @@ -1203,79 +1207,79 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ } // LDoN - item.LDoNTheme = std::stoul(row[ItemField::ldontheme]); - item.LDoNPrice = std::stoul(row[ItemField::ldonprice]); - item.LDoNSellBackRate = std::stoul(row[ItemField::ldonsellbackrate]); - item.LDoNSold = std::stoul(row[ItemField::ldonsold]); - item.PointType = std::stoul(row[ItemField::pointtype]); + 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]); // Bag - item.BagSize = static_cast(std::stoul(row[ItemField::bagsize])); - item.BagSlots = static_cast(EQ::Clamp(std::stoi(row[ItemField::bagslots]), 0, 10)); // Will need to be changed from std::min to just use database value when bag slots are increased - item.BagType = static_cast(std::stoul(row[ItemField::bagtype])); - item.BagWR = static_cast(EQ::Clamp(std::stoi(row[ItemField::bagwr]), 0, 100)); + item.BagSize = static_cast(Strings::ToUnsignedInt(row[ItemField::bagsize])); + item.BagSlots = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::bagslots]), 0, 10)); // Will need to be changed from std::min to just use database value when bag slots are increased + item.BagType = static_cast(Strings::ToUnsignedInt(row[ItemField::bagtype])); + item.BagWR = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::bagwr]), 0, 100)); // Bard Effect - item.Bard.Effect = disable_bard_focus_effects ? 0 : std::stoi(row[ItemField::bardeffect]); - item.Bard.Type = disable_bard_focus_effects ? 0 : static_cast(std::stoul(row[ItemField::bardtype])); - item.Bard.Level = disable_bard_focus_effects ? 0 : static_cast(std::stoul(row[ItemField::bardlevel])); - item.Bard.Level2 = disable_bard_focus_effects ? 0 : static_cast(std::stoul(row[ItemField::bardlevel2])); + item.Bard.Effect = disable_bard_focus_effects ? 0 : Strings::ToInt(row[ItemField::bardeffect]); + item.Bard.Type = disable_bard_focus_effects ? 0 : static_cast(Strings::ToUnsignedInt(row[ItemField::bardtype])); + item.Bard.Level = disable_bard_focus_effects ? 0 : static_cast(Strings::ToUnsignedInt(row[ItemField::bardlevel])); + item.Bard.Level2 = disable_bard_focus_effects ? 0 : static_cast(Strings::ToUnsignedInt(row[ItemField::bardlevel2])); // Book - item.Book = static_cast(std::stoul(row[ItemField::book])); - item.BookType = std::stoul(row[ItemField::booktype]); + item.Book = static_cast(Strings::ToUnsignedInt(row[ItemField::book])); + item.BookType = Strings::ToUnsignedInt(row[ItemField::booktype]); // Click Effect - item.CastTime = std::stoul(row[ItemField::casttime]); - item.CastTime_ = std::stoi(row[ItemField::casttime_]); - item.Click.Effect = std::stoi(row[ItemField::clickeffect]); - item.Click.Type = static_cast(std::stoul(row[ItemField::clicktype])); - item.Click.Level = static_cast(std::stoul(row[ItemField::clicklevel])); - item.Click.Level2 = static_cast(std::stoul(row[ItemField::clicklevel2])); + 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(Strings::ToUnsignedInt(row[ItemField::clicktype])); + item.Click.Level = static_cast(Strings::ToUnsignedInt(row[ItemField::clicklevel])); + item.Click.Level2 = static_cast(Strings::ToUnsignedInt(row[ItemField::clicklevel2])); strn0cpy(item.ClickName, row[ItemField::clickname], sizeof(item.ClickName)); - item.RecastDelay = std::stoul(row[ItemField::recastdelay]); - item.RecastType = std::stoi(row[ItemField::recasttype]); + item.RecastDelay = Strings::ToUnsignedInt(row[ItemField::recastdelay]); + item.RecastType = Strings::ToInt(row[ItemField::recasttype]); // Focus Effect - item.Focus.Effect = disable_spell_focus_effects ? 0 : std::stoi(row[ItemField::focuseffect]); - item.Focus.Type = disable_spell_focus_effects ? 0 : static_cast(std::stoul(row[ItemField::focustype])); - item.Focus.Level = disable_spell_focus_effects ? 0 : static_cast(std::stoul(row[ItemField::focuslevel])); - item.Focus.Level2 = disable_spell_focus_effects ? 0 : static_cast(std::stoul(row[ItemField::focuslevel2])); + item.Focus.Effect = disable_spell_focus_effects ? 0 : Strings::ToInt(row[ItemField::focuseffect]); + item.Focus.Type = disable_spell_focus_effects ? 0 : static_cast(Strings::ToUnsignedInt(row[ItemField::focustype])); + item.Focus.Level = disable_spell_focus_effects ? 0 : static_cast(Strings::ToUnsignedInt(row[ItemField::focuslevel])); + item.Focus.Level2 = disable_spell_focus_effects ? 0 : static_cast(Strings::ToUnsignedInt(row[ItemField::focuslevel2])); strn0cpy(item.FocusName, disable_spell_focus_effects ? "" : row[ItemField::focusname], sizeof(item.FocusName)); // Proc Effect - item.Proc.Effect = std::stoi(row[ItemField::proceffect]); - item.Proc.Type = static_cast(std::stoul(row[ItemField::proctype])); - item.Proc.Level = static_cast(std::stoul(row[ItemField::proclevel])); - item.Proc.Level2 = static_cast(std::stoul(row[ItemField::proclevel2])); + item.Proc.Effect = Strings::ToInt(row[ItemField::proceffect]); + item.Proc.Type = static_cast(Strings::ToUnsignedInt(row[ItemField::proctype])); + item.Proc.Level = static_cast(Strings::ToUnsignedInt(row[ItemField::proclevel])); + item.Proc.Level2 = static_cast(Strings::ToUnsignedInt(row[ItemField::proclevel2])); strn0cpy(item.ProcName, row[ItemField::procname], sizeof(item.ProcName)); - item.ProcRate = std::stoi(row[ItemField::procrate]); + item.ProcRate = Strings::ToInt(row[ItemField::procrate]); // Scroll Effect - item.Scroll.Effect = std::stoi(row[ItemField::scrolleffect]); - item.Scroll.Type = static_cast(std::stoul(row[ItemField::scrolltype])); - item.Scroll.Level = static_cast(std::stoul(row[ItemField::scrolllevel])); - item.Scroll.Level2 = static_cast(std::stoul(row[ItemField::scrolllevel2])); + item.Scroll.Effect = Strings::ToInt(row[ItemField::scrolleffect]); + item.Scroll.Type = static_cast(Strings::ToUnsignedInt(row[ItemField::scrolltype])); + item.Scroll.Level = static_cast(Strings::ToUnsignedInt(row[ItemField::scrolllevel])); + item.Scroll.Level2 = static_cast(Strings::ToUnsignedInt(row[ItemField::scrolllevel2])); strn0cpy(item.ScrollName, row[ItemField::scrollname], sizeof(item.ScrollName)); // Worn Effect - item.Worn.Effect = std::stoi(row[ItemField::worneffect]); - item.Worn.Type = static_cast(std::stoul(row[ItemField::worntype])); - item.Worn.Level = static_cast(std::stoul(row[ItemField::wornlevel])); - item.Worn.Level2 = static_cast(std::stoul(row[ItemField::wornlevel2])); + item.Worn.Effect = Strings::ToInt(row[ItemField::worneffect]); + item.Worn.Type = static_cast(Strings::ToUnsignedInt(row[ItemField::worntype])); + item.Worn.Level = static_cast(Strings::ToUnsignedInt(row[ItemField::wornlevel])); + item.Worn.Level2 = static_cast(Strings::ToUnsignedInt(row[ItemField::wornlevel2])); strn0cpy(item.WornName, row[ItemField::wornname], sizeof(item.WornName)); // Evolving Item - item.EvolvingID = std::stoul(row[ItemField::evoid]); - item.EvolvingItem = static_cast(std::stoul(row[ItemField::evoitem])); - item.EvolvingLevel = static_cast(std::stoul(row[ItemField::evolvinglevel])); - item.EvolvingMax = static_cast(std::stoul(row[ItemField::evomax])); + item.EvolvingID = Strings::ToUnsignedInt(row[ItemField::evoid]); + item.EvolvingItem = static_cast(Strings::ToUnsignedInt(row[ItemField::evoitem])); + item.EvolvingLevel = static_cast(Strings::ToUnsignedInt(row[ItemField::evolvinglevel])); + item.EvolvingMax = static_cast(Strings::ToUnsignedInt(row[ItemField::evomax])); // Scripting - item.CharmFileID = Strings::IsNumber(row[ItemField::charmfileid]) ? std::stoul(row[ItemField::charmfileid]) : 0; + 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 = std::stoul(row[ItemField::scriptfileid]); + item.ScriptFileID = Strings::ToUnsignedInt(row[ItemField::scriptfileid]); try { hash.insert(item.ID, item); @@ -1345,7 +1349,7 @@ std::string SharedDatabase::GetBook(const char *txtfile, int16 *language) auto& row = results.begin(); txtout.assign(row[0],strlen(row[0])); - *language = static_cast(atoi(row[1])); + *language = static_cast(Strings::ToInt(row[1])); return txtout; } @@ -1365,8 +1369,8 @@ void SharedDatabase::GetFactionListInfo(uint32 &list_count, uint32 &max_lists) { auto& row = results.begin(); - list_count = static_cast(atoul(row[0])); - max_lists = static_cast(atoul(row[1] ? row[1] : "0")); + list_count = static_cast(Strings::ToUnsignedInt(row[0])); + max_lists = static_cast(Strings::ToUnsignedInt(row[1] ? row[1] : "0")); } const NPCFactionList* SharedDatabase::GetNPCFactionEntry(uint32 id) const @@ -1399,7 +1403,7 @@ void SharedDatabase::LoadNPCFactionLists(void *data, uint32 size, uint32 list_co uint32 current_entry = 0; for(auto& row = results.begin(); row != results.end(); ++row) { - const uint32 id = static_cast(atoul(row[0])); + const uint32 id = static_cast(Strings::ToUnsignedInt(row[0])); if(id != current_id) { if(current_id != 0) { hash.insert(current_id, faction); @@ -1409,8 +1413,8 @@ void SharedDatabase::LoadNPCFactionLists(void *data, uint32 size, uint32 list_co current_entry = 0; current_id = id; faction.id = id; - faction.primaryfaction = static_cast(atoul(row[1])); - faction.assistprimaryfaction = (atoi(row[2]) == 0); + faction.primaryfaction = static_cast(Strings::ToUnsignedInt(row[1])); + faction.assistprimaryfaction = (Strings::ToInt(row[2]) == 0); } if(!row[3]) @@ -1419,10 +1423,10 @@ void SharedDatabase::LoadNPCFactionLists(void *data, uint32 size, uint32 list_co if(current_entry >= MAX_NPC_FACTIONS) continue; - faction.factionid[current_entry] = static_cast(atoul(row[3])); - faction.factionvalue[current_entry] = static_cast(atoi(row[4])); - faction.factionnpcvalue[current_entry] = static_cast(atoi(row[5])); - faction.factiontemp[current_entry] = static_cast(atoi(row[6])); + faction.factionid[current_entry] = static_cast(Strings::ToUnsignedInt(row[3])); + faction.factionvalue[current_entry] = static_cast(Strings::ToInt(row[4])); + faction.factionnpcvalue[current_entry] = static_cast(Strings::ToInt(row[5])); + faction.factiontemp[current_entry] = static_cast(Strings::ToInt(row[6])); ++current_entry; } @@ -1660,7 +1664,7 @@ bool SharedDatabase::GetCommandSettings(std::map= skill_count || class_ >= class_count || level >= level_count) continue; @@ -1860,9 +1864,9 @@ void SharedDatabase::LoadDamageShieldTypes(SPDat_Spell_Struct* sp, int32 iMaxSpe } for(auto& row = results.begin(); row != results.end(); ++row) { - const int spellID = atoi(row[0]); + const int spellID = Strings::ToInt(row[0]); if((spellID > 0) && (spellID <= iMaxSpellID)) - sp[spellID].damage_shield_type = atoi(row[1]); + sp[spellID].damage_shield_type = Strings::ToInt(row[1]); } } @@ -1880,7 +1884,7 @@ int SharedDatabase::GetMaxSpellID() { auto& row = results.begin(); - return atoi(row[0]); + return Strings::ToInt(row[0]); } bool SharedDatabase::LoadSpells(const std::string &prefix, int32 *records, const SPDat_Spell_Struct **sp) { @@ -1926,7 +1930,7 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { int counter = 0; for (auto& row = results.begin(); row != results.end(); ++row) { - const int tempid = atoi(row[0]); + const int tempid = Strings::ToInt(row[0]); if(tempid >= max_spells) { LogSpells("Non fatal error: spell.id >= max_spells, ignoring"); continue; @@ -1943,141 +1947,141 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { strn0cpy(sp[tempid].cast_on_other, row[7], sizeof(sp[tempid].cast_on_other)); strn0cpy(sp[tempid].spell_fades, row[8], sizeof(sp[tempid].spell_fades)); - sp[tempid].range=static_cast(atof(row[9])); - sp[tempid].aoe_range=static_cast(atof(row[10])); - sp[tempid].push_back=static_cast(atof(row[11])); - sp[tempid].push_up=static_cast(atof(row[12])); - sp[tempid].cast_time=atoi(row[13]); - sp[tempid].recovery_time=atoi(row[14]); - sp[tempid].recast_time=atoi(row[15]); - sp[tempid].buff_duration_formula=atoi(row[16]); - sp[tempid].buff_duration=atoi(row[17]); - sp[tempid].aoe_duration=atoi(row[18]); - sp[tempid].mana=atoi(row[19]); + sp[tempid].range=static_cast(Strings::ToFloat(row[9])); + sp[tempid].aoe_range=static_cast(Strings::ToFloat(row[10])); + sp[tempid].push_back=static_cast(Strings::ToFloat(row[11])); + sp[tempid].push_up=static_cast(Strings::ToFloat(row[12])); + sp[tempid].cast_time=Strings::ToInt(row[13]); + sp[tempid].recovery_time=Strings::ToInt(row[14]); + sp[tempid].recast_time=Strings::ToInt(row[15]); + sp[tempid].buff_duration_formula=Strings::ToInt(row[16]); + sp[tempid].buff_duration=Strings::ToInt(row[17]); + sp[tempid].aoe_duration=Strings::ToInt(row[18]); + sp[tempid].mana=Strings::ToInt(row[19]); int y=0; for(y=0; y< EFFECT_COUNT;y++) - sp[tempid].base_value[y]=atoi(row[20+y]); // effect_base_value + sp[tempid].base_value[y]=Strings::ToInt(row[20+y]); // effect_base_value for(y=0; y < EFFECT_COUNT; y++) - sp[tempid].limit_value[y]=atoi(row[32+y]); // effect_limit_value + sp[tempid].limit_value[y]=Strings::ToInt(row[32+y]); // effect_limit_value for(y=0; y< EFFECT_COUNT;y++) - sp[tempid].max_value[y]=atoi(row[44+y]); + sp[tempid].max_value[y]=Strings::ToInt(row[44+y]); for(y=0; y< 4;y++) - sp[tempid].component[y]=atoi(row[58+y]); + sp[tempid].component[y]=Strings::ToInt(row[58+y]); for(y=0; y< 4;y++) - sp[tempid].component_count[y]=atoi(row[62+y]); + sp[tempid].component_count[y]=Strings::ToInt(row[62+y]); for(y=0; y< 4;y++) - sp[tempid].no_expend_reagent[y]=atoi(row[66+y]); + sp[tempid].no_expend_reagent[y]=Strings::ToInt(row[66+y]); for(y=0; y< EFFECT_COUNT;y++) - sp[tempid].formula[y]=atoi(row[70+y]); + sp[tempid].formula[y]=Strings::ToInt(row[70+y]); - sp[tempid].good_effect=atoi(row[83]); - sp[tempid].activated=atoi(row[84]); - sp[tempid].resist_type=atoi(row[85]); + sp[tempid].good_effect=Strings::ToInt(row[83]); + sp[tempid].activated=Strings::ToInt(row[84]); + sp[tempid].resist_type=Strings::ToInt(row[85]); for(y=0; y< EFFECT_COUNT;y++) - sp[tempid].effect_id[y]=atoi(row[86+y]); + sp[tempid].effect_id[y]=Strings::ToInt(row[86+y]); - sp[tempid].target_type = static_cast(atoi(row[98])); - sp[tempid].base_difficulty=atoi(row[99]); + sp[tempid].target_type = static_cast(Strings::ToInt(row[98])); + sp[tempid].base_difficulty=Strings::ToInt(row[99]); - int tmp_skill = atoi(row[100]); + int tmp_skill = Strings::ToInt(row[100]); if (tmp_skill < 0 || tmp_skill > EQ::skills::HIGHEST_SKILL) sp[tempid].skill = EQ::skills::SkillBegging; /* not much better we can do. */ // can probably be changed to client-based 'SkillNone' once activated else sp[tempid].skill = static_cast(tmp_skill); - sp[tempid].zone_type=atoi(row[101]); - sp[tempid].environment_type=atoi(row[102]); - sp[tempid].time_of_day=atoi(row[103]); + sp[tempid].zone_type=Strings::ToInt(row[101]); + sp[tempid].environment_type=Strings::ToInt(row[102]); + sp[tempid].time_of_day=Strings::ToInt(row[103]); for(y=0; y < PLAYER_CLASS_COUNT;y++) - sp[tempid].classes[y]=atoi(row[104+y]); + sp[tempid].classes[y]=Strings::ToInt(row[104+y]); - sp[tempid].casting_animation=atoi(row[120]); - sp[tempid].spell_affect_index=atoi(row[123]); - sp[tempid].disallow_sit=atoi(row[124]); - sp[tempid].deity_agnostic=atoi(row[125]); + sp[tempid].casting_animation=Strings::ToInt(row[120]); + sp[tempid].spell_affect_index=Strings::ToInt(row[123]); + sp[tempid].disallow_sit=Strings::ToInt(row[124]); + sp[tempid].deity_agnostic=Strings::ToInt(row[125]); for (y = 0; y < 16; y++) - sp[tempid].deities[y]=atoi(row[126+y]); + sp[tempid].deities[y]=Strings::ToInt(row[126+y]); - sp[tempid].new_icon=atoi(row[144]); - sp[tempid].uninterruptable=atoi(row[146]) != 0; - sp[tempid].resist_difficulty=atoi(row[147]); - sp[tempid].unstackable_dot = atoi(row[148]) != 0; - sp[tempid].recourse_link = atoi(row[150]); - sp[tempid].no_partial_resist = atoi(row[151]) != 0; + sp[tempid].new_icon=Strings::ToInt(row[144]); + sp[tempid].uninterruptable=Strings::ToInt(row[146]) != 0; + sp[tempid].resist_difficulty=Strings::ToInt(row[147]); + sp[tempid].unstackable_dot = Strings::ToInt(row[148]) != 0; + sp[tempid].recourse_link = Strings::ToInt(row[150]); + sp[tempid].no_partial_resist = Strings::ToInt(row[151]) != 0; - sp[tempid].short_buff_box = atoi(row[154]); - sp[tempid].description_id = atoi(row[155]); - sp[tempid].type_description_id = atoi(row[156]); - sp[tempid].effect_description_id = atoi(row[157]); + sp[tempid].short_buff_box = Strings::ToInt(row[154]); + sp[tempid].description_id = Strings::ToInt(row[155]); + sp[tempid].type_description_id = Strings::ToInt(row[156]); + sp[tempid].effect_description_id = Strings::ToInt(row[157]); - sp[tempid].npc_no_los = atoi(row[159]) != 0; - sp[tempid].feedbackable = atoi(row[160]) != 0; - sp[tempid].reflectable = atoi(row[161]) != 0; - sp[tempid].bonus_hate=atoi(row[162]); + sp[tempid].npc_no_los = Strings::ToInt(row[159]) != 0; + sp[tempid].feedbackable = Strings::ToInt(row[160]) != 0; + sp[tempid].reflectable = Strings::ToInt(row[161]) != 0; + sp[tempid].bonus_hate=Strings::ToInt(row[162]); - sp[tempid].ldon_trap = atoi(row[165]) != 0; - sp[tempid].endurance_cost=atoi(row[166]); - sp[tempid].timer_id=atoi(row[167]); - sp[tempid].is_discipline = atoi(row[168]) != 0; - sp[tempid].hate_added=atoi(row[173]); - sp[tempid].endurance_upkeep=atoi(row[174]); - sp[tempid].hit_number_type = atoi(row[175]); - sp[tempid].hit_number = atoi(row[176]); - sp[tempid].pvp_resist_base=atoi(row[177]); - sp[tempid].pvp_resist_per_level=atoi(row[178]); - sp[tempid].pvp_resist_cap=atoi(row[179]); - sp[tempid].spell_category=atoi(row[180]); - sp[tempid].pvp_duration = atoi(row[181]); - sp[tempid].pvp_duration_cap = atoi(row[182]); - sp[tempid].pcnpc_only_flag=atoi(row[183]); - sp[tempid].cast_not_standing = atoi(row[184]) != 0; - sp[tempid].can_mgb=atoi(row[185]); - sp[tempid].dispel_flag = atoi(row[186]); - sp[tempid].min_resist = atoi(row[189]); - sp[tempid].max_resist = atoi(row[190]); - sp[tempid].viral_targets = atoi(row[191]); - sp[tempid].viral_timer = atoi(row[192]); - sp[tempid].nimbus_effect = atoi(row[193]); - sp[tempid].directional_start = static_cast(atoi(row[194])); - sp[tempid].directional_end = static_cast(atoi(row[195])); - sp[tempid].sneak = atoi(row[196]) != 0; - sp[tempid].not_focusable = atoi(row[197]) != 0; - sp[tempid].no_detrimental_spell_aggro = atoi(row[198]) != 0; - sp[tempid].suspendable = atoi(row[200]) != 0; - sp[tempid].viral_range = atoi(row[201]); - sp[tempid].song_cap = atoi(row[202]); - sp[tempid].no_block = atoi(row[205]); - sp[tempid].spell_group=atoi(row[207]); - sp[tempid].rank = atoi(row[208]); - sp[tempid].no_resist=atoi(row[209]); - sp[tempid].cast_restriction = atoi(row[211]); - sp[tempid].allow_rest = atoi(row[212]) != 0; - sp[tempid].can_cast_in_combat = atoi(row[213]) != 0; - sp[tempid].can_cast_out_of_combat = atoi(row[214]) != 0; - sp[tempid].override_crit_chance = atoi(row[217]); - sp[tempid].aoe_max_targets = atoi(row[218]); - sp[tempid].no_heal_damage_item_mod = atoi(row[219]); - sp[tempid].caster_requirement_id = atoi(row[220]); - sp[tempid].spell_class = atoi(row[221]); - sp[tempid].spell_subclass = atoi(row[222]); - sp[tempid].persist_death = atoi(row[224]) != 0; - sp[tempid].min_distance = static_cast(atof(row[227])); - sp[tempid].min_distance_mod = static_cast(atof(row[228])); - sp[tempid].max_distance = static_cast(atof(row[229])); - sp[tempid].max_distance_mod = static_cast(atof(row[230])); - sp[tempid].min_range = static_cast(atoi(row[231])); - sp[tempid].no_remove = atoi(row[232]) != 0; + sp[tempid].ldon_trap = Strings::ToInt(row[165]) != 0; + sp[tempid].endurance_cost=Strings::ToInt(row[166]); + sp[tempid].timer_id=Strings::ToInt(row[167]); + sp[tempid].is_discipline = Strings::ToInt(row[168]) != 0; + sp[tempid].hate_added=Strings::ToInt(row[173]); + sp[tempid].endurance_upkeep=Strings::ToInt(row[174]); + sp[tempid].hit_number_type = Strings::ToInt(row[175]); + sp[tempid].hit_number = Strings::ToInt(row[176]); + sp[tempid].pvp_resist_base=Strings::ToInt(row[177]); + sp[tempid].pvp_resist_per_level=Strings::ToInt(row[178]); + sp[tempid].pvp_resist_cap=Strings::ToInt(row[179]); + sp[tempid].spell_category=Strings::ToInt(row[180]); + sp[tempid].pvp_duration = Strings::ToInt(row[181]); + sp[tempid].pvp_duration_cap = Strings::ToInt(row[182]); + sp[tempid].pcnpc_only_flag=Strings::ToInt(row[183]); + sp[tempid].cast_not_standing = Strings::ToInt(row[184]) != 0; + sp[tempid].can_mgb=Strings::ToInt(row[185]); + sp[tempid].dispel_flag = Strings::ToInt(row[186]); + sp[tempid].min_resist = Strings::ToInt(row[189]); + sp[tempid].max_resist = Strings::ToInt(row[190]); + sp[tempid].viral_targets = Strings::ToInt(row[191]); + sp[tempid].viral_timer = Strings::ToInt(row[192]); + sp[tempid].nimbus_effect = Strings::ToInt(row[193]); + sp[tempid].directional_start = static_cast(Strings::ToInt(row[194])); + sp[tempid].directional_end = static_cast(Strings::ToInt(row[195])); + sp[tempid].sneak = Strings::ToInt(row[196]) != 0; + sp[tempid].not_focusable = Strings::ToInt(row[197]) != 0; + sp[tempid].no_detrimental_spell_aggro = Strings::ToInt(row[198]) != 0; + sp[tempid].suspendable = Strings::ToInt(row[200]) != 0; + sp[tempid].viral_range = Strings::ToInt(row[201]); + sp[tempid].song_cap = Strings::ToInt(row[202]); + sp[tempid].no_block = Strings::ToInt(row[205]); + sp[tempid].spell_group=Strings::ToInt(row[207]); + sp[tempid].rank = Strings::ToInt(row[208]); + sp[tempid].no_resist=Strings::ToInt(row[209]); + sp[tempid].cast_restriction = Strings::ToInt(row[211]); + sp[tempid].allow_rest = Strings::ToInt(row[212]) != 0; + sp[tempid].can_cast_in_combat = Strings::ToInt(row[213]) != 0; + sp[tempid].can_cast_out_of_combat = Strings::ToInt(row[214]) != 0; + sp[tempid].override_crit_chance = Strings::ToInt(row[217]); + sp[tempid].aoe_max_targets = Strings::ToInt(row[218]); + sp[tempid].no_heal_damage_item_mod = Strings::ToInt(row[219]); + sp[tempid].caster_requirement_id = Strings::ToInt(row[220]); + sp[tempid].spell_class = Strings::ToInt(row[221]); + sp[tempid].spell_subclass = Strings::ToInt(row[222]); + sp[tempid].persist_death = Strings::ToInt(row[224]) != 0; + sp[tempid].min_distance = static_cast(Strings::ToFloat(row[227])); + sp[tempid].min_distance_mod = static_cast(Strings::ToFloat(row[228])); + sp[tempid].max_distance = static_cast(Strings::ToFloat(row[229])); + sp[tempid].max_distance_mod = static_cast(Strings::ToFloat(row[230])); + sp[tempid].min_range = static_cast(Strings::ToInt(row[231])); + sp[tempid].no_remove = Strings::ToInt(row[232]) != 0; sp[tempid].damage_shield_type = 0; } @@ -2096,7 +2100,7 @@ int SharedDatabase::GetMaxBaseDataLevel() { auto& row = results.begin(); - return atoi(row[0]); + return Strings::ToInt(row[0]); } bool SharedDatabase::LoadBaseData(const std::string &prefix) { @@ -2130,8 +2134,8 @@ void SharedDatabase::LoadBaseData(void *data, int max_level) { } for (auto& row = results.begin(); row != results.end(); ++row) { - const int lvl = atoi(row[0]); - const int cl = atoi(row[1]); + const int lvl = Strings::ToInt(row[0]); + const int cl = Strings::ToInt(row[1]); if(lvl <= 0) { LogError("Non fatal error: base_data.level <= 0, ignoring."); @@ -2154,14 +2158,14 @@ void SharedDatabase::LoadBaseData(void *data, int max_level) { } BaseDataStruct *bd = reinterpret_cast(base_ptr + (((16 * (lvl - 1)) + (cl - 1)) * sizeof(BaseDataStruct))); - bd->base_hp = atof(row[2]); - bd->base_mana = atof(row[3]); - bd->base_end = atof(row[4]); - bd->hp_regen = atof(row[5]); - bd->end_regen = atof(row[6]); - bd->hp_factor = atof(row[7]); - bd->mana_factor = atof(row[8]); - bd->endurance_factor = atof(row[9]); + bd->base_hp = Strings::ToFloat(row[2]); + bd->base_mana = Strings::ToFloat(row[3]); + bd->base_end = Strings::ToFloat(row[4]); + bd->hp_regen = Strings::ToFloat(row[5]); + bd->end_regen = Strings::ToFloat(row[6]); + bd->hp_factor = Strings::ToFloat(row[7]); + bd->mana_factor = Strings::ToFloat(row[8]); + bd->endurance_factor = Strings::ToFloat(row[9]); } } @@ -2214,9 +2218,9 @@ void SharedDatabase::GetLootTableInfo(uint32 &loot_table_count, uint32 &max_loot auto& row = results.begin(); - loot_table_count = static_cast(atoul(row[0])); - max_loot_table = static_cast(atoul(row[1] ? row[1] : "0")); - loot_table_entries = static_cast(atoul(row[2])); + loot_table_count = static_cast(Strings::ToUnsignedInt(row[0])); + max_loot_table = static_cast(Strings::ToUnsignedInt(row[1] ? row[1] : "0")); + loot_table_entries = static_cast(Strings::ToUnsignedInt(row[2])); } void SharedDatabase::GetLootDropInfo(uint32 &loot_drop_count, uint32 &max_loot_drop, uint32 &loot_drop_entries) { @@ -2239,9 +2243,9 @@ void SharedDatabase::GetLootDropInfo(uint32 &loot_drop_count, uint32 &max_loot_d auto& row =results.begin(); - loot_drop_count = static_cast(atoul(row[0])); - max_loot_drop = static_cast(atoul(row[1] ? row[1] : "0")); - loot_drop_entries = static_cast(atoul(row[2])); + loot_drop_count = static_cast(Strings::ToUnsignedInt(row[0])); + max_loot_drop = static_cast(Strings::ToUnsignedInt(row[1] ? row[1] : "0")); + loot_drop_entries = static_cast(Strings::ToUnsignedInt(row[2])); } void SharedDatabase::LoadLootTables(void *data, uint32 size) { @@ -2285,7 +2289,7 @@ void SharedDatabase::LoadLootTables(void *data, uint32 size) { uint32 current_entry = 0; for (auto& row = results.begin(); row != results.end(); ++row) { - const uint32 id = static_cast(atoul(row[0])); + const uint32 id = static_cast(Strings::ToUnsignedInt(row[0])); if (id != current_id) { if (current_id != 0) { hash.insert( @@ -2297,12 +2301,12 @@ void SharedDatabase::LoadLootTables(void *data, uint32 size) { memset(loot_table, 0, sizeof(LootTable_Struct) + (sizeof(LootTableEntries_Struct) * 128)); current_entry = 0; current_id = id; - lt->mincash = static_cast(atoul(row[1])); - lt->maxcash = static_cast(atoul(row[2])); - lt->avgcoin = static_cast(atoul(row[3])); + lt->mincash = static_cast(Strings::ToUnsignedInt(row[1])); + lt->maxcash = static_cast(Strings::ToUnsignedInt(row[2])); + lt->avgcoin = static_cast(Strings::ToUnsignedInt(row[3])); - lt->content_flags.min_expansion = static_cast(atoi(row[9])); - lt->content_flags.max_expansion = static_cast(atoi(row[10])); + lt->content_flags.min_expansion = static_cast(Strings::ToInt(row[9])); + lt->content_flags.max_expansion = static_cast(Strings::ToInt(row[10])); strn0cpy(lt->content_flags.content_flags, row[11], sizeof(lt->content_flags.content_flags)); strn0cpy(lt->content_flags.content_flags_disabled, row[12], sizeof(lt->content_flags.content_flags_disabled)); @@ -2316,11 +2320,11 @@ void SharedDatabase::LoadLootTables(void *data, uint32 size) { continue; } - lt->Entries[current_entry].lootdrop_id = static_cast(atoul(row[4])); - lt->Entries[current_entry].multiplier = static_cast(atoi(row[5])); - lt->Entries[current_entry].droplimit = static_cast(atoi(row[6])); - lt->Entries[current_entry].mindrop = static_cast(atoi(row[7])); - lt->Entries[current_entry].probability = static_cast(atof(row[8])); + lt->Entries[current_entry].lootdrop_id = static_cast(Strings::ToUnsignedInt(row[4])); + lt->Entries[current_entry].multiplier = static_cast(Strings::ToInt(row[5])); + lt->Entries[current_entry].droplimit = static_cast(Strings::ToInt(row[6])); + lt->Entries[current_entry].mindrop = static_cast(Strings::ToInt(row[7])); + lt->Entries[current_entry].probability = static_cast(Strings::ToFloat(row[8])); ++(lt->NumEntries); ++current_entry; @@ -2379,7 +2383,7 @@ void SharedDatabase::LoadLootDrops(void *data, uint32 size) { uint32 current_entry = 0; for (auto& row = results.begin(); row != results.end(); ++row) { - const auto id = static_cast(atoul(row[0])); + const auto id = static_cast(Strings::ToUnsignedInt(row[0])); if (id != current_id) { if (current_id != 0) { hash.insert( @@ -2392,8 +2396,8 @@ void SharedDatabase::LoadLootDrops(void *data, uint32 size) { current_entry = 0; current_id = id; - p_loot_drop_struct->content_flags.min_expansion = static_cast(atoi(row[10])); - p_loot_drop_struct->content_flags.max_expansion = static_cast(atoi(row[11])); + p_loot_drop_struct->content_flags.min_expansion = static_cast(Strings::ToInt(row[10])); + p_loot_drop_struct->content_flags.max_expansion = static_cast(Strings::ToInt(row[11])); strn0cpy(p_loot_drop_struct->content_flags.content_flags, row[12], sizeof(p_loot_drop_struct->content_flags.content_flags)); strn0cpy(p_loot_drop_struct->content_flags.content_flags_disabled, row[13], sizeof(p_loot_drop_struct->content_flags.content_flags_disabled)); @@ -2403,15 +2407,15 @@ void SharedDatabase::LoadLootDrops(void *data, uint32 size) { continue; } - p_loot_drop_struct->Entries[current_entry].item_id = static_cast(atoul(row[1])); - p_loot_drop_struct->Entries[current_entry].item_charges = static_cast(atoi(row[2])); - p_loot_drop_struct->Entries[current_entry].equip_item = static_cast(atoi(row[3])); - p_loot_drop_struct->Entries[current_entry].chance = static_cast(atof(row[4])); - p_loot_drop_struct->Entries[current_entry].trivial_min_level = static_cast(atoi(row[5])); - p_loot_drop_struct->Entries[current_entry].trivial_max_level = static_cast(atoi(row[6])); - p_loot_drop_struct->Entries[current_entry].npc_min_level = static_cast(atoi(row[7])); - p_loot_drop_struct->Entries[current_entry].npc_max_level = static_cast(atoi(row[8])); - p_loot_drop_struct->Entries[current_entry].multiplier = static_cast(atoi(row[9])); + p_loot_drop_struct->Entries[current_entry].item_id = static_cast(Strings::ToUnsignedInt(row[1])); + p_loot_drop_struct->Entries[current_entry].item_charges = static_cast(Strings::ToInt(row[2])); + p_loot_drop_struct->Entries[current_entry].equip_item = static_cast(Strings::ToInt(row[3])); + p_loot_drop_struct->Entries[current_entry].chance = static_cast(Strings::ToFloat(row[4])); + p_loot_drop_struct->Entries[current_entry].trivial_min_level = static_cast(Strings::ToInt(row[5])); + p_loot_drop_struct->Entries[current_entry].trivial_max_level = static_cast(Strings::ToInt(row[6])); + p_loot_drop_struct->Entries[current_entry].npc_min_level = static_cast(Strings::ToInt(row[7])); + p_loot_drop_struct->Entries[current_entry].npc_max_level = static_cast(Strings::ToInt(row[8])); + p_loot_drop_struct->Entries[current_entry].multiplier = static_cast(Strings::ToInt(row[9])); ++(p_loot_drop_struct->NumEntries); ++current_entry; @@ -2507,7 +2511,7 @@ uint32 SharedDatabase::GetSpellsCount() auto& row = results.begin(); if (row[0]) { - return atoul(row[0]); + return Strings::ToUnsignedInt(row[0]); } return 0; @@ -2523,7 +2527,7 @@ uint32 SharedDatabase::GetItemsCount() auto& row = results.begin(); if (row[0]) { - return atoul(row[0]); + return Strings::ToUnsignedInt(row[0]); } return 0; diff --git a/common/strings.cpp b/common/strings.cpp index 2b31a3881..5a37b7659 100644 --- a/common/strings.cpp +++ b/common/strings.cpp @@ -191,24 +191,23 @@ std::string Strings::Escape(const std::string &s) bool Strings::IsNumber(const std::string &s) { - try { - auto r = stoi(s); - return true; - } - catch (std::exception &) { - return false; + for (char const &c: s) { + if (c == s[0] && s[0] == '-') { + continue; + } + if (std::isdigit(c) == 0) { + return false; + } } + + return true; } bool Strings::IsFloat(const std::string &s) { - try { - auto r = stof(s); - return true; - } - catch (std::exception &) { - return false; - } + char* ptr; + strtof(s.c_str(), &ptr); + return (*ptr) == '\0'; } std::string Strings::Join(const std::vector &ar, const std::string &delim) @@ -225,6 +224,20 @@ std::string Strings::Join(const std::vector &ar, const std::string return ret; } +std::string Strings::Join(const std::vector &ar, const std::string &delim) +{ + std::string ret; + for (size_t i = 0; i < ar.size(); ++i) { + if (i != 0) { + ret += delim; + } + + ret += std::to_string(ar[i]); + } + + return ret; +} + void Strings::FindReplace(std::string &string_subject, const std::string &search_string, const std::string &replace_string) { @@ -714,7 +727,7 @@ uint32 Strings::TimeToSeconds(std::string time_string) time_unit.end() ); - auto unit = std::stoul(time_unit); + auto unit = Strings::ToUnsignedInt(time_unit); uint32 duration = 0; if (Strings::Contains(time_string, "s")) { @@ -741,7 +754,7 @@ bool Strings::ToBool(std::string bool_string) Strings::Contains(bool_string, "on") || Strings::Contains(bool_string, "enable") || Strings::Contains(bool_string, "enabled") || - (Strings::IsNumber(bool_string) && std::stoi(bool_string)) + (Strings::IsNumber(bool_string) && Strings::ToInt(bool_string)) ) { return true; } @@ -763,3 +776,88 @@ std::string Strings::Random(size_t length) std::generate_n(str.begin(), length, randchar); return str; } + +// a wrapper for stoi which will return a fallback if the string +// fails to cast to a number +int Strings::ToInt(const std::string &s, int fallback) +{ + if (!Strings::IsNumber(s)) { + return fallback; + } + + try { + return std::stoi(s); + } + catch (std::exception &) { + return fallback; + } +} + +int64 Strings::ToBigInt(const std::string &s, int64 fallback) +{ + if (!Strings::IsNumber(s)) { + return fallback; + } + + try { + return std::stoll(s); + } + catch (std::exception &) { + return fallback; + } +} + +uint32 Strings::ToUnsignedInt(const std::string &s, uint32 fallback) +{ + if (!Strings::IsNumber(s)) { + return fallback; + } + + try { + return std::stoul(s); + } + catch (std::exception &) { + return fallback; + } +} + +uint64 Strings::ToUnsignedBigInt(const std::string &s, uint64 fallback) +{ + if (!Strings::IsNumber(s)) { + return fallback; + } + + try { + return std::stoull(s); + } + catch (std::exception &) { + return fallback; + } +} + +float Strings::ToFloat(const std::string &s, float fallback) +{ + if (!Strings::IsFloat(s)) { + return fallback; + } + + try { + return std::stof(s); + } + catch (std::exception &) { + return fallback; + } +} + +std::string Strings::RemoveNumbers(std::string s) +{ + int current = 0; + for (int i = 0; i < s.length(); i++) { + if (!isdigit(s[i])) { + s[current] = s[i]; + current++; + } + } + + return s.substr(0, current); +} diff --git a/common/strings.h b/common/strings.h index a70a7432f..d454b90b9 100644 --- a/common/strings.h +++ b/common/strings.h @@ -86,7 +86,13 @@ class Strings { public: static bool Contains(std::vector container, std::string element); static bool Contains(const std::string& subject, const std::string& search); + static int ToInt(const std::string &s, int fallback = 0); + static int64 ToBigInt(const std::string &s, int64 fallback = 0); + static uint32 ToUnsignedInt(const std::string &s, uint32 fallback = 0); + static uint64 ToUnsignedBigInt(const std::string &s, uint64 fallback = 0); + static float ToFloat(const std::string &s, float fallback = 0.0f); static bool IsNumber(const std::string &s); + static std::string RemoveNumbers(std::string s); static bool IsFloat(const std::string &s); static const std::string ToLower(std::string s); static const std::string ToUpper(std::string s); @@ -106,6 +112,7 @@ public: static std::string GetBetween(const std::string &s, std::string start_delim, std::string stop_delim); static std::string Implode(std::string glue, std::vector src); static std::string Join(const std::vector &ar, const std::string &delim); + static std::string Join(const std::vector &ar, const std::string &delim); static std::string MillisecondsToTime(int duration); static std::string Money(uint32 platinum, uint32 gold = 0, uint32 silver = 0, uint32 copper = 0); static std::string NumberToWords(unsigned long long int n); diff --git a/common/strings_legacy.cpp b/common/strings_legacy.cpp index 480a4ebe5..e1d324d45 100644 --- a/common/strings_legacy.cpp +++ b/common/strings_legacy.cpp @@ -192,7 +192,7 @@ bool atobool(const char *iBool) if (!strcasecmp(iBool, "n")) { return false; } - if (atoi(iBool)) { + if (Strings::ToInt(iBool)) { return true; } return false; diff --git a/common/termcolor/rang.hpp b/common/termcolor/rang.hpp index 68f830b6f..090c46d80 100644 --- a/common/termcolor/rang.hpp +++ b/common/termcolor/rang.hpp @@ -42,6 +42,8 @@ #include #include +inline bool g_is_forced_tty = std::getenv("IS_TTY"); + namespace rang { /* For better compability with most of terminals do not use any style settings @@ -220,6 +222,10 @@ inline bool isMsysPty(int fd) noexcept inline bool isTerminal(const std::streambuf *osbuf) noexcept { + if (g_is_forced_tty) { + return g_is_forced_tty; + } + using std::cerr; using std::clog; using std::cout; diff --git a/common/timer.cpp b/common/timer.cpp index f4d931764..280b82518 100644 --- a/common/timer.cpp +++ b/common/timer.cpp @@ -16,7 +16,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - // Disgrace: for windows compile #ifndef WIN32 #include diff --git a/common/version.h b/common/version.h index b667db189..3941cce9d 100644 --- a/common/version.h +++ b/common/version.h @@ -18,14 +18,22 @@ * */ -#ifndef _EQEMU_VERSION_H -#define _EQEMU_VERSION_H +#ifndef EQEMU_VERSION_H +#define EQEMU_VERSION_H -#define LOGIN_VERSION "0.8.0" #define EQEMU_PROTOCOL_VERSION "0.3.10" -#define CURRENT_VERSION "2.0" - +// Build variables +// these get injected during the build pipeline +#define CURRENT_VERSION "22.4.5-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__ +#ifndef WIN32 +#define LAST_MODIFIED __TIME__ +#else +#define LAST_MODIFIED __TIMESTAMP__ +#endif /** * Every time a Database SQL is added to Github increment CURRENT_BINARY_DATABASE_VERSION @@ -34,16 +42,9 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9217 -#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9036 +#define CURRENT_BINARY_DATABASE_VERSION 9225 -#define COMPILE_DATE __DATE__ -#define COMPILE_TIME __TIME__ -#ifndef WIN32 - #define LAST_MODIFIED __TIME__ -#else - #define LAST_MODIFIED __TIMESTAMP__ -#endif +#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9038 #endif diff --git a/eqlaunch/zone_launch.cpp b/eqlaunch/zone_launch.cpp index 4e0a9a8ff..15943f315 100644 --- a/eqlaunch/zone_launch.cpp +++ b/eqlaunch/zone_launch.cpp @@ -28,11 +28,6 @@ int ZoneLaunch::s_running = 0; //the number of zones running under this launcher Timer ZoneLaunch::s_startTimer(1); //I do not trust this things state after static initialization -void ZoneLaunch::InitStartTimer() { - s_startTimer.Start(1); - s_startTimer.Trigger(); -} - ZoneLaunch::ZoneLaunch(WorldServer *world, const char *launcher_name, const char *zone_name, uint16 port, const EQEmuConfig *config) : m_state(StateStartPending), diff --git a/eqlaunch/zone_launch.h b/eqlaunch/zone_launch.h index ac48be92c..d52a93bb2 100644 --- a/eqlaunch/zone_launch.h +++ b/eqlaunch/zone_launch.h @@ -39,10 +39,6 @@ public: void SendStatus() const; const char *GetZone() const { return(m_zone.c_str()); } - uint32 GetStartCount() const { return(m_startCount); } - - //should only be called during process init to setup the start timer. - static void InitStartTimer(); protected: bool IsRunning() const { return(m_state == StateStarted || m_state == StateStopPending || m_state == StateRestartPending); } diff --git a/loginserver/account_management.cpp b/loginserver/account_management.cpp index 6be011951..b95000ed1 100644 --- a/loginserver/account_management.cpp +++ b/loginserver/account_management.cpp @@ -260,27 +260,6 @@ bool AccountManagement::UpdateLoginserverWorldAdminAccountPasswordByName( return updated_account; } -/** - * @param in_account_id - * @param in_account_password_hash - */ -bool AccountManagement::UpdateLoginserverWorldAdminAccountPasswordById( - uint32 in_account_id, - const std::string &in_account_password_hash -) -{ - bool updated_account = server.db->UpdateLoginWorldAdminAccountPassword(in_account_id, in_account_password_hash); - - LogInfo( - "[{}] account_name [{}] status [{}]", - __func__, - in_account_id, - (updated_account ? "success" : "failed") - ); - - return updated_account; -} - constexpr int REQUEST_TIMEOUT_MS = 1500; /** @@ -381,7 +360,7 @@ uint32 AccountManagement::CheckExternalLoginserverUserCredentials( auto s = Strings::Split(server.options.GetEQEmuLoginServerAddress(), ':'); if (s.size() == 2) { auto address = s[0]; - auto port = std::stoi(s[1]); + auto port = Strings::ToInt(s[1]); EQ::Net::DNSLookup( address, port, false, [&](const std::string &addr) { diff --git a/loginserver/account_management.h b/loginserver/account_management.h index 2c92af69d..190c26437 100644 --- a/loginserver/account_management.h +++ b/loginserver/account_management.h @@ -80,16 +80,6 @@ public: const std::string &in_account_password ); - /** - * @param in_account_id - * @param in_account_password_hash - * @return - */ - static bool UpdateLoginserverWorldAdminAccountPasswordById( - uint32 in_account_id, - const std::string &in_account_password_hash - ); - static uint32 HealthCheckUserLogin(); }; diff --git a/loginserver/client.cpp b/loginserver/client.cpp index c862538cb..06b1b6e3d 100644 --- a/loginserver/client.cpp +++ b/loginserver/client.cpp @@ -26,10 +26,11 @@ bool Client::Process() { EQApplicationPacket *app = m_connection->PopPacket(); while (app) { + auto o = m_connection->GetOpcodeManager(); LogPacketClientServer( "[{}] [{:#06x}] Size [{}] {}", OpcodeManager::EmuToName(app->GetOpcode()), - m_connection->GetOpcodeManager()->EmuToEQ(app->GetOpcode()), + o->EmuToEQ(app->GetOpcode()) == 0 ? app->GetProtocolOpcode() : o->EmuToEQ(app->GetOpcode()), app->Size(), (LogSys.IsLogEnabled(Logs::Detail, Logs::PacketClientServer) ? DumpPacketToString(app) : "") ); @@ -657,146 +658,6 @@ void Client::CreateEQEmuAccount( } } -/** - * @param connection - */ -void Client::LoginOnNewConnection(std::shared_ptr connection) -{ - m_login_connection = connection; -} - -/** - * @param conn - * @param from - * @param to - */ -void Client::LoginOnStatusChange( - std::shared_ptr conn, - EQ::Net::DbProtocolStatus from, - EQ::Net::DbProtocolStatus to -) -{ - if (to == EQ::Net::StatusConnected) { - LogDebug("EQ::Net::StatusConnected"); - LoginSendSessionReady(); - } - - if (to == EQ::Net::StatusDisconnecting || to == EQ::Net::StatusDisconnected) { - LogDebug("EQ::Net::StatusDisconnecting || EQ::Net::StatusDisconnected"); - - DoFailedLogin(); - } -} - -/** - * @param conn - * @param from - * @param to - */ -void Client::LoginOnStatusChangeIgnored( - std::shared_ptr conn, - EQ::Net::DbProtocolStatus from, - EQ::Net::DbProtocolStatus to -) -{ -} - -/** - * @param conn - * @param p - */ -void Client::LoginOnPacketRecv(std::shared_ptr conn, const EQ::Net::Packet &p) -{ - auto opcode = p.GetUInt16(0); - switch (opcode) { - case 0x0017: //OP_ChatMessage - LoginSendLogin(); - break; - case 0x0018: - LoginProcessLoginResponse(p); - break; - } -} - -void Client::LoginSendSessionReady() -{ - EQ::Net::DynamicPacket p; - p.PutUInt16(0, 1); //OP_SessionReady - p.PutUInt32(2, 2); - - m_login_connection->QueuePacket(p); -} - -void Client::LoginSendLogin() -{ - size_t buffer_len = m_stored_user.length() + m_stored_pass.length() + 2; - std::unique_ptr buffer(new char[buffer_len]); - - strcpy(&buffer[0], m_stored_user.c_str()); - strcpy(&buffer[m_stored_user.length() + 1], m_stored_pass.c_str()); - - size_t encrypted_len = buffer_len; - - if (encrypted_len % 8 > 0) { - encrypted_len = ((encrypted_len / 8) + 1) * 8; - } - - EQ::Net::DynamicPacket p; - p.Resize(12 + encrypted_len); - p.PutUInt16(0, 2); //OP_Login - p.PutUInt32(2, 3); - - eqcrypt_block(&buffer[0], buffer_len, (char *) p.Data() + 12, true); - - m_login_connection->QueuePacket(p); -} - -/** - * @param p - */ -void Client::LoginProcessLoginResponse(const EQ::Net::Packet &p) -{ - auto encrypt_size = p.Length() - 12; - - if (encrypt_size % 8 > 0) { - encrypt_size = (encrypt_size / 8) * 8; - } - - std::unique_ptr decrypted(new char[encrypt_size]); - - eqcrypt_block((char *) p.Data() + 12, encrypt_size, &decrypted[0], false); - - EQ::Net::StaticPacket sp(&decrypted[0], encrypt_size); - auto response_error = sp.GetUInt16(1); - - m_login_connection_manager->OnConnectionStateChange( - std::bind( - &Client::LoginOnStatusChangeIgnored, - this, - std::placeholders::_1, - std::placeholders::_2, - std::placeholders::_3 - ) - ); - - if (response_error > 101) { - LogDebug("response [{0}] failed login", response_error); - DoFailedLogin(); - m_login_connection->Close(); - } - else { - LogDebug( - "response [{0}] login succeeded user [{1}]", - response_error, - m_stored_user - ); - - auto m_dbid = sp.GetUInt32(8); - - CreateEQEmuAccount(m_stored_user, m_stored_pass, m_dbid); - m_login_connection->Close(); - } -} bool Client::ProcessHealthCheck(std::string username) { if (username == "healthcheckuser") { diff --git a/loginserver/client.h b/loginserver/client.h index d96bc5302..708e1582d 100644 --- a/loginserver/client.h +++ b/loginserver/client.h @@ -198,21 +198,6 @@ private: std::string m_stored_user; std::string m_stored_pass; - void LoginOnNewConnection(std::shared_ptr connection); - void LoginOnStatusChange( - std::shared_ptr conn, - EQ::Net::DbProtocolStatus from, - EQ::Net::DbProtocolStatus to - ); - void LoginOnStatusChangeIgnored( - std::shared_ptr conn, - EQ::Net::DbProtocolStatus from, - EQ::Net::DbProtocolStatus to - ); - void LoginOnPacketRecv(std::shared_ptr conn, const EQ::Net::Packet &p); - void LoginSendSessionReady(); - void LoginSendLogin(); - void LoginProcessLoginResponse(const EQ::Net::Packet &p); static bool ProcessHealthCheck(std::string username); }; diff --git a/loginserver/database.cpp b/loginserver/database.cpp index b07b0a1c2..25ea28aa6 100644 --- a/loginserver/database.cpp +++ b/loginserver/database.cpp @@ -32,7 +32,7 @@ Database::Database( user.c_str(), pass.c_str(), name.c_str(), - std::stoi(port), + Strings::ToInt(port), &errnum, errbuf ) @@ -93,7 +93,7 @@ bool Database::GetLoginDataFromAccountInfo( auto row = results.begin(); - id = atoi(row[0]); + id = Strings::ToInt(row[0]); password = row[1]; LogDebug( @@ -145,7 +145,7 @@ bool Database::GetLoginTokenDataFromToken( } if (strcmp(row[2], "login_server_id") == 0) { - db_account_id = atoi(row[3]); + db_account_id = Strings::ToInt(row[3]); found_login_id = true; continue; } @@ -178,7 +178,7 @@ unsigned int Database::GetFreeID(const std::string &loginserver) auto row = results.begin(); - return std::stoi(row[0]); + return Strings::ToInt(row[0]); } /** @@ -368,12 +368,12 @@ Database::DbWorldRegistration Database::GetWorldRegistration( auto row = results.begin(); r.loaded = true; - r.server_id = std::stoi(row[0]); + r.server_id = Strings::ToInt(row[0]); r.server_description = row[1]; - r.server_list_type = std::stoi(row[3]); - r.is_server_trusted = std::stoi(row[2]) > 0; + r.server_list_type = Strings::ToInt(row[3]); + r.is_server_trusted = Strings::ToInt(row[2]) > 0; r.server_list_description = row[4]; - r.server_admin_id = std::stoi(row[5]); + r.server_admin_id = Strings::ToInt(row[5]); if (r.server_admin_id <= 0) { return r; @@ -513,7 +513,7 @@ bool Database::CreateWorldRegistration( auto row = results.begin(); - id = std::stoi(row[0]); + id = Strings::ToInt(row[0]); auto insert_query = fmt::format( "INSERT INTO login_world_servers SET id = {0}, long_name = '{1}', short_name = '{2}', last_ip_address = '{3}', \n" "login_server_list_type_id = 3, login_server_admin_id = {4}, is_server_trusted = 0, tag_description = ''", @@ -647,7 +647,7 @@ Database::DbLoginServerAdmin Database::GetLoginServerAdmin(const std::string &ac if (results.RowCount() == 1) { auto row = results.begin(); r.loaded = true; - r.id = std::stoi(row[0]); + r.id = Strings::ToInt(row[0]); r.account_name = row[1]; r.account_password = row[2]; r.first_name = row[3]; @@ -683,7 +683,7 @@ Database::DbLoginServerAccount Database::GetLoginServerAccountByAccountName( if (results.RowCount() == 1) { auto row = results.begin(); r.loaded = true; - r.id = std::stoi(row[0]); + r.id = Strings::ToInt(row[0]); r.account_name = row[1]; r.account_password = row[2]; r.account_email = row[3]; diff --git a/loginserver/database.h b/loginserver/database.h index b53af1de9..f194934a9 100644 --- a/loginserver/database.h +++ b/loginserver/database.h @@ -29,7 +29,6 @@ public: * Destructor, frees our database if needed. */ ~Database(); - bool IsConnected() { return (m_database != nullptr); } /** * Retrieves the login data (password hash and account id) from the account name provided needed for client login procedure. diff --git a/loginserver/login_types.h b/loginserver/login_types.h index 25e64307e..3f4f20d59 100644 --- a/loginserver/login_types.h +++ b/loginserver/login_types.h @@ -23,13 +23,6 @@ struct LoginHandShakeReply_Struct { char unknown[1]; // variable length string }; -// for reference, login buffer is variable (minimum size 8 due to encryption) -struct PlayerLogin_Struct { - LoginBaseMessage_Struct base_header; - char username[1]; - char password[1]; -}; - // variable length, can use directly if not serializing strings struct PlayerLoginReply_Struct { // base header excluded to make struct data easier to encrypt diff --git a/loginserver/loginserver_webserver.cpp b/loginserver/loginserver_webserver.cpp index eb0acb551..e7f3f5a3b 100644 --- a/loginserver/loginserver_webserver.cpp +++ b/loginserver/loginserver_webserver.cpp @@ -480,8 +480,8 @@ namespace LoginserverWebserver { for (auto row = results.begin(); row != results.end(); ++row) { LoginserverWebserver::TokenManager::token_data token_data; token_data.token = row[0]; - token_data.can_write = std::stoi(row[1]) > 0; - token_data.can_read = std::stoi(row[2]) > 0; + token_data.can_write = Strings::ToInt(row[1]) > 0; + token_data.can_read = Strings::ToInt(row[2]) > 0; LogDebug( "Inserting api token to internal list [{0}] write {1} read {2}", diff --git a/loginserver/main.cpp b/loginserver/main.cpp index 43daa4551..af02b878b 100644 --- a/loginserver/main.cpp +++ b/loginserver/main.cpp @@ -288,9 +288,16 @@ int main(int argc, char **argv) LogInfo("[Config] [Security] IsPasswordLoginAllowed [{0}]", server.options.IsPasswordLoginAllowed()); LogInfo("[Config] [Security] IsUpdatingInsecurePasswords [{0}]", server.options.IsUpdatingInsecurePasswords()); + Timer keepalive(INTERSERVER_TIMER); // does auto-reconnect + auto loop_fn = [&](EQ::Timer* t) { Timer::SetCurrentTime(); + if (keepalive.Check()) { + keepalive.Start(); + server.db->ping(); + } + if (!run_server) { EQ::EventLoop::Get().Shutdown(); return; diff --git a/loginserver/server_manager.cpp b/loginserver/server_manager.cpp index 77b70fd8a..4dfe66c4a 100644 --- a/loginserver/server_manager.cpp +++ b/loginserver/server_manager.cpp @@ -73,25 +73,6 @@ ServerManager::ServerManager() ServerManager::~ServerManager() = default; -/** - * @param ip_address - * @param port - * @return - */ -WorldServer *ServerManager::GetServerByAddress(const std::string &ip_address, int port) -{ - auto iter = m_world_servers.begin(); - while (iter != m_world_servers.end()) { - if ((*iter)->GetConnection()->Handle()->RemoteIP() == ip_address && - (*iter)->GetConnection()->Handle()->RemotePort()) { - return (*iter).get(); - } - ++iter; - } - - return nullptr; -} - /** * @param client * @param sequence diff --git a/loginserver/server_manager.h b/loginserver/server_manager.h index ac652a2b5..24711c6ac 100644 --- a/loginserver/server_manager.h +++ b/loginserver/server_manager.h @@ -72,17 +72,6 @@ public: const std::list> &getWorldServers() const; private: - - /** - * Retrieves a server(if exists) by ip address - * Useful utility for the reconnect process - * - * @param ip_address - * @param port - * @return - */ - WorldServer *GetServerByAddress(const std::string &ip_address, int port); - std::unique_ptr m_server_connection; std::list> m_world_servers; diff --git a/loginserver/world_server.h b/loginserver/world_server.h index c4ea5f87d..57f9ac150 100644 --- a/loginserver/world_server.h +++ b/loginserver/world_server.h @@ -31,7 +31,6 @@ public: * Accesses connection, it is intentional that this is not const (trust me). */ std::shared_ptr GetConnection() { return m_connection; } - void SetConnection(std::shared_ptr c) { m_connection = c; } /** * @return diff --git a/package.json b/package.json new file mode 100644 index 000000000..8617ab870 --- /dev/null +++ b/package.json @@ -0,0 +1,8 @@ +{ + "name": "eqemu-server", + "version": "22.4.5", + "repository": { + "type": "git", + "url": "https://github.com/EQEmu/Server.git" + } +} diff --git a/queryserv/database.cpp b/queryserv/database.cpp index 5b655a21e..7a442ae4c 100644 --- a/queryserv/database.cpp +++ b/queryserv/database.cpp @@ -50,7 +50,6 @@ #include "../common/strings.h" #include "../common/servertalk.h" - void QSDatabase::AddSpeech( const char *from, const char *to, @@ -125,7 +124,7 @@ void QSDatabase::LogPlayerDropItem(QSPlayerDropItem_Struct *QS) } } -void QSDatabase::LogPlayerTrade(QSPlayerLogTrade_Struct *QS, uint32 detailCount) +void QSDatabase::LogPlayerTrade(PlayerLogTrade_Struct *QS, uint32 detailCount) { std::string query = StringFormat( @@ -134,10 +133,10 @@ void QSDatabase::LogPlayerTrade(QSPlayerLogTrade_Struct *QS, uint32 detailCount) "`char1_sp` = '%i', `char1_cp` = '%i', `char1_items` = '%i', " "`char2_id` = '%i', `char2_pp` = '%i', `char2_gp` = '%i', " "`char2_sp` = '%i', `char2_cp` = '%i', `char2_items` = '%i'", - QS->char1_id, QS->char1_money.platinum, QS->char1_money.gold, - QS->char1_money.silver, QS->char1_money.copper, QS->char1_count, - QS->char2_id, QS->char2_money.platinum, QS->char2_money.gold, - QS->char2_money.silver, QS->char2_money.copper, QS->char2_count + QS->character_1_id, QS->character_1_money.platinum, QS->character_1_money.gold, + QS->character_1_money.silver, QS->character_1_money.copper, QS->character_1_item_count, + QS->character_2_id, QS->character_2_money.platinum, QS->character_2_money.gold, + QS->character_2_money.silver, QS->character_2_money.copper, QS->character_2_item_count ); auto results = QueryDatabase(query); if (!results.Success()) { @@ -157,10 +156,10 @@ void QSDatabase::LogPlayerTrade(QSPlayerLogTrade_Struct *QS, uint32 detailCount) "`from_id` = '%i', `from_slot` = '%i', `to_id` = '%i', `to_slot` = '%i', " "`item_id` = '%i', `charges` = '%i', `aug_1` = '%i', `aug_2` = '%i', " "`aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'", - lastIndex, QS->items[i].from_id, QS->items[i].from_slot, - QS->items[i].to_id, QS->items[i].to_slot, QS->items[i].item_id, - QS->items[i].charges, QS->items[i].aug_1, QS->items[i].aug_2, - QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5 + lastIndex, QS->item_entries[i].from_character_id, QS->item_entries[i].from_slot, + QS->item_entries[i].to_character_id, QS->item_entries[i].to_slot, QS->item_entries[i].item_id, + QS->item_entries[i].charges, QS->item_entries[i].aug_1, QS->item_entries[i].aug_2, + QS->item_entries[i].aug_3, QS->item_entries[i].aug_4, QS->item_entries[i].aug_5 ); results = QueryDatabase(query); if (!results.Success()) { diff --git a/queryserv/database.h b/queryserv/database.h index 0741f9aa0..5072f5b55 100644 --- a/queryserv/database.h +++ b/queryserv/database.h @@ -33,13 +33,11 @@ #include #include -//atoi is not uint32 or uint32 safe!!!! -#define atoul(str) strtoul(str, nullptr, 10) class QSDatabase : public Database { public: void AddSpeech(const char* from, const char* to, const char* message, uint16 minstatus, uint32 guilddbid, uint8 type); - void LogPlayerTrade(QSPlayerLogTrade_Struct* QS, uint32 DetailCount); + void LogPlayerTrade(PlayerLogTrade_Struct* QS, uint32 DetailCount); void LogPlayerDropItem(QSPlayerDropItem_Struct* QS); void LogPlayerHandin(QSPlayerLogHandin_Struct* QS, uint32 DetailCount); void LogPlayerNPCKill(QSPlayerLogNPCKill_Struct* QS, uint32 Members); @@ -47,12 +45,6 @@ public: void LogPlayerMove(QSPlayerLogMove_Struct* QS, uint32 Items); void LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint32 Items); void GeneralQueryReceive(ServerPacket *pack); - -protected: - void HandleMysqlError(uint32 errnum); -private: - void DBInitVars(); - }; #endif diff --git a/queryserv/lfguild.cpp b/queryserv/lfguild.cpp index d97cc3855..e1ec30257 100644 --- a/queryserv/lfguild.cpp +++ b/queryserv/lfguild.cpp @@ -44,15 +44,15 @@ bool LFGuildManager::LoadDatabase() } for (auto row = results.begin(); row != results.end(); ++row) { - uint32 type = atoul(row[0]); + uint32 type = Strings::ToUnsignedInt(row[0]); if(type == 0) { - PlayerLookingForGuild p(row[1], row[2], atoul(row[3]), atoul(row[5]), atoul(row[6]), atoul(row[7]), atoul(row[8])); + PlayerLookingForGuild p(row[1], row[2], Strings::ToUnsignedInt(row[3]), Strings::ToUnsignedInt(row[5]), Strings::ToUnsignedInt(row[6]), Strings::ToUnsignedInt(row[7]), Strings::ToUnsignedInt(row[8])); Players.push_back(p); continue; } - GuildLookingForPlayers g(row[1], row[2], atoul(row[3]), atoul(row[4]), atoul(row[5]), atoul(row[6]), atoul(row[7]), atoul(row[8])); + GuildLookingForPlayers g(row[1], row[2], Strings::ToUnsignedInt(row[3]), Strings::ToUnsignedInt(row[4]), Strings::ToUnsignedInt(row[5]), Strings::ToUnsignedInt(row[6]), Strings::ToUnsignedInt(row[7]), Strings::ToUnsignedInt(row[8])); Guilds.push_back(g); } diff --git a/queryserv/queryserv.cpp b/queryserv/queryserv.cpp index aabfb5f1d..a504b8e77 100644 --- a/queryserv/queryserv.cpp +++ b/queryserv/queryserv.cpp @@ -33,6 +33,7 @@ #include "worldserver.h" #include "../common/path_manager.h" #include "../common/zone_store.h" +#include "../common/events/player_event_logs.h" #include #include #include @@ -47,6 +48,7 @@ WorldServer *worldserver = 0; EQEmuLogSys LogSys; PathManager path; ZoneStore zone_store; +PlayerEventLogs player_event_logs; void CatchSignal(int sig_num) { @@ -106,6 +108,9 @@ int main() /* Load Looking For Guild Manager */ lfguildmanager.LoadDatabase(); + Timer player_event_process_timer(1000); + player_event_logs.SetDatabase(&database)->Init(); + auto loop_fn = [&](EQ::Timer* t) { Timer::SetCurrentTime(); @@ -117,6 +122,10 @@ int main() if (LFGuildExpireTimer.Check()) { lfguildmanager.ExpireEntries(); } + + if (player_event_process_timer.Check()) { + player_event_logs.Process(); + } }; EQ::Timer process_timer(loop_fn); diff --git a/queryserv/worldserver.cpp b/queryserv/worldserver.cpp index 70dc91577..f46baf983 100644 --- a/queryserv/worldserver.cpp +++ b/queryserv/worldserver.cpp @@ -29,6 +29,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "lfguild.h" #include "queryservconfig.h" #include "worldserver.h" +#include "../common/events/player_events.h" +#include "../common/events/player_event_logs.h" #include #include #include @@ -89,6 +91,17 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) case 0: { break; } + case ServerOP_PlayerEvent: { + auto n = PlayerEvent::PlayerEventContainer{}; + auto s = (ServerSendPlayerEvent_Struct *) p.Data(); + EQ::Util::MemoryStreamReader ss(s->cereal_data, s->cereal_size); + cereal::BinaryInputArchive archive(ss); + archive(n); + + player_event_logs.AddToQueue(n.player_event_log); + + break; + } case ServerOP_KeepAlive: { break; } @@ -100,7 +113,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) break; } case ServerOP_QSPlayerLogTrades: { - QSPlayerLogTrade_Struct *QS = (QSPlayerLogTrade_Struct *) p.Data(); + PlayerLogTrade_Struct *QS = (PlayerLogTrade_Struct *) p.Data(); database.LogPlayerTrade(QS, QS->_detail_count); break; } diff --git a/shared_memory/main.cpp b/shared_memory/main.cpp index 98a9c46b4..b5473d43f 100644 --- a/shared_memory/main.cpp +++ b/shared_memory/main.cpp @@ -124,7 +124,7 @@ int main(int argc, char **argv) return 1; } } else { - content_db.SetMysql(database.getMySQL()); + content_db.SetMySQL(database); } LogSys.SetDatabase(&database) diff --git a/tests/main.cpp b/tests/main.cpp index 2f32c2840..50ddf890b 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -46,8 +46,7 @@ int main() auto ConfigLoadResult = EQEmuConfig::LoadConfig(); Config = EQEmuConfig::get(); try { - std::ofstream outfile("test_output.txt"); - std::unique_ptr output(new Test::TextOutput(Test::TextOutput::Verbose, outfile)); + std::unique_ptr output(new Test::TextOutput(Test::TextOutput::Verbose)); Test::Suite tests; tests.add(new MemoryMappedFileTest()); tests.add(new IPCMutexTest()); @@ -60,7 +59,9 @@ int main() tests.add(new SkillsUtilsTest()); tests.add(new TaskStateTest()); tests.run(*output, true); - } catch (...) { + } + catch (std::exception &ex) { + LogError("Test Failure [{}]", ex.what()); return -1; } return 0; diff --git a/tests/string_util_test.h b/tests/string_util_test.h index 5d8a3a956..3a8b59c35 100644 --- a/tests/string_util_test.h +++ b/tests/string_util_test.h @@ -31,6 +31,8 @@ public: TEST_ADD(StringUtilTest::SearchDeliminatedStringTest); TEST_ADD(StringUtilTest::SplitStringTest); TEST_ADD(StringUtilTest::FromCharsTest); + TEST_ADD(StringUtilTest::TestIsFloat); + TEST_ADD(StringUtilTest::TestIsNumber); } ~StringUtilTest() { @@ -116,6 +118,26 @@ public: TEST_ASSERT(float_value == 3.14f); } + + void TestIsFloat() { + TEST_ASSERT_EQUALS(Strings::IsFloat("0.23424523"), true); + TEST_ASSERT_EQUALS(Strings::IsFloat("12312312313.23424523"), true); + TEST_ASSERT_EQUALS(Strings::IsFloat("12312312313"), true); + TEST_ASSERT_EQUALS(Strings::IsFloat(".234234"), true); + TEST_ASSERT_EQUALS(Strings::IsFloat(".234234f"), false); + TEST_ASSERT_EQUALS(Strings::IsFloat("Johnson"), false); + } + + void TestIsNumber() { + TEST_ASSERT_EQUALS(Strings::IsNumber("0.23424523"), false); + TEST_ASSERT_EQUALS(Strings::IsNumber("12312312313.23424523"), false); + TEST_ASSERT_EQUALS(Strings::IsNumber("12312312313"), true); + TEST_ASSERT_EQUALS(Strings::IsNumber("12312312313f"), false); // character at end + TEST_ASSERT_EQUALS(Strings::IsNumber("18446744073709551616"), true); // 64 + TEST_ASSERT_EQUALS(Strings::IsNumber("-18"), true); + TEST_ASSERT_EQUALS(Strings::IsNumber("-f18"), false); + TEST_ASSERT_EQUALS(Strings::IsNumber("-18446744073709551616"), true); // 64 + } }; #endif diff --git a/ucs/chatchannel.cpp b/ucs/chatchannel.cpp index 20e0e0603..4da5aebc8 100644 --- a/ucs/chatchannel.cpp +++ b/ucs/chatchannel.cpp @@ -48,10 +48,10 @@ ChatChannel::ChatChannel(std::string inName, std::string inOwner, std::string in m_moderated = false; LogDebug( - "New ChatChannel created: Name: [{}], Owner: [{}], Password: [{}], MinStatus: [{}]", - m_name.c_str(), - m_owner.c_str(), - m_password.c_str(), + "New ChatChannel created: Name: [{}] Owner: [{}] Password: [{}] MinStatus: [{}]", + m_name, + m_owner, + m_password, m_minimum_status ); @@ -78,7 +78,7 @@ ChatChannel *ChatChannelList::CreateChannel( { uint8 max_perm_player_channels = RuleI(Chat, MaxPermanentPlayerChannels); - if (!database.CheckChannelNameFilter(name)) { + if (!RuleB(Chat, ChannelsIgnoreNameFilter) && !database.CheckChannelNameFilter(name)) { if (!(owner == SYSTEM_OWNER)) { return nullptr; } @@ -657,7 +657,7 @@ ChatChannel *ChatChannelList::RemoveClientFromChannel(const std::string& in_chan std::string channel_name = in_channel_name; if (in_channel_name.length() > 0 && isdigit(channel_name[0])) { - channel_name = c->ChannelSlotName(atoi(in_channel_name.c_str())); + channel_name = c->ChannelSlotName(Strings::ToInt(in_channel_name.c_str())); } auto *required_channel = FindChannel(channel_name); @@ -667,7 +667,7 @@ ChatChannel *ChatChannelList::RemoveClientFromChannel(const std::string& in_chan } LogDebug("Client [{}] removed from channel [{}]. Channel is owned by {}. Command directed: {}", c->GetName(), channel_name, required_channel->GetOwnerName(), command_directed); - if (c->GetName() == required_channel->GetOwnerName() && command_directed) { // Check if the client that is leaving is the the channel owner + if (c->GetName() == required_channel->GetOwnerName() && command_directed) { // Check if the client that is leaving is the channel owner LogDebug("Owner left the channel [{}], removing channel from database...", channel_name); database.DeleteChatChannel(channel_name); // Remove the channel from the database. LogDebug("Flagging [{}] channel as temporary...", channel_name); diff --git a/ucs/clientlist.cpp b/ucs/clientlist.cpp index dd4220bd7..cb5736725 100644 --- a/ucs/clientlist.cpp +++ b/ucs/clientlist.cpp @@ -379,14 +379,14 @@ static void ProcessSetMessageStatus(std::string SetMessageCommand) { if (NumEnd == std::string::npos) { - MessageNumber = atoi(SetMessageCommand.substr(NumStart).c_str()); + MessageNumber = Strings::ToInt(SetMessageCommand.substr(NumStart).c_str()); database.SetMessageStatus(MessageNumber, Status); break; } - MessageNumber = atoi(SetMessageCommand.substr(NumStart, NumEnd - NumStart).c_str()); + MessageNumber = Strings::ToInt(SetMessageCommand.substr(NumStart, NumEnd - NumStart).c_str()); database.SetMessageStatus(MessageNumber, Status); @@ -643,10 +643,11 @@ void Clientlist::Process() while (KeyValid && !(*it)->GetForceDisconnect() && (app = (*it)->ClientStream->PopPacket())) { EmuOpcode opcode = app->GetOpcode(); + auto o = (*it)->ClientStream->GetOpcodeManager(); LogPacketClientServer( "[{}] [{:#06x}] Size [{}] {}", OpcodeManager::EmuToName(app->GetOpcode()), - (*it)->ClientStream->GetOpcodeManager()->EmuToEQ(app->GetOpcode()), + o->EmuToEQ(app->GetOpcode()) == 0 ? app->GetProtocolOpcode() : o->EmuToEQ(app->GetOpcode()), app->Size(), (LogSys.IsLogEnabled(Logs::Detail, Logs::PacketClientServer) ? DumpPacketToString(app) : "") ); @@ -792,7 +793,10 @@ void Clientlist::ProcessOPMailCommand(Client *c, std::string command_string, boo case CommandJoin: if (!command_directed) { //Append saved channels to params - parameters = parameters + ", " + database.CurrentPlayerChannels(c->GetName()); + const auto saved_channels = database.CurrentPlayerChannels(c->GetName()); + if (!saved_channels.empty()) { + parameters += fmt::format(", {}", Strings::Join(saved_channels, ", ")); + } parameters = RemoveDuplicateChannels(parameters); } c->JoinChannels(parameters, command_directed); @@ -872,7 +876,7 @@ void Clientlist::ProcessOPMailCommand(Client *c, std::string command_string, boo break; case CommandGetBody: - database.SendBody(c, atoi(parameters.c_str())); + database.SendBody(c, Strings::ToInt(parameters.c_str())); break; case CommandMailTo: @@ -887,7 +891,7 @@ void Clientlist::ProcessOPMailCommand(Client *c, std::string command_string, boo case CommandSelectMailBox: { std::string::size_type NumStart = parameters.find_first_of("0123456789"); - c->ChangeMailBox(atoi(parameters.substr(NumStart).c_str())); + c->ChangeMailBox(Strings::ToInt(parameters.substr(NumStart).c_str())); break; } case CommandSetMailForwarding: @@ -1249,7 +1253,7 @@ void Client::ProcessChannelList(std::string Input) { std::string ChannelName = Input; if (isdigit(ChannelName[0])) - ChannelName = ChannelSlotName(atoi(ChannelName.c_str())); + ChannelName = ChannelSlotName(Strings::ToInt(ChannelName.c_str())); ChatChannel *RequiredChannel = ChannelList->FindChannel(ChannelName); @@ -1410,7 +1414,7 @@ void Client::SendChannelMessageByNumber(std::string Message) { if (MessageStart == std::string::npos) return; - int ChannelNumber = atoi(Message.substr(0, MessageStart).c_str()); + int ChannelNumber = Strings::ToInt(Message.substr(0, MessageStart).c_str()); if ((ChannelNumber < 1) || (ChannelNumber > MAX_JOINED_CHANNELS)) { @@ -1653,7 +1657,7 @@ void Client::SetChannelPassword(std::string ChannelPassword) { std::string ChannelName = ChannelPassword.substr(ChannelStart); if ((ChannelName.length() > 0) && isdigit(ChannelName[0])) - ChannelName = ChannelSlotName(atoi(ChannelName.c_str())); + ChannelName = ChannelSlotName(Strings::ToInt(ChannelName.c_str())); std::string Message; @@ -1718,7 +1722,7 @@ void Client::SetChannelOwner(std::string CommandString) { std::string ChannelName = CapitaliseName(CommandString.substr(ChannelStart)); if ((ChannelName.length() > 0) && isdigit(ChannelName[0])) - ChannelName = ChannelSlotName(atoi(ChannelName.c_str())); + ChannelName = ChannelSlotName(Strings::ToInt(ChannelName.c_str())); LogInfo("Set owner of channel [[{}]] to [[{}]]", ChannelName.c_str(), NewOwner.c_str()); @@ -1764,7 +1768,7 @@ void Client::OPList(std::string CommandString) { std::string ChannelName = CapitaliseName(CommandString.substr(ChannelStart)); if ((ChannelName.length() > 0) && isdigit(ChannelName[0])) - ChannelName = ChannelSlotName(atoi(ChannelName.c_str())); + ChannelName = ChannelSlotName(Strings::ToInt(ChannelName.c_str())); ChatChannel *RequiredChannel = ChannelList->FindChannel(ChannelName); @@ -1807,7 +1811,7 @@ void Client::ChannelInvite(std::string CommandString) { std::string ChannelName = CapitaliseName(CommandString.substr(ChannelStart)); if ((ChannelName.length() > 0) && isdigit(ChannelName[0])) - ChannelName = ChannelSlotName(atoi(ChannelName.c_str())); + ChannelName = ChannelSlotName(Strings::ToInt(ChannelName.c_str())); LogInfo("[[{}]] invites [[{}]] to channel [[{}]]", GetName().c_str(), Invitee.c_str(), ChannelName.c_str()); @@ -1877,7 +1881,7 @@ void Client::ChannelModerate(std::string CommandString) { std::string ChannelName = CapitaliseName(CommandString.substr(ChannelStart)); if ((ChannelName.length() > 0) && isdigit(ChannelName[0])) - ChannelName = ChannelSlotName(atoi(ChannelName.c_str())); + ChannelName = ChannelSlotName(Strings::ToInt(ChannelName.c_str())); ChatChannel *RequiredChannel = ChannelList->FindChannel(ChannelName); @@ -1935,7 +1939,7 @@ void Client::ChannelGrantModerator(std::string CommandString) { std::string ChannelName = CapitaliseName(CommandString.substr(ChannelStart)); if ((ChannelName.length() > 0) && isdigit(ChannelName[0])) - ChannelName = ChannelSlotName(atoi(ChannelName.c_str())); + ChannelName = ChannelSlotName(Strings::ToInt(ChannelName.c_str())); LogInfo("[[{}]] gives [[{}]] moderator rights to channel [[{}]]", GetName().c_str(), Moderator.c_str(), ChannelName.c_str()); @@ -2016,7 +2020,7 @@ void Client::ChannelGrantVoice(std::string CommandString) { std::string ChannelName = CapitaliseName(CommandString.substr(ChannelStart)); if ((ChannelName.length() > 0) && isdigit(ChannelName[0])) - ChannelName = ChannelSlotName(atoi(ChannelName.c_str())); + ChannelName = ChannelSlotName(Strings::ToInt(ChannelName.c_str())); LogInfo("[[{}]] gives [[{}]] voice to channel [[{}]]", GetName().c_str(), Voicee.c_str(), ChannelName.c_str()); @@ -2104,7 +2108,7 @@ void Client::ChannelKick(std::string CommandString) { std::string ChannelName = CapitaliseName(CommandString.substr(ChannelStart)); if ((ChannelName.length() > 0) && isdigit(ChannelName[0])) - ChannelName = ChannelSlotName(atoi(ChannelName.c_str())); + ChannelName = ChannelSlotName(Strings::ToInt(ChannelName.c_str())); LogInfo("[[{}]] kicks [[{}]] from channel [[{}]]", GetName().c_str(), Kickee.c_str(), ChannelName.c_str()); diff --git a/ucs/database.cpp b/ucs/database.cpp index 4c4e6dfbe..f214486fd 100644 --- a/ucs/database.cpp +++ b/ucs/database.cpp @@ -84,10 +84,10 @@ void UCSDatabase::GetAccountStatus(Client *client) auto row = results.begin(); - client->SetAccountStatus(atoi(row[0])); - client->SetHideMe(atoi(row[1]) != 0); - client->SetKarma(atoi(row[2])); - client->SetRevoked((atoi(row[3]) == 1 ? true : false)); + client->SetAccountStatus(Strings::ToInt(row[0])); + client->SetHideMe(Strings::ToInt(row[1]) != 0); + client->SetKarma(Strings::ToInt(row[2])); + client->SetRevoked((Strings::ToInt(row[3]) == 1 ? true : false)); LogDebug( "Set account status to [{}], hideme to [{}] and karma to [{}] for [{}]", @@ -119,9 +119,9 @@ int UCSDatabase::FindAccount(const char *characterName, Client *client) } auto row = results.begin(); - client->AddCharacter(atoi(row[0]), characterName, atoi(row[2])); + client->AddCharacter(Strings::ToInt(row[0]), characterName, Strings::ToInt(row[2])); - int accountID = atoi(row[1]); + int accountID = Strings::ToInt(row[1]); LogInfo("Account ID for [{}] is [{}]", characterName, accountID); @@ -137,7 +137,7 @@ int UCSDatabase::FindAccount(const char *characterName, Client *client) } for (auto row = results.begin(); row != results.end(); ++row) - client->AddCharacter(atoi(row[0]), row[1], atoi(row[2])); + client->AddCharacter(Strings::ToInt(row[0]), row[1], Strings::ToInt(row[2])); return accountID; } @@ -197,7 +197,7 @@ int UCSDatabase::FindCharacter(const char *characterName) auto row = results.begin(); - int characterID = atoi(row[0]); + int characterID = Strings::ToInt(row[0]); return characterID; } @@ -225,7 +225,9 @@ bool UCSDatabase::GetVariable(const char *varname, char *varvalue, uint16 varval bool UCSDatabase::LoadChatChannels() { - LoadFilteredNamesFromDB(); + if (!RuleB(Chat, ChannelsIgnoreNameFilter)) { + LoadFilteredNamesFromDB(); + } LoadReservedNamesFromDB(); LogInfo("Loading chat channels from the database"); @@ -242,7 +244,7 @@ bool UCSDatabase::LoadChatChannels() auto channel_min_status = row[3]; if (!ChannelList->FindChannel(channel_name)) { - ChannelList->CreateChannel(channel_name, channel_owner, channel_password, true, atoi(channel_min_status), false); + ChannelList->CreateChannel(channel_name, channel_owner, channel_password, true, Strings::ToInt(channel_min_status), false); } } return true; @@ -281,18 +283,6 @@ void UCSDatabase::LoadFilteredNamesFromDB() LogInfo("Loaded [{}] filtered channel name(s)", names.size()); } -bool UCSDatabase::IsChatChannelInDB(const std::string& channel_name) -{ - auto r = ChatchannelsRepository::Count( - *this, - fmt::format( - "name = {}", Strings::Escape(channel_name) - ) - ); - - return r > 0; -} - void UCSDatabase::SaveChatChannel( const std::string& channel_name, const std::string& channel_owner, @@ -334,16 +324,17 @@ void UCSDatabase::DeleteChatChannel(const std::string& channel_name) LogInfo("Deleting channel [{}] from the database.", channel_name); } -std::string UCSDatabase::CurrentPlayerChannels(const std::string& player_name) { - int current_player_channel_count = CurrentPlayerChannelCount(player_name); - if (current_player_channel_count == 0) { - return ""; +std::vector UCSDatabase::CurrentPlayerChannels(const std::string& player_name) { + auto rows = ChatchannelsRepository::GetWhere(*this, fmt::format("`owner` = '{}'", Strings::Escape(player_name))); + if (rows.empty()) { + return {}; } - const auto rquery = fmt::format("SELECT GROUP_CONCAT(`name` SEPARATOR ', ') FROM chatchannels WHERE `owner` = '{}'; ", Strings::Escape(player_name)); - auto results = QueryDatabase(rquery); - auto row = results.begin(); - std::string channels = row[0]; - LogDebug("Player [{}] has the following permanent channels saved to the database: [{}].", player_name, channels); + std::vector channels = {}; + channels.reserve(rows.size()); + for (auto &e: rows) { + channels.emplace_back(e.name); + } + LogDebug("Player [{}] has the following [{}] permanent channels saved to the database: [{}].", player_name, rows.size(), Strings::Join(channels, ", ")); return channels; } @@ -740,7 +731,7 @@ void UCSDatabase::GetFriendsAndIgnore(const int& charID, std::vector #include #include -//atoi is not uint32 or uint32 safe!!!! -#define atoul(str) strtoul(str, nullptr, 10) class UCSDatabase : public Database { public: @@ -46,12 +45,11 @@ public: bool LoadChatChannels(); void LoadReservedNamesFromDB(); void LoadFilteredNamesFromDB(); - bool IsChatChannelInDB(const std::string& channel_name); bool CheckChannelNameFilter(const std::string& channel_name); void SaveChatChannel(const std::string& channel_name, const std::string& channel_owner, const std::string& channel_password, const uint16& min_status); void DeleteChatChannel(const std::string& channel_name); int CurrentPlayerChannelCount(const std::string& player_name); - std::string CurrentPlayerChannels(const std::string& player_name); + std::vector CurrentPlayerChannels(const std::string& player_name); void GetAccountStatus(Client *c); void SetChannelPassword(const std::string& channel_name, const std::string& password); void SetChannelOwner(const std::string& channel_name, const std::string& owner); @@ -63,12 +61,6 @@ public: void AddFriendOrIgnore(const int& char_id, const int& type, const std::string& name); void RemoveFriendOrIgnore(const int& char_id, const int& type, const std::string& name); void GetFriendsAndIgnore(const int& char_id, std::vector &Friends, std::vector &Ignorees); - -protected: - void HandleMysqlError(uint32 errnum); -private: - void DBInitVars(); - }; #endif diff --git a/ucs/ucs.cpp b/ucs/ucs.cpp index 78dabcc08..8b365b96d 100644 --- a/ucs/ucs.cpp +++ b/ucs/ucs.cpp @@ -37,9 +37,10 @@ #include "../common/net/tcp_server.h" #include "../common/net/servertalk_client_connection.h" -#include "../common/discord_manager.h" +#include "../common/discord/discord_manager.h" #include "../common/path_manager.h" #include "../common/zone_store.h" +#include "../common/events/player_event_logs.h" ChatChannelList *ChannelList; Clientlist *g_Clientlist; @@ -49,6 +50,7 @@ WorldServer *worldserver = nullptr; DiscordManager discord_manager; PathManager path; ZoneStore zone_store; +PlayerEventLogs player_event_logs; const ucsconfig *Config; @@ -93,7 +95,7 @@ void CatchSignal(int sig_num) { } } -void DiscordQueueListener() { +void PlayerEventQueueListener() { while (caught_loop == 0) { discord_manager.ProcessMessageQueue(); Sleep(100); @@ -112,7 +114,7 @@ int main() { Timer ChannelListProcessTimer(60000); Timer ClientConnectionPruneTimer(60000); - Timer InterserverTimer(INTERSERVER_TIMER); // does auto-reconnect + Timer keepalive(INTERSERVER_TIMER); // does auto-reconnect LogInfo("Starting EQEmu Universal Chat Server"); @@ -177,7 +179,7 @@ int main() { std::signal(SIGKILL, CatchSignal); std::signal(SIGSEGV, CatchSignal); - std::thread(DiscordQueueListener).detach(); + std::thread(PlayerEventQueueListener).detach(); worldserver = new WorldServer; @@ -186,6 +188,10 @@ int main() { // crash_test.detach(); auto loop_fn = [&](EQ::Timer* t) { + if (keepalive.Check()) { + keepalive.Start(); + database.ping(); + } Timer::SetCurrentTime(); diff --git a/ucs/worldserver.cpp b/ucs/worldserver.cpp index f7522040c..39e076d7b 100644 --- a/ucs/worldserver.cpp +++ b/ucs/worldserver.cpp @@ -26,7 +26,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "clientlist.h" #include "ucsconfig.h" #include "database.h" -#include "../common/discord_manager.h" +#include "../common/discord/discord_manager.h" +#include "../common/events/player_event_logs.h" #include #include @@ -76,6 +77,18 @@ void WorldServer::ProcessMessage(uint16 opcode, EQ::Net::Packet &p) } case ServerOP_ReloadLogs: { LogSys.LoadLogDatabaseSettings(); + player_event_logs.ReloadSettings(); + break; + } + case ServerOP_PlayerEvent: { + auto n = PlayerEvent::PlayerEventContainer{}; + auto s = (ServerSendPlayerEvent_Struct*) pack->pBuffer; + EQ::Util::MemoryStreamReader ss(s->cereal_data, s->cereal_size); + cereal::BinaryInputArchive archive(ss); + archive(n); + + discord_manager.QueuePlayerEventMessage(n); + break; } case ServerOP_DiscordWebhookMessage: { diff --git a/utils/TaskMaster/activities.cpp b/utils/TaskMaster/activities.cpp index 4cbb2a1b5..2f2dc0451 100644 --- a/utils/TaskMaster/activities.cpp +++ b/utils/TaskMaster/activities.cpp @@ -507,11 +507,11 @@ void MainFrame::SaveActivity(wxCommandEvent& event) ourAct.optional = mActivityOptional->GetValue(); getStr = mActID->GetValue(); - ourAct.activityId = atoi(getStr.mb_str()); + ourAct.activityId = Strings::ToInt(getStr.mb_str()); getStr.Clear(); getStr = mActStep->GetValue(); - ourAct.step = atoi(getStr.mb_str()); + ourAct.step = Strings::ToInt(getStr.mb_str()); getStr.Clear(); int type = mActType->GetSelection(); @@ -530,17 +530,17 @@ void MainFrame::SaveActivity(wxCommandEvent& event) } getStr = mActDeliver->GetValue(); - ourAct.deliverToNpc = atoi(getStr.mb_str()); + ourAct.deliverToNpc = Strings::ToInt(getStr.mb_str()); getStr.Clear(); ourAct.goalmethod = mActMethod->GetSelection(); getStr = mActGoalID->GetValue(); - ourAct.goalid = atoi(getStr.mb_str()); + ourAct.goalid = Strings::ToInt(getStr.mb_str()); getStr.Clear(); getStr = mActGoalCount->GetValue(); - ourAct.goalcount = atoi(getStr.mb_str()); + ourAct.goalcount = Strings::ToInt(getStr.mb_str()); getStr.Clear(); if(ourAct.activityId == openedActivity.activityid && ourAct.id == openedActivity.id){ @@ -645,4 +645,4 @@ void MainFrame::ContextMenuActivityList() PopupMenu(mMenu); delete mMenu; -} \ No newline at end of file +} diff --git a/utils/TaskMaster/base_utility.cpp b/utils/TaskMaster/base_utility.cpp index d507bdb89..dbbd444f7 100644 --- a/utils/TaskMaster/base_utility.cpp +++ b/utils/TaskMaster/base_utility.cpp @@ -76,7 +76,7 @@ bool MainFrame::LoadItems(){ while ((row = mysql_fetch_row(res)) != NULL){ eqitem newIT; strcpy(newIT.name, row[0]); - newIT.id = atoi(row[1]); + newIT.id = Strings::ToInt(row[1]); itemList.push_back(newIT); itemsLoaded++; } @@ -127,7 +127,7 @@ bool MainFrame::LoadZones() eqtask_zones newZ; strcpy(newZ.name, row[0]); - newZ.id = atoi(row[1]); + newZ.id = Strings::ToInt(row[1]); taskZoneList.push_back(newZ); int * zoneId = new int; @@ -168,7 +168,7 @@ bool MainFrame::LoadTasks() res = mysql_use_result(mMysql); while ((row = mysql_fetch_row(res)) != NULL){ eqtask newT; - newT.id = atoi(row[0]); + newT.id = Strings::ToInt(row[0]); //This isn't all that safe //Working under the assumption that: @@ -185,15 +185,15 @@ bool MainFrame::LoadTasks() if(newT.id > highestIndex) highestIndex = newT.id; - newT.rewardid = atoi(row[4]); - newT.cashreward = atoi(row[5]); - newT.xpreward = atoi(row[6]); - newT.rewardmethod = atoi(row[7]); - newT.startzone = atoi(row[8]); - newT.duration = atoi(row[9]); - newT.level_min = atoi(row[10]); - newT.level_max = atoi(row[11]); - newT.repeatable = atoi(row[12]) ? true : false; + newT.rewardid = Strings::ToInt(row[4]); + newT.cashreward = Strings::ToInt(row[5]); + newT.xpreward = Strings::ToInt(row[6]); + newT.rewardmethod = Strings::ToInt(row[7]); + newT.startzone = Strings::ToInt(row[8]); + newT.duration = Strings::ToInt(row[9]); + newT.level_min = Strings::ToInt(row[10]); + newT.level_max = Strings::ToInt(row[11]); + newT.repeatable = Strings::ToInt(row[12]) ? true : false; taskList.push_back(newT); @@ -225,8 +225,8 @@ bool MainFrame::LoadGoals() res = mysql_use_result(mMysql); while ((row = mysql_fetch_row(res)) != NULL){ eqtask_goallist newGL; - newGL.id = atoi(row[0]); - newGL.value = atoi(row[1]); + newGL.id = Strings::ToInt(row[0]); + newGL.value = Strings::ToInt(row[1]); goalTaskList.push_back(newGL); goalsLoaded++; @@ -258,19 +258,19 @@ bool MainFrame::LoadActivities() { while ((row = mysql_fetch_row(res)) != NULL) { eqtask_activities newAL; - newAL.id = atoi(row[0]); - newAL.activityId = atoi(row[1]); - newAL.step = atoi(row[2]); - newAL.activityType = atoi(row[3]); + newAL.id = Strings::ToInt(row[0]); + newAL.activityId = Strings::ToInt(row[1]); + newAL.step = Strings::ToInt(row[2]); + newAL.activityType = Strings::ToInt(row[3]); strcpy(newAL.text1, row[4]); strcpy(newAL.text2, row[5]); strcpy(newAL.text3, row[6]); - newAL.goalid = atoi(row[7]); - newAL.goalmethod = atoi(row[8]); - newAL.goalcount = atoi(row[9]); - newAL.deliverToNpc = atoi(row[10]); - newAL.zoneid = atoi(row[11]); - newAL.optional = atoi(row[12]) ? true : false; + newAL.goalid = Strings::ToInt(row[7]); + newAL.goalmethod = Strings::ToInt(row[8]); + newAL.goalcount = Strings::ToInt(row[9]); + newAL.deliverToNpc = Strings::ToInt(row[10]); + newAL.zoneid = Strings::ToInt(row[11]); + newAL.optional = Strings::ToInt(row[12]) ? true : false; taskActivitiesList.push_back(newAL); activitiesLoaded++; @@ -301,8 +301,8 @@ bool MainFrame::LoadProximity() while ((row = mysql_fetch_row(res)) != NULL){ eqtask_proximity newPR; - newPR.zoneid = atoi(row[0]); - newPR.exploreid = atoi(row[1]); + newPR.zoneid = Strings::ToInt(row[0]); + newPR.exploreid = Strings::ToInt(row[1]); newPR.minx = atof(row[2]); newPR.maxx = atof(row[3]); newPR.miny = atof(row[4]); @@ -438,4 +438,4 @@ wxString MainFrame::MakeStringSQLSafe(const char * c) ret.Printf("%s", c); ret.Replace("\'", "\\\'"); return ret; -} \ No newline at end of file +} diff --git a/utils/TaskMaster/proximity.cpp b/utils/TaskMaster/proximity.cpp index 0ed3820d9..cbe498d7a 100644 --- a/utils/TaskMaster/proximity.cpp +++ b/utils/TaskMaster/proximity.cpp @@ -276,7 +276,7 @@ void MainFrame::SaveProximity(wxCommandEvent& event) inStr.Clear(); inStr = mProxId->GetValue(); - toSave.exploreid = atoi(inStr.mb_str()); + toSave.exploreid = Strings::ToInt(inStr.mb_str()); inStr.Clear(); inStr = mProxMinx->GetValue(); @@ -465,4 +465,4 @@ void MainFrame::ContextMenuProximity() PopupMenu(mMenu); delete mMenu; -} \ No newline at end of file +} diff --git a/utils/TaskMaster/tasks.cpp b/utils/TaskMaster/tasks.cpp index 48aa44080..9cfedb7fe 100644 --- a/utils/TaskMaster/tasks.cpp +++ b/utils/TaskMaster/tasks.cpp @@ -195,7 +195,7 @@ void MainFrame::OnRewardButton(wxCommandEvent& event) { wxString ridStr = mRewardID->GetValue(); int rtype = mRewardMethod->GetCurrentSelection(); - int rid = atoi(ridStr.mb_str()); + int rid = Strings::ToInt(ridStr.mb_str()); ShowRewardChange(rtype,rid); } @@ -224,15 +224,15 @@ void MainFrame::SaveTask(wxCommandEvent& event) getStr.Clear(); getStr = mTaskMinLvl->GetValue(); - ourTask.level_min = atoi(getStr.mb_str()); + ourTask.level_min = Strings::ToInt(getStr.mb_str()); getStr.Clear(); getStr = mTaskMaxLvl->GetValue(); - ourTask.level_max = atoi(getStr.mb_str()); + ourTask.level_max = Strings::ToInt(getStr.mb_str()); getStr.Clear(); getStr = mTaskDuration->GetValue(); - ourTask.duration = atoi(getStr.mb_str()); + ourTask.duration = Strings::ToInt(getStr.mb_str()); getStr.Clear(); getStr = mRewardName->GetValue(); @@ -240,15 +240,15 @@ void MainFrame::SaveTask(wxCommandEvent& event) getStr.Clear(); getStr = mRewardID->GetValue(); - ourTask.rewardid = atoi(getStr.mb_str()); + ourTask.rewardid = Strings::ToInt(getStr.mb_str()); getStr.Clear(); getStr = mRewardCash->GetValue(); - ourTask.cashreward = atoi(getStr.mb_str()); + ourTask.cashreward = Strings::ToInt(getStr.mb_str()); getStr.Clear(); getStr = mRewardXP->GetValue(); - ourTask.xpreward = atoi(getStr.mb_str()); + ourTask.xpreward = Strings::ToInt(getStr.mb_str()); getStr.Clear(); int * i = (int*)mStartZone->GetClientData(mStartZone->GetSelection()); @@ -325,4 +325,4 @@ void MainFrame::ContextMenuTaskList() PopupMenu(mMenu); delete mMenu; -} \ No newline at end of file +} diff --git a/utils/deprecated/apathing/load_db.cpp b/utils/deprecated/apathing/load_db.cpp index 44a5f7b80..dc712568e 100644 --- a/utils/deprecated/apathing/load_db.cpp +++ b/utils/deprecated/apathing/load_db.cpp @@ -19,8 +19,8 @@ Fear Pathing generation utility. bool load_paths_from_db(MYSQL *m, Map *map, const char *zone, list &db_paths, list &end_points) { char query[512]; - - sprintf(query, + + sprintf(query, "SELECT x,y,z,gridid FROM grid_entries,zone " "WHERE zone.zoneidnumber=zoneid AND short_name='%s' " "ORDER BY gridid,number", zone); @@ -28,21 +28,21 @@ bool load_paths_from_db(MYSQL *m, Map *map, const char *zone, list & printf("Unable to query: %s\n", mysql_error(m)); return(false); } - + MYSQL_RES *res = mysql_store_result(m); if(res == NULL) { printf("Unable to store res: %s\n", mysql_error(m)); return(false); } - + MYSQL_ROW row; - + PathNode *cur = NULL, *last = NULL, *first = NULL; PathGraph *g = NULL; int cur_g = -1,last_g = -1; - + // int lid = 0; - + while((row = mysql_fetch_row(res))) { last = cur; cur = new PathNode; @@ -50,7 +50,7 @@ bool load_paths_from_db(MYSQL *m, Map *map, const char *zone, list & cur->x = atof(row[0]); cur->y = atof(row[1]); cur->z = atof(row[2]); - cur_g = atoi(row[3]); + cur_g = Strings::ToInt(row[3]); if(cur_g != last_g) { if(g != NULL) { //if we have a first and last node for this path @@ -70,15 +70,15 @@ bool load_paths_from_db(MYSQL *m, Map *map, const char *zone, list & last_g = cur_g; last = NULL; } - + g->nodes.push_back(cur); - + #ifdef LINK_PATH_ENDPOINTS //this is a begining point if(last == NULL) end_points.push_back(cur); #endif - + if(last != NULL) { #ifdef SPLIT_INVALID_PATHS if(CheckLOS(map, last, cur)) { @@ -93,7 +93,7 @@ bool load_paths_from_db(MYSQL *m, Map *map, const char *zone, list & #endif } } - + //handle the last active path if(g != NULL) { if(first != NULL && cur->Dist2(first) < ENDPOINT_CONNECT_MAX_DISTANCE*ENDPOINT_CONNECT_MAX_DISTANCE) { @@ -102,7 +102,7 @@ bool load_paths_from_db(MYSQL *m, Map *map, const char *zone, list & } db_paths.push_back(g); } - + mysql_free_result(res); return(true); } @@ -110,25 +110,25 @@ bool load_paths_from_db(MYSQL *m, Map *map, const char *zone, list & bool load_spawns_from_db(MYSQL *m, const char *zone, list &db_spawns) { char query[512]; - - sprintf(query, + + sprintf(query, "SELECT x,y,z FROM spawn2 " "WHERE zone='%s'", zone); if(mysql_query(m, query) != 0) { printf("Unable to query: %s\n", mysql_error(m)); return(false); } - + MYSQL_RES *res = mysql_store_result(m); if(res == NULL) { printf("Unable to store res: %s\n", mysql_error(m)); return(false); } - + MYSQL_ROW row; - + PathNode *cur = NULL; - + while((row = mysql_fetch_row(res))) { cur = new PathNode; cur->x = atof(row[0]); @@ -136,34 +136,34 @@ bool load_spawns_from_db(MYSQL *m, const char *zone, list &db_spawns) cur->z = atof(row[2]); db_spawns.push_back(cur); } - + mysql_free_result(res); - + return(true); } bool load_doors_from_db(MYSQL *m, const char *zone, list &db_spawns) { char query[512]; - - sprintf(query, + + sprintf(query, "SELECT pos_x,pos_y,pos_z FROM doors " "WHERE zone='%s'", zone); if(mysql_query(m, query) != 0) { printf("Unable to query: %s\n", mysql_error(m)); return(false); } - + MYSQL_RES *res = mysql_store_result(m); if(res == NULL) { printf("Unable to store res: %s\n", mysql_error(m)); return(false); } - + MYSQL_ROW row; - + PathNode *cur = NULL; - + while((row = mysql_fetch_row(res))) { cur = new PathNode; cur->x = atof(row[0]); @@ -173,54 +173,54 @@ bool load_doors_from_db(MYSQL *m, const char *zone, list &db_spawns) //doors, not the edge of them which I assume these points are db_spawns.push_back(cur); } - + mysql_free_result(res); - + return(true); } bool load_hints_from_db(MYSQL *m, const char *zone, list &db_spawns) { char query[512]; - - sprintf(query, + + sprintf(query, "SELECT x,y,z,forced,disjoint FROM fear_hints " "WHERE zone='%s'", zone); if(mysql_query(m, query) != 0) { printf("Unable to query: %s\n", mysql_error(m)); return(false); } - + MYSQL_RES *res = mysql_store_result(m); if(res == NULL) { printf("Unable to store res: %s\n", mysql_error(m)); return(false); } - + MYSQL_ROW row; - + PathNode *cur = NULL; - + while((row = mysql_fetch_row(res))) { cur = new PathNode; cur->x = atof(row[0]); cur->y = atof(row[1]); cur->z = atof(row[2]); - cur->forced = atoi(row[3])?true:false; - cur->disjoint = atoi(row[4])?true:false; + cur->forced = Strings::ToInt(row[3])?true:false; + cur->disjoint = Strings::ToInt(row[4])?true:false; db_spawns.push_back(cur); } - + mysql_free_result(res); - + return(true); } bool load_settings_from_db(MYSQL *m, const char *zone) { char query[512]; - - sprintf(query, + + sprintf(query, "SELECT use_doors, min_fix_z, max_fear_distance, image_scale, split_invalid_paths," " link_path_endpoints, end_distance, split_long_min, split_long_step, same_dist, node_combine_dist," " grid_combine_dist, close_all_los, cross_count, cross_min_length, cross_max_z_diff, cross_combine_dist," @@ -231,46 +231,46 @@ bool load_settings_from_db(MYSQL *m, const char *zone) { // printf("Unable to query: %s\n", mysql_error(m)); return(false); } - + MYSQL_RES *res = mysql_store_result(m); if(res == NULL) { // printf("Unable to store res: %s\n", mysql_error(m)); return(false); } - + MYSQL_ROW row; - + int r = 0; if((row = mysql_fetch_row(res))) { - INCLUDE_DOORS = atoi(row[r++])?true:false; + INCLUDE_DOORS = Strings::ToInt(row[r++])?true:false; MIN_FIX_Z = atof(row[r++]); FEAR_MAXIMUM_DISTANCE = atof(row[r++]); - IMAGE_SCALE = atoi(row[r++]); - SPLIT_INVALID_PATHS = atoi(row[r++])?true:false; - LINK_PATH_ENDPOINTS = atoi(row[r++])?true:false; + IMAGE_SCALE = Strings::ToInt(row[r++]); + SPLIT_INVALID_PATHS = Strings::ToInt(row[r++])?true:false; + LINK_PATH_ENDPOINTS = Strings::ToInt(row[r++])?true:false; ENDPOINT_CONNECT_MAX_DISTANCE = atof(row[r++]); SPLIT_LINE_LENGTH = atof(row[r++]); SPLIT_LINE_INTERVAL = atof(row[r++]); CLOSE_ENOUGH = atof(row[r++]); CLOSE_ENOUGH_COMBINE = atof(row[r++]); MERGE_MIN_SECOND_DIST = atof(row[r++]); - COMBINE_CHECK_ALL_LOS = atoi(row[r++])?true:false; - CROSS_REDUCE_COUNT = atoi(row[r++]); + COMBINE_CHECK_ALL_LOS = Strings::ToInt(row[r++])?true:false; + CROSS_REDUCE_COUNT = Strings::ToInt(row[r++]); CROSS_MIN_LENGTH = atof(row[r++]); CROSS_MAX_Z_DIFF = atof(row[r++]); CLOSE_ENOUGH_CROSS = atof(row[r++]); - + SPAWN_MIN_SECOND_DIST = atof(row[r++]); MAX_LINK_SPAWN_DIST = atof(row[r++]); - int sc = atoi(row[r++]); + int sc = Strings::ToInt(row[r++]); SPAWN_LINK_TWICE = sc >= 2?true:false; SPAWN_LINK_THRICE = sc >= 3?true:false; mysql_free_result(res); return(true); } - + mysql_free_result(res); - + return(false); } diff --git a/utils/deprecated/azone2/azone.cpp b/utils/deprecated/azone2/azone.cpp index 81a143ba2..c457d4540 100644 --- a/utils/deprecated/azone2/azone.cpp +++ b/utils/deprecated/azone2/azone.cpp @@ -1118,7 +1118,7 @@ void QTBuilder::AddPlaceable(FileLoader *fileloader, char *ZoneFileName, bool Li if((ch==EOF)||(ch=='\n')) { IniBuffer[StrIndex] = '\0'; if(State == ReadingModelNumbers) { - ModelNumber = atoi(IniBuffer); + ModelNumber = Strings::ToInt(IniBuffer); if((ModelNumber >= 0) && (ModelNumber < fileloader->model_data.model_count)) { fileloader->model_data.models[ModelNumber]->IncludeInMap = true; @@ -1146,7 +1146,7 @@ void QTBuilder::AddPlaceable(FileLoader *fileloader, char *ZoneFileName, bool Li } } else { - ModelNumber = atoi(IniBuffer); + ModelNumber = Strings::ToInt(IniBuffer); if((ModelNumber >= 0) && (ModelNumber < fileloader->model_data.model_count)) { fileloader->model_data.models[ModelNumber]->IncludeInMap = true; @@ -1323,7 +1323,7 @@ void QTBuilder::AddPlaceableV4(FileLoader *fileloader, char *ZoneFileName, bool Group = true; strcpy(IniBuffer, IniBuffer+1); } - ModelNumber = atoi(IniBuffer); + ModelNumber = Strings::ToInt(IniBuffer); if(!Group) { if((ModelNumber >= 0) && (ModelNumber < fileloader->model_data.model_count)) @@ -1369,7 +1369,7 @@ void QTBuilder::AddPlaceableV4(FileLoader *fileloader, char *ZoneFileName, bool Group = true; strcpy(IniBuffer, IniBuffer+1); } - ModelNumber = atoi(IniBuffer); + ModelNumber = Strings::ToInt(IniBuffer); if(!Group) { if((ModelNumber >= 0) && (ModelNumber < fileloader->model_data.model_count)) diff --git a/utils/deprecated/azone2/dat.cpp b/utils/deprecated/azone2/dat.cpp index 7fec482be..645814787 100644 --- a/utils/deprecated/azone2/dat.cpp +++ b/utils/deprecated/azone2/dat.cpp @@ -278,7 +278,7 @@ int DATLoader::Open(char *base_path, char *zone_name, Archive *archive) { if(Token == "*QUADSPERTILE") { Token = GetToken(ZonBuffer, ZonPosition); - QuadsPerTile = atoi(Token.c_str()); + QuadsPerTile = Strings::ToInt(Token.c_str()); #ifdef DEBUGDAT printf("Set QuadsPerTile to %i\n", QuadsPerTile); #endif diff --git a/utils/deprecated/azone2/wld.cpp b/utils/deprecated/azone2/wld.cpp index d4dbcf25b..953a777c4 100644 --- a/utils/deprecated/azone2/wld.cpp +++ b/utils/deprecated/azone2/wld.cpp @@ -97,7 +97,7 @@ FRAG_CONSTRUCTOR(Data15) { plac->scale[1] = hdr->scale[1]; plac->scale[2] = hdr->scale[1]; - plac->model = atoi((const char*)&wld->sHash[-(int)hdr->ref]); + plac->model = Strings::ToInt((const char*)&wld->sHash[-(int)hdr->ref]); pl = new Placeable *[wld->model_data.plac_count + 1]; memcpy(pl, wld->model_data.placeable, sizeof(Placeable *) * wld->model_data.plac_count); diff --git a/utils/deprecated/charmove/export_char.cpp b/utils/deprecated/charmove/export_char.cpp index 293c3d7b9..68e796b55 100644 --- a/utils/deprecated/charmove/export_char.cpp +++ b/utils/deprecated/charmove/export_char.cpp @@ -20,41 +20,41 @@ void usage() { } int main(int argc, char *argv[]) { - + const char *outfile; - + if(argc != 3) usage(); - int charid = atoi(argv[1]); + int charid = Strings::ToInt(argv[1]); if(charid == 0) usage(); outfile = argv[2]; - + char *query = new char[1024]; char host[200], user[200], passwd[200], database[200]; int32 port=0; bool compression = false; bool items[6] = {false, false, false, false, false, false}; - + if(!DBcore::ReadDBINI(host, user, passwd, database, port, compression, items)) { exit(1); } - + if (!items[0] || !items[1] || !items[2] || !items[3]) { printf ("Incomplete DB.INI file.\n"); exit (1); } - + MYSQL m; mysql_init(&m); - + if(!mysql_real_connect(&m, host, user, passwd, database, 0, NULL, 0)) { printf("Unable to connect 1: %s.\n", mysql_error(&m)); return(1); } - + CharHeader header; char *ppbuffer; char *eppbuffer; @@ -62,13 +62,13 @@ int main(int argc, char *argv[]) { InventoryEntry *inventory; InventoryEntry *sharedbank; QuestGlobalEntry *qglobals;*/ - + sprintf(query, "SELECT name,profile,extprofile,x,y,z,zonename,zoneid FROM character_ WHERE id=%d", charid); if(mysql_query(&m, query) != 0) { printf("Unable to query.\n"); return(1); } - + MYSQL_RES *res = mysql_use_result(&m); if(res == NULL) { printf("Unable to use character_ res.\n"); @@ -82,7 +82,7 @@ int main(int argc, char *argv[]) { } unsigned long* lengths; lengths = mysql_fetch_lengths(res); - + header.char_magic = CHAR_MAGIC; strcpy(header.name, row[0]); header.profile_length = lengths[1]; @@ -91,15 +91,15 @@ int main(int argc, char *argv[]) { header.y = atof(row[4]); header.z = atof(row[5]); strcpy(header.zone_name, row[6]); - header.zone_id = atoi(row[7]); + header.zone_id = Strings::ToInt(row[7]); //copy in blobs ppbuffer = new char[header.profile_length]; eppbuffer = new char[header.extprofile_length]; memcpy(ppbuffer, row[1], header.profile_length); memcpy(eppbuffer, row[2], header.extprofile_length); - + mysql_free_result(res); - + //query faction sprintf(query, "SELECT faction_id,current_value FROM faction_values WHERE char_id=%d", charid); if(mysql_query(&m, query) != 0) { @@ -114,12 +114,12 @@ int main(int argc, char *argv[]) { vector fr; while((row = mysql_fetch_row(res))) { FactionValueRecord r; - r.faction_id = atoi(row[0]); - r.current_value = atoi(row[1]); + r.faction_id = Strings::ToInt(row[0]); + r.current_value = Strings::ToInt(row[1]); fr.push_back(r); } mysql_free_result(res); - + //query inventory sprintf(query, "SELECT slotid,itemid,charges,color,augslot1,augslot2,augslot3,augslot4,augslot5,instnodrop FROM inventory WHERE charid=%d", charid); if(mysql_query(&m, query) != 0) { @@ -134,19 +134,19 @@ int main(int argc, char *argv[]) { vector inv; while((row = mysql_fetch_row(res))) { InventoryEntry r; - r.slotid = atoi(row[0]); - r.itemid = atoi(row[1]); - r.charges = atoi(row[2]); - r.colors = atoi(row[3]); - r.augs[0] = atoi(row[4]); - r.augs[1] = atoi(row[5]); - r.augs[2] = atoi(row[6]); - r.augs[3] = atoi(row[7]); - r.augs[4] = atoi(row[8]); + r.slotid = Strings::ToInt(row[0]); + r.itemid = Strings::ToInt(row[1]); + r.charges = Strings::ToInt(row[2]); + r.colors = Strings::ToInt(row[3]); + r.augs[0] = Strings::ToInt(row[4]); + r.augs[1] = Strings::ToInt(row[5]); + r.augs[2] = Strings::ToInt(row[6]); + r.augs[3] = Strings::ToInt(row[7]); + r.augs[4] = Strings::ToInt(row[8]); inv.push_back(r); } mysql_free_result(res); - + //query shared bank sprintf(query, "SELECT slotid,itemid,charges,augslot1,augslot2,augslot3,augslot4,augslot5 FROM sharedbank,character_ WHERE sharedbank.acctid = character_.account_id AND character_.id=%d", charid); if(mysql_query(&m, query) != 0) { @@ -161,18 +161,18 @@ int main(int argc, char *argv[]) { vector sb; while((row = mysql_fetch_row(res))) { InventoryEntry r; - r.slotid = atoi(row[0]); - r.itemid = atoi(row[1]); - r.charges = atoi(row[2]); - r.augs[0] = atoi(row[3]); - r.augs[1] = atoi(row[4]); - r.augs[2] = atoi(row[5]); - r.augs[3] = atoi(row[6]); - r.augs[4] = atoi(row[7]); + r.slotid = Strings::ToInt(row[0]); + r.itemid = Strings::ToInt(row[1]); + r.charges = Strings::ToInt(row[2]); + r.augs[0] = Strings::ToInt(row[3]); + r.augs[1] = Strings::ToInt(row[4]); + r.augs[2] = Strings::ToInt(row[5]); + r.augs[3] = Strings::ToInt(row[6]); + r.augs[4] = Strings::ToInt(row[7]); sb.push_back(r); } mysql_free_result(res); - + //query quest_globals sprintf(query, "SELECT npcid,zoneid,name,value,expdate FROM quest_globals WHERE charid=%d", charid); if(mysql_query(&m, query) != 0) { @@ -187,37 +187,37 @@ int main(int argc, char *argv[]) { vector qg; while((row = mysql_fetch_row(res))) { QuestGlobalEntry r; - r.npcid = atoi(row[0]); - r.zoneid = atoi(row[1]); + r.npcid = Strings::ToInt(row[0]); + r.zoneid = Strings::ToInt(row[1]); strcpy(r.name, row[2]); strcpy(r.value, row[3]); - r.expdate = atoi(row[4]); + r.expdate = Strings::ToInt(row[4]); qg.push_back(r); } mysql_free_result(res); - + mysql_close(&m); - - + + FILE *outf = fopen(outfile, "wb"); if(outf == NULL) { printf("Unable to open output file %s\n", outfile); return(1); } - + //fill in our counters header.faction_value_count = fr.size(); header.inventory_count = inv.size(); header.sharedbank_count = sb.size(); header.quest_globals_count = qg.size(); - + //write header fwrite(&header, 1, sizeof(header), outf); - + //write out pp and epp fwrite(ppbuffer, 1, header.profile_length, outf); fwrite(eppbuffer, 1, header.extprofile_length, outf); - + //write out our variable length segments vector::iterator curfr, endfr; curfr = fr.begin(); @@ -226,7 +226,7 @@ int main(int argc, char *argv[]) { FactionValueRecord &r = *curfr; fwrite(&r, 1, sizeof(FactionValueRecord), outf); } - + vector::iterator curi, endi; curi = inv.begin(); endi = inv.end(); @@ -234,14 +234,14 @@ int main(int argc, char *argv[]) { InventoryEntry &i = *curi; fwrite(&i, 1, sizeof(InventoryEntry), outf); } - + curi = sb.begin(); endi = sb.end(); for(; curi != endi; curi++) { InventoryEntry &i = *curi; fwrite(&i, 1, sizeof(InventoryEntry), outf); } - + vector::iterator curqg, endqg; curqg = qg.begin(); endqg = qg.end(); @@ -249,9 +249,9 @@ int main(int argc, char *argv[]) { QuestGlobalEntry &r = *curqg; fwrite(&r, 1, sizeof(QuestGlobalEntry), outf); } - + fclose(outf); - + return(0); } diff --git a/utils/deprecated/charmove/import_char.cpp b/utils/deprecated/charmove/import_char.cpp index 48bb009a5..1a330df62 100644 --- a/utils/deprecated/charmove/import_char.cpp +++ b/utils/deprecated/charmove/import_char.cpp @@ -15,42 +15,42 @@ void usage() { } int main(int argc, char *argv[]) { - + const char *infile; - + if(argc != 3) usage(); - int accountid = atoi(argv[1]); + int accountid = Strings::ToInt(argv[1]); if(accountid == 0) usage(); infile = argv[2]; - + char *query = new char[1024000]; char *cursor; char host[200], user[200], passwd[200], database[200]; int32 port=0; bool compression = false; bool items[6] = {false, false, false, false, false, false}; - + if(!DBcore::ReadDBINI(host, user, passwd, database, port, compression, items)) { exit(1); } - + if (!items[0] || !items[1] || !items[2] || !items[3]) { printf ("Incomplete DB.INI file.\n"); exit (1); } - + MYSQL m; mysql_init(&m); - + if(!mysql_real_connect(&m, host, user, passwd, database, 0, NULL, 0)) { printf("Unable to connect 1: %s.\n", mysql_error(&m)); return(1); } - + CharHeader header; char *ppbuffer; char *eppbuffer; @@ -58,25 +58,25 @@ int main(int argc, char *argv[]) { InventoryEntry *inventory; InventoryEntry *sharedbank; QuestGlobalEntry *qglobals; - + FILE *inf = fopen(infile, "rb"); if(inf == NULL) { printf("Unable to open infile %s\n", infile); return(1); } - + if(fread(&header, sizeof(header), 1, inf) != 1) { printf("Error reading header.\n"); return(1); } - + ppbuffer = new char[header.profile_length]; eppbuffer = new char[header.extprofile_length]; factions = new FactionValueRecord[header.faction_value_count]; inventory = new InventoryEntry[header.inventory_count]; sharedbank = new InventoryEntry[header.sharedbank_count]; qglobals = new QuestGlobalEntry[header.quest_globals_count]; - + //read all the shit in if(fread(ppbuffer, header.profile_length, 1, inf) != 1) { printf("Error reading pp.\n"); @@ -102,9 +102,9 @@ int main(int argc, char *argv[]) { printf("Error reading quest globals.\n"); return(1); } - + fclose(inf); - + cursor = query; cursor += sprintf(cursor, "INSERT INTO character_ " "(account_id,name,profile,extprofile,x,y,z,zonename,zoneid)" @@ -119,7 +119,7 @@ int main(int argc, char *argv[]) { } int charid = mysql_insert_id(&m); uint32 r; - + //faction for(r = 0; r < header.faction_value_count; r++) { sprintf(query, "INSERT INTO faction_values (char_id,faction_id,current_value)" @@ -129,13 +129,13 @@ int main(int argc, char *argv[]) { return(1); } } - + //inventory for(r = 0; r < header.inventory_count; r++) { sprintf(query, "INSERT INTO inventory (charid,slotid,itemid,charges,color,augslot1,augslot2,augslot3,augslot4,augslot5,instnodrop)" " VALUES(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)", charid, inventory[r].slotid, inventory[r].itemid, inventory[r].charges, inventory[r].colors, - inventory[r].augs[0], inventory[r].augs[1], inventory[r].augs[2], inventory[r].augs[3], + inventory[r].augs[0], inventory[r].augs[1], inventory[r].augs[2], inventory[r].augs[3], inventory[r].augs[4], inventory[r].instnodrop ); if(mysql_query(&m, query) != 0) { @@ -143,7 +143,7 @@ int main(int argc, char *argv[]) { return(1); } } - + //shared bank //this is far from perfect since this is per-account, works great with empty shard bank... for(r = 0; r < header.sharedbank_count; r++) { @@ -158,7 +158,7 @@ int main(int argc, char *argv[]) { // return(1); } } - + //quest globals for(r = 0; r < header.quest_globals_count; r++) { cursor = query; @@ -168,17 +168,17 @@ int main(int argc, char *argv[]) { cursor += sprintf(cursor, "','"); cursor += mysql_real_escape_string(&m, cursor, (const char *) qglobals[r].value, strlen(qglobals[r].value)); sprintf(cursor, "',%d)", qglobals[r].expdate); - + if(mysql_query(&m, query) != 0) { printf("Unable to insert quest global: %s\n", mysql_error(&m)); return(1); } } - + mysql_close(&m); - + printf("Successfully imported %s as character id %d\n", header.name, charid); - + return(0); } diff --git a/utils/deprecated/perlxs/EQDB.h b/utils/deprecated/perlxs/EQDB.h deleted file mode 100644 index 73375705f..000000000 --- a/utils/deprecated/perlxs/EQDB.h +++ /dev/null @@ -1,9 +0,0 @@ - //NOTE: you must have a space after the * of a return value - - unsigned int field_count(); - unsigned long affected_rows(); - unsigned long insert_id(); - unsigned int get_errno(); - Const_char * error(); - EQDBRes * query(Const_char *q); - Const_char * escape_string(Const_char *from); //NOT THREAD SAFE! (m_escapeBuffer) diff --git a/utils/deprecated/perlxs/EQDB.h.xs b/utils/deprecated/perlxs/EQDB.h.xs deleted file mode 100644 index fb1b3af33..000000000 --- a/utils/deprecated/perlxs/EQDB.h.xs +++ /dev/null @@ -1,37 +0,0 @@ - -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -typedef const char Const_char; - -#ifdef EMBPERL -#include "../common/debug.h" -#include "../common/useperl.h" -#include "EQDB.h" - -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - - -MODULE = EQDB PACKAGE = EQDB - -PROTOTYPES: ENABLE - - - diff --git a/utils/deprecated/perlxs/EQDBRes.h b/utils/deprecated/perlxs/EQDBRes.h deleted file mode 100644 index 67a5554ee..000000000 --- a/utils/deprecated/perlxs/EQDBRes.h +++ /dev/null @@ -1,7 +0,0 @@ - unsigned long num_rows() { return (res) ? mysql_num_rows(res) : 0; } - unsigned long num_fields() { return (res) ? mysql_num_fields(res) : 0; } - void DESTROY() { } - void finish() { if (res) mysql_free_result(res); res=NULL; }; - vector fetch_row_array(); - map fetch_row_hash(); - unsigned long * fetch_lengths() { return (res) ? mysql_fetch_lengths(res) : 0; } diff --git a/utils/deprecated/perlxs/EQDBRes.h.xs b/utils/deprecated/perlxs/EQDBRes.h.xs deleted file mode 100644 index 8b50e1f8b..000000000 --- a/utils/deprecated/perlxs/EQDBRes.h.xs +++ /dev/null @@ -1,33 +0,0 @@ - -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -typedef const char Const_char; - -#ifdef EMBPERL -#include "../common/debug.h" -#include "../common/useperl.h" -#include "EQDBRes.h" - - -MODULE = EQDBRes PACKAGE = EQDBRes - -PROTOTYPES: ENABLE - - - diff --git a/utils/deprecated/perlxs/EQLConfig.h b/utils/deprecated/perlxs/EQLConfig.h deleted file mode 100644 index b0f352834..000000000 --- a/utils/deprecated/perlxs/EQLConfig.h +++ /dev/null @@ -1,19 +0,0 @@ - Const_char * GetName() const { return(m_name.c_str()); } - int GetStaticCount() const { return(m_zones.size()); } - bool IsConnected() const; //is this launcher connected to world - - void DeleteLauncher(); //kill this launcher and all its zones. - - void RestartZone(Const_char *zone_ref); - void StopZone(Const_char *zone_ref); - void StartZone(Const_char *zone_ref); - - bool BootStaticZone(Const_char *short_name, uint16 port); - bool ChangeStaticZone(Const_char *short_name, uint16 port); - bool DeleteStaticZone(Const_char *short_name); - - bool SetDynamicCount(int count); - int GetDynamicCount() const; - - vector ListZones(); //returns an array of zone refs - map GetZoneDetails(Const_char *zone_ref); diff --git a/utils/deprecated/perlxs/EQLConfig.h.xs b/utils/deprecated/perlxs/EQLConfig.h.xs deleted file mode 100644 index 7d5c4d797..000000000 --- a/utils/deprecated/perlxs/EQLConfig.h.xs +++ /dev/null @@ -1,37 +0,0 @@ - -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -typedef const char Const_char; - -#ifdef EMBPERL -#include "../common/debug.h" -#include "EQWParser.h" -#include "EQLConfig.h" - -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - - -MODULE = EQLConfig PACKAGE = EQLConfig - -PROTOTYPES: ENABLE - - - diff --git a/utils/deprecated/perlxs/EQW.h b/utils/deprecated/perlxs/EQW.h deleted file mode 100644 index e1dc00b8d..000000000 --- a/utils/deprecated/perlxs/EQW.h +++ /dev/null @@ -1,36 +0,0 @@ - //NOTE: you must have a space after the * of a return value - Const_char * GetConfig(Const_char *var_name); - void LockWorld(); - void UnlockWorld(); - - bool LSConnected(); - void LSReconnect(); - - int CountZones(); - vector ListBootedZones(); //returns an array of zone_refs (opaque) - map GetZoneDetails(Const_char *zone_ref); //returns a hash ref of details - - int CountPlayers(); - vector ListPlayers(Const_char *zone_name = ""); //returns an array of player refs (opaque) - map GetPlayerDetails(Const_char *player_ref); //returns a hash ref of details - - int CountLaunchers(bool active_only); -// vector ListActiveLaunchers(); //returns an array of launcher names - vector ListLaunchers(); //returns an array of launcher names - EQLConfig * GetLauncher(Const_char *launcher_name); //returns the EQLConfig object for the specified launcher. - void CreateLauncher(Const_char *launcher_name, int dynamic_count); -// EQLConfig * FindLauncher(Const_char *zone_ref); - - //Guild routines, mostly wrappers around guild_mgr - int32 CreateGuild(const char* name, int32 leader_char_id); - bool DeleteGuild(int32 guild_id); - bool RenameGuild(int32 guild_id, const char* name); - bool SetGuildMOTD(int32 guild_id, const char* motd, const char *setter); - bool SetGuildLeader(int32 guild_id, int32 leader_char_id); - bool SetGuild(int32 charid, int32 guild_id, int8 rank); - bool SetGuildRank(int32 charid, int8 rank); - bool SetBankerFlag(int32 charid, bool is_banker); - bool SetTributeFlag(int32 charid, bool enabled); - bool SetPublicNote(int32 charid, const char *note); - - diff --git a/utils/deprecated/perlxs/EQW.h.xs b/utils/deprecated/perlxs/EQW.h.xs deleted file mode 100644 index af40c9abd..000000000 --- a/utils/deprecated/perlxs/EQW.h.xs +++ /dev/null @@ -1,37 +0,0 @@ - -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -typedef const char Const_char; - -#ifdef EMBPERL -#include "../common/debug.h" -#include "EQWParser.h" -#include "EQW.h" - -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - - -MODULE = EQW PACKAGE = EQW - -PROTOTYPES: ENABLE - - - diff --git a/utils/deprecated/perlxs/HTTPRequest.h b/utils/deprecated/perlxs/HTTPRequest.h deleted file mode 100644 index 4a4bdd38a..000000000 --- a/utils/deprecated/perlxs/HTTPRequest.h +++ /dev/null @@ -1,14 +0,0 @@ - - - Const_char * get(Const_char *name, Const_char *default_value = "") const; - int getInt(Const_char *name, int default_value = 0) const; - float getFloat(Const_char *name, float default_value = 0.0) const; - - //returns a database-safe string - Const_char * getEscaped(Const_char *name, Const_char *default_value = "") const; - - map get_all() const; - - void redirect(Const_char *URL); - void SetResponseCode(Const_char *code); - void header(Const_char *name, Const_char *value); diff --git a/utils/deprecated/perlxs/HTTPRequest.h.xs b/utils/deprecated/perlxs/HTTPRequest.h.xs deleted file mode 100644 index 1ce1a26b9..000000000 --- a/utils/deprecated/perlxs/HTTPRequest.h.xs +++ /dev/null @@ -1,37 +0,0 @@ - -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -typedef const char Const_char; - -#ifdef EMBPERL -#include "../common/debug.h" -#include "EQWParser.h" -#include "HTTPRequest.h" - -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - - -MODULE = HTTPRequest PACKAGE = HTTPRequest - -PROTOTYPES: ENABLE - - - diff --git a/utils/deprecated/perlxs/PlayerCorpse.h b/utils/deprecated/perlxs/PlayerCorpse.h deleted file mode 100644 index e20c1ae71..000000000 --- a/utils/deprecated/perlxs/PlayerCorpse.h +++ /dev/null @@ -1,28 +0,0 @@ - int32 GetCharID() { return charid; } - int32 GetDecayTime() { if (!corpse_decay_timer.Enabled()) return 0xFFFFFFFF; else return corpse_decay_timer.GetRemainingTime(); } - inline void Lock() { pLocked = true; } - inline void UnLock() { pLocked = false; } - inline bool IsLocked() { return pLocked; } - inline void ResetLooter() { BeingLootedBy = 0xFFFFFFFF; } - inline int32 GetDBID() { return dbid; } - inline char* GetOwnerName() { return orgname;} - void SetDecayTimer(int32 decaytime); - bool IsEmpty(); - void AddItem(uint32 itemnum, int8 charges, sint16 slot = 0); - uint32 GetWornItem(sint16 equipSlot) const; - void RemoveItem(int16 lootslot); - void SetCash(int16 in_copper, int16 in_silver, int16 in_gold, int16 in_platinum); - void RemoveCash(); - int32 CountItems(); - void Delete(); - uint32 GetCopper() { return copper; } - uint32 GetSilver() { return silver; } - uint32 GetGold() { return gold; } - uint32 GetPlatinum() { return platinum; } - void Summon(Client* client, bool spell); - void CastRezz(int16 spellid, Mob* Caster); - void CompleteRezz(); - bool CanMobLoot(int charid); - void AllowMobLoot(Mob *them, int8 slot); - void AddLooter(Mob *who); - bool IsRezzed() { return isrezzed; } diff --git a/utils/deprecated/perlxs/PlayerCorpse.h.xs b/utils/deprecated/perlxs/PlayerCorpse.h.xs deleted file mode 100644 index d25570ff9..000000000 --- a/utils/deprecated/perlxs/PlayerCorpse.h.xs +++ /dev/null @@ -1,37 +0,0 @@ - -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "features.h" -#ifdef EMBPERL_XS_CLASSES -#include "../common/debug.h" -#include "embperl.h" - -#include "PlayerCorpse.h" - -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - - -MODULE = Corpse PACKAGE = Corpse - -PROTOTYPES: ENABLE - - - diff --git a/utils/deprecated/perlxs/all_convert b/utils/deprecated/perlxs/all_convert deleted file mode 100644 index 64c4191e8..000000000 --- a/utils/deprecated/perlxs/all_convert +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/sh - -if [ ! -h ./miniperl ]; then - echo "You must have a link in this dir to perl named ./miniperl" - exit 1 -fi - -./convert client.h Client -./convert entity.h EntityList -./convert mob.h Mob -./convert npc.h NPC -./convert PlayerCorpse.h Corpse -./convert groups.h Group -./convert perlpacket.h PerlPacket -./export ../../world/EQW.h EQW.h -./convert EQW.h EQW -./export ../../common/EQDB.h EQDB.h -./convert EQDB.h EQDB -./export ../../common/EQDBRes.h EQDBRes.h -./convert EQDBRes.h EQDBRes -./export ../../world/HTTPRequest.h HTTPRequest.h -./convert HTTPRequest.h HTTPRequest -./export ../../world/EQLConfig.h EQLConfig.h -./convert EQLConfig.h EQLConfig - -echo "Putting files in place..." -./put diff --git a/utils/deprecated/perlxs/class.sh b/utils/deprecated/perlxs/class.sh deleted file mode 100644 index 917851fcf..000000000 --- a/utils/deprecated/perlxs/class.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -xsubpp -typemap class.typemap class.xs diff --git a/utils/deprecated/perlxs/class.typemap b/utils/deprecated/perlxs/class.typemap deleted file mode 100644 index bc475e8ed..000000000 --- a/utils/deprecated/perlxs/class.typemap +++ /dev/null @@ -1,442 +0,0 @@ -#our object types -EQLConfig * T_PTROBJ -EQDB * T_PTROBJ -EQDBRes * T_PTROBJ -Client * T_PTROBJ -NPC * T_PTROBJ -Mob * T_PTROBJ -Group * T_PTROBJ -Corpse * T_PTROBJ -EntityList * T_PTROBJ -PerlPacket * T_PTROBJ -EQW * T_PTROBJ -HTTPRequest * T_PTROBJ -Const_char * T_PV - -#some nice c++ types -vector T_STRINGARRAY -map T_STRINGMAP - -#our int types -FACTION_VALUE T_IV -EmuAppearance T_UV -SkillType T_UV -Mob::eStandingPetOrder T_IV -int32 T_UV -int16 T_UV -int8 T_UV -uint32 T_UV -uint16 T_UV -uint8 T_UV -sint32 T_IV -sint16 T_IV -sint8 T_IV - -int * T_INTARRAY -unsigned long * T_INTARRAY - -# basic C types -int T_IV -unsigned T_UV -unsigned int T_UV -long T_IV -unsigned long T_UV -unsigned long long T_UV -short T_IV -unsigned short T_UV -char T_CHAR -unsigned char T_U_CHAR -char * T_PV -unsigned char * T_PV -const char * T_PV -caddr_t T_PV -wchar_t * T_PV -wchar_t T_IV -# bool_t is defined in -bool_t T_IV -size_t T_UV -ssize_t T_IV -time_t T_NV -unsigned long * T_OPAQUEPTR -char ** T_PACKEDARRAY -void * T_PTR -Time_t * T_PV -SV * T_SV -SVREF T_SVREF -AV * T_AVREF -HV * T_HVREF -CV * T_CVREF - -IV T_IV -UV T_UV -NV T_NV -I32 T_IV -I16 T_IV -I8 T_IV -STRLEN T_UV -U32 T_U_LONG -U16 T_U_SHORT -U8 T_UV -Result T_U_CHAR -Boolean T_BOOL -float T_FLOAT -double T_DOUBLE -SysRet T_SYSRET -SysRetLong T_SYSRET -FILE * T_STDIO -PerlIO * T_INOUT -FileHandle T_PTROBJ -InputStream T_IN -InOutStream T_INOUT -OutputStream T_OUT -bool T_BOOL - -############################################################################# -INPUT -T_SV - $var = $arg -T_SVREF - if (SvROK($arg)) - $var = (SV*)SvRV($arg); - else - Perl_croak(aTHX_ \"$var is not a reference\"); -T_AVREF - if (SvROK($arg) && SvTYPE(SvRV($arg))==SVt_PVAV) - $var = (AV*)SvRV($arg); - else - Perl_croak(aTHX_ \"$var is not an array reference\"); -T_HVREF - if (SvROK($arg) && SvTYPE(SvRV($arg))==SVt_PVHV) - $var = (HV*)SvRV($arg); - else - Perl_croak(aTHX_ \"$var is not a hash reference\"); -T_CVREF - if (SvROK($arg) && SvTYPE(SvRV($arg))==SVt_PVCV) - $var = (CV*)SvRV($arg); - else - Perl_croak(aTHX_ \"$var is not a code reference\"); -T_SYSRET - $var NOT IMPLEMENTED -T_UV - $var = ($type)SvUV($arg) -T_IV - $var = ($type)SvIV($arg) -T_INT - $var = (int)SvIV($arg) -T_ENUM - $var = ($type)SvIV($arg) -T_BOOL - $var = (bool)SvTRUE($arg) -T_U_INT - $var = (unsigned int)SvUV($arg) -T_SHORT - $var = (short)SvIV($arg) -T_U_SHORT - $var = (unsigned short)SvUV($arg) -T_LONG - $var = (long)SvIV($arg) -T_U_LONG - $var = (unsigned long)SvUV($arg) -T_CHAR - $var = (char)*SvPV_nolen($arg) -T_U_CHAR - $var = (unsigned char)SvUV($arg) -T_FLOAT - $var = (float)SvNV($arg) -T_NV - $var = ($type)SvNV($arg) -T_DOUBLE - $var = (double)SvNV($arg) -T_PV - $var = ($type)SvPV_nolen($arg) -T_PTR - $var = INT2PTR($type,SvIV($arg)) -T_PTRREF - if (SvROK($arg)) { - IV tmp = SvIV((SV*)SvRV($arg)); - $var = INT2PTR($type,tmp); - } - else - Perl_croak(aTHX_ \"$var is not a reference\"); - if($var == NULL) - Perl_croak(aTHX_ \"$var is NULL, avoiding crash.\"); -T_REF_IV_REF - if (sv_isa($arg, \"${ntype}\")) { - IV tmp = SvIV((SV*)SvRV($arg)); - $var = *INT2PTR($type *, tmp); - } - else - Perl_croak(aTHX_ \"$var is not of type ${ntype}\"); -T_REF_IV_PTR - if (sv_isa($arg, \"${ntype}\")) { - IV tmp = SvIV((SV*)SvRV($arg)); - $var = INT2PTR($type, tmp); - } - else - Perl_croak(aTHX_ \"$var is not of type ${ntype}\"); - if($var == NULL) - Perl_croak(aTHX_ \"$var is NULL, avoiding crash.\"); -T_PTROBJ - if (sv_derived_from($arg, \"${ntype}\")) { - IV tmp = SvIV((SV*)SvRV($arg)); - $var = INT2PTR($type,tmp); - } - else - Perl_croak(aTHX_ \"$var is not of type ${ntype}\"); - if($var == NULL) - Perl_croak(aTHX_ \"$var is NULL, avoiding crash.\"); -T_PTRDESC - if (sv_isa($arg, \"${ntype}\")) { - IV tmp = SvIV((SV*)SvRV($arg)); - ${type}_desc = (\U${type}_DESC\E*) tmp; - $var = ${type}_desc->ptr; - } - else - Perl_croak(aTHX_ \"$var is not of type ${ntype}\"); - if($var == NULL) - Perl_croak(aTHX_ \"$var is NULL, avoiding crash.\"); -T_REFREF - if (SvROK($arg)) { - IV tmp = SvIV((SV*)SvRV($arg)); - $var = *INT2PTR($type,tmp); - } - else - Perl_croak(aTHX_ \"$var is not a reference\"); - if($var == NULL) - Perl_croak(aTHX_ \"$var is NULL, avoiding crash.\"); -T_REFOBJ - if (sv_isa($arg, \"${ntype}\")) { - IV tmp = SvIV((SV*)SvRV($arg)); - $var = *INT2PTR($type,tmp); - } - else - Perl_croak(aTHX_ \"$var is not of type ${ntype}\"); - if($var == NULL) - Perl_croak(aTHX_ \"$var is NULL, avoiding crash.\"); -T_OPAQUE - $var = *($type *)SvPV_nolen($arg) -T_OPAQUEPTR - $var = ($type)SvPV_nolen($arg) -T_PACKED - $var = XS_unpack_$ntype($arg) -T_PACKEDARRAY - $var = XS_unpack_$ntype($arg) -T_CALLBACK - $var = make_perl_cb_$type($arg) -T_ARRAY - U32 ix_$var = $argoff; - $var = $ntype(items -= $argoff); - while (items--) { - DO_ARRAY_ELEM; - ix_$var++; - } - /* this is the number of elements in the array */ - ix_$var -= $argoff -T_INTARRAY - AV *av_$var; - if (SvROK($arg) && SvTYPE(SvRV($arg))==SVt_PVAV) - av_$var = (AV*)SvRV($arg); - else - Perl_croak(aTHX_ \"$var is not an array reference\"); - I32 len_$var = av_len(av_$var) + 1; - I32 ix_$var; - $var = new $ntype\[len_$var\]; - for(ix_$var = 0; ix_$var < len_$var; ix_$var ++) { - SV **tmp = av_fetch(av_$var, ix_$var, 0); - if(tmp == NULL || *tmp == NULL) { - $var\[ix_$var\] = 0; - continue; - } - $var\[ix_$var\] = ($ntype)SvIV(*tmp); - } -T_STDIO - $var = PerlIO_findFILE(IoIFP(sv_2io($arg))) -T_IN - $var = IoIFP(sv_2io($arg)) -T_INOUT - $var = IoIFP(sv_2io($arg)) -T_OUT - $var = IoOFP(sv_2io($arg)) -T_STRINGARRAY - $var NOT IMPLEMENTED -T_STRINGMAP - $var NOT IMPLEMENTED - - -############################################################################# -OUTPUT -T_SV - $arg = $var; -T_SVREF - $arg = newRV((SV*)$var); -T_AVREF - $arg = newRV((SV*)$var); -T_HVREF - $arg = newRV((SV*)$var); -T_CVREF - $arg = newRV((SV*)$var); -T_IV - sv_setiv($arg, (IV)$var); -T_UV - sv_setuv($arg, (UV)$var); -T_INT - sv_setiv($arg, (IV)$var); -T_SYSRET - if ($var != -1) { - if ($var == 0) - sv_setpvn($arg, "0 but true", 10); - else - sv_setiv($arg, (IV)$var); - } -T_ENUM - sv_setiv($arg, (IV)$var); -T_BOOL - $arg = boolSV($var); -T_U_INT - sv_setuv($arg, (UV)$var); -T_SHORT - sv_setiv($arg, (IV)$var); -T_U_SHORT - sv_setuv($arg, (UV)$var); -T_LONG - sv_setiv($arg, (IV)$var); -T_U_LONG - sv_setuv($arg, (UV)$var); -T_CHAR - sv_setpvn($arg, (char *)&$var, 1); -T_U_CHAR - sv_setuv($arg, (UV)$var); -T_FLOAT - sv_setnv($arg, (double)$var); -T_NV - sv_setnv($arg, (NV)$var); -T_DOUBLE - sv_setnv($arg, (double)$var); -T_PV - sv_setpv((SV*)$arg, $var); -T_PTR - sv_setiv($arg, PTR2IV($var)); -T_PTRREF - sv_setref_pv($arg, Nullch, (void*)$var); -T_REF_IV_REF - sv_setref_pv($arg, \"${ntype}\", (void*)new $ntype($var)); -T_REF_IV_PTR - sv_setref_pv($arg, \"${ntype}\", (void*)$var); -T_PTROBJ - sv_setref_pv($arg, \"${ntype}\", (void*)$var); -T_PTRDESC - sv_setref_pv($arg, \"${ntype}\", (void*)new\U${type}_DESC\E($var)); -T_REFREF - NOT_IMPLEMENTED -T_REFOBJ - NOT IMPLEMENTED -T_OPAQUE - sv_setpvn($arg, (char *)&$var, sizeof($var)); -T_OPAQUEPTR - sv_setpvn($arg, (char *)$var, sizeof(*$var)); -T_PACKED - XS_pack_$ntype($arg, $var); -T_PACKEDARRAY - XS_pack_$ntype($arg, $var, count_$ntype); -T_DATAUNIT - sv_setpvn($arg, $var.chp(), $var.size()); -T_CALLBACK - sv_setpvn($arg, $var.context.value().chp(), - $var.context.value().size()); -T_ARRAY - { - U32 ix_$var; - EXTEND(SP,size_$var); - for (ix_$var = 0; ix_$var < size_$var; ix_$var++) { - ST(ix_$var) = sv_newmortal(); - DO_ARRAY_ELEM - } - } -T_STDIO - { - GV *gv = newGVgen("$Package"); - PerlIO *fp = PerlIO_importFILE($var,0); - if ( fp && do_open(gv, "+<&", 3, FALSE, 0, 0, fp) ) - sv_setsv($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1))); - else - $arg = &PL_sv_undef; - } -T_IN - { - GV *gv = newGVgen("$Package"); - if ( do_open(gv, "<&", 2, FALSE, 0, 0, $var) ) - sv_setsv($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1))); - else - $arg = &PL_sv_undef; - } -T_INOUT - { - GV *gv = newGVgen("$Package"); - if ( do_open(gv, "+<&", 3, FALSE, 0, 0, $var) ) - sv_setsv($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1))); - else - $arg = &PL_sv_undef; - } -T_OUT - { - GV *gv = newGVgen("$Package"); - if ( do_open(gv, "+>&", 3, FALSE, 0, 0, $var) ) - sv_setsv($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1))); - else - $arg = &PL_sv_undef; - } -T_STRINGARRAY - { - U32 ix_$var; - /* pop crap off the stack we dont really want */ - POPs; - POPs; - /* grow the stack to the number of elements being returned */ - EXTEND(SP, $var.size()); - for (ix_$var = 0; ix_$var < $var.size(); ix_$var++) { - const string &it = $var\[ix_$var\]; - ST(ix_$var) = sv_newmortal(); - sv_setpvn(ST(ix_$var), it.c_str(), it.length()); - } - /* hackish, but im over it. The normal xsubpp return will be right below this */ - XSRETURN($var.size()); - } -T_STRINGMAP - if (RETVAL.begin()!=RETVAL.end()) - { - //NOTE: we are leaking the original $arg right now - HV *hv = newHV(); - sv_2mortal((SV*)hv); - $arg = newRV((SV*)hv); - - map::const_iterator cur, end; - cur = $var.begin(); - end = $var.end(); - for(; cur != end; cur++) { - /* get the element from the hash, creating if needed (will be needed) */ - SV**ele = hv_fetch(hv, cur->first.c_str(), cur->first.length(), TRUE); - if(ele == NULL) { - Perl_croak(aTHX_ \"Unable to create a hash element for $var\"); - break; - } - /* put our string in the SV associated with this element in the hash */ - sv_setpvn(*ele, cur->second.c_str(), cur->second.length()); - } - } - - - - - - - - - - - - - - - - - diff --git a/utils/deprecated/perlxs/client.h b/utils/deprecated/perlxs/client.h deleted file mode 100644 index 6c12e88a3..000000000 --- a/utils/deprecated/perlxs/client.h +++ /dev/null @@ -1,177 +0,0 @@ - -//BEGIN CLIENT METHODS - - void SendSound(); - bool Save(int8 iCommitNow); - void SaveBackup(); - - inline bool Connected(); - inline bool InZone(); - inline void Kick(); - inline void Disconnect(); - inline bool IsLD(); - void WorldKick(); - inline int8 GetAnon(); - void Duck(); - void Stand(); - - void SetGM(bool toggle); - void SetPVP(bool toggle); - inline bool GetPVP(); - inline bool GetGM(); - - inline void SetBaseClass(uint32 i); - inline void SetBaseRace(uint32 i); - inline void SetBaseGender(uint32 i); - - inline int8 GetBaseFace(); - - inline int8 GetLanguageSkill(int16 n); - inline Const_char * GetLastName(); - inline int32 GetLDoNPoints(); - - - inline int8 GetBaseSTR(); - inline int8 GetBaseSTA(); - inline int8 GetBaseCHA(); - inline int8 GetBaseDEX(); - inline int8 GetBaseINT(); - inline int8 GetBaseAGI(); - inline int8 GetBaseWIS(); - - int16 GetWeight(); - inline uint32 GetEXP(); - bool UpdateLDoNPoints(sint32 points, int32 theme); - inline void SetDeity(uint32 i); - - void AddEXP(uint32 add_exp, int8 conlevel = 0xFF, bool resexp = false); - void SetEXP(uint32 set_exp, uint32 set_aaxp, bool resexp=false); - - void SetBindPoint(int to_zone = -1, float new_x = 0.0f, float new_y = 0.0f, float new_z = 0.0f); - void MovePC(int32 zoneID, float x, float y, float z, float heading); - void ChangeLastName(const char* in_lastname); - - FACTION_VALUE GetFactionLevel(int32 char_id, int32 npc_id, int32 p_race, int32 p_class, int32 p_deity, sint32 pFaction, Mob* tnpc); - - void SetFactionLevel(int32 char_id, int32 npc_id, int8 char_class, int8 char_race, int8 char_deity); - void SetFactionLevel2(int32 char_id, sint32 faction_id, int8 char_class, int8 char_race, int8 char_deity, sint32 value); - sint16 GetRawItemAC(); - - inline int32 AccountID(); - inline Const_char * AccountName(); - inline sint16 Admin(); - inline int32 CharacterID(); - void UpdateAdmin(bool iFromDB = true); - void UpdateWho(int8 remove = 0); - - inline int8 GuildRank(); - inline int32 GuildID(); - - int8 GetFace(); - - bool TakeMoneyFromPP(uint32 copper); - void AddMoneyToPP(uint32 copper, uint32 silver, uint32 gold,uint32 platinum,bool updateclient); - - bool TGB() {return tgb;} - - int16 GetSkillPoints() {return m_pp.points;} - void SetSkillPoints(int inp) {m_pp.points = inp;} - - void IncreaseSkill(int skill_id, int value = 1) { if (skill_id <= HIGHEST_SKILL) { m_pp.skills[skill_id] += value; } } - void IncreaseLanguageSkill(int skill_id, int value = 1) { if (skill_id < 26) { m_pp.languages[skill_id] += value; } } - virtual uint16 GetSkill(SkillType skill_id) const { if (skill_id <= HIGHEST_SKILL) { return((itembonuses.skillmod[skill_id] > 0)? m_pp.skills[skill_id]*(100 + itembonuses.skillmod[skill_id])/100 : m_pp.skills[skill_id]); } return 0; } - uint32 GetRawSkill(SkillType skill_id) const { if (skill_id <= HIGHEST_SKILL) { return(m_pp.skills[skill_id]); } return 0; } - bool HasSkill(SkillType skill_id) const; - bool CanHaveSkill(SkillType skill_id) const; - void SetSkill(SkillType skill_num, int8 value); // socket 12-29-01 - void AddSkill(SkillType skillid, int8 value); - void CheckSpecializeIncrease(int16 spell_id); - bool CheckIncreaseSkill(SkillType skillid, int chancemodi = 0); - void SetLanguageSkill(int langid, int value); - int8 MaxSkill(SkillType skillid); - - void GMKill(); - inline bool IsMedding(); - inline int16 GetDuelTarget(); - inline bool IsDueling(); - inline void SetDuelTarget(int16 set_id); - inline void SetDueling(bool duel); - - void ResetAA(); - - void MemSpell(int16 spell_id, int slot, bool update_client = true); - void UnmemSpell(int slot, bool update_client = true); - void UnmemSpellAll(bool update_client = true); - void ScribeSpell(int16 spell_id, int slot, bool update_client = true); - void UnscribeSpell(int slot, bool update_client = true); - void UnscribeSpellAll(bool update_client = true); - - inline bool IsSitting(); - inline bool IsBecomeNPC(); - inline int8 GetBecomeNPCLevel(); - inline void SetBecomeNPC(bool flag); - inline void SetBecomeNPCLevel(int8 level); - bool LootToStack(uint32 itemid); - void SetFeigned(bool in_feigned); - inline bool GetFeigned(); - - inline bool AutoSplitEnabled(); - - void SetHorseId(int16 horseid_in); - int16 GetHorseId(); - - uint32 NukeItem(uint32 itemnum); - void SetTint(sint16 slot_id, uint32 color); - void SetMaterial(sint16 slot_id, uint32 item_id); - void Undye(); - uint32 GetItemIDAt(sint16 slot_id); - void DeleteItemInInventory(sint16 slot_id, sint8 quantity = 0, bool client_update = false); - void SummonItem(uint32 item_id, sint8 charges = 0); - void SetStats(int8 type,sint16 increase_val); - void IncStats(int8 type,sint16 increase_val); - void DropItem(sint16 slot_id); - - void BreakInvis(); - Group* GetGroup(); - void LeaveGroup(); - - bool Hungry(); - bool Thirsty(); - int16 GetInstrumentMod(int16 spell_id); - bool DecreaseByID(int32 type, int8 amt); - int8 SlotConvert2(int8 slot); - void Escape(); - void RemoveNoRent(); - void RangedAttack(Mob* other); - void ThrowingAttack(Mob* other); - void GoFish(); - void ForageItem(); - float CalcPriceMod(Mob* other = 0, bool reverse = false); - void ResetTrade(); - bool UseDiscipline(int32 spell_id, int32 target); - sint32 GetCharacterFactionLevel(sint32 faction_id); - - - void SetZoneFlag(uint32 zone_id); - void ClearZoneFlag(uint32 zone_id); - bool HasZoneFlag(uint32 zone_id) const; - void SendZoneFlagInfo(Client *to) const; - void LoadZoneFlags(); - void SetAATitle(const char *txt); - -//TODO: inventory and ptimers interfaces -//I think there are two GetAA methods in client - - - - - - - - - - - - - - diff --git a/utils/deprecated/perlxs/client.h.xs b/utils/deprecated/perlxs/client.h.xs deleted file mode 100644 index ede992bd5..000000000 --- a/utils/deprecated/perlxs/client.h.xs +++ /dev/null @@ -1,36 +0,0 @@ - -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "features.h" -#ifdef EMBPERL_XS_CLASSES -#include "../common/debug.h" -#include "embperl.h" - -#include "client.h" - -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - -MODULE = Client PACKAGE = Client - -PROTOTYPES: ENABLE - - - diff --git a/utils/deprecated/perlxs/convert b/utils/deprecated/perlxs/convert deleted file mode 100644 index 20aaf845c..000000000 --- a/utils/deprecated/perlxs/convert +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/sh - -if [ ! -r "$1" -o -z "$2" ]; then - echo "Usage: $0 headerfile classname" -fi - -name=`basename "$1" .h` -name="perl_${name}" - -echo "Starting conversion of $2" >&2 - -{ -cat "$1.xs" - -cat "$1" \ -| sed -e 's/inline//g' -e 's/const//g' -e 's/virtual//g' \ --e 's/{.*}/;/g' -e 's#//.*$##g' \ --e 's/(void)/()/g' \ -| tr -d '[&;]' \ -| perl -p -e "s/^\\s+(.+)[ \\t]([a-zA-Z0-9_]*)\\(/&\$1&$2::\$2(/g" \ -| tr '&' '\n' - -} > tmp - -{ - -xsubpp -typemap class.typemap tmp \ -| sed -e "s/\"$2::/\"/g" \ - -e 's/("\([a-zA-Z0-9_]*\)"/(strcpy(buf, "\1")/g' \ - -e 's/ / /g' -e 's/ / /g' \ - -e 's#char\* file = __FILE__;#char file[256];^ strncpy(file, __FILE__, 256);^ file[255] = '\0';^ ^ if(items != 1)^ fprintf(stderr, "boot_quest does not take any arguments.");^ char buf[128];^^ //add the strcpy stuff to get rid of const warnings....^^#g' \ - -e 's/Ptr//g' \ - -e 's/Mob__e/Mob::e/g' \ -| tr '^' '\n' \ -| grep -v "^#line" - -echo "#endif //EMBPERL_XS_CLASSES" -echo -} > "$name.cpp" - - -#rm -f tmp - - diff --git a/utils/deprecated/perlxs/entity.h b/utils/deprecated/perlxs/entity.h deleted file mode 100644 index 3a8f20c44..000000000 --- a/utils/deprecated/perlxs/entity.h +++ /dev/null @@ -1,62 +0,0 @@ - - Mob* GetMobID(int16 id); - Mob* GetMob(const char* name); - Mob* GetMobByNpcTypeID(int32 get_id); - Client* GetClientByName(const char *name); - Client* GetClientByAccID(int32 accid); - Client* GetClientByID(int16 id); - Client* GetClientByCharID(int32 iCharID); - Client* GetClientByWID(int32 iWID); - Group* GetGroupByMob(Mob* mob); - Group* GetGroupByClient(Client* client); - Group* GetGroupByID(int32 id); - Group* GetGroupByLeaderName(char* leader); - Corpse* GetCorpseByOwner(Client* client); - Corpse* GetCorpseByID(int16 id); - Corpse* GetCorpseByName(char* name); - void ClearClientPetitionQueue(); - bool CanAddHateForMob(Mob *p); - - void Clear(); - bool RemoveMob(int16 delete_id); - bool RemoveClient(int16 delete_id); - bool RemoveNPC(int16 delete_id); - bool RemoveGroup(int32 delete_id); - bool RemoveCorpse(int16 delete_id); - bool RemoveDoor(int16 delete_id); - bool RemoveTrap(int16 delete_id); - bool RemoveObject(int16 delete_id); - void RemoveAllMobs(); - void RemoveAllClients(); - void RemoveAllNPCs(); - void RemoveAllGroups(); - void RemoveAllCorpses(); - void RemoveAllDoors(); - void RemoveAllTraps(); - void RemoveAllObjects(); - - void Message(int32 to_guilddbid, int32 type, const char* message, ...); - void MessageStatus(int32 to_guilddbid, int to_minstatus, int32 type, const char* message, ...); - void MessageClose(Mob* sender, bool skipsender, float dist, int32 type, const char* message, ...); - - void RemoveFromTargets(Mob* mob); - void ReplaceWithTarget(Mob* pOldMob, Mob*pNewTarget); - - void OpenDoorsNear(NPC* opener); - - char* MakeNameUnique(char* name); - static char* RemoveNumbers(char* name); -// signal quest command support - void SignalMobsByNPCID(int32 npc_type, int signal_id); - void RemoveEntity(int16 id); - - sint32 DeleteNPCCorpses(); - sint32 DeletePlayerCorpses(); - void HalveAggro(Mob* who); - void DoubleAggro(Mob* who); - void ClearFeignAggro(Mob* targ); - - bool Fighting(Mob* targ); - void RemoveFromHateLists(Mob* mob, bool settoone = false); - void MessageGroup(Mob* sender, bool skipclose, int32 type, const char* message, ...); - diff --git a/utils/deprecated/perlxs/entity.h.xs b/utils/deprecated/perlxs/entity.h.xs deleted file mode 100644 index 84a85bb97..000000000 --- a/utils/deprecated/perlxs/entity.h.xs +++ /dev/null @@ -1,37 +0,0 @@ - -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "features.h" -#ifdef EMBPERL_XS_CLASSES -#include "../common/debug.h" -#include "embperl.h" - -#include "entity.h" - -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - - -MODULE = EntityList PACKAGE = EntityList - -PROTOTYPES: ENABLE - - - diff --git a/utils/deprecated/perlxs/export b/utils/deprecated/perlxs/export deleted file mode 100644 index 952af2170..000000000 --- a/utils/deprecated/perlxs/export +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh - -FROM="$1" -TO="$2" - -if [ ! -r "$1" -o -z "$2" ]; then - echo "Usage: $0 [src] [dest]" -fi - -grep -A100000 "BEGIN PERL EXPORT" "$FROM" \ -| grep -B 100000 "END PERL EXPORT" \ -| grep -v "PERL EXPORT" >"$TO" diff --git a/utils/deprecated/perlxs/groups.h b/utils/deprecated/perlxs/groups.h deleted file mode 100644 index 99887e1e8..000000000 --- a/utils/deprecated/perlxs/groups.h +++ /dev/null @@ -1,17 +0,0 @@ - void DisbandGroup(); - bool IsGroupMember(Mob* client); - void CastGroupSpell(Mob* caster,uint16 spellid); - void SplitExp(uint32 exp, Mob* other); - void GroupMessage(Mob* sender,const char* message); - int32 GetTotalGroupDamage(Mob* other); - void SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum); - void SetLeader(Mob* newleader){ leader=newleader; }; - Mob* GetLeader(){ return leader; }; - char* GetLeaderName(){ return membername[0]; }; - void SendHPPacketsTo(Mob* newmember); - void SendHPPacketsFrom(Mob* newmember); - bool IsLeader(Mob* leadertest) { return leadertest==leader; }; - int8 GroupCount(); - int32 GetHighestLevel(); - void TeleportGroup(Mob* sender, int32 zoneID, float x, float y, float z, float heading); - inline const int32 GetID() const { return id; } diff --git a/utils/deprecated/perlxs/groups.h.xs b/utils/deprecated/perlxs/groups.h.xs deleted file mode 100644 index c142a764f..000000000 --- a/utils/deprecated/perlxs/groups.h.xs +++ /dev/null @@ -1,37 +0,0 @@ - -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "features.h" -#ifdef EMBPERL_XS_CLASSES -#include "../common/debug.h" -#include "embperl.h" - -#include "groups.h" - -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - - -MODULE = Group PACKAGE = Group - -PROTOTYPES: ENABLE - - - diff --git a/utils/deprecated/perlxs/mob.h b/utils/deprecated/perlxs/mob.h deleted file mode 100644 index 7dc85b2a3..000000000 --- a/utils/deprecated/perlxs/mob.h +++ /dev/null @@ -1,249 +0,0 @@ - -//BEGIN ENTITY METHODS - - virtual bool IsClient() { return false; } - virtual bool IsNPC() { return false; } - virtual bool IsMob() { return false; } - virtual bool IsCorpse() { return false; } - virtual bool IsPlayerCorpse() { return false; } - virtual bool IsNPCCorpse() { return false; } - virtual bool IsObject() { return false; } -// virtual bool IsGroup() { return false; } - virtual bool IsDoor() { return false; } - virtual bool IsTrap() { return false; } - virtual bool IsBeacon() { return false; } - - Client* CastToClient(); - NPC* CastToNPC(); - Mob* CastToMob(); - Corpse* CastToCorpse(); -// Object* CastToObject(); -// Group* CastToGroup(); -// Doors* CastToDoors(); -// Trap* CastToTrap(); -// Beacon* CastToBeacon(); - -//BEGIN MOB METHODS - int16& GetID(); - virtual Const_char * GetName(); - void Depop(bool StartSpawnTimer = true); - - void RogueAssassinate(Mob* other); - bool BehindMob(Mob* other = 0, float playerx = 0.0f, float playery = 0.0f); - void SetLevel(uint8 in_level, bool command = false); - - uint32 GetSkill(SkillType skill_num); - void SendWearChange(int8 material_slot); - sint32 GetEquipment(int8 material_slot); // returns item id - sint32 GetEquipmentMaterial(int8 material_slot); - sint32 GetEquipmentColor(int8 material_slot); - bool IsMoving(); - void GoToBind(); - void Gate(); - bool Attack(Mob* other, int Hand = 13, bool FromRiposte = false) - virtual void Damage(Mob* from, sint32 damage, int16 spell_id, SkillType attack_skill, bool avoidable = true, sint8 buffslot = -1, bool iBuffTic = false) {}; - - void Heal(); - void SetMaxHP(); - int32 GetLevelCon(int8 iOtherLevel); - void SetHP(sint32 hp); - void DoAnim(const int animnum, int type=1); - void ChangeSize(float in_size, bool bNoRestriction = false); - void GMMove(float x, float y, float z, float heading = 0.01); - void SendPosUpdate(int8 iSendToSelf = 0); - void SendPosition(); - bool HasProcs(); - //bool CheckLos(Mob* other); - bool IsInvisible(Mob *other = 0); - void SetInvisible(bool state); - bool FindBuff(int16 spellid); - bool FindType(int8 type, bool bOffensive = false, int16 threshold = 100); - sint8 GetBuffSlotFromType(int8 type); - void MakePet(int16 spell_id, const char* pettype, const char *name=NULL); - virtual inline int16 GetBaseRace(); - virtual inline int8 GetBaseGender(); - virtual inline int8 GetDeity(); - inline const int16& GetRace(); - inline const int8& GetGender(); - inline const int8& GetTexture(); - inline const int8& GetHelmTexture(); - inline const int8& GetClass(); - inline const uint8& GetLevel(); - Const_char * GetCleanName(); - inline Mob* GetTarget(); - virtual inline void SetTarget(Mob* mob); - virtual inline float GetHPRatio(); - - bool IsWarriorClass(); - virtual inline const sint32& GetHP(); - virtual inline const sint32& GetMaxHP(); - virtual float GetWalkspeed(); - virtual float GetRunspeed(); - virtual int GetCasterLevel(int16 spell_id); - virtual inline const sint32& GetMaxMana(); - virtual inline const sint32& GetMana(); - virtual void SetMana(sint32 amount); - virtual inline float GetManaRatio(); - - inline virtual int16 GetAC(); - inline virtual int16 GetATK(); - inline virtual sint16 GetSTR(); - inline virtual sint16 GetSTA(); - inline virtual sint16 GetDEX(); - inline virtual sint16 GetAGI(); - inline virtual sint16 GetINT(); - inline virtual sint16 GetWIS(); - inline virtual sint16 GetCHA(); - inline virtual sint16 GetMR(); - inline virtual sint16 GetFR(); - inline virtual sint16 GetDR(); - inline virtual sint16 GetPR(); - inline virtual sint16 GetCR(); - - inline virtual sint16 GetMaxSTR(); - inline virtual sint16 GetMaxSTA(); - inline virtual sint16 GetMaxDEX(); - inline virtual sint16 GetMaxAGI(); - inline virtual sint16 GetMaxINT(); - inline virtual sint16 GetMaxWIS(); - inline virtual sint16 GetMaxCHA(); - - virtual float GetActSpellRange(int16 spell_id, float range); - virtual sint32 GetActSpellDamage(int16 spell_id, sint32 value); - virtual sint32 GetActSpellHealing(int16 spell_id, sint32 value); - virtual sint32 GetActSpellCost(int16 spell_id, sint32 cost); - virtual sint32 GetActSpellDuration(int16 spell_id, sint32 duration); - virtual sint32 GetActSpellCasttime(int16 spell_id, sint32 casttime); - double ResistSpell(uint8 ressit_type, int16 spell_id, Mob *caster); - uint16 GetSpecializeSkillValue(int16 spell_id) const; - - int32 GetNPCTypeID(); - bool IsTargeted(); - - inline const float& GetX(); - inline const float& GetY(); - inline const float& GetZ(); - inline const float& GetHeading(); - inline const float& GetSize(); - - void SetFollowID(int32 id); - int32 GetFollowID(); - - virtual void Message(int32 type, const char* message, ...); - virtual void MessageString(int32 type, int32 string_id, int32 distance = 0); - void Say(const char *format, ...); - void Shout(const char *format, ...); - void Emote(const char *format, ...); - void InterruptSpell(int16 spellid = 0xFFFF); - - virtual void CastSpell(int16 spell_id, int16 target_id, int16 slot = 10, sint32 casttime = -1, sint32 mana_cost = -1); - bool IsImmuneToSpell(int16 spell_id, Mob *caster); - void BuffFadeBySpellID(int16 spell_id); - void BuffFadeByEffect(int effectid, int skipslot = -1); - void BuffFadeAll(); - void BuffFadeBySlot(int slot, bool iRecalcBonuses = true); - - int CanBuffStack(int16 spellid, int8 caster_level, bool iFailIfOverwrite = false); - inline bool IsCasting(); - int16 CastingSpellID(); - - void SetAppearance(EmuAppearance app, bool iIgnoreSelf = true); - - inline EmuAppearance GetAppearance(); - inline const int8& GetRunAnimSpeed(); - inline void SetRunAnimSpeed(sint8 in); - - void SetPetID(int16 NewPetID); - inline const int16& GetPetID(); - void SetOwnerID(int16 NewOwnerID); - inline const int16& GetOwnerID(); - inline const int16& GetPetType(); - - inline const int8& GetBodyType(); - virtual void Stun(int duration); - - void Spin(); - void Kill(); - - inline void SetInvul(bool invul); - inline bool GetInvul(); - inline void SetExtraHaste(int Haste); - virtual int GetHaste(); - int GetMonkHandToHandDamage(void); - - bool CanThisClassDoubleAttack(void); - bool CanThisClassDualWield(void); - bool CanThisClassRiposte(void); - bool CanThisClassDodge(void); - bool CanThisClassParry(void); - - int GetMonkHandToHandDelay(void); - int8 GetClassLevelFactor(); - void Mesmerize(); - inline bool IsMezzed(); - inline bool IsStunned(); - - void StartEnrage(); - bool IsEnraged(); - - FACTION_VALUE GetReverseFactionCon(Mob* iOther); - inline const bool& IsAIControlled(); - inline const float& GetAggroRange(); - inline const float& GetAssistRange(); - - inline void SetPetOrder(Mob::eStandingPetOrder i); - inline const Mob::eStandingPetOrder& GetPetOrder(); - inline const bool& IsRoamer(); - inline const bool IsRooted(); - - void AddToHateList(Mob* other, sint32 hate = 0, sint32 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false); - void SetHate(Mob* other, sint32 hate = 0, sint32 damage = 0); - int32 GetHateAmount(Mob* tmob, bool is_dam = false); - int32 GetDamageAmount(Mob* tmob); - Mob* GetHateTop(); - Mob* GetHateDamageTop(Mob* other); - Mob* GetHateRandom(); - bool IsEngaged(); - bool HateSummon(); - void FaceTarget(Mob* MobToFace = 0, bool update = false); - void SetHeading(float iHeading); - void WipeHateList(); - - inline bool CheckAggro(Mob* other); - - sint8 CalculateHeadingToTarget(float in_x, float in_y); - bool CalculateNewPosition(float x, float y, float z, float speed, bool checkZ = false); - bool CalculateNewPosition2(float x, float y, float z, float speed, bool checkZ = false); - float CalculateDistance(float x, float y, float z); - void SendTo(float new_x, float new_y, float new_z); - void SendToFixZ(float new_x, float new_y, float new_z); - void NPCSpecialAttacks(const char* parse, int permtag); - inline int32& DontHealMeBefore(); - inline int32& DontBuffMeBefore(); - inline int32& DontDotMeBefore(); - inline int32& DontRootMeBefore(); - inline int32& DontSnareMeBefore(); - - sint16 GetResist(int8 type); - Mob* GetShieldTarget(); - void SetShieldTarget(Mob* mob); - bool Charmed(); - int32 GetLevelHP(int8 tlevel); - int32 GetZoneID() const; - int16 CheckAggroAmount(int16 spellid); - int16 CheckHealAggroAmount(int16 spellid); - virtual int32 GetAA(int32 aa_id); - bool DivineAura(); - - void AddFeignMemory(Client* attacker); - void RemoveFromFeignMemory(Client* attacker); - void ClearFeignMemory(); - -//END MOB METHODS - - - - - - - diff --git a/utils/deprecated/perlxs/mob.h.xs b/utils/deprecated/perlxs/mob.h.xs deleted file mode 100644 index 692247173..000000000 --- a/utils/deprecated/perlxs/mob.h.xs +++ /dev/null @@ -1,39 +0,0 @@ - -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "features.h" -#ifdef EMBPERL_XS_CLASSES -#include "../common/debug.h" -#include "embperl.h" - -typedef const char Const_char; - -#include "mob.h" - -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - - -MODULE = Mob PACKAGE = Mob - -PROTOTYPES: ENABLE - - - diff --git a/utils/deprecated/perlxs/npc.h b/utils/deprecated/perlxs/npc.h deleted file mode 100644 index 93e8581e1..000000000 --- a/utils/deprecated/perlxs/npc.h +++ /dev/null @@ -1,63 +0,0 @@ - void SignalNPC(int _signal_id); - FACTION_VALUE CheckNPCFactionAlly(sint32 other_faction); - void AddItem(int32 itemid, int8 charges, int8 slot = 0); - void AddLootTable(); - void RemoveItem(uint16 item_id, int16 quantity = 0, int16 slot = 0); - void ClearItemList(); - void AddCash(int16 in_copper, int16 in_silver, int16 in_gold, int16 in_platinum); - void RemoveCash(); - int32 CountLoot(); - inline int32 GetLoottableID() { return loottable_id; } - inline uint32 GetCopper() { return copper; } - inline uint32 GetSilver() { return silver; } - inline uint32 GetGold() { return gold; } - inline uint32 GetPlatinum() { return platinum; } - - inline void SetCopper(uint32 amt) { copper = amt; } - inline void SetSilver(uint32 amt) { silver = amt; } - inline void SetGold(uint32 amt) { gold = amt; } - inline void SetPlatinum(uint32 amt) { platinum = amt; } - void SetGrid(int16 grid_){ grid=grid_; } - void SetSp2(int32 sg2){ spawn_group=sg2; } - int16 GetWaypointMax(){ return wp_m; } - sint16 GetGrid(){ return grid; } - int32 GetSp2(){ return spawn_group; } - - inline const sint32& GetNPCFactionID() { return npc_faction_id; } - inline sint32 GetPrimaryFaction() { return primary_faction; } - sint32 GetNPCHate(Mob* in_ent) {return hate_list.GetEntHate(in_ent);} - bool IsOnHatelist(Mob*p) { return hate_list.IsOnHateList(p);} - - void SetNPCFactionID(sint32 in) { npc_faction_id = in; database.GetFactionIdsForNPC(npc_faction_id, &faction_list, &primary_faction); } - int16 GetMaxDMG() {return max_dmg;} - bool IsAnimal() { return(bodytype == 21); } - int16 GetPetSpellID() {return pet_spell_id;} - void SetPetSpellID(int16 amt) {pet_spell_id = amt;} - int32 GetMaxDamage(int8 tlevel); - void SetTaunting(bool tog) {taunting = tog;} - void PickPocket(Client* thief); - void StartSwarmTimer(int32 duration) { swarm_timer.Start(duration); } - void DoClassAttacks(Mob *target); - - - - int GetMaxWp() const { return max_wp; } - void DisplayWaypointInfo(Client *to); - void CalculateNewWaypoint(); -// int8 CalculateHeadingToNextWaypoint(); -// float CalculateDistanceToNextWaypoint(); - void AssignWaypoints(int32 grid); - void SetWaypointPause(); - void UpdateWaypoint(int wp_index); - // quest wandering commands - void StopWandering(); - void ResumeWandering(); - void PauseWandering(int pausetime); - void MoveTo(float mtx, float mty, float mtz, float mth, bool saveguardspot); - - void NextGuardPosition(); - void SaveGuardSpot(bool iClearGuardSpot = false); - inline bool IsGuarding() const { return(guard_heading != 0); } - void AI_SetRoambox(float iDist, float iMaxX, float iMinX, float iMaxY, float iMinY, int32 iDelay = 2500); - const int32& GetNPCSpellsID(); - diff --git a/utils/deprecated/perlxs/npc.h.xs b/utils/deprecated/perlxs/npc.h.xs deleted file mode 100644 index b84085f58..000000000 --- a/utils/deprecated/perlxs/npc.h.xs +++ /dev/null @@ -1,39 +0,0 @@ - -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "features.h" -#ifdef EMBPERL_XS_CLASSES -#include "../common/debug.h" -#include "embperl.h" - -typedef const char Const_char; - -#include "npc.h" - -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - - -MODULE = NPC PACKAGE = NPC - -PROTOTYPES: ENABLE - - - diff --git a/utils/deprecated/perlxs/perlpacket.h b/utils/deprecated/perlxs/perlpacket.h deleted file mode 100644 index 58fba479c..000000000 --- a/utils/deprecated/perlxs/perlpacket.h +++ /dev/null @@ -1,28 +0,0 @@ -PerlPacket * -PerlPacket::new(const char *opcode = "OP_Unknown", uint32 len = 0); - void DESTROY(); - - bool SetOpcode(const char *opcode); - void Resize(uint32 len); - - //sending functions - void SendTo(Client *who); - void SendToAll(); - - //editing - void Zero(); - void FromArray(int *numbers, uint32 length); - void SetByte(uint32 pos, uint8 val); - void SetShort(uint32 pos, uint16 val); - void SetLong(uint32 pos, uint32 val); - void SetFloat(uint32 pos, float val); - void SetString(uint32 pos, char *str); - - void SetEQ1319(uint32 pos, float part13, float part19); - void SetEQ1913(uint32 pos, float part19, float part13); - - //reading - uint8 GetByte(uint32 pos); - uint16 GetShort(uint32 pos); - uint32 GetLong(uint32 pos); - float GetFloat(uint32 pos); diff --git a/utils/deprecated/perlxs/perlpacket.h.xs b/utils/deprecated/perlxs/perlpacket.h.xs deleted file mode 100644 index 6ba3ab910..000000000 --- a/utils/deprecated/perlxs/perlpacket.h.xs +++ /dev/null @@ -1,36 +0,0 @@ - -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "features.h" -#ifdef EMBPERL_XS_CLASSES -#include "../common/debug.h" -#include "embperl.h" - -#include "perlpacket.h" - -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - -MODULE = PerlPacket PACKAGE = PerlPacket - -PROTOTYPES: ENABLE - - - diff --git a/utils/deprecated/perlxs/put b/utils/deprecated/perlxs/put deleted file mode 100644 index 54009f6fa..000000000 --- a/utils/deprecated/perlxs/put +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -cp perl_PlayerCorpse.cpp perl_client.cpp perl_entity.cpp perl_groups.cpp \ - perl_mob.cpp perl_npc.cpp perl_perlpacket.cpp \ -../../zone/ - -cp perl_EQW.cpp perl_HTTPRequest.cpp perl_EQLConfig.cpp ../../world/ - -cp perl_EQDB.cpp perl_EQDBRes.cpp ../../common/ - diff --git a/utils/deprecated/player_profile_set/player_profile_set/MiscFunctions.cpp b/utils/deprecated/player_profile_set/player_profile_set/MiscFunctions.cpp index aae237489..0d8108a20 100644 --- a/utils/deprecated/player_profile_set/player_profile_set/MiscFunctions.cpp +++ b/utils/deprecated/player_profile_set/player_profile_set/MiscFunctions.cpp @@ -226,7 +226,7 @@ bool atobool(char* iBool) { return true; if (!strcasecmp(iBool, "n")) return false; - if (atoi(iBool)) + if (Strings::ToInt(iBool)) return true; return false; } @@ -328,4 +328,4 @@ int FloatToEQH(float d) float EQHtoFloat(int d) { return(360.0f - float((d * 360) >> 11)); -} \ No newline at end of file +} diff --git a/utils/deprecated/player_profile_set/player_profile_set/database.cpp b/utils/deprecated/player_profile_set/player_profile_set/database.cpp index be85d51a2..a0aeadeb9 100644 --- a/utils/deprecated/player_profile_set/player_profile_set/database.cpp +++ b/utils/deprecated/player_profile_set/player_profile_set/database.cpp @@ -60,7 +60,7 @@ void EQEmuDatabase::GetPlayer(std::string name) while ((row = mysql_fetch_row(res)) != NULL) { player_entry pe; - pe.id = atoi(row[1]); + pe.id = Strings::ToInt(row[1]); pe.data = new char[sizeof(PlayerProfile_Struct)]; memcpy(pe.data, row[0], sizeof(PlayerProfile_Struct)); player_list.push_back(pe); @@ -97,7 +97,7 @@ void EQEmuDatabase::GetPlayers() while ((row = mysql_fetch_row(res)) != NULL) { player_entry pe; - pe.id = atoi(row[1]); + pe.id = Strings::ToInt(row[1]); pe.data = new char[sizeof(PlayerProfile_Struct)]; memcpy(pe.data, row[0], sizeof(PlayerProfile_Struct)); player_list.push_back(pe); diff --git a/utils/deprecated/ppconvert/ppconvert.cpp b/utils/deprecated/ppconvert/ppconvert.cpp index 716ddd753..4054b4e05 100644 --- a/utils/deprecated/ppconvert/ppconvert.cpp +++ b/utils/deprecated/ppconvert/ppconvert.cpp @@ -16,30 +16,30 @@ using namespace std; int convert_profile_once(char *src, char *dst, int len); int main() { - + char host[200], user[200], passwd[200], database[200]; int32 port=0; bool compression = false; bool items[6] = {false, false, false, false, false, false}; - + if(!DBcore::ReadDBINI(host, user, passwd, database, port, compression, items)) { exit(1); } - + if (!items[0] || !items[1] || !items[2] || !items[3]) { printf ("Incomplete DB.INI file.\n"); exit (1); } - + vector updates; - + MYSQL m; MYSQL out; mysql_init(&m); mysql_init(&out); - + if(!mysql_real_connect(&m, host, user, passwd, database, 0, NULL, 0)) { printf("Unable to connect 1: %s.\n", mysql_error(&m)); return(1); @@ -53,53 +53,53 @@ int main() { printf("Unable to query.\n"); return(1); } - + MYSQL_RES *res = mysql_use_result(&m); if(res == NULL) { printf("Unable to use res.\n"); return(1); } - + char *inbuffer = new char[sizeof(PlayerProfile_Struct)]; - + MYSQL_ROW row; unsigned long *lengths; - + int convert_count = 0; int correct_count = 0; int failed_count = 0; while((row = mysql_fetch_row(res))) { lengths = mysql_fetch_lengths(res); - unsigned long id = atoi(row[0]); - + unsigned long id = Strings::ToInt(row[0]); + int curlen = lengths[2]; - + if(curlen == sizeof(PlayerProfile_Struct)) { correct_count++; continue; //allready current. } - + fprintf(stderr, "Converting char %lu: %s...", id, row[1]); - + //make a copy of the version in the DB memcpy(inbuffer, row[2], curlen); - + char *outbuffer = new char[2*sizeof(PlayerProfile_Struct) + 512]; - + int steps; for(steps = 0; steps < MAX_CONVERT_STEPS && curlen != sizeof(PlayerProfile_Struct); steps++) { //clear outbuffer memset(outbuffer, 0, sizeof(PlayerProfile_Struct)); - + fprintf(stderr, " |"); fflush(stderr); - + //convert inbuffer one step closer to the current profile, into outbuffer curlen = convert_profile_once(inbuffer, outbuffer, curlen); if(curlen == 0) break; - + //copy outbuffer into inbuffer for the next convert step memcpy(inbuffer, outbuffer, curlen); } @@ -111,26 +111,26 @@ int main() { } fprintf(stderr, " *"); fflush(stderr); - + //the correct profile ends up in inbuffer, so we can escape it into outbuffer char *bptr = outbuffer; bptr += snprintf(bptr, 128, "UPDATE character_ SET profile='"); bptr += mysql_real_escape_string(&m, bptr, (const char *) inbuffer, sizeof(PlayerProfile_Struct)); snprintf(bptr, 128, "' WHERE id=%lu", id); - + // printf("Query: '%s'\n", outbuffer); /* if(mysql_query(&out, outbuffer) != 0) { failed_count++; printf(" Error updating char id %lu: %s\n", id, mysql_error(&m)); continue; } -*/ +*/ updates.push_back(outbuffer); fprintf(stderr, " done.\n"); // convert_count++; } // mysql_free_result(res); - + vector::iterator cur, end; cur = updates.begin(); @@ -145,12 +145,12 @@ updates.push_back(outbuffer); printf("."); fflush(stdout); delete[] *cur; - + convert_count++; } fprintf(stderr, "%d chars converted, %d errors, %d chars were up to date.\n", convert_count, failed_count, correct_count); - + mysql_close(&m); mysql_close(&out); return(0); @@ -217,11 +217,11 @@ int convert_profile_once(char *src, char *dst, int len) { s_ptr+=8; ptr+=12; memcpy(ptr,s_ptr,3700); - + pp->bind_x=((Before_Sep14th_PlayerProfile_Struct*)newpps)->bind_x; pp->bind_y=((Before_Sep14th_PlayerProfile_Struct*)newpps)->bind_y; pp->bind_z=((Before_Sep14th_PlayerProfile_Struct*)newpps)->bind_z; - + len = sizeof(Before_Sep14th_PlayerProfile_Struct); break; } @@ -249,7 +249,7 @@ int convert_profile_once(char *src, char *dst, int len) { pp->bind_x[0]=oldpp->bind_x; pp->bind_y[0]=oldpp->bind_y; pp->bind_z[0]=oldpp->bind_z; - + len = sizeof(Before_Dec15th_PlayerProfile_Struct); break; } @@ -257,10 +257,10 @@ int convert_profile_once(char *src, char *dst, int len) { #define StructDist(in, f1, f2) (uint32(&in->f2)-uint32(&in->f1)) Before_Dec15th_PlayerProfile_Struct* ops = (Before_Dec15th_PlayerProfile_Struct*)src; Before_June29th_PlayerProfile_Struct* pp = (Before_June29th_PlayerProfile_Struct*)dst; - + //start with the basics memcpy(dst, ops, sizeof(Before_June29th_PlayerProfile_Struct)); - + pp->anon = ops->anon; pp->guildrank = ops->guildrank; memcpy(pp->unknown0245, &ops->fatigue, StructDist(ops, fatigue, guildid2)); @@ -270,24 +270,24 @@ int convert_profile_once(char *src, char *dst, int len) { memcpy(pp->unknown6392, &ops->unknown5248, StructDist(ops, unknown5248, unknown11376)); //put the tribute block in the right place memcpy(&pp->tribute_time_remaining, &ops->tribute_time_remaining, StructDist(ops, tribute_time_remaining, unknown5764)); - + //copy over things that maybe moved, but I havent figure out how yet pp->aapoints = ops->aapoints; pp->aapoints_spent = ops->aapoints_spent; - + len = sizeof(Before_June29th_PlayerProfile_Struct); } case sizeof(Before_June29th_PlayerProfile_Struct): { Before_June29th_PlayerProfile_Struct* ops = (Before_June29th_PlayerProfile_Struct*)src; memcpy(dst, ops, sizeof(Before_June29th_PlayerProfile_Struct)); - + len = sizeof(Before_May12_PlayerProfile_Struct); } case sizeof(Before_May12_PlayerProfile_Struct): { Before_May12_PlayerProfile_Struct* ops = (Before_May12_PlayerProfile_Struct*)src; PlayerProfile_Struct* pp = (PlayerProfile_Struct*)dst; memcpy(dst, ops, sizeof(Before_May12_PlayerProfile_Struct)); - + memcpy(&pp->checksum, &ops->checksum, StructDist(ops, checksum, haircolor)); memcpy(&pp->haircolor, &ops->haircolor, StructDist(ops, haircolor, unknown0310[0])); memcpy(&pp->item_material[0], &ops->item_material[0], StructDist(ops, item_material[0], servername[0])); @@ -300,7 +300,7 @@ int convert_profile_once(char *src, char *dst, int len) { memcpy(&pp->tribute_time_remaining, &ops->tribute_time_remaining, StructDist(ops, tribute_time_remaining, unknown6860)); memcpy(&pp->leader_abilities, &ops->leader_abilities, StructDist(ops, leader_abilities, unknown6932[0])); memcpy(&pp->air_remaining, &ops->air_remaining, StructDist(ops, air_remaining, unknown18492)); - + /* * This is the last statement in this switch. */ diff --git a/utils/deprecated/ppskillfix/ppskillfix.cpp b/utils/deprecated/ppskillfix/ppskillfix.cpp index f2c7c1474..cfdbdb892 100644 --- a/utils/deprecated/ppskillfix/ppskillfix.cpp +++ b/utils/deprecated/ppskillfix/ppskillfix.cpp @@ -16,30 +16,30 @@ using namespace std; int convert_profile_once(char *src, char *dst, int len); int main() { - + char host[200], user[200], passwd[200], database[200]; int32 port=0; bool compression = false; bool items[6] = {false, false, false, false, false, false}; - + if(!DBcore::ReadDBINI(host, user, passwd, database, port, compression, items)) { exit(1); } - + if (!items[0] || !items[1] || !items[2] || !items[3]) { printf ("Incomplete DB.INI file.\n"); exit (1); } - + vector updates; - + MYSQL m; MYSQL out; mysql_init(&m); mysql_init(&out); - + if(!mysql_real_connect(&m, host, user, passwd, database, 0, NULL, 0)) { printf("Unable to connect 1: %s.\n", mysql_error(&m)); return(1); @@ -53,36 +53,36 @@ int main() { printf("Unable to query.\n"); return(1); } - + MYSQL_RES *res = mysql_use_result(&m); if(res == NULL) { printf("Unable to use res.\n"); return(1); } - + char *inbuffer = new char[sizeof(PlayerProfile_Struct)]; PlayerProfile_Struct *in_pp = (PlayerProfile_Struct *) inbuffer; - + MYSQL_ROW row; unsigned long *lengths; - + int convert_count = 0; int correct_count = 0; int failed_count = 0; while((row = mysql_fetch_row(res))) { lengths = mysql_fetch_lengths(res); - unsigned long id = atoi(row[0]); - + unsigned long id = Strings::ToInt(row[0]); + int curlen = lengths[2]; - + if(curlen != sizeof(PlayerProfile_Struct)) { fprintf(stderr, "Char '%s' has the wrong size. Expected %d, got %d\n", row[1], sizeof(PlayerProfile_Struct), curlen); failed_count++; continue; } - - + + //make a copy of the version in the DB memcpy(inbuffer, row[2], curlen); @@ -99,32 +99,32 @@ fprintf(stderr, "Char '%s' skill %d = %d\n", row[1], r, in_pp->skills[r]); correct_count++; continue; } - + fprintf(stderr, "Converting char %lu: %s...", id, row[1]); convert_count++; - + char *outbuffer = new char[2*sizeof(PlayerProfile_Struct) + 512]; - - + + //the correct profile ends up in inbuffer, so we can escape it into outbuffer char *bptr = outbuffer; bptr += snprintf(bptr, 128, "UPDATE character_ SET profile='"); bptr += mysql_real_escape_string(&m, bptr, (const char *) inbuffer, sizeof(PlayerProfile_Struct)); snprintf(bptr, 128, "' WHERE id=%lu", id); - + // printf("Query: '%s'\n", outbuffer); /* if(mysql_query(&out, outbuffer) != 0) { failed_count++; printf(" Error updating char id %lu: %s\n", id, mysql_error(&m)); continue; } -*/ +*/ updates.push_back(outbuffer); fprintf(stderr, " done.\n"); // convert_count++; } // mysql_free_result(res); - + vector::iterator cur, end; cur = updates.begin(); @@ -139,12 +139,12 @@ updates.push_back(outbuffer); printf("."); fflush(stdout);*/ delete[] *cur; - + convert_count++; } fprintf(stderr, "%d chars converted, %d errors, %d chars were up to date.\n", convert_count, failed_count, correct_count); - + mysql_close(&m); mysql_close(&out); return(0); diff --git a/utils/deprecated/spell_explorer.cpp b/utils/deprecated/spell_explorer.cpp index 83d116a46..ef4b2a7c8 100644 --- a/utils/deprecated/spell_explorer.cpp +++ b/utils/deprecated/spell_explorer.cpp @@ -4,43 +4,43 @@ #include "../zone/spdat.h" int main(int argc, char** argv) { - + int spid = 0; - + if(argc != 2) { printf("Invalid args: %s [spell id]\n", argv[0]); return(1); } - - spid = atoi(argv[1]); - - + + spid = Strings::ToInt(argv[1]); + + int tempid=0; int16 counter=0; char spell_line[2048]; - + FILE *sf = fopen("spells_us.txt", "r"); - + if(sf == NULL) { printf("Unable to open spells_us.txt file.\n"); return false; } - + SPDat_Spell_Struct sp; - + while(!feof(sf)) { fgets(spell_line, sizeof(spell_line), sf); Seperator sep(spell_line, '^', 205, 100, false, 0, 0, false); - + if(spell_line[0]=='\0') break; - - tempid = atoi(sep.arg[0]); + + tempid = Strings::ToInt(sep.arg[0]); if(tempid != spid) continue; - + printf("Found spell %d\n", spid); - + counter++; strcpy(sp.name, sep.arg[1]); strcpy(sp.player_1, sep.arg[2]); @@ -55,83 +55,83 @@ int main(int argc, char** argv) { sp.aoerange=atof(sep.arg[10]); sp.pushback=atof(sep.arg[11]); sp.pushup=atof(sep.arg[12]); - sp.cast_time=atoi(sep.arg[13]); - sp.recovery_time=atoi(sep.arg[14]); - sp.recast_time=atoi(sep.arg[15]); - sp.buffdurationformula=atoi(sep.arg[16]); - sp.buffduration=atoi(sep.arg[17]); - sp.AEDuration=atoi(sep.arg[18]); - sp.mana=atoi(sep.arg[19]); - + sp.cast_time=Strings::ToInt(sep.arg[13]); + sp.recovery_time=Strings::ToInt(sep.arg[14]); + sp.recast_time=Strings::ToInt(sep.arg[15]); + sp.buffdurationformula=Strings::ToInt(sep.arg[16]); + sp.buffduration=Strings::ToInt(sep.arg[17]); + sp.AEDuration=Strings::ToInt(sep.arg[18]); + sp.mana=Strings::ToInt(sep.arg[19]); + int y=0; for(y=0; y < EFFECT_COUNT;y++) - sp.base[y]=atoi(sep.arg[20+y]); + sp.base[y]=Strings::ToInt(sep.arg[20+y]); for(y=0;y<11;y++) - sp.base2[y]=atoi(sep.arg[33+y]); + sp.base2[y]=Strings::ToInt(sep.arg[33+y]); for(y=0; y < EFFECT_COUNT;y++) - sp.max[y]=atoi(sep.arg[44+y]); - - sp.icon=atoi(sep.arg[56]); - sp.memicon=atoi(sep.arg[57]); - + sp.max[y]=Strings::ToInt(sep.arg[44+y]); + + sp.icon=Strings::ToInt(sep.arg[56]); + sp.memicon=Strings::ToInt(sep.arg[57]); + for(y=0; y< 4;y++) - sp.components[y]=atoi(sep.arg[58+y]); - + sp.components[y]=Strings::ToInt(sep.arg[58+y]); + for(y=0; y< 4;y++) - sp.component_counts[y]=atoi(sep.arg[62+y]); - + sp.component_counts[y]=Strings::ToInt(sep.arg[62+y]); + for(y=0; y< 4;y++) - sp.NoexpendReagent[y]=atoi(sep.arg[66+y]); - + sp.NoexpendReagent[y]=Strings::ToInt(sep.arg[66+y]); + for(y=0; y< 12;y++) - sp.formula[y]=atoi(sep.arg[70+y]); - - sp.LightType=atoi(sep.arg[82]); - sp.goodEffect=atoi(sep.arg[83]); - sp.Activated=atoi(sep.arg[84]); - sp.resisttype=atoi(sep.arg[85]); - + sp.formula[y]=Strings::ToInt(sep.arg[70+y]); + + sp.LightType=Strings::ToInt(sep.arg[82]); + sp.goodEffect=Strings::ToInt(sep.arg[83]); + sp.Activated=Strings::ToInt(sep.arg[84]); + sp.resisttype=Strings::ToInt(sep.arg[85]); + for(y=0; y< 12;y++) - sp.effectid[y]=atoi(sep.arg[86+y]); - - sp.targettype=(SpellTargetType)atoi(sep.arg[98]); - sp.basediff=atoi(sep.arg[99]); - sp.skill=(SkillType)atoi(sep.arg[100]); - sp.zonetype=atoi(sep.arg[101]); - sp.EnvironmentType=atoi(sep.arg[102]); - sp.TimeOfDay=atoi(sep.arg[103]); - + sp.effectid[y]=Strings::ToInt(sep.arg[86+y]); + + sp.targettype=(SpellTargetType)Strings::ToInt(sep.arg[98]); + sp.basediff=Strings::ToInt(sep.arg[99]); + sp.skill=(SkillType)Strings::ToInt(sep.arg[100]); + sp.zonetype=Strings::ToInt(sep.arg[101]); + sp.EnvironmentType=Strings::ToInt(sep.arg[102]); + sp.TimeOfDay=Strings::ToInt(sep.arg[103]); + for(y=0; y< 16;y++) - sp.classes[y]=atoi(sep.arg[104+y]); - - sp.CastingAnim=atoi(sep.arg[120]); - sp.TargetAnim=atoi(sep.arg[121]); - sp.TravelType=atoi(sep.arg[122]); - sp.SpellAffectIndex=atoi(sep.arg[123]); - + sp.classes[y]=Strings::ToInt(sep.arg[104+y]); + + sp.CastingAnim=Strings::ToInt(sep.arg[120]); + sp.TargetAnim=Strings::ToInt(sep.arg[121]); + sp.TravelType=Strings::ToInt(sep.arg[122]); + sp.SpellAffectIndex=Strings::ToInt(sep.arg[123]); + for(y=0; y< 23;y++) { - sp.spacing124[y]=atoi(sep.arg[124+y]); + sp.spacing124[y]=Strings::ToInt(sep.arg[124+y]); } - - sp.ResistDiff=atoi(sep.arg[147]); - sp.dot_stacking_exempt=atoi(sep.arg[148]); - sp.deletable=atoi(sep.arg[149]); - - sp.RecourseLink = atoi(sep.arg[150]); - sp.descnum = atoi(sep.arg[155]); - sp.typedescnum = atoi(sep.arg[156]); - sp.effectdescnum = atoi(sep.arg[157]); + + sp.ResistDiff=Strings::ToInt(sep.arg[147]); + sp.dot_stacking_exempt=Strings::ToInt(sep.arg[148]); + sp.deletable=Strings::ToInt(sep.arg[149]); + + sp.RecourseLink = Strings::ToInt(sep.arg[150]); + sp.descnum = Strings::ToInt(sep.arg[155]); + sp.typedescnum = Strings::ToInt(sep.arg[156]); + sp.effectdescnum = Strings::ToInt(sep.arg[157]); // for(y=0; y< 17;y++) -// sp.Spacing4[y] = atoi(sep.arg[158+y]); - +// sp.Spacing4[y] = Strings::ToInt(sep.arg[158+y]); + break; } fclose(sf); - + const struct SPDat_Spell_Struct *s=&sp; - + printf("Spell info for spell #%d:\n", spid); printf(" name: %s\n", s->name); printf(" player_1: %s\n", s->player_1); @@ -181,7 +181,7 @@ int main(int argc, char** argv) { printf(" RecourseLink: %d\n", s->RecourseLink); printf(" Spacing124[23]: %d, %d, %d, %d, %d\n", s->spacing124[0], s->spacing124[1], s->spacing124[2], s->spacing124[3], s->spacing124[4]); - + return(0); } diff --git a/utils/scripts/build/linux-build.sh b/utils/scripts/build/linux-build.sh new file mode 100755 index 000000000..6897c599e --- /dev/null +++ b/utils/scripts/build/linux-build.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +set -x + +sudo chown eqemu:eqemu /drone/src/ * -R +sudo chown eqemu:eqemu /home/eqemu/.ccache/ * -R + +git submodule init && git submodule update + +perl utils/scripts/build/tag-version.pl + +mkdir -p build && cd build && cmake -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_LUA=ON -DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING="-Os" -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -G 'Unix Makefiles' .. && make -j$((`nproc`-4)) + +curl https://raw.githubusercontent.com/Akkadius/eqemu-install-v2/master/eqemu_config.json --output eqemu_config.json +./bin/tests + +# shellcheck disable=SC2164 +cd /drone/src/ + +chmod +x ./utils/scripts/build/should-release/should-release +./utils/scripts/build/should-release/should-release || exit + +rm ./build/bin/*.a +zip -j eqemu-server-linux-x64.zip ./build/bin/* + +# shellcheck disable=SC2010 +ls -lsh | grep zip +sudo apt-get update && sudo apt-get install -y rclone +rclone config create remote ftp env_auth true > /dev/null +rclone copy eqemu-server-linux-x64.zip remote: 2>&1 +rclone ls remote: 2>&1 diff --git a/utils/scripts/build/releaser.Dockerfile b/utils/scripts/build/releaser.Dockerfile new file mode 100644 index 000000000..46f942c0a --- /dev/null +++ b/utils/scripts/build/releaser.Dockerfile @@ -0,0 +1,24 @@ +############################################# +# debian +############################################# +FROM debian:11-slim + +############################################# +# basics +############################################# +RUN apt-get update && apt-get install -y \ + rclone \ + git \ + make \ + jq \ + wget \ + curl + +############################################# +# node +############################################# +RUN curl -sL https://deb.nodesource.com/setup_14.x | bash && \ + apt-get update && apt-get install -y nodejs && rm -rf /var/lib/apt/lists/* + +RUN npm install -g gh-release + diff --git a/utils/scripts/build/should-release/go.mod b/utils/scripts/build/should-release/go.mod new file mode 100644 index 000000000..679ef56c4 --- /dev/null +++ b/utils/scripts/build/should-release/go.mod @@ -0,0 +1,16 @@ +module should-release + +go 1.18 + +require ( + github.com/google/go-github/v41 v41.0.0 + golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be +) + +require ( + github.com/golang/protobuf v1.3.2 // indirect + github.com/google/go-querystring v1.1.0 // indirect + golang.org/x/crypto v0.1.0 // indirect + golang.org/x/net v0.7.0 // indirect + google.golang.org/appengine v1.6.7 // indirect +) diff --git a/utils/scripts/build/should-release/go.sum b/utils/scripts/build/should-release/go.sum new file mode 100644 index 000000000..fc12dc0b9 --- /dev/null +++ b/utils/scripts/build/should-release/go.sum @@ -0,0 +1,31 @@ +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-github/v41 v41.0.0 h1:HseJrM2JFf2vfiZJ8anY2hqBjdfY1Vlj/K27ueww4gg= +github.com/google/go-github/v41 v41.0.0/go.mod h1:XgmCA5H323A9rtgExdTcnDkcqp6S30AVACCBDOonIxg= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +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.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +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/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= diff --git a/utils/scripts/build/should-release/main.go b/utils/scripts/build/should-release/main.go new file mode 100644 index 000000000..bd80f5990 --- /dev/null +++ b/utils/scripts/build/should-release/main.go @@ -0,0 +1,95 @@ +package main + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "github.com/google/go-github/v41/github" + "golang.org/x/oauth2" + "log" + "net/http" + "os" + "os/exec" + "path/filepath" + "strings" +) + +type PackageJson struct { + Name string `json:"name"` + Version string `json:"version"` + Repository struct { + Type string `json:"type"` + URL string `json:"url"` + } `json:"repository"` +} + +func main() { + // get latest release from github + client := github.NewClient(nil) + if len(os.Getenv("GITHUB_TOKEN")) > 0 { + ts := oauth2.StaticTokenSource( + &oauth2.Token{AccessToken: os.Getenv("GITHUB_TOKEN")}, + ) + tc := &http.Client{ + Transport: &oauth2.Transport{ + Source: ts, + }, + } + client = github.NewClient(tc) + } + + release, _, err := client.Repositories.GetLatestRelease(context.Background(), "EQEmu", "Server") + if err != nil { + log.Println(err) + os.Exit(1) + } + + version := strings.ReplaceAll(*release.TagName, "v", "") + + // get current version from package.json + currentLevel := filepath.Join("./package.json") + packageJsonFile := currentLevel + if _, err := os.Stat(currentLevel); errors.Is(err, os.ErrNotExist) { + packageJsonFile = "" + // this is only really needed when developing this binary + walkUpToRoot := filepath.Join("../../../../package.json") + if _, err := os.Stat(walkUpToRoot); err == nil { + // path/to/whatever exists + packageJsonFile = walkUpToRoot + } + } + + out, err := exec.Command("git", "rev-parse", "--abbrev-ref", "HEAD").Output() + if err != nil { + log.Fatal(err) + } + currentBranch := strings.TrimSpace(string(out)) + if currentBranch != "master" { + fmt.Printf("Not on master, no need to release\n") + fmt.Printf("Exiting code 78 to halt pipeline steps gracefully\n") + os.Exit(78) + } + + if len(os.Getenv("RCLONE_FTP_PASS")) == 0 { + fmt.Printf("Missing RCLONE_FTP_PASS no need to release\n") + fmt.Printf("Exiting code 78 to halt pipeline steps gracefully\n") + os.Exit(78) + } + + if len(packageJsonFile) == 0 { + fmt.Printf("Could not find package.json\n") + os.Exit(1) + } + + packageJson, err := os.ReadFile(packageJsonFile) + var p PackageJson + _ = json.Unmarshal(packageJson, &p) + + // version compare + if p.Version == version { + fmt.Printf("Version [%v] already exists. No need to release\n", version) + fmt.Printf("Exiting code 78 to halt pipeline steps gracefully\n") + os.Exit(78) + } +} diff --git a/utils/scripts/build/should-release/should-release b/utils/scripts/build/should-release/should-release new file mode 100755 index 000000000..97fcdb851 Binary files /dev/null and b/utils/scripts/build/should-release/should-release differ diff --git a/utils/scripts/build/should-release/should-release.exe b/utils/scripts/build/should-release/should-release.exe new file mode 100755 index 000000000..b65592783 Binary files /dev/null and b/utils/scripts/build/should-release/should-release.exe differ diff --git a/utils/scripts/build/tag-version.pl b/utils/scripts/build/tag-version.pl new file mode 100644 index 000000000..803b4f608 --- /dev/null +++ b/utils/scripts/build/tag-version.pl @@ -0,0 +1,61 @@ +#!/usr/bin/perl +use strict; +use warnings FATAL => 'all'; + +open my $fh, '<', './package.json' or die "Can't open file $!"; +my $package_json = do { + local $/; + <$fh> +}; + +my $version = ""; +sub trim($) +{ + my $string = shift; + $string =~ s/^\s+//; + $string =~ s/\s+$//; + return $string; +} + +# manually parse because we can't guarantee json module is available +# it's jank but it's quick and dirty +# this is only used in the build pipeline +foreach my $line (split("\n", $package_json)) { + if ($line =~ /version/i) { + $version = $line; + $version =~ s/version//g; + $version =~ s/://g; + $version =~ s/"//g; + $version =~ s/,//g; + $version = trim($version); + } +} + +print "Version is [" . $version . "]\n"; + +# server version file +my $version_file_name = "./common/version.h"; +open my $vfh, '<', $version_file_name or die "Can't open file $!"; +my $version_file = do { + local $/; + <$vfh> +}; + +# write new version +my $new_version_file = ""; +foreach my $line (split("\n", $version_file)) { + if ($line =~ /CURRENT_VERSION/i) { + my @s = split("\"", $line); + if ($#s == 2) { + $line =~ s/$s[1]/$version/g; + } + } + + $new_version_file .= $line . "\n"; +} + +open(my $wfh, '>', $version_file_name) or die "Could not open file '$version_file_name' $!"; +print $wfh $new_version_file; +close $wfh; + +print $new_version_file; diff --git a/utils/scripts/build/windows-build.ps1 b/utils/scripts/build/windows-build.ps1 new file mode 100644 index 000000000..7a016eebe --- /dev/null +++ b/utils/scripts/build/windows-build.ps1 @@ -0,0 +1,42 @@ +$cwd = Get-Location + +Set-Location -Path "$cwd" + +git submodule init +git submodule update + +if (![System.IO.Directory]::Exists("$cwd\win-build-x64")) +{ + Write-Information -MessageData "Creating build x64 folder" -InformationAction Continue + New-Item -Path "$cwd\win-build-x64" -ItemType Directory +} + +perl .\utils\scripts\build\tag-version.pl + +Write-Information -MessageData "Creating build x64" -InformationAction Continue +Set-Location -Path "$cwd\win-build-x64" +cmake -Wno-dev -G "Visual Studio 17 2022" -A x64 -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_ZLIB=ON "$cwd" +cmake --build . --config RelWithDebInfo --clean-first +Set-Location -Path "$cwd" + +if ($LASTEXITCODE -ne 0) { echo "Build emitted error"; exit 1 } + +.\utils\scripts\build\should-release\should-release.exe; if ($LASTEXITCODE -ne 0) { exit } + +# trim some fat +del $cwd\win-build-x64\bin\RelWithDebInfo\export_client_files.pdb +del $cwd\win-build-x64\bin\RelWithDebInfo\import_client_files.pdb +del $cwd\win-build-x64\bin\RelWithDebInfo\shared_memory.pdb +del $cwd\win-build-x64\bin\RelWithDebInfo\queryserv.pdb +del $cwd\win-build-x64\bin\RelWithDebInfo\eqlaunch.pdb +del $cwd\win-build-x64\bin\RelWithDebInfo\cppunit.pdb +del $cwd\win-build-x64\bin\RelWithDebInfo\tests.pdb +del $cwd\win-build-x64\bin\RelWithDebInfo\tests.exe + +7z a eqemu-server-windows-x64.zip $cwd\win-build-x64\bin\RelWithDebInfo\*.exe $cwd\win-build-x64\bin\RelWithDebInfo\*.dll $cwd\win-build-x64\bin\RelWithDebInfo\*.pdb $cwd\win-build-x64\libs\zlibng\RelWithDebInfo\*.dll $cwd\win-build-x64\libs\zlibng\RelWithDebInfo\*.pdb + +dir *.zip +rclone config create remote ftp env_auth true +rclone copy eqemu-server-windows-x64.zip remote: 2>&1 +rclone ls remote: 2>&1 + diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index efdff15fa..633e5030c 100755 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -1199,6 +1199,25 @@ sub get_mysql_path } } } + if ($path eq "") { + my @files; + my $start_dir = trim(`echo %programfiles%`); + find( + sub { + if ($#files > 0) { + return; + } + push @files, $File::Find::name unless $File::Find::name!~/mysql.exe/i; + }, + $start_dir + ); + for my $file (@files) { + if ($file=~/mysql.exe/i) { + $path = $file; + last; + } + } + } } if ($OS eq "Linux") { $path = `which mysql`; diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 1302574d3..6b70625b9 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -471,6 +471,14 @@ 9215|2023_01_08_zone_max_level.sql|SHOW COLUMNS FROM `zone` LIKE 'max_level'|empty| 9216|2023_01_15_merc_data.sql|SHOW TABLES LIKE 'mercs'|empty| 9217|2023_01_15_chatchannel_reserved_names.sql|SHOW TABLES LIKE 'chatchannel_reserved_names'|empty| +9218|2023_01_24_item_recast.sql|show columns from character_item_recast like '%recast_type%'|contains|smallint +9219|2023_01_29_merchant_status_requirements.sql|SHOW COLUMNS FROM merchantlist LIKE 'min_status'|empty| +9220|2022_12_19_player_events_tables.sql|SHOW TABLES LIKE 'player_event_logs'|empty| +9221|2023_02_24_npc_scaling_zone_id_instance_version.sql|SHOW COLUMNS FROM `npc_scale_global_base` LIKE 'zone_id'|empty| +9222|2023_02_28_npc_scaling_zone_list_version_list.sql|SHOW COLUMNS FROM `npc_scale_global_base` LIKE 'zone_id_list'|empty| +9223|2023_03_04_npc_scale_global_base_heroic_strikethrough.sql|SHOW COLUMNS FROM `npc_scale_global_base` LIKE 'heroic_strikethrough'|empty| +9224|2023_03_08_npc_scale_global_base_avoidance.sql|SHOW COLUMNS FROM `npc_scale_global_base` LIKE 'hp_regen_per_second'|empty| +9225|2023_01_21_bots_raid_members.sql|SHOW COLUMNS FROM `raid_members` LIKE 'botid'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/bots/bots_db_update_manifest.txt b/utils/sql/git/bots/bots_db_update_manifest.txt index c67c33969..32191b95a 100644 --- a/utils/sql/git/bots/bots_db_update_manifest.txt +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -35,6 +35,8 @@ 9034|2022_12_02_bot_spell_settings.sql|SHOW COLUMNS FROM `bot_data` LIKE 'enforce_spell_settings'|empty| 9035|2022_12_04_bot_archery.sql|SHOW COLUMNS FROM `bot_data` LIKE 'archery_setting'|empty| 9036|2023_01_19_drop_bot_views.sql|SHOW TABLES LIKE 'vw_groups'|not_empty| +9037|2023_01_22_add_name_index.sql||show index from bot_data WHERE key_name = 'name`|empty| +9038|2023_02_16_add_caster_range.sql|SHOW COLUMNS FROM `bot_data` LIKE 'caster_range'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/bots/required/2023_01_22_add_name_index.sql b/utils/sql/git/bots/required/2023_01_22_add_name_index.sql new file mode 100644 index 000000000..d4e3cca14 --- /dev/null +++ b/utils/sql/git/bots/required/2023_01_22_add_name_index.sql @@ -0,0 +1 @@ +create index `name` on bot_data(`name`); \ No newline at end of file diff --git a/utils/sql/git/bots/required/2023_02_16_add_caster_range.sql b/utils/sql/git/bots/required/2023_02_16_add_caster_range.sql new file mode 100644 index 000000000..0a2946164 --- /dev/null +++ b/utils/sql/git/bots/required/2023_02_16_add_caster_range.sql @@ -0,0 +1,2 @@ +ALTER TABLE `bot_data` +ADD COLUMN `caster_range` INT(11) UNSIGNED NOT NULL DEFAULT '300' AFTER `archery_setting`; \ No newline at end of file diff --git a/utils/sql/git/optional/drakkin_guktan_faction_data.sql b/utils/sql/git/optional/2020_05_25_drakkin_guktan_faction_data.sql similarity index 100% rename from utils/sql/git/optional/drakkin_guktan_faction_data.sql rename to utils/sql/git/optional/2020_05_25_drakkin_guktan_faction_data.sql diff --git a/utils/sql/git/optional/2023_02_17_fix_sseru_mischief_doors.sql b/utils/sql/git/optional/2023_02_17_fix_sseru_mischief_doors.sql new file mode 100644 index 000000000..df765dd91 --- /dev/null +++ b/utils/sql/git/optional/2023_02_17_fix_sseru_mischief_doors.sql @@ -0,0 +1,305 @@ +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8172, 1, 'mischiefplane', 0, 'POMDOOR201', 740.388, -1038.75, 122.85, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8173, 2, 'mischiefplane', 0, 'POMDOOR201', 275.25, -525.013, 145.27, 128, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8174, 3, 'mischiefplane', 0, 'POMDOOR201', 164.949, -553.374, 115.25, 128, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8175, 4, 'mischiefplane', 0, 'POMDOOR201', 55, -950.956, 115.213, 129, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8176, 5, 'mischiefplane', 0, 'POMDOOR201', 251.111, -864.781, 115.123, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8177, 6, 'mischiefplane', 0, 'POMDOOR201', 186.406, -1084.5, 115.345, 257, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8178, 7, 'mischiefplane', 0, 'POMDOOR201', 179.387, -1084.59, 115.345, 256, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8179, 8, 'mischiefplane', 0, 'POMDOOR201', 586.75, 96.25, 144.438, 384, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8180, 9, 'mischiefplane', 0, 'POMDOOR201', 586.75, 105.32, 144.438, 383, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8181, 10, 'mischiefplane', 0, 'POMDOOR201', 345.037, 258.236, 115, 127, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8182, 11, 'mischiefplane', 0, 'POMDOOR201', 359.844, 229.924, 115, 384, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8183, 12, 'mischiefplane', 0, 'POMDOOR201', 59.9314, 110.174, 115.25, 383, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8184, 13, 'mischiefplane', 0, 'POMDOOR201', -20.2295, -385.07, 120, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8185, 14, 'mischiefplane', 0, 'JNTREE104', 1247.1, -404.761, 265.908, 253.4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 77, 335, 170, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8186, 15, 'mischiefplane', 0, 'BRISPORT202', 339.875, -39.4209, 178.09, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8187, 16, 'mischiefplane', 0, 'CHANDALIER200', 222.419, 229.656, 172.19, 375.7, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 77, 335, 170, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8188, 17, 'mischiefplane', 0, 'POMDOOR202', 1525.55, -389.829, -9.90946, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 77, 335, 170, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8189, 18, 'mischiefplane', 0, 'POMDOOR202', 1339.4, -359.905, -9.90946, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 77, 335, 170, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8190, 19, 'mischiefplane', 0, 'POMDOOR202', 1144.7, -252.963, -9.90946, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 77, 335, 170, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8191, 20, 'mischiefplane', 0, 'POMDOOR202', 1139.4, -176.89, -9.92395, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 77, 335, 170, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8192, 21, 'mischiefplane', 0, 'POMDOOR202', 1309.52, -49.9891, -9.92395, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 77, 335, 170, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8193, 22, 'mischiefplane', 0, 'POMDOOR202', 1469.62, -169.907, -9.97395, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 77, 335, 170, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8194, 23, 'mischiefplane', 0, 'POMDOOR201', 1320.52, 227.861, -9.99347, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 77, 335, 170, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8195, 24, 'mischiefplane', 0, 'POMDOOR200', 646.5, -152.867, 174.94, 255.66, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8196, 25, 'mischiefplane', 0, 'POMDOOR200', 646.5, -132.942, 174.94, 257.34, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8197, 26, 'mischiefplane', 0, 'POMDOOR200', 661.813, -86.6188, 174.94, 130.14, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 760, 175, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8198, 27, 'mischiefplane', 0, 'POMDOOR200', 646.5, -112.935, 174.94, 255.96, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 128, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8199, 28, 'mischiefplane', 0, 'POMDOOR200', 681.75, -86.5188, 174.94, 128.1, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8200, 29, 'mischiefplane', 0, 'POMDOOR200', 801.734, -111.417, 114.971, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8201, 30, 'mischiefplane', 0, 'POMDOOR200', 911.08, -362.772, 114.971, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8202, 31, 'mischiefplane', 0, 'POMDOOR200', 727.611, -688.413, 114.971, 385.36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8203, 32, 'mischiefplane', 0, 'POMTORCH200', 722.153, -670.469, 123.221, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8204, 33, 'mischiefplane', 0, 'POMTORCH200', 467.527, -1138.68, 123.121, 256, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8205, 34, 'mischiefplane', 0, 'POMDOOR200', 392.808, -1128.09, 114.971, 384, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8206, 35, 'mischiefplane', 0, 'BRISPORT202', 629.286, 179.871, 181.94, 127.52, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8207, 36, 'mischiefplane', 0, 'POMDOOR203', 1379.88, -950.369, -9.99143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8208, 37, 'mischiefplane', 0, 'POMDOOR203', 1709.04, -989.59, -9.99143, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8209, 38, 'mischiefplane', 0, 'POMDOOR203', 1734.37, -1335.35, -9.92482, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8210, 39, 'mischiefplane', 0, 'POMDOOR201', 1341.19, 6.90461, -9.99347, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8211, 40, 'mischiefplane', 0, 'POMDOOR201', 1466.28, -7.96457, -9.99347, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8212, 41, 'mischiefplane', 0, 'POMDOOR200', 521.813, -93.3971, 180.924, 128, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8213, 42, 'mischiefplane', 0, 'POMDOOR206', 302.132, -155.263, 168.001, 256, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8214, 43, 'mischiefplane', 0, 'POMDOOR200', 86.6493, -2.00653, 179.89, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8215, 44, 'mischiefplane', 0, 'POMDOOR200', 102.875, 213.431, 179.89, 383.78, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8216, 45, 'mischiefplane', 0, 'POMDOOR205', 143.631, 262.86, 179.879, 0.560303, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8217, 46, 'mischiefplane', 0, 'BRISPORT202', 159.888, 257.147, 170.039, 256, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 114, 230, 175, 135, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8218, 47, 'mischiefplane', 0, 'POMDOOR200', 328.905, -923.639, 114.971, 1.32091, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 114, 230, 175, 135, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8219, 48, 'mischiefplane', 0, 'POMDOOR205', 706.73, 116.494, 143.982, 128, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 114, 230, 175, 135, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8220, 49, 'mischiefplane', 0, 'KNBOOKC101', 727.26, 71.9691, 143.955, 384, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8221, 50, 'mischiefplane', 0, 'POMDOOR200', 706.719, 208.406, 143.944, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8222, 51, 'mischiefplane', 0, 'KNBOOKC101', 735.469, 252.906, 143.944, 128, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 128, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8223, 52, 'mischiefplane', 0, 'KNBOOKC101', 509.329, 7.01836, 174.94, 384, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -6, 83, 115, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8224, 53, 'mischiefplane', 0, 'POMDOOR200', 539.287, 22.9663, 174.94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -6, 83, 115, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8225, 54, 'mischiefplane', 0, 'POMDOOR205', 661.771, 296.36, 174.94, 128, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -6, 83, 115, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8226, 55, 'mischiefplane', 0, 'POMTORCH200', -0.914244, -467.462, 152.996, 384, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -6, 83, 115, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8227, 56, 'mischiefplane', 0, 'POMDOOR200', -18.481, -472.763, 144.946, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -6, 83, 115, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8228, 57, 'mischiefplane', 0, 'POMDOOR200', -16.4709, -311.962, 144.946, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -6, 83, 115, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8229, 58, 'mischiefplane', 0, 'POMDOOR200', 91.9687, 213.388, 114.971, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8230, 59, 'mischiefplane', 0, 'POMDOOR200', 141.554, -1122.54, 114.971, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -6, 83, 115, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8231, 60, 'mischiefplane', 0, 'POMDOOR200', 102.898, -1073.09, 114.971, 384, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -6, 83, 115, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8232, 61, 'mischiefplane', 0, 'POMDOOR200', 201.988, -1106.12, 114.971, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -6, 83, 115, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8233, 62, 'mischiefplane', 0, 'POMDOOR200', 212.827, -1128.02, 114.971, 383.66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -6, 83, 115, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8234, 63, 'mischiefplane', 0, 'POMDOOR200', 108.481, -0.034598, 114.971, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -6, 83, 115, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8235, 64, 'mischiefplane', 0, 'POMTORCH200', 45.9188, 162.501, 122.571, 128, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -6, 83, 115, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8236, 65, 'mischiefplane', 0, 'POMDOOR200', 137.03, 173.493, 94.9707, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -6, 83, 115, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8237, 66, 'mischiefplane', 0, 'POMDOOR200', 86.4347, 156.952, 114.971, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -6, 83, 115, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8238, 67, 'mischiefplane', 0, 'POMTORCH200', 90.8187, 134.949, 122.721, 128, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -6, 83, 115, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8239, 68, 'mischiefplane', 0, 'POMTORCH200', 90.8688, 189.354, 122.721, 128, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8240, 69, 'mischiefplane', 0, 'POMTORCH200', 114.451, 240.787, 121.971, 317, 59, 0, 0, 0, 0, 0, 0, 0, 0, 1, 'mischiefplane', 0, -6, 83, 115, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8241, 70, 'mischiefplane', 0, 'POMDOOR200', 143.387, 262.861, 114.971, 0.719619, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -6, 83, 115, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8242, 71, 'mischiefplane', 0, 'BOOKREG200', 286.381, 78.2721, 119.573, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -6, 83, 115, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8243, 72, 'mischiefplane', 0, 'POMDOOR200', 148.406, 82.9282, 114.971, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -6, 83, 115, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8244, 73, 'mischiefplane', 0, 'POMDOOR200', 17.2007, -277.04, 144.951, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -6, 83, 115, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8245, 74, 'mischiefplane', 0, 'POMTORCH200', 642.535, 314.025, 182.94, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -6, 83, 115, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8246, 75, 'mischiefplane', 0, 'BRISPORT202', 660.344, 267.579, 177.69, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -6, 83, 115, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8247, 76, 'mischiefplane', 0, 'BRISPORT202', 439.912, 304.528, 178.94, 259.58, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -6, 83, 115, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8248, 77, 'mischiefplane', 0, 'KNBOOKC101', 441.923, 267.972, 174.94, 256, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8249, 78, 'mischiefplane', 0, 'POMTORCH200', 740.009, 114.144, 151.871, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -6, 83, 115, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8250, 79, 'mischiefplane', 0, 'POMTHRONE200', 820.064, -820.657, 125.006, 384, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 421, 1428, -5, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8251, 80, 'mischiefplane', 0, 'POMTHRONE200', 819.985, -1098.55, 125.009, 128, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 77, 335, 170, 66, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8252, 81, 'mischiefplane', 0, 'POMDOOR205', 226.927, 108.624, 186.89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 421, 1428, -5, 66, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8253, 82, 'mischiefplane', 0, 'BRISPORT202', 734.419, 269.856, 146.644, 128, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 114, 712, 147, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8254, 83, 'mischiefplane', 0, 'POMDOOR205', 536.231, 312.847, 174.94, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 114, 712, 147, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8255, 84, 'mischiefplane', 0, 'POMDOOR200', 641.779, 113.463, 174.94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 114, 712, 147, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8256, 85, 'mischiefplane', 0, 'POMDOOR200', 412.76, -146.571, 180.89, 382.88, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 114, 712, 147, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8257, 86, 'mischiefplane', 0, 'POMDOOR200', 216.942, 295.666, 186.89, 128.319, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 114, 712, 147, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8258, 87, 'mischiefplane', 0, 'POMDOOR200', 229.889, 168.497, 184.89, 384, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 114, 712, 147, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8259, 88, 'mischiefplane', 0, 'POMDOOR201', 1428.14, 141.957, -9.99198, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 114, 712, 147, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8260, 89, 'mischiefplane', 0, 'POMDOOR200', 108.367, -649.859, 114.971, 0.139709, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 114, 712, 147, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8261, 90, 'mischiefplane', 0, 'POMDOOR205', 177.857, -505.792, 144.971, 384, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 114, 712, 147, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8262, 91, 'mischiefplane', 0, 'POMDOOR200', 17.0805, -505.666, 144.971, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 114, 712, 147, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8263, 92, 'mischiefplane', 0, 'POMDOOR205', 86.3992, -649.932, 114.971, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 114, 712, 147, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8264, 93, 'mischiefplane', 0, 'POMDOOR200', 86.4089, -839.605, 114.971, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 114, 712, 147, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8265, 94, 'mischiefplane', 0, 'POMDOOR200', 173.432, -911.68, 114.971, 0.659769, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 114, 712, 147, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8266, 95, 'mischiefplane', 0, 'POMDOOR200', 223.526, -866.734, 114.971, 2.50012, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 114, 712, 147, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8267, 96, 'mischiefplane', 0, 'POMDOOR200', 141.386, -877.641, 114.971, 254.92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 114, 712, 147, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8268, 97, 'mischiefplane', 0, 'POMDOOR200', 222.369, -967.522, 114.971, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 114, 712, 147, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8269, 98, 'mischiefplane', 0, 'SLTOME200', 722.469, -732.545, 114.971, 384, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 114, 712, 147, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8270, 99, 'mischiefplane', 0, 'POMDOOR205', 911.12, -282.074, 114.971, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 114, 712, 147, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8271, 100, 'mischiefplane', 0, 'POMDOOR200', 541.785, -66.5416, 114.971, 128.58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 114, 712, 147, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8272, 101, 'mischiefplane', 0, 'POMDOOR205', 541.852, -88.1934, 114.971, 128, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 114, 712, 147, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8273, 102, 'mischiefplane', 0, 'DOOR2', 336.946, -327.68, 70.0768, 128, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 114, 712, 147, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8274, 103, 'mischiefplane', 0, 'POMDOOR200', 672.691, -168.587, 174.94, 384.68, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 128, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8275, 104, 'mischiefplane', 0, 'POMDOOR200', 692.703, -168.538, 174.94, 384, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8276, 105, 'mischiefplane', 0, 'POMDOOR200', 712.646, -168.548, 174.94, 384, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8277, 106, 'mischiefplane', 0, 'POMDOOR200', 728.545, -121.971, 174.94, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 128, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8278, 107, 'mischiefplane', 0, 'POMDOOR200', 728.526, -142.028, 174.94, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8279, 108, 'mischiefplane', 0, 'POMDOOR200', 728.469, -102.029, 174.94, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8280, 109, 'mischiefplane', 0, 'POMDOOR200', 701.777, -86.4187, 174.94, 128, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8281, 110, 'mischiefplane', 0, 'BRISPORT202', 754.738, -127.791, 177.84, 255, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -390, 95, 120, 254, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8282, 111, 'mischiefplane', 0, 'POMDOOR201', 828.597, -119.978, 174.94, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 128, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8283, 112, 'mischiefplane', 0, 'POMDOOR200', 322.83, 246.447, 114.971, 384, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 128, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8284, 113, 'mischiefplane', 0, 'POMDOOR205', 322.868, 268.328, 114.971, 256, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 128, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8285, 114, 'mischiefplane', 0, 'POMDOOR204', 1425.4, 262.936, -9.94849, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 128, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8286, 115, 'mischiefplane', 0, 'POMDOOR204', 1383.55, 270.848, -9.94849, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 128, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8287, 116, 'mischiefplane', 0, 'POMDOOR204', 1340.3, 293.837, -9.99071, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 128, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8288, 117, 'mischiefplane', 0, 'POMDOOR204', 1329.41, 325.914, -9.89849, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 128, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8289, 118, 'mischiefplane', 0, 'POMDOOR204', 1366.61, 356.846, -9.94849, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 128, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8290, 119, 'mischiefplane', 0, 'POMDOOR204', 1402.48, 325.893, -9.94849, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 128, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8291, 120, 'mischiefplane', 0, 'POMDOOR204', 1413.37, 375.882, -9.94749, 384, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 128, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8292, 121, 'mischiefplane', 0, 'POMDOOR201', 1208.34, 142.944, -9.93711, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 128, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8293, 122, 'mischiefplane', 0, 'POMDOOR201', 1211.62, 77.9356, -9.99347, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 128, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8294, 123, 'mischiefplane', 0, 'POMDOOR203', 1529.23, -649.707, -9.93114, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 128, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8295, 124, 'mischiefplane', 0, 'POMDOOR203', 1260.08, -429.852, -9.94143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 128, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8296, 125, 'mischiefplane', 0, 'POMDOOR203', 969.362, -659.699, -9.99144, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 128, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8297, 126, 'mischiefplane', 0, 'POMDOOR203', 1040.18, -759.705, -9.94143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 128, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8298, 127, 'mischiefplane', 0, 'POMDOOR203', 1734.32, -734.62, -9.89143, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 128, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8299, 128, 'mischiefplane', 0, 'PURPTREE200', -1017, -353.7, 91.0007, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'cobaltscar', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8300, 129, 'mischiefplane', 0, 'BRISPORT202', 62.75, -186.838, 117.871, 384.52, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -6, 83, 115, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8301, 130, 'mischiefplane', 0, 'POMTORCH200', 40.9188, -27.6989, 123.027, 128, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -180, 112, 115, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8302, 131, 'mischiefplane', 0, 'ERPLANT4', 152.073, -155, 118.477, 128, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -415, 1520, 270, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8303, 132, 'mischiefplane', 0, 'BRISPORT202', 132.763, -186.894, 117.821, 384, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -180, 80, 115, 255, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8304, 133, 'mischiefplane', 0, 'BOOKREG200', 231.655, -114.504, 119.161, 170, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -930, 280, 115, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8305, 134, 'mischiefplane', 0, 'POMTORCH200', 270.806, -929.962, 123.121, 128, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -390, 95, 120, 254, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8306, 135, 'mischiefplane', 0, 'BOOKREG200', 44.1068, -826.02, 119.062, 256, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 290, 390, 120, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8307, 136, 'mischiefplane', 0, 'ERPLANT3', 1443.14, 398.661, -9.96472, 128, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -390, 95, 120, 254, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8308, 137, 'mischiefplane', 0, 'BRISPORT200', 1901.65, -469.719, 0.108568, 58, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -127, 687, 175, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8309, 138, 'mischiefplane', 0, 'POMCHESS201', 681.312, 150.524, 179.245, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -960, 620, 125, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8310, 139, 'mischiefplane', 0, 'JNTREE104', 1465.13, -399.466, 270.658, 384, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -930, 95, 120, 254, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8311, 140, 'mischiefplane', 0, '0', 97.5, 215, 118, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 220.5, 97.5, 116.8, 128, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8312, 141, 'mischiefplane', 0, 'DOOR2', 402.292, -386.971, 69.9768, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -930, 95, 120, 254, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8313, 142, 'mischiefplane', 0, 'POMDOOR201', 453.456, -89.7571, 115.414, 256, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -930, 95, 120, 254, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8314, 143, 'mischiefplane', 0, '0', 175, 142.5, 98.1, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 175, 142.5, 98.1, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8315, 144, 'mischiefplane', 0, '0', 89.3, 162.5, 116.8, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 162.5, 79, 116.8, 128, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8316, 145, 'mischiefplane', 0, 'POMDOOR201', 495, -749.75, 115.47, 128, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -930, 95, 120, 254, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8317, 146, 'mischiefplane', 0, 'POMDOOR201', 495.002, -754.911, 115.47, 129, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -930, 95, 120, 254, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8318, 147, 'mischiefplane', 0, 'POMDOOR201', 54.9901, -943.455, 115.22, 128, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -930, 95, 120, 254, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8319, 148, 'mischiefplane', 0, '0', 140, 257, 116.8, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 140, 257, 116.8, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8320, 149, 'mischiefplane', 0, 'POMDOOR201', 165.032, -544.538, 115.22, 128, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -930, 95, 120, 254, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8321, 150, 'mischiefplane', 0, '0', 145.5, 77, 116.8, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, 77, 155, 116.8, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8322, 151, 'mischiefplane', 0, 'POMDOOR201', 758.963, -1021.2, 119.832, 384, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'mischiefplane', 0, -930, 95, 120, 254, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8991, 201, 'sseru', 0, 'SERUDOOR302', -15.9808, -757.201, 154.002, 128, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8992, 200, 'sseru', 0, 'SERUDOOR302', -111.02, -757.215, 154.002, 128, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8993, 173, 'sseru', 0, 'SERUDOOR302', -523.317, -232.025, 90.002, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8994, 172, 'sseru', 0, 'SERUDOOR302', -567.071, -156.991, 90.002, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8995, 171, 'sseru', 0, 'SERUDOOR302', -296.986, -283.013, 90.002, 256, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8996, 170, 'sseru', 0, 'SERUDOOR302', -297.171, -185.012, 90.002, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8997, 166, 'sseru', 0, 'COMDOOR301', -267.957, -231.624, 56.002, 256, 57, 0, 0, 0, 0, 0, 0, 0, 0, 165, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8998, 161, 'sseru', 0, 'SERUDOOR302', -912.036, -542.11, 84.002, 128, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (8999, 160, 'sseru', 0, 'SERUDOOR302', -864.005, -509.079, 96.002, 128.389, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9000, 159, 'sseru', 0, 'SERUDOOR302', -815.999, -541.981, 84.002, 128, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9001, 158, 'sseru', 0, 'SERUDOOR302', -742.169, -615.992, 84.002, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9002, 157, 'sseru', 0, 'SERUDOOR302', -710.085, -663.999, 96.002, 0.111912, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9003, 156, 'sseru', 0, 'SERUDOOR302', -742.153, -711.976, 84.002, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9004, 147, 'sseru', 0, 'SERUDOOR302', -956.858, -552.955, 154.002, 256, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9005, 146, 'sseru', 0, 'SERUDOOR302', -956.933, -648.03, 154.002, 256, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9006, 145, 'sseru', 0, 'SERUDOOR302', -891.056, -690.999, 154.002, 65.9524, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9007, 144, 'sseru', 0, 'SERUDOOR302', -957.093, -757.066, 154.002, 64.6327, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9008, 143, 'sseru', 0, 'SERUDOOR302', -847.954, -756.849, 154.002, 384, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9009, 142, 'sseru', 0, 'SERUDOOR302', -752.965, -757.148, 154.002, 127.755, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9010, 141, 'sseru', 0, 'SERUDOOR302', -431.994, -358.428, 190.002, 128, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9011, 140, 'sseru', 0, 'SERUDOOR302', -305.977, -231.995, 190.002, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9012, 139, 'sseru', 0, 'SERUDOOR302', -558.09, -231.986, 190.002, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9013, 138, 'sseru', 0, 'SERUDOOR302', -431.961, -105.998, 190.002, 384, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9014, 136, 'sseru', 0, 'SERUDOOR302', -956.795, 89.0354, 154.002, 256, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9015, 135, 'sseru', 0, 'SERUDOOR302', -956.992, 184.017, 154.002, 256, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9016, 134, 'sseru', 0, 'SERUDOOR302', -891.163, 227.155, 154.002, 448.503, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9017, 133, 'sseru', 0, 'SERUDOOR302', -957.148, 293.018, 154.002, 448.484, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9018, 132, 'sseru', 0, 'SERUDOOR302', -847.971, 292.823, 154.002, 128.065, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9019, 131, 'sseru', 0, 'SERUDOOR302', -752.927, 292.931, 154.002, 128.967, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9020, 130, 'sseru', 0, 'SERUDOOR302', -960.042, 121.251, 119.002, 384, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9021, 129, 'sseru', 0, 'SERUDOOR302', -833.175, 106.981, 119.002, 256, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9022, 128, 'sseru', 0, 'SERUDOOR302', -770.992, 169.155, 119.002, 384, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9023, 127, 'sseru', 0, 'SERUDOOR302', -786.013, 296.006, 119.002, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9024, 126, 'sseru', 0, 'SERUDOOR302', -710.253, 200.022, 96.002, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9025, 125, 'sseru', 0, 'SERUDOOR302', -742.018, 247.98, 84.002, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9026, 124, 'sseru', 0, 'SERUDOOR302', -741.935, 152.004, 84.002, 256, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9027, 123, 'sseru', 0, 'SERUDOOR302', -863.988, 45.1296, 96.002, 384, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9028, 120, 'sseru', 0, 'SERUDOOR302', -760.06, 325.958, 56.002, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9029, 119, 'sseru', 0, 'SERUDOOR302', -760.249, 261.986, 56.002, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9030, 118, 'sseru', 0, 'SERUDOOR302', -770.95, 227.895, 55.992, 128, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9031, 117, 'sseru', 0, 'SERUDOOR302', -812.193, 200.017, 56.002, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9032, 116, 'sseru', 0, 'SERUDOOR302', -987.98, 95.9949, 56.002, 384, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9033, 115, 'sseru', 0, 'SERUDOOR302', -923.965, 96.2348, 56.002, 384, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9034, 114, 'sseru', 0, 'SERUDOOR302', -890.082, 107.059, 56.002, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9035, 113, 'sseru', 0, 'SERUDOOR302', -862.018, 150.108, 56.002, 384, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9036, 102, 'sseru', 0, 'SERUDOOR302', 0.022436, 45.8475, 96.002, 384, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9037, 101, 'sseru', 0, 'SERUDOOR302', -154.912, 199.937, 96.002, 256, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9038, 96, 'sseru', 0, 'SERUDOOR302', -103.93, 259.994, 56.002, 256, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9039, 95, 'sseru', 0, 'SERUDOOR302', -103.749, 324.049, 56.002, 256, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9040, 94, 'sseru', 0, 'SERUDOOR302', -92.9568, 225.751, 56.002, 128, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9041, 93, 'sseru', 0, 'SERUDOOR302', -49.9018, 198.029, 56.002, 256, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9042, 92, 'sseru', 0, 'SERUDOOR302', 126.053, 95.8086, 56.002, 128, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9043, 91, 'sseru', 0, 'SERUDOOR302', 61.9644, 96.2242, 56.002, 384, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9044, 90, 'sseru', 0, 'SERUDOOR302', 27.8566, 106.989, 56.002, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9045, 89, 'sseru', 0, 'SERUDOOR302', 0.009796, 147.885, 56.002, 384, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9046, 86, 'sseru', 0, 'SERUDOOR302', 93.0613, -757.016, 154.002, 448.957, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9047, 85, 'sseru', 0, 'SERUDOOR302', 26.947, -690.899, 154.002, 448.879, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9048, 82, 'sseru', 0, 'SERUDOOR302', 61.9842, -560.087, 56.002, 384, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9049, 81, 'sseru', 0, 'SERUDOOR302', 126.025, -559.939, 56.002, 384, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9050, 80, 'sseru', 0, 'SERUDOOR302', -93.0699, -689.947, 56.002, 128, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9051, 79, 'sseru', 0, 'SERUDOOR302', -103.883, -724.005, 56.002, 253.882, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9052, 78, 'sseru', 0, 'SERUDOOR302', -103.913, -788.008, 56.002, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9053, 72, 'sseru', 0, 'SERUDOOR302', -155.042, -663.956, 96.002, 256, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9054, 71, 'sseru', 0, 'SERUDOOR302', -122.038, -711.849, 83.902, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9055, 70, 'sseru', 0, 'SERUDOOR302', -122.004, -615.992, 83.902, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9056, 69, 'sseru', 0, 'SERUDOOR302', 0.082713, -509.908, 96.002, 384, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9057, 68, 'sseru', 0, 'SERUDOOR302', -47.9142, -542.027, 84.002, 384, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9058, 67, 'sseru', 0, 'SERUDOOR302', 47.9787, -541.984, 83.752, 384, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9059, 47, 'sseru', 0, 'CRATEG', -1500.5, 105.226, -54.348, 1.21634, 53, 0, 0, 0, 0, 0, 0, 0, 1, 110, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9060, 45, 'sseru', 0, 'CRATEG', -1500.54, 271.021, -54.248, 0.898787, 53, 0, 0, 0, 0, 0, 0, 0, 1, 110, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9061, 46, 'sseru', 0, 'CRATEG', -1547.51, 270.872, -54.248, 256.497, 53, 0, 0, 0, 0, 0, 0, 0, 1, 110, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9062, 48, 'sseru', 0, 'CRATEG', -1547.49, 105.022, -54.348, 259.896, 53, 0, 0, 0, 0, 0, 0, 0, 1, 110, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9063, 73, 'sseru', 0, 'SERUDOOR302', 96.0841, -586.038, 119.002, 384, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9064, 74, 'sseru', 0, 'SERUDOOR302', -30.9845, -571.021, 119.002, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9065, 75, 'sseru', 0, 'SERUDOOR302', -93.0769, -633.045, 119.002, 384, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9066, 76, 'sseru', 0, 'SERUDOOR302', -78.8788, -759.968, 119.002, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9067, 77, 'sseru', 0, 'SERUDOOR302', -50.4212, -662.019, 56.002, 256, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9068, 83, 'sseru', 0, 'SERUDOOR302', 27.9427, -571.011, 56.002, 256, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9069, 84, 'sseru', 0, 'SERUDOOR302', -0.062209, -611.915, 56.002, 128, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9070, 87, 'sseru', 0, 'SERUDOOR302', 92.9006, -553.001, 154.002, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9071, 88, 'sseru', 0, 'SERUDOOR302', 92.9937, -647.944, 154.002, 256, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9072, 97, 'sseru', 0, 'SERUDOOR302', -122.113, 247.959, 84.002, 256, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9073, 98, 'sseru', 0, 'SERUDOOR302', -122.123, 151.892, 84.002, 256, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9074, 99, 'sseru', 0, 'SERUDOOR302', -47.9979, 78.125, 84.002, 384, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9075, 100, 'sseru', 0, 'SERUDOOR302', 48.0357, 78.2125, 84.002, 384, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9076, 103, 'sseru', 0, 'SERUDOOR302', -78.8239, 295.994, 119.002, 256, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9077, 104, 'sseru', 0, 'SERUDOOR302', -92.9716, 169.007, 119.002, 384, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9078, 105, 'sseru', 0, 'SERUDOOR302', -30.7422, 107.042, 119.002, 256, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9079, 106, 'sseru', 0, 'SERUDOOR302', 96.0255, 122.229, 119.002, 384, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9080, 107, 'sseru', 0, 'SERUDOOR302', 27.1106, 227.109, 154.002, 319.56, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9081, 108, 'sseru', 0, 'SERUDOOR302', 93.1498, 293.131, 154.002, 320, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9082, 109, 'sseru', 0, 'SERUDOOR302', -16.1129, 292.901, 154.002, 128, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9083, 110, 'sseru', 0, 'SERUDOOR302', -111.044, 292.788, 154.002, 128, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9084, 111, 'sseru', 0, 'SERUDOOR302', 92.8211, 183.959, 154.002, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9085, 112, 'sseru', 0, 'SERUDOOR302', 92.9013, 89.0085, 154.002, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9086, 121, 'sseru', 0, 'SERUDOOR302', -911.996, 78.0958, 84.002, 128, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9087, 122, 'sseru', 0, 'SERUDOOR302', -816.049, 77.947, 84.002, 128, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9088, 148, 'sseru', 0, 'SERUDOOR302', -811.776, -664.009, 56.002, 256.139, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9089, 149, 'sseru', 0, 'SERUDOOR302', -770.962, -691.887, 56.002, 384, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9090, 150, 'sseru', 0, 'SERUDOOR302', -760.124, -725.947, 56.002, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9091, 151, 'sseru', 0, 'SERUDOOR302', -760.244, -789.964, 56.002, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9092, 152, 'sseru', 0, 'SERUDOOR302', -862.034, -614.384, 56.002, 128.335, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9093, 153, 'sseru', 0, 'SERUDOOR302', -890.186, -570.982, 56.002, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9094, 154, 'sseru', 0, 'SERUDOOR302', -924.007, -559.715, 56.002, 384, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9095, 155, 'sseru', 0, 'SERUDOOR302', -988, -560.085, 56.002, 128, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9096, 167, 'sseru', 0, 'SERUDOOR302', -373.001, -97.3237, 90.002, 128.833, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9097, 168, 'sseru', 0, 'SERUDOOR302', -567.044, -306.939, 90.002, 0.490723, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9098, 169, 'sseru', 0, 'SERUDOOR302', -373.029, -367.273, 90.002, 128, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9099, 174, 'sseru', 0, 'SERUDOOR302', -960.037, -584.608, 119.002, 384, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9100, 175, 'sseru', 0, 'SERUDOOR302', -833.213, -571.067, 119.002, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9101, 176, 'sseru', 0, 'SERUDOOR302', -770.976, -632.877, 119.002, 384.439, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9102, 177, 'sseru', 0, 'SERUDOOR302', -786.041, -759.979, 119.002, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 10, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9103, 178, 'sseru', 0, 'SERUJAIL301', -1724.05, 188.906, -72.098, 0, 76, 0, 0, 0, 0, 0, 0, 0, 0, 16, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9104, 179, 'sseru', 0, 'SERUJAIL302', -1708.03, 265.331, -71.998, 128, 76, 0, 0, 0, 0, 0, 0, 0, 0, 9, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9105, 180, 'sseru', 0, 'SERUJAIL302', -1652.83, 265.765, -71.998, 384, 76, 0, 0, 0, 0, 0, 0, 0, 0, 9, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9106, 181, 'sseru', 0, 'SERUJAIL302', -1708.83, 107.926, -71.998, 384, 76, 0, 0, 0, 0, 0, 0, 0, 0, 9, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9107, 182, 'sseru', 0, 'SERUJAIL302', -1652.13, 108.189, -71.998, 128, 76, 0, 0, 0, 0, 0, 0, 0, 0, 9, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9108, 184, 'sseru', 0, 'SERUJAIL301', -1724.03, -647.33, -71.998, 256.885, 76, 0, 0, 0, 0, 0, 0, 0, 0, 16, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9109, 185, 'sseru', 0, 'SERUJAIL302', -1708.05, -567.967, -71.998, 129.092, 76, 0, 0, 0, 0, 0, 0, 0, 0, 9, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9110, 186, 'sseru', 0, 'SERUJAIL302', -1651.99, -567.816, -71.998, 128.411, 76, 0, 0, 0, 0, 0, 0, 0, 0, 9, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9111, 187, 'sseru', 0, 'SERUJAIL302', -1707.99, -725.943, -71.998, 384.31, 76, 0, 0, 0, 0, 0, 0, 0, 0, 9, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9112, 188, 'sseru', 0, 'SERUJAIL302', -1651.92, -726.063, -71.998, 384.769, 76, 0, 0, 0, 0, 0, 0, 0, 0, 9, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9113, 190, 'sseru', 0, 'MGLYPH301', 1029.25, -330.186, 64.002, 384, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'sseru', 0, -447, 1016, 225, 249, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9114, 189, 'sseru', 0, 'MGLYPH301', 1029.07, -132.984, 64.002, 128, 58, 0, 0, 0, 0, 0, 0, 0, 0, 188, 'sseru', 0, -12, 1017, 225, 248, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9115, 193, 'sseru', 0, 'MGLYPH301', -145.971, 179.059, 121.502, 384, 58, 0, 0, 0, 0, 0, 0, 0, 0, 192, 'sseru', 0, 64, 82, 157, 120, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9116, 192, 'sseru', 0, 'MGLYPH301', -21.0324, 54.0964, 121.502, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 191, 'sseru', 0, 281, -137, 157, 252, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9117, 195, 'sseru', 0, 'MGLYPH301', 81.8796, 53.3392, 156.502, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 194, 'sseru', 0, 179, -132, 122, 247, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9118, 194, 'sseru', 0, 'MGLYPH301', -148.124, 281.138, 156.252, 384, 58, 0, 0, 0, 0, 0, 0, 0, 0, 193, 'sseru', 0, 65, -22, 122, 124, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9119, 197, 'sseru', 0, 'MGLYPH301', -20.8551, -517.956, 121.502, 256, 58, 0, 0, 0, 0, 0, 0, 0, 0, 196, 'sseru', 0, -526, 82, 157, 119, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9120, 196, 'sseru', 0, 'MGLYPH301', -145.812, -642.949, 121.517, 384, 58, 0, 0, 0, 0, 0, 0, 0, 0, 195, 'sseru', 0, -743, -132, 157, 3, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9121, 198, 'sseru', 0, 'MGLYPH301', 82.0349, -516.532, 156.252, 256, 58, 0, 0, 0, 0, 0, 0, 0, 0, 197, 'sseru', 0, -533, -17, 122, 128, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9122, 199, 'sseru', 0, 'MGLYPH301', -147.752, -744.875, 156.502, 384, 58, 0, 0, 0, 0, 0, 0, 0, 0, 198, 'sseru', 0, -642, -134, 122, 252, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9123, 203, 'sseru', 0, 'MGLYPH301', -843.229, 54.0784, 121.252, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 202, 'sseru', 0, 65, -947, 157, 132, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9124, 202, 'sseru', 0, 'MGLYPH301', -718.861, 178.99, 121.502, 128, 58, 0, 0, 0, 0, 0, 0, 0, 0, 201, 'sseru', 0, 280, -730, 157, 3, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9125, 204, 'sseru', 0, 'MGLYPH301', -945.492, 52.1604, 156.502, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 203, 'sseru', 0, 66, -844, 122, 127, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9126, 205, 'sseru', 0, 'MGLYPH301', -717.612, 281.353, 156.686, 128, 58, 0, 0, 0, 0, 0, 0, 0, 0, 204, 'sseru', 0, 179, -730, 122, 254, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9127, 207, 'sseru', 0, 'MGLYPH301', -718.314, -643.055, 121.502, 128, 58, 0, 0, 0, 0, 0, 0, 0, 0, 206, 'sseru', 0, -745, -729, 158, 247, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9128, 206, 'sseru', 0, 'MGLYPH301', -843.04, -518.122, 121.452, 256, 58, 0, 0, 0, 0, 0, 0, 0, 0, 205, 'sseru', 0, -528, -944, 157, 122, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9129, 208, 'sseru', 0, 'MGLYPH301', -716.189, -745.05, 156.502, 128, 58, 0, 0, 0, 0, 0, 0, 0, 0, 207, 'sseru', 0, -643, -730, 122, 247, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9130, 209, 'sseru', 0, 'MGLYPH301', -945.518, -517.086, 156.719, 256, 58, 0, 0, 0, 0, 0, 0, 0, 0, 208, 'sseru', 0, -531, -843, 122, 120, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9131, 214, 'sseru', 0, 'MGLYPH301', 1001.13, -448.291, 225.502, 384, 58, 0, 0, 0, 0, 0, 0, 0, 0, 213, 'sseru', 0, -330, 966, 59.1, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9132, 213, 'sseru', 0, 'MGLYPH301', 1001.11, -13.1465, 225.562, 384, 58, 0, 0, 0, 0, 0, 0, 0, 0, 212, 'sseru', 0, -133, 995, 59, 246, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9133, 212, 'sseru', 0, 'MGLYPH301', -281.973, -232.013, 192.752, 128, 58, 0, 0, 0, 0, 0, 0, 0, 0, 211, 'sseru', 0, 367, 1148, 59, 121, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9134, 211, 'sseru', 0, 'MGLYPH301', -581.038, -82.9619, 129.002, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 210, 'sseru', 0, -92, -579, 193, 253, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9135, 210, 'sseru', 0, 'MGLYPH301', -580.881, -231.9, 93.1596, 384, 58, 0, 0, 0, 0, 0, 0, 0, 0, 209, 'sseru', 0, -372, -282, 130, 124, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9136, 217, 'sseru', 0, 'SERUJAIL302', -524.18, -286.177, 90.002, 254.136, 54, 0, 0, 0, 0, 0, 0, 0, 0, -1, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9137, 218, 'sseru', 0, 'SERUJAIL302', -524.75, -284.874, 100.002, 4.82398, 54, 0, 0, 0, 0, 0, 0, 0, 0, -1, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9138, 222, 'sseru', 0, 'MGLYPH301', -499.26, -287.825, 90.002, 208, 54, 0, 0, 0, 0, 0, 0, 0, 0, -1, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9139, 227, 'sseru', 0, 'MGLYPH301', -499.378, -287.808, 99.752, 461, 54, 0, 0, 0, 0, 0, 0, 0, 0, -1, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9140, 10, 'sseru', 0, 'SSERUPL404', -2046, -232, 2, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, -1, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9141, 9, 'sseru', 0, 'SSERUPL400', -2044, 967, 56, 256, 54, 0, 0, 0, 0, 0, 0, 0, 0, -1, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9142, 8, 'sseru', 0, 'SSERUPL401', -1522.01, 1016, 52.5, 256, 54, 0, 0, 0, 0, 0, 0, 0, 0, -1, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9143, 7, 'sseru', 0, 'SSERUPL403', -424, 754, 56, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, -1, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); +REPLACE INTO `doors` (`id`, `doorid`, `zone`, `version`, `name`, `pos_y`, `pos_x`, `pos_z`, `heading`, `opentype`, `guild`, `lockpick`, `keyitem`, `nokeyring`, `triggerdoor`, `triggertype`, `disable_timer`, `doorisopen`, `door_param`, `dest_zone`, `dest_instance`, `dest_x`, `dest_y`, `dest_z`, `dest_heading`, `invert_state`, `incline`, `size`, `buffer`, `client_version_mask`, `is_ldon_door`, `dz_switch_id`, `min_expansion`, `max_expansion`, `content_flags`, `content_flags_disabled`) VALUES (9144, 4, 'sseru', 0, 'SSERUPL402', 560.038, -231.998, 52.006, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, -1, 'NONE', 0, 0, 0, 0, 0, 0, 0, 100, 0, 4294967295, 0, 0, -1, -1, NULL, NULL); diff --git a/utils/sql/git/required/2022_12_19_player_events_tables.sql b/utils/sql/git/required/2022_12_19_player_events_tables.sql new file mode 100644 index 000000000..df27b01c9 --- /dev/null +++ b/utils/sql/git/required/2022_12_19_player_events_tables.sql @@ -0,0 +1,34 @@ +CREATE TABLE `player_event_log_settings` +( + `id` bigint(20) NOT NULL, + `event_name` varchar(100) DEFAULT NULL, + `event_enabled` tinyint(1) DEFAULT NULL, + `retention_days` int(11) DEFAULT 0, + `discord_webhook_id` int(11) DEFAULT 0, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `player_event_logs` +( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `account_id` bigint(20) DEFAULT NULL, + `character_id` bigint(20) DEFAULT NULL, + `zone_id` int(11) DEFAULT NULL, + `instance_id` int(11) DEFAULT NULL, + `x` float DEFAULT NULL, + `y` float DEFAULT NULL, + `z` float DEFAULT NULL, + `heading` float DEFAULT NULL, + `event_type_id` int(11) DEFAULT NULL, + `event_type_name` varchar(255) DEFAULT NULL, + `event_data` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`event_data`)), + `created_at` datetime DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `event_created_at` (`event_type_id`,`created_at`), + KEY `zone_id` (`zone_id`), + KEY `character_id` (`character_id`,`zone_id`) USING BTREE, + KEY `created_at` (`created_at`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4; + +DROP TABLE `hackers`; +DROP TABLE `eventlog`; diff --git a/utils/sql/git/required/2023_01_21_bots_raid_members.sql b/utils/sql/git/required/2023_01_21_bots_raid_members.sql new file mode 100644 index 000000000..45cfbf2ec --- /dev/null +++ b/utils/sql/git/required/2023_01_21_bots_raid_members.sql @@ -0,0 +1,4 @@ +DROP INDEX IF EXISTS `PRIMARY` ON `raid_members`; +CREATE UNIQUE INDEX IF NOT EXISTS `UNIQUE` ON `raid_members`(`name`); +ALTER TABLE `raid_members` ADD COLUMN `bot_id` int(4) NOT NULL DEFAULT 0 AFTER `charid`; +ALTER TABLE `raid_members` ADD COLUMN `id` BIGINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT FIRST; diff --git a/utils/sql/git/required/2023_01_24_item_recast.sql b/utils/sql/git/required/2023_01_24_item_recast.sql new file mode 100644 index 000000000..f2722af1c --- /dev/null +++ b/utils/sql/git/required/2023_01_24_item_recast.sql @@ -0,0 +1,2 @@ +ALTER TABLE `character_item_recast` + CHANGE COLUMN `recast_type` `recast_type` INT(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `id`; \ No newline at end of file diff --git a/utils/sql/git/required/2023_01_29_merchant_status_requirements.sql b/utils/sql/git/required/2023_01_29_merchant_status_requirements.sql new file mode 100644 index 000000000..caedaa638 --- /dev/null +++ b/utils/sql/git/required/2023_01_29_merchant_status_requirements.sql @@ -0,0 +1,3 @@ +ALTER TABLE `merchantlist` +ADD COLUMN `min_status` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `level_required`, +ADD COLUMN `max_status` tinyint(3) UNSIGNED NOT NULL DEFAULT 255 AFTER `min_status`; \ No newline at end of file diff --git a/utils/sql/git/required/2023_02_24_npc_scaling_zone_id_instance_version.sql b/utils/sql/git/required/2023_02_24_npc_scaling_zone_id_instance_version.sql new file mode 100644 index 000000000..560aa4961 --- /dev/null +++ b/utils/sql/git/required/2023_02_24_npc_scaling_zone_id_instance_version.sql @@ -0,0 +1,5 @@ +ALTER TABLE `npc_scale_global_base` +ADD COLUMN `zone_id` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `level`, +ADD COLUMN `instance_version` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `zone_id`, +DROP PRIMARY KEY, +ADD PRIMARY KEY (`type`, `level`, `zone_id`, `instance_version`) USING BTREE; diff --git a/utils/sql/git/required/2023_02_28_npc_scaling_zone_list_version_list.sql b/utils/sql/git/required/2023_02_28_npc_scaling_zone_list_version_list.sql new file mode 100644 index 000000000..a25d123fd --- /dev/null +++ b/utils/sql/git/required/2023_02_28_npc_scaling_zone_list_version_list.sql @@ -0,0 +1,5 @@ +ALTER TABLE `npc_scale_global_base` + CHANGE COLUMN `zone_id` `zone_id_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL AFTER `level`, + CHANGE COLUMN `instance_version` `instance_version_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL AFTER `zone_id_list`, + DROP PRIMARY KEY, + ADD PRIMARY KEY (`type`, `level`, `zone_id_list`(255), `instance_version_list`(255)) USING BTREE; diff --git a/utils/sql/git/required/2023_03_04_npc_scale_global_base_heroic_strikethrough.sql b/utils/sql/git/required/2023_03_04_npc_scale_global_base_heroic_strikethrough.sql new file mode 100644 index 000000000..6559cb0a0 --- /dev/null +++ b/utils/sql/git/required/2023_03_04_npc_scale_global_base_heroic_strikethrough.sql @@ -0,0 +1,55 @@ +UPDATE `npc_scale_global_base` SET ac = 0 WHERE ac IS NULL; +UPDATE `npc_scale_global_base` SET hp = 0 WHERE hp IS NULL; +UPDATE `npc_scale_global_base` SET accuracy = 0 WHERE accuracy IS NULL; +UPDATE `npc_scale_global_base` SET slow_mitigation = 0 WHERE slow_mitigation IS NULL; +UPDATE `npc_scale_global_base` SET attack = 0 WHERE attack IS NULL; +UPDATE `npc_scale_global_base` SET strength = 0 WHERE strength IS NULL; +UPDATE `npc_scale_global_base` SET stamina = 0 WHERE stamina IS NULL; +UPDATE `npc_scale_global_base` SET dexterity = 0 WHERE dexterity IS NULL; +UPDATE `npc_scale_global_base` SET agility = 0 WHERE agility IS NULL; +UPDATE `npc_scale_global_base` SET intelligence = 0 WHERE intelligence IS NULL; +UPDATE `npc_scale_global_base` SET wisdom = 0 WHERE wisdom IS NULL; +UPDATE `npc_scale_global_base` SET charisma = 0 WHERE charisma IS NULL; +UPDATE `npc_scale_global_base` SET magic_resist = 0 WHERE magic_resist IS NULL; +UPDATE `npc_scale_global_base` SET cold_resist = 0 WHERE cold_resist IS NULL; +UPDATE `npc_scale_global_base` SET fire_resist = 0 WHERE fire_resist IS NULL; +UPDATE `npc_scale_global_base` SET poison_resist = 0 WHERE poison_resist IS NULL; +UPDATE `npc_scale_global_base` SET disease_resist = 0 WHERE disease_resist IS NULL; +UPDATE `npc_scale_global_base` SET corruption_resist = 0 WHERE corruption_resist IS NULL; +UPDATE `npc_scale_global_base` SET physical_resist = 0 WHERE physical_resist IS NULL; +UPDATE `npc_scale_global_base` SET min_dmg = 0 WHERE min_dmg IS NULL; +UPDATE `npc_scale_global_base` SET max_dmg = 0 WHERE max_dmg IS NULL; +UPDATE `npc_scale_global_base` SET hp_regen_rate = 0 WHERE hp_regen_rate IS NULL; +UPDATE `npc_scale_global_base` SET attack_delay = 0 WHERE attack_delay IS NULL; +UPDATE `npc_scale_global_base` SET physical_resist = 0 WHERE physical_resist IS NULL; +UPDATE `npc_scale_global_base` SET spell_scale = 100 WHERE spell_scale IS NULL; +UPDATE `npc_scale_global_base` SET heal_scale = 100 WHERE heal_scale IS NULL; +UPDATE `npc_scale_global_base` SET special_abilities = '' WHERE special_abilities IS NULL; +ALTER TABLE `npc_scale_global_base` + MODIFY COLUMN `ac` int(11) NOT NULL DEFAULT 0 AFTER `instance_version_list`, + MODIFY COLUMN `hp` int(11) NOT NULL DEFAULT 0 AFTER `ac`, + MODIFY COLUMN `accuracy` int(11) NOT NULL DEFAULT 0 AFTER `hp`, + MODIFY COLUMN `slow_mitigation` int(11) NOT NULL DEFAULT 0 AFTER `accuracy`, + MODIFY COLUMN `attack` int(11) NOT NULL DEFAULT 0 AFTER `slow_mitigation`, + MODIFY COLUMN `strength` int(11) NOT NULL DEFAULT 0 AFTER `attack`, + MODIFY COLUMN `stamina` int(11) NOT NULL DEFAULT 0 AFTER `strength`, + MODIFY COLUMN `dexterity` int(11) NOT NULL DEFAULT 0 AFTER `stamina`, + MODIFY COLUMN `agility` int(11) NOT NULL DEFAULT 0 AFTER `dexterity`, + MODIFY COLUMN `intelligence` int(11) NOT NULL DEFAULT 0 AFTER `agility`, + MODIFY COLUMN `wisdom` int(11) NOT NULL DEFAULT 0 AFTER `intelligence`, + MODIFY COLUMN `charisma` int(11) NOT NULL DEFAULT 0 AFTER `wisdom`, + MODIFY COLUMN `magic_resist` int(11) NOT NULL DEFAULT 0 AFTER `charisma`, + MODIFY COLUMN `cold_resist` int(11) NOT NULL DEFAULT 0 AFTER `magic_resist`, + MODIFY COLUMN `fire_resist` int(11) NOT NULL DEFAULT 0 AFTER `cold_resist`, + MODIFY COLUMN `poison_resist` int(11) NOT NULL DEFAULT 0 AFTER `fire_resist`, + MODIFY COLUMN `disease_resist` int(11) NOT NULL DEFAULT 0 AFTER `poison_resist`, + MODIFY COLUMN `corruption_resist` int(11) NOT NULL DEFAULT 0 AFTER `disease_resist`, + MODIFY COLUMN `physical_resist` int(11) NOT NULL DEFAULT 0 AFTER `corruption_resist`, + MODIFY COLUMN `min_dmg` int(11) NOT NULL DEFAULT 0 AFTER `physical_resist`, + MODIFY COLUMN `max_dmg` int(11) NOT NULL DEFAULT 0 AFTER `min_dmg`, + MODIFY COLUMN `hp_regen_rate` int(11) NOT NULL DEFAULT 0 AFTER `max_dmg`, + MODIFY COLUMN `attack_delay` int(11) NOT NULL DEFAULT 0 AFTER `hp_regen_rate`, + MODIFY COLUMN `spell_scale` int(11) NOT NULL DEFAULT 100 AFTER `attack_delay`, + MODIFY COLUMN `heal_scale` int(11) NOT NULL DEFAULT 100 AFTER `spell_scale`, + MODIFY COLUMN `special_abilities` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT '' AFTER `heal_scale`, + ADD COLUMN `heroic_strikethrough` int(11) NOT NULL DEFAULT 0 AFTER `heal_scale`; diff --git a/utils/sql/git/required/2023_03_08_npc_scale_global_base_avoidance.sql b/utils/sql/git/required/2023_03_08_npc_scale_global_base_avoidance.sql new file mode 100644 index 000000000..64755da49 --- /dev/null +++ b/utils/sql/git/required/2023_03_08_npc_scale_global_base_avoidance.sql @@ -0,0 +1,5 @@ +ALTER TABLE `npc_scale_global_base` +MODIFY COLUMN `hp` bigint(20) NOT NULL DEFAULT 0 AFTER `ac`, +MODIFY COLUMN `hp_regen_rate` bigint(20) NOT NULL DEFAULT 0 AFTER `max_dmg`, +ADD COLUMN `hp_regen_per_second` bigint(20) NOT NULL DEFAULT 0 AFTER `hp_regen_rate`, +ADD COLUMN `avoidance` int(11) unsigned NOT NULL DEFAULT 0 AFTER `heal_scale`; diff --git a/utils/sql/peq_aa_tables_post_rework.sql b/utils/sql/peq_aa_tables_post_rework.sql index 9d3b05eaf..72f83cc83 100644 --- a/utils/sql/peq_aa_tables_post_rework.sql +++ b/utils/sql/peq_aa_tables_post_rework.sql @@ -1,20656 +1,150 @@ +-- MariaDB dump 10.19 Distrib 10.5.18-MariaDB, for debian-linux-gnu (x86_64) +-- +-- Host: mariadb Database: peq +-- ------------------------------------------------------ +-- Server version 10.5.4-MariaDB-1:10.5.4+maria~focal + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `aa_ability` +-- + DROP TABLE IF EXISTS `aa_ability`; -CREATE TABLE IF NOT EXISTS `aa_ability` ( +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `aa_ability` ( `id` int(10) unsigned NOT NULL, `name` text NOT NULL, - `category` int(10) NOT NULL DEFAULT '-1', - `classes` int(10) NOT NULL DEFAULT '65535', - `races` int(10) NOT NULL DEFAULT '65535', - `drakkin_heritage` int(10) NOT NULL DEFAULT '127', - `deities` int(10) NOT NULL DEFAULT '131071', - `status` int(10) NOT NULL DEFAULT '0', - `type` int(10) NOT NULL DEFAULT '0', - `charges` int(11) NOT NULL DEFAULT '0', - `grant_only` tinyint(4) NOT NULL DEFAULT '0', - `first_rank_id` int(10) NOT NULL DEFAULT '-1', - `enabled` tinyint(3) unsigned NOT NULL DEFAULT '1', + `category` int(10) NOT NULL DEFAULT -1, + `classes` int(10) NOT NULL DEFAULT 131070, + `races` int(10) NOT NULL DEFAULT 65535, + `drakkin_heritage` int(10) NOT NULL DEFAULT 127, + `deities` int(10) NOT NULL DEFAULT 131071, + `status` int(10) NOT NULL DEFAULT 0, + `type` int(10) NOT NULL DEFAULT 0, + `charges` int(11) NOT NULL DEFAULT 0, + `grant_only` tinyint(4) NOT NULL DEFAULT 0, + `first_rank_id` int(10) NOT NULL DEFAULT -1, + `enabled` tinyint(3) unsigned NOT NULL DEFAULT 1, + `reset_on_death` tinyint(4) NOT NULL DEFAULT 0, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; -INSERT INTO `aa_ability` (`id`, `name`, `category`, `classes`, `races`, `drakkin_heritage`, `deities`, `status`, `type`, `charges`, `grant_only`, `first_rank_id`, `enabled`) VALUES - (0, 'Unknown AA -1', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 49999, 1), - (1, 'Innate Strength', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 2, 1), - (2, 'Innate Stamina', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 7, 1), - (3, 'Innate Agility', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 12, 1), - (4, 'Innate Dexterity', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 17, 1), - (5, 'Innate Intelligence', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 22, 1), - (6, 'Innate Wisdom', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 27, 1), - (7, 'Innate Charisma', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 32, 1), - (8, 'Innate Fire Protection', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 37, 1), - (9, 'Innate Cold Protection', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 42, 1), - (10, 'Innate Magic Protection', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 47, 1), - (11, 'Innate Poison Protection', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 52, 1), - (12, 'Innate Disease Protection', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 57, 1), - (13, 'Innate Run Speed', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 62, 1), - (15, 'Innate Metabolism', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 68, 1), - (16, 'Innate Lung Capacity', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 71, 1), - (17, 'First Aid', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 74, 1), - (18, 'Healing Adept', -1, 16942, 65535, 127, 131071, 0, 2, 0, 0, 77, 1), - (19, 'Healing Gift', -1, 16942, 65535, 127, 131071, 0, 2, 0, 0, 80, 1), - (20, 'Spell Casting Mastery', -1, 15906, 65535, 127, 131071, 0, 2, 0, 0, 83, 1), - (21, 'Spell Casting Reinforcement', -1, 25150, 65535, 127, 131071, 0, 2, 0, 0, 86, 1), - (23, 'Spell Casting Fury', -1, 32446, 65535, 127, 131071, 0, 2, 0, 0, 92, 1), - (25, 'Spell Casting Subtlety', -1, 15360, 65535, 127, 131071, 0, 2, 0, 0, 98, 1), - (26, 'Spell Casting Expertise', -1, 15504, 65535, 127, 131071, 0, 2, 0, 0, 101, 1), - (27, 'Spell Casting Deftness', -1, 7184, 65535, 127, 131071, 0, 2, 0, 0, 104, 1), - (28, 'Natural Durability', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 107, 1), - (29, 'Natural Healing', -1, 49629, 65535, 127, 131071, 0, 2, 0, 0, 110, 1), - (30, 'Combat Fury', -1, 16596, 65535, 127, 131071, 0, 2, 0, 0, 113, 1), - (31, 'Fear Resistance', -1, 49629, 65535, 127, 131071, 0, 2, 0, 0, 116, 1), - (32, 'Finishing Blow', -1, 49629, 65535, 127, 131071, 0, 2, 0, 0, 119, 1), - (33, 'Combat Stability', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 122, 1), - (34, 'Combat Agility', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 125, 1), - (35, 'Mass Group Buff', -1, 30254, 65535, 127, 131071, 0, 3, 0, 0, 128, 1), - (36, 'Divine Resurrection', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 129, 1), - (37, 'Innate Invis to Undead', -1, 1026, 65535, 127, 131071, 0, 3, 0, 0, 130, 1), - (38, 'Celestial Regeneration', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 131, 1), - (39, 'Bestow Divine Aura', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 132, 1), - (41, 'Purify Soul', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 136, 1), - (42, 'Quick Evacuation', -1, 2080, 65535, 127, 131071, 0, 3, 0, 0, 137, 1), - (43, 'Exodus', -1, 2080, 65535, 127, 131071, 0, 3, 0, 0, 140, 1), - (44, 'Quick Damage', -1, 6176, 65535, 127, 131071, 0, 3, 0, 0, 141, 1), - (45, 'Enhanced Root', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 144, 1), - (46, 'Dire Charm', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 145, 1), - (47, 'Cannibalization', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 146, 1), - (48, 'Quick Buff', -1, 25134, 65535, 127, 131071, 0, 2, 0, 0, 147, 1), - (49, 'Alchemy Mastery', 6, 512, 65535, 127, 131071, 0, 1, 0, 0, 150, 1), - (50, 'Rabid Bear', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 153, 1), - (52, 'Improved Familiar', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 155, 1), - (53, 'Nexus Gate', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 156, 1), - (55, 'Permanent Illusion', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 158, 1), - (56, 'Jewel Craft Mastery', 6, 8192, 65535, 127, 131071, 0, 1, 0, 0, 159, 1), - (57, 'Gather Mana', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 162, 1), - (58, 'Mend Companion', -1, 21504, 65535, 127, 131071, 0, 3, 0, 0, 163, 1), - (60, 'Frenzied Burnout', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 167, 1), - (61, 'Elemental Form: Fire', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 168, 1), - (62, 'Elemental Form: Water', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 171, 1), - (63, 'Elemental Form: Earth', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 174, 1), - (64, 'Elemental Form: Air', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 177, 1), - (67, 'Elemental Pact', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 182, 1), - (68, 'Life Burn', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 183, 1), - (69, 'Dead Mesmerization', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 184, 1), - (70, 'Fear Storm', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 185, 1), - (71, 'Flesh to Bone', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 186, 1), - (72, 'Call to Corpse', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 187, 1), - (73, 'Divine Stun', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 188, 1), - (75, 'Slay Undead', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 190, 1), - (76, 'Act of Valor', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 193, 1), - (77, 'Holy Steed', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 194, 1), - (78, 'Fearless', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 195, 1), - (79, '2 Hand Bash', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 196, 1), - (80, 'Innate Camouflage', -1, 40, 65535, 127, 131071, 0, 3, 0, 0, 197, 1), - (81, 'Ambidexterity', -1, 16841, 65535, 127, 131071, 0, 3, 0, 0, 198, 1), - (82, 'Archery Mastery', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 199, 1), - (84, 'Endless Quiver', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 205, 1), - (85, 'Unholy Steed', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 206, 1), - (87, 'Leech Touch', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 208, 1), - (89, 'Soul Abrasion', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 210, 1), - (90, 'Instrument Mastery', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 213, 1), - (94, 'Jam Fest', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 225, 1), - (97, 'Critical Mend', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 230, 1), - (98, 'Purify Body', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 233, 1), - (100, 'Rapid Feign', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 237, 1), - (101, 'Return Kick', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 240, 1), - (102, 'Escape', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 243, 1), - (103, 'Poison Mastery', 6, 256, 65535, 127, 131071, 0, 1, 0, 0, 244, 1), - (104, 'Double Riposte', -1, 49501, 65535, 127, 131071, 0, 2, 0, 0, 247, 1), - (107, 'Purge Poison', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 254, 1), - (108, 'Flurry', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 255, 1), - (109, 'Rampage', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 258, 1), - (110, 'Area Taunt', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 259, 1), - (111, 'War Cry', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 260, 1), - (112, 'Bandage Wound', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 263, 1), - (114, 'Spell Casting Fury Mastery', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 267, 1), - (116, 'Dragon Punch', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 273, 1), - (117, 'Strong Root', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 274, 1), - (118, 'Singing Mastery', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 275, 1), - (119, 'Body and Mind Rejuvenation', -1, 16540, 65535, 127, 131071, 0, 3, 0, 0, 278, 1), - (120, 'Physical Enhancement', -1, 49629, 65535, 127, 131071, 0, 3, 0, 0, 279, 1), - (121, 'Adv. Trap Negotiation', -1, 384, 65535, 127, 131071, 0, 3, 0, 0, 280, 1), - (122, 'Acrobatics', -1, 448, 65535, 127, 131071, 0, 3, 0, 0, 283, 1), - (123, 'Scribble Notes', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 286, 1), - (124, 'Chaotic Stab', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 287, 1), - (125, 'Pet Discipline', -1, 22032, 65535, 127, 131071, 0, 3, 0, 0, 288, 1), - (126, 'Hobble of Spirits', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 289, 1), - (127, 'Frenzy of Spirit', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 290, 1), - (128, 'Paragon of Spirit', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 291, 1), - (129, 'Chains of Purity', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10348, 1), - (130, 'Resplendent Glory', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 8300, 1), - (131, 'Rage of Rallos Zek', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 8303, 1), - (132, 'Enhanced Area Taunt', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 8312, 1), - (133, 'Decapitation', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 14200, 1), - (134, 'Hastened Berserking Disciplines', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 14203, 1), - (135, 'Quiet Miracle', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 14206, 1), - (136, 'Repel the Wicked', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 14207, 1), - (137, 'Beacon of Life', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 14208, 1), - (138, 'Blessed Chains', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 14209, 1), - (139, 'Hastened Focused Celestial Regeneration', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 14213, 1), - (140, 'Quickened Spirit Calling', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 14225, 1), - (141, 'New Tanaan Crafting Mastery', 6, 65535, 65535, 127, 131071, 0, 1, 0, 0, 412, 1), - (142, 'Planar Power', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 418, 1), - (143, 'Planar Durability', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 423, 1), - (144, 'Innate Enlightenment', -1, 15360, 65535, 127, 131071, 0, 2, 0, 0, 426, 1), - (146, 'Unknown AA 8001', 9, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8000, 0), - (147, 'Spiritual Rebuke', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 14231, 1), - (148, 'Pathosis', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 14232, 1), - (149, 'Preincarnation', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 14233, 1), - (150, 'Mastery of the Past', -1, 15504, 65535, 127, 131071, 0, 2, 0, 0, 446, 1), - (151, 'Spiritual Blessing', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 14234, 1), - (152, 'Communion of the Cheetah', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 14237, 1), - (153, 'Radiant Cure', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 459, 1), - (154, 'Hastened Divinity', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 462, 1), - (156, 'Hastened Purification of the Soul', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 468, 1), - (157, 'Hastened Gathering', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 471, 1), - (158, 'Hastened Rabidity', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 474, 1), - (159, 'Hastened Exodus', -1, 2080, 65535, 127, 131071, 0, 3, 0, 0, 477, 1), - (160, 'Hastened Root', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 480, 1), - (161, 'Hastened Mending', -1, 21504, 65535, 127, 131071, 0, 3, 0, 0, 483, 1), - (163, 'Hastened Instigation', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 489, 1), - (164, 'Hastened Rampage', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 492, 1), - (165, 'Hastened Purification of the Body', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 495, 1), - (166, 'Hasty Exit', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 498, 1), - (167, 'Hastened Purification', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 501, 1), - (168, 'Hastened Nature\'s Fury', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 14241, 1), - (169, 'Divine Arbitration', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 507, 1), - (170, 'Wrath of the Wild', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 510, 1), - (171, 'Virulent Paralysis', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 513, 1), - (172, 'Harvest of Druzzil', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 516, 1), - (173, 'Eldritch Rune', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 517, 1), - (174, 'Servant of Ro', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 520, 1), - (175, 'Wake the Dead', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 523, 1), - (176, 'Suspended Minion', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 526, 1), - (177, 'Spirit Call', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 528, 1), - (178, 'Wrath of the Forest Walker', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 14244, 1), - (179, 'Gift of Sylvan Spirits', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 14249, 1), - (180, 'Hand of Piety', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 534, 1), - (181, 'Mithaniel\'s Binding', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 537, 1), - (182, 'Summon Personal Tribute Master', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 5006, 1), - (183, 'Extended Vinelash Cascade', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 14254, 1), - (184, 'Guardian of the Forest', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 545, 1), - (185, 'Spirit of the Wood', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 548, 1), - (186, 'Bestial Frenzy', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 551, 1), - (187, 'Harmonious Attack', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 556, 1), - (188, 'Knight\'s Advantage', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 561, 1), - (189, 'Ferocity', -1, 33097, 65535, 127, 131071, 0, 2, 0, 0, 564, 1), - (190, 'Viscid Roots', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 567, 1), - (193, 'Feigned Minion', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 574, 1), - (194, 'Unfailing Divinity', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 577, 1), - (195, 'Animation Empathy', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 580, 1), - (196, 'Rush to Judgment', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 583, 1), - (197, 'Living Shield', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 586, 1), - (198, 'Consumption of the Soul', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 589, 1), - (199, 'Boastful Bellow', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 592, 1), - (200, 'Fervent Blessing', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 593, 1), - (201, 'Touch of the Wicked', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 596, 1), - (202, 'Punishing Blade', -1, 32841, 65535, 127, 131071, 0, 2, 0, 0, 599, 1), - (203, 'Speed of the Knight', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 602, 1), - (204, 'Shroud of Stealth', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 605, 1), - (205, 'Nimble Evasion', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 606, 1), - (206, 'Technique of Master Wu', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 611, 1), - (207, 'Host of the Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 616, 1), - (208, 'Call of Xuzl', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 619, 1), - (209, 'Hastened Stealth', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 622, 1), - (210, 'Ingenuity', -1, 33089, 65535, 127, 131071, 0, 2, 0, 0, 625, 1), - (211, 'Fleet of Foot', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 628, 1), - (212, 'Fading Memories', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 630, 1), - (213, 'Tactical Mastery', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 631, 1), - (214, 'Theft of Life', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 634, 1), - (215, 'Fury of Magic', -1, 13858, 65535, 127, 131071, 0, 2, 0, 0, 637, 1), - (216, 'Extended Spirit of the Bear', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 14259, 1), - (217, 'Project Illusion', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 643, 1), - (218, 'Headshot', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 644, 1), - (219, 'Entrap', -1, 40, 65535, 127, 131071, 0, 3, 0, 0, 645, 1), - (220, 'Sonic Displacement', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 13528, 1), - (221, 'Total Domination', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 649, 1), - (222, 'Stalwart Endurance', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 652, 1), - (223, 'Quick Summoning', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 655, 1), - (224, 'Mental Clarity', -1, 32446, 65535, 127, 131071, 0, 2, 0, 0, 658, 1), - (225, 'Innate Regeneration', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 661, 1), - (227, 'Extended Notes', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 665, 1), - (228, 'Hastened Warder\'s Gift', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 13463, 1), - (229, 'Improved Reclaim Energy', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 671, 1), - (230, 'Hastened Possum', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 13449, 1), - (231, 'Shauri\'s Sonorious Clouding', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 13527, 1), - (232, 'Veil of the Underbrush', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 14262, 1), - (233, 'Packrat', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 678, 1), - (234, 'Heightened Endurance ', -1, 33089, 65535, 127, 131071, 0, 2, 0, 0, 683, 1), - (235, 'Weapon Affinity', -1, 49629, 65535, 127, 131071, 0, 2, 0, 0, 686, 1), - (236, 'Secondary Forte', -1, 15906, 65535, 127, 131071, 0, 2, 0, 0, 691, 1), - (237, 'Persistent Casting', -1, 32446, 65535, 127, 131071, 0, 2, 0, 0, 692, 1), - (238, 'Tune of Pursuance', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 695, 1), - (239, 'Hastened Companion\'s Sacrifice', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 13474, 1), - (240, 'Cheetah\'s Pounce', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 13483, 1), - (241, 'Bloodlust', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 13484, 1), - (242, 'Primal Fury', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 13485, 1), - (244, 'Lure of the Siren\'s Song', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 13529, 1), - (245, 'Bestial Alignment', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 718, 1), - (246, 'Hidden Communion of the Cheetah', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 14265, 1), - (247, 'Feral Swipe', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 723, 1), - (248, 'Warder\'s Fury', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 724, 1), - (249, 'Warder\'s Alacrity', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 729, 1), - (250, 'Pet Affinity', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 734, 1), - (251, 'Mastery of the Past', -1, 16942, 65535, 127, 131071, 0, 2, 0, 0, 735, 1), - (252, 'Spell Casting Subtlety', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 738, 1), - (254, 'Divine Avatar', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 746, 1), - (255, 'Exquisite Benediction', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 749, 1), - (256, 'Hastened Curing', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 754, 1), - (257, 'Nature\'s Boon', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 757, 1), - (258, 'Advanced Tracking', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 762, 1), - (259, 'Critical Affliction', -1, 18104, 65535, 127, 131071, 0, 2, 0, 0, 767, 1), - (260, 'Glacial Arrow', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 13549, 1), - (261, 'Doppelganger', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 773, 1), - (262, 'Enhanced Forgetfulness', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 776, 1), - (263, 'Mesmerization Mastery', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 781, 1), - (264, 'Quick Mass Group Buff', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 782, 1), - (265, 'Shared Health', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 785, 1), - (266, 'Elemental Fury', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 790, 1), - (267, 'Elemental Alacrity ', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 795, 1), - (268, 'Elemental Agility', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 800, 1), - (269, 'Elemental Durability', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 803, 1), - (270, 'Sinister Strikes', -1, 16841, 65535, 127, 131071, 0, 3, 0, 0, 806, 1), - (271, 'Strikethrough', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 807, 1), - (272, 'Stonewall', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 810, 1), - (273, 'Rapid Strikes ', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 815, 1), - (274, 'Kick Mastery', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 820, 1), - (275, 'Heightened Awareness', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 823, 1), - (276, 'Destructive Force ', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 828, 1), - (278, 'Death\'s Fury ', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 834, 1), - (279, 'Quickening of Death ', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 839, 1), - (280, 'Group Perfected Invisibility to Undead', -1, 14336, 65535, 127, 131071, 0, 3, 0, 0, 14281, 1), - (281, 'Triple Backstab', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 846, 1), - (282, 'Hastened Piety', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 849, 1), - (283, 'Immobilizing Bash', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 852, 1), - (284, 'Vicious Smash', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 855, 1), - (285, 'Radiant Cure', -1, 4, 65535, 127, 131071, 0, 2, 0, 0, 860, 1), - (286, 'Purification ', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 863, 1), - (287, 'Precision of the Pathfinder', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 864, 1), - (288, 'Coat of Thistles', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 867, 1), - (289, 'Flaming Arrows', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 872, 1), - (290, 'Frost Arrows', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 875, 1), - (291, 'Perfected Invisibility to Undead', -1, 14336, 65535, 127, 131071, 0, 3, 0, 0, 14282, 1), - (292, 'Trap Circumvention ', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 881, 1), - (293, 'Quickened Stasis', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 14283, 1), - (294, 'Virulent Venom ', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 888, 1), - (295, 'Extended Dreary Deeds', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 14286, 1), - (296, 'Intense Hatred', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 895, 1), - (297, 'Quickened Frenzied Burnout', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 14289, 1), - (299, 'Sturdiness', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 907, 1), - (300, 'Warlord\'s Tenacity ', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 912, 1), - (301, 'Strengthened Strike', -1, 9, 65535, 127, 131071, 0, 3, 0, 0, 915, 1), - (302, 'Extended Shielding', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 918, 1), - (303, 'Ro\'s Flaming Familiar ', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 921, 1), - (304, 'E\'ci\'s Icy Familiar ', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 922, 1), - (305, 'Druzzil\'s Mystical Familiar ', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 923, 1), - (306, 'Unknown AA 15819', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 15819, 1), - (307, 'Ward of Destruction ', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 926, 1), - (308, 'Frenzied Devastation', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 931, 1), - (309, 'Combat Fury', -1, 32769, 65535, 127, 131071, 0, 2, 0, 0, 934, 1), - (310, 'Combat Fury', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 937, 1), - (311, 'Combat Fury', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 940, 1), - (312, 'Quickened Host of the Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 14292, 1), - (313, 'Hastened Companion\'s Relocation', -1, 30224, 65535, 127, 131071, 0, 3, 0, 0, 14295, 1), - (314, 'Veteran\'s Wrath', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 1047, 1), - (315, 'Planar Durability', -1, 32788, 65535, 127, 131071, 0, 3, 0, 0, 952, 1), - (316, 'Innate Enlightenment', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 955, 1), - (317, 'Dire Charm', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 960, 1), - (318, 'Dire Charm', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 961, 1), - (319, 'Touch of the Divine', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 962, 1), - (320, 'Swarm of Decay', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 967, 1), - (321, 'Call of the Ancients', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 970, 1), - (322, 'Innate See Invis', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 1388, 1), - (323, 'Virulent Talon', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 14307, 1), - (324, 'Blacksmithing Mastery', 6, 65535, 65535, 127, 131071, 0, 1, 0, 0, 979, 1), - (325, 'Baking Mastery', 6, 65535, 65535, 127, 131071, 0, 1, 0, 0, 982, 1), - (326, 'Brewing Mastery', 6, 65535, 65535, 127, 131071, 0, 1, 0, 0, 985, 1), - (327, 'Fletching Mastery', 6, 65535, 65535, 127, 131071, 0, 1, 0, 0, 988, 1), - (328, 'Pottery Mastery', 6, 65535, 65535, 127, 131071, 0, 1, 0, 0, 991, 1), - (329, 'Tailoring Mastery', 6, 65535, 65535, 127, 131071, 0, 1, 0, 0, 994, 1), - (330, 'Salvage', 6, 65535, 65535, 127, 131071, 0, 1, 0, 0, 997, 1), - (331, 'Origin', 9, 65535, 65535, 127, 131071, 0, 1, 0, 0, 1000, 1), - (333, 'Discordant Defiance', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 1006, 1), - (334, 'Mystical Attuning', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 1021, 1), - (335, 'Delay Death', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 1026, 1), - (336, 'Earthen Brawn', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8263, 1), - (337, 'Unknown AA 15798', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 15798, 1), - (338, 'Veteran\'s Wrath', -1, 16596, 65535, 127, 131071, 0, 2, 0, 0, 1041, 1), - (339, 'Veteran\'s Wrath', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 1044, 1), - (340, 'Unknown AA 15833', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 15833, 1), - (341, 'Veteran\'s Wrath', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 1050, 1), - (342, 'Staff Block', -1, 15360, 65535, 127, 131071, 0, 2, 0, 0, 14301, 1), - (343, 'Hastened Pestilent Paralysis', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 14308, 1), - (344, 'Hastened Mercurial Torment', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 14311, 1), - (345, 'Unknown AA 15768', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15768, 1), - (346, 'Unknown AA 15771', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 15771, 1), - (347, 'Mnemonic Retention', -1, 32446, 65535, 127, 131071, 0, 2, 0, 0, 1071, 1), - (348, 'Expansive Mind', -1, 32446, 65535, 127, 131071, 0, 2, 0, 0, 1072, 1), - (350, 'Death\'s Malaise', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 14321, 1), - (351, 'Dying Grasp', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 14322, 1), - (352, 'Arcane Tongues', 6, 15360, 65535, 127, 131071, 0, 2, 0, 0, 1089, 1), - (353, 'Master of Disguise', -1, 384, 65535, 127, 131071, 0, 3, 0, 0, 1092, 1), - (354, 'Slippery Attacks', -1, 16841, 65535, 127, 131071, 0, 2, 0, 0, 1093, 1), - (355, 'Unknown AA 15836', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 15836, 1), - (357, 'Unknown AA 16176', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 16176, 1), - (358, 'Fury of Magic', -1, 16540, 65535, 127, 131071, 0, 2, 0, 0, 1107, 1), - (359, 'Dance of Blades', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 1110, 1), - (360, 'Bloodthirsty Blade', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 13616, 1), - (361, 'Shield of Notes', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 1116, 1), - (362, 'Roar of Thunder', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 1119, 1), - (363, 'Unknown AA 16179', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 16179, 1), - (364, 'Persistent Minion', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 1122, 1), - (365, 'A Hole In Space', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 14323, 1), - (366, 'Advanced Pet Discipline', -1, 22032, 65535, 127, 131071, 0, 3, 0, 0, 1129, 1), - (367, 'Throwing Mastery', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1131, 1), - (368, 'Blur of Axes', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1134, 1), - (369, 'Hastened War Cry', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1137, 1), - (370, 'Dead Aim', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1140, 1), - (371, 'Frenzied Defense', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1166, 1), - (372, 'Tireless Sprint', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1146, 1), - (373, 'Desperation', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1149, 1), - (374, 'Untamed Rage', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1150, 1), - (375, 'Echoing Cries', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1155, 1), - (376, 'Distant Strike', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 14372, 1), - (377, 'Earthen Stability', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8268, 1), - (378, 'Earthen Alacrity', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8273, 1), - (379, 'Earthen Artistry', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8278, 1), - (380, 'Earthen Sagacity', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8283, 1), - (381, 'Earthen Brilliance', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8288, 1), - (382, 'Earthen Allure', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8293, 1), - (383, 'Extended Spirit of the Wood', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 12646, 1), - (384, 'Spirit of the Bear', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 12651, 1), - (385, 'Twinheal', -1, 16942, 65535, 127, 131071, 0, 2, 0, 0, 12652, 1), - (386, 'Nature\'s Fury', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 12661, 1), - (387, 'Blood Pact', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1178, 1), - (388, 'Shielding Resistance', -1, 16841, 65535, 127, 131071, 0, 2, 0, 0, 1181, 1), - (389, 'Healing Boon', -1, 518, 65535, 127, 131071, 0, 2, 0, 0, 1186, 1), - (390, 'Elemental Union', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 13695, 1), - (391, 'Celestial Hammer', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 1192, 1), - (392, 'Divine Retribution', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 1195, 1), - (393, 'Nature\'s Blessing', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 12655, 1), - (394, 'Extended Convergence of Spirit', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 12645, 1), - (395, 'Hastened Storm Strike', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 12664, 1), - (396, 'Sanctuary', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 1209, 1), - (397, 'Destructive Fury', -1, 2048, 65535, 127, 131071, 0, 2, 0, 0, 1210, 1), - (398, 'Destructive Fury', -1, 13858, 65535, 127, 131071, 0, 2, 0, 0, 1213, 1), - (399, 'Unknown AA 16180', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 16180, 1), - (400, 'Hastened Improved Twincast', -1, 14370, 65535, 127, 131071, 0, 3, 0, 0, 14331, 1), - (401, 'Extended Heel of Kanji', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 12688, 1), - (402, 'Extended Scaledfist', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 12691, 1), - (403, 'Paralytic Spores', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 14264, 1), - (404, 'Call of the Wild', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 1228, 1), - (405, 'Secondary Recall', -1, 2080, 65535, 127, 131071, 0, 3, 0, 0, 1229, 1), - (406, 'Nature\'s Bounty', -1, 40, 65535, 127, 131071, 0, 3, 0, 0, 1230, 1), - (407, 'Extended Speed Focus', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 7884, 1), - (408, 'Extended Crystalpalm', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 7885, 1), - (409, 'Stasis', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 1233, 1), - (410, 'Fists of Steel', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 12706, 1), - (411, 'Extended Deftdance', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 12709, 1), - (412, 'Color Shock', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 1239, 1), - (413, 'Mind Over Matter', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 1242, 1), - (414, 'Soothing Words', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 1245, 1), - (415, 'Hastened Deftdance', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 12710, 1), - (416, 'Hastened Lyre Leap', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 12713, 1), - (417, 'Hastened Quick Time', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 12716, 1), - (418, 'Replenish Companion', -1, 21504, 65535, 127, 131071, 0, 3, 0, 0, 1126, 1), - (419, 'Extended Quick Time', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 12719, 1), - (420, 'Imitate Death', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 1255, 1), - (424, 'Extended Fierce Eye', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 12720, 1), - (425, 'Hastened Fierce Eye', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 12721, 1), - (426, 'Unknown AA 15904', -1, 2080, 65535, 127, 131071, 0, 3, 0, 0, 15904, 1), - (427, 'Resounding Dirge', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 12737, 1), - (428, 'Death Peace', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 1272, 1), - (429, 'Unknown AA 15908', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15908, 1), - (430, 'Mercurial Torment', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 12766, 1), - (431, 'Pestilent Paralysis', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 12770, 1), - (432, 'Hastened Divine Companion Aura', -1, 30224, 65535, 127, 131071, 0, 3, 0, 0, 12773, 1), - (433, 'Embalmer\'s Carapace', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 12778, 1), - (434, 'Steadfast Will', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 1284, 1), - (435, 'Shield Block', -1, 21, 65535, 127, 131071, 0, 2, 0, 0, 1287, 1), - (436, 'Hastened Encroaching Darkness', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 12779, 1), - (437, 'Tracking Mastery', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 1296, 1), - (438, 'Expanding Darkness', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 12782, 1), - (439, 'Precision', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 1304, 1), - (440, 'Nerves of Steel', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 1307, 1), - (441, 'Aegis of Kildrukaun', -1, 5120, 65535, 127, 131071, 0, 3, 0, 0, 12785, 1), - (442, 'Touch of the Cursed', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 1313, 1), - (443, 'Bestial Bloodrage', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12804, 1), - (444, 'Companion\'s Sacrifice', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12807, 1), - (445, 'Shield Block', -1, 16384, 65535, 127, 131071, 0, 2, 0, 0, 12813, 1), - (446, 'Spiritual Channeling', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 1323, 1), - (447, 'Ancestral Aid', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 1327, 1), - (448, 'Extended Feralgia', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12816, 1), - (450, 'Hastened Protective Spirit', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12819, 1), - (451, 'Mind Crash', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1334, 1), - (452, 'Prolonged Destruction', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1337, 1), - (453, 'Summon Permutation Peddler', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 9032, 1), - (454, 'Hastened Empathic Fury', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12822, 1), - (455, 'Convergence of Spirits', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 13556, 1), - (456, 'Teleport Bind', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1343, 1), - (457, 'Quickened Paragon of Spirit', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12831, 1), - (458, 'Warder\'s Gift', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12837, 1), - (459, 'Gelid Rending', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12846, 1), - (460, 'Quickened Nature\'s Salve', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 12849, 1), - (462, 'Auspice of the Hunter', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 1345, 1), - (463, 'Divine Guardian', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 13385, 1), - (464, 'Divine Peace', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 13388, 1), - (465, 'Savage Spirit', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1348, 1), - (466, 'Trials of Mata Muram', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1011, 1), - (467, 'Press the Attack', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 1351, 1), - (468, 'Crippling Strike', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 1352, 1), - (469, 'Stunning Kick', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 1355, 1), - (470, 'Eye Gouge', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 1358, 1), - (471, 'Gift of the Dark Reign', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1361, 1), - (472, 'Tenacity of the Dark Reign', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1362, 1), - (473, 'Embrace of the Dark Reign', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1363, 1), - (474, 'Power of the Dark Reign', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1364, 1), - (475, 'Fervor of the Dark Reign', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1365, 1), - (476, 'Gift of the Keepers', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1366, 1), - (477, 'Valor of the Keepers', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1367, 1), - (478, 'Embrace of the Keepers', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1368, 1), - (479, 'Power of the Keepers', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1369, 1), - (480, 'Sanctity of the Keepers', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1370, 1), - (481, 'Lesson of the Devoted', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1371, 1), - (482, 'Infusion of the Faithful', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1372, 1), - (483, 'Chaotic Jester', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1373, 1), - (484, 'Expedient Recovery', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1374, 1), - (485, 'Steadfast Servant', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1375, 1), - (486, 'Staunch Recovery', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1376, 1), - (487, 'Intensity of the Resolute', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1377, 1), - (488, 'Curse of Blood', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1378, 1), - (489, 'Yaulp', -1, 6, 65535, 127, 131071, 0, 3, 0, 0, 13389, 1), - (490, 'Abscond', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12864, 1), - (491, 'Atol\'s Unresistable Shackles', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12865, 1), - (492, 'Dimensional Shield', -1, 14336, 65535, 127, 131071, 0, 3, 0, 0, 12866, 1), - (493, 'Improved Sustained Destruction', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12867, 1), - (494, 'Silent Casting', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 1409, 1), - (495, 'Gift of Mana', -1, 15906, 65535, 127, 131071, 0, 2, 0, 0, 1435, 1), - (496, 'Field Dressing', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 1611, 1), - (497, 'Bandage Wounds', -1, 32766, 65535, 127, 131071, 0, 1, 0, 0, 1420, 1), - (498, 'Enhanced Aggression', -1, 49629, 65535, 127, 131071, 0, 2, 0, 0, 1592, 1), - (499, 'Cascading Rage', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1425, 1), - (500, 'Silent Casting', -1, 15360, 65535, 127, 131071, 0, 2, 0, 0, 1404, 1), - (501, 'E\'ci\'s Icy Blessing', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12886, 1), - (503, 'Hastened Thunder', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 1471, 1), - (504, 'Conservation', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1453, 1), - (505, 'Cry of Battle', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 1458, 1), - (506, 'Ward of Purity', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 1459, 1), - (507, 'Ro\'s Fiery Blessing', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12887, 1), - (508, 'Druzzil\'s Mystical Blessing', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12888, 1), - (509, 'Kerafyrm\'s Favor', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12889, 1), - (510, 'Kerafyrm\'s Prismatic Familiar', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12892, 1), - (511, 'Throne of Heroes', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 4665, 1), - (512, 'Translocational Anchor', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1630, 1), - (513, 'Hastened Phantasmal Opponent', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12894, 1), - (514, 'Pyromancy', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1478, 1), - (515, 'Improved Twincast', -1, 14370, 65535, 127, 131071, 0, 3, 0, 0, 12893, 1), - (516, 'Abundant Healing', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 1486, 1), - (517, 'Hastened First Spire of Enchantment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12902, 1), - (518, 'Shared Camouflage', -1, 40, 65535, 127, 131071, 0, 3, 0, 0, 1494, 1), - (519, 'Convergence of Spirits', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 1495, 1), - (520, 'Nature\'s Guardian', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 1498, 1), - (521, 'Edict of Command', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 1501, 1), - (522, 'Extended Burnout', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 1504, 1), - (523, 'Hastened Second Spire of Enchantment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12907, 1), - (524, 'Blood Magic', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 1510, 1), - (525, 'Graverobbing', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 1511, 1), - (526, 'Affliction Mastery', -1, 1568, 65535, 127, 131071, 0, 3, 0, 0, 1514, 1), - (527, 'Hastened Third Spire of Enchantment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12912, 1), - (528, 'Ancestral Guard', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 1520, 1), - (529, 'Cloak of Light', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 1523, 1), - (530, 'Profound Visage', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12920, 1), - (531, 'Cloak of Shadows', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 1527, 1), - (532, 'Willful Death', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 1528, 1), - (533, 'Unknown AA 16016', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 16016, 1), - (534, 'Calculated Insanity', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12931, 1), - (535, 'Crippling Aurora', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12937, 1), - (536, 'Appraisal', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 1542, 1), - (537, 'Precise Strikes', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 1543, 1), - (538, 'Hastened Death', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 1546, 1), - (539, 'Unflinching Resolve', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 1549, 1), - (540, 'Weightless Steps', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 1552, 1), - (541, 'Hastened Blades', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 1555, 1), - (542, 'Unknown AA 16071', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 16071, 1), - (543, 'Diminutive Companion', -1, 20480, 65535, 127, 131071, 0, 3, 0, 0, 12941, 1), - (544, 'Song of Stone', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 1569, 1), - (545, 'Deep Sleep', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 1572, 1), - (546, 'Companion\'s Gift', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 1577, 1), - (547, 'Unknown AA 16081', -1, 15360, 65535, 127, 131071, 0, 3, 0, 0, 16081, 1), - (548, 'Hastened Defiance', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 1583, 1), - (549, 'Dauntless Perseverance', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 1591, 1), - (550, 'Steadfast Resolve', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 14275, 1), - (551, 'Hastened Mind Crash', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1414, 1), - (552, 'Call of Challenge', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 1597, 1), - (553, 'Cacophony', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 1598, 1), - (554, 'Hastened Nightmare Stasis', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 14341, 1), - (555, 'Anatomy', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 1604, 1), - (556, 'Scintillating Beam', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 14346, 1), - (557, 'Trick Shot', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 1608, 1), - (558, 'Turn Undead', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 1383, 1), - (559, 'Turn Summoned', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 1462, 1), - (560, 'Selo\'s Enduring Cadence', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 1627, 1), - (561, 'Hastened Harvest of Druzzil', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12881, 1), - (562, 'Lightning Strikes', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 1616, 1), - (563, 'Concentration', -1, 33089, 65535, 127, 131071, 0, 2, 0, 0, 1588, 1), - (565, 'Mana Burn', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1638, 1), - (567, 'Unknown AA 16146', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 16146, 1), - (568, 'Thief\'s Intuition', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 1641, 1), - (569, 'Thief\'s Intuition', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 1642, 1), - (570, 'Valiant Steed', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 1645, 1), - (571, 'Abyssal Steed', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 1646, 1), - (572, 'Holy Warhorse', -1, 4, 65535, 127, 131071, 0, 3, 0, 1, 1643, 1), - (573, 'Unholy Warhorse', -1, 16, 65535, 127, 131071, 0, 3, 0, 1, 1644, 1), - (574, 'Harmonic Dissonance', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 1647, 1), - (575, 'Tinkering Mastery', 6, 15639, 65535, 127, 131071, 0, 1, 0, 1, 4672, 1), - (576, 'Jewel Craft Mastery ', 6, 57343, 65535, 127, 131071, 0, 1, 0, 0, 4675, 1), - (577, 'Concussive Intuition', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 12885, 1), - (578, 'Glyph Spray', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12939, 1), - (579, 'Combat Medic ', -1, 32766, 65535, 127, 131071, 0, 1, 0, 0, 4688, 1), - (580, 'Hastened Outrider\'s Accuracy', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 13565, 1), - (581, 'Quick Draw', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 4698, 1), - (582, 'Battle Ready', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 4699, 1), - (583, 'Hastened Outrider\'s Evasion', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 13568, 1), - (584, 'Grasp of Sylvan Spirits', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 13571, 1), - (585, 'Glyph of Dragon Scales', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 4702, 1), - (586, 'Glyph of Indeterminable Reward', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 13788, 1), - (587, 'Glyph of Arcane Secrets', 7, 32318, 65535, 127, 131071, 0, 4, 1, 0, 4704, 1), - (588, 'Glyph of Draconic Potential', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 4705, 1), - (589, 'Glyph of Destruction', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 4706, 1), - (590, 'Breath of Atathus', 8, 65535, 65535, 127, 131071, 0, 4, 0, 1, 5150, 1), - (591, 'Breath of Draton\'ra', 8, 65535, 65535, 127, 131071, 0, 4, 0, 1, 5165, 1), - (592, 'Breath of Osh\'vir', 8, 65535, 65535, 127, 131071, 0, 4, 0, 1, 5180, 1), - (593, 'Breath of Venesh', 8, 65535, 65535, 127, 131071, 0, 4, 0, 1, 5195, 1), - (594, 'Breath of Mysaphar', 8, 65535, 65535, 127, 131071, 0, 4, 0, 1, 5210, 1), - (595, 'Breath of Keikolin', 8, 65535, 65535, 127, 131071, 0, 4, 0, 1, 5225, 1), - (596, 'Small Modulation Shard', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 12963, 1), - (597, 'Medium Modulation Shard', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 12964, 1), - (598, 'Large Modulation Shard', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 12965, 1), - (599, 'Hastened Malosinete', -1, 4608, 65535, 127, 131071, 0, 3, 0, 0, 12968, 1), - (600, 'Blessing of the Devoted', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 9033, 1), - (601, 'Grappling Strike', -1, 65, 65535, 127, 131071, 0, 3, 0, 0, 4836, 1), - (602, 'Mental Contortion', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 12938, 1), - (603, 'Shield of the Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 12971, 1), - (604, 'Extended Malosinete', -1, 4608, 65535, 127, 131071, 0, 3, 0, 0, 12977, 1), - (605, 'Shield Specialist', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 4844, 1), - (606, 'Mark of the Mage Hunter', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 4849, 1), - (609, 'Uncanny Resilience', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 4854, 1), - (610, 'Blinding Fury', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 4857, 1), - (611, 'Battle Leap', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 4860, 1), - (612, 'Soul Seeker', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 4861, 1), - (613, 'Lingering Death', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 13096, 1), - (614, 'Spirit Guardian', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 5369, 1), - (615, 'Surreality', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 4887, 1), - (616, 'Mana Draw', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 4890, 1), - (617, 'Doppelganger\'s Beckon', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 5127, 1), - (618, 'Armor of Ancestral Spirits', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 12989, 1), - (619, 'Group Pact of the Wolf', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 12992, 1), - (620, 'Hastened Inconspicuous Totem', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 13001, 1), - (621, 'Fire Core', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 4903, 1), - (622, 'Vapor Core', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 4906, 1), - (623, 'Ice Core ', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 4909, 1), - (624, 'Stone Core ', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 4912, 1), - (625, 'Volatile Mana Blaze', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 4915, 1), - (626, 'Purified Spirits', -1, 546, 65535, 127, 131071, 0, 3, 0, 0, 13004, 1), - (627, 'Group Spirit Walk', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 13008, 1), - (628, 'Greater Blood Tithe', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 4924, 1), - (629, 'Gathering Dusk', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 4927, 1), - (630, 'Group Silent Presence', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 13009, 1), - (631, 'Double Attack', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 5366, 1), - (632, 'Sanguine Mind Crystal', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 4934, 1), - (633, 'Azure Mind Crystal', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 4935, 1), - (634, 'Hastened Cannibalization', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 13010, 1), - (635, 'Hastened Spirit Channeling', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 13013, 1), - (636, 'Arcane Whisper', -1, 14336, 65535, 127, 131071, 0, 3, 0, 0, 4938, 1), - (637, 'Vengeful Spirits', -1, 9776, 65535, 127, 131071, 0, 3, 0, 0, 13017, 1), - (638, 'Crippling Apparition', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 13020, 1), - (639, 'Dimensional Instability', -1, 14336, 65535, 127, 131071, 0, 3, 0, 0, 4943, 1), - (640, 'Cryomancy', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 4944, 1), - (641, 'Hastened Self Preservation', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13055, 1), - (642, 'Binding Axe', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13065, 1), - (643, 'Agony of Absolution', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13066, 1), - (644, 'Hastened Absolution', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13067, 1), - (645, 'Hastened Calculated Insanity', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 13753, 1), - (646, 'Hastened Mental Contortion', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 13758, 1), - (647, 'Hastened Crippling Aurora', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 13764, 1), - (649, 'Hastened Leech Touch', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 14046, 1), - (650, 'Bony Grasp of Death', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 14051, 1), - (651, 'Thought Leech', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 14052, 1), - (652, 'Hastened Leechcurse Discipline', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 14056, 1), - (653, 'Hastened Unholy Aura Discipline', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 14059, 1), - (654, 'Hastened Harmshield', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 14062, 1), - (655, 'Hastened Projection of Doom', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 14065, 1), - (656, 'Hastened Projection of Piety', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14068, 1), - (657, 'Shield of Brilliance', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14071, 1), - (658, 'Hastened Sanctification Discipline', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14076, 1), - (659, 'Speed of the Savior', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14080, 1), - (660, 'Divine Call', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14081, 1), - (661, 'Hunter\'s Fury', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 5248, 1), - (662, 'Union of Spirits', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 5251, 1), - (663, 'Quickened Stuns', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14100, 1), - (664, 'Extended Outrider\'s Attack', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 14115, 1), - (665, 'Death\'s Wrath', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 5264, 1), - (666, 'Taste of Blood', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 5015, 1), - (667, 'Summoner\'s Beckon', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 5269, 1), - (668, 'Hymn of the Last Stand', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 5017, 1), - (669, 'Bladed Song', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 5020, 1), - (670, 'Twisted Shank', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 5021, 1), - (671, 'Dirty Fighting', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 5022, 1), - (672, 'Ligament Slice', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 5025, 1), - (673, 'Tumble', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 5028, 1), - (674, 'Unknown AA 16149', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 16149, 1), - (675, 'Shrink', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 14224, 1), - (676, 'Convergence', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 14358, 1), - (677, 'Gift of Deathly Resolve', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 14359, 1), - (678, 'Unknown AA 16082', -1, 2080, 65535, 127, 131071, 0, 3, 0, 0, 16082, 1), - (679, 'Unknown AA 16083', -1, 15906, 65535, 127, 131071, 0, 2, 0, 0, 16083, 1), - (680, 'Unknown AA 16084', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 16084, 1), - (681, 'Unknown AA 16087', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 16087, 1), - (682, 'Unknown AA 16096', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 16096, 1), - (683, 'Unknown AA 16097', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 16097, 1), - (684, 'Unknown AA 16104', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16104, 1), - (685, 'Unknown AA 16105', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16105, 1), - (686, 'Unknown AA 16106', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16106, 1), - (687, 'Unknown AA 16107', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16107, 1), - (688, 'Unknown AA 16108', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16108, 1), - (689, 'Combat Medic ', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 5136, 1), - (690, 'Unknown AA 16109', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16109, 1), - (691, 'Unknown AA 16113', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16113, 1), - (692, 'Unknown AA 16114', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16114, 1), - (693, 'Unknown AA 16117', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16117, 1), - (694, 'Unknown AA 16120', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 16120, 1), - (695, 'Unknown AA 16152', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 16152, 1), - (696, 'Unknown AA 16156', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 16156, 1), - (697, 'Mortal Coil', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 5085, 1), - (698, 'Hastened Purified Spirits', -1, 546, 65535, 127, 131071, 0, 3, 0, 0, 13416, 1), - (699, 'Swarm of Fireflies', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 13419, 1), - (700, 'Unknown AA 16159', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 16159, 1), - (701, 'Armor of the Inquisitor', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 5095, 1), - (702, 'Hand of Disruption', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 5098, 1), - (703, 'Quickened Death Bloom', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 14318, 1), - (704, 'Hero\'s Barracks', 9, 65535, 65535, 127, 131071, 0, 4, 0, 1, 14367, 1), - (705, 'Spirit of the White Wolf', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 5105, 1), - (706, 'Unknown AA 16160', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 16160, 1), - (707, 'Pact of the Wolf', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 5109, 1), - (708, 'Enchant Alaran Metal', -1, 8192, 65535, 127, 131071, 0, 3, 0, 1, 13271, 1), - (709, 'Mass Enchant Alaran Metal', -1, 8192, 65535, 127, 131071, 0, 3, 0, 1, 13272, 1), - (710, 'Funeral Pyre', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 14360, 1), - (711, 'Unknown AA 16162', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 16162, 1), - (712, 'Hastened Sanctuary', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 5118, 1), - (713, 'Etherium Blades', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 14129, 1), - (714, 'Hastened Assassination Disciplines', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 14135, 1), - (715, 'Cunning Disguise: Shissar', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 14139, 1), - (716, 'Scout\'s Mastery of Piercing', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 14141, 1), - (717, 'Extended Envenomed Blades', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 14144, 1), - (718, 'Heel of Brithrax', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 14151, 1), - (719, 'Extended Zan Fi\'s Whistle', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 14163, 1), - (720, 'Hastened Marr\'s Salvation', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14088, 1), - (721, 'Hastened Armor of the Inquisitor', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14091, 1), - (722, 'Hastened Drape of Shadows', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 14304, 1), - (723, 'Unknown AA 16185', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 16185, 1), - (724, 'Hastened Eldritch Rune', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 14364, 1), - (725, 'Unknown AA 16124', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 16124, 1), - (726, 'Unknown AA 16128', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 16128, 1), - (727, 'Unknown AA 16131', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 16131, 1), - (728, 'Unknown AA 16137', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 16137, 1), - (729, 'Unknown AA 16140', -1, 6, 65535, 127, 131071, 0, 3, 0, 0, 16140, 1), - (730, 'Unknown AA 16186', -1, 9, 65535, 127, 131071, 0, 3, 0, 0, 16186, 1), - (731, 'Unknown AA 16188', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 16188, 1), - (732, 'Unknown AA 16195', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 16195, 1), - (733, 'Killing Spree', -1, 33089, 65535, 127, 131071, 0, 2, 0, 0, 4739, 1), - (734, 'Hold the Line', -1, 32833, 65535, 127, 131071, 0, 3, 0, 0, 4742, 1), - (735, 'Battle Frenzy', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 13134, 1), - (737, 'Quickened Silent Casting', -1, 15360, 65535, 127, 131071, 0, 2, 0, 0, 13143, 1), - (738, 'Quickened Silent Casting', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 13146, 1), - (739, 'Balefire Burst', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 13164, 1), - (740, 'Blood Tithe', -1, 1568, 65535, 127, 131071, 0, 3, 0, 0, 4761, 1), - (741, 'Leap of Faith', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 13202, 1), - (742, 'Unknown AA 16196', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 16196, 1), - (743, 'Hastened Explosion of Hatred', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 13166, 1), - (744, 'Howl of the Warlord', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 13169, 1), - (745, 'Hastened Tune In Your Head', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 13204, 1), - (746, 'Unknown AA 16197', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 16197, 1), - (747, 'Unknown AA 16200', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 16200, 1), - (748, 'Nightmare Stasis', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 4894, 1), - (749, 'Explosion of Spite', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 13165, 1), - (751, 'Scent of Terris', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 13225, 1), - (752, 'Bloodfury', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13224, 1), - (753, 'Dreary Deeds', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 13252, 1), - (754, 'Enchant Feymetal', -1, 8192, 65535, 127, 131071, 0, 3, 0, 1, 13260, 1), - (755, 'Mass Enchant Feymetal', -1, 8192, 65535, 127, 131071, 0, 3, 0, 1, 13261, 1), - (756, 'Enlightened Focus of Arcanum', -1, 15904, 65535, 127, 131071, 0, 3, 0, 0, 13646, 1), - (757, 'Shifting Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 5276, 1), - (758, 'Extended Silent Casting', -1, 15360, 65535, 127, 131071, 0, 3, 0, 0, 13667, 1), - (759, 'Fury of Kerafyrm', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 13670, 1), - (760, 'Unknown AA 16203', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 16203, 1), - (761, 'Unknown AA 16208', -1, 552, 65535, 127, 131071, 0, 3, 0, 0, 16208, 1), - (762, 'Shield Block', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 5283, 1), - (763, 'Mirrored Pestilence', -1, 1552, 65535, 127, 131071, 0, 3, 0, 0, 13684, 1), - (764, 'Embrace The Decay', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 13687, 1), - (765, 'Quickened Scent of Terris', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 13689, 1), - (766, 'Frenzy of the Dead', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 13693, 1), - (767, 'Unknown AA 16211', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 16211, 1), - (768, 'Unknown AA 16215', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 16215, 1), - (769, 'Marr\'s Salvation', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 13100, 1), - (770, 'Blessing of the Faithful', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 13101, 1), - (771, 'Unbridled Strike of Fear', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 13108, 1), - (772, 'Noteworthy Disguise: Drake', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 14192, 1), - (773, 'Death\'s Effigy', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 13133, 1), - (774, 'Empowered Focus of Arcanum', -1, 15904, 65535, 127, 131071, 0, 3, 0, 0, 14690, 1), - (775, 'Unknown AA 16342', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 16342, 1), - (776, 'Arcane Overkill', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 5295, 1), - (777, 'Funeral Dirge', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 5298, 1), - (778, 'Protection of the Spirit Wolf', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 5007, 1), - (779, 'Hastened Juggernaut Surge', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13873, 1), - (780, 'Hastened Resilience', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13878, 1), - (781, 'Hastened Blood Pact', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13881, 1), - (782, 'Unknown AA 16317', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 16317, 1), - (783, 'Energetic Attunement', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 1056, 1), - (784, 'Heart of Flames', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 1251, 1), - (785, 'Heart of Vapor', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 1252, 1), - (786, 'Heart of Ice', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 1253, 1), - (787, 'Heart of Stone', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 1254, 1), - (789, 'Stealthy Getaway', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 1477, 1), - (790, 'Seized Opportunity', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 878, 1), - (791, 'Veil of Mindshadow', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 4931, 1), - (792, 'Army of the Dead', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 1274, 1), - (793, 'Mana Blast', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1639, 1), - (794, 'Mana Blaze', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 1640, 1), - (795, 'Innate Corruption Protection', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 1662, 1), - (796, 'Hastened Five Point Palm', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 13889, 1), - (797, 'Moving Mountains', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 13130, 1), - (798, 'Veturika\'s Perseverance', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 14229, 1), - (799, 'Unknown AA 16644', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 16644, 1), - (800, 'Vehement Rage', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 6607, 1), - (801, 'Knee Strike', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6610, 1), - (802, 'Hastened Fortitude Discipline', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6611, 1), - (803, 'Hastened Furious Discipline', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6614, 1), - (804, 'Warlord\'s Bravery', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6617, 1), - (805, 'Hastened Speed Focus', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 14148, 1), - (806, 'Hastened Zan Fi\'s Whistle', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 14160, 1), - (807, 'Pressure Points', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 14157, 1), - (808, 'Hastened Thunder', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 14166, 1), - (809, 'Allegretto of Battle', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 14181, 1), - (810, 'Vivace of Conflict', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 14186, 1), - (811, 'Unknown AA 16218', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 16218, 1), - (812, 'Unknown AA 16221', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 16221, 1), - (813, 'Unknown AA 16222', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 16222, 1), - (814, 'Unknown AA 16225', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 16225, 1), - (815, 'Unknown AA 16230', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 16230, 1), - (816, 'Unknown AA 16235', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 16235, 1), - (817, 'Unknown AA 16238', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 16238, 1), - (818, 'Unknown AA 16257', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 16257, 1), - (819, 'Unknown AA 16666', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 16666, 1), - (820, 'Death\'s Revenge', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 6630, 1), - (821, 'Harmshield', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 6635, 1), - (822, 'Explosion of Hatred', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 6640, 1), - (823, 'Cascading Theft of Defense', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 6641, 1), - (824, 'Hate Step', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 6644, 1), - (825, 'Vicious Bite of Chaos', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 6645, 1), - (826, 'Encroaching Darkness', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 6646, 1), - (827, 'Unknown AA 16745', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 16745, 1), - (828, 'Unknown AA 16260', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 16260, 1), - (829, 'Unknown AA 16263', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 16263, 1), - (830, 'Unknown AA 16272', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 16272, 1), - (831, 'Unknown AA 16276', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 16276, 1), - (832, 'Unknown AA 16287', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 16287, 1), - (833, 'Unknown AA 17252', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 17252, 1), - (834, 'Unknown AA 16296', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 16296, 1), - (835, 'Unknown AA 16300', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 16300, 1), - (836, 'Unknown AA 16310', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 16310, 1), - (837, 'Unknown AA 16330', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 16330, 1), - (838, 'Unknown AA 16163', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 16163, 1), - (839, 'Unknown AA 16360', -1, 2080, 65535, 127, 131071, 0, 3, 0, 0, 16360, 1), - (840, 'Unknown AA 16363', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 16363, 1), - (841, 'Sleight of Hand', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6663, 1), - (842, 'Enduring Vision', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6666, 1), - (843, 'Expertise of Blades', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6668, 1), - (844, 'Cunning Disguise: Human', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6671, 1), - (845, 'Cunning Disguise: Half-Elf', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6672, 1), - (846, 'Cunning Disguise: Barbarian', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6673, 1), - (847, 'Cunning Disguise: Erudite', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6674, 1), - (848, 'Cunning Disguise: Troll', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6675, 1), - (849, 'Cunning Disguise: Goblin', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6676, 1), - (850, 'Unknown AA 16366', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 16366, 1), - (851, 'Unknown AA 16369', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 16369, 1), - (852, 'Unknown AA 16370', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 16370, 1), - (853, 'Unknown AA 16371', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 16371, 1), - (854, 'Unknown AA 17256', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 17256, 1), - (856, 'Tigir\'s Insect Swarm', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6691, 1), - (857, 'Dampen Resistance', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6692, 1), - (858, 'Hastened Dampen Resistance', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6697, 1), - (859, 'Spirit Walk', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6702, 1), - (860, 'Hastened Virulent Paralysis', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6703, 1), - (861, 'Languid Bite', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6706, 1), - (862, 'Quickened Blood of Nadox', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6709, 1), - (863, 'Hastened Spirit Call', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6712, 1), - (864, 'Hastened Thousand Blades', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 14169, 1), - (865, 'Unknown AA 17257', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 17257, 1), - (866, 'Extended Dance of Blades', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 14179, 1), - (867, 'Extended Thousand Blades', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 14180, 1), - (868, 'Unknown AA 16380', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 16380, 1), - (869, 'Unknown AA 16386', -1, 4608, 65535, 127, 131071, 0, 3, 0, 0, 16386, 1), - (870, 'Harmonious Arrow', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6750, 1), - (871, 'Hastened Weapon Shield', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6751, 1), - (872, 'Outrider\'s Attack', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6754, 1), - (873, 'Group Guardian of the Forest', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6755, 1), - (874, 'Pack Hunt', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6758, 1), - (875, 'Keen Blade', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6761, 1), - (876, 'Outrider\'s Evasion', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6764, 1), - (877, 'Ranged Finesse', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6765, 1), - (878, 'Bow Mastery', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 1196, 1), - (879, 'Unknown AA 17258', -1, 1040, 65535, 127, 131071, 0, 2, 0, 0, 17258, 1), - (880, 'Unknown AA 16392', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 16392, 1), - (881, 'Unknown AA 16395', -1, 10248, 65535, 127, 131071, 0, 3, 0, 0, 16395, 1), - (882, 'Unknown AA 16396', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 16396, 1), - (883, 'Unknown AA 16536', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 16536, 1), - (884, 'Unknown AA 17209', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 17209, 1), - (885, 'Unknown AA 17212', -1, 1, 65535, 127, 131071, 0, 2, 0, 0, 17212, 1), - (886, 'Unknown AA 17218', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 17218, 1), - (888, 'Unknown AA 17555', -1, 1024, 65535, 127, 131071, 0, 5, 0, 0, 17555, 1), - (889, 'Unknown AA 17229', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 17229, 1), - (890, 'Unknown AA 17235', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 17235, 1), - (891, 'Healing Light', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 6791, 1), - (892, 'Halt the Dead', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 6794, 1), - (894, 'Unknown AA 17242', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 17242, 1), - (895, 'Unknown AA 17245', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 17245, 1), - (896, 'Unknown AA 17249', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 17249, 1), - (897, 'Unknown AA 17199', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 17199, 1), - (898, 'Unknown AA 17267', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 17267, 1), - (899, 'Unknown AA 17273', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 17273, 1), - (900, 'Rise of Bones', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 6815, 1), - (901, 'Whisperwind', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 6818, 1), - (902, 'Hastened Blood Magic', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 6819, 1), - (903, 'Overpower Undead', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 6822, 1), - (904, 'Hastened Swarm of Decay', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 6823, 1), - (905, 'Gift of the Grave', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 6828, 1), - (906, 'Hastened Gut Punch', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10522, 1), - (907, 'Hastened First Spire of the Warlord', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10527, 1), - (908, 'Hastened Second Spire of the Warlord', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10532, 1), - (909, 'Hastened Third Spire of the Warlord', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10537, 1), - (910, 'Unknown AA 17280', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 17280, 1), - (911, 'Warlord\'s Resurgence', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10545, 1), - (912, 'Warlord\'s Fury', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10546, 1), - (914, 'Improved Shield Specialist', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10548, 1), - (915, 'Unknown AA 17281', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 17281, 1), - (917, 'Hastened Grappling Strike', -1, 65, 65535, 127, 131071, 0, 3, 0, 0, 10588, 1), - (918, 'Furious Refrain', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 10627, 1), - (919, 'Unknown AA 17554', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 17554, 1), - (920, 'Valorous Rage', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10711, 1), - (921, 'Hastened Group Guardian of the Forest', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10714, 1), - (922, 'Hastened Outrider\'s Attack', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10719, 1), - (923, 'Hastened Protection of the Spirit Wolf', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10722, 1), - (924, 'Hastened Imbued Ferocity', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10727, 1), - (925, 'Hastened Harmonious Arrow', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10730, 1), - (926, 'Hastened Entrap', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10733, 1), - (927, 'Poison Arrows', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10736, 1), - (928, 'Merciless Blade', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 14026, 1), - (929, 'Combatant\'s Pact', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 14029, 1), - (930, 'Warlord\'s Resolve', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 14032, 1), - (931, 'Hastened Hate\'s Attraction', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 12582, 1), - (932, 'Unknown AA 17289', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 17289, 1), - (933, 'Improved Death Peace', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 12635, 1), - (934, 'Unknown AA 17307', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 17307, 1), - (935, 'Blessing of Ro', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10789, 1), - (936, 'Extended Wild Growth', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 10792, 1), - (937, 'Unknown AA 17317', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 17317, 1), - (938, 'Eyes Wide Open', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 12636, 1), - (939, 'Communion of the Cheetah', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 12638, 1), - (940, 'Hastened Song of Stone', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6870, 1), - (941, 'Flurry', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6873, 1), - (942, 'Destructive Cascade', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6876, 1), - (943, 'Total Domination', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6879, 1), - (944, 'Enhanced Forgetfulness', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6882, 1), - (945, 'Infusion of Thunder', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 10346, 1), - (946, 'Hastened Warlord\'s Bravery', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 14037, 1), - (947, 'Hastened Warlord\'s Tenacity', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 14040, 1), - (948, 'Unknown AA 17328', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 17328, 1), - (949, 'Unknown AA 17329', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 17329, 1), - (950, 'Unknown AA 17336', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 17336, 1), - (951, 'Unknown AA 17339', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 17339, 1), - (952, 'Unknown AA 17342', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 17342, 1), - (953, 'Unknown AA 17344', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 17344, 1), - (954, 'Unknown AA 17347', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 17347, 1), - (955, 'Unknown AA 17357', -1, 514, 65535, 127, 131071, 0, 2, 0, 0, 17357, 1), - (956, 'Unknown AA 17361', -1, 2080, 65535, 127, 131071, 0, 3, 0, 0, 17361, 1), - (957, 'Unknown AA 17364', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 17364, 1), - (958, 'Unknown AA 17370', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 17370, 1), - (959, 'Unknown AA 17372', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 17372, 1), - (960, 'Stomping Leap', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 6930, 1), - (961, 'Juggernaut Surge', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6931, 1), - (962, 'Distraction Attack', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6932, 1), - (963, 'Hastened Savage Spirit', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6935, 1), - (964, 'Dying Blow', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6938, 1), - (965, 'Hastened Projection of Fury', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10519, 1), - (966, 'Unknown AA 17373', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 17373, 1), - (967, 'Blade Guardian', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 13444, 1), - (968, 'Unknown AA 17375', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 17375, 1), - (969, 'Unknown AA 17378', -1, 15360, 65535, 127, 131071, 0, 2, 0, 0, 17378, 1), - (970, 'Unknown AA 17378', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 17379, 1), - (971, 'Unknown AA 17378', -1, 16384, 65535, 127, 131071, 0, 2, 0, 0, 17380, 1), - (972, 'Unknown AA 17384', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 17384, 1), - (974, 'Unknown AA 17409', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 17409, 1), - (975, 'Unknown AA 17414', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 17414, 1), - (976, 'Unknown AA 17418', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 17418, 1), - (977, 'Unknown AA 17558', -1, 1024, 65535, 127, 131071, 0, 5, 0, 0, 17558, 1), - (978, 'Unknown AA 17428', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 17428, 1), - (979, 'Unknown AA 17436', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 17436, 1), - (980, 'Natural Invisibility', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6970, 1), - (981, 'Attack of the Warders', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6971, 1), - (982, 'Hastened Feral Attacks', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6974, 1), - (983, 'Hastened Focused Paragon', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6977, 1), - (984, 'Hastened Paragon', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6980, 1), - (985, 'Group Bestial Alignment', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6983, 1), - (986, 'Bite of the Asp', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6984, 1), - (987, 'Raven\'s Claw', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6985, 1), - (988, 'Gorilla Smash', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6986, 1), - (989, 'Stonefoot', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 10340, 1), - (990, 'Hastened Stunning Kick', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 10343, 1), - (991, 'Quickened Turn Undead', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10470, 1), - (992, 'Tranquil Blessings', -1, 30254, 65535, 127, 131071, 0, 3, 0, 0, 3676, 1), - (993, 'Righteous Zeal', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6082, 1), - (994, 'Hastened Divine Retribution', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6088, 1), - (995, 'Intrinsic Efficiency', -1, 15386, 65535, 127, 131071, 0, 2, 0, 0, 6112, 1), - (996, 'Powerful Elixirs', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6113, 1), - (997, 'Celestial Rapidity', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6534, 1), - (998, 'Hastened Celestial Regeneration', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 2400, 1), - (999, 'Improved Burst of Life', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7765, 1), - (1000, 'Unknown AA 17439', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 17439, 1), - (1001, 'Unknown AA 17445', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 17445, 1), - (1002, 'Unknown AA 17448', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 17448, 1), - (1003, 'Unknown AA 10478', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10478, 1), - (1004, 'Unknown AA 17492', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 17492, 1), - (1005, 'Unknown AA 17495', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 17495, 1), - (1006, 'Unknown AA 17515', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 17515, 1), - (1007, 'Unknown AA 17517', -1, 5120, 65535, 127, 131071, 0, 3, 0, 0, 17517, 1), - (1008, 'Unknown AA 17522', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 17522, 1), - (1009, 'Unknown AA 17533', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 17533, 1), - (1011, 'Neshika\'s Blink', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 7869, 1), - (1012, 'Five Point Palm', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 7875, 1), - (1013, 'War Cry of the Braxi', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 13872, 1), - (1014, 'Unknown AA 17538', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 17538, 1), - (1015, 'Unknown AA 17547', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 17547, 1), - (1016, 'Unknown AA 17549', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 17549, 1), - (1017, 'Unknown AA 17238', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 17238, 1), - (1018, 'Unknown AA 17553', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 17553, 1), - (1019, 'Unknown AA 17248', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 17248, 1), - (1020, 'Hastened Companion\'s Blessing', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 12478, 1), - (1021, 'Unknown AA 17215', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 17215, 1), - (1022, 'Destructive Fury', -1, 16540, 65535, 127, 131071, 0, 2, 0, 0, 6636, 1), - (1023, 'Restoration of Life', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14010, 1), - (1024, 'Hastened Leap of Faith', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14085, 1), - (1025, 'Hastened Beacon of the Righteous', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 14011, 1), - (1026, 'Unknown AA 17561', -1, 1024, 65535, 127, 131071, 0, 5, 0, 0, 17561, 1), - (1027, 'Unknown AA 17564', -1, 1024, 65535, 127, 131071, 0, 5, 0, 0, 17564, 1), - (1028, 'Unknown AA 17567', -1, 1024, 65535, 127, 131071, 0, 5, 0, 0, 17567, 1), - (1029, 'Unknown AA 17570', -1, 1024, 65535, 127, 131071, 0, 5, 0, 0, 17570, 1), - (1030, 'Unknown AA 17573', -1, 1024, 65535, 127, 131071, 0, 5, 0, 0, 17573, 1), - (1031, 'Unknown AA 17576', -1, 2048, 65535, 127, 131071, 0, 5, 0, 0, 17576, 1), - (1032, 'Unknown AA 17579', -1, 2048, 65535, 127, 131071, 0, 5, 0, 0, 17579, 1), - (1033, 'Unknown AA 17582', -1, 2048, 65535, 127, 131071, 0, 5, 0, 0, 17582, 1), - (1034, 'Unknown AA 17585', -1, 2048, 65535, 127, 131071, 0, 5, 0, 0, 17585, 1), - (1035, 'Unknown AA 17588', -1, 2048, 65535, 127, 131071, 0, 5, 0, 0, 17588, 1), - (1036, 'Unknown AA 17591', -1, 2048, 65535, 127, 131071, 0, 5, 0, 0, 17591, 1), - (1037, 'Unknown AA 17594', -1, 2048, 65535, 127, 131071, 0, 5, 0, 0, 17594, 1), - (1038, 'Unknown AA 17597', -1, 4096, 65535, 127, 131071, 0, 5, 0, 0, 17597, 1), - (1039, 'Unknown AA 17600', -1, 4096, 65535, 127, 131071, 0, 5, 0, 0, 17600, 1), - (1040, 'Theft of Essence', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 7900, 1), - (1041, 'Malosinete', -1, 4608, 65535, 127, 131071, 0, 3, 0, 0, 7903, 1), - (1042, 'Unknown AA 17603', -1, 4096, 65535, 127, 131071, 0, 5, 0, 0, 17603, 1), - (1043, 'Unknown AA 17606', -1, 4096, 65535, 127, 131071, 0, 5, 0, 0, 17606, 1), - (1044, 'Unknown AA 17609', -1, 4096, 65535, 127, 131071, 0, 5, 0, 0, 17609, 1), - (1045, 'Unknown AA 17612', -1, 4096, 65535, 127, 131071, 0, 5, 0, 0, 17612, 1), - (1046, 'Unknown AA 17615', -1, 4096, 65535, 127, 131071, 0, 5, 0, 0, 17615, 1), - (1047, 'Unknown AA 17618', -1, 8192, 65535, 127, 131071, 0, 5, 0, 0, 17618, 1), - (1048, 'Unknown AA 17621', -1, 8192, 65535, 127, 131071, 0, 5, 0, 0, 17621, 1), - (1049, 'Unknown AA 17624', -1, 8192, 65535, 127, 131071, 0, 5, 0, 0, 17624, 1), - (1050, 'Unknown AA 17627', -1, 8192, 65535, 127, 131071, 0, 5, 0, 0, 17627, 1), - (1051, 'Unknown AA 17630', -1, 8192, 65535, 127, 131071, 0, 5, 0, 0, 17630, 1), - (1052, 'Unknown AA 17633', -1, 8192, 65535, 127, 131071, 0, 5, 0, 0, 17633, 1), - (1053, 'Unknown AA 10481', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 10481, 1), - (1054, 'Unknown AA 17639', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 17639, 1), - (1060, 'Hastened Turn Undead', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7940, 1), - (1061, 'Cascading Divine Aura', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7943, 1), - (1062, 'Group Purify Soul', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7944, 1), - (1063, 'Hastened Renewal', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7945, 1), - (1064, 'Sanctified Blessing', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7948, 1), - (1065, 'Focused Celestial Regeneration', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7951, 1), - (1090, 'Mastery of Nature', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 7980, 1), - (1091, 'Hastened Nature\'s Guardian', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 7983, 1), - (1092, 'Spirit of the Black Wolf', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 7986, 1), - (1093, 'Hastened Lycan Soul', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 7989, 1), - (1113, 'Hastened Mass Group Buff', -1, 30254, 65535, 127, 131071, 0, 3, 0, 0, 5010, 1), - (1115, 'Mystical Shield', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 5045, 1), - (1120, 'Self Stasis', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 8030, 1), - (1121, 'Hastened Veil of Mindshadow', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 8031, 1), - (1122, 'Phantasmal Opponent', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 8034, 1), - (1123, 'Hastened Edict of Command', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 8035, 1), - (1124, 'Fog of Memories', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 8038, 1), - (1125, 'Bite of Tashani', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 8039, 1), - (1150, 'Fury of Druzzil', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 8060, 1), - (1151, 'Fury of Eci', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 8063, 1), - (1152, 'Fury of Ro', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 8066, 1), - (1153, 'Fortified Entanglement', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 8069, 1), - (1154, 'Force of Will', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 8072, 1), - (1155, 'Atol\'s Shackles', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 8075, 1), - (1156, 'Hastened Manaburn', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 8076, 1), - (1157, 'Hastened Call of Xuzl', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 8082, 1), - (1158, 'Divine Steed', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 1667, 1), - (1159, 'Hastened Leap', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 11014, 1), - (1169, 'Unknown AA 16336', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 16336, 1), - (1170, 'Unknown AA 16339', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 16339, 1), - (1171, 'Hastened Counterattack Discipline', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 15502, 1), - (1173, 'Hastened Onslaught', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 15509, 1), - (1174, 'Mrylokar\'s Rigor', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 15512, 1), - (1175, 'Absorbing Agent', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 15515, 1), - (1176, 'Improved Requiem of Time', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 15516, 1), - (1177, 'Quickened Requiem of Time', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 15517, 1), - (1178, 'Silent Displacement', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 15521, 1), - (1200, 'Companion\'s Alacrity', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 8190, 1), - (1201, 'Improved Intimidation', -1, 41408, 65535, 127, 131071, 0, 2, 0, 1, 8193, 1), - (1202, 'Perfected Levitation', -1, 31272, 65535, 127, 131071, 0, 2, 0, 0, 8194, 1), - (1203, 'Hastened Fortify Companion', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 8195, 1), - (1204, 'Empowered Ingenuity', -1, 33089, 65535, 127, 131071, 0, 2, 0, 0, 8198, 1), - (1205, 'Companion\'s Fury', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 8201, 1), - (1206, 'Quickened Radiant Cure', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 8204, 1), - (1207, 'Quickened Radiant Cure', -1, 4, 65535, 127, 131071, 0, 2, 0, 0, 8207, 1), - (1208, 'Mental Stamina', -1, 32446, 65535, 127, 131071, 0, 2, 0, 0, 8210, 1), - (1209, 'Hardy Endurance', -1, 33089, 65535, 127, 131071, 0, 2, 0, 0, 8215, 1), - (1210, 'Group Perfected Invisibility', -1, 14336, 65535, 127, 131071, 0, 3, 0, 0, 8220, 1), - (1211, 'Focus of Arcanum', -1, 15904, 65535, 127, 131071, 0, 3, 0, 0, 8221, 1), - (1212, 'Group Perfected Invisibility to Undead', -1, 1046, 65535, 127, 131071, 0, 2, 0, 0, 8222, 1), - (1214, 'Cascade of Life', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 8224, 1), - (1215, 'Summon Companion', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 8227, 1), - (1216, 'Mental Fortitude', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 8228, 1), - (1217, 'Gate', -1, 15906, 65535, 127, 131071, 0, 2, 0, 0, 8231, 1), - (1218, 'Extended Ingenuity', -1, 128, 65535, 127, 131071, 0, 2, 0, 0, 8040, 1), - (1219, 'Armor of Wisdom', -1, 1, 65535, 127, 131071, 0, 2, 0, 0, 8235, 1), - (1220, 'Armor of Wisdom', -1, 20, 65535, 127, 131071, 0, 2, 0, 0, 8240, 1), - (1221, 'Armor of Wisdom', -1, 202, 65535, 127, 131071, 0, 2, 0, 0, 8245, 1), - (1222, 'Armor of Wisdom', -1, 49920, 65535, 127, 131071, 0, 2, 0, 0, 8250, 1), - (1223, 'Armor of Wisdom', -1, 15392, 65535, 127, 131071, 0, 2, 0, 0, 8255, 1), - (1232, 'Way of the Katori', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15429, 1), - (1233, 'Harmony of Battle', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15432, 1), - (1234, 'Hastened Ironfist', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15438, 1), - (1235, 'Two-Finger Wasp Touch', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15447, 1), - (1236, 'Thunderfoot', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15444, 1), - (1237, 'Extended Bloodlust', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 15414, 1), - (1239, 'Consumption of Spirit', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 15423, 1), - (1240, 'Frenzied Swipes', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 15424, 1), - (1242, 'Hastened Synergy', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15450, 1), - (1243, 'Hastened Crane Stance', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15453, 1), - (1244, 'Hastened Eye Gouge', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 15456, 1), - (1245, 'Troubadour\'s Slashing Mastery', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 15540, 1), - (1246, 'Troubadour\'s Blunt Mastery', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 15543, 1), - (1247, 'Troubadour\'s Piercing Mastery', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 15546, 1), - (1248, 'Hastened Lure of the Siren\'s Song', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 15549, 1), - (1249, 'Frenzied Axe of Rallos', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 15555, 1), - (1250, 'Juggernaut\'s Mastery of Throwing', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 15564, 1), - (1251, 'Furious Rampage', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 15567, 1), - (1252, 'Battle Stomp', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 15569, 1), - (1253, 'Communion of Blood', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 15570, 1), - (1254, 'Hastened Dying Grasp', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 15571, 1), - (1255, 'Rest the Dead', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 15574, 1), - (1256, 'Extended Encroaching Darkness', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 15579, 1), - (1257, 'Hand of Death', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 15582, 1), - (1258, 'Quickened Levant', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 15591, 1), - (1259, 'Cascade of Decay', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 15594, 1), - (1261, 'Hastened Fury of the Gods', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 15598, 1), - (1262, 'Lower Element', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 15601, 1), - (1263, 'Destructive Adept', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 15602, 1), - (1264, 'Arcane Fusion', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 15609, 1), - (1265, 'Arcane Destruction', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 15611, 1), - (1266, 'Force of Flame', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 15612, 1), - (1267, 'Force of Ice', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 15615, 1), - (1269, 'Sha\'s Reprisal', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 15425, 1), - (1270, 'Crippling Spirit', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 15377, 1), - (1271, 'Quick Damage', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 15622, 1), - (1272, 'Assassin\'s Wrath', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 15625, 1), - (1273, 'Hastened Swiftblade', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 15634, 1), - (1274, 'Improved Explosion of Spite', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15639, 1), - (1275, 'Improved Explosion of Hatred', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15640, 1), - (1277, 'Soul Touch', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15642, 1), - (1278, 'Soul Flay', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15643, 1), - (1279, 'Ragged Bite of Agony', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15646, 1), - (1281, 'Everburn', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 15648, 1), - (1282, 'Marr\'s Gift', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15619, 1), - (1300, 'Fundament of Intellect', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 9100, 1), - (1301, 'Fundament of Intellect', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 9109, 1), - (1302, 'Fundament of Intellect', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 9118, 1), - (1303, 'Fundament of Intellect', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 9127, 1), - (1304, 'Fundament of Wisdom', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 9136, 1), - (1305, 'Fundament of Wisdom', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 9145, 1), - (1306, 'Fundament of Wisdom', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 9154, 1), - (1307, 'Fundament of Power', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 9163, 1), - (1308, 'Fundament of Power', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 9172, 1), - (1309, 'Fundament of Power', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 9181, 1), - (1310, 'Fundament of Power', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 9190, 1), - (1311, 'Fundament of Power', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 9199, 1), - (1312, 'Fundament of Combat', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 9208, 1), - (1313, 'Fundament of Combat', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 9217, 1), - (1314, 'Fundament of Combat', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 9226, 1), - (1315, 'Fundament of Combat', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 9235, 1), - (1350, 'Fundament: First Spire of Arcanum', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 9300, 1), - (1351, 'Fundament: Second Spire of Arcanum', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 9303, 1), - (1352, 'Fundament: Third Spire of Arcanum', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 9306, 1), - (1360, 'Fundament: First Spire of the Sensei', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 9309, 1), - (1361, 'Fundament: Second Spire of the Sensei', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 9312, 1), - (1362, 'Fundament: Third Spire of the Sensei', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 9315, 1), - (1370, 'Fundament: First Spire of the Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 9318, 1), - (1371, 'Fundament: Second Spire of the Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 9321, 1), - (1372, 'Fundament: Third Spire of the Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 9324, 1), - (1380, 'Fundament: First Spire of Enchantment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 9327, 1), - (1381, 'Fundament: Second Spire of Enchantment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 9330, 1), - (1382, 'Fundament: Third Spire of Enchantment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 9333, 1), - (1390, 'Fundament: First Spire of Necromancy', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 9336, 1), - (1391, 'Fundament: Second Spire of Necromancy', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 9339, 1), - (1392, 'Fundament: Third Spire of Necromancy', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 9342, 1), - (1400, 'Fundament: First Spire of the Warlord', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 9345, 1), - (1401, 'Fundament: Second Spire of the Warlord', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 9348, 1), - (1402, 'Fundament: Third Spire of the Warlord', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 9351, 1), - (1403, 'Sturdy Companion', -1, 30224, 65535, 127, 131071, 0, 3, 0, 0, 9503, 1), - (1404, 'Extended Swarm', -1, 32306, 65535, 127, 131071, 0, 3, 0, 0, 9506, 1), - (1405, 'Twincast', -1, 15906, 65535, 127, 131071, 0, 3, 0, 0, 9509, 1), - (1406, 'Staff Block', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 9512, 1), - (1410, 'Fundament: First Spire of the Rake', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 9354, 1), - (1411, 'Fundament: Second Spire of the Rake', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 9357, 1), - (1412, 'Fundament: Third Spire of the Rake', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 9360, 1), - (1420, 'Fundament: First Spire of the Minstrels', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 9363, 1), - (1421, 'Fundament: Second Spire of the Minstrels', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 9366, 1), - (1422, 'Fundament: Third Spire of the Minstrels', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 9369, 1), - (1430, 'Fundament: First Spire of the Savage Lord', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 9372, 1), - (1431, 'Fundament: Second Spire of the Savage Lord', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 9375, 1), - (1432, 'Fundament: Third Spire of the Savage Lord', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 9378, 1), - (1433, 'Extended Ingenuity', -1, 33089, 65535, 127, 131071, 0, 2, 0, 0, 8232, 1), - (1440, 'Fundament: First Spire of Holiness', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 9381, 1), - (1441, 'Fundament: Second Spire of Holiness', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 9384, 1), - (1442, 'Fundament: Third Spire of Holiness', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 9387, 1), - (1450, 'Fundament: First Spire of the Reavers', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 9390, 1), - (1451, 'Fundament: Second Spire of the Reavers', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 9393, 1), - (1452, 'Fundament: Third Spire of the Reavers', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 9396, 1), - (1460, 'Fundament: First Spire of the Pathfinders', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 9399, 1), - (1461, 'Fundament: Second Spire of the Pathfinders', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 9402, 1), - (1462, 'Fundament: Third Spire of the Pathfinders', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 9405, 1), - (1470, 'Fundament: First Spire of Divinity', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 9408, 1), - (1471, 'Fundament: Second Spire of Divinity', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 9411, 1), - (1472, 'Fundament: Third Spire of Divinity', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 9414, 1), - (1480, 'Fundament: First Spire of Nature', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 9417, 1), - (1481, 'Fundament: Second Spire of Nature', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 9420, 1), - (1482, 'Fundament: Third Spire of Nature', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 9423, 1), - (1490, 'Fundament: First Spire of Ancestors', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 9426, 1), - (1491, 'Fundament: Second Spire of Ancestors', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 9429, 1), - (1492, 'Fundament: Third Spire of Ancestors', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 9432, 1), - (1500, 'Fundament: First Spire of Savagery', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 9435, 1), - (1501, 'Fundament: Second Spire of Savagery', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 9438, 1), - (1502, 'Fundament: Third Spire of Savagery', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 9441, 1), - (1503, 'Hallowed Steed', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 13673, 1), - (1504, 'Wicked Steed', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 13674, 1), - (1505, 'Unknown AA 16103', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 16103, 1), - (1580, 'Divine Companion Aura', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 5809, 1), - (1662, 'Spell Casting Mastery', -1, 16412, 65535, 127, 131071, 0, 2, 0, 0, 1216, 1), - (1663, 'Gift of Mana', -1, 16412, 65535, 127, 131071, 0, 2, 0, 0, 1219, 1), - (1664, 'Twinproc', -1, 50175, 65535, 127, 131071, 0, 3, 0, 0, 12416, 1), - (1665, 'Tactical Mastery', -1, 16596, 65535, 127, 131071, 0, 3, 0, 0, 12419, 1), - (1666, 'Group Perfected Levitation', -1, 31272, 65535, 127, 131071, 0, 2, 0, 0, 12422, 1), - (1667, 'Quickened Encroaching Darkness', -1, 1040, 65535, 127, 131071, 0, 2, 0, 0, 6026, 1), - (1668, 'Acute Focus of Arcanum', -1, 15904, 65535, 127, 131071, 0, 3, 0, 0, 8260, 1), - (1669, 'Flurry', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 5806, 1), - (1680, 'Hastened Flash of Anger', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 13905, 1), - (1681, 'Hastened Bazu Roar', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 13908, 1), - (1682, 'Hastened Scowl', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 13911, 1), - (1683, 'Hastened Mark of the Mage Hunter', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 13917, 1), - (1684, 'Knowledge of Alaran Culture', 2, 65535, 65535, 127, 131071, 0, 4, 0, 0, 14017, 1), - (1685, 'Knowledge of Alaran Culture - Advanced', 2, 65535, 65535, 127, 131071, 0, 4, 0, 0, 14018, 1), - (1686, 'Brace For Impact', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 14019, 1), - (1687, 'Summon Tome of the Hero\'s Journey', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 14371, 1), - (1800, 'Enchant Planar Alloy', -1, 8192, 65535, 127, 131071, 0, 3, 0, 1, 14373, 1), - (1801, 'Mass Enchant Planar Alloy', -1, 8192, 65535, 127, 131071, 0, 3, 0, 1, 14374, 1), - (2000, 'Armor of Experience', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 4700, 1), - (2001, 'Sneering Grin', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15096, 1), - (2002, 'Warlord\'s Grasp', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15099, 1), - (2003, 'Hastened Press the Attack', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15100, 1), - (2004, 'Hastened Rage of Rallos Zek', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15105, 1), - (2005, 'Hastened Unbroken Attention', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15108, 1), - (2006, 'Extended Resplendant Glory', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15113, 1), - (2007, 'Wars Sheol\'s Heroic Blade', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15119, 1), - (2008, 'Hastened Vehement Rage', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15120, 1), - (2009, 'Hastened Barbed Tongue', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15123, 1), - (2010, 'Hastened Shield Topple', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15126, 1), - (2011, 'Imperator\'s Command', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15129, 1), - (2012, 'Imperator\'s Charge', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15130, 1), - (2013, 'Imperator\'s Precision', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 15131, 1), - (2014, 'Hastened Divine Call', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15132, 1), - (2015, 'Extended Divine Call', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15135, 1), - (2016, 'Heroic Leap', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15136, 1), - (2018, 'Helix of the Undying', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 15146, 1), - (2019, 'Group Armor of the Inquisitor', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15147, 1), - (2020, 'Quickened Demand For Honor', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15150, 1), - (2021, 'Extended Sanctification', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15153, 1), - (2022, 'Extended Speed of the Savior', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15154, 1), - (2023, 'Extended Preservation of Marr', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15155, 1), - (2024, 'Extended Shield of Brilliance', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15158, 1), - (2025, 'Extended Blessing of the Faithful', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15159, 1), - (2026, 'Hastened Speed of the Savior', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15162, 1), - (2028, 'Hastened Shield of Brilliance', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 15168, 1), - (2031, 'Purity of Death', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15177, 1), - (2032, 'Quickened Scourge Skin', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15179, 1), - (2034, 'Gift of the Quick Spear', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15193, 1), - (2035, 'Extended Provocation for Power', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 15194, 1), - (2036, 'Quickened Auspice of the Hunter', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 15253, 1), - (2037, 'Chameleon\'s Gift', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 15304, 1), - (2040, 'Hastened Enraging Kicks', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 15283, 1), - (2041, 'Close Combat Mastery', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 15288, 1), - (2042, 'Quickened Cover Tracks', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 15295, 1), - (2045, 'Shield of Reverence', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 15338, 1), - (2046, 'Extended Healing Frenzy', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 15342, 1), - (2047, 'Call of the Herald', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 15343, 1), - (2048, 'Covenant of Spirit', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 15356, 1), - (2049, 'Talisman of Celerity', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 15357, 1), - (2050, 'Extended Spiritual Blessing', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 15358, 1), - (2051, 'Rejuvenation of Spirit', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 15362, 1), - (2053, 'Hastened Turgur\'s Swarm', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 15371, 1), - (2054, 'Shielding of Spirits', -1, 16930, 65535, 127, 131071, 0, 2, 0, 0, 15374, 1), - (2055, 'Hastened Lunar Healing', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 15383, 1), - (2056, 'Quickened Blessing of Ro', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 15389, 1), - (2057, 'Hastened Wall of Wind', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 15403, 1), - (2059, 'Quickened Focused Paragon of Spirit', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 15406, 1), - (2060, 'Elemental Ward', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15200, 1), - (2061, 'Cloak of Shadows', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15203, 1), - (2062, 'Hastened Elemental Union', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15204, 1), - (2063, 'Hastened Virulent Talon', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15207, 1), - (2064, 'Wind of Malosinete', -1, 4608, 65535, 127, 131071, 0, 3, 0, 0, 15210, 1), - (2065, 'Mana Reserve', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15213, 1), - (2066, 'Second Wind Ward', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15214, 1), - (2076, 'Steel Vengeance', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15217, 1), - (2077, 'Extended Vapor Core', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15220, 1), - (2078, 'Extended Stone Core', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15223, 1), - (2079, 'Extended Fire Core', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15226, 1), - (2080, 'Extended Ice Core', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15229, 1), - (2081, 'Flames of Power', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 15232, 1), - (2200, 'Rune of Banishment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15475, 1), - (2201, 'Hastened Glyph Spray', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15478, 1), - (2202, 'Illusions of Grandeur', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15481, 1), - (2203, 'Illusory Ally', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15482, 1), - (2204, 'Gracious Gift of Mana', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15485, 1), - (2205, 'Chromatic Haze', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15486, 1), - (2206, 'Blanket of Forgetfulness', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15489, 1), - (2207, 'Ethereal Manipulation', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15490, 1), - (2208, 'Quick Mezz', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15493, 1), - (2209, 'Reactive Rune', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 15496, 1), - (2234, 'Cover Tracks', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10368, 1), - (2235, 'Imbued Ferocity', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10387, 1), - (2709, 'Perfected Dead Man Floating', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 13692, 1), - (2899, 'Levant', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 10700, 1), - (3000, 'Auroria Mastery', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 6987, 1), - (3202, 'Pet Discipline', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 7733, 1), - (3203, 'Enchant Palladium Trio', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7736, 1), - (3204, 'Mass Enchant Palladium', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7737, 1), - (3205, 'Greater Mass Enchant Palladium', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7738, 1), - (3206, 'Enchant Dwerium', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7732, 1), - (3207, 'Mass Enchant Dwerium', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7734, 1), - (3208, 'Enchant Palladium', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7735, 1), - (3209, 'Enchant Temporite', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7739, 1), - (3210, 'Mass Enchant Temporite', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7740, 1), - (3211, 'Nature\'s Reprieve', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10388, 1), - (3212, 'Hastened Divine Intervention', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10358, 1), - (3213, 'Projection of Fury', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 10351, 1), - (3214, 'Improved Atone', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10364, 1), - (3215, 'Projection of Doom', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 10352, 1), - (3216, 'Projection of Piety', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10353, 1), - (3217, 'Hastened Jolting Kicks', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 12500, 1), - (3218, 'Enchant Cosgrite', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7741, 1), - (3219, 'Mass Enchant Cosgrite', 6, 8192, 65535, 127, 131071, 0, 3, 0, 1, 7742, 1), - (3500, 'Blessing of Light', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10355, 1), - (3506, 'Fierce Eye', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 5717, 1), - (3511, 'Punch Mastery', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 6020, 1), - (3512, 'Companion\'s Durability', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 6051, 1), - (3513, 'Rake\'s Deadly Aim', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6322, 1), - (3514, 'Rogue\'s Fury', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6325, 1), - (3515, 'Envenomed Blades', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6328, 1), - (3516, 'Companion of Necessity', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 6333, 1), - (3517, 'Rake\'s Powerful Aim', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6334, 1), - (3518, 'Hastened Cacophony', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6337, 1), - (3519, 'Hastened Funeral Dirge', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6340, 1), - (3520, 'Master\'s Hastened Combination', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 6343, 1), - (3521, 'Hastened Silent Casting', -1, 546, 65535, 127, 131071, 0, 2, 0, 0, 6346, 1), - (3522, 'Hastened Silent Casting', -1, 15360, 65535, 127, 131071, 0, 2, 0, 0, 6349, 1), - (3525, 'Precise Blow', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 5776, 1), - (3550, 'Beguiler\'s Banishment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 5849, 1), - (3551, 'Beguiler\'s Directed Banishment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 5870, 1), - (3600, 'Rapid Defiance', 1, 1, 65535, 127, 131071, 0, 3, 0, 1, 6136, 1), - (3646, 'Blast of Anger', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6135, 1), - (3676, 'Gift of Life', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10354, 1), - (3701, 'Dirge of the Sleepwalker', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6200, 1), - (3702, 'Quick Time', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6201, 1), - (3703, 'Steady Hands ', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6202, 1), - (3704, 'Selo\'s Sonata', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6205, 1), - (3705, 'Companion\'s Blessing ', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 6206, 1), - (3706, 'Hastened Bestial Alignment ', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6209, 1), - (3707, 'Fortify Companion ', -1, 30224, 65535, 127, 131071, 0, 2, 0, 0, 6212, 1), - (3708, 'Burst of Power ', -1, 20, 65535, 127, 131071, 0, 2, 0, 0, 6215, 1), - (3709, 'Pact of the Wurine', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6218, 1), - (3710, 'Reckless Abandon ', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6219, 1), - (3711, 'Gift of Resurrection', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 6222, 1), - (3713, 'Hastened Call of the Wild ', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 6228, 1), - (3714, 'Protection of Direwood', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 6232, 1), - (3716, 'Clinging Root ', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 6236, 1), - (3718, 'Critical Affliction', -1, 8194, 65535, 127, 131071, 0, 2, 0, 0, 6240, 1), - (3720, 'Mana Overburn ', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 6249, 1), - (3724, 'Knight\'s Return Strike ', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 6266, 1), - (3725, 'Hunter\'s Return Kick ', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6269, 1), - (3726, 'Hastened Ligament Slice ', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6272, 1), - (3727, 'Knave\'s Return Strike', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 6275, 1), - (3728, 'Storm Strike', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 6278, 1), - (3729, 'Turgur\'s Swarm', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6281, 1), - (3730, 'Silent Presence', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6282, 1), - (3731, 'Infused by Rage ', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6283, 1), - (3732, 'Gut Punch', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6286, 1), - (3733, 'Warlord\'s Return Kick', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6287, 1), - (3734, 'Arcomancy ', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 6290, 1), - (3800, 'Blessing of Resurrection', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6299, 1), - (3801, 'General Sturdiness', -1, 65535, 65535, 127, 131071, 0, 1, 0, 0, 6119, 1), - (3802, 'Shield Block', -1, 392, 65535, 127, 131071, 0, 2, 0, 0, 6124, 1), - (3803, 'Hastened Trueshot', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6355, 1), - (3804, 'Outrider\'s Accuracy', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6370, 1), - (3805, 'Hastened Mend', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 4801, 1), - (3812, 'Perfected Invisibility', -1, 14336, 65535, 127, 131071, 0, 3, 0, 0, 7069, 1), - (3813, 'Spell Casting Reinforcement', -1, 7168, 65535, 127, 131071, 0, 2, 0, 0, 6257, 1), - (3815, 'Destructive Cascade', -1, 9776, 65535, 127, 131071, 0, 3, 0, 0, 6375, 1), - (3816, 'Companion\'s Relocation', -1, 30224, 65535, 127, 131071, 0, 3, 0, 0, 6379, 1), - (3817, 'Focused Paragon of Spirits', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6380, 1), - (3818, 'Companion\'s Agility', -1, 30224, 65535, 127, 131071, 0, 3, 0, 0, 6383, 1), - (3819, 'Maestro\'s Concentration', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 6386, 1), - (3820, 'Blessing of Life', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 6395, 1), - (3821, 'Quickened Harvest of Druzzil', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 6503, 1), - (3822, 'Chattering Bones', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 6508, 1), - (3823, 'Warlord\'s Deadly Aim', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 6511, 1), - (3824, 'Quickened Call of the Wild', -1, 544, 65535, 127, 131071, 0, 3, 0, 0, 6514, 1), - (3826, 'Force of Disruption', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 5984, 1), - (3830, 'Hastened Divine Avatar', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7100, 1), - (3831, 'Hastened Purification', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 7103, 1), - (3832, 'Beastlords Feral Kick', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 7106, 1), - (3833, 'Burst of Power ', -1, 32841, 65535, 127, 131071, 0, 2, 0, 0, 6409, 1), - (3834, 'Burst of Power ', -1, 256, 65535, 127, 131071, 0, 2, 0, 0, 6419, 1), - (3835, 'Shield Block', -1, 15360, 65535, 127, 131071, 0, 2, 0, 0, 6428, 1), - (3836, 'Holy Root', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6436, 1), - (3837, 'Burst of Power ', -1, 16512, 65535, 127, 131071, 0, 2, 0, 0, 6060, 1), - (3838, 'Quickened Suspend Minion', -1, 30224, 65535, 127, 131071, 0, 3, 0, 0, 6445, 1), - (3839, 'Quickened Summon Axes', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6452, 1), - (3840, 'Recourse of Life', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6601, 1), - (3841, 'Call Hither', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 6455, 1), - (3842, 'Fortified Survival', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 6458, 1), - (3843, 'Fortified Intervention', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 6461, 1), - (3865, 'Planar Durability', -1, 72, 65535, 127, 131071, 0, 3, 0, 0, 6422, 1), - (3890, 'Hastened Force of Will', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 7822, 1), - (3891, 'Hastened Burnout', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 7832, 1), - (3892, 'Hastened Rumbling Servant', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 7828, 1), - (3893, 'Extended Rumbling Servant', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 7827, 1), - (3899, 'Furious Leap', -1, 32769, 65535, 127, 131071, 0, 3, 0, 0, 6499, 1), - (4001, 'Undaunted Fury', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 7407, 1), - (4002, 'Frenzied Volley', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 7818, 1), - (4200, 'Hastened Forceful Rejuvenation', -1, 32318, 65535, 127, 131071, 0, 2, 0, 0, 12475, 1), - (4666, 'Shield Specialist', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 4666, 1), - (5000, 'Glyph of Courage', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 7000, 1), - (5002, 'Glyph of Stored Life', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 7002, 1), - (5003, 'Glyph of Frantic Infusion', 7, 30224, 65535, 127, 131071, 0, 4, 1, 0, 7003, 1), - (5004, 'Glyph of Angry Thoughts', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 7004, 1), - (5005, 'Foraging', 8, 65535, 65535, 127, 131071, 0, 1, 0, 0, 7062, 1), - (6000, 'Harm Touch', 9, 16, 65535, 127, 131071, 0, 3, 0, 0, 7800, 1), - (6001, 'Lay on Hands', 9, 4, 65535, 127, 131071, 0, 3, 0, 0, 7850, 1), - (6002, 'Hunter\'s Attack Power', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 6546, 1), - (6106, 'Sustained Destruction', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 6106, 1), - (6302, 'Hastened Reckless Abandon', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6302, 1), - (6362, 'Hastened Recklessness', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6362, 1), - (6478, 'Hastened Blessing of Resurrection', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6478, 1), - (6481, 'Hastened Divine Resurrection', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6481, 1), - (6488, 'Flurry of Life', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 6488, 1), - (6489, 'Hastened Holyforge', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 6489, 1), - (6492, 'Inquisitor\'s Judgement', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 6492, 1), - (6988, 'Extended Group Bestial Alignment', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 6988, 1), - (7000, 'Voice of Thule', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 6639, 1), - (7001, 'Zan Fi\'s Whistle', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 7872, 1), - (7002, 'Summon Remains', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 9500, 1), - (7003, 'Forceful Rejuvenation', -1, 32318, 65535, 127, 131071, 0, 2, 0, 0, 9502, 1), - (7007, 'Summon Remains', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 9501, 1), - (7009, 'Teleport Bind', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 1419, 1), - (7016, 'Glyph of the Master', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 7016, 1), - (7017, 'Glyph of Lost Secrets', 7, 32318, 65535, 127, 131071, 0, 4, 1, 0, 7017, 1), - (7018, 'Glyph of Genari Might', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 7018, 1), - (7019, 'Glyph of the Cataclysm', 7, 65535, 65535, 127, 131071, 0, 4, 1, 0, 7019, 1), - (7025, 'Group Shrink', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 7669, 1), - (7033, 'Lasting Bravery', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 7033, 1), - (7036, 'Hastened Blast of Anger', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 7036, 1), - (7050, 'Call of the Hero', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 1017, 1), - (7060, 'Precision of Axes', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 4809, 1), - (7070, 'Hastened Distraction Attack', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6941, 1), - (7105, 'Deathly Pact', -1, 1040, 65535, 127, 131071, 0, 3, 0, 0, 976, 1), - (7106, 'Planar Durability', -1, 16768, 65535, 127, 131071, 0, 3, 0, 0, 6467, 1), - (7107, 'Hastened Getaway', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 7005, 1), - (7108, 'Divine Aura', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 977, 1), - (7109, 'Hastened Wrath of the Wild', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 7664, 1), - (7689, 'Burst of Life', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7689, 1), - (7690, 'Spirit Mastery', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 7690, 1), - (7695, 'Quickened Blood of Avoling', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 7695, 1), - (7698, 'Dead Man Floating', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 7698, 1), - (7699, 'Dread Incarnate', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 7699, 1), - (7700, 'Flurry', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 7700, 1), - (7703, 'Death Bloom', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 7703, 1), - (7712, 'Disruptive Persecution', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 7712, 1), - (7715, 'Hastened Whisperwind', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 7715, 1), - (7743, 'Hastened Guardian of the Forest', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 7743, 1), - (7746, 'Hastened Flusterbolt', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 7746, 1), - (7747, 'Volatile Arrow', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 7747, 1), - (7748, 'Pathfinder\'s Grace', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 7748, 1), - (7751, 'Hastened Cover Tracks', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 7751, 1), - (7754, 'Steed of Souls', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 7754, 1), - (7755, 'Scourge Skin', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 7755, 1), - (7756, 'Death\'s Effigy', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 7756, 1), - (7757, 'Hastened Visage of Death', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 7757, 1), - (7760, 'Hastened Hate Step', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 7760, 1), - (7801, 'Songwriting', 6, 128, 65535, 127, 131071, 0, 3, 0, 0, 9001, 1), - (7809, 'Hybrid Research', 6, 16412, 65535, 127, 131071, 0, 2, 0, 0, 9011, 1), - (7819, 'Written Prayer', 6, 546, 65535, 127, 131071, 0, 2, 0, 0, 9021, 1), - (7925, 'Sionachie\'s Crescendo', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 1018, 1), - (8081, 'Summon Resupply Agent', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 9000, 1), - (8130, 'Summon Clockwork Banker', 5, 65535, 65535, 127, 131071, 0, 4, 0, 1, 9031, 1), - (8200, 'Hastened Dirge of the Sleepwalker', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 10329, 1), - (8201, 'Vainglorious Shout ', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 10330, 1), - (8202, 'Lyre Leap ', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 10331, 1), - (8203, 'Domination Mastery ', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 10332, 1), - (8204, 'Lyrical Prankster', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 10333, 1), - (8205, 'Selo\'s Kick ', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 10336, 1), - (8261, 'A Tune Stuck In Your Head', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 10339, 1), - (8262, 'The Show Must Go On', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 7010, 1), - (8300, 'Spell Casting Subtlety', -1, 16384, 65535, 127, 131071, 0, 2, 0, 0, 10370, 1), - (8301, 'Improved Natural Invisibility', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 10373, 1), - (8302, 'Protection of the Warder', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 10374, 1), - (8303, 'Nature\'s Salve', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 10377, 1), - (8304, 'Focus of Animus', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 10380, 1), - (8314, 'Fluid March', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 8314, 1), - (8317, 'Hastened Selo\'s Kick', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 8317, 1), - (8319, 'Hastened Bellow', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 8319, 1), - (8322, 'Belltone Mind', -1, 128, 65535, 127, 131071, 0, 3, 0, 0, 8322, 1), - (8325, 'Subtle Blows', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 8325, 1), - (8331, 'Enhanced Thief\'s Eyes', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 8331, 1), - (8332, 'Extended Languid Bite', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 8332, 1), - (8335, 'Quickened Malosinete', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 8335, 1), - (8341, 'Drape of Shadows', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 8341, 1), - (8342, 'Host in the Shell', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 8342, 1), - (8347, 'Hastened Mana Draw', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 8347, 1), - (8350, 'Hastened Mezmerization', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 8350, 1), - (8400, 'Self Preservation', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 10400, 1), - (8401, 'Hastened Frenzy', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 10401, 1), - (8402, 'Extended Havoc', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 10404, 1), - (8500, 'Healing Frenzy', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10450, 1), - (8501, 'Overpowering Strikes', -1, 6, 65535, 127, 131071, 0, 3, 0, 0, 10453, 1), - (8502, 'Quickened Blessing of Ressurection', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10456, 1), - (8503, 'Hastened Atonement', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10459, 1), - (8504, 'Improved Sanctuary', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10462, 1), - (8505, 'Blessing of Sanctuary', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10463, 1), - (8506, 'Hastened Celestial Hammer', -1, 2, 65535, 127, 131071, 0, 3, 0, 0, 10464, 1), - (8600, 'Spirit of Eagle', -1, 40, 65535, 127, 131071, 0, 3, 0, 0, 10500, 1), - (8601, 'Flight of Eagles', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10501, 1), - (8602, 'Egress', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10502, 1), - (8603, 'Spirits of Nature', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10503, 1), - (8604, 'Wall of Wind', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10506, 1), - (8605, 'Hastened Spirit of the Wood', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10511, 1), - (8606, 'Hastened Convergence of Spirits', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10514, 1), - (8700, 'Beam of Slumber', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 10550, 1), - (8701, 'Phantasmic Reflex', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 10551, 1), - (8702, 'Friendly Stasis', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 10557, 1), - (8703, 'Hastened Self Stasis', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 10558, 1), - (8704, 'Forceful Banishment', -1, 8192, 65535, 127, 131071, 0, 3, 0, 0, 10561, 1), - (8708, 'Hastened Cascading Rage', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 6908, 1), - (8800, 'Force of Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 10600, 1), - (8801, 'Aspect of Zomm', -1, 6144, 65535, 127, 131071, 0, 3, 0, 0, 10603, 1), - (8802, 'Extended Shared Health', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 10610, 1), - (8900, 'Agile Feet', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 10650, 1), - (8901, 'Hastened Defensive Poses', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 10653, 1), - (8902, 'Extended Impenetrable Discipline', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 10656, 1), - (8903, 'Hastened Destructive Force', -1, 64, 65535, 127, 131071, 0, 3, 0, 0, 10657, 1), - (9001, 'Reluctant Benevolence', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 10701, 1), - (9100, 'Bestow Divine Aura', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10752, 1), - (9101, 'Blessing of Purification', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10753, 1), - (9102, 'Sense the Dead', -1, 1030, 65535, 127, 131071, 0, 3, 0, 0, 10754, 1), - (9200, 'Hastened Auspice of the Hunter', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10800, 1), - (9201, 'Clenched Jaw', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10803, 1), - (9202, 'Scout\'s Mastery of Fire', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10806, 1), - (9203, 'Scout\'s Mastery of Ice', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10809, 1), - (9205, 'Scout\'s Mastery of Slashing', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10815, 1), - (9206, 'Scout\'s Mastery of Piercing', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10818, 1), - (9207, 'Scout\'s Mastery of Blunt Weapons', -1, 8, 65535, 127, 131071, 0, 3, 0, 0, 10821, 1), - (9300, 'Massive Strike', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 10850, 1), - (9301, 'Strikethrough', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 10853, 1), - (9400, 'Hate\'s Attraction', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 10900, 1), - (9401, 'Feigned Minion', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 10903, 1), - (9402, 'Hastened Summon Remains', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 10909, 1), - (9403, 'Visage of Death', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 10912, 1), - (9404, 'Cascading Theft of Life', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 10915, 1), - (9500, 'Extended Sloth', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 10950, 1), - (9501, 'Hastened Ancestral Aid', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 10951, 1), - (9502, 'Hastened Union of Spirits', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 10954, 1), - (9503, 'Group Shrink', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 10957, 1), - (9504, 'Inconspicuous Totem', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 10958, 1), - (9505, 'Extended Pestilence', -1, 512, 65535, 127, 131071, 0, 3, 0, 0, 10959, 1), - (9600, 'Hastened Taunt', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 11000, 1), - (9601, 'Extended Shield Reflect', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 11003, 1), - (9602, 'Extended Commanding Voice', -1, 1, 65535, 127, 131071, 0, 3, 0, 0, 11004, 1), - (9700, 'Hastened Destruction', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 11050, 1), - (9701, 'Netherstep', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 11055, 1), - (9702, 'Beam of Displacement', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 11056, 1), - (9703, 'Translocate', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 11057, 1), - (9704, 'Teleport', -1, 2048, 65535, 127, 131071, 0, 3, 0, 0, 11058, 1), - (10367, 'Ageless Enmity', -1, 1, 65535, 127, 131071, 0, 2, 0, 0, 10367, 1), - (10389, 'Extended Trickery', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 10389, 1), - (10392, 'Ageless Enmity', -1, 20, 65535, 127, 131071, 0, 2, 0, 0, 10392, 1), - (10393, 'Shackles of Tunare', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10393, 1), - (10394, 'Beacon of the Righteous', -1, 4, 65535, 127, 131071, 0, 3, 0, 0, 10394, 1), - (10395, 'Bobbing Corpse', -1, 16, 65535, 127, 131071, 0, 3, 0, 0, 10395, 1), - (10396, 'Group Spirit of the White Wolf', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10396, 1), - (10397, 'Group Spirit of the Black Wolf', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10397, 1), - (10405, 'Hastened Deflection Discipline', -1, 20, 65535, 127, 131071, 0, 3, 0, 0, 10405, 1), - (10410, 'Rogue Triple Attack Skillup Test', -1, 256, 65535, 127, 131071, 0, 3, 0, 1, 10410, 1), - (10413, 'Hastened Host of the Elements', -1, 4096, 65535, 127, 131071, 0, 3, 0, 0, 10413, 1), - (10424, 'Hand of Ro', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10424, 1), - (10425, 'Fixation of Ro', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10425, 1), - (10426, 'Peaceful Spirit of the Wood', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10426, 1), - (10427, 'Peaceful Convergence of Spirits', -1, 32, 65535, 127, 131071, 0, 3, 0, 0, 10427, 1), - (10434, 'Quickened Army of the Dead', -1, 1024, 65535, 127, 131071, 0, 3, 0, 0, 10434, 1), - (11073, 'Playing Possum', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 11073, 1), - (11074, 'Cat-like Reflexes', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 11074, 1), - (11077, 'Hastened Bite of the Asp', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 11077, 1), - (11078, 'Hastened Gorilla Smash', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 11078, 1), - (11079, 'Hastened Raven\'s Claw', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 11079, 1), - (11080, 'Chameleon Strike', -1, 16384, 65535, 127, 131071, 0, 3, 0, 0, 11080, 1), - (11085, 'Two Hands, No Mercy!', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 11085, 1), - (11088, 'Hastened Cry of Battle', -1, 32768, 65535, 127, 131071, 0, 3, 0, 0, 11088, 1), - (12600, 'Hastened Frenzied Stabbing', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 12600, 1), - (12603, 'Extended Frenzied Stabbing Discipline', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 12603, 1), - (12606, 'Speed of the Scoundrel', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 12606, 1), - (12607, 'Hastened Pinpoint', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 12607, 1), - (12615, 'Hastened Twisted Chance Discipline', -1, 256, 65535, 127, 131071, 0, 3, 0, 0, 12615, 1), - (15073, 'Banestrike', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 15073, 1), - (15074, 'Hastened Banestrike', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 15074, 1), - (30050, 'Unknown AA 30050', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 30050, 1), - (30100, 'Unknown AA 30100', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 30100, 1), - (30150, 'Unknown AA 30150', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 30150, 1), - (30175, 'Unknown AA 30175', 2, 65335, 65535, 127, 131071, 0, 4, 0, 1, 30175, 1), - (30180, 'Unknown AA 30180', 2, 128, 65535, 127, 131071, 0, 4, 0, 1, 30180, 1), - (30185, 'Unknown AA 30185', 2, 64, 65535, 127, 131071, 0, 4, 0, 1, 30185, 1), - (30190, 'Unknown AA 30190', 2, 8, 65535, 127, 131071, 0, 4, 0, 1, 30190, 1), - (30195, 'Unknown AA 30195', 2, 65535, 65535, 127, 131071, 0, 4, 0, 1, 30195, 1); +-- +-- Dumping data for table `aa_ability` +-- + +LOCK TABLES `aa_ability` WRITE; +/*!40000 ALTER TABLE `aa_ability` DISABLE KEYS */; +INSERT INTO `aa_ability` VALUES (0,'Unknown AA -1',-1,65535,65535,127,131071,0,1,0,0,49999,1,0),(1,'Innate Strength',-1,65535,65535,127,131071,0,1,0,0,2,1,0),(2,'Innate Stamina',-1,65535,65535,127,131071,0,1,0,0,7,1,0),(3,'Innate Agility',-1,65535,65535,127,131071,0,1,0,0,12,1,0),(4,'Innate Dexterity',-1,65535,65535,127,131071,0,1,0,0,17,1,0),(5,'Innate Intelligence',-1,65535,65535,127,131071,0,1,0,0,22,1,0),(6,'Innate Wisdom',-1,65535,65535,127,131071,0,1,0,0,27,1,0),(7,'Innate Charisma',-1,65535,65535,127,131071,0,1,0,0,32,1,0),(8,'Innate Fire Protection',-1,65535,65535,127,131071,0,1,0,0,37,1,0),(9,'Innate Cold Protection',-1,65535,65535,127,131071,0,1,0,0,42,1,0),(10,'Innate Magic Protection',-1,65535,65535,127,131071,0,1,0,0,47,1,0),(11,'Innate Poison Protection',-1,65535,65535,127,131071,0,1,0,0,52,1,0),(12,'Innate Disease Protection',-1,65535,65535,127,131071,0,1,0,0,57,1,0),(13,'Innate Run Speed',-1,65535,65535,127,131071,0,1,0,0,62,1,0),(15,'Innate Metabolism',-1,65535,65535,127,131071,0,1,0,0,68,1,0),(16,'Innate Lung Capacity',-1,65535,65535,127,131071,0,1,0,0,71,1,0),(17,'First Aid',-1,65535,65535,127,131071,0,1,0,0,74,1,0),(18,'Healing Adept',-1,16942,65535,127,131071,0,2,0,0,77,1,0),(19,'Healing Gift',-1,16942,65535,127,131071,0,2,0,0,80,1,0),(20,'Spell Casting Mastery',-1,15906,65535,127,131071,0,2,0,0,83,1,0),(21,'Spell Casting Reinforcement',-1,25150,65535,127,131071,0,2,0,0,86,1,0),(23,'Spell Casting Fury',-1,32446,65535,127,131071,0,2,0,0,92,1,0),(25,'Spell Casting Subtlety',-1,15360,65535,127,131071,0,2,0,0,98,1,0),(26,'Spell Casting Expertise',-1,15504,65535,127,131071,0,2,0,0,101,1,0),(27,'Spell Casting Deftness',-1,7184,65535,127,131071,0,2,0,0,104,1,0),(28,'Natural Durability',-1,65535,65535,127,131071,0,1,0,0,107,1,0),(29,'Natural Healing',-1,49629,65535,127,131071,0,2,0,0,110,1,0),(30,'Combat Fury',-1,16596,65535,127,131071,0,2,0,0,113,1,0),(31,'Fear Resistance',-1,49629,65535,127,131071,0,2,0,0,116,1,0),(32,'Finishing Blow',-1,49629,65535,127,131071,0,2,0,0,119,1,0),(33,'Combat Stability',-1,65535,65535,127,131071,0,1,0,0,122,1,0),(34,'Combat Agility',-1,65535,65535,127,131071,0,1,0,0,125,1,0),(35,'Mass Group Buff',-1,30254,65535,127,131071,0,3,0,0,128,1,0),(36,'Divine Resurrection',-1,2,65535,127,131071,0,3,0,0,129,1,0),(37,'Innate Invis to Undead',-1,1026,65535,127,131071,0,3,0,0,130,1,0),(38,'Celestial Regeneration',-1,2,65535,127,131071,0,3,0,0,131,1,0),(39,'Bestow Divine Aura',-1,2,65535,127,131071,0,3,0,0,132,1,0),(41,'Purify Soul',-1,2,65535,127,131071,0,3,0,0,136,1,0),(42,'Quick Evacuation',-1,2080,65535,127,131071,0,3,0,0,137,1,0),(43,'Exodus',-1,2080,65535,127,131071,0,3,0,0,140,1,0),(44,'Quick Damage',-1,6176,65535,127,131071,0,3,0,0,141,1,0),(45,'Enhanced Root',-1,32,65535,127,131071,0,3,0,0,144,1,0),(46,'Dire Charm',-1,8192,65535,127,131071,0,3,0,0,145,1,0),(47,'Cannibalization',-1,512,65535,127,131071,0,3,0,0,146,1,0),(48,'Quick Buff',-1,25134,65535,127,131071,0,2,0,0,147,1,0),(49,'Alchemy Mastery',6,512,65535,127,131071,0,1,0,0,150,1,0),(50,'Rabid Bear',-1,512,65535,127,131071,0,3,0,0,153,1,0),(52,'Improved Familiar',-1,2048,65535,127,131071,0,3,0,0,155,1,0),(53,'Nexus Gate',-1,2048,65535,127,131071,0,3,0,0,156,1,0),(55,'Permanent Illusion',-1,8192,65535,127,131071,0,3,0,0,158,1,0),(56,'Jewel Craft Mastery',6,8192,65535,127,131071,0,1,0,0,159,1,0),(57,'Gather Mana',-1,8192,65535,127,131071,0,3,0,0,162,1,0),(58,'Mend Companion',-1,21504,65535,127,131071,0,3,0,0,163,1,0),(60,'Frenzied Burnout',-1,4096,65535,127,131071,0,3,0,0,167,1,0),(61,'Elemental Form: Fire',-1,4096,65535,127,131071,0,3,0,0,168,1,0),(62,'Elemental Form: Water',-1,4096,65535,127,131071,0,3,0,0,171,1,0),(63,'Elemental Form: Earth',-1,4096,65535,127,131071,0,3,0,0,174,1,0),(64,'Elemental Form: Air',-1,4096,65535,127,131071,0,3,0,0,177,1,0),(67,'Elemental Pact',-1,4096,65535,127,131071,0,3,0,0,182,1,0),(68,'Life Burn',-1,1024,65535,127,131071,0,3,0,0,183,1,0),(69,'Dead Mesmerization',-1,1024,65535,127,131071,0,3,0,0,184,1,0),(70,'Fear Storm',-1,1024,65535,127,131071,0,3,0,0,185,1,0),(71,'Flesh to Bone',-1,1024,65535,127,131071,0,3,0,0,186,1,0),(72,'Call to Corpse',-1,1024,65535,127,131071,0,3,0,0,187,1,0),(73,'Divine Stun',-1,4,65535,127,131071,0,3,0,0,188,1,0),(75,'Slay Undead',-1,4,65535,127,131071,0,3,0,0,190,1,0),(76,'Act of Valor',-1,4,65535,127,131071,0,3,0,0,193,1,0),(77,'Holy Steed',-1,4,65535,127,131071,0,3,0,0,194,1,0),(78,'Fearless',-1,20,65535,127,131071,0,3,0,0,195,1,0),(79,'2 Hand Bash',-1,20,65535,127,131071,0,3,0,0,196,1,0),(80,'Innate Camouflage',-1,40,65535,127,131071,0,3,0,0,197,1,0),(81,'Ambidexterity',-1,16841,65535,127,131071,0,3,0,0,198,1,0),(82,'Archery Mastery',-1,8,65535,127,131071,0,3,0,0,199,1,0),(84,'Endless Quiver',-1,8,65535,127,131071,0,3,0,0,205,1,0),(85,'Unholy Steed',-1,16,65535,127,131071,0,3,0,0,206,1,0),(87,'Leech Touch',-1,16,65535,127,131071,0,3,0,0,208,1,0),(89,'Soul Abrasion',-1,16,65535,127,131071,0,3,0,0,210,1,0),(90,'Instrument Mastery',-1,128,65535,127,131071,0,3,0,0,213,1,0),(94,'Jam Fest',-1,128,65535,127,131071,0,3,0,0,225,1,0),(97,'Critical Mend',-1,64,65535,127,131071,0,3,0,0,230,1,0),(98,'Purify Body',-1,64,65535,127,131071,0,3,0,0,233,1,0),(100,'Rapid Feign',-1,64,65535,127,131071,0,3,0,0,237,1,0),(101,'Return Kick',-1,64,65535,127,131071,0,3,0,0,240,1,0),(102,'Escape',-1,256,65535,127,131071,0,3,0,0,243,1,0),(103,'Poison Mastery',6,256,65535,127,131071,0,1,0,0,244,1,0),(104,'Double Riposte',-1,49501,65535,127,131071,0,2,0,0,247,1,0),(107,'Purge Poison',-1,256,65535,127,131071,0,3,0,0,254,1,0),(108,'Flurry',-1,32769,65535,127,131071,0,3,0,0,255,1,0),(109,'Rampage',-1,32769,65535,127,131071,0,3,0,0,258,1,0),(110,'Area Taunt',-1,1,65535,127,131071,0,3,0,0,259,1,0),(111,'War Cry',-1,1,65535,127,131071,0,3,0,0,260,1,0),(112,'Bandage Wound',-1,32769,65535,127,131071,0,3,0,0,263,1,0),(114,'Spell Casting Fury Mastery',-1,2048,65535,127,131071,0,3,0,0,267,1,0),(116,'Dragon Punch',-1,64,65535,127,131071,0,3,0,0,273,1,0),(117,'Strong Root',-1,2048,65535,127,131071,0,3,0,0,274,1,0),(118,'Singing Mastery',-1,128,65535,127,131071,0,3,0,0,275,1,0),(119,'Body and Mind Rejuvenation',-1,16540,65535,127,131071,0,3,0,0,278,1,0),(120,'Physical Enhancement',-1,49629,65535,127,131071,0,3,0,0,279,1,0),(121,'Adv. Trap Negotiation',-1,384,65535,127,131071,0,3,0,0,280,1,0),(122,'Acrobatics',-1,448,65535,127,131071,0,3,0,0,283,1,0),(123,'Scribble Notes',-1,128,65535,127,131071,0,3,0,0,286,1,0),(124,'Chaotic Stab',-1,256,65535,127,131071,0,3,0,0,287,1,0),(125,'Pet Discipline',-1,22032,65535,127,131071,0,3,0,0,288,1,0),(126,'Hobble of Spirits',-1,16384,65535,127,131071,0,3,0,0,289,1,0),(127,'Frenzy of Spirit',-1,16384,65535,127,131071,0,3,0,0,290,1,0),(128,'Paragon of Spirit',-1,16384,65535,127,131071,0,3,0,0,291,1,0),(129,'Chains of Purity',-1,4,65535,127,131071,0,3,0,0,10348,1,0),(130,'Resplendent Glory',-1,1,65535,127,131071,0,3,0,0,8300,1,0),(131,'Rage of Rallos Zek',-1,1,65535,127,131071,0,3,0,0,8303,1,0),(132,'Enhanced Area Taunt',-1,1,65535,127,131071,0,3,0,0,8312,1,0),(133,'Decapitation',-1,32768,65535,127,131071,0,3,0,0,14200,1,0),(134,'Hastened Berserking Disciplines',-1,32768,65535,127,131071,0,3,0,0,14203,1,0),(135,'Quiet Miracle',-1,2,65535,127,131071,0,3,0,0,14206,1,0),(136,'Repel the Wicked',-1,2,65535,127,131071,0,3,0,0,14207,1,0),(137,'Beacon of Life',-1,2,65535,127,131071,0,3,0,0,14208,1,0),(138,'Blessed Chains',-1,2,65535,127,131071,0,3,0,0,14209,1,0),(139,'Hastened Focused Celestial Regeneration',-1,2,65535,127,131071,0,3,0,0,14213,1,0),(140,'Quickened Spirit Calling',-1,512,65535,127,131071,0,3,0,0,14225,1,0),(141,'New Tanaan Crafting Mastery',6,65535,65535,127,131071,0,1,0,0,412,1,0),(142,'Planar Power',-1,65535,65535,127,131071,0,1,0,0,418,1,0),(143,'Planar Durability',-1,1,65535,127,131071,0,3,0,0,423,1,0),(144,'Innate Enlightenment',-1,15360,65535,127,131071,0,2,0,0,426,1,0),(146,'Unknown AA 8001',9,65535,65535,127,131071,0,1,0,0,8000,0,0),(147,'Spiritual Rebuke',-1,512,65535,127,131071,0,3,0,0,14231,1,0),(148,'Pathosis',-1,512,65535,127,131071,0,3,0,0,14232,1,0),(149,'Preincarnation',-1,544,65535,127,131071,0,3,0,0,14233,1,0),(150,'Mastery of the Past',-1,15504,65535,127,131071,0,2,0,0,446,1,0),(151,'Spiritual Blessing',-1,512,65535,127,131071,0,3,0,0,14234,1,0),(152,'Communion of the Cheetah',-1,512,65535,127,131071,0,3,0,0,14237,1,0),(153,'Radiant Cure',-1,546,65535,127,131071,0,2,0,0,459,1,0),(154,'Hastened Divinity',-1,2,65535,127,131071,0,3,0,0,462,1,0),(156,'Hastened Purification of the Soul',-1,2,65535,127,131071,0,3,0,0,468,1,0),(157,'Hastened Gathering',-1,8192,65535,127,131071,0,3,0,0,471,1,0),(158,'Hastened Rabidity',-1,512,65535,127,131071,0,3,0,0,474,1,0),(159,'Hastened Exodus',-1,2080,65535,127,131071,0,3,0,0,477,1,0),(160,'Hastened Root',-1,2048,65535,127,131071,0,3,0,0,480,1,0),(161,'Hastened Mending',-1,21504,65535,127,131071,0,3,0,0,483,1,0),(163,'Hastened Instigation',-1,1,65535,127,131071,0,3,0,0,489,1,0),(164,'Hastened Rampage',-1,32769,65535,127,131071,0,3,0,0,492,1,0),(165,'Hastened Purification of the Body',-1,64,65535,127,131071,0,3,0,0,495,1,0),(166,'Hasty Exit',-1,256,65535,127,131071,0,3,0,0,498,1,0),(167,'Hastened Purification',-1,256,65535,127,131071,0,3,0,0,501,1,0),(168,'Hastened Nature\'s Fury',-1,32,65535,127,131071,0,3,0,0,14241,1,0),(169,'Divine Arbitration',-1,2,65535,127,131071,0,3,0,0,507,1,0),(170,'Wrath of the Wild',-1,32,65535,127,131071,0,3,0,0,510,1,0),(171,'Virulent Paralysis',-1,512,65535,127,131071,0,3,0,0,513,1,0),(172,'Harvest of Druzzil',-1,2048,65535,127,131071,0,3,0,0,516,1,0),(173,'Eldritch Rune',-1,8192,65535,127,131071,0,3,0,0,517,1,0),(174,'Servant of Ro',-1,4096,65535,127,131071,0,3,0,0,520,1,0),(175,'Wake the Dead',-1,1024,65535,127,131071,0,3,0,0,523,1,0),(176,'Suspended Minion',-1,30224,65535,127,131071,0,2,0,0,526,1,0),(177,'Spirit Call',-1,512,65535,127,131071,0,3,0,0,528,1,0),(178,'Wrath of the Forest Walker',-1,32,65535,127,131071,0,3,0,0,14244,1,0),(179,'Gift of Sylvan Spirits',-1,32,65535,127,131071,0,3,0,0,14249,1,0),(180,'Hand of Piety',-1,4,65535,127,131071,0,3,0,0,534,1,0),(181,'Mithaniel\'s Binding',-1,32769,65535,127,131071,0,3,0,0,537,1,0),(182,'Summon Personal Tribute Master',5,65535,65535,127,131071,0,4,0,1,5006,1,0),(183,'Extended Vinelash Cascade',-1,32,65535,127,131071,0,3,0,0,14254,1,0),(184,'Guardian of the Forest',-1,8,65535,127,131071,0,3,0,0,545,1,0),(185,'Spirit of the Wood',-1,32,65535,127,131071,0,3,0,0,548,1,0),(186,'Bestial Frenzy',-1,16384,65535,127,131071,0,3,0,0,551,1,0),(187,'Harmonious Attack',-1,128,65535,127,131071,0,3,0,0,556,1,0),(188,'Knight\'s Advantage',-1,20,65535,127,131071,0,3,0,0,561,1,0),(189,'Ferocity',-1,33097,65535,127,131071,0,2,0,0,564,1,0),(190,'Viscid Roots',-1,32,65535,127,131071,0,3,0,0,567,1,0),(193,'Feigned Minion',-1,1024,65535,127,131071,0,3,0,0,574,1,0),(194,'Unfailing Divinity',-1,2,65535,127,131071,0,3,0,0,577,1,0),(195,'Animation Empathy',-1,8192,65535,127,131071,0,3,0,0,580,1,0),(196,'Rush to Judgment',-1,4,65535,127,131071,0,3,0,0,583,1,0),(197,'Living Shield',-1,1,65535,127,131071,0,3,0,0,586,1,0),(198,'Consumption of the Soul',-1,16,65535,127,131071,0,3,0,0,589,1,0),(199,'Boastful Bellow',-1,128,65535,127,131071,0,3,0,0,592,1,0),(200,'Fervent Blessing',-1,4,65535,127,131071,0,3,0,0,593,1,0),(201,'Touch of the Wicked',-1,16,65535,127,131071,0,3,0,0,596,1,0),(202,'Punishing Blade',-1,32841,65535,127,131071,0,2,0,0,599,1,0),(203,'Speed of the Knight',-1,20,65535,127,131071,0,3,0,0,602,1,0),(204,'Shroud of Stealth',-1,256,65535,127,131071,0,3,0,0,605,1,0),(205,'Nimble Evasion',-1,256,65535,127,131071,0,3,0,0,606,1,0),(206,'Technique of Master Wu',-1,64,65535,127,131071,0,3,0,0,611,1,0),(207,'Host of the Elements',-1,4096,65535,127,131071,0,3,0,0,616,1,0),(208,'Call of Xuzl',-1,2048,65535,127,131071,0,3,0,0,619,1,0),(209,'Hastened Stealth',-1,256,65535,127,131071,0,3,0,0,622,1,0),(210,'Ingenuity',-1,33089,65535,127,131071,0,2,0,0,625,1,0),(211,'Fleet of Foot',-1,128,65535,127,131071,0,3,0,0,628,1,0),(212,'Fading Memories',-1,128,65535,127,131071,0,3,0,0,630,1,0),(213,'Tactical Mastery',-1,32769,65535,127,131071,0,3,0,0,631,1,0),(214,'Theft of Life',-1,1040,65535,127,131071,0,3,0,0,634,1,0),(215,'Fury of Magic',-1,13858,65535,127,131071,0,2,0,0,637,1,0),(216,'Extended Spirit of the Bear',-1,32,65535,127,131071,0,3,0,0,14259,1,0),(217,'Project Illusion',-1,8192,65535,127,131071,0,3,0,0,643,1,0),(218,'Headshot',-1,8,65535,127,131071,0,3,0,0,644,1,0),(219,'Entrap',-1,40,65535,127,131071,0,3,0,0,645,1,0),(220,'Sonic Displacement',-1,128,65535,127,131071,0,3,0,0,13528,1,0),(221,'Total Domination',-1,8192,65535,127,131071,0,3,0,0,649,1,0),(222,'Stalwart Endurance',-1,32769,65535,127,131071,0,3,0,0,652,1,0),(223,'Quick Summoning',-1,4096,65535,127,131071,0,3,0,0,655,1,0),(224,'Mental Clarity',-1,32446,65535,127,131071,0,2,0,0,658,1,0),(225,'Innate Regeneration',-1,65535,65535,127,131071,0,1,0,0,661,1,0),(227,'Extended Notes',-1,128,65535,127,131071,0,3,0,0,665,1,0),(228,'Hastened Warder\'s Gift',-1,16384,65535,127,131071,0,3,0,0,13463,1,0),(229,'Improved Reclaim Energy',-1,4096,65535,127,131071,0,3,0,0,671,1,0),(230,'Hastened Possum',-1,16384,65535,127,131071,0,3,0,0,13449,1,0),(231,'Shauri\'s Sonorious Clouding',-1,128,65535,127,131071,0,3,0,0,13527,1,0),(232,'Veil of the Underbrush',-1,32,65535,127,131071,0,3,0,0,14262,1,0),(233,'Packrat',-1,65535,65535,127,131071,0,1,0,0,678,1,0),(234,'Heightened Endurance ',-1,33089,65535,127,131071,0,2,0,0,683,1,0),(235,'Weapon Affinity',-1,49629,65535,127,131071,0,2,0,0,686,1,0),(236,'Secondary Forte',-1,15906,65535,127,131071,0,2,0,0,691,1,0),(237,'Persistent Casting',-1,32446,65535,127,131071,0,2,0,0,692,1,0),(238,'Tune of Pursuance',-1,128,65535,127,131071,0,3,0,0,695,1,0),(239,'Hastened Companion\'s Sacrifice',-1,16384,65535,127,131071,0,3,0,0,13474,1,0),(240,'Cheetah\'s Pounce',-1,16384,65535,127,131071,0,3,0,0,13483,1,0),(241,'Bloodlust',-1,16384,65535,127,131071,0,3,0,0,13484,1,0),(242,'Primal Fury',-1,16384,65535,127,131071,0,3,0,0,13485,1,0),(244,'Lure of the Siren\'s Song',-1,128,65535,127,131071,0,3,0,0,13529,1,0),(245,'Bestial Alignment',-1,16384,65535,127,131071,0,3,0,0,718,1,0),(246,'Hidden Communion of the Cheetah',-1,32,65535,127,131071,0,3,0,0,14265,1,0),(247,'Feral Swipe',-1,16384,65535,127,131071,0,3,0,0,723,1,0),(248,'Warder\'s Fury',-1,16384,65535,127,131071,0,3,0,0,724,1,0),(249,'Warder\'s Alacrity',-1,16384,65535,127,131071,0,3,0,0,729,1,0),(250,'Pet Affinity',-1,30224,65535,127,131071,0,2,0,0,734,1,0),(251,'Mastery of the Past',-1,16942,65535,127,131071,0,2,0,0,735,1,0),(252,'Spell Casting Subtlety',-1,546,65535,127,131071,0,2,0,0,738,1,0),(254,'Divine Avatar',-1,2,65535,127,131071,0,3,0,0,746,1,0),(255,'Exquisite Benediction',-1,2,65535,127,131071,0,3,0,0,749,1,0),(256,'Hastened Curing',-1,546,65535,127,131071,0,2,0,0,754,1,0),(257,'Nature\'s Boon',-1,32,65535,127,131071,0,3,0,0,757,1,0),(258,'Advanced Tracking',-1,32,65535,127,131071,0,3,0,0,762,1,0),(259,'Critical Affliction',-1,18104,65535,127,131071,0,2,0,0,767,1,0),(260,'Glacial Arrow',-1,8,65535,127,131071,0,3,0,0,13549,1,0),(261,'Doppelganger',-1,8192,65535,127,131071,0,3,0,0,773,1,0),(262,'Enhanced Forgetfulness',-1,8192,65535,127,131071,0,3,0,0,776,1,0),(263,'Mesmerization Mastery',-1,8192,65535,127,131071,0,3,0,0,781,1,0),(264,'Quick Mass Group Buff',-1,8192,65535,127,131071,0,3,0,0,782,1,0),(265,'Shared Health',-1,4096,65535,127,131071,0,3,0,0,785,1,0),(266,'Elemental Fury',-1,4096,65535,127,131071,0,3,0,0,790,1,0),(267,'Elemental Alacrity ',-1,4096,65535,127,131071,0,3,0,0,795,1,0),(268,'Elemental Agility',-1,4096,65535,127,131071,0,3,0,0,800,1,0),(269,'Elemental Durability',-1,4096,65535,127,131071,0,3,0,0,803,1,0),(270,'Sinister Strikes',-1,16841,65535,127,131071,0,3,0,0,806,1,0),(271,'Strikethrough',-1,64,65535,127,131071,0,3,0,0,807,1,0),(272,'Stonewall',-1,64,65535,127,131071,0,3,0,0,810,1,0),(273,'Rapid Strikes ',-1,64,65535,127,131071,0,3,0,0,815,1,0),(274,'Kick Mastery',-1,64,65535,127,131071,0,3,0,0,820,1,0),(275,'Heightened Awareness',-1,64,65535,127,131071,0,3,0,0,823,1,0),(276,'Destructive Force ',-1,64,65535,127,131071,0,3,0,0,828,1,0),(278,'Death\'s Fury ',-1,1040,65535,127,131071,0,3,0,0,834,1,0),(279,'Quickening of Death ',-1,1024,65535,127,131071,0,3,0,0,839,1,0),(280,'Group Perfected Invisibility to Undead',-1,14336,65535,127,131071,0,3,0,0,14281,1,0),(281,'Triple Backstab',-1,256,65535,127,131071,0,3,0,0,846,1,0),(282,'Hastened Piety',-1,4,65535,127,131071,0,3,0,0,849,1,0),(283,'Immobilizing Bash',-1,20,65535,127,131071,0,3,0,0,852,1,0),(284,'Vicious Smash',-1,20,65535,127,131071,0,3,0,0,855,1,0),(285,'Radiant Cure',-1,4,65535,127,131071,0,2,0,0,860,1,0),(286,'Purification ',-1,4,65535,127,131071,0,3,0,0,863,1,0),(287,'Precision of the Pathfinder',-1,8,65535,127,131071,0,3,0,0,864,1,0),(288,'Coat of Thistles',-1,8,65535,127,131071,0,3,0,0,867,1,0),(289,'Flaming Arrows',-1,8,65535,127,131071,0,3,0,0,872,1,0),(290,'Frost Arrows',-1,8,65535,127,131071,0,3,0,0,875,1,0),(291,'Perfected Invisibility to Undead',-1,14336,65535,127,131071,0,3,0,0,14282,1,0),(292,'Trap Circumvention ',-1,256,65535,127,131071,0,3,0,0,881,1,0),(293,'Quickened Stasis',-1,8192,65535,127,131071,0,3,0,0,14283,1,0),(294,'Virulent Venom ',-1,256,65535,127,131071,0,3,0,0,888,1,0),(295,'Extended Dreary Deeds',-1,8192,65535,127,131071,0,3,0,0,14286,1,0),(296,'Intense Hatred',-1,16,65535,127,131071,0,3,0,0,895,1,0),(297,'Quickened Frenzied Burnout',-1,4096,65535,127,131071,0,3,0,0,14289,1,0),(299,'Sturdiness',-1,1,65535,127,131071,0,3,0,0,907,1,0),(300,'Warlord\'s Tenacity ',-1,1,65535,127,131071,0,3,0,0,912,1,0),(301,'Strengthened Strike',-1,9,65535,127,131071,0,3,0,0,915,1,0),(302,'Extended Shielding',-1,1,65535,127,131071,0,3,0,0,918,1,0),(303,'Ro\'s Flaming Familiar ',-1,2048,65535,127,131071,0,3,0,0,921,1,0),(304,'E\'ci\'s Icy Familiar ',-1,2048,65535,127,131071,0,3,0,0,922,1,0),(305,'Druzzil\'s Mystical Familiar ',-1,2048,65535,127,131071,0,3,0,0,923,1,0),(306,'Unknown AA 15819',-1,8,65535,127,131071,0,3,0,0,15819,1,0),(307,'Ward of Destruction ',-1,2048,65535,127,131071,0,3,0,0,926,1,0),(308,'Frenzied Devastation',-1,2048,65535,127,131071,0,3,0,0,931,1,0),(309,'Combat Fury',-1,32769,65535,127,131071,0,2,0,0,934,1,0),(310,'Combat Fury',-1,256,65535,127,131071,0,3,0,0,937,1,0),(311,'Combat Fury',-1,8,65535,127,131071,0,3,0,0,940,1,0),(312,'Quickened Host of the Elements',-1,4096,65535,127,131071,0,3,0,0,14292,1,0),(313,'Hastened Companion\'s Relocation',-1,30224,65535,127,131071,0,3,0,0,14295,1,0),(314,'Veteran\'s Wrath',-1,8,65535,127,131071,0,3,0,0,1047,1,0),(315,'Planar Durability',-1,32788,65535,127,131071,0,3,0,0,952,1,0),(316,'Innate Enlightenment',-1,546,65535,127,131071,0,2,0,0,955,1,0),(317,'Dire Charm',-1,32,65535,127,131071,0,3,0,0,960,1,0),(318,'Dire Charm',-1,1024,65535,127,131071,0,3,0,0,961,1,0),(319,'Touch of the Divine',-1,2,65535,127,131071,0,3,0,0,962,1,0),(320,'Swarm of Decay',-1,1024,65535,127,131071,0,3,0,0,967,1,0),(321,'Call of the Ancients',-1,512,65535,127,131071,0,3,0,0,970,1,0),(322,'Innate See Invis',-1,65535,65535,127,131071,0,1,0,0,1388,1,0),(323,'Virulent Talon',-1,4096,65535,127,131071,0,3,0,0,14307,1,0),(324,'Blacksmithing Mastery',6,65535,65535,127,131071,0,1,0,0,979,1,0),(325,'Baking Mastery',6,65535,65535,127,131071,0,1,0,0,982,1,0),(326,'Brewing Mastery',6,65535,65535,127,131071,0,1,0,0,985,1,0),(327,'Fletching Mastery',6,65535,65535,127,131071,0,1,0,0,988,1,0),(328,'Pottery Mastery',6,65535,65535,127,131071,0,1,0,0,991,1,0),(329,'Tailoring Mastery',6,65535,65535,127,131071,0,1,0,0,994,1,0),(330,'Salvage',6,65535,65535,127,131071,0,1,0,0,997,1,0),(331,'Origin',9,65535,65535,127,131071,0,1,0,0,1000,1,0),(333,'Discordant Defiance',-1,65535,65535,127,131071,0,1,0,0,1006,1,0),(334,'Mystical Attuning',-1,65535,65535,127,131071,0,1,0,0,1021,1,0),(335,'Delay Death',-1,65535,65535,127,131071,0,1,0,0,1026,1,0),(336,'Earthen Brawn',-1,65535,65535,127,131071,0,1,0,0,8263,1,0),(337,'Unknown AA 15798',-1,8,65535,127,131071,0,3,0,0,15798,1,0),(338,'Veteran\'s Wrath',-1,16596,65535,127,131071,0,2,0,0,1041,1,0),(339,'Veteran\'s Wrath',-1,256,65535,127,131071,0,3,0,0,1044,1,0),(340,'Unknown AA 15833',-1,2,65535,127,131071,0,3,0,0,15833,1,0),(341,'Veteran\'s Wrath',-1,32769,65535,127,131071,0,3,0,0,1050,1,0),(342,'Staff Block',-1,15360,65535,127,131071,0,2,0,0,14301,1,0),(343,'Hastened Pestilent Paralysis',-1,1024,65535,127,131071,0,3,0,0,14308,1,0),(344,'Hastened Mercurial Torment',-1,1024,65535,127,131071,0,3,0,0,14311,1,0),(345,'Unknown AA 15768',-1,4,65535,127,131071,0,3,0,0,15768,1,0),(346,'Unknown AA 15771',-1,65535,65535,127,131071,0,1,0,0,15771,1,0),(347,'Mnemonic Retention',-1,32446,65535,127,131071,0,2,0,0,1071,1,0),(348,'Expansive Mind',-1,32446,65535,127,131071,0,2,0,0,1072,1,0),(350,'Death\'s Malaise',-1,1024,65535,127,131071,0,3,0,0,14321,1,0),(351,'Dying Grasp',-1,1024,65535,127,131071,0,3,0,0,14322,1,0),(352,'Arcane Tongues',6,15360,65535,127,131071,0,2,0,0,1089,1,0),(353,'Master of Disguise',-1,384,65535,127,131071,0,3,0,0,1092,1,0),(354,'Slippery Attacks',-1,16841,65535,127,131071,0,2,0,0,1093,1,0),(355,'Unknown AA 15836',-1,2,65535,127,131071,0,3,0,0,15836,1,0),(357,'Unknown AA 16176',-1,8,65535,127,131071,0,3,0,0,16176,1,0),(358,'Fury of Magic',-1,16540,65535,127,131071,0,2,0,0,1107,1,0),(359,'Dance of Blades',-1,128,65535,127,131071,0,3,0,0,1110,1,0),(360,'Bloodthirsty Blade',-1,16,65535,127,131071,0,3,0,0,13616,1,0),(361,'Shield of Notes',-1,128,65535,127,131071,0,3,0,0,1116,1,0),(362,'Roar of Thunder',-1,16384,65535,127,131071,0,3,0,0,1119,1,0),(363,'Unknown AA 16179',-1,8,65535,127,131071,0,3,0,0,16179,1,0),(364,'Persistent Minion',-1,30224,65535,127,131071,0,2,0,0,1122,1,0),(365,'A Hole In Space',-1,2048,65535,127,131071,0,3,0,0,14323,1,0),(366,'Advanced Pet Discipline',-1,22032,65535,127,131071,0,3,0,0,1129,1,0),(367,'Throwing Mastery',-1,32768,65535,127,131071,0,3,0,0,1131,1,0),(368,'Blur of Axes',-1,32768,65535,127,131071,0,3,0,0,1134,1,0),(369,'Hastened War Cry',-1,32768,65535,127,131071,0,3,0,0,1137,1,0),(370,'Dead Aim',-1,32768,65535,127,131071,0,3,0,0,1140,1,0),(371,'Frenzied Defense',-1,32768,65535,127,131071,0,3,0,0,1166,1,0),(372,'Tireless Sprint',-1,32768,65535,127,131071,0,3,0,0,1146,1,0),(373,'Desperation',-1,32768,65535,127,131071,0,3,0,0,1149,1,0),(374,'Untamed Rage',-1,32768,65535,127,131071,0,3,0,0,1150,1,0),(375,'Echoing Cries',-1,32768,65535,127,131071,0,3,0,0,1155,1,0),(376,'Distant Strike',-1,64,65535,127,131071,0,3,0,0,14372,1,0),(377,'Earthen Stability',-1,65535,65535,127,131071,0,1,0,0,8268,1,0),(378,'Earthen Alacrity',-1,65535,65535,127,131071,0,1,0,0,8273,1,0),(379,'Earthen Artistry',-1,65535,65535,127,131071,0,1,0,0,8278,1,0),(380,'Earthen Sagacity',-1,65535,65535,127,131071,0,1,0,0,8283,1,0),(381,'Earthen Brilliance',-1,65535,65535,127,131071,0,1,0,0,8288,1,0),(382,'Earthen Allure',-1,65535,65535,127,131071,0,1,0,0,8293,1,0),(383,'Extended Spirit of the Wood',-1,32,65535,127,131071,0,3,0,0,12646,1,0),(384,'Spirit of the Bear',-1,32,65535,127,131071,0,3,0,0,12651,1,0),(385,'Twinheal',-1,16942,65535,127,131071,0,2,0,0,12652,1,0),(386,'Nature\'s Fury',-1,32,65535,127,131071,0,3,0,0,12661,1,0),(387,'Blood Pact',-1,32768,65535,127,131071,0,3,0,0,1178,1,0),(388,'Shielding Resistance',-1,16841,65535,127,131071,0,2,0,0,1181,1,0),(389,'Healing Boon',-1,518,65535,127,131071,0,2,0,0,1186,1,0),(390,'Elemental Union',-1,4096,65535,127,131071,0,3,0,0,13695,1,0),(391,'Celestial Hammer',-1,2,65535,127,131071,0,3,0,0,1192,1,0),(392,'Divine Retribution',-1,2,65535,127,131071,0,3,0,0,1195,1,0),(393,'Nature\'s Blessing',-1,32,65535,127,131071,0,3,0,0,12655,1,0),(394,'Extended Convergence of Spirit',-1,32,65535,127,131071,0,3,0,0,12645,1,0),(395,'Hastened Storm Strike',-1,32,65535,127,131071,0,3,0,0,12664,1,0),(396,'Sanctuary',-1,2,65535,127,131071,0,3,0,0,1209,1,0),(397,'Destructive Fury',-1,2048,65535,127,131071,0,2,0,0,1210,1,0),(398,'Destructive Fury',-1,13858,65535,127,131071,0,2,0,0,1213,1,0),(399,'Unknown AA 16180',-1,8,65535,127,131071,0,3,0,0,16180,1,0),(400,'Hastened Improved Twincast',-1,14370,65535,127,131071,0,3,0,0,14331,1,0),(401,'Extended Heel of Kanji',-1,64,65535,127,131071,0,3,0,0,12688,1,0),(402,'Extended Scaledfist',-1,64,65535,127,131071,0,3,0,0,12691,1,0),(403,'Paralytic Spores',-1,544,65535,127,131071,0,3,0,0,14264,1,0),(404,'Call of the Wild',-1,544,65535,127,131071,0,3,0,0,1228,1,0),(405,'Secondary Recall',-1,2080,65535,127,131071,0,3,0,0,1229,1,0),(406,'Nature\'s Bounty',-1,40,65535,127,131071,0,3,0,0,1230,1,0),(407,'Extended Speed Focus',-1,64,65535,127,131071,0,3,0,0,7884,1,0),(408,'Extended Crystalpalm',-1,64,65535,127,131071,0,3,0,0,7885,1,0),(409,'Stasis',-1,8192,65535,127,131071,0,3,0,0,1233,1,0),(410,'Fists of Steel',-1,64,65535,127,131071,0,3,0,0,12706,1,0),(411,'Extended Deftdance',-1,128,65535,127,131071,0,3,0,0,12709,1,0),(412,'Color Shock',-1,8192,65535,127,131071,0,3,0,0,1239,1,0),(413,'Mind Over Matter',-1,8192,65535,127,131071,0,3,0,0,1242,1,0),(414,'Soothing Words',-1,8192,65535,127,131071,0,3,0,0,1245,1,0),(415,'Hastened Deftdance',-1,128,65535,127,131071,0,3,0,0,12710,1,0),(416,'Hastened Lyre Leap',-1,128,65535,127,131071,0,3,0,0,12713,1,0),(417,'Hastened Quick Time',-1,128,65535,127,131071,0,3,0,0,12716,1,0),(418,'Replenish Companion',-1,21504,65535,127,131071,0,3,0,0,1126,1,0),(419,'Extended Quick Time',-1,128,65535,127,131071,0,3,0,0,12719,1,0),(420,'Imitate Death',-1,64,65535,127,131071,0,3,0,0,1255,1,0),(424,'Extended Fierce Eye',-1,128,65535,127,131071,0,3,0,0,12720,1,0),(425,'Hastened Fierce Eye',-1,128,65535,127,131071,0,3,0,0,12721,1,0),(426,'Unknown AA 15904',-1,2080,65535,127,131071,0,3,0,0,15904,1,0),(427,'Resounding Dirge',-1,128,65535,127,131071,0,3,0,0,12737,1,0),(428,'Death Peace',-1,1040,65535,127,131071,0,3,0,0,1272,1,0),(429,'Unknown AA 15908',-1,64,65535,127,131071,0,3,0,0,15908,1,0),(430,'Mercurial Torment',-1,1024,65535,127,131071,0,3,0,0,12766,1,0),(431,'Pestilent Paralysis',-1,1024,65535,127,131071,0,3,0,0,12770,1,0),(432,'Hastened Divine Companion Aura',-1,30224,65535,127,131071,0,3,0,0,12773,1,0),(433,'Embalmer\'s Carapace',-1,1024,65535,127,131071,0,3,0,0,12778,1,0),(434,'Steadfast Will',-1,20,65535,127,131071,0,3,0,0,1284,1,0),(435,'Shield Block',-1,21,65535,127,131071,0,2,0,0,1287,1,0),(436,'Hastened Encroaching Darkness',-1,1024,65535,127,131071,0,3,0,0,12779,1,0),(437,'Tracking Mastery',-1,8,65535,127,131071,0,3,0,0,1296,1,0),(438,'Expanding Darkness',-1,1024,65535,127,131071,0,3,0,0,12782,1,0),(439,'Precision',-1,256,65535,127,131071,0,3,0,0,1304,1,0),(440,'Nerves of Steel',-1,256,65535,127,131071,0,3,0,0,1307,1,0),(441,'Aegis of Kildrukaun',-1,5120,65535,127,131071,0,3,0,0,12785,1,0),(442,'Touch of the Cursed',-1,16,65535,127,131071,0,3,0,0,1313,1,0),(443,'Bestial Bloodrage',-1,16384,65535,127,131071,0,3,0,0,12804,1,0),(444,'Companion\'s Sacrifice',-1,16384,65535,127,131071,0,3,0,0,12807,1,0),(445,'Shield Block',-1,16384,65535,127,131071,0,2,0,0,12813,1,0),(446,'Spiritual Channeling',-1,512,65535,127,131071,0,3,0,0,1323,1,0),(447,'Ancestral Aid',-1,512,65535,127,131071,0,3,0,0,1327,1,0),(448,'Extended Feralgia',-1,16384,65535,127,131071,0,3,0,0,12816,1,0),(450,'Hastened Protective Spirit',-1,16384,65535,127,131071,0,3,0,0,12819,1,0),(451,'Mind Crash',-1,2048,65535,127,131071,0,3,0,0,1334,1,0),(452,'Prolonged Destruction',-1,2048,65535,127,131071,0,3,0,0,1337,1,0),(453,'Summon Permutation Peddler',5,65535,65535,127,131071,0,4,0,1,9032,1,0),(454,'Hastened Empathic Fury',-1,16384,65535,127,131071,0,3,0,0,12822,1,0),(455,'Convergence of Spirits',-1,8,65535,127,131071,0,3,0,0,13556,1,0),(456,'Teleport Bind',-1,2048,65535,127,131071,0,3,0,0,1343,1,0),(457,'Quickened Paragon of Spirit',-1,16384,65535,127,131071,0,3,0,0,12831,1,0),(458,'Warder\'s Gift',-1,16384,65535,127,131071,0,3,0,0,12837,1,0),(459,'Gelid Rending',-1,16384,65535,127,131071,0,3,0,0,12846,1,0),(460,'Quickened Nature\'s Salve',-1,16384,65535,127,131071,0,3,0,0,12849,1,0),(462,'Auspice of the Hunter',-1,8,65535,127,131071,0,3,0,0,1345,1,0),(463,'Divine Guardian',-1,2,65535,127,131071,0,3,0,0,13385,1,0),(464,'Divine Peace',-1,2,65535,127,131071,0,3,0,0,13388,1,0),(465,'Savage Spirit',-1,32768,65535,127,131071,0,3,0,0,1348,1,0),(466,'Trials of Mata Muram',2,65535,65535,127,131071,0,4,0,1,1011,1,0),(467,'Press the Attack',-1,1,65535,127,131071,0,3,0,0,1351,1,0),(468,'Crippling Strike',-1,64,65535,127,131071,0,3,0,0,1352,1,0),(469,'Stunning Kick',-1,64,65535,127,131071,0,3,0,0,1355,1,0),(470,'Eye Gouge',-1,64,65535,127,131071,0,3,0,0,1358,1,0),(471,'Gift of the Dark Reign',2,65535,65535,127,131071,0,4,0,1,1361,1,0),(472,'Tenacity of the Dark Reign',2,65535,65535,127,131071,0,4,0,1,1362,1,0),(473,'Embrace of the Dark Reign',2,65535,65535,127,131071,0,4,0,1,1363,1,0),(474,'Power of the Dark Reign',2,65535,65535,127,131071,0,4,0,1,1364,1,0),(475,'Fervor of the Dark Reign',2,65535,65535,127,131071,0,4,0,1,1365,1,0),(476,'Gift of the Keepers',2,65535,65535,127,131071,0,4,0,1,1366,1,0),(477,'Valor of the Keepers',2,65535,65535,127,131071,0,4,0,1,1367,1,0),(478,'Embrace of the Keepers',2,65535,65535,127,131071,0,4,0,1,1368,1,0),(479,'Power of the Keepers',2,65535,65535,127,131071,0,4,0,1,1369,1,0),(480,'Sanctity of the Keepers',2,65535,65535,127,131071,0,4,0,1,1370,1,0),(481,'Lesson of the Devoted',5,65535,65535,127,131071,0,4,0,1,1371,1,0),(482,'Infusion of the Faithful',5,65535,65535,127,131071,0,4,0,1,1372,1,0),(483,'Chaotic Jester',5,65535,65535,127,131071,0,4,0,1,1373,1,0),(484,'Expedient Recovery',5,65535,65535,127,131071,0,4,0,1,1374,1,0),(485,'Steadfast Servant',5,65535,65535,127,131071,0,4,0,1,1375,1,0),(486,'Staunch Recovery',5,65535,65535,127,131071,0,4,0,1,1376,1,0),(487,'Intensity of the Resolute',5,65535,65535,127,131071,0,4,0,1,1377,1,0),(488,'Curse of Blood',2,65535,65535,127,131071,0,4,0,1,1378,1,0),(489,'Yaulp',-1,6,65535,127,131071,0,3,0,0,13389,1,0),(490,'Abscond',-1,2048,65535,127,131071,0,3,0,0,12864,1,0),(491,'Atol\'s Unresistable Shackles',-1,2048,65535,127,131071,0,3,0,0,12865,1,0),(492,'Dimensional Shield',-1,14336,65535,127,131071,0,3,0,0,12866,1,0),(493,'Improved Sustained Destruction',-1,2048,65535,127,131071,0,3,0,0,12867,1,0),(494,'Silent Casting',-1,546,65535,127,131071,0,2,0,0,1409,1,0),(495,'Gift of Mana',-1,15906,65535,127,131071,0,2,0,0,1435,1,0),(496,'Field Dressing',-1,32769,65535,127,131071,0,3,0,0,1611,1,0),(497,'Bandage Wounds',-1,32766,65535,127,131071,0,1,0,0,1420,1,0),(498,'Enhanced Aggression',-1,49629,65535,127,131071,0,2,0,0,1592,1,0),(499,'Cascading Rage',-1,32768,65535,127,131071,0,3,0,0,1425,1,0),(500,'Silent Casting',-1,15360,65535,127,131071,0,2,0,0,1404,1,0),(501,'E\'ci\'s Icy Blessing',-1,2048,65535,127,131071,0,3,0,0,12886,1,0),(503,'Hastened Thunder',-1,16384,65535,127,131071,0,3,0,0,1471,1,0),(504,'Conservation',-1,32768,65535,127,131071,0,3,0,0,1453,1,0),(505,'Cry of Battle',-1,32768,65535,127,131071,0,3,0,0,1458,1,0),(506,'Ward of Purity',-1,2,65535,127,131071,0,3,0,0,1459,1,0),(507,'Ro\'s Fiery Blessing',-1,2048,65535,127,131071,0,3,0,0,12887,1,0),(508,'Druzzil\'s Mystical Blessing',-1,2048,65535,127,131071,0,3,0,0,12888,1,0),(509,'Kerafyrm\'s Favor',-1,2048,65535,127,131071,0,3,0,0,12889,1,0),(510,'Kerafyrm\'s Prismatic Familiar',-1,2048,65535,127,131071,0,3,0,0,12892,1,0),(511,'Throne of Heroes',5,65535,65535,127,131071,0,4,0,1,4665,1,0),(512,'Translocational Anchor',-1,2048,65535,127,131071,0,3,0,0,1630,1,0),(513,'Hastened Phantasmal Opponent',-1,8192,65535,127,131071,0,3,0,0,12894,1,0),(514,'Pyromancy',-1,2048,65535,127,131071,0,3,0,0,1478,1,0),(515,'Improved Twincast',-1,14370,65535,127,131071,0,3,0,0,12893,1,0),(516,'Abundant Healing',-1,546,65535,127,131071,0,2,0,0,1486,1,0),(517,'Hastened First Spire of Enchantment',-1,8192,65535,127,131071,0,3,0,0,12902,1,0),(518,'Shared Camouflage',-1,40,65535,127,131071,0,3,0,0,1494,1,0),(519,'Convergence of Spirits',-1,32,65535,127,131071,0,3,0,0,1495,1,0),(520,'Nature\'s Guardian',-1,32,65535,127,131071,0,3,0,0,1498,1,0),(521,'Edict of Command',-1,8192,65535,127,131071,0,3,0,0,1501,1,0),(522,'Extended Burnout',-1,4096,65535,127,131071,0,3,0,0,1504,1,0),(523,'Hastened Second Spire of Enchantment',-1,8192,65535,127,131071,0,3,0,0,12907,1,0),(524,'Blood Magic',-1,1024,65535,127,131071,0,3,0,0,1510,1,0),(525,'Graverobbing',-1,1024,65535,127,131071,0,3,0,0,1511,1,0),(526,'Affliction Mastery',-1,1568,65535,127,131071,0,3,0,0,1514,1,0),(527,'Hastened Third Spire of Enchantment',-1,8192,65535,127,131071,0,3,0,0,12912,1,0),(528,'Ancestral Guard',-1,512,65535,127,131071,0,3,0,0,1520,1,0),(529,'Cloak of Light',-1,4,65535,127,131071,0,3,0,0,1523,1,0),(530,'Profound Visage',-1,8192,65535,127,131071,0,3,0,0,12920,1,0),(531,'Cloak of Shadows',-1,1040,65535,127,131071,0,3,0,0,1527,1,0),(532,'Willful Death',-1,1040,65535,127,131071,0,3,0,0,1528,1,0),(533,'Unknown AA 16016',-1,1024,65535,127,131071,0,3,0,0,16016,1,0),(534,'Calculated Insanity',-1,8192,65535,127,131071,0,3,0,0,12931,1,0),(535,'Crippling Aurora',-1,8192,65535,127,131071,0,3,0,0,12937,1,0),(536,'Appraisal',-1,256,65535,127,131071,0,3,0,0,1542,1,0),(537,'Precise Strikes',-1,256,65535,127,131071,0,3,0,0,1543,1,0),(538,'Hastened Death',-1,64,65535,127,131071,0,3,0,0,1546,1,0),(539,'Unflinching Resolve',-1,64,65535,127,131071,0,3,0,0,1549,1,0),(540,'Weightless Steps',-1,64,65535,127,131071,0,3,0,0,1552,1,0),(541,'Hastened Blades',-1,128,65535,127,131071,0,3,0,0,1555,1,0),(542,'Unknown AA 16071',-1,8192,65535,127,131071,0,3,0,0,16071,1,0),(543,'Diminutive Companion',-1,20480,65535,127,131071,0,3,0,0,12941,1,0),(544,'Song of Stone',-1,128,65535,127,131071,0,3,0,0,1569,1,0),(545,'Deep Sleep',-1,8192,65535,127,131071,0,3,0,0,1572,1,0),(546,'Companion\'s Gift',-1,4096,65535,127,131071,0,3,0,0,1577,1,0),(547,'Unknown AA 16081',-1,15360,65535,127,131071,0,3,0,0,16081,1,0),(548,'Hastened Defiance',-1,1,65535,127,131071,0,3,0,0,1583,1,0),(549,'Dauntless Perseverance',-1,1,65535,127,131071,0,3,0,0,1591,1,0),(550,'Steadfast Resolve',-1,16384,65535,127,131071,0,3,0,0,14275,1,0),(551,'Hastened Mind Crash',-1,2048,65535,127,131071,0,3,0,0,1414,1,0),(552,'Call of Challenge',-1,1,65535,127,131071,0,3,0,0,1597,1,0),(553,'Cacophony',-1,128,65535,127,131071,0,3,0,0,1598,1,0),(554,'Hastened Nightmare Stasis',-1,8192,65535,127,131071,0,3,0,0,14341,1,0),(555,'Anatomy',-1,256,65535,127,131071,0,3,0,0,1604,1,0),(556,'Scintillating Beam',-1,8192,65535,127,131071,0,3,0,0,14346,1,0),(557,'Trick Shot',-1,8,65535,127,131071,0,3,0,0,1608,1,0),(558,'Turn Undead',-1,2,65535,127,131071,0,3,0,0,1383,1,0),(559,'Turn Summoned',-1,4096,65535,127,131071,0,3,0,0,1462,1,0),(560,'Selo\'s Enduring Cadence',-1,128,65535,127,131071,0,3,0,0,1627,1,0),(561,'Hastened Harvest of Druzzil',-1,2048,65535,127,131071,0,3,0,0,12881,1,0),(562,'Lightning Strikes',-1,8,65535,127,131071,0,3,0,0,1616,1,0),(563,'Concentration',-1,33089,65535,127,131071,0,2,0,0,1588,1,0),(565,'Mana Burn',-1,2048,65535,127,131071,0,3,0,0,1638,1,0),(567,'Unknown AA 16146',-1,2,65535,127,131071,0,3,0,0,16146,1,0),(568,'Thief\'s Intuition',-1,256,65535,127,131071,0,3,0,0,1641,1,0),(569,'Thief\'s Intuition',-1,128,65535,127,131071,0,3,0,0,1642,1,0),(570,'Valiant Steed',-1,4,65535,127,131071,0,3,0,0,1645,1,0),(571,'Abyssal Steed',-1,16,65535,127,131071,0,3,0,0,1646,1,0),(572,'Holy Warhorse',-1,4,65535,127,131071,0,3,0,1,1643,1,0),(573,'Unholy Warhorse',-1,16,65535,127,131071,0,3,0,1,1644,1,0),(574,'Harmonic Dissonance',2,65535,65535,127,131071,0,4,0,1,1647,1,0),(575,'Tinkering Mastery',6,15639,65535,127,131071,0,1,0,1,4672,1,0),(576,'Jewel Craft Mastery ',6,57343,65535,127,131071,0,1,0,0,4675,1,0),(577,'Concussive Intuition',-1,2048,65535,127,131071,0,3,0,0,12885,1,0),(578,'Glyph Spray',-1,8192,65535,127,131071,0,3,0,0,12939,1,0),(579,'Combat Medic ',-1,32766,65535,127,131071,0,1,0,0,4688,1,0),(580,'Hastened Outrider\'s Accuracy',-1,8,65535,127,131071,0,3,0,0,13565,1,0),(581,'Quick Draw',-1,65535,65535,127,131071,0,1,0,0,4698,1,0),(582,'Battle Ready',-1,65535,65535,127,131071,0,1,0,0,4699,1,0),(583,'Hastened Outrider\'s Evasion',-1,8,65535,127,131071,0,3,0,0,13568,1,0),(584,'Grasp of Sylvan Spirits',-1,8,65535,127,131071,0,3,0,0,13571,1,0),(585,'Glyph of Dragon Scales',7,65535,65535,127,131071,0,4,1,0,4702,1,0),(586,'Glyph of Indeterminable Reward',7,65535,65535,127,131071,0,4,1,0,13788,1,0),(587,'Glyph of Arcane Secrets',7,32318,65535,127,131071,0,4,1,0,4704,1,0),(588,'Glyph of Draconic Potential',7,65535,65535,127,131071,0,4,1,0,4705,1,0),(589,'Glyph of Destruction',7,65535,65535,127,131071,0,4,1,0,4706,1,0),(590,'Breath of Atathus',8,65535,65535,127,131071,0,4,0,1,5150,1,0),(591,'Breath of Draton\'ra',8,65535,65535,127,131071,0,4,0,1,5165,1,0),(592,'Breath of Osh\'vir',8,65535,65535,127,131071,0,4,0,1,5180,1,0),(593,'Breath of Venesh',8,65535,65535,127,131071,0,4,0,1,5195,1,0),(594,'Breath of Mysaphar',8,65535,65535,127,131071,0,4,0,1,5210,1,0),(595,'Breath of Keikolin',8,65535,65535,127,131071,0,4,0,1,5225,1,0),(596,'Small Modulation Shard',-1,4096,65535,127,131071,0,3,0,0,12963,1,0),(597,'Medium Modulation Shard',-1,4096,65535,127,131071,0,3,0,0,12964,1,0),(598,'Large Modulation Shard',-1,4096,65535,127,131071,0,3,0,0,12965,1,0),(599,'Hastened Malosinete',-1,4608,65535,127,131071,0,3,0,0,12968,1,0),(600,'Blessing of the Devoted',5,65535,65535,127,131071,0,4,0,1,9033,1,0),(601,'Grappling Strike',-1,65,65535,127,131071,0,3,0,0,4836,1,0),(602,'Mental Contortion',-1,8192,65535,127,131071,0,3,0,0,12938,1,0),(603,'Shield of the Elements',-1,4096,65535,127,131071,0,3,0,0,12971,1,0),(604,'Extended Malosinete',-1,4608,65535,127,131071,0,3,0,0,12977,1,0),(605,'Shield Specialist',-1,1,65535,127,131071,0,3,0,0,4844,1,0),(606,'Mark of the Mage Hunter',-1,1,65535,127,131071,0,3,0,0,4849,1,0),(609,'Uncanny Resilience',-1,32768,65535,127,131071,0,3,0,0,4854,1,0),(610,'Blinding Fury',-1,32768,65535,127,131071,0,3,0,0,4857,1,0),(611,'Battle Leap',-1,32769,65535,127,131071,0,3,0,0,4860,1,0),(612,'Soul Seeker',-1,1024,65535,127,131071,0,3,0,0,4861,1,0),(613,'Lingering Death',-1,1024,65535,127,131071,0,3,0,0,13096,1,0),(614,'Spirit Guardian',-1,512,65535,127,131071,0,3,0,0,5369,1,0),(615,'Surreality',-1,8192,65535,127,131071,0,3,0,0,4887,1,0),(616,'Mana Draw',-1,8192,65535,127,131071,0,3,0,0,4890,1,0),(617,'Doppelganger\'s Beckon',-1,8192,65535,127,131071,0,3,0,0,5127,1,0),(618,'Armor of Ancestral Spirits',-1,512,65535,127,131071,0,3,0,0,12989,1,0),(619,'Group Pact of the Wolf',-1,512,65535,127,131071,0,3,0,0,12992,1,0),(620,'Hastened Inconspicuous Totem',-1,512,65535,127,131071,0,3,0,0,13001,1,0),(621,'Fire Core',-1,4096,65535,127,131071,0,3,0,0,4903,1,0),(622,'Vapor Core',-1,4096,65535,127,131071,0,3,0,0,4906,1,0),(623,'Ice Core ',-1,4096,65535,127,131071,0,3,0,0,4909,1,0),(624,'Stone Core ',-1,4096,65535,127,131071,0,3,0,0,4912,1,0),(625,'Volatile Mana Blaze',-1,2048,65535,127,131071,0,3,0,0,4915,1,0),(626,'Purified Spirits',-1,546,65535,127,131071,0,3,0,0,13004,1,0),(627,'Group Spirit Walk',-1,512,65535,127,131071,0,3,0,0,13008,1,0),(628,'Greater Blood Tithe',-1,1024,65535,127,131071,0,3,0,0,4924,1,0),(629,'Gathering Dusk',-1,1024,65535,127,131071,0,3,0,0,4927,1,0),(630,'Group Silent Presence',-1,512,65535,127,131071,0,3,0,0,13009,1,0),(631,'Double Attack',-1,512,65535,127,131071,0,3,0,0,5366,1,0),(632,'Sanguine Mind Crystal',-1,8192,65535,127,131071,0,3,0,0,4934,1,0),(633,'Azure Mind Crystal',-1,8192,65535,127,131071,0,3,0,0,4935,1,0),(634,'Hastened Cannibalization',-1,512,65535,127,131071,0,3,0,0,13010,1,0),(635,'Hastened Spirit Channeling',-1,512,65535,127,131071,0,3,0,0,13013,1,0),(636,'Arcane Whisper',-1,14336,65535,127,131071,0,3,0,0,4938,1,0),(637,'Vengeful Spirits',-1,9776,65535,127,131071,0,3,0,0,13017,1,0),(638,'Crippling Apparition',-1,512,65535,127,131071,0,3,0,0,13020,1,0),(639,'Dimensional Instability',-1,14336,65535,127,131071,0,3,0,0,4943,1,0),(640,'Cryomancy',-1,2048,65535,127,131071,0,3,0,0,4944,1,0),(641,'Hastened Self Preservation',-1,32768,65535,127,131071,0,3,0,0,13055,1,0),(642,'Binding Axe',-1,32768,65535,127,131071,0,3,0,0,13065,1,0),(643,'Agony of Absolution',-1,32768,65535,127,131071,0,3,0,0,13066,1,0),(644,'Hastened Absolution',-1,32768,65535,127,131071,0,3,0,0,13067,1,0),(645,'Hastened Calculated Insanity',-1,8192,65535,127,131071,0,3,0,0,13753,1,0),(646,'Hastened Mental Contortion',-1,8192,65535,127,131071,0,3,0,0,13758,1,0),(647,'Hastened Crippling Aurora',-1,8192,65535,127,131071,0,3,0,0,13764,1,0),(649,'Hastened Leech Touch',-1,16,65535,127,131071,0,3,0,0,14046,1,0),(650,'Bony Grasp of Death',-1,16,65535,127,131071,0,3,0,0,14051,1,0),(651,'Thought Leech',-1,16,65535,127,131071,0,3,0,0,14052,1,0),(652,'Hastened Leechcurse Discipline',-1,16,65535,127,131071,0,3,0,0,14056,1,0),(653,'Hastened Unholy Aura Discipline',-1,16,65535,127,131071,0,3,0,0,14059,1,0),(654,'Hastened Harmshield',-1,1040,65535,127,131071,0,3,0,0,14062,1,0),(655,'Hastened Projection of Doom',-1,16,65535,127,131071,0,3,0,0,14065,1,0),(656,'Hastened Projection of Piety',-1,4,65535,127,131071,0,3,0,0,14068,1,0),(657,'Shield of Brilliance',-1,4,65535,127,131071,0,3,0,0,14071,1,0),(658,'Hastened Sanctification Discipline',-1,4,65535,127,131071,0,3,0,0,14076,1,0),(659,'Speed of the Savior',-1,4,65535,127,131071,0,3,0,0,14080,1,0),(660,'Divine Call',-1,4,65535,127,131071,0,3,0,0,14081,1,0),(661,'Hunter\'s Fury',-1,8,65535,127,131071,0,3,0,0,5248,1,0),(662,'Union of Spirits',-1,512,65535,127,131071,0,3,0,0,5251,1,0),(663,'Quickened Stuns',-1,4,65535,127,131071,0,3,0,0,14100,1,0),(664,'Extended Outrider\'s Attack',-1,8,65535,127,131071,0,3,0,0,14115,1,0),(665,'Death\'s Wrath',-1,1024,65535,127,131071,0,3,0,0,5264,1,0),(666,'Taste of Blood',-1,16384,65535,127,131071,0,3,0,0,5015,1,0),(667,'Summoner\'s Beckon',-1,4096,65535,127,131071,0,3,0,0,5269,1,0),(668,'Hymn of the Last Stand',-1,128,65535,127,131071,0,3,0,0,5017,1,0),(669,'Bladed Song',-1,128,65535,127,131071,0,3,0,0,5020,1,0),(670,'Twisted Shank',-1,256,65535,127,131071,0,3,0,0,5021,1,0),(671,'Dirty Fighting',-1,256,65535,127,131071,0,3,0,0,5022,1,0),(672,'Ligament Slice',-1,256,65535,127,131071,0,3,0,0,5025,1,0),(673,'Tumble',-1,256,65535,127,131071,0,3,0,0,5028,1,0),(674,'Unknown AA 16149',-1,2,65535,127,131071,0,3,0,0,16149,1,0),(675,'Shrink',-1,512,65535,127,131071,0,3,0,0,14224,1,0),(676,'Convergence',-1,1024,65535,127,131071,0,3,0,0,14358,1,0),(677,'Gift of Deathly Resolve',-1,1024,65535,127,131071,0,3,0,0,14359,1,0),(678,'Unknown AA 16082',-1,2080,65535,127,131071,0,3,0,0,16082,1,0),(679,'Unknown AA 16083',-1,15906,65535,127,131071,0,2,0,0,16083,1,0),(680,'Unknown AA 16084',-1,2048,65535,127,131071,0,3,0,0,16084,1,0),(681,'Unknown AA 16087',-1,2048,65535,127,131071,0,3,0,0,16087,1,0),(682,'Unknown AA 16096',-1,8,65535,127,131071,0,3,0,0,16096,1,0),(683,'Unknown AA 16097',-1,8,65535,127,131071,0,3,0,0,16097,1,0),(684,'Unknown AA 16104',-1,1,65535,127,131071,0,3,0,0,16104,1,0),(685,'Unknown AA 16105',-1,1,65535,127,131071,0,3,0,0,16105,1,0),(686,'Unknown AA 16106',-1,1,65535,127,131071,0,3,0,0,16106,1,0),(687,'Unknown AA 16107',-1,1,65535,127,131071,0,3,0,0,16107,1,0),(688,'Unknown AA 16108',-1,1,65535,127,131071,0,3,0,0,16108,1,0),(689,'Combat Medic ',-1,32769,65535,127,131071,0,3,0,0,5136,1,0),(690,'Unknown AA 16109',-1,1,65535,127,131071,0,3,0,0,16109,1,0),(691,'Unknown AA 16113',-1,1,65535,127,131071,0,3,0,0,16113,1,0),(692,'Unknown AA 16114',-1,1,65535,127,131071,0,3,0,0,16114,1,0),(693,'Unknown AA 16117',-1,1,65535,127,131071,0,3,0,0,16117,1,0),(694,'Unknown AA 16120',-1,1,65535,127,131071,0,3,0,0,16120,1,0),(695,'Unknown AA 16152',-1,2,65535,127,131071,0,3,0,0,16152,1,0),(696,'Unknown AA 16156',-1,2,65535,127,131071,0,3,0,0,16156,1,0),(697,'Mortal Coil',-1,16,65535,127,131071,0,3,0,0,5085,1,0),(698,'Hastened Purified Spirits',-1,546,65535,127,131071,0,3,0,0,13416,1,0),(699,'Swarm of Fireflies',-1,32,65535,127,131071,0,3,0,0,13419,1,0),(700,'Unknown AA 16159',-1,2,65535,127,131071,0,3,0,0,16159,1,0),(701,'Armor of the Inquisitor',-1,4,65535,127,131071,0,3,0,0,5095,1,0),(702,'Hand of Disruption',-1,4,65535,127,131071,0,3,0,0,5098,1,0),(703,'Quickened Death Bloom',-1,1024,65535,127,131071,0,3,0,0,14318,1,0),(704,'Hero\'s Barracks',9,65535,65535,127,131071,0,4,0,1,14367,1,0),(705,'Spirit of the White Wolf',-1,32,65535,127,131071,0,3,0,0,5105,1,0),(706,'Unknown AA 16160',-1,2,65535,127,131071,0,3,0,0,16160,1,0),(707,'Pact of the Wolf',-1,512,65535,127,131071,0,3,0,0,5109,1,0),(708,'Enchant Alaran Metal',-1,8192,65535,127,131071,0,3,0,1,13271,1,0),(709,'Mass Enchant Alaran Metal',-1,8192,65535,127,131071,0,3,0,1,13272,1,0),(710,'Funeral Pyre',-1,1024,65535,127,131071,0,3,0,0,14360,1,0),(711,'Unknown AA 16162',-1,2,65535,127,131071,0,3,0,0,16162,1,0),(712,'Hastened Sanctuary',-1,2,65535,127,131071,0,3,0,0,5118,1,0),(713,'Etherium Blades',-1,256,65535,127,131071,0,3,0,0,14129,1,0),(714,'Hastened Assassination Disciplines',-1,256,65535,127,131071,0,3,0,0,14135,1,0),(715,'Cunning Disguise: Shissar',-1,256,65535,127,131071,0,3,0,0,14139,1,0),(716,'Scout\'s Mastery of Piercing',-1,256,65535,127,131071,0,3,0,0,14141,1,0),(717,'Extended Envenomed Blades',-1,256,65535,127,131071,0,3,0,0,14144,1,0),(718,'Heel of Brithrax',-1,64,65535,127,131071,0,3,0,0,14151,1,0),(719,'Extended Zan Fi\'s Whistle',-1,64,65535,127,131071,0,3,0,0,14163,1,0),(720,'Hastened Marr\'s Salvation',-1,4,65535,127,131071,0,3,0,0,14088,1,0),(721,'Hastened Armor of the Inquisitor',-1,4,65535,127,131071,0,3,0,0,14091,1,0),(722,'Hastened Drape of Shadows',-1,4096,65535,127,131071,0,3,0,0,14304,1,0),(723,'Unknown AA 16185',-1,8,65535,127,131071,0,3,0,0,16185,1,0),(724,'Hastened Eldritch Rune',-1,8192,65535,127,131071,0,3,0,0,14364,1,0),(725,'Unknown AA 16124',-1,4,65535,127,131071,0,3,0,0,16124,1,0),(726,'Unknown AA 16128',-1,4,65535,127,131071,0,3,0,0,16128,1,0),(727,'Unknown AA 16131',-1,4,65535,127,131071,0,3,0,0,16131,1,0),(728,'Unknown AA 16137',-1,4,65535,127,131071,0,3,0,0,16137,1,0),(729,'Unknown AA 16140',-1,6,65535,127,131071,0,3,0,0,16140,1,0),(730,'Unknown AA 16186',-1,9,65535,127,131071,0,3,0,0,16186,1,0),(731,'Unknown AA 16188',-1,16,65535,127,131071,0,3,0,0,16188,1,0),(732,'Unknown AA 16195',-1,16,65535,127,131071,0,3,0,0,16195,1,0),(733,'Killing Spree',-1,33089,65535,127,131071,0,2,0,0,4739,1,0),(734,'Hold the Line',-1,32833,65535,127,131071,0,3,0,0,4742,1,0),(735,'Battle Frenzy',-1,2,65535,127,131071,0,3,0,0,13134,1,0),(737,'Quickened Silent Casting',-1,15360,65535,127,131071,0,2,0,0,13143,1,0),(738,'Quickened Silent Casting',-1,546,65535,127,131071,0,2,0,0,13146,1,0),(739,'Balefire Burst',-1,4,65535,127,131071,0,3,0,0,13164,1,0),(740,'Blood Tithe',-1,1568,65535,127,131071,0,3,0,0,4761,1,0),(741,'Leap of Faith',-1,4,65535,127,131071,0,3,0,0,13202,1,0),(742,'Unknown AA 16196',-1,16,65535,127,131071,0,3,0,0,16196,1,0),(743,'Hastened Explosion of Hatred',-1,16,65535,127,131071,0,3,0,0,13166,1,0),(744,'Howl of the Warlord',-1,1,65535,127,131071,0,3,0,0,13169,1,0),(745,'Hastened Tune In Your Head',-1,128,65535,127,131071,0,3,0,0,13204,1,0),(746,'Unknown AA 16197',-1,16,65535,127,131071,0,3,0,0,16197,1,0),(747,'Unknown AA 16200',-1,16,65535,127,131071,0,3,0,0,16200,1,0),(748,'Nightmare Stasis',-1,8192,65535,127,131071,0,3,0,0,4894,1,0),(749,'Explosion of Spite',-1,16,65535,127,131071,0,3,0,0,13165,1,0),(751,'Scent of Terris',-1,1024,65535,127,131071,0,3,0,0,13225,1,0),(752,'Bloodfury',-1,32768,65535,127,131071,0,3,0,0,13224,1,0),(753,'Dreary Deeds',-1,8192,65535,127,131071,0,3,0,0,13252,1,0),(754,'Enchant Feymetal',-1,8192,65535,127,131071,0,3,0,1,13260,1,0),(755,'Mass Enchant Feymetal',-1,8192,65535,127,131071,0,3,0,1,13261,1,0),(756,'Enlightened Focus of Arcanum',-1,15904,65535,127,131071,0,3,0,0,13646,1,0),(757,'Shifting Elements',-1,4096,65535,127,131071,0,3,0,0,5276,1,0),(758,'Extended Silent Casting',-1,15360,65535,127,131071,0,3,0,0,13667,1,0),(759,'Fury of Kerafyrm',-1,2048,65535,127,131071,0,3,0,0,13670,1,0),(760,'Unknown AA 16203',-1,544,65535,127,131071,0,3,0,0,16203,1,0),(761,'Unknown AA 16208',-1,552,65535,127,131071,0,3,0,0,16208,1,0),(762,'Shield Block',-1,546,65535,127,131071,0,2,0,0,5283,1,0),(763,'Mirrored Pestilence',-1,1552,65535,127,131071,0,3,0,0,13684,1,0),(764,'Embrace The Decay',-1,1024,65535,127,131071,0,3,0,0,13687,1,0),(765,'Quickened Scent of Terris',-1,1024,65535,127,131071,0,3,0,0,13689,1,0),(766,'Frenzy of the Dead',-1,1024,65535,127,131071,0,3,0,0,13693,1,0),(767,'Unknown AA 16211',-1,512,65535,127,131071,0,3,0,0,16211,1,0),(768,'Unknown AA 16215',-1,32,65535,127,131071,0,3,0,0,16215,1,0),(769,'Marr\'s Salvation',-1,4,65535,127,131071,0,3,0,0,13100,1,0),(770,'Blessing of the Faithful',-1,4,65535,127,131071,0,3,0,0,13101,1,0),(771,'Unbridled Strike of Fear',-1,16,65535,127,131071,0,3,0,0,13108,1,0),(772,'Noteworthy Disguise: Drake',-1,128,65535,127,131071,0,3,0,0,14192,1,0),(773,'Death\'s Effigy',-1,1024,65535,127,131071,0,3,0,0,13133,1,0),(774,'Empowered Focus of Arcanum',-1,15904,65535,127,131071,0,3,0,0,14690,1,0),(775,'Unknown AA 16342',-1,1024,65535,127,131071,0,3,0,0,16342,1,0),(776,'Arcane Overkill',-1,2048,65535,127,131071,0,3,0,0,5295,1,0),(777,'Funeral Dirge',-1,128,65535,127,131071,0,3,0,0,5298,1,0),(778,'Protection of the Spirit Wolf',-1,8,65535,127,131071,0,3,0,0,5007,1,0),(779,'Hastened Juggernaut Surge',-1,32768,65535,127,131071,0,3,0,0,13873,1,0),(780,'Hastened Resilience',-1,32768,65535,127,131071,0,3,0,0,13878,1,0),(781,'Hastened Blood Pact',-1,32768,65535,127,131071,0,3,0,0,13881,1,0),(782,'Unknown AA 16317',-1,32768,65535,127,131071,0,3,0,0,16317,1,0),(783,'Energetic Attunement',-1,65535,65535,127,131071,0,1,0,0,1056,1,0),(784,'Heart of Flames',-1,4096,65535,127,131071,0,3,0,0,1251,1,0),(785,'Heart of Vapor',-1,4096,65535,127,131071,0,3,0,0,1252,1,0),(786,'Heart of Ice',-1,4096,65535,127,131071,0,3,0,0,1253,1,0),(787,'Heart of Stone',-1,4096,65535,127,131071,0,3,0,0,1254,1,0),(789,'Stealthy Getaway',-1,256,65535,127,131071,0,3,0,0,1477,1,0),(790,'Seized Opportunity',-1,256,65535,127,131071,0,3,0,0,878,1,0),(791,'Veil of Mindshadow',-1,8192,65535,127,131071,0,3,0,0,4931,1,0),(792,'Army of the Dead',-1,1024,65535,127,131071,0,3,0,0,1274,1,0),(793,'Mana Blast',-1,2048,65535,127,131071,0,3,0,0,1639,1,0),(794,'Mana Blaze',-1,2048,65535,127,131071,0,3,0,0,1640,1,0),(795,'Innate Corruption Protection',-1,65535,65535,127,131071,0,1,0,0,1662,1,0),(796,'Hastened Five Point Palm',-1,64,65535,127,131071,0,3,0,0,13889,1,0),(797,'Moving Mountains',-1,64,65535,127,131071,0,3,0,0,13130,1,0),(798,'Veturika\'s Perseverance',-1,2,65535,127,131071,0,3,0,0,14229,1,0),(799,'Unknown AA 16644',-1,16,65535,127,131071,0,3,0,0,16644,1,0),(800,'Vehement Rage',-1,32769,65535,127,131071,0,3,0,0,6607,1,0),(801,'Knee Strike',-1,1,65535,127,131071,0,3,0,0,6610,1,0),(802,'Hastened Fortitude Discipline',-1,1,65535,127,131071,0,3,0,0,6611,1,0),(803,'Hastened Furious Discipline',-1,1,65535,127,131071,0,3,0,0,6614,1,0),(804,'Warlord\'s Bravery',-1,1,65535,127,131071,0,3,0,0,6617,1,0),(805,'Hastened Speed Focus',-1,64,65535,127,131071,0,3,0,0,14148,1,0),(806,'Hastened Zan Fi\'s Whistle',-1,64,65535,127,131071,0,3,0,0,14160,1,0),(807,'Pressure Points',-1,64,65535,127,131071,0,3,0,0,14157,1,0),(808,'Hastened Thunder',-1,64,65535,127,131071,0,3,0,0,14166,1,0),(809,'Allegretto of Battle',-1,128,65535,127,131071,0,3,0,0,14181,1,0),(810,'Vivace of Conflict',-1,128,65535,127,131071,0,3,0,0,14186,1,0),(811,'Unknown AA 16218',-1,544,65535,127,131071,0,3,0,0,16218,1,0),(812,'Unknown AA 16221',-1,32,65535,127,131071,0,3,0,0,16221,1,0),(813,'Unknown AA 16222',-1,32,65535,127,131071,0,3,0,0,16222,1,0),(814,'Unknown AA 16225',-1,32,65535,127,131071,0,3,0,0,16225,1,0),(815,'Unknown AA 16230',-1,16384,65535,127,131071,0,3,0,0,16230,1,0),(816,'Unknown AA 16235',-1,16384,65535,127,131071,0,3,0,0,16235,1,0),(817,'Unknown AA 16238',-1,16384,65535,127,131071,0,3,0,0,16238,1,0),(818,'Unknown AA 16257',-1,64,65535,127,131071,0,3,0,0,16257,1,0),(819,'Unknown AA 16666',-1,16,65535,127,131071,0,3,0,0,16666,1,0),(820,'Death\'s Revenge',-1,16,65535,127,131071,0,3,0,0,6630,1,0),(821,'Harmshield',-1,1040,65535,127,131071,0,3,0,0,6635,1,0),(822,'Explosion of Hatred',-1,16,65535,127,131071,0,3,0,0,6640,1,0),(823,'Cascading Theft of Defense',-1,16,65535,127,131071,0,3,0,0,6641,1,0),(824,'Hate Step',-1,16,65535,127,131071,0,3,0,0,6644,1,0),(825,'Vicious Bite of Chaos',-1,16,65535,127,131071,0,3,0,0,6645,1,0),(826,'Encroaching Darkness',-1,1040,65535,127,131071,0,3,0,0,6646,1,0),(827,'Unknown AA 16745',-1,2,65535,127,131071,0,3,0,0,16745,1,0),(828,'Unknown AA 16260',-1,64,65535,127,131071,0,3,0,0,16260,1,0),(829,'Unknown AA 16263',-1,256,65535,127,131071,0,3,0,0,16263,1,0),(830,'Unknown AA 16272',-1,256,65535,127,131071,0,3,0,0,16272,1,0),(831,'Unknown AA 16276',-1,256,65535,127,131071,0,3,0,0,16276,1,0),(832,'Unknown AA 16287',-1,128,65535,127,131071,0,3,0,0,16287,1,0),(833,'Unknown AA 17252',-1,16,65535,127,131071,0,3,0,0,17252,1,0),(834,'Unknown AA 16296',-1,128,65535,127,131071,0,3,0,0,16296,1,0),(835,'Unknown AA 16300',-1,128,65535,127,131071,0,3,0,0,16300,1,0),(836,'Unknown AA 16310',-1,32768,65535,127,131071,0,3,0,0,16310,1,0),(837,'Unknown AA 16330',-1,32768,65535,127,131071,0,3,0,0,16330,1,0),(838,'Unknown AA 16163',-1,8,65535,127,131071,0,3,0,0,16163,1,0),(839,'Unknown AA 16360',-1,2080,65535,127,131071,0,3,0,0,16360,1,0),(840,'Unknown AA 16363',-1,2048,65535,127,131071,0,3,0,0,16363,1,0),(841,'Sleight of Hand',-1,256,65535,127,131071,0,3,0,0,6663,1,0),(842,'Enduring Vision',-1,256,65535,127,131071,0,3,0,0,6666,1,0),(843,'Expertise of Blades',-1,256,65535,127,131071,0,3,0,0,6668,1,0),(844,'Cunning Disguise: Human',-1,256,65535,127,131071,0,3,0,0,6671,1,0),(845,'Cunning Disguise: Half-Elf',-1,256,65535,127,131071,0,3,0,0,6672,1,0),(846,'Cunning Disguise: Barbarian',-1,256,65535,127,131071,0,3,0,0,6673,1,0),(847,'Cunning Disguise: Erudite',-1,256,65535,127,131071,0,3,0,0,6674,1,0),(848,'Cunning Disguise: Troll',-1,256,65535,127,131071,0,3,0,0,6675,1,0),(849,'Cunning Disguise: Goblin',-1,256,65535,127,131071,0,3,0,0,6676,1,0),(850,'Unknown AA 16366',-1,2048,65535,127,131071,0,3,0,0,16366,1,0),(851,'Unknown AA 16369',-1,2048,65535,127,131071,0,3,0,0,16369,1,0),(852,'Unknown AA 16370',-1,4096,65535,127,131071,0,3,0,0,16370,1,0),(853,'Unknown AA 16371',-1,4096,65535,127,131071,0,3,0,0,16371,1,0),(854,'Unknown AA 17256',-1,16,65535,127,131071,0,3,0,0,17256,1,0),(856,'Tigir\'s Insect Swarm',-1,512,65535,127,131071,0,3,0,0,6691,1,0),(857,'Dampen Resistance',-1,512,65535,127,131071,0,3,0,0,6692,1,0),(858,'Hastened Dampen Resistance',-1,512,65535,127,131071,0,3,0,0,6697,1,0),(859,'Spirit Walk',-1,512,65535,127,131071,0,3,0,0,6702,1,0),(860,'Hastened Virulent Paralysis',-1,512,65535,127,131071,0,3,0,0,6703,1,0),(861,'Languid Bite',-1,512,65535,127,131071,0,3,0,0,6706,1,0),(862,'Quickened Blood of Nadox',-1,512,65535,127,131071,0,3,0,0,6709,1,0),(863,'Hastened Spirit Call',-1,512,65535,127,131071,0,3,0,0,6712,1,0),(864,'Hastened Thousand Blades',-1,128,65535,127,131071,0,3,0,0,14169,1,0),(865,'Unknown AA 17257',-1,16,65535,127,131071,0,3,0,0,17257,1,0),(866,'Extended Dance of Blades',-1,128,65535,127,131071,0,3,0,0,14179,1,0),(867,'Extended Thousand Blades',-1,128,65535,127,131071,0,3,0,0,14180,1,0),(868,'Unknown AA 16380',-1,4096,65535,127,131071,0,3,0,0,16380,1,0),(869,'Unknown AA 16386',-1,4608,65535,127,131071,0,3,0,0,16386,1,0),(870,'Harmonious Arrow',-1,8,65535,127,131071,0,3,0,0,6750,1,0),(871,'Hastened Weapon Shield',-1,8,65535,127,131071,0,3,0,0,6751,1,0),(872,'Outrider\'s Attack',-1,8,65535,127,131071,0,3,0,0,6754,1,0),(873,'Group Guardian of the Forest',-1,8,65535,127,131071,0,3,0,0,6755,1,0),(874,'Pack Hunt',-1,8,65535,127,131071,0,3,0,0,6758,1,0),(875,'Keen Blade',-1,8,65535,127,131071,0,3,0,0,6761,1,0),(876,'Outrider\'s Evasion',-1,8,65535,127,131071,0,3,0,0,6764,1,0),(877,'Ranged Finesse',-1,8,65535,127,131071,0,3,0,0,6765,1,0),(878,'Bow Mastery',-1,8,65535,127,131071,0,3,0,0,1196,1,0),(879,'Unknown AA 17258',-1,1040,65535,127,131071,0,2,0,0,17258,1,0),(880,'Unknown AA 16392',-1,8192,65535,127,131071,0,3,0,0,16392,1,0),(881,'Unknown AA 16395',-1,10248,65535,127,131071,0,3,0,0,16395,1,0),(882,'Unknown AA 16396',-1,8192,65535,127,131071,0,3,0,0,16396,1,0),(883,'Unknown AA 16536',-1,546,65535,127,131071,0,2,0,0,16536,1,0),(884,'Unknown AA 17209',-1,1,65535,127,131071,0,3,0,0,17209,1,0),(885,'Unknown AA 17212',-1,1,65535,127,131071,0,2,0,0,17212,1,0),(886,'Unknown AA 17218',-1,1,65535,127,131071,0,3,0,0,17218,1,0),(888,'Unknown AA 17555',-1,1024,65535,127,131071,0,5,0,0,17555,1,0),(889,'Unknown AA 17229',-1,4,65535,127,131071,0,3,0,0,17229,1,0),(890,'Unknown AA 17235',-1,4,65535,127,131071,0,3,0,0,17235,1,0),(891,'Healing Light',-1,4,65535,127,131071,0,3,0,0,6791,1,0),(892,'Halt the Dead',-1,4,65535,127,131071,0,3,0,0,6794,1,0),(894,'Unknown AA 17242',-1,4,65535,127,131071,0,3,0,0,17242,1,0),(895,'Unknown AA 17245',-1,16,65535,127,131071,0,3,0,0,17245,1,0),(896,'Unknown AA 17249',-1,16,65535,127,131071,0,3,0,0,17249,1,0),(897,'Unknown AA 17199',7,65535,65535,127,131071,0,4,1,0,17199,1,0),(898,'Unknown AA 17267',-1,16,65535,127,131071,0,3,0,0,17267,1,0),(899,'Unknown AA 17273',-1,128,65535,127,131071,0,3,0,0,17273,1,0),(900,'Rise of Bones',-1,1024,65535,127,131071,0,3,0,0,6815,1,0),(901,'Whisperwind',-1,1024,65535,127,131071,0,3,0,0,6818,1,0),(902,'Hastened Blood Magic',-1,1024,65535,127,131071,0,3,0,0,6819,1,0),(903,'Overpower Undead',-1,1024,65535,127,131071,0,3,0,0,6822,1,0),(904,'Hastened Swarm of Decay',-1,1024,65535,127,131071,0,3,0,0,6823,1,0),(905,'Gift of the Grave',-1,1024,65535,127,131071,0,3,0,0,6828,1,0),(906,'Hastened Gut Punch',-1,1,65535,127,131071,0,3,0,0,10522,1,0),(907,'Hastened First Spire of the Warlord',-1,1,65535,127,131071,0,3,0,0,10527,1,0),(908,'Hastened Second Spire of the Warlord',-1,1,65535,127,131071,0,3,0,0,10532,1,0),(909,'Hastened Third Spire of the Warlord',-1,1,65535,127,131071,0,3,0,0,10537,1,0),(910,'Unknown AA 17280',-1,128,65535,127,131071,0,3,0,0,17280,1,0),(911,'Warlord\'s Resurgence',-1,1,65535,127,131071,0,3,0,0,10545,1,0),(912,'Warlord\'s Fury',-1,1,65535,127,131071,0,3,0,0,10546,1,0),(914,'Improved Shield Specialist',-1,1,65535,127,131071,0,3,0,0,10548,1,0),(915,'Unknown AA 17281',-1,128,65535,127,131071,0,3,0,0,17281,1,0),(917,'Hastened Grappling Strike',-1,65,65535,127,131071,0,3,0,0,10588,1,0),(918,'Furious Refrain',-1,128,65535,127,131071,0,3,0,0,10627,1,0),(919,'Unknown AA 17554',-1,32768,65535,127,131071,0,3,0,0,17554,1,0),(920,'Valorous Rage',-1,4,65535,127,131071,0,3,0,0,10711,1,0),(921,'Hastened Group Guardian of the Forest',-1,8,65535,127,131071,0,3,0,0,10714,1,0),(922,'Hastened Outrider\'s Attack',-1,8,65535,127,131071,0,3,0,0,10719,1,0),(923,'Hastened Protection of the Spirit Wolf',-1,8,65535,127,131071,0,3,0,0,10722,1,0),(924,'Hastened Imbued Ferocity',-1,8,65535,127,131071,0,3,0,0,10727,1,0),(925,'Hastened Harmonious Arrow',-1,8,65535,127,131071,0,3,0,0,10730,1,0),(926,'Hastened Entrap',-1,8,65535,127,131071,0,3,0,0,10733,1,0),(927,'Poison Arrows',-1,8,65535,127,131071,0,3,0,0,10736,1,0),(928,'Merciless Blade',-1,1,65535,127,131071,0,3,0,0,14026,1,0),(929,'Combatant\'s Pact',-1,1,65535,127,131071,0,3,0,0,14029,1,0),(930,'Warlord\'s Resolve',-1,1,65535,127,131071,0,3,0,0,14032,1,0),(931,'Hastened Hate\'s Attraction',-1,16,65535,127,131071,0,3,0,0,12582,1,0),(932,'Unknown AA 17289',-1,2,65535,127,131071,0,3,0,0,17289,1,0),(933,'Improved Death Peace',-1,1040,65535,127,131071,0,3,0,0,12635,1,0),(934,'Unknown AA 17307',-1,2,65535,127,131071,0,3,0,0,17307,1,0),(935,'Blessing of Ro',-1,32,65535,127,131071,0,3,0,0,10789,1,0),(936,'Extended Wild Growth',-1,544,65535,127,131071,0,3,0,0,10792,1,0),(937,'Unknown AA 17317',-1,512,65535,127,131071,0,3,0,0,17317,1,0),(938,'Eyes Wide Open',-1,65535,65535,127,131071,0,1,0,0,12636,1,0),(939,'Communion of the Cheetah',-1,32,65535,127,131071,0,3,0,0,12638,1,0),(940,'Hastened Song of Stone',-1,128,65535,127,131071,0,3,0,0,6870,1,0),(941,'Flurry',-1,128,65535,127,131071,0,3,0,0,6873,1,0),(942,'Destructive Cascade',-1,128,65535,127,131071,0,3,0,0,6876,1,0),(943,'Total Domination',-1,128,65535,127,131071,0,3,0,0,6879,1,0),(944,'Enhanced Forgetfulness',-1,128,65535,127,131071,0,3,0,0,6882,1,0),(945,'Infusion of Thunder',-1,64,65535,127,131071,0,3,0,0,10346,1,0),(946,'Hastened Warlord\'s Bravery',-1,1,65535,127,131071,0,3,0,0,14037,1,0),(947,'Hastened Warlord\'s Tenacity',-1,1,65535,127,131071,0,3,0,0,14040,1,0),(948,'Unknown AA 17328',-1,512,65535,127,131071,0,3,0,0,17328,1,0),(949,'Unknown AA 17329',-1,512,65535,127,131071,0,3,0,0,17329,1,0),(950,'Unknown AA 17336',-1,512,65535,127,131071,0,3,0,0,17336,1,0),(951,'Unknown AA 17339',-1,544,65535,127,131071,0,3,0,0,17339,1,0),(952,'Unknown AA 17342',-1,512,65535,127,131071,0,3,0,0,17342,1,0),(953,'Unknown AA 17344',-1,32,65535,127,131071,0,3,0,0,17344,1,0),(954,'Unknown AA 17347',-1,32,65535,127,131071,0,3,0,0,17347,1,0),(955,'Unknown AA 17357',-1,514,65535,127,131071,0,2,0,0,17357,1,0),(956,'Unknown AA 17361',-1,2080,65535,127,131071,0,3,0,0,17361,1,0),(957,'Unknown AA 17364',-1,32,65535,127,131071,0,3,0,0,17364,1,0),(958,'Unknown AA 17370',-1,32,65535,127,131071,0,3,0,0,17370,1,0),(959,'Unknown AA 17372',-1,32,65535,127,131071,0,3,0,0,17372,1,0),(960,'Stomping Leap',-1,32769,65535,127,131071,0,3,0,0,6930,1,0),(961,'Juggernaut Surge',-1,32768,65535,127,131071,0,3,0,0,6931,1,0),(962,'Distraction Attack',-1,32768,65535,127,131071,0,3,0,0,6932,1,0),(963,'Hastened Savage Spirit',-1,32768,65535,127,131071,0,3,0,0,6935,1,0),(964,'Dying Blow',-1,32768,65535,127,131071,0,3,0,0,6938,1,0),(965,'Hastened Projection of Fury',-1,1,65535,127,131071,0,3,0,0,10519,1,0),(966,'Unknown AA 17373',-1,16384,65535,127,131071,0,3,0,0,17373,1,0),(967,'Blade Guardian',-1,1,65535,127,131071,0,3,0,0,13444,1,0),(968,'Unknown AA 17375',-1,16384,65535,127,131071,0,3,0,0,17375,1,0),(969,'Unknown AA 17378',-1,15360,65535,127,131071,0,2,0,0,17378,1,0),(970,'Unknown AA 17378',-1,546,65535,127,131071,0,2,0,0,17379,1,0),(971,'Unknown AA 17378',-1,16384,65535,127,131071,0,2,0,0,17380,1,0),(972,'Unknown AA 17384',-1,16384,65535,127,131071,0,3,0,0,17384,1,0),(974,'Unknown AA 17409',-1,256,65535,127,131071,0,3,0,0,17409,1,0),(975,'Unknown AA 17414',-1,256,65535,127,131071,0,3,0,0,17414,1,0),(976,'Unknown AA 17418',-1,32768,65535,127,131071,0,3,0,0,17418,1,0),(977,'Unknown AA 17558',-1,1024,65535,127,131071,0,5,0,0,17558,1,0),(978,'Unknown AA 17428',-1,32768,65535,127,131071,0,3,0,0,17428,1,0),(979,'Unknown AA 17436',-1,32768,65535,127,131071,0,3,0,0,17436,1,0),(980,'Natural Invisibility',-1,16384,65535,127,131071,0,3,0,0,6970,1,0),(981,'Attack of the Warders',-1,16384,65535,127,131071,0,3,0,0,6971,1,0),(982,'Hastened Feral Attacks',-1,16384,65535,127,131071,0,3,0,0,6974,1,0),(983,'Hastened Focused Paragon',-1,16384,65535,127,131071,0,3,0,0,6977,1,0),(984,'Hastened Paragon',-1,16384,65535,127,131071,0,3,0,0,6980,1,0),(985,'Group Bestial Alignment',-1,16384,65535,127,131071,0,3,0,0,6983,1,0),(986,'Bite of the Asp',-1,16384,65535,127,131071,0,3,0,0,6984,1,0),(987,'Raven\'s Claw',-1,16384,65535,127,131071,0,3,0,0,6985,1,0),(988,'Gorilla Smash',-1,16384,65535,127,131071,0,3,0,0,6986,1,0),(989,'Stonefoot',-1,64,65535,127,131071,0,3,0,0,10340,1,0),(990,'Hastened Stunning Kick',-1,64,65535,127,131071,0,3,0,0,10343,1,0),(991,'Quickened Turn Undead',-1,2,65535,127,131071,0,3,0,0,10470,1,0),(992,'Tranquil Blessings',-1,30254,65535,127,131071,0,3,0,0,3676,1,0),(993,'Righteous Zeal',-1,2,65535,127,131071,0,3,0,0,6082,1,0),(994,'Hastened Divine Retribution',-1,2,65535,127,131071,0,3,0,0,6088,1,0),(995,'Intrinsic Efficiency',-1,15386,65535,127,131071,0,2,0,0,6112,1,0),(996,'Powerful Elixirs',-1,2,65535,127,131071,0,3,0,0,6113,1,0),(997,'Celestial Rapidity',-1,2,65535,127,131071,0,3,0,0,6534,1,0),(998,'Hastened Celestial Regeneration',-1,2,65535,127,131071,0,3,0,0,2400,1,0),(999,'Improved Burst of Life',-1,2,65535,127,131071,0,3,0,0,7765,1,0),(1000,'Unknown AA 17439',-1,32768,65535,127,131071,0,3,0,0,17439,1,0),(1001,'Unknown AA 17445',-1,32768,65535,127,131071,0,3,0,0,17445,1,0),(1002,'Unknown AA 17448',-1,32768,65535,127,131071,0,3,0,0,17448,1,0),(1003,'Unknown AA 10478',-1,8,65535,127,131071,0,3,0,0,10478,1,0),(1004,'Unknown AA 17492',-1,2048,65535,127,131071,0,3,0,0,17492,1,0),(1005,'Unknown AA 17495',-1,2048,65535,127,131071,0,3,0,0,17495,1,0),(1006,'Unknown AA 17515',-1,4096,65535,127,131071,0,3,0,0,17515,1,0),(1007,'Unknown AA 17517',-1,5120,65535,127,131071,0,3,0,0,17517,1,0),(1008,'Unknown AA 17522',-1,1024,65535,127,131071,0,3,0,0,17522,1,0),(1009,'Unknown AA 17533',-1,1024,65535,127,131071,0,3,0,0,17533,1,0),(1011,'Neshika\'s Blink',-1,64,65535,127,131071,0,3,0,0,7869,1,0),(1012,'Five Point Palm',-1,64,65535,127,131071,0,3,0,0,7875,1,0),(1013,'War Cry of the Braxi',-1,32768,65535,127,131071,0,3,0,0,13872,1,0),(1014,'Unknown AA 17538',-1,1024,65535,127,131071,0,3,0,0,17538,1,0),(1015,'Unknown AA 17547',-1,8192,65535,127,131071,0,3,0,0,17547,1,0),(1016,'Unknown AA 17549',-1,8192,65535,127,131071,0,3,0,0,17549,1,0),(1017,'Unknown AA 17238',-1,4,65535,127,131071,0,3,0,0,17238,1,0),(1018,'Unknown AA 17553',-1,8192,65535,127,131071,0,3,0,0,17553,1,0),(1019,'Unknown AA 17248',-1,4,65535,127,131071,0,3,0,0,17248,1,0),(1020,'Hastened Companion\'s Blessing',-1,30224,65535,127,131071,0,2,0,0,12478,1,0),(1021,'Unknown AA 17215',-1,1,65535,127,131071,0,3,0,0,17215,1,0),(1022,'Destructive Fury',-1,16540,65535,127,131071,0,2,0,0,6636,1,0),(1023,'Restoration of Life',-1,4,65535,127,131071,0,3,0,0,14010,1,0),(1024,'Hastened Leap of Faith',-1,4,65535,127,131071,0,3,0,0,14085,1,0),(1025,'Hastened Beacon of the Righteous',-1,4,65535,127,131071,0,3,0,0,14011,1,0),(1026,'Unknown AA 17561',-1,1024,65535,127,131071,0,5,0,0,17561,1,0),(1027,'Unknown AA 17564',-1,1024,65535,127,131071,0,5,0,0,17564,1,0),(1028,'Unknown AA 17567',-1,1024,65535,127,131071,0,5,0,0,17567,1,0),(1029,'Unknown AA 17570',-1,1024,65535,127,131071,0,5,0,0,17570,1,0),(1030,'Unknown AA 17573',-1,1024,65535,127,131071,0,5,0,0,17573,1,0),(1031,'Unknown AA 17576',-1,2048,65535,127,131071,0,5,0,0,17576,1,0),(1032,'Unknown AA 17579',-1,2048,65535,127,131071,0,5,0,0,17579,1,0),(1033,'Unknown AA 17582',-1,2048,65535,127,131071,0,5,0,0,17582,1,0),(1034,'Unknown AA 17585',-1,2048,65535,127,131071,0,5,0,0,17585,1,0),(1035,'Unknown AA 17588',-1,2048,65535,127,131071,0,5,0,0,17588,1,0),(1036,'Unknown AA 17591',-1,2048,65535,127,131071,0,5,0,0,17591,1,0),(1037,'Unknown AA 17594',-1,2048,65535,127,131071,0,5,0,0,17594,1,0),(1038,'Unknown AA 17597',-1,4096,65535,127,131071,0,5,0,0,17597,1,0),(1039,'Unknown AA 17600',-1,4096,65535,127,131071,0,5,0,0,17600,1,0),(1040,'Theft of Essence',-1,4096,65535,127,131071,0,3,0,0,7900,1,0),(1041,'Malosinete',-1,4608,65535,127,131071,0,3,0,0,7903,1,0),(1042,'Unknown AA 17603',-1,4096,65535,127,131071,0,5,0,0,17603,1,0),(1043,'Unknown AA 17606',-1,4096,65535,127,131071,0,5,0,0,17606,1,0),(1044,'Unknown AA 17609',-1,4096,65535,127,131071,0,5,0,0,17609,1,0),(1045,'Unknown AA 17612',-1,4096,65535,127,131071,0,5,0,0,17612,1,0),(1046,'Unknown AA 17615',-1,4096,65535,127,131071,0,5,0,0,17615,1,0),(1047,'Unknown AA 17618',-1,8192,65535,127,131071,0,5,0,0,17618,1,0),(1048,'Unknown AA 17621',-1,8192,65535,127,131071,0,5,0,0,17621,1,0),(1049,'Unknown AA 17624',-1,8192,65535,127,131071,0,5,0,0,17624,1,0),(1050,'Unknown AA 17627',-1,8192,65535,127,131071,0,5,0,0,17627,1,0),(1051,'Unknown AA 17630',-1,8192,65535,127,131071,0,5,0,0,17630,1,0),(1052,'Unknown AA 17633',-1,8192,65535,127,131071,0,5,0,0,17633,1,0),(1053,'Unknown AA 10481',-1,1024,65535,127,131071,0,3,0,0,10481,1,0),(1054,'Unknown AA 17639',-1,1,65535,127,131071,0,3,0,0,17639,1,0),(1060,'Hastened Turn Undead',-1,2,65535,127,131071,0,3,0,0,7940,1,0),(1061,'Cascading Divine Aura',-1,2,65535,127,131071,0,3,0,0,7943,1,0),(1062,'Group Purify Soul',-1,2,65535,127,131071,0,3,0,0,7944,1,0),(1063,'Hastened Renewal',-1,2,65535,127,131071,0,3,0,0,7945,1,0),(1064,'Sanctified Blessing',-1,2,65535,127,131071,0,3,0,0,7948,1,0),(1065,'Focused Celestial Regeneration',-1,2,65535,127,131071,0,3,0,0,7951,1,0),(1090,'Mastery of Nature',-1,32,65535,127,131071,0,3,0,0,7980,1,0),(1091,'Hastened Nature\'s Guardian',-1,32,65535,127,131071,0,3,0,0,7983,1,0),(1092,'Spirit of the Black Wolf',-1,32,65535,127,131071,0,3,0,0,7986,1,0),(1093,'Hastened Lycan Soul',-1,32,65535,127,131071,0,3,0,0,7989,1,0),(1113,'Hastened Mass Group Buff',-1,30254,65535,127,131071,0,3,0,0,5010,1,0),(1115,'Mystical Shield',-1,65535,65535,127,131071,0,1,0,0,5045,1,0),(1120,'Self Stasis',-1,8192,65535,127,131071,0,3,0,0,8030,1,0),(1121,'Hastened Veil of Mindshadow',-1,8192,65535,127,131071,0,3,0,0,8031,1,0),(1122,'Phantasmal Opponent',-1,8192,65535,127,131071,0,3,0,0,8034,1,0),(1123,'Hastened Edict of Command',-1,8192,65535,127,131071,0,3,0,0,8035,1,0),(1124,'Fog of Memories',-1,8192,65535,127,131071,0,3,0,0,8038,1,0),(1125,'Bite of Tashani',-1,8192,65535,127,131071,0,3,0,0,8039,1,0),(1150,'Fury of Druzzil',-1,2048,65535,127,131071,0,3,0,0,8060,1,0),(1151,'Fury of Eci',-1,2048,65535,127,131071,0,3,0,0,8063,1,0),(1152,'Fury of Ro',-1,2048,65535,127,131071,0,3,0,0,8066,1,0),(1153,'Fortified Entanglement',-1,2048,65535,127,131071,0,3,0,0,8069,1,0),(1154,'Force of Will',-1,2048,65535,127,131071,0,3,0,0,8072,1,0),(1155,'Atol\'s Shackles',-1,2048,65535,127,131071,0,3,0,0,8075,1,0),(1156,'Hastened Manaburn',-1,2048,65535,127,131071,0,3,0,0,8076,1,0),(1157,'Hastened Call of Xuzl',-1,2048,65535,127,131071,0,3,0,0,8082,1,0),(1158,'Divine Steed',-1,4,65535,127,131071,0,3,0,0,1667,1,0),(1159,'Hastened Leap',-1,32769,65535,127,131071,0,3,0,0,11014,1,0),(1169,'Unknown AA 16336',-1,1024,65535,127,131071,0,3,0,0,16336,1,0),(1170,'Unknown AA 16339',-1,1024,65535,127,131071,0,3,0,0,16339,1,0),(1171,'Hastened Counterattack Discipline',-1,256,65535,127,131071,0,3,0,0,15502,1,0),(1173,'Hastened Onslaught',-1,256,65535,127,131071,0,3,0,0,15509,1,0),(1174,'Mrylokar\'s Rigor',-1,256,65535,127,131071,0,3,0,0,15512,1,0),(1175,'Absorbing Agent',-1,256,65535,127,131071,0,3,0,0,15515,1,0),(1176,'Improved Requiem of Time',-1,128,65535,127,131071,0,3,0,0,15516,1,0),(1177,'Quickened Requiem of Time',-1,128,65535,127,131071,0,3,0,0,15517,1,0),(1178,'Silent Displacement',-1,128,65535,127,131071,0,3,0,0,15521,1,0),(1200,'Companion\'s Alacrity',-1,30224,65535,127,131071,0,2,0,0,8190,1,0),(1201,'Improved Intimidation',-1,41408,65535,127,131071,0,2,0,1,8193,1,0),(1202,'Perfected Levitation',-1,31272,65535,127,131071,0,2,0,0,8194,1,0),(1203,'Hastened Fortify Companion',-1,30224,65535,127,131071,0,2,0,0,8195,1,0),(1204,'Empowered Ingenuity',-1,33089,65535,127,131071,0,2,0,0,8198,1,0),(1205,'Companion\'s Fury',-1,30224,65535,127,131071,0,2,0,0,8201,1,0),(1206,'Quickened Radiant Cure',-1,546,65535,127,131071,0,2,0,0,8204,1,0),(1207,'Quickened Radiant Cure',-1,4,65535,127,131071,0,2,0,0,8207,1,0),(1208,'Mental Stamina',-1,32446,65535,127,131071,0,2,0,0,8210,1,0),(1209,'Hardy Endurance',-1,33089,65535,127,131071,0,2,0,0,8215,1,0),(1210,'Group Perfected Invisibility',-1,14336,65535,127,131071,0,3,0,0,8220,1,0),(1211,'Focus of Arcanum',-1,15904,65535,127,131071,0,3,0,0,8221,1,0),(1212,'Group Perfected Invisibility to Undead',-1,1046,65535,127,131071,0,2,0,0,8222,1,0),(1214,'Cascade of Life',-1,546,65535,127,131071,0,2,0,0,8224,1,0),(1215,'Summon Companion',-1,30224,65535,127,131071,0,2,0,0,8227,1,0),(1216,'Mental Fortitude',-1,65535,65535,127,131071,0,1,0,0,8228,1,0),(1217,'Gate',-1,15906,65535,127,131071,0,2,0,0,8231,1,0),(1218,'Extended Ingenuity',-1,128,65535,127,131071,0,2,0,0,8040,1,0),(1219,'Armor of Wisdom',-1,1,65535,127,131071,0,2,0,0,8235,1,0),(1220,'Armor of Wisdom',-1,20,65535,127,131071,0,2,0,0,8240,1,0),(1221,'Armor of Wisdom',-1,202,65535,127,131071,0,2,0,0,8245,1,0),(1222,'Armor of Wisdom',-1,49920,65535,127,131071,0,2,0,0,8250,1,0),(1223,'Armor of Wisdom',-1,15392,65535,127,131071,0,2,0,0,8255,1,0),(1232,'Way of the Katori',-1,64,65535,127,131071,0,3,0,0,15429,1,0),(1233,'Harmony of Battle',-1,64,65535,127,131071,0,3,0,0,15432,1,0),(1234,'Hastened Ironfist',-1,64,65535,127,131071,0,3,0,0,15438,1,0),(1235,'Two-Finger Wasp Touch',-1,64,65535,127,131071,0,3,0,0,15447,1,0),(1236,'Thunderfoot',-1,64,65535,127,131071,0,3,0,0,15444,1,0),(1237,'Extended Bloodlust',-1,16384,65535,127,131071,0,3,0,0,15414,1,0),(1239,'Consumption of Spirit',-1,16384,65535,127,131071,0,3,0,0,15423,1,0),(1240,'Frenzied Swipes',-1,16384,65535,127,131071,0,3,0,0,15424,1,0),(1242,'Hastened Synergy',-1,64,65535,127,131071,0,3,0,0,15450,1,0),(1243,'Hastened Crane Stance',-1,64,65535,127,131071,0,3,0,0,15453,1,0),(1244,'Hastened Eye Gouge',-1,64,65535,127,131071,0,3,0,0,15456,1,0),(1245,'Troubadour\'s Slashing Mastery',-1,128,65535,127,131071,0,3,0,0,15540,1,0),(1246,'Troubadour\'s Blunt Mastery',-1,128,65535,127,131071,0,3,0,0,15543,1,0),(1247,'Troubadour\'s Piercing Mastery',-1,128,65535,127,131071,0,3,0,0,15546,1,0),(1248,'Hastened Lure of the Siren\'s Song',-1,128,65535,127,131071,0,3,0,0,15549,1,0),(1249,'Frenzied Axe of Rallos',-1,32768,65535,127,131071,0,3,0,0,15555,1,0),(1250,'Juggernaut\'s Mastery of Throwing',-1,32768,65535,127,131071,0,3,0,0,15564,1,0),(1251,'Furious Rampage',-1,32768,65535,127,131071,0,3,0,0,15567,1,0),(1252,'Battle Stomp',-1,32768,65535,127,131071,0,3,0,0,15569,1,0),(1253,'Communion of Blood',-1,32768,65535,127,131071,0,3,0,0,15570,1,0),(1254,'Hastened Dying Grasp',-1,1024,65535,127,131071,0,3,0,0,15571,1,0),(1255,'Rest the Dead',-1,1040,65535,127,131071,0,3,0,0,15574,1,0),(1256,'Extended Encroaching Darkness',-1,1040,65535,127,131071,0,3,0,0,15579,1,0),(1257,'Hand of Death',-1,1024,65535,127,131071,0,3,0,0,15582,1,0),(1258,'Quickened Levant',-1,1024,65535,127,131071,0,3,0,0,15591,1,0),(1259,'Cascade of Decay',-1,1024,65535,127,131071,0,3,0,0,15594,1,0),(1261,'Hastened Fury of the Gods',-1,2048,65535,127,131071,0,3,0,0,15598,1,0),(1262,'Lower Element',-1,2048,65535,127,131071,0,3,0,0,15601,1,0),(1263,'Destructive Adept',-1,2048,65535,127,131071,0,3,0,0,15602,1,0),(1264,'Arcane Fusion',-1,2048,65535,127,131071,0,3,0,0,15609,1,0),(1265,'Arcane Destruction',-1,2048,65535,127,131071,0,3,0,0,15611,1,0),(1266,'Force of Flame',-1,2048,65535,127,131071,0,3,0,0,15612,1,0),(1267,'Force of Ice',-1,2048,65535,127,131071,0,3,0,0,15615,1,0),(1269,'Sha\'s Reprisal',-1,16384,65535,127,131071,0,3,0,0,15425,1,0),(1270,'Crippling Spirit',-1,512,65535,127,131071,0,3,0,0,15377,1,0),(1271,'Quick Damage',-1,1024,65535,127,131071,0,3,0,0,15622,1,0),(1272,'Assassin\'s Wrath',-1,256,65535,127,131071,0,3,0,0,15625,1,0),(1273,'Hastened Swiftblade',-1,256,65535,127,131071,0,3,0,0,15634,1,0),(1274,'Improved Explosion of Spite',-1,16,65535,127,131071,0,3,0,0,15639,1,0),(1275,'Improved Explosion of Hatred',-1,16,65535,127,131071,0,3,0,0,15640,1,0),(1277,'Soul Touch',-1,16,65535,127,131071,0,3,0,0,15642,1,0),(1278,'Soul Flay',-1,16,65535,127,131071,0,3,0,0,15643,1,0),(1279,'Ragged Bite of Agony',-1,16,65535,127,131071,0,3,0,0,15646,1,0),(1281,'Everburn',-1,32768,65535,127,131071,0,3,0,0,15648,1,0),(1282,'Marr\'s Gift',-1,4,65535,127,131071,0,3,0,0,15619,1,0),(1300,'Fundament of Intellect',-1,2048,65535,127,131071,0,3,0,0,9100,1,0),(1301,'Fundament of Intellect',-1,1024,65535,127,131071,0,3,0,0,9109,1,0),(1302,'Fundament of Intellect',-1,4096,65535,127,131071,0,3,0,0,9118,1,0),(1303,'Fundament of Intellect',-1,8192,65535,127,131071,0,3,0,0,9127,1,0),(1304,'Fundament of Wisdom',-1,2,65535,127,131071,0,3,0,0,9136,1,0),(1305,'Fundament of Wisdom',-1,32,65535,127,131071,0,3,0,0,9145,1,0),(1306,'Fundament of Wisdom',-1,512,65535,127,131071,0,3,0,0,9154,1,0),(1307,'Fundament of Power',-1,8,65535,127,131071,0,3,0,0,9163,1,0),(1308,'Fundament of Power',-1,16,65535,127,131071,0,3,0,0,9172,1,0),(1309,'Fundament of Power',-1,4,65535,127,131071,0,3,0,0,9181,1,0),(1310,'Fundament of Power',-1,128,65535,127,131071,0,3,0,0,9190,1,0),(1311,'Fundament of Power',-1,16384,65535,127,131071,0,3,0,0,9199,1,0),(1312,'Fundament of Combat',-1,1,65535,127,131071,0,3,0,0,9208,1,0),(1313,'Fundament of Combat',-1,64,65535,127,131071,0,3,0,0,9217,1,0),(1314,'Fundament of Combat',-1,32768,65535,127,131071,0,3,0,0,9226,1,0),(1315,'Fundament of Combat',-1,256,65535,127,131071,0,3,0,0,9235,1,0),(1350,'Fundament: First Spire of Arcanum',-1,2048,65535,127,131071,0,3,0,0,9300,1,0),(1351,'Fundament: Second Spire of Arcanum',-1,2048,65535,127,131071,0,3,0,0,9303,1,0),(1352,'Fundament: Third Spire of Arcanum',-1,2048,65535,127,131071,0,3,0,0,9306,1,0),(1360,'Fundament: First Spire of the Sensei',-1,64,65535,127,131071,0,3,0,0,9309,1,0),(1361,'Fundament: Second Spire of the Sensei',-1,64,65535,127,131071,0,3,0,0,9312,1,0),(1362,'Fundament: Third Spire of the Sensei',-1,64,65535,127,131071,0,3,0,0,9315,1,0),(1370,'Fundament: First Spire of the Elements',-1,4096,65535,127,131071,0,3,0,0,9318,1,0),(1371,'Fundament: Second Spire of the Elements',-1,4096,65535,127,131071,0,3,0,0,9321,1,0),(1372,'Fundament: Third Spire of the Elements',-1,4096,65535,127,131071,0,3,0,0,9324,1,0),(1380,'Fundament: First Spire of Enchantment',-1,8192,65535,127,131071,0,3,0,0,9327,1,0),(1381,'Fundament: Second Spire of Enchantment',-1,8192,65535,127,131071,0,3,0,0,9330,1,0),(1382,'Fundament: Third Spire of Enchantment',-1,8192,65535,127,131071,0,3,0,0,9333,1,0),(1390,'Fundament: First Spire of Necromancy',-1,1024,65535,127,131071,0,3,0,0,9336,1,0),(1391,'Fundament: Second Spire of Necromancy',-1,1024,65535,127,131071,0,3,0,0,9339,1,0),(1392,'Fundament: Third Spire of Necromancy',-1,1024,65535,127,131071,0,3,0,0,9342,1,0),(1400,'Fundament: First Spire of the Warlord',-1,1,65535,127,131071,0,3,0,0,9345,1,0),(1401,'Fundament: Second Spire of the Warlord',-1,1,65535,127,131071,0,3,0,0,9348,1,0),(1402,'Fundament: Third Spire of the Warlord',-1,1,65535,127,131071,0,3,0,0,9351,1,0),(1403,'Sturdy Companion',-1,30224,65535,127,131071,0,3,0,0,9503,1,0),(1404,'Extended Swarm',-1,32306,65535,127,131071,0,3,0,0,9506,1,0),(1405,'Twincast',-1,15906,65535,127,131071,0,3,0,0,9509,1,0),(1406,'Staff Block',-1,64,65535,127,131071,0,3,0,0,9512,1,0),(1410,'Fundament: First Spire of the Rake',-1,256,65535,127,131071,0,3,0,0,9354,1,0),(1411,'Fundament: Second Spire of the Rake',-1,256,65535,127,131071,0,3,0,0,9357,1,0),(1412,'Fundament: Third Spire of the Rake',-1,256,65535,127,131071,0,3,0,0,9360,1,0),(1420,'Fundament: First Spire of the Minstrels',-1,128,65535,127,131071,0,3,0,0,9363,1,0),(1421,'Fundament: Second Spire of the Minstrels',-1,128,65535,127,131071,0,3,0,0,9366,1,0),(1422,'Fundament: Third Spire of the Minstrels',-1,128,65535,127,131071,0,3,0,0,9369,1,0),(1430,'Fundament: First Spire of the Savage Lord',-1,16384,65535,127,131071,0,3,0,0,9372,1,0),(1431,'Fundament: Second Spire of the Savage Lord',-1,16384,65535,127,131071,0,3,0,0,9375,1,0),(1432,'Fundament: Third Spire of the Savage Lord',-1,16384,65535,127,131071,0,3,0,0,9378,1,0),(1433,'Extended Ingenuity',-1,33089,65535,127,131071,0,2,0,0,8232,1,0),(1440,'Fundament: First Spire of Holiness',-1,4,65535,127,131071,0,3,0,0,9381,1,0),(1441,'Fundament: Second Spire of Holiness',-1,4,65535,127,131071,0,3,0,0,9384,1,0),(1442,'Fundament: Third Spire of Holiness',-1,4,65535,127,131071,0,3,0,0,9387,1,0),(1450,'Fundament: First Spire of the Reavers',-1,16,65535,127,131071,0,3,0,0,9390,1,0),(1451,'Fundament: Second Spire of the Reavers',-1,16,65535,127,131071,0,3,0,0,9393,1,0),(1452,'Fundament: Third Spire of the Reavers',-1,16,65535,127,131071,0,3,0,0,9396,1,0),(1460,'Fundament: First Spire of the Pathfinders',-1,8,65535,127,131071,0,3,0,0,9399,1,0),(1461,'Fundament: Second Spire of the Pathfinders',-1,8,65535,127,131071,0,3,0,0,9402,1,0),(1462,'Fundament: Third Spire of the Pathfinders',-1,8,65535,127,131071,0,3,0,0,9405,1,0),(1470,'Fundament: First Spire of Divinity',-1,2,65535,127,131071,0,3,0,0,9408,1,0),(1471,'Fundament: Second Spire of Divinity',-1,2,65535,127,131071,0,3,0,0,9411,1,0),(1472,'Fundament: Third Spire of Divinity',-1,2,65535,127,131071,0,3,0,0,9414,1,0),(1480,'Fundament: First Spire of Nature',-1,32,65535,127,131071,0,3,0,0,9417,1,0),(1481,'Fundament: Second Spire of Nature',-1,32,65535,127,131071,0,3,0,0,9420,1,0),(1482,'Fundament: Third Spire of Nature',-1,32,65535,127,131071,0,3,0,0,9423,1,0),(1490,'Fundament: First Spire of Ancestors',-1,512,65535,127,131071,0,3,0,0,9426,1,0),(1491,'Fundament: Second Spire of Ancestors',-1,512,65535,127,131071,0,3,0,0,9429,1,0),(1492,'Fundament: Third Spire of Ancestors',-1,512,65535,127,131071,0,3,0,0,9432,1,0),(1500,'Fundament: First Spire of Savagery',-1,32768,65535,127,131071,0,3,0,0,9435,1,0),(1501,'Fundament: Second Spire of Savagery',-1,32768,65535,127,131071,0,3,0,0,9438,1,0),(1502,'Fundament: Third Spire of Savagery',-1,32768,65535,127,131071,0,3,0,0,9441,1,0),(1503,'Hallowed Steed',-1,4,65535,127,131071,0,3,0,0,13673,1,0),(1504,'Wicked Steed',-1,16,65535,127,131071,0,3,0,0,13674,1,0),(1505,'Unknown AA 16103',-1,1024,65535,127,131071,0,3,0,0,16103,1,0),(1580,'Divine Companion Aura',-1,30224,65535,127,131071,0,2,0,0,5809,1,0),(1662,'Spell Casting Mastery',-1,16412,65535,127,131071,0,2,0,0,1216,1,0),(1663,'Gift of Mana',-1,16412,65535,127,131071,0,2,0,0,1219,1,0),(1664,'Twinproc',-1,50175,65535,127,131071,0,3,0,0,12416,1,0),(1665,'Tactical Mastery',-1,16596,65535,127,131071,0,3,0,0,12419,1,0),(1666,'Group Perfected Levitation',-1,31272,65535,127,131071,0,2,0,0,12422,1,0),(1667,'Quickened Encroaching Darkness',-1,1040,65535,127,131071,0,2,0,0,6026,1,0),(1668,'Acute Focus of Arcanum',-1,15904,65535,127,131071,0,3,0,0,8260,1,0),(1669,'Flurry',-1,20,65535,127,131071,0,3,0,0,5806,1,0),(1680,'Hastened Flash of Anger',-1,1,65535,127,131071,0,3,0,0,13905,1,0),(1681,'Hastened Bazu Roar',-1,1,65535,127,131071,0,3,0,0,13908,1,0),(1682,'Hastened Scowl',-1,1,65535,127,131071,0,3,0,0,13911,1,0),(1683,'Hastened Mark of the Mage Hunter',-1,1,65535,127,131071,0,3,0,0,13917,1,0),(1684,'Knowledge of Alaran Culture',2,65535,65535,127,131071,0,4,0,0,14017,1,0),(1685,'Knowledge of Alaran Culture - Advanced',2,65535,65535,127,131071,0,4,0,0,14018,1,0),(1686,'Brace For Impact',-1,1,65535,127,131071,0,3,0,0,14019,1,0),(1687,'Summon Tome of the Hero\'s Journey',2,65535,65535,127,131071,0,4,0,1,14371,1,0),(1800,'Enchant Planar Alloy',-1,8192,65535,127,131071,0,3,0,1,14373,1,0),(1801,'Mass Enchant Planar Alloy',-1,8192,65535,127,131071,0,3,0,1,14374,1,0),(2000,'Armor of Experience',5,65535,65535,127,131071,0,4,0,1,4700,1,0),(2001,'Sneering Grin',-1,1,65535,127,131071,0,3,0,0,15096,1,0),(2002,'Warlord\'s Grasp',-1,1,65535,127,131071,0,3,0,0,15099,1,0),(2003,'Hastened Press the Attack',-1,1,65535,127,131071,0,3,0,0,15100,1,0),(2004,'Hastened Rage of Rallos Zek',-1,1,65535,127,131071,0,3,0,0,15105,1,0),(2005,'Hastened Unbroken Attention',-1,1,65535,127,131071,0,3,0,0,15108,1,0),(2006,'Extended Resplendant Glory',-1,1,65535,127,131071,0,3,0,0,15113,1,0),(2007,'Wars Sheol\'s Heroic Blade',-1,1,65535,127,131071,0,3,0,0,15119,1,0),(2008,'Hastened Vehement Rage',-1,1,65535,127,131071,0,3,0,0,15120,1,0),(2009,'Hastened Barbed Tongue',-1,1,65535,127,131071,0,3,0,0,15123,1,0),(2010,'Hastened Shield Topple',-1,1,65535,127,131071,0,3,0,0,15126,1,0),(2011,'Imperator\'s Command',-1,1,65535,127,131071,0,3,0,0,15129,1,0),(2012,'Imperator\'s Charge',-1,1,65535,127,131071,0,3,0,0,15130,1,0),(2013,'Imperator\'s Precision',-1,1,65535,127,131071,0,3,0,0,15131,1,0),(2014,'Hastened Divine Call',-1,4,65535,127,131071,0,3,0,0,15132,1,0),(2015,'Extended Divine Call',-1,4,65535,127,131071,0,3,0,0,15135,1,0),(2016,'Heroic Leap',-1,4,65535,127,131071,0,3,0,0,15136,1,0),(2018,'Helix of the Undying',-1,20,65535,127,131071,0,3,0,0,15146,1,0),(2019,'Group Armor of the Inquisitor',-1,4,65535,127,131071,0,3,0,0,15147,1,0),(2020,'Quickened Demand For Honor',-1,4,65535,127,131071,0,3,0,0,15150,1,0),(2021,'Extended Sanctification',-1,4,65535,127,131071,0,3,0,0,15153,1,0),(2022,'Extended Speed of the Savior',-1,4,65535,127,131071,0,3,0,0,15154,1,0),(2023,'Extended Preservation of Marr',-1,4,65535,127,131071,0,3,0,0,15155,1,0),(2024,'Extended Shield of Brilliance',-1,4,65535,127,131071,0,3,0,0,15158,1,0),(2025,'Extended Blessing of the Faithful',-1,4,65535,127,131071,0,3,0,0,15159,1,0),(2026,'Hastened Speed of the Savior',-1,4,65535,127,131071,0,3,0,0,15162,1,0),(2028,'Hastened Shield of Brilliance',-1,4,65535,127,131071,0,3,0,0,15168,1,0),(2031,'Purity of Death',-1,16,65535,127,131071,0,3,0,0,15177,1,0),(2032,'Quickened Scourge Skin',-1,16,65535,127,131071,0,3,0,0,15179,1,0),(2034,'Gift of the Quick Spear',-1,16,65535,127,131071,0,3,0,0,15193,1,0),(2035,'Extended Provocation for Power',-1,16,65535,127,131071,0,3,0,0,15194,1,0),(2036,'Quickened Auspice of the Hunter',-1,8,65535,127,131071,0,3,0,0,15253,1,0),(2037,'Chameleon\'s Gift',-1,8,65535,127,131071,0,3,0,0,15304,1,0),(2040,'Hastened Enraging Kicks',-1,8,65535,127,131071,0,3,0,0,15283,1,0),(2041,'Close Combat Mastery',-1,8,65535,127,131071,0,3,0,0,15288,1,0),(2042,'Quickened Cover Tracks',-1,8,65535,127,131071,0,3,0,0,15295,1,0),(2045,'Shield of Reverence',-1,2,65535,127,131071,0,3,0,0,15338,1,0),(2046,'Extended Healing Frenzy',-1,2,65535,127,131071,0,3,0,0,15342,1,0),(2047,'Call of the Herald',-1,2,65535,127,131071,0,3,0,0,15343,1,0),(2048,'Covenant of Spirit',-1,544,65535,127,131071,0,3,0,0,15356,1,0),(2049,'Talisman of Celerity',-1,512,65535,127,131071,0,3,0,0,15357,1,0),(2050,'Extended Spiritual Blessing',-1,512,65535,127,131071,0,3,0,0,15358,1,0),(2051,'Rejuvenation of Spirit',-1,544,65535,127,131071,0,3,0,0,15362,1,0),(2053,'Hastened Turgur\'s Swarm',-1,512,65535,127,131071,0,3,0,0,15371,1,0),(2054,'Shielding of Spirits',-1,16930,65535,127,131071,0,2,0,0,15374,1,0),(2055,'Hastened Lunar Healing',-1,32,65535,127,131071,0,3,0,0,15383,1,0),(2056,'Quickened Blessing of Ro',-1,32,65535,127,131071,0,3,0,0,15389,1,0),(2057,'Hastened Wall of Wind',-1,32,65535,127,131071,0,3,0,0,15403,1,0),(2059,'Quickened Focused Paragon of Spirit',-1,16384,65535,127,131071,0,3,0,0,15406,1,0),(2060,'Elemental Ward',-1,4096,65535,127,131071,0,3,0,0,15200,1,0),(2061,'Cloak of Shadows',-1,4096,65535,127,131071,0,3,0,0,15203,1,0),(2062,'Hastened Elemental Union',-1,4096,65535,127,131071,0,3,0,0,15204,1,0),(2063,'Hastened Virulent Talon',-1,4096,65535,127,131071,0,3,0,0,15207,1,0),(2064,'Wind of Malosinete',-1,4608,65535,127,131071,0,3,0,0,15210,1,0),(2065,'Mana Reserve',-1,4096,65535,127,131071,0,3,0,0,15213,1,0),(2066,'Second Wind Ward',-1,4096,65535,127,131071,0,3,0,0,15214,1,0),(2076,'Steel Vengeance',-1,4096,65535,127,131071,0,3,0,0,15217,1,0),(2077,'Extended Vapor Core',-1,4096,65535,127,131071,0,3,0,0,15220,1,0),(2078,'Extended Stone Core',-1,4096,65535,127,131071,0,3,0,0,15223,1,0),(2079,'Extended Fire Core',-1,4096,65535,127,131071,0,3,0,0,15226,1,0),(2080,'Extended Ice Core',-1,4096,65535,127,131071,0,3,0,0,15229,1,0),(2081,'Flames of Power',-1,4096,65535,127,131071,0,3,0,0,15232,1,0),(2200,'Rune of Banishment',-1,8192,65535,127,131071,0,3,0,0,15475,1,0),(2201,'Hastened Glyph Spray',-1,8192,65535,127,131071,0,3,0,0,15478,1,0),(2202,'Illusions of Grandeur',-1,8192,65535,127,131071,0,3,0,0,15481,1,0),(2203,'Illusory Ally',-1,8192,65535,127,131071,0,3,0,0,15482,1,0),(2204,'Gracious Gift of Mana',-1,8192,65535,127,131071,0,3,0,0,15485,1,0),(2205,'Chromatic Haze',-1,8192,65535,127,131071,0,3,0,0,15486,1,0),(2206,'Blanket of Forgetfulness',-1,8192,65535,127,131071,0,3,0,0,15489,1,0),(2207,'Ethereal Manipulation',-1,8192,65535,127,131071,0,3,0,0,15490,1,0),(2208,'Quick Mezz',-1,8192,65535,127,131071,0,3,0,0,15493,1,0),(2209,'Reactive Rune',-1,8192,65535,127,131071,0,3,0,0,15496,1,0),(2234,'Cover Tracks',-1,8,65535,127,131071,0,3,0,0,10368,1,0),(2235,'Imbued Ferocity',-1,8,65535,127,131071,0,3,0,0,10387,1,0),(2709,'Perfected Dead Man Floating',-1,1024,65535,127,131071,0,3,0,0,13692,1,0),(2899,'Levant',-1,1024,65535,127,131071,0,3,0,0,10700,1,0),(3000,'Auroria Mastery',-1,8192,65535,127,131071,0,3,0,0,6987,1,0),(3202,'Pet Discipline',-1,8192,65535,127,131071,0,3,0,0,7733,1,0),(3203,'Enchant Palladium Trio',6,8192,65535,127,131071,0,3,0,1,7736,1,0),(3204,'Mass Enchant Palladium',6,8192,65535,127,131071,0,3,0,1,7737,1,0),(3205,'Greater Mass Enchant Palladium',6,8192,65535,127,131071,0,3,0,1,7738,1,0),(3206,'Enchant Dwerium',6,8192,65535,127,131071,0,3,0,1,7732,1,0),(3207,'Mass Enchant Dwerium',6,8192,65535,127,131071,0,3,0,1,7734,1,0),(3208,'Enchant Palladium',6,8192,65535,127,131071,0,3,0,1,7735,1,0),(3209,'Enchant Temporite',6,8192,65535,127,131071,0,3,0,1,7739,1,0),(3210,'Mass Enchant Temporite',6,8192,65535,127,131071,0,3,0,1,7740,1,0),(3211,'Nature\'s Reprieve',-1,8,65535,127,131071,0,3,0,0,10388,1,0),(3212,'Hastened Divine Intervention',-1,2,65535,127,131071,0,3,0,0,10358,1,0),(3213,'Projection of Fury',-1,1,65535,127,131071,0,3,0,0,10351,1,0),(3214,'Improved Atone',-1,2,65535,127,131071,0,3,0,0,10364,1,0),(3215,'Projection of Doom',-1,16,65535,127,131071,0,3,0,0,10352,1,0),(3216,'Projection of Piety',-1,4,65535,127,131071,0,3,0,0,10353,1,0),(3217,'Hastened Jolting Kicks',-1,8,65535,127,131071,0,3,0,0,12500,1,0),(3218,'Enchant Cosgrite',6,8192,65535,127,131071,0,3,0,1,7741,1,0),(3219,'Mass Enchant Cosgrite',6,8192,65535,127,131071,0,3,0,1,7742,1,0),(3500,'Blessing of Light',-1,4,65535,127,131071,0,3,0,0,10355,1,0),(3506,'Fierce Eye',-1,128,65535,127,131071,0,3,0,0,5717,1,0),(3511,'Punch Mastery',-1,64,65535,127,131071,0,3,0,0,6020,1,0),(3512,'Companion\'s Durability',-1,30224,65535,127,131071,0,2,0,0,6051,1,0),(3513,'Rake\'s Deadly Aim',-1,256,65535,127,131071,0,3,0,0,6322,1,0),(3514,'Rogue\'s Fury',-1,256,65535,127,131071,0,3,0,0,6325,1,0),(3515,'Envenomed Blades',-1,256,65535,127,131071,0,3,0,0,6328,1,0),(3516,'Companion of Necessity',-1,4096,65535,127,131071,0,3,0,0,6333,1,0),(3517,'Rake\'s Powerful Aim',-1,256,65535,127,131071,0,3,0,0,6334,1,0),(3518,'Hastened Cacophony',-1,128,65535,127,131071,0,3,0,0,6337,1,0),(3519,'Hastened Funeral Dirge',-1,128,65535,127,131071,0,3,0,0,6340,1,0),(3520,'Master\'s Hastened Combination',-1,64,65535,127,131071,0,3,0,0,6343,1,0),(3521,'Hastened Silent Casting',-1,546,65535,127,131071,0,2,0,0,6346,1,0),(3522,'Hastened Silent Casting',-1,15360,65535,127,131071,0,2,0,0,6349,1,0),(3525,'Precise Blow',-1,32768,65535,127,131071,0,3,0,0,5776,1,0),(3550,'Beguiler\'s Banishment',-1,8192,65535,127,131071,0,3,0,0,5849,1,0),(3551,'Beguiler\'s Directed Banishment',-1,8192,65535,127,131071,0,3,0,0,5870,1,0),(3600,'Rapid Defiance',1,1,65535,127,131071,0,3,0,1,6136,1,0),(3646,'Blast of Anger',-1,1,65535,127,131071,0,3,0,0,6135,1,0),(3676,'Gift of Life',-1,4,65535,127,131071,0,3,0,0,10354,1,0),(3701,'Dirge of the Sleepwalker',-1,128,65535,127,131071,0,3,0,0,6200,1,0),(3702,'Quick Time',-1,128,65535,127,131071,0,3,0,0,6201,1,0),(3703,'Steady Hands ',-1,128,65535,127,131071,0,3,0,0,6202,1,0),(3704,'Selo\'s Sonata',-1,128,65535,127,131071,0,3,0,0,6205,1,0),(3705,'Companion\'s Blessing ',-1,30224,65535,127,131071,0,2,0,0,6206,1,0),(3706,'Hastened Bestial Alignment ',-1,16384,65535,127,131071,0,3,0,0,6209,1,0),(3707,'Fortify Companion ',-1,30224,65535,127,131071,0,2,0,0,6212,1,0),(3708,'Burst of Power ',-1,20,65535,127,131071,0,2,0,0,6215,1,0),(3709,'Pact of the Wurine',-1,16384,65535,127,131071,0,3,0,0,6218,1,0),(3710,'Reckless Abandon ',-1,32768,65535,127,131071,0,3,0,0,6219,1,0),(3711,'Gift of Resurrection',-1,4,65535,127,131071,0,3,0,0,6222,1,0),(3713,'Hastened Call of the Wild ',-1,544,65535,127,131071,0,3,0,0,6228,1,0),(3714,'Protection of Direwood',-1,32,65535,127,131071,0,3,0,0,6232,1,0),(3716,'Clinging Root ',-1,8192,65535,127,131071,0,3,0,0,6236,1,0),(3718,'Critical Affliction',-1,8194,65535,127,131071,0,2,0,0,6240,1,0),(3720,'Mana Overburn ',-1,8192,65535,127,131071,0,3,0,0,6249,1,0),(3724,'Knight\'s Return Strike ',-1,20,65535,127,131071,0,3,0,0,6266,1,0),(3725,'Hunter\'s Return Kick ',-1,8,65535,127,131071,0,3,0,0,6269,1,0),(3726,'Hastened Ligament Slice ',-1,256,65535,127,131071,0,3,0,0,6272,1,0),(3727,'Knave\'s Return Strike',-1,256,65535,127,131071,0,3,0,0,6275,1,0),(3728,'Storm Strike',-1,32,65535,127,131071,0,3,0,0,6278,1,0),(3729,'Turgur\'s Swarm',-1,512,65535,127,131071,0,3,0,0,6281,1,0),(3730,'Silent Presence',-1,512,65535,127,131071,0,3,0,0,6282,1,0),(3731,'Infused by Rage ',-1,1,65535,127,131071,0,3,0,0,6283,1,0),(3732,'Gut Punch',-1,1,65535,127,131071,0,3,0,0,6286,1,0),(3733,'Warlord\'s Return Kick',-1,1,65535,127,131071,0,3,0,0,6287,1,0),(3734,'Arcomancy ',-1,2048,65535,127,131071,0,3,0,0,6290,1,0),(3800,'Blessing of Resurrection',-1,2,65535,127,131071,0,3,0,0,6299,1,0),(3801,'General Sturdiness',-1,65535,65535,127,131071,0,1,0,0,6119,1,0),(3802,'Shield Block',-1,392,65535,127,131071,0,2,0,0,6124,1,0),(3803,'Hastened Trueshot',-1,8,65535,127,131071,0,3,0,0,6355,1,0),(3804,'Outrider\'s Accuracy',-1,8,65535,127,131071,0,3,0,0,6370,1,0),(3805,'Hastened Mend',-1,64,65535,127,131071,0,3,0,0,4801,1,0),(3812,'Perfected Invisibility',-1,14336,65535,127,131071,0,3,0,0,7069,1,0),(3813,'Spell Casting Reinforcement',-1,7168,65535,127,131071,0,2,0,0,6257,1,0),(3815,'Destructive Cascade',-1,9776,65535,127,131071,0,3,0,0,6375,1,0),(3816,'Companion\'s Relocation',-1,30224,65535,127,131071,0,3,0,0,6379,1,0),(3817,'Focused Paragon of Spirits',-1,16384,65535,127,131071,0,3,0,0,6380,1,0),(3818,'Companion\'s Agility',-1,30224,65535,127,131071,0,3,0,0,6383,1,0),(3819,'Maestro\'s Concentration',-1,128,65535,127,131071,0,3,0,0,6386,1,0),(3820,'Blessing of Life',-1,4,65535,127,131071,0,3,0,0,6395,1,0),(3821,'Quickened Harvest of Druzzil',-1,2048,65535,127,131071,0,3,0,0,6503,1,0),(3822,'Chattering Bones',-1,16,65535,127,131071,0,3,0,0,6508,1,0),(3823,'Warlord\'s Deadly Aim',-1,1,65535,127,131071,0,3,0,0,6511,1,0),(3824,'Quickened Call of the Wild',-1,544,65535,127,131071,0,3,0,0,6514,1,0),(3826,'Force of Disruption',-1,4,65535,127,131071,0,3,0,0,5984,1,0),(3830,'Hastened Divine Avatar',-1,2,65535,127,131071,0,3,0,0,7100,1,0),(3831,'Hastened Purification',-1,4,65535,127,131071,0,3,0,0,7103,1,0),(3832,'Beastlords Feral Kick',-1,16384,65535,127,131071,0,3,0,0,7106,1,0),(3833,'Burst of Power ',-1,32841,65535,127,131071,0,2,0,0,6409,1,0),(3834,'Burst of Power ',-1,256,65535,127,131071,0,2,0,0,6419,1,0),(3835,'Shield Block',-1,15360,65535,127,131071,0,2,0,0,6428,1,0),(3836,'Holy Root',-1,2,65535,127,131071,0,3,0,0,6436,1,0),(3837,'Burst of Power ',-1,16512,65535,127,131071,0,2,0,0,6060,1,0),(3838,'Quickened Suspend Minion',-1,30224,65535,127,131071,0,3,0,0,6445,1,0),(3839,'Quickened Summon Axes',-1,32768,65535,127,131071,0,3,0,0,6452,1,0),(3840,'Recourse of Life',-1,2,65535,127,131071,0,3,0,0,6601,1,0),(3841,'Call Hither',-1,4096,65535,127,131071,0,3,0,0,6455,1,0),(3842,'Fortified Survival',-1,32,65535,127,131071,0,3,0,0,6458,1,0),(3843,'Fortified Intervention',-1,512,65535,127,131071,0,3,0,0,6461,1,0),(3865,'Planar Durability',-1,72,65535,127,131071,0,3,0,0,6422,1,0),(3890,'Hastened Force of Will',-1,2048,65535,127,131071,0,3,0,0,7822,1,0),(3891,'Hastened Burnout',-1,4096,65535,127,131071,0,3,0,0,7832,1,0),(3892,'Hastened Rumbling Servant',-1,4096,65535,127,131071,0,3,0,0,7828,1,0),(3893,'Extended Rumbling Servant',-1,4096,65535,127,131071,0,3,0,0,7827,1,0),(3899,'Furious Leap',-1,32769,65535,127,131071,0,3,0,0,6499,1,0),(4001,'Undaunted Fury',-1,32768,65535,127,131071,0,3,0,0,7407,1,0),(4002,'Frenzied Volley',-1,32768,65535,127,131071,0,3,0,0,7818,1,0),(4200,'Hastened Forceful Rejuvenation',-1,32318,65535,127,131071,0,2,0,0,12475,1,0),(4666,'Shield Specialist',-1,20,65535,127,131071,0,3,0,0,4666,1,0),(5000,'Glyph of Courage',7,65535,65535,127,131071,0,4,1,0,7000,1,0),(5002,'Glyph of Stored Life',7,65535,65535,127,131071,0,4,1,0,7002,1,0),(5003,'Glyph of Frantic Infusion',7,30224,65535,127,131071,0,4,1,0,7003,1,0),(5004,'Glyph of Angry Thoughts',7,65535,65535,127,131071,0,4,1,0,7004,1,0),(5005,'Foraging',8,65535,65535,127,131071,0,1,0,0,7062,1,0),(6000,'Harm Touch',9,16,65535,127,131071,0,3,0,0,7800,1,0),(6001,'Lay on Hands',9,4,65535,127,131071,0,3,0,0,7850,1,1),(6002,'Hunter\'s Attack Power',-1,8,65535,127,131071,0,3,0,0,6546,1,0),(6106,'Sustained Destruction',-1,2048,65535,127,131071,0,3,0,0,6106,1,0),(6302,'Hastened Reckless Abandon',-1,32768,65535,127,131071,0,3,0,0,6302,1,0),(6362,'Hastened Recklessness',-1,32768,65535,127,131071,0,3,0,0,6362,1,0),(6478,'Hastened Blessing of Resurrection',-1,2,65535,127,131071,0,3,0,0,6478,1,0),(6481,'Hastened Divine Resurrection',-1,2,65535,127,131071,0,3,0,0,6481,1,0),(6488,'Flurry of Life',-1,2,65535,127,131071,0,3,0,0,6488,1,0),(6489,'Hastened Holyforge',-1,4,65535,127,131071,0,3,0,0,6489,1,0),(6492,'Inquisitor\'s Judgement',-1,4,65535,127,131071,0,3,0,0,6492,1,0),(6988,'Extended Group Bestial Alignment',-1,16384,65535,127,131071,0,3,0,0,6988,1,0),(7000,'Voice of Thule',-1,16,65535,127,131071,0,3,0,0,6639,1,0),(7001,'Zan Fi\'s Whistle',-1,64,65535,127,131071,0,3,0,0,7872,1,0),(7002,'Summon Remains',-1,1024,65535,127,131071,0,3,0,0,9500,1,0),(7003,'Forceful Rejuvenation',-1,32318,65535,127,131071,0,2,0,0,9502,1,0),(7007,'Summon Remains',-1,16,65535,127,131071,0,3,0,0,9501,1,0),(7009,'Teleport Bind',-1,32,65535,127,131071,0,3,0,0,1419,1,0),(7016,'Glyph of the Master',7,65535,65535,127,131071,0,4,1,0,7016,1,0),(7017,'Glyph of Lost Secrets',7,32318,65535,127,131071,0,4,1,0,7017,1,0),(7018,'Glyph of Genari Might',7,65535,65535,127,131071,0,4,1,0,7018,1,0),(7019,'Glyph of the Cataclysm',7,65535,65535,127,131071,0,4,1,0,7019,1,0),(7025,'Group Shrink',-1,16384,65535,127,131071,0,3,0,0,7669,1,0),(7033,'Lasting Bravery',-1,1,65535,127,131071,0,3,0,0,7033,1,0),(7036,'Hastened Blast of Anger',-1,1,65535,127,131071,0,3,0,0,7036,1,0),(7050,'Call of the Hero',-1,4096,65535,127,131071,0,3,0,0,1017,1,0),(7060,'Precision of Axes',-1,32768,65535,127,131071,0,3,0,0,4809,1,0),(7070,'Hastened Distraction Attack',-1,32768,65535,127,131071,0,3,0,0,6941,1,0),(7105,'Deathly Pact',-1,1040,65535,127,131071,0,3,0,0,976,1,0),(7106,'Planar Durability',-1,16768,65535,127,131071,0,3,0,0,6467,1,0),(7107,'Hastened Getaway',-1,256,65535,127,131071,0,3,0,0,7005,1,0),(7108,'Divine Aura',-1,4,65535,127,131071,0,3,0,0,977,1,0),(7109,'Hastened Wrath of the Wild',-1,32,65535,127,131071,0,3,0,0,7664,1,0),(7689,'Burst of Life',-1,2,65535,127,131071,0,3,0,0,7689,1,0),(7690,'Spirit Mastery',-1,2,65535,127,131071,0,3,0,0,7690,1,0),(7695,'Quickened Blood of Avoling',-1,512,65535,127,131071,0,3,0,0,7695,1,0),(7698,'Dead Man Floating',-1,1024,65535,127,131071,0,3,0,0,7698,1,0),(7699,'Dread Incarnate',-1,1024,65535,127,131071,0,3,0,0,7699,1,0),(7700,'Flurry',-1,256,65535,127,131071,0,3,0,0,7700,1,0),(7703,'Death Bloom',-1,1024,65535,127,131071,0,3,0,0,7703,1,0),(7712,'Disruptive Persecution',-1,4,65535,127,131071,0,3,0,0,7712,1,0),(7715,'Hastened Whisperwind',-1,1024,65535,127,131071,0,3,0,0,7715,1,0),(7743,'Hastened Guardian of the Forest',-1,8,65535,127,131071,0,3,0,0,7743,1,0),(7746,'Hastened Flusterbolt',-1,8,65535,127,131071,0,3,0,0,7746,1,0),(7747,'Volatile Arrow',-1,8,65535,127,131071,0,3,0,0,7747,1,0),(7748,'Pathfinder\'s Grace',-1,8,65535,127,131071,0,3,0,0,7748,1,0),(7751,'Hastened Cover Tracks',-1,8,65535,127,131071,0,3,0,0,7751,1,0),(7754,'Steed of Souls',-1,16,65535,127,131071,0,3,0,0,7754,1,0),(7755,'Scourge Skin',-1,16,65535,127,131071,0,3,0,0,7755,1,0),(7756,'Death\'s Effigy',-1,16,65535,127,131071,0,3,0,0,7756,1,0),(7757,'Hastened Visage of Death',-1,16,65535,127,131071,0,3,0,0,7757,1,0),(7760,'Hastened Hate Step',-1,16,65535,127,131071,0,3,0,0,7760,1,0),(7801,'Songwriting',6,128,65535,127,131071,0,3,0,0,9001,1,0),(7809,'Hybrid Research',6,16412,65535,127,131071,0,2,0,0,9011,1,0),(7819,'Written Prayer',6,546,65535,127,131071,0,2,0,0,9021,1,0),(7925,'Sionachie\'s Crescendo',-1,128,65535,127,131071,0,3,0,0,1018,1,0),(8081,'Summon Resupply Agent',5,65535,65535,127,131071,0,4,0,1,9000,1,0),(8130,'Summon Clockwork Banker',5,65535,65535,127,131071,0,4,0,1,9031,1,0),(8200,'Hastened Dirge of the Sleepwalker',-1,128,65535,127,131071,0,3,0,0,10329,1,0),(8201,'Vainglorious Shout ',-1,128,65535,127,131071,0,3,0,0,10330,1,0),(8202,'Lyre Leap ',-1,128,65535,127,131071,0,3,0,0,10331,1,0),(8203,'Domination Mastery ',-1,128,65535,127,131071,0,3,0,0,10332,1,0),(8204,'Lyrical Prankster',-1,128,65535,127,131071,0,3,0,0,10333,1,0),(8205,'Selo\'s Kick ',-1,128,65535,127,131071,0,3,0,0,10336,1,0),(8261,'A Tune Stuck In Your Head',-1,128,65535,127,131071,0,3,0,0,10339,1,0),(8262,'The Show Must Go On',-1,128,65535,127,131071,0,3,0,0,7010,1,0),(8300,'Spell Casting Subtlety',-1,16384,65535,127,131071,0,2,0,0,10370,1,0),(8301,'Improved Natural Invisibility',-1,16384,65535,127,131071,0,3,0,0,10373,1,0),(8302,'Protection of the Warder',-1,16384,65535,127,131071,0,3,0,0,10374,1,0),(8303,'Nature\'s Salve',-1,16384,65535,127,131071,0,3,0,0,10377,1,0),(8304,'Focus of Animus',-1,16384,65535,127,131071,0,3,0,0,10380,1,0),(8314,'Fluid March',-1,128,65535,127,131071,0,3,0,0,8314,1,0),(8317,'Hastened Selo\'s Kick',-1,128,65535,127,131071,0,3,0,0,8317,1,0),(8319,'Hastened Bellow',-1,128,65535,127,131071,0,3,0,0,8319,1,0),(8322,'Belltone Mind',-1,128,65535,127,131071,0,3,0,0,8322,1,0),(8325,'Subtle Blows',-1,256,65535,127,131071,0,3,0,0,8325,1,0),(8331,'Enhanced Thief\'s Eyes',-1,256,65535,127,131071,0,3,0,0,8331,1,0),(8332,'Extended Languid Bite',-1,512,65535,127,131071,0,3,0,0,8332,1,0),(8335,'Quickened Malosinete',-1,512,65535,127,131071,0,3,0,0,8335,1,0),(8341,'Drape of Shadows',-1,4096,65535,127,131071,0,3,0,0,8341,1,0),(8342,'Host in the Shell',-1,4096,65535,127,131071,0,3,0,0,8342,1,0),(8347,'Hastened Mana Draw',-1,8192,65535,127,131071,0,3,0,0,8347,1,0),(8350,'Hastened Mezmerization',-1,8192,65535,127,131071,0,3,0,0,8350,1,0),(8400,'Self Preservation',-1,32768,65535,127,131071,0,3,0,0,10400,1,0),(8401,'Hastened Frenzy',-1,32768,65535,127,131071,0,3,0,0,10401,1,0),(8402,'Extended Havoc',-1,32768,65535,127,131071,0,3,0,0,10404,1,0),(8500,'Healing Frenzy',-1,2,65535,127,131071,0,3,0,0,10450,1,0),(8501,'Overpowering Strikes',-1,6,65535,127,131071,0,3,0,0,10453,1,0),(8502,'Quickened Blessing of Ressurection',-1,2,65535,127,131071,0,3,0,0,10456,1,0),(8503,'Hastened Atonement',-1,2,65535,127,131071,0,3,0,0,10459,1,0),(8504,'Improved Sanctuary',-1,2,65535,127,131071,0,3,0,0,10462,1,0),(8505,'Blessing of Sanctuary',-1,2,65535,127,131071,0,3,0,0,10463,1,0),(8506,'Hastened Celestial Hammer',-1,2,65535,127,131071,0,3,0,0,10464,1,0),(8600,'Spirit of Eagle',-1,40,65535,127,131071,0,3,0,0,10500,1,0),(8601,'Flight of Eagles',-1,32,65535,127,131071,0,3,0,0,10501,1,0),(8602,'Egress',-1,32,65535,127,131071,0,3,0,0,10502,1,0),(8603,'Spirits of Nature',-1,32,65535,127,131071,0,3,0,0,10503,1,0),(8604,'Wall of Wind',-1,32,65535,127,131071,0,3,0,0,10506,1,0),(8605,'Hastened Spirit of the Wood',-1,32,65535,127,131071,0,3,0,0,10511,1,0),(8606,'Hastened Convergence of Spirits',-1,32,65535,127,131071,0,3,0,0,10514,1,0),(8700,'Beam of Slumber',-1,8192,65535,127,131071,0,3,0,0,10550,1,0),(8701,'Phantasmic Reflex',-1,8192,65535,127,131071,0,3,0,0,10551,1,0),(8702,'Friendly Stasis',-1,8192,65535,127,131071,0,3,0,0,10557,1,0),(8703,'Hastened Self Stasis',-1,8192,65535,127,131071,0,3,0,0,10558,1,0),(8704,'Forceful Banishment',-1,8192,65535,127,131071,0,3,0,0,10561,1,0),(8708,'Hastened Cascading Rage',-1,32768,65535,127,131071,0,3,0,0,6908,1,0),(8800,'Force of Elements',-1,4096,65535,127,131071,0,3,0,0,10600,1,0),(8801,'Aspect of Zomm',-1,6144,65535,127,131071,0,3,0,0,10603,1,0),(8802,'Extended Shared Health',-1,4096,65535,127,131071,0,3,0,0,10610,1,0),(8900,'Agile Feet',-1,64,65535,127,131071,0,3,0,0,10650,1,0),(8901,'Hastened Defensive Poses',-1,64,65535,127,131071,0,3,0,0,10653,1,0),(8902,'Extended Impenetrable Discipline',-1,64,65535,127,131071,0,3,0,0,10656,1,0),(8903,'Hastened Destructive Force',-1,64,65535,127,131071,0,3,0,0,10657,1,0),(9001,'Reluctant Benevolence',-1,1024,65535,127,131071,0,3,0,0,10701,1,0),(9100,'Bestow Divine Aura',-1,4,65535,127,131071,0,3,0,0,10752,1,0),(9101,'Blessing of Purification',-1,4,65535,127,131071,0,3,0,0,10753,1,0),(9102,'Sense the Dead',-1,1030,65535,127,131071,0,3,0,0,10754,1,0),(9200,'Hastened Auspice of the Hunter',-1,8,65535,127,131071,0,3,0,0,10800,1,0),(9201,'Clenched Jaw',-1,8,65535,127,131071,0,3,0,0,10803,1,0),(9202,'Scout\'s Mastery of Fire',-1,8,65535,127,131071,0,3,0,0,10806,1,0),(9203,'Scout\'s Mastery of Ice',-1,8,65535,127,131071,0,3,0,0,10809,1,0),(9205,'Scout\'s Mastery of Slashing',-1,8,65535,127,131071,0,3,0,0,10815,1,0),(9206,'Scout\'s Mastery of Piercing',-1,8,65535,127,131071,0,3,0,0,10818,1,0),(9207,'Scout\'s Mastery of Blunt Weapons',-1,8,65535,127,131071,0,3,0,0,10821,1,0),(9300,'Massive Strike',-1,256,65535,127,131071,0,3,0,0,10850,1,0),(9301,'Strikethrough',-1,256,65535,127,131071,0,3,0,0,10853,1,0),(9400,'Hate\'s Attraction',-1,16,65535,127,131071,0,3,0,0,10900,1,0),(9401,'Feigned Minion',-1,16,65535,127,131071,0,3,0,0,10903,1,0),(9402,'Hastened Summon Remains',-1,16,65535,127,131071,0,3,0,0,10909,1,0),(9403,'Visage of Death',-1,16,65535,127,131071,0,3,0,0,10912,1,0),(9404,'Cascading Theft of Life',-1,16,65535,127,131071,0,3,0,0,10915,1,0),(9500,'Extended Sloth',-1,512,65535,127,131071,0,3,0,0,10950,1,0),(9501,'Hastened Ancestral Aid',-1,512,65535,127,131071,0,3,0,0,10951,1,0),(9502,'Hastened Union of Spirits',-1,512,65535,127,131071,0,3,0,0,10954,1,0),(9503,'Group Shrink',-1,512,65535,127,131071,0,3,0,0,10957,1,0),(9504,'Inconspicuous Totem',-1,512,65535,127,131071,0,3,0,0,10958,1,0),(9505,'Extended Pestilence',-1,512,65535,127,131071,0,3,0,0,10959,1,0),(9600,'Hastened Taunt',-1,1,65535,127,131071,0,3,0,0,11000,1,0),(9601,'Extended Shield Reflect',-1,1,65535,127,131071,0,3,0,0,11003,1,0),(9602,'Extended Commanding Voice',-1,1,65535,127,131071,0,3,0,0,11004,1,0),(9700,'Hastened Destruction',-1,2048,65535,127,131071,0,3,0,0,11050,1,0),(9701,'Netherstep',-1,2048,65535,127,131071,0,3,0,0,11055,1,0),(9702,'Beam of Displacement',-1,2048,65535,127,131071,0,3,0,0,11056,1,0),(9703,'Translocate',-1,2048,65535,127,131071,0,3,0,0,11057,1,0),(9704,'Teleport',-1,2048,65535,127,131071,0,3,0,0,11058,1,0),(10367,'Ageless Enmity',-1,1,65535,127,131071,0,2,0,0,10367,1,0),(10389,'Extended Trickery',-1,256,65535,127,131071,0,3,0,0,10389,1,0),(10392,'Ageless Enmity',-1,20,65535,127,131071,0,2,0,0,10392,1,0),(10393,'Shackles of Tunare',-1,4,65535,127,131071,0,3,0,0,10393,1,0),(10394,'Beacon of the Righteous',-1,4,65535,127,131071,0,3,0,0,10394,1,0),(10395,'Bobbing Corpse',-1,16,65535,127,131071,0,3,0,0,10395,1,0),(10396,'Group Spirit of the White Wolf',-1,32,65535,127,131071,0,3,0,0,10396,1,0),(10397,'Group Spirit of the Black Wolf',-1,32,65535,127,131071,0,3,0,0,10397,1,0),(10405,'Hastened Deflection Discipline',-1,20,65535,127,131071,0,3,0,0,10405,1,0),(10410,'Rogue Triple Attack Skillup Test',-1,256,65535,127,131071,0,3,0,1,10410,1,0),(10413,'Hastened Host of the Elements',-1,4096,65535,127,131071,0,3,0,0,10413,1,0),(10424,'Hand of Ro',-1,32,65535,127,131071,0,3,0,0,10424,1,0),(10425,'Fixation of Ro',-1,32,65535,127,131071,0,3,0,0,10425,1,0),(10426,'Peaceful Spirit of the Wood',-1,32,65535,127,131071,0,3,0,0,10426,1,0),(10427,'Peaceful Convergence of Spirits',-1,32,65535,127,131071,0,3,0,0,10427,1,0),(10434,'Quickened Army of the Dead',-1,1024,65535,127,131071,0,3,0,0,10434,1,0),(11073,'Playing Possum',-1,16384,65535,127,131071,0,3,0,0,11073,1,0),(11074,'Cat-like Reflexes',-1,16384,65535,127,131071,0,3,0,0,11074,1,0),(11077,'Hastened Bite of the Asp',-1,16384,65535,127,131071,0,3,0,0,11077,1,0),(11078,'Hastened Gorilla Smash',-1,16384,65535,127,131071,0,3,0,0,11078,1,0),(11079,'Hastened Raven\'s Claw',-1,16384,65535,127,131071,0,3,0,0,11079,1,0),(11080,'Chameleon Strike',-1,16384,65535,127,131071,0,3,0,0,11080,1,0),(11085,'Two Hands, No Mercy!',-1,32768,65535,127,131071,0,3,0,0,11085,1,0),(11088,'Hastened Cry of Battle',-1,32768,65535,127,131071,0,3,0,0,11088,1,0),(12600,'Hastened Frenzied Stabbing',-1,256,65535,127,131071,0,3,0,0,12600,1,0),(12603,'Extended Frenzied Stabbing Discipline',-1,256,65535,127,131071,0,3,0,0,12603,1,0),(12606,'Speed of the Scoundrel',-1,256,65535,127,131071,0,3,0,0,12606,1,0),(12607,'Hastened Pinpoint',-1,256,65535,127,131071,0,3,0,0,12607,1,0),(12615,'Hastened Twisted Chance Discipline',-1,256,65535,127,131071,0,3,0,0,12615,1,0),(15073,'Banestrike',2,65535,65535,127,131071,0,4,0,1,15073,1,0),(15074,'Hastened Banestrike',2,65535,65535,127,131071,0,4,0,1,15074,1,0),(30050,'Unknown AA 30050',2,65535,65535,127,131071,0,4,0,1,30050,1,0),(30100,'Unknown AA 30100',2,65535,65535,127,131071,0,4,0,1,30100,1,0),(30150,'Unknown AA 30150',2,65535,65535,127,131071,0,4,0,1,30150,1,0),(30175,'Unknown AA 30175',2,65335,65535,127,131071,0,4,0,1,30175,1,0),(30180,'Unknown AA 30180',2,128,65535,127,131071,0,4,0,1,30180,1,0),(30185,'Unknown AA 30185',2,64,65535,127,131071,0,4,0,1,30185,1,0),(30190,'Unknown AA 30190',2,8,65535,127,131071,0,4,0,1,30190,1,0),(30195,'Unknown AA 30195',2,65535,65535,127,131071,0,4,0,1,30195,1,0); +/*!40000 ALTER TABLE `aa_ability` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `aa_ranks` +-- DROP TABLE IF EXISTS `aa_ranks`; -CREATE TABLE IF NOT EXISTS `aa_ranks` ( +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `aa_ranks` ( `id` int(10) unsigned NOT NULL, - `upper_hotkey_sid` int(10) NOT NULL DEFAULT '-1', - `lower_hotkey_sid` int(10) NOT NULL DEFAULT '-1', - `title_sid` int(10) NOT NULL DEFAULT '-1', - `desc_sid` int(10) NOT NULL DEFAULT '-1', - `cost` int(10) NOT NULL DEFAULT '1', - `level_req` int(10) NOT NULL DEFAULT '51', - `spell` int(10) NOT NULL DEFAULT '-1', - `spell_type` int(10) NOT NULL DEFAULT '0', - `recast_time` int(10) NOT NULL DEFAULT '0', - `expansion` int(10) NOT NULL DEFAULT '0', - `prev_id` int(10) NOT NULL DEFAULT '-1', - `next_id` int(10) NOT NULL DEFAULT '-1', + `upper_hotkey_sid` int(10) NOT NULL DEFAULT -1, + `lower_hotkey_sid` int(10) NOT NULL DEFAULT -1, + `title_sid` int(10) NOT NULL DEFAULT -1, + `desc_sid` int(10) NOT NULL DEFAULT -1, + `cost` int(10) NOT NULL DEFAULT 1, + `level_req` int(10) NOT NULL DEFAULT 51, + `spell` int(10) NOT NULL DEFAULT -1, + `spell_type` int(10) NOT NULL DEFAULT 0, + `recast_time` int(10) NOT NULL DEFAULT 0, + `expansion` int(10) NOT NULL DEFAULT 0, + `prev_id` int(10) NOT NULL DEFAULT -1, + `next_id` int(10) NOT NULL DEFAULT -1, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; -INSERT INTO `aa_ranks` (`id`, `upper_hotkey_sid`, `lower_hotkey_sid`, `title_sid`, `desc_sid`, `cost`, `level_req`, `spell`, `spell_type`, `recast_time`, `expansion`, `prev_id`, `next_id`) VALUES - (2, -1, -1, 2, 2, 1, 51, -1, 0, 0, 3, -1, 3), - (3, -1, -1, 2, 2, 1, 51, -1, 0, 0, 3, 2, 4), - (4, -1, -1, 2, 2, 1, 51, -1, 0, 0, 3, 3, 5), - (5, -1, -1, 2, 2, 1, 51, -1, 0, 0, 3, 4, 6), - (6, -1, -1, 2, 2, 1, 51, -1, 0, 0, 3, 5, 292), - (7, -1, -1, 7, 7, 1, 51, -1, 0, 0, 3, -1, 8), - (8, -1, -1, 7, 7, 1, 51, -1, 0, 0, 3, 7, 9), - (9, -1, -1, 7, 7, 1, 51, -1, 0, 0, 3, 8, 10), - (10, -1, -1, 7, 7, 1, 51, -1, 0, 0, 3, 9, 11), - (11, -1, -1, 7, 7, 1, 51, -1, 0, 0, 3, 10, 302), - (12, -1, -1, 12, 12, 1, 51, -1, 0, 0, 3, -1, 13), - (13, -1, -1, 12, 12, 1, 51, -1, 0, 0, 3, 12, 14), - (14, -1, -1, 12, 12, 1, 51, -1, 0, 0, 3, 13, 15), - (15, -1, -1, 12, 12, 1, 51, -1, 0, 0, 3, 14, 16), - (16, -1, -1, 12, 12, 1, 51, -1, 0, 0, 3, 15, 312), - (17, -1, -1, 17, 17, 1, 51, -1, 0, 0, 3, -1, 18), - (18, -1, -1, 17, 17, 1, 51, -1, 0, 0, 3, 17, 19), - (19, -1, -1, 17, 17, 1, 51, -1, 0, 0, 3, 18, 20), - (20, -1, -1, 17, 17, 1, 51, -1, 0, 0, 3, 19, 21), - (21, -1, -1, 17, 17, 1, 51, -1, 0, 0, 3, 20, 322), - (22, -1, -1, 22, 22, 1, 51, -1, 0, 0, 3, -1, 23), - (23, -1, -1, 22, 22, 1, 51, -1, 0, 0, 3, 22, 24), - (24, -1, -1, 22, 22, 1, 51, -1, 0, 0, 3, 23, 25), - (25, -1, -1, 22, 22, 1, 51, -1, 0, 0, 3, 24, 26), - (26, -1, -1, 22, 22, 1, 51, -1, 0, 0, 3, 25, 332), - (27, -1, -1, 27, 27, 1, 51, -1, 0, 0, 3, -1, 28), - (28, -1, -1, 27, 27, 1, 51, -1, 0, 0, 3, 27, 29), - (29, -1, -1, 27, 27, 1, 51, -1, 0, 0, 3, 28, 30), - (30, -1, -1, 27, 27, 1, 51, -1, 0, 0, 3, 29, 31), - (31, -1, -1, 27, 27, 1, 51, -1, 0, 0, 3, 30, 342), - (32, -1, -1, 32, 32, 1, 51, -1, 0, 0, 3, -1, 33), - (33, -1, -1, 32, 32, 1, 51, -1, 0, 0, 3, 32, 34), - (34, -1, -1, 32, 32, 1, 51, -1, 0, 0, 3, 33, 35), - (35, -1, -1, 32, 32, 1, 51, -1, 0, 0, 3, 34, 36), - (36, -1, -1, 32, 32, 1, 51, -1, 0, 0, 3, 35, 352), - (37, -1, -1, 37, 37, 1, 51, -1, 0, 0, 3, -1, 38), - (38, -1, -1, 37, 37, 1, 51, -1, 0, 0, 3, 37, 39), - (39, -1, -1, 37, 37, 1, 51, -1, 0, 0, 3, 38, 40), - (40, -1, -1, 37, 37, 1, 51, -1, 0, 0, 3, 39, 41), - (41, -1, -1, 37, 37, 1, 51, -1, 0, 0, 3, 40, 362), - (42, -1, -1, 42, 42, 1, 51, -1, 0, 0, 3, -1, 43), - (43, -1, -1, 42, 42, 1, 51, -1, 0, 0, 3, 42, 44), - (44, -1, -1, 42, 42, 1, 51, -1, 0, 0, 3, 43, 45), - (45, -1, -1, 42, 42, 1, 51, -1, 0, 0, 3, 44, 46), - (46, -1, -1, 42, 42, 1, 51, -1, 0, 0, 3, 45, 372), - (47, -1, -1, 47, 47, 1, 51, -1, 0, 0, 3, -1, 48), - (48, -1, -1, 47, 47, 1, 51, -1, 0, 0, 3, 47, 49), - (49, -1, -1, 47, 47, 1, 51, -1, 0, 0, 3, 48, 50), - (50, -1, -1, 47, 47, 1, 51, -1, 0, 0, 3, 49, 51), - (51, -1, -1, 47, 47, 1, 51, -1, 0, 0, 3, 50, 382), - (52, -1, -1, 52, 52, 1, 51, -1, 0, 0, 3, -1, 53), - (53, -1, -1, 52, 52, 1, 51, -1, 0, 0, 3, 52, 54), - (54, -1, -1, 52, 52, 1, 51, -1, 0, 0, 3, 53, 55), - (55, -1, -1, 52, 52, 1, 51, -1, 0, 0, 3, 54, 56), - (56, -1, -1, 52, 52, 1, 51, -1, 0, 0, 3, 55, 392), - (57, -1, -1, 57, 57, 1, 51, -1, 0, 0, 3, -1, 58), - (58, -1, -1, 57, 57, 1, 51, -1, 0, 0, 3, 57, 59), - (59, -1, -1, 57, 57, 1, 51, -1, 0, 0, 3, 58, 60), - (60, -1, -1, 57, 57, 1, 51, -1, 0, 0, 3, 59, 61), - (61, -1, -1, 57, 57, 1, 51, -1, 0, 0, 3, 60, 402), - (62, -1, -1, 62, 62, 1, 51, -1, 0, 0, 3, -1, 63), - (63, -1, -1, 62, 62, 1, 51, -1, 0, 0, 3, 62, 64), - (64, -1, -1, 62, 62, 1, 51, -1, 0, 0, 3, 63, 672), - (68, -1, -1, 68, 68, 1, 51, -1, 0, 0, 3, -1, 69), - (69, -1, -1, 68, 68, 1, 51, -1, 0, 0, 3, 68, 70), - (70, -1, -1, 68, 68, 1, 51, -1, 0, 0, 3, 69, -1), - (71, -1, -1, 71, 71, 1, 51, -1, 0, 0, 3, -1, 72), - (72, -1, -1, 71, 71, 1, 51, -1, 0, 0, 3, 71, 73), - (73, -1, -1, 71, 71, 1, 51, -1, 0, 0, 3, 72, 676), - (74, -1, -1, 74, 74, 1, 51, -1, 0, 0, 3, -1, 75), - (75, -1, -1, 74, 74, 1, 51, -1, 0, 0, 3, 74, 76), - (76, -1, -1, 74, 74, 1, 51, -1, 0, 0, 3, 75, -1), - (77, -1, -1, 77, 77, 2, 55, -1, 0, 0, 3, -1, 78), - (78, -1, -1, 77, 77, 4, 55, -1, 0, 0, 3, 77, 79), - (79, -1, -1, 77, 77, 6, 55, -1, 0, 0, 3, 78, 434), - (80, -1, -1, 80, 80, 2, 55, -1, 0, 0, 3, -1, 81), - (81, -1, -1, 80, 80, 4, 55, -1, 0, 0, 3, 80, 82), - (82, -1, -1, 80, 80, 6, 55, -1, 0, 0, 3, 81, 437), - (83, -1, -1, 83, 83, 2, 55, -1, 0, 0, 3, -1, 84), - (84, -1, -1, 83, 83, 4, 55, -1, 0, 0, 3, 83, 85), - (85, -1, -1, 83, 83, 6, 55, -1, 0, 0, 3, 84, 13099), - (86, -1, -1, 86, 86, 2, 55, -1, 0, 0, 3, -1, 87), - (87, -1, -1, 86, 86, 4, 55, -1, 0, 0, 3, 86, 88), - (88, -1, -1, 86, 86, 6, 55, -1, 0, 0, 3, 87, 266), - (92, -1, -1, 92, 92, 2, 55, -1, 0, 0, 3, -1, 93), - (93, -1, -1, 92, 92, 4, 55, -1, 0, 0, 3, 92, 94), - (94, -1, -1, 92, 92, 6, 55, -1, 0, 0, 3, 93, -1), - (98, -1, -1, 98, 98, 2, 55, -1, 0, 0, 3, -1, 99), - (99, -1, -1, 98, 98, 4, 55, -1, 0, 0, 3, 98, 100), - (100, -1, -1, 98, 98, 6, 55, -1, 0, 0, 3, 99, 4767), - (101, -1, -1, 101, 101, 2, 55, -1, 0, 0, 3, -1, 102), - (102, -1, -1, 101, 101, 4, 55, -1, 0, 0, 3, 101, 103), - (103, -1, -1, 101, 101, 6, 55, -1, 0, 0, 3, 102, -1), - (104, -1, -1, 104, 104, 2, 55, -1, 0, 0, 3, -1, 105), - (105, -1, -1, 104, 104, 4, 55, -1, 0, 0, 3, 104, 106), - (106, -1, -1, 104, 104, 6, 55, -1, 0, 0, 3, 105, -1), - (107, -1, -1, 107, 107, 2, 55, -1, 0, 0, 3, -1, 108), - (108, -1, -1, 107, 107, 4, 55, -1, 0, 0, 3, 107, 109), - (109, -1, -1, 107, 107, 6, 55, -1, 0, 0, 3, 108, 7541), - (110, -1, -1, 110, 110, 2, 55, -1, 0, 0, 3, -1, 111), - (111, -1, -1, 110, 110, 4, 55, -1, 0, 0, 3, 110, 112), - (112, -1, -1, 110, 110, 6, 55, -1, 0, 0, 3, 111, -1), - (113, -1, -1, 113, 113, 2, 55, -1, 0, 0, 3, -1, 114), - (114, -1, -1, 113, 113, 4, 55, -1, 0, 0, 3, 113, 115), - (115, -1, -1, 113, 113, 6, 55, -1, 0, 0, 3, 114, 443), - (116, -1, -1, 116, 116, 2, 55, -1, 0, 0, 3, -1, 117), - (117, -1, -1, 116, 116, 4, 55, -1, 0, 0, 3, 116, 118), - (118, -1, -1, 116, 116, 6, 55, -1, 0, 0, 3, 117, -1), - (119, -1, -1, 119, 119, 2, 55, -1, 0, 0, 3, -1, 120), - (120, -1, -1, 119, 119, 4, 55, -1, 0, 0, 3, 119, 121), - (121, -1, -1, 119, 119, 6, 55, -1, 0, 0, 3, 120, 440), - (122, -1, -1, 122, 122, 2, 55, -1, 0, 0, 3, -1, 123), - (123, -1, -1, 122, 122, 4, 55, -1, 0, 0, 3, 122, 124), - (124, -1, -1, 122, 122, 6, 55, -1, 0, 0, 3, 123, 454), - (125, -1, -1, 125, 125, 2, 55, -1, 0, 0, 3, -1, 126), - (126, -1, -1, 125, 125, 4, 55, -1, 0, 0, 3, 125, 127), - (127, -1, -1, 125, 125, 6, 55, -1, 0, 0, 3, 126, 449), - (128, 128, 128, 128, 128, 9, 59, 5228, 1, 4320, 3, -1, -1), - (129, 129, 129, 129, 129, 5, 59, 2738, 2, 64800, 3, -1, -1), - (130, 130, 130, 130, 130, 3, 59, 2739, 3, 7, 3, -1, -1), - (131, 131, 131, 131, 131, 5, 59, 2740, 4, 900, 3, -1, 531), - (132, 132, 132, 132, 132, 6, 59, 2741, 5, 600, 3, -1, -1), - (136, 136, -1, 136, 136, 5, 59, 2742, 7, 1800, 3, -1, 15341), - (137, -1, -1, 137, 137, 3, 59, -1, 0, 0, 3, -1, 138), - (138, -1, -1, 137, 137, 6, 59, -1, 0, 0, 3, 137, 139), - (139, -1, -1, 137, 137, 9, 59, -1, 0, 0, 3, 138, -1), - (140, 140, -1, 140, 140, 6, 59, 2771, 3, 4320, 3, -1, -1), - (141, -1, -1, 141, 12863, 3, 59, -1, 0, 0, 3, -1, 142), - (142, -1, -1, 141, 12863, 6, 59, -1, 0, 0, 3, 141, 143), - (143, -1, -1, 141, 12863, 9, 59, -1, 0, 0, 3, 142, 12863), - (144, -1, -1, 144, 144, 5, 59, -1, 0, 0, 3, -1, -1), - (145, 145, 145, 145, 145, 9, 59, 2761, 2, 4320, 3, -1, -1), - (146, 146, 146, 146, 146, 5, 59, 2749, 2, 180, 3, -1, 5069), - (147, -1, -1, 147, 147, 3, 59, -1, 0, 0, 3, -1, 148), - (148, -1, -1, 147, 147, 6, 59, -1, 0, 0, 3, 147, 149), - (149, -1, -1, 147, 147, 9, 59, -1, 0, 0, 3, 148, -1), - (150, -1, -1, 150, 150, 3, 59, -1, 0, 0, 3, -1, 151), - (151, -1, -1, 150, 150, 6, 59, -1, 0, 0, 3, 150, 152), - (152, -1, -1, 150, 150, 9, 59, -1, 0, 0, 3, 151, -1), - (153, 153, 153, 153, 153, 5, 59, 2750, 3, 2160, 3, -1, 1519), - (155, 155, 155, 155, 155, 9, 59, 2758, 8, 60, 3, -1, 533), - (156, 156, 156, 156, 156, 6, 59, 2734, 2, 4320, 3, -1, -1), - (158, -1, -1, 158, 158, 3, 59, -1, 0, 0, 3, -1, -1), - (159, -1, -1, 159, 159, 2, 59, -1, 0, 0, 3, -1, 160), - (160, -1, -1, 159, 159, 4, 59, -1, 0, 0, 3, 159, 161), - (161, -1, -1, 159, 159, 6, 59, -1, 0, 0, 3, 160, -1), - (162, 162, 162, 162, 162, 5, 59, 2753, 3, 8640, 3, -1, -1), - (163, 163, 163, 163, 163, 5, 59, 2752, 2, 2160, 3, -1, -1), - (167, 167, 167, 167, 167, 6, 59, 2754, 14, 900, 3, -1, 5879), - (168, 168, 168, 168, 168, 3, 59, 2795, 4, 10, 3, -1, 169), - (169, 168, 168, 168, 168, 6, 59, 2796, 4, 10, 3, 168, 170), - (170, 168, 168, 168, 168, 9, 59, 2797, 4, 10, 3, 169, 15241), - (171, 171, 171, 171, 171, 3, 59, 2798, 4, 10, 3, -1, 172), - (172, 171, 171, 171, 171, 6, 59, 2799, 4, 10, 3, 171, 173), - (173, 171, 171, 171, 171, 9, 59, 2800, 4, 10, 3, 172, 15244), - (174, 174, 174, 174, 174, 3, 59, 2792, 4, 10, 3, -1, 175), - (175, 174, 174, 174, 174, 6, 59, 2793, 4, 10, 3, 174, 176), - (176, 174, 174, 174, 174, 9, 59, 2794, 4, 10, 3, 175, 15247), - (177, 177, 177, 177, 177, 3, 59, 2789, 4, 10, 3, -1, 178), - (178, 177, 177, 177, 177, 6, 59, 2790, 4, 10, 3, 177, 179), - (179, 177, 177, 177, 177, 9, 59, 2791, 4, 10, 3, 178, 15250), - (182, -1, -1, 182, 182, 5, 59, -1, 0, 0, 3, -1, -1), - (183, 183, 183, 183, 183, 9, 59, 2755, 4, 8640, 3, -1, -1), - (184, 184, 184, 184, 184, 3, 59, 2756, 5, 4320, 3, -1, 5953), - (185, 185, 185, 185, 185, 5, 59, 2757, 6, 4320, 3, -1, -1), - (186, 186, 186, 186, 186, 3, 59, 2772, 7, 7, 3, -1, -1), - (187, 187, 187, 187, 187, 6, 59, 2764, 8, 4320, 3, -1, -1), - (188, 188, 188, 188, 188, 9, 59, 2190, 2, 30, 3, -1, 1277), - (190, -1, -1, 190, 190, 3, 59, -1, 0, 0, 3, -1, 191), - (191, -1, -1, 190, 190, 6, 59, -1, 0, 0, 3, 190, 192), - (192, -1, -1, 190, 190, 9, 59, -1, 0, 0, 3, 191, 1524), - (193, 193, 193, 193, 193, 3, 59, 2775, 3, 4320, 3, -1, -1), - (194, 194, 194, 194, 194, 5, 59, 2874, 0, 1, 3, -1, -1), - (195, -1, -1, 195, 195, 6, 59, -1, 0, 0, 3, -1, -1), - (196, -1, -1, 196, 196, 6, 59, -1, 0, 0, 3, -1, -1), - (197, 197, 197, 197, 197, 5, 59, 2765, 2, 7, 3, -1, -1), - (198, -1, -1, 198, 198, 9, 59, -1, 0, 0, 3, -1, -1), - (199, -1, -1, 199, 199, 3, 59, -1, 0, 0, 3, -1, 200), - (200, -1, -1, 199, 199, 6, 59, -1, 0, 0, 3, 199, 201), - (201, -1, -1, 199, 199, 9, 59, -1, 0, 0, 3, 200, 12507), - (205, -1, -1, 205, 205, 9, 59, -1, 0, 0, 3, -1, -1), - (206, 206, 206, 206, 206, 5, 59, 2875, 0, 1, 3, -1, -1), - (208, 208, 208, 208, 208, 6, 59, 2766, 2, 4320, 3, -1, -1), - (210, -1, -1, 210, 210, 3, 59, -1, 0, 0, 3, -1, 211), - (211, -1, -1, 210, 210, 6, 59, -1, 0, 0, 3, 210, 212), - (212, -1, -1, 210, 210, 9, 59, -1, 0, 0, 3, 211, 1316), - (213, -1, -1, 213, 213, 3, 59, -1, 0, 0, 3, -1, 214), - (214, -1, -1, 213, 213, 6, 59, -1, 0, 0, 3, 213, 215), - (215, -1, -1, 213, 213, 9, 59, -1, 0, 0, 3, 214, 700), - (225, -1, -1, 225, 225, 3, 59, -1, 0, 0, 3, -1, 226), - (226, -1, -1, 225, 225, 6, 59, -1, 0, 0, 3, 225, 227), - (227, -1, -1, 225, 225, 9, 59, -1, 0, 0, 3, 226, -1), - (230, -1, -1, 230, 230, 3, 59, -1, 0, 0, 3, -1, 231), - (231, -1, -1, 230, 230, 6, 59, -1, 0, 0, 3, 230, 232), - (232, -1, -1, 230, 230, 9, 59, -1, 0, 0, 3, 231, 539), - (233, 233, 233, 233, 233, 9, 59, 5248, 1, 1800, 3, -1, -1), - (237, -1, -1, 237, 237, 3, 59, -1, 0, 0, 3, -1, 238), - (238, -1, -1, 237, 237, 6, 59, -1, 0, 0, 3, 237, 239), - (239, -1, -1, 237, 237, 9, 59, -1, 0, 0, 3, 238, -1), - (240, -1, -1, 240, 240, 3, 59, -1, 0, 0, 3, -1, 241), - (241, -1, -1, 240, 240, 6, 59, -1, 0, 0, 3, 240, 242), - (242, -1, -1, 240, 240, 9, 59, -1, 0, 0, 3, 241, -1), - (243, 243, -1, 243, 243, 9, 59, 5244, 1, 1440, 3, -1, -1), - (244, -1, -1, 244, 244, 3, 59, -1, 0, 0, 3, -1, 245), - (245, -1, -1, 244, 244, 6, 59, -1, 0, 0, 3, 244, 246), - (246, -1, -1, 244, 244, 9, 59, -1, 0, 0, 3, 245, 8328), - (247, -1, -1, 247, 247, 3, 59, -1, 0, 0, 3, -1, 248), - (248, -1, -1, 247, 247, 6, 59, -1, 0, 0, 3, 247, 249), - (249, -1, -1, 247, 247, 9, 59, -1, 0, 0, 3, 248, 504), - (254, 254, 254, 254, 254, 5, 59, 5232, 12, 4320, 3, -1, -1), - (255, -1, -1, 255, 255, 3, 59, -1, 0, 0, 3, -1, 256), - (256, -1, -1, 255, 255, 6, 59, -1, 0, 0, 3, 255, 257), - (257, -1, -1, 255, 255, 9, 59, -1, 0, 0, 3, 256, 542), - (258, 258, -1, 258, 258, 5, 59, 5233, 1, 600, 3, -1, 10578), - (259, 259, 259, 259, 259, 5, 59, 5234, 2, 900, 3, -1, -1), - (260, 260, -1, 260, 260, 3, 59, 5229, 3, 2160, 3, -1, 261), - (261, 260, -1, 260, 260, 6, 59, 5230, 3, 2160, 3, 260, 262), - (262, 260, -1, 260, 260, 9, 59, 5231, 3, 2160, 3, 261, 8309), - (263, -1, -1, 263, 263, 3, 59, -1, 0, 0, 3, -1, 264), - (264, -1, -1, 263, 263, 6, 59, -1, 0, 0, 3, 263, 265), - (265, -1, -1, 263, 263, 9, 59, -1, 0, 0, 3, 264, -1), - (266, -1, -1, 86, 86, 8, 59, -1, 0, 0, 3, 88, 10467), - (267, -1, -1, 267, 267, 3, 59, -1, 0, 0, 3, -1, 268), - (268, -1, -1, 267, 267, 6, 59, -1, 0, 0, 3, 267, 269), - (269, -1, -1, 267, 267, 9, 59, -1, 0, 0, 3, 268, 640), - (273, -1, -1, 273, 273, 5, 59, 2767, 0, 0, 3, -1, -1), - (274, 274, 274, 274, 274, 5, 59, 2748, 4, 4320, 3, -1, -1), - (275, -1, -1, 275, 275, 3, 59, -1, 0, 0, 3, -1, 276), - (276, -1, -1, 275, 275, 6, 59, -1, 0, 0, 3, 275, 277), - (277, -1, -1, 275, 275, 9, 59, -1, 0, 0, 3, 276, 701), - (278, -1, -1, 278, 278, 5, 59, -1, 0, 0, 3, -1, -1), - (279, -1, -1, 279, 279, 5, 59, -1, 0, 0, 3, -1, 18972), - (280, -1, -1, 280, 280, 3, 59, -1, 0, 0, 3, -1, 281), - (281, -1, -1, 280, 280, 6, 59, -1, 0, 0, 3, 280, 282), - (282, -1, -1, 280, 280, 9, 59, -1, 0, 0, 3, 281, -1), - (283, -1, -1, 283, 283, 3, 59, -1, 0, 0, 3, -1, 284), - (284, -1, -1, 283, 283, 6, 59, -1, 0, 0, 3, 283, 285), - (285, -1, -1, 283, 283, 9, 59, -1, 0, 0, 3, 284, -1), - (286, -1, -1, 286, 286, 3, 59, -1, 0, 0, 3, -1, -1), - (287, -1, -1, 287, 287, 6, 59, -1, 0, 0, 3, -1, -1), - (288, -1, -1, 288, 288, 6, 59, -1, 0, 0, 3, -1, -1), - (289, 289, 289, 289, 289, 5, 59, 3290, 3, 300, 3, -1, 1607), - (290, 290, 290, 290, 290, 4, 59, 3289, 4, 720, 3, -1, 13173), - (291, 291, 291, 291, 291, 6, 59, 3291, 5, 900, 3, -1, 1123), - (292, -1, -1, 2, 2, 1, 61, -1, 0, 0, 4, 6, 293), - (293, -1, -1, 2, 2, 1, 61, -1, 0, 0, 4, 292, 294), - (294, -1, -1, 2, 2, 1, 62, -1, 0, 0, 4, 293, 295), - (295, -1, -1, 2, 2, 1, 62, -1, 0, 0, 4, 294, 296), - (296, -1, -1, 2, 2, 1, 63, -1, 0, 0, 4, 295, 297), - (297, -1, -1, 2, 2, 1, 63, -1, 0, 0, 4, 296, 298), - (298, -1, -1, 2, 2, 1, 64, -1, 0, 0, 4, 297, 299), - (299, -1, -1, 2, 2, 1, 64, -1, 0, 0, 4, 298, 300), - (300, -1, -1, 2, 2, 1, 65, -1, 0, 0, 4, 299, 301), - (301, -1, -1, 2, 2, 1, 65, -1, 0, 0, 4, 300, -1), - (302, -1, -1, 7, 7, 1, 61, -1, 0, 0, 4, 11, 303), - (303, -1, -1, 7, 7, 1, 61, -1, 0, 0, 4, 302, 304), - (304, -1, -1, 7, 7, 1, 62, -1, 0, 0, 4, 303, 305), - (305, -1, -1, 7, 7, 1, 62, -1, 0, 0, 4, 304, 306), - (306, -1, -1, 7, 7, 1, 63, -1, 0, 0, 4, 305, 307), - (307, -1, -1, 7, 7, 1, 63, -1, 0, 0, 4, 306, 308), - (308, -1, -1, 7, 7, 1, 64, -1, 0, 0, 4, 307, 309), - (309, -1, -1, 7, 7, 1, 64, -1, 0, 0, 4, 308, 310), - (310, -1, -1, 7, 7, 1, 65, -1, 0, 0, 4, 309, 311), - (311, -1, -1, 7, 7, 1, 65, -1, 0, 0, 4, 310, -1), - (312, -1, -1, 12, 12, 1, 61, -1, 0, 0, 4, 16, 313), - (313, -1, -1, 12, 12, 1, 61, -1, 0, 0, 4, 312, 314), - (314, -1, -1, 12, 12, 1, 62, -1, 0, 0, 4, 313, 315), - (315, -1, -1, 12, 12, 1, 62, -1, 0, 0, 4, 314, 316), - (316, -1, -1, 12, 12, 1, 63, -1, 0, 0, 4, 315, 317), - (317, -1, -1, 12, 12, 1, 63, -1, 0, 0, 4, 316, 318), - (318, -1, -1, 12, 12, 1, 64, -1, 0, 0, 4, 317, 319), - (319, -1, -1, 12, 12, 1, 64, -1, 0, 0, 4, 318, 320), - (320, -1, -1, 12, 12, 1, 65, -1, 0, 0, 4, 319, 321), - (321, -1, -1, 12, 12, 1, 65, -1, 0, 0, 4, 320, -1), - (322, -1, -1, 17, 17, 1, 61, -1, 0, 0, 4, 21, 323), - (323, -1, -1, 17, 17, 1, 61, -1, 0, 0, 4, 322, 324), - (324, -1, -1, 17, 17, 1, 62, -1, 0, 0, 4, 323, 325), - (325, -1, -1, 17, 17, 1, 62, -1, 0, 0, 4, 324, 326), - (326, -1, -1, 17, 17, 1, 63, -1, 0, 0, 4, 325, 327), - (327, -1, -1, 17, 17, 1, 63, -1, 0, 0, 4, 326, 328), - (328, -1, -1, 17, 17, 1, 64, -1, 0, 0, 4, 327, 329), - (329, -1, -1, 17, 17, 1, 64, -1, 0, 0, 4, 328, 330), - (330, -1, -1, 17, 17, 1, 65, -1, 0, 0, 4, 329, 331), - (331, -1, -1, 17, 17, 1, 65, -1, 0, 0, 4, 330, -1), - (332, -1, -1, 22, 22, 1, 61, -1, 0, 0, 4, 26, 333), - (333, -1, -1, 22, 22, 1, 61, -1, 0, 0, 4, 332, 334), - (334, -1, -1, 22, 22, 1, 62, -1, 0, 0, 4, 333, 335), - (335, -1, -1, 22, 22, 1, 62, -1, 0, 0, 4, 334, 336), - (336, -1, -1, 22, 22, 1, 63, -1, 0, 0, 4, 335, 337), - (337, -1, -1, 22, 22, 1, 63, -1, 0, 0, 4, 336, 338), - (338, -1, -1, 22, 22, 1, 64, -1, 0, 0, 4, 337, 339), - (339, -1, -1, 22, 22, 1, 64, -1, 0, 0, 4, 338, 340), - (340, -1, -1, 22, 22, 1, 65, -1, 0, 0, 4, 339, 341), - (341, -1, -1, 22, 22, 1, 65, -1, 0, 0, 4, 340, -1), - (342, -1, -1, 27, 27, 1, 61, -1, 0, 0, 4, 31, 343), - (343, -1, -1, 27, 27, 1, 61, -1, 0, 0, 4, 342, 344), - (344, -1, -1, 27, 27, 1, 62, -1, 0, 0, 4, 343, 345), - (345, -1, -1, 27, 27, 1, 62, -1, 0, 0, 4, 344, 346), - (346, -1, -1, 27, 27, 1, 63, -1, 0, 0, 4, 345, 347), - (347, -1, -1, 27, 27, 1, 63, -1, 0, 0, 4, 346, 348), - (348, -1, -1, 27, 27, 1, 64, -1, 0, 0, 4, 347, 349), - (349, -1, -1, 27, 27, 1, 64, -1, 0, 0, 4, 348, 350), - (350, -1, -1, 27, 27, 1, 65, -1, 0, 0, 4, 349, 351), - (351, -1, -1, 27, 27, 1, 65, -1, 0, 0, 4, 350, -1), - (352, -1, -1, 32, 32, 1, 61, -1, 0, 0, 4, 36, 353), - (353, -1, -1, 32, 32, 1, 61, -1, 0, 0, 4, 352, 354), - (354, -1, -1, 32, 32, 1, 62, -1, 0, 0, 4, 353, 355), - (355, -1, -1, 32, 32, 1, 62, -1, 0, 0, 4, 354, 356), - (356, -1, -1, 32, 32, 1, 63, -1, 0, 0, 4, 355, 357), - (357, -1, -1, 32, 32, 1, 63, -1, 0, 0, 4, 356, 358), - (358, -1, -1, 32, 32, 1, 64, -1, 0, 0, 4, 357, 359), - (359, -1, -1, 32, 32, 1, 64, -1, 0, 0, 4, 358, 360), - (360, -1, -1, 32, 32, 1, 65, -1, 0, 0, 4, 359, 361), - (361, -1, -1, 32, 32, 1, 65, -1, 0, 0, 4, 360, -1), - (362, -1, -1, 37, 37, 1, 61, -1, 0, 0, 4, 41, 363), - (363, -1, -1, 37, 37, 1, 61, -1, 0, 0, 4, 362, 364), - (364, -1, -1, 37, 37, 1, 62, -1, 0, 0, 4, 363, 365), - (365, -1, -1, 37, 37, 1, 62, -1, 0, 0, 4, 364, 366), - (366, -1, -1, 37, 37, 1, 63, -1, 0, 0, 4, 365, 367), - (367, -1, -1, 37, 37, 1, 63, -1, 0, 0, 4, 366, 368), - (368, -1, -1, 37, 37, 1, 64, -1, 0, 0, 4, 367, 369), - (369, -1, -1, 37, 37, 1, 64, -1, 0, 0, 4, 368, 370), - (370, -1, -1, 37, 37, 1, 65, -1, 0, 0, 4, 369, 371), - (371, -1, -1, 37, 37, 1, 65, -1, 0, 0, 4, 370, -1), - (372, -1, -1, 42, 42, 1, 61, -1, 0, 0, 4, 46, 373), - (373, -1, -1, 42, 42, 1, 61, -1, 0, 0, 4, 372, 374), - (374, -1, -1, 42, 42, 1, 62, -1, 0, 0, 4, 373, 375), - (375, -1, -1, 42, 42, 1, 62, -1, 0, 0, 4, 374, 376), - (376, -1, -1, 42, 42, 1, 63, -1, 0, 0, 4, 375, 377), - (377, -1, -1, 42, 42, 1, 63, -1, 0, 0, 4, 376, 378), - (378, -1, -1, 42, 42, 1, 64, -1, 0, 0, 4, 377, 379), - (379, -1, -1, 42, 42, 1, 64, -1, 0, 0, 4, 378, 380), - (380, -1, -1, 42, 42, 1, 65, -1, 0, 0, 4, 379, 381), - (381, -1, -1, 42, 42, 1, 65, -1, 0, 0, 4, 380, -1), - (382, -1, -1, 47, 47, 1, 61, -1, 0, 0, 4, 51, 383), - (383, -1, -1, 47, 47, 1, 61, -1, 0, 0, 4, 382, 384), - (384, -1, -1, 47, 47, 1, 62, -1, 0, 0, 4, 383, 385), - (385, -1, -1, 47, 47, 1, 62, -1, 0, 0, 4, 384, 386), - (386, -1, -1, 47, 47, 1, 63, -1, 0, 0, 4, 385, 387), - (387, -1, -1, 47, 47, 1, 63, -1, 0, 0, 4, 386, 388), - (388, -1, -1, 47, 47, 1, 64, -1, 0, 0, 4, 387, 389), - (389, -1, -1, 47, 47, 1, 64, -1, 0, 0, 4, 388, 390), - (390, -1, -1, 47, 47, 1, 65, -1, 0, 0, 4, 389, 391), - (391, -1, -1, 47, 47, 1, 65, -1, 0, 0, 4, 390, -1), - (392, -1, -1, 52, 52, 1, 61, -1, 0, 0, 4, 56, 393), - (393, -1, -1, 52, 52, 1, 61, -1, 0, 0, 4, 392, 394), - (394, -1, -1, 52, 52, 1, 62, -1, 0, 0, 4, 393, 395), - (395, -1, -1, 52, 52, 1, 62, -1, 0, 0, 4, 394, 396), - (396, -1, -1, 52, 52, 1, 63, -1, 0, 0, 4, 395, 397), - (397, -1, -1, 52, 52, 1, 63, -1, 0, 0, 4, 396, 398), - (398, -1, -1, 52, 52, 1, 64, -1, 0, 0, 4, 397, 399), - (399, -1, -1, 52, 52, 1, 64, -1, 0, 0, 4, 398, 400), - (400, -1, -1, 52, 52, 1, 65, -1, 0, 0, 4, 399, 401), - (401, -1, -1, 52, 52, 1, 65, -1, 0, 0, 4, 400, -1), - (402, -1, -1, 57, 57, 1, 61, -1, 0, 0, 4, 61, 403), - (403, -1, -1, 57, 57, 1, 61, -1, 0, 0, 4, 402, 404), - (404, -1, -1, 57, 57, 1, 62, -1, 0, 0, 4, 403, 405), - (405, -1, -1, 57, 57, 1, 62, -1, 0, 0, 4, 404, 406), - (406, -1, -1, 57, 57, 1, 63, -1, 0, 0, 4, 405, 407), - (407, -1, -1, 57, 57, 1, 63, -1, 0, 0, 4, 406, 408), - (408, -1, -1, 57, 57, 1, 64, -1, 0, 0, 4, 407, 409), - (409, -1, -1, 57, 57, 1, 64, -1, 0, 0, 4, 408, 410), - (410, -1, -1, 57, 57, 1, 65, -1, 0, 0, 4, 409, 411), - (411, -1, -1, 57, 57, 1, 65, -1, 0, 0, 4, 410, -1), - (412, -1, -1, 412, 412, 3, 51, -1, 0, 0, 3, -1, 413), - (413, -1, -1, 412, 412, 3, 51, -1, 0, 0, 3, 412, 414), - (414, -1, -1, 412, 412, 3, 51, -1, 0, 0, 3, 413, 415), - (415, -1, -1, 412, 412, 3, 51, -1, 0, 0, 3, 414, 416), - (416, -1, -1, 412, 412, 3, 51, -1, 0, 0, 3, 415, 417), - (417, -1, -1, 412, 412, 3, 51, -1, 0, 0, 3, 416, -1), - (418, -1, -1, 418, 418, 2, 61, -1, 0, 0, 4, -1, 419), - (419, -1, -1, 418, 418, 2, 62, -1, 0, 0, 4, 418, 420), - (420, -1, -1, 418, 418, 2, 63, -1, 0, 0, 4, 419, 421), - (421, -1, -1, 418, 418, 2, 64, -1, 0, 0, 4, 420, 422), - (422, -1, -1, 418, 418, 2, 65, -1, 0, 0, 4, 421, 1001), - (423, -1, -1, 423, 423, 3, 61, -1, 0, 0, 4, -1, 424), - (424, -1, -1, 423, 423, 3, 63, -1, 0, 0, 4, 423, 425), - (425, -1, -1, 423, 423, 3, 65, -1, 0, 0, 4, 424, -1), - (426, -1, -1, 426, 426, 3, 61, -1, 0, 0, 4, -1, 427), - (427, -1, -1, 426, 426, 3, 62, -1, 0, 0, 4, 426, 428), - (428, -1, -1, 426, 426, 3, 63, -1, 0, 0, 4, 427, 429), - (429, -1, -1, 426, 426, 3, 64, -1, 0, 0, 4, 428, 430), - (430, -1, -1, 426, 426, 3, 65, -1, 0, 0, 4, 429, -1), - (434, -1, -1, 77, 77, 2, 62, -1, 0, 0, 4, 79, 435), - (435, -1, -1, 77, 77, 4, 63, -1, 0, 0, 4, 434, 436), - (436, -1, -1, 77, 77, 6, 64, -1, 0, 0, 4, 435, 1083), - (437, -1, -1, 80, 80, 2, 62, -1, 0, 0, 4, 82, 438), - (438, -1, -1, 80, 80, 3, 63, -1, 0, 0, 4, 437, 439), - (439, -1, -1, 80, 80, 4, 64, -1, 0, 0, 4, 438, 1086), - (440, -1, -1, 119, 119, 2, 62, -1, 0, 0, 4, 121, 441), - (441, -1, -1, 119, 119, 2, 63, -1, 0, 0, 4, 440, 442), - (442, -1, -1, 119, 119, 2, 64, -1, 0, 0, 4, 441, 1053), - (443, -1, -1, 113, 113, 3, 62, -1, 0, 0, 4, 115, 444), - (444, -1, -1, 113, 113, 3, 63, -1, 0, 0, 4, 443, 445), - (445, -1, -1, 113, 113, 3, 64, -1, 0, 0, 4, 444, -1), - (446, -1, -1, 446, 735, 3, 62, -1, 0, 0, 4, -1, 447), - (447, -1, -1, 446, 735, 3, 63, -1, 0, 0, 4, 446, 448), - (448, -1, -1, 446, 735, 3, 64, -1, 0, 0, 4, 447, 7050), - (449, -1, -1, 125, 125, 3, 61, -1, 0, 0, 4, 127, 450), - (450, -1, -1, 125, 125, 3, 62, -1, 0, 0, 4, 449, 451), - (451, -1, -1, 125, 125, 3, 63, -1, 0, 0, 4, 450, 452), - (452, -1, -1, 125, 125, 3, 64, -1, 0, 0, 4, 451, 453), - (453, -1, -1, 125, 125, 3, 65, -1, 0, 0, 4, 452, 1061), - (454, -1, -1, 122, 122, 3, 61, -1, 0, 0, 4, 124, 455), - (455, -1, -1, 122, 122, 3, 62, -1, 0, 0, 4, 454, 456), - (456, -1, -1, 122, 122, 3, 63, -1, 0, 0, 4, 455, 457), - (457, -1, -1, 122, 122, 3, 64, -1, 0, 0, 4, 456, 458), - (458, -1, -1, 122, 122, 3, 65, -1, 0, 0, 4, 457, 1066), - (459, 459, 459, 459, 459, 2, 61, 3297, 8, 180, 4, -1, 460), - (460, 459, 459, 459, 459, 4, 63, 3298, 8, 180, 4, 459, 461), - (461, 459, 459, 459, 459, 6, 65, 3299, 8, 180, 4, 460, 1189), - (462, -1, -1, 462, 462, 2, 63, -1, 0, 0, 4, -1, 463), - (463, -1, -1, 462, 462, 2, 64, -1, 0, 0, 4, 462, 464), - (464, -1, -1, 462, 462, 2, 65, -1, 0, 0, 4, 463, 7994), - (468, -1, -1, 468, 468, 2, 63, -1, 0, 0, 4, -1, 469), - (469, -1, -1, 468, 468, 2, 64, -1, 0, 0, 4, 468, 470), - (470, -1, -1, 468, 468, 2, 65, -1, 0, 0, 4, 469, 6439), - (471, -1, -1, 471, 471, 2, 63, -1, 0, 0, 4, -1, 472), - (472, -1, -1, 471, 471, 2, 64, -1, 0, 0, 4, 471, 473), - (473, -1, -1, 471, 471, 2, 65, -1, 0, 0, 4, 472, 12899), - (474, -1, -1, 474, 474, 2, 63, -1, 0, 0, 4, -1, 475), - (475, -1, -1, 474, 474, 2, 64, -1, 0, 0, 4, 474, 476), - (476, -1, -1, 474, 474, 2, 65, -1, 0, 0, 4, 475, 15359), - (477, -1, -1, 477, 477, 2, 63, -1, 0, 0, 4, -1, 478), - (478, -1, -1, 477, 477, 2, 64, -1, 0, 0, 4, 477, 479), - (479, -1, -1, 477, 477, 2, 65, -1, 0, 0, 4, 478, 6233), - (480, -1, -1, 480, 480, 2, 63, -1, 0, 0, 4, -1, 481), - (481, -1, -1, 480, 480, 2, 64, -1, 0, 0, 4, 480, 482), - (482, -1, -1, 480, 480, 2, 65, -1, 0, 0, 4, 481, 4921), - (483, -1, -1, 483, 483, 2, 63, -1, 0, 0, 4, -1, 484), - (484, -1, -1, 483, 483, 2, 64, -1, 0, 0, 4, 483, 485), - (485, -1, -1, 483, 483, 2, 65, -1, 0, 0, 4, 484, -1), - (489, -1, -1, 489, 489, 3, 63, -1, 0, 0, 4, -1, 490), - (490, -1, -1, 489, 489, 3, 64, -1, 0, 0, 4, 489, 491), - (491, -1, -1, 489, 489, 3, 65, -1, 0, 0, 4, 490, 7116), - (492, -1, -1, 492, 492, 2, 63, -1, 0, 0, 4, -1, 493), - (493, -1, -1, 492, 492, 2, 64, -1, 0, 0, 4, 492, 494), - (494, -1, -1, 492, 492, 2, 65, -1, 0, 0, 4, 493, 7128), - (495, -1, -1, 495, 495, 2, 63, -1, 0, 0, 4, -1, 496), - (496, -1, -1, 495, 495, 2, 64, -1, 0, 0, 4, 495, 497), - (497, -1, -1, 495, 495, 2, 65, -1, 0, 0, 4, 496, 6260), - (498, -1, -1, 498, 498, 2, 63, -1, 0, 0, 4, -1, 499), - (499, -1, -1, 498, 498, 2, 64, -1, 0, 0, 4, 498, 500), - (500, -1, -1, 498, 498, 2, 65, -1, 0, 0, 4, 499, 886), - (501, -1, -1, 501, 501, 2, 63, -1, 0, 0, 4, -1, 502), - (502, -1, -1, 501, 501, 2, 64, -1, 0, 0, 4, 501, 503), - (503, -1, -1, 501, 501, 2, 65, -1, 0, 0, 4, 502, 6319), - (504, -1, -1, 247, 247, 3, 62, -1, 0, 0, 4, 249, 505), - (505, -1, -1, 247, 247, 3, 63, -1, 0, 0, 4, 504, 506), - (506, -1, -1, 247, 247, 3, 64, -1, 0, 0, 4, 505, -1), - (507, 507, 507, 507, 507, 3, 61, 3252, 9, 180, 4, -1, 508), - (508, 507, 507, 507, 507, 3, 63, 3253, 9, 180, 4, 507, 509), - (509, 507, 507, 507, 507, 3, 65, 3254, 9, 180, 4, 508, -1), - (510, 510, 510, 510, 510, 3, 61, 3255, 37, 240, 4, -1, 511), - (511, 510, 510, 510, 510, 3, 63, 3256, 37, 240, 4, 510, 512), - (512, 510, 510, 510, 510, 3, 65, 3257, 37, 240, 4, 511, 7425), - (513, 513, 513, 513, 513, 3, 61, 3274, 4, 120, 4, -1, 514), - (514, 513, 513, 513, 513, 3, 63, 3275, 4, 120, 4, 513, 515), - (515, 513, 513, 513, 513, 3, 65, 3276, 4, 120, 4, 514, 6095), - (516, 516, 516, 516, 516, 2, 62, 3338, 5, 480, 4, -1, 6398), - (517, 517, 517, 517, 517, 3, 61, 3258, 12, 600, 4, -1, 518), - (518, 517, 517, 517, 517, 3, 63, 3259, 12, 600, 4, 517, 519), - (519, 517, 517, 517, 517, 3, 65, 3260, 12, 600, 4, 518, 1440), - (520, 520, 520, 520, 520, 3, 61, 3265, 6, 540, 4, -1, 521), - (521, 520, 520, 520, 520, 3, 63, 3266, 6, 540, 4, 520, 522), - (522, 520, 520, 520, 520, 3, 65, 3267, 6, 540, 4, 521, 1507), - (523, 523, 523, 523, 523, 5, 61, 3268, 9, 540, 4, -1, 524), - (524, 523, 523, 523, 523, 4, 63, 3269, 9, 540, 4, 523, 525), - (525, 523, 523, 523, 523, 3, 65, 3270, 9, 540, 4, 524, -1), - (526, 526, 526, 526, 526, 5, 62, 3248, 0, 1, 4, -1, 527), - (527, 526, 526, 526, 526, 3, 64, 3249, 0, 1, 4, 526, -1), - (528, 528, 528, 528, 528, 4, 61, 3283, 5, 720, 4, -1, 529), - (529, 528, 528, 528, 528, 3, 63, 3284, 5, 720, 4, 528, 530), - (530, 528, 528, 528, 528, 2, 65, 3285, 5, 720, 4, 529, 900), - (531, 131, 131, 131, 131, 3, 63, 3250, 4, 900, 4, 131, 532), - (532, 131, 131, 131, 131, 6, 64, 3251, 4, 900, 4, 531, 1203), - (533, 155, 155, 155, 155, 6, 64, 3264, 8, 60, 4, 155, 1344), - (534, 534, 534, 534, 534, 3, 61, 3261, 4, 2160, 4, -1, 535), - (535, 534, 534, 534, 534, 3, 63, 3262, 4, 2160, 4, 534, 536), - (536, 534, 534, 534, 534, 3, 65, 3263, 4, 2160, 4, 535, 715), - (537, -1, -1, 537, 537, 3, 63, -1, 0, 0, 4, -1, 538), - (538, -1, -1, 537, 537, 3, 64, -1, 0, 0, 4, 537, -1), - (539, -1, -1, 230, 230, 2, 63, -1, 0, 0, 4, 232, 540), - (540, -1, -1, 230, 230, 4, 64, -1, 0, 0, 4, 539, 541), - (541, -1, -1, 230, 230, 6, 65, -1, 0, 0, 4, 540, 12677), - (542, -1, -1, 255, 255, 2, 63, -1, 0, 0, 4, 257, 543), - (543, -1, -1, 255, 255, 4, 64, -1, 0, 0, 4, 542, 544), - (544, -1, -1, 255, 255, 6, 65, -1, 0, 0, 4, 543, 1163), - (545, 545, 545, 545, 545, 3, 61, 3271, 3, 900, 4, -1, 546), - (546, 545, 545, 545, 545, 3, 63, 3272, 3, 900, 4, 545, 547), - (547, 545, 545, 545, 545, 3, 65, 3273, 3, 900, 4, 546, 1293), - (548, 548, 548, 548, 548, 4, 61, 3277, 5, 900, 4, -1, 549), - (549, 548, 548, 548, 548, 3, 63, 3278, 5, 900, 4, 548, 550), - (550, 548, 548, 548, 548, 2, 65, 3279, 5, 900, 4, 549, 1225), - (551, -1, -1, 551, 551, 2, 61, -1, 0, 0, 4, -1, 552), - (552, -1, -1, 551, 551, 2, 62, -1, 0, 0, 4, 551, 553), - (553, -1, -1, 551, 551, 2, 63, -1, 0, 0, 4, 552, 554), - (554, -1, -1, 551, 551, 2, 64, -1, 0, 0, 4, 553, 555), - (555, -1, -1, 551, 551, 2, 65, -1, 0, 0, 4, 554, 1633), - (556, -1, -1, 556, 556, 2, 61, -1, 0, 0, 4, -1, 557), - (557, -1, -1, 556, 556, 2, 62, -1, 0, 0, 4, 556, 558), - (558, -1, -1, 556, 556, 2, 63, -1, 0, 0, 4, 557, 559), - (559, -1, -1, 556, 556, 2, 64, -1, 0, 0, 4, 558, 560), - (560, -1, -1, 556, 556, 2, 65, -1, 0, 0, 4, 559, 1563), - (561, -1, -1, 561, 561, 2, 61, -1, 0, 0, 4, -1, 562), - (562, -1, -1, 561, 561, 4, 63, -1, 0, 0, 4, 561, 563), - (563, -1, -1, 561, 561, 6, 65, -1, 0, 0, 4, 562, 1624), - (564, -1, -1, 564, 564, 3, 61, -1, 0, 0, 4, -1, 565), - (565, -1, -1, 564, 564, 3, 63, -1, 0, 0, 4, 564, 566), - (566, -1, -1, 564, 564, 3, 65, -1, 0, 0, 4, 565, 1621), - (567, -1, -1, 567, 567, 5, 63, -1, 0, 0, 4, -1, 5061), - (574, -1, -1, 574, 574, 3, 61, -1, 0, 0, 4, -1, 575), - (575, -1, -1, 574, 574, 3, 63, -1, 0, 0, 4, 574, 576), - (576, -1, -1, 574, 574, 3, 65, -1, 0, 0, 4, 575, 7718), - (577, -1, -1, 577, 577, 2, 61, -1, 0, 0, 4, -1, 578), - (578, -1, -1, 577, 577, 4, 63, -1, 0, 0, 4, 577, 579), - (579, -1, -1, 577, 577, 6, 65, -1, 0, 0, 4, 578, -1), - (580, -1, -1, 580, 580, 4, 61, -1, 0, 0, 4, -1, 581), - (581, -1, -1, 580, 580, 3, 63, -1, 0, 0, 4, 580, 582), - (582, -1, -1, 580, 580, 2, 65, -1, 0, 0, 4, 581, -1), - (583, -1, -1, 583, 583, 2, 63, -1, 0, 0, 4, -1, 584), - (584, -1, -1, 583, 583, 2, 64, -1, 0, 0, 4, 583, 585), - (585, -1, -1, 583, 583, 2, 65, -1, 0, 0, 4, 584, -1), - (586, -1, -1, 586, 586, 2, 61, -1, 0, 0, 4, -1, 587), - (587, -1, -1, 586, 586, 4, 63, -1, 0, 0, 4, 586, 588), - (588, -1, -1, 586, 586, 6, 65, -1, 0, 0, 4, 587, 6130), - (589, -1, -1, 589, 589, 3, 61, -1, 0, 0, 4, -1, 590), - (590, -1, -1, 589, 589, 3, 63, -1, 0, 0, 4, 589, 591), - (591, -1, -1, 589, 589, 3, 65, -1, 0, 0, 4, 590, 893), - (592, 592, 592, 592, 592, 6, 63, 3282, 2, 18, 4, -1, 702), - (593, -1, -1, 593, 593, 3, 61, -1, 0, 0, 4, -1, 594), - (594, -1, -1, 593, 593, 3, 63, -1, 0, 0, 4, 593, 595), - (595, -1, -1, 593, 593, 3, 65, -1, 0, 0, 4, 594, 5972), - (596, -1, -1, 596, 596, 2, 61, -1, 0, 0, 4, -1, 597), - (597, -1, -1, 596, 596, 4, 63, -1, 0, 0, 4, 596, 598), - (598, -1, -1, 596, 596, 6, 65, -1, 0, 0, 4, 597, 5973), - (599, -1, -1, 599, 599, 2, 61, -1, 0, 0, 4, -1, 600), - (600, -1, -1, 599, 599, 4, 63, -1, 0, 0, 4, 599, 601), - (601, -1, -1, 599, 599, 6, 65, -1, 0, 0, 4, 600, 1536), - (602, -1, -1, 602, 602, 3, 61, -1, 0, 0, 4, -1, 603), - (603, -1, -1, 602, 602, 3, 63, -1, 0, 0, 4, 602, 604), - (604, -1, -1, 602, 602, 3, 65, -1, 0, 0, 4, 603, 1533), - (605, -1, -1, 605, 605, 6, 63, -1, 0, 0, 4, -1, -1), - (606, -1, -1, 606, 606, 1, 61, -1, 0, 0, 4, -1, 607), - (607, -1, -1, 606, 606, 1, 62, -1, 0, 0, 4, 606, 608), - (608, -1, -1, 606, 606, 1, 63, -1, 0, 0, 4, 607, 609), - (609, -1, -1, 606, 606, 1, 64, -1, 0, 0, 4, 608, 610), - (610, -1, -1, 606, 606, 1, 65, -1, 0, 0, 4, 609, -1), - (611, -1, -1, 611, 611, 2, 61, -1, 0, 0, 4, -1, 612), - (612, -1, -1, 611, 611, 2, 62, -1, 0, 0, 4, 611, 613), - (613, -1, -1, 611, 611, 2, 63, -1, 0, 0, 4, 612, 614), - (614, -1, -1, 611, 611, 2, 64, -1, 0, 0, 4, 613, 615), - (615, -1, -1, 611, 611, 2, 65, -1, 0, 0, 4, 614, 7175), - (616, 616, 616, 616, 616, 5, 63, 3286, 7, 900, 4, -1, 617), - (617, 616, 616, 616, 616, 4, 64, 3287, 7, 900, 4, 616, 618), - (618, 616, 616, 616, 616, 3, 65, 3288, 7, 900, 4, 617, 1248), - (619, 619, 619, 619, 619, 3, 61, 3292, 6, 900, 4, -1, 620), - (620, 619, 619, 619, 619, 2, 63, 3293, 6, 900, 4, 619, 621), - (621, 619, 619, 619, 619, 1, 65, 3294, 6, 900, 4, 620, 721), - (622, -1, -1, 622, 622, 3, 61, -1, 0, 0, 4, -1, 623), - (623, -1, -1, 622, 622, 3, 62, -1, 0, 0, 4, 622, 624), - (624, -1, -1, 622, 622, 3, 63, -1, 0, 0, 4, 623, 8329), - (625, -1, -1, 625, 625, 1, 61, -1, 0, 0, 4, -1, 626), - (626, -1, -1, 625, 625, 2, 63, -1, 0, 0, 4, 625, 627), - (627, -1, -1, 625, 625, 3, 65, -1, 0, 0, 4, 626, 4733), - (628, -1, -1, 628, 628, 2, 62, -1, 0, 0, 4, -1, 629), - (629, -1, -1, 628, 628, 4, 64, -1, 0, 0, 4, 628, -1), - (630, 630, 630, 630, 630, 6, 63, 5243, 7, 1, 4, -1, -1), - (631, -1, -1, 631, 631, 2, 61, -1, 0, 0, 4, -1, 632), - (632, -1, -1, 631, 631, 3, 63, -1, 0, 0, 4, 631, 633), - (633, -1, -1, 631, 631, 4, 65, -1, 0, 0, 4, 632, 1172), - (634, -1, -1, 634, 634, 1, 61, -1, 0, 0, 4, -1, 635), - (635, -1, -1, 634, 634, 2, 63, -1, 0, 0, 4, 634, 636), - (636, -1, -1, 634, 634, 3, 65, -1, 0, 0, 4, 635, 844), - (637, -1, -1, 637, 637, 3, 61, -1, 0, 0, 4, -1, 638), - (638, -1, -1, 637, 637, 6, 63, -1, 0, 0, 4, 637, 639), - (639, -1, -1, 637, 637, 9, 65, -1, 0, 0, 4, 638, 770), - (640, -1, -1, 267, 267, 2, 61, -1, 0, 0, 4, 269, 641), - (641, -1, -1, 267, 267, 4, 63, -1, 0, 0, 4, 640, 642), - (642, -1, -1, 267, 267, 6, 65, -1, 0, 0, 4, 641, 924), - (643, 643, 643, 643, 643, 4, 62, 5227, 0, 1, 4, -1, -1), - (644, -1, -1, 644, 644, 4, 60, -1, 0, 0, 4, -1, 1601), - (645, 645, -1, 645, 645, 4, 64, 3614, 4, 5, 4, -1, 5999), - (649, -1, -1, 649, 649, 2, 61, -1, 0, 0, 4, -1, 650), - (650, -1, -1, 649, 649, 4, 63, -1, 0, 0, 4, 649, 651), - (651, -1, -1, 649, 649, 6, 65, -1, 0, 0, 4, 650, 5860), - (652, -1, -1, 652, 652, 2, 61, -1, 0, 0, 4, -1, 653), - (653, -1, -1, 652, 652, 4, 63, -1, 0, 0, 4, 652, 654), - (654, -1, -1, 652, 652, 6, 65, -1, 0, 0, 4, 653, -1), - (655, -1, -1, 655, 655, 3, 59, -1, 0, 0, 3, -1, 656), - (656, -1, -1, 655, 655, 6, 59, -1, 0, 0, 3, 655, 657), - (657, -1, -1, 655, 655, 9, 59, -1, 0, 0, 3, 656, -1), - (658, -1, -1, 658, 658, 2, 55, -1, 0, 0, 3, -1, 659), - (659, -1, -1, 658, 658, 4, 55, -1, 0, 0, 3, 658, 660), - (660, -1, -1, 658, 658, 6, 55, -1, 0, 0, 3, 659, 5306), - (661, -1, -1, 65, 661, 1, 51, -1, 0, 0, 3, -1, 662), - (662, -1, -1, 65, 661, 1, 51, -1, 0, 0, 3, 661, 663), - (663, -1, -1, 65, 661, 1, 51, -1, 0, 0, 3, 662, 674), - (665, -1, -1, 270, 665, 3, 59, -1, 0, 0, 3, -1, 666), - (666, -1, -1, 270, 665, 6, 59, -1, 0, 0, 3, 665, 667), - (667, -1, -1, 270, 665, 9, 59, -1, 0, 0, 3, 666, 668), - (668, -1, -1, 270, 665, 2, 63, -1, 0, 0, 4, 667, 669), - (669, -1, -1, 270, 665, 2, 64, -1, 0, 0, 4, 668, 670), - (670, -1, -1, 270, 665, 2, 65, -1, 0, 0, 4, 669, 7612), - (671, -1, -1, 671, 671, 3, 59, -1, 0, 0, 3, -1, -1), - (672, -1, -1, 62, 62, 5, 61, -1, 0, 0, 7, 64, 673), - (673, -1, -1, 62, 62, 5, 61, -1, 0, 0, 7, 672, -1), - (674, -1, -1, 65, 661, 3, 61, -1, 0, 0, 7, 663, 675), - (675, -1, -1, 65, 661, 3, 61, -1, 0, 0, 7, 674, 1031), - (676, -1, -1, 71, 71, 2, 61, -1, 0, 0, 7, 73, 677), - (677, -1, -1, 71, 71, 3, 61, -1, 0, 0, 7, 676, 978), - (678, -1, -1, 678, 678, 3, 61, -1, 0, 0, 7, -1, 679), - (679, -1, -1, 678, 678, 3, 61, -1, 0, 0, 7, 678, 680), - (680, -1, -1, 678, 678, 3, 61, -1, 0, 0, 7, 679, 681), - (681, -1, -1, 678, 678, 3, 61, -1, 0, 0, 7, 680, 682), - (682, -1, -1, 678, 678, 3, 61, -1, 0, 0, 7, 681, 6518), - (683, -1, -1, 683, 683, 3, 61, -1, 0, 0, 7, -1, 684), - (684, -1, -1, 683, 683, 6, 61, -1, 0, 0, 7, 683, 685), - (685, -1, -1, 683, 683, 9, 61, -1, 0, 0, 7, 684, 1036), - (686, -1, -1, 686, 686, 5, 55, -1, 0, 0, 7, -1, 687), - (687, -1, -1, 686, 686, 5, 55, -1, 0, 0, 7, 686, 688), - (688, -1, -1, 686, 686, 5, 55, -1, 0, 0, 7, 687, 689), - (689, -1, -1, 686, 686, 5, 55, -1, 0, 0, 7, 688, 690), - (690, -1, -1, 686, 686, 5, 55, -1, 0, 0, 7, 689, 7640), - (691, -1, -1, 691, 691, 9, 55, -1, 0, 0, 7, -1, -1), - (692, -1, -1, 692, 692, 3, 55, -1, 0, 0, 7, -1, 693), - (693, -1, -1, 692, 692, 6, 55, -1, 0, 0, 7, 692, 694), - (694, -1, -1, 692, 692, 9, 55, -1, 0, 0, 7, 693, 7647), - (695, -1, -1, 695, 695, 4, 65, -1, 0, 0, 7, -1, 696), - (696, -1, -1, 695, 695, 4, 65, -1, 0, 0, 7, 695, 697), - (697, -1, -1, 695, 695, 4, 65, -1, 0, 0, 7, 696, 698), - (698, -1, -1, 695, 695, 4, 65, -1, 0, 0, 7, 697, 699), - (699, -1, -1, 695, 695, 4, 65, -1, 0, 0, 7, 698, 15529), - (700, -1, -1, 213, 213, 9, 61, -1, 0, 0, 7, 215, -1), - (701, -1, -1, 275, 275, 9, 61, -1, 0, 0, 7, 277, -1), - (702, 592, 592, 592, 592, 3, 65, 4842, 2, 18, 7, 592, 703), - (703, 592, 592, 592, 592, 3, 65, 4843, 2, 18, 7, 702, 704), - (704, 592, 592, 592, 592, 3, 65, 4844, 2, 18, 7, 703, 705), - (705, 592, 592, 592, 592, 3, 65, 4845, 2, 18, 7, 704, 706), - (706, 592, 592, 592, 592, 3, 65, 4846, 2, 18, 7, 705, 1102), - (715, 534, 534, 534, 534, 3, 65, 5112, 4, 2160, 7, 536, 716), - (716, 534, 534, 534, 534, 6, 65, 5113, 4, 2160, 7, 715, 717), - (717, 534, 534, 534, 534, 9, 65, 5114, 4, 2160, 7, 716, 1278), - (718, 718, 718, 718, 718, 3, 65, 4521, 7, 4320, 7, -1, 719), - (719, 718, 718, 718, 718, 6, 65, 4522, 7, 4320, 7, 718, 720), - (720, 718, 718, 718, 718, 9, 65, 4523, 7, 4320, 7, 719, 1019), - (721, 619, 619, 619, 619, 5, 65, 5110, 6, 900, 7, 621, 722), - (722, 619, 619, 619, 619, 5, 65, 5111, 6, 900, 7, 721, 6296), - (723, 723, 723, 723, 723, 9, 65, 4788, 6, 30, 7, -1, 4963), - (724, -1, -1, 724, 724, 3, 65, -1, 0, 0, 7, -1, 725), - (725, -1, -1, 724, 724, 3, 65, -1, 0, 0, 7, 724, 726), - (726, -1, -1, 724, 724, 3, 65, -1, 0, 0, 7, 725, 727), - (727, -1, -1, 724, 724, 3, 65, -1, 0, 0, 7, 726, 728), - (728, -1, -1, 724, 724, 3, 65, -1, 0, 0, 7, 727, 5254), - (729, -1, -1, 729, 729, 5, 65, -1, 0, 0, 7, -1, 730), - (730, -1, -1, 729, 729, 5, 65, -1, 0, 0, 7, 729, 731), - (731, -1, -1, 729, 729, 5, 65, -1, 0, 0, 7, 730, 732), - (732, -1, -1, 729, 729, 5, 65, -1, 0, 0, 7, 731, 733), - (733, -1, -1, 729, 729, 5, 65, -1, 0, 0, 7, 732, 1467), - (734, -1, -1, 734, 734, 12, 65, -1, 0, 0, 7, -1, -1), - (735, -1, -1, 735, 735, 3, 62, -1, 0, 0, 7, -1, 736), - (736, -1, -1, 735, 735, 3, 62, -1, 0, 0, 7, 735, 737), - (737, -1, -1, 735, 735, 3, 62, -1, 0, 0, 7, 736, 7056), - (738, -1, -1, 98, 738, 3, 55, -1, 0, 0, 7, -1, 739), - (739, -1, -1, 98, 738, 6, 55, -1, 0, 0, 7, 738, 740), - (740, -1, -1, 98, 738, 9, 55, -1, 0, 0, 7, 739, 5317), - (746, 746, 746, 746, 746, 3, 65, 4549, 10, 2160, 7, -1, 747), - (747, 746, 746, 746, 746, 6, 65, 4550, 10, 2160, 7, 746, 748), - (748, 746, 746, 746, 746, 9, 65, 4551, 10, 2160, 7, 747, 1491), - (749, 749, 749, 749, 749, 5, 65, 4790, 11, 1800, 7, -1, 750), - (750, 749, 749, 749, 749, 5, 65, 4791, 11, 1800, 7, 749, 751), - (751, 749, 749, 749, 749, 5, 65, 4792, 11, 1800, 7, 750, 752), - (752, 749, 749, 749, 749, 5, 65, 4793, 11, 1800, 7, 751, 753), - (753, 749, 749, 749, 749, 5, 65, 4794, 11, 1800, 7, 752, 1206), - (754, -1, -1, 754, 754, 3, 65, -1, 0, 0, 7, -1, 755), - (755, -1, -1, 754, 754, 6, 65, -1, 0, 0, 7, 754, 756), - (756, -1, -1, 754, 754, 9, 65, -1, 0, 0, 7, 755, 7659), - (757, 757, -1, 757, 757, 5, 65, 4796, 6, 1800, 7, -1, 758), - (758, 757, -1, 757, 757, 5, 65, 4797, 6, 1800, 7, 757, 759), - (759, 757, -1, 757, 757, 5, 65, 4798, 6, 1800, 7, 758, 760), - (760, 757, -1, 757, 757, 5, 65, 4799, 6, 1800, 7, 759, 761), - (761, 757, -1, 757, 757, 5, 65, 4800, 6, 1800, 7, 760, 1222), - (762, -1, -1, 762, 762, 4, 65, -1, 0, 0, 7, -1, 763), - (763, -1, -1, 762, 762, 4, 65, -1, 0, 0, 7, 762, 764), - (764, -1, -1, 762, 762, 4, 65, -1, 0, 0, 7, 763, 765), - (765, -1, -1, 762, 762, 4, 65, -1, 0, 0, 7, 764, 766), - (766, -1, -1, 762, 762, 4, 65, -1, 0, 0, 7, 765, -1), - (767, -1, -1, 767, 767, 3, 65, -1, 0, 0, 7, -1, 768), - (768, -1, -1, 767, 767, 6, 65, -1, 0, 0, 7, 767, 769), - (769, -1, -1, 767, 767, 9, 65, -1, 0, 0, 7, 768, 1099), - (770, -1, -1, 637, 637, 3, 65, -1, 0, 0, 7, 639, 771), - (771, -1, -1, 637, 637, 6, 65, -1, 0, 0, 7, 770, 772), - (772, -1, -1, 637, 637, 9, 65, -1, 0, 0, 7, 771, 4749), - (773, 773, -1, 773, 773, 3, 65, 4552, 5, 1800, 7, -1, 774), - (774, 773, -1, 773, 773, 6, 65, 4553, 5, 1800, 7, 773, 775), - (775, 773, -1, 773, 773, 9, 65, 4554, 5, 1800, 7, 774, 5854), - (776, -1, -1, 776, 776, 3, 65, -1, 0, 0, 7, -1, 777), - (777, -1, -1, 776, 776, 3, 65, -1, 0, 0, 7, 776, 778), - (778, -1, -1, 776, 776, 3, 65, -1, 0, 0, 7, 777, 779), - (779, -1, -1, 776, 776, 3, 65, -1, 0, 0, 7, 778, 780), - (780, -1, -1, 776, 776, 3, 65, -1, 0, 0, 7, 779, -1), - (781, -1, -1, 781, 781, 12, 65, -1, 0, 0, 7, -1, 5850), - (782, -1, -1, 782, 782, 3, 65, -1, 0, 0, 7, -1, 783), - (783, -1, -1, 782, 782, 6, 65, -1, 0, 0, 7, 782, 784), - (784, -1, -1, 782, 782, 9, 65, -1, 0, 0, 7, 783, -1), - (785, 785, 785, 785, 785, 5, 65, 5235, 8, 900, 7, -1, 786), - (786, 785, 785, 785, 785, 5, 65, 5236, 8, 900, 7, 785, 787), - (787, 785, 785, 785, 785, 5, 65, 5237, 8, 900, 7, 786, 788), - (788, 785, 785, 785, 785, 5, 65, 5238, 8, 900, 7, 787, 789), - (789, 785, 785, 785, 785, 5, 65, 5239, 8, 900, 7, 788, 15235), - (790, -1, -1, 790, 790, 3, 65, -1, 0, 0, 7, -1, 791), - (791, -1, -1, 790, 790, 3, 65, -1, 0, 0, 7, 790, 792), - (792, -1, -1, 790, 790, 3, 65, -1, 0, 0, 7, 791, 793), - (793, -1, -1, 790, 790, 3, 65, -1, 0, 0, 7, 792, 794), - (794, -1, -1, 790, 790, 3, 65, -1, 0, 0, 7, 793, 5259), - (795, -1, -1, 795, 795, 5, 65, -1, 0, 0, 7, -1, 796), - (796, -1, -1, 795, 795, 5, 65, -1, 0, 0, 7, 795, 797), - (797, -1, -1, 795, 795, 5, 65, -1, 0, 0, 7, 796, 798), - (798, -1, -1, 795, 795, 5, 65, -1, 0, 0, 7, 797, 799), - (799, -1, -1, 795, 795, 5, 65, -1, 0, 0, 7, 798, 1430), - (800, -1, -1, 800, 800, 3, 65, -1, 0, 0, 7, -1, 801), - (801, -1, -1, 800, 800, 6, 65, -1, 0, 0, 7, 800, 802), - (802, -1, -1, 800, 800, 9, 65, -1, 0, 0, 7, 801, -1), - (803, -1, -1, 803, 803, 3, 65, -1, 0, 0, 7, -1, 804), - (804, -1, -1, 803, 803, 6, 65, -1, 0, 0, 7, 803, 805), - (805, -1, -1, 803, 803, 9, 65, -1, 0, 0, 7, 804, -1), - (806, -1, -1, 806, 806, 12, 65, -1, 0, 0, 7, -1, -1), - (807, -1, -1, 807, 807, 3, 65, -1, 0, 0, 7, -1, 808), - (808, -1, -1, 807, 807, 6, 65, -1, 0, 0, 7, 807, 809), - (809, -1, -1, 807, 807, 9, 65, -1, 0, 0, 7, 808, 1268), - (810, -1, -1, 810, 810, 5, 65, -1, 0, 0, 7, -1, 811), - (811, -1, -1, 810, 810, 5, 65, -1, 0, 0, 7, 810, 812), - (812, -1, -1, 810, 810, 5, 65, -1, 0, 0, 7, 811, 813), - (813, -1, -1, 810, 810, 5, 65, -1, 0, 0, 7, 812, 814), - (814, -1, -1, 810, 810, 5, 65, -1, 0, 0, 7, 813, 4824), - (815, -1, -1, 815, 815, 4, 65, -1, 0, 0, 7, -1, 816), - (816, -1, -1, 815, 815, 4, 65, -1, 0, 0, 7, 815, 817), - (817, -1, -1, 815, 815, 4, 65, -1, 0, 0, 7, 816, 818), - (818, -1, -1, 815, 815, 4, 65, -1, 0, 0, 7, 817, 819), - (819, -1, -1, 815, 815, 4, 65, -1, 0, 0, 7, 818, 5141), - (820, -1, -1, 820, 820, 3, 65, -1, 0, 0, 7, -1, 821), - (821, -1, -1, 820, 820, 6, 65, -1, 0, 0, 7, 820, 822), - (822, -1, -1, 820, 820, 9, 65, -1, 0, 0, 7, 821, 1265), - (823, -1, -1, 823, 823, 5, 65, -1, 0, 0, 7, -1, 824), - (824, -1, -1, 823, 823, 5, 65, -1, 0, 0, 7, 823, 825), - (825, -1, -1, 823, 823, 5, 65, -1, 0, 0, 7, 824, 826), - (826, -1, -1, 823, 823, 5, 65, -1, 0, 0, 7, 825, 827), - (827, -1, -1, 823, 823, 5, 65, -1, 0, 0, 7, 826, -1), - (828, 828, 828, 828, 828, 3, 65, 5240, 2, 3600, 7, -1, 829), - (829, 828, 828, 828, 828, 6, 65, 5241, 2, 3600, 7, 828, 830), - (830, 828, 828, 828, 828, 9, 65, 5242, 2, 3600, 7, 829, 16250), - (834, -1, -1, 834, 834, 3, 65, -1, 0, 0, 7, -1, 835), - (835, -1, -1, 834, 834, 3, 65, -1, 0, 0, 7, 834, 836), - (836, -1, -1, 834, 834, 3, 65, -1, 0, 0, 7, 835, 837), - (837, -1, -1, 834, 834, 3, 65, -1, 0, 0, 7, 836, 838), - (838, -1, -1, 834, 834, 3, 65, -1, 0, 0, 7, 837, -1), - (839, -1, -1, 839, 839, 5, 65, -1, 0, 0, 7, -1, 840), - (840, -1, -1, 839, 839, 5, 65, -1, 0, 0, 7, 839, 841), - (841, -1, -1, 839, 839, 5, 65, -1, 0, 0, 7, 840, 842), - (842, -1, -1, 839, 839, 5, 65, -1, 0, 0, 7, 841, 843), - (843, -1, -1, 839, 839, 5, 65, -1, 0, 0, 7, 842, 5325), - (844, -1, -1, 634, 634, 5, 65, -1, 0, 0, 7, 636, 845), - (845, -1, -1, 634, 634, 5, 65, -1, 0, 0, 7, 844, 1319), - (846, -1, -1, 846, 846, 3, 65, -1, 0, 0, 7, -1, 847), - (847, -1, -1, 846, 846, 6, 65, -1, 0, 0, 7, 846, 848), - (848, -1, -1, 846, 846, 9, 65, -1, 0, 0, 7, 847, 1301), - (849, -1, -1, 849, 849, 3, 65, -1, 0, 0, 7, -1, 850), - (850, -1, -1, 849, 849, 6, 65, -1, 0, 0, 7, 849, 851), - (851, -1, -1, 849, 849, 9, 65, -1, 0, 0, 7, 850, 10621), - (852, -1, -1, 852, 852, 5, 65, -1, 0, 0, 7, -1, 853), - (853, -1, -1, 852, 852, 5, 65, -1, 0, 0, 7, 852, 854), - (854, -1, -1, 852, 852, 5, 65, -1, 0, 0, 7, 853, 5500), - (855, -1, -1, 855, 855, 5, 65, -1, 0, 0, 7, -1, 856), - (856, -1, -1, 855, 855, 5, 65, -1, 0, 0, 7, 855, 857), - (857, -1, -1, 855, 855, 5, 65, -1, 0, 0, 7, 856, 858), - (858, -1, -1, 855, 855, 5, 65, -1, 0, 0, 7, 857, 859), - (859, -1, -1, 855, 855, 5, 65, -1, 0, 0, 7, 858, 7673), - (860, 860, 860, 860, 860, 3, 65, 3297, 5, 180, 7, -1, 861), - (861, 860, 860, 860, 860, 6, 65, 3298, 5, 180, 7, 860, 862), - (862, 860, 860, 860, 860, 9, 65, 3299, 5, 180, 7, 861, 5130), - (863, 863, -1, 863, 863, 12, 65, 5248, 6, 4320, 7, -1, -1), - (864, -1, -1, 864, 864, 3, 65, -1, 0, 0, 7, -1, 865), - (865, -1, -1, 864, 864, 6, 65, -1, 0, 0, 7, 864, 866), - (866, -1, -1, 864, 864, 9, 65, -1, 0, 0, 7, 865, 1290), - (867, -1, -1, 867, 867, 5, 65, -1, 0, 0, 7, -1, 868), - (868, -1, -1, 867, 867, 5, 65, -1, 0, 0, 7, 867, 869), - (869, -1, -1, 867, 867, 5, 65, -1, 0, 0, 7, 868, 870), - (870, -1, -1, 867, 867, 5, 65, -1, 0, 0, 7, 869, 871), - (871, -1, -1, 867, 867, 5, 65, -1, 0, 0, 7, 870, 7362), - (872, 872, 872, 872, 872, 3, 65, 4802, 5, 180, 7, -1, 873), - (873, 872, 872, 872, 872, 6, 65, 4803, 5, 180, 7, 872, 874), - (874, 872, 872, 872, 872, 9, 65, 4804, 5, 180, 7, 873, 7367), - (875, 875, 875, 875, 875, 3, 65, 4805, 5, 180, 7, -1, 876), - (876, 875, 875, 875, 875, 6, 65, 4806, 5, 180, 7, 875, 877), - (877, 875, 875, 875, 875, 9, 65, 4807, 5, 180, 7, 876, 7370), - (878, -1, -1, 878, 878, 3, 65, -1, 0, 0, 7, -1, 879), - (879, -1, -1, 878, 878, 6, 65, -1, 0, 0, 7, 878, 880), - (880, -1, -1, 878, 878, 9, 65, -1, 0, 0, 7, 879, 1539), - (881, -1, -1, 881, 881, 3, 65, -1, 0, 0, 7, -1, 882), - (882, -1, -1, 881, 881, 3, 65, -1, 0, 0, 7, 881, 883), - (883, -1, -1, 881, 881, 3, 65, -1, 0, 0, 7, 882, 884), - (884, -1, -1, 881, 881, 3, 65, -1, 0, 0, 7, 883, 885), - (885, -1, -1, 881, 881, 3, 65, -1, 0, 0, 7, 884, -1), - (886, -1, -1, 498, 498, 5, 65, -1, 0, 0, 7, 500, 887), - (887, -1, -1, 498, 498, 5, 65, -1, 0, 0, 7, 886, 975), - (888, -1, -1, 888, 888, 3, 65, -1, 0, 0, 7, -1, 889), - (889, -1, -1, 888, 888, 3, 65, -1, 0, 0, 7, 888, 890), - (890, -1, -1, 888, 888, 3, 65, -1, 0, 0, 7, 889, 891), - (891, -1, -1, 888, 888, 3, 65, -1, 0, 0, 7, 890, 892), - (892, -1, -1, 888, 888, 3, 65, -1, 0, 0, 7, 891, 16267), - (893, -1, -1, 589, 589, 5, 65, -1, 0, 0, 7, 591, 894), - (894, -1, -1, 589, 589, 5, 65, -1, 0, 0, 7, 893, 5270), - (895, -1, -1, 895, 895, 5, 65, -1, 0, 0, 7, -1, 896), - (896, -1, -1, 895, 895, 5, 65, -1, 0, 0, 7, 895, 897), - (897, -1, -1, 895, 895, 5, 65, -1, 0, 0, 7, 896, 898), - (898, -1, -1, 895, 895, 5, 65, -1, 0, 0, 7, 897, 899), - (899, -1, -1, 895, 895, 5, 65, -1, 0, 0, 7, 898, 6075), - (900, 528, 528, 528, 528, 5, 65, 4826, 5, 720, 7, 530, 901), - (901, 528, 528, 528, 528, 5, 65, 4827, 5, 720, 7, 900, 6103), - (907, -1, -1, 907, 907, 5, 65, -1, 0, 0, 7, -1, 908), - (908, -1, -1, 907, 907, 5, 65, -1, 0, 0, 7, 907, 909), - (909, -1, -1, 907, 907, 5, 65, -1, 0, 0, 7, 908, 910), - (910, -1, -1, 907, 907, 5, 65, -1, 0, 0, 7, 909, 911), - (911, -1, -1, 907, 907, 5, 65, -1, 0, 0, 7, 910, 5243), - (912, 912, 912, 912, 912, 3, 65, 4925, 4, 3600, 7, -1, 913), - (913, 912, 912, 912, 912, 6, 65, 4926, 4, 3600, 7, 912, 914), - (914, 912, 912, 912, 912, 9, 65, 4927, 4, 3600, 7, 913, 1330), - (915, -1, -1, 915, 915, 3, 65, -1, 0, 0, 7, -1, 916), - (916, -1, -1, 915, 915, 6, 65, -1, 0, 0, 7, 915, 917), - (917, -1, -1, 915, 915, 9, 65, -1, 0, 0, 7, 916, -1), - (918, -1, -1, 918, 918, 3, 65, -1, 0, 0, 7, -1, 919), - (919, -1, -1, 918, 918, 6, 65, -1, 0, 0, 7, 918, 920), - (920, -1, -1, 918, 918, 9, 65, -1, 0, 0, 7, 919, -1), - (921, 921, 921, 921, 921, 12, 65, 4833, 8, 60, 7, -1, 1340), - (922, 922, 922, 922, 922, 12, 65, 4834, 8, 60, 7, -1, 1341), - (923, 923, 923, 923, 923, 12, 65, 4835, 8, 60, 7, -1, 1342), - (924, -1, -1, 267, 267, 5, 65, -1, 0, 0, 7, 642, 925), - (925, -1, -1, 267, 267, 5, 65, -1, 0, 0, 7, 924, 5133), - (926, 926, 926, 926, 926, 3, 65, 4836, 12, 1800, 7, -1, 927), - (927, 926, 926, 926, 926, 3, 65, 4837, 12, 1800, 7, 926, 928), - (928, 926, 926, 926, 926, 3, 65, 4838, 12, 1800, 7, 927, 929), - (929, 926, 926, 926, 926, 3, 65, 4839, 12, 1800, 7, 928, 930), - (930, 926, 926, 926, 926, 3, 65, 4840, 12, 1800, 7, 929, 14991), - (931, 931, 931, 931, 931, 3, 65, 5245, 13, 4320, 7, -1, 932), - (932, 931, 931, 931, 931, 6, 65, 5246, 13, 4320, 7, 931, 933), - (933, 931, 931, 931, 931, 9, 65, 5247, 13, 4320, 7, 932, -1), - (934, -1, -1, 113, 934, 2, 55, -1, 0, 0, 3, -1, 935), - (935, -1, -1, 113, 934, 4, 55, -1, 0, 0, 3, 934, 936), - (936, -1, -1, 113, 934, 6, 55, -1, 0, 0, 3, 935, 943), - (937, -1, -1, 113, 937, 2, 55, -1, 0, 0, 3, -1, 938), - (938, -1, -1, 113, 937, 4, 55, -1, 0, 0, 3, 937, 939), - (939, -1, -1, 113, 937, 6, 55, -1, 0, 0, 3, 938, 946), - (940, -1, -1, 113, 940, 2, 55, -1, 0, 0, 3, -1, 941), - (941, -1, -1, 113, 940, 4, 55, -1, 0, 0, 3, 940, 942), - (942, -1, -1, 113, 940, 6, 55, -1, 0, 0, 3, 941, 949), - (943, -1, -1, 113, 934, 3, 62, -1, 0, 0, 4, 936, 944), - (944, -1, -1, 113, 934, 3, 63, -1, 0, 0, 4, 943, 945), - (945, -1, -1, 113, 934, 3, 64, -1, 0, 0, 4, 944, -1), - (946, -1, -1, 113, 937, 3, 62, -1, 0, 0, 4, 939, 947), - (947, -1, -1, 113, 937, 3, 63, -1, 0, 0, 4, 946, 948), - (948, -1, -1, 113, 937, 3, 64, -1, 0, 0, 4, 947, -1), - (949, -1, -1, 113, 940, 3, 62, -1, 0, 0, 4, 942, 950), - (950, -1, -1, 113, 940, 3, 63, -1, 0, 0, 4, 949, 951), - (951, -1, -1, 113, 940, 3, 64, -1, 0, 0, 4, 950, -1), - (952, -1, -1, 952, 952, 3, 61, -1, 0, 0, 4, -1, 953), - (953, -1, -1, 952, 952, 3, 63, -1, 0, 0, 4, 952, 954), - (954, -1, -1, 952, 952, 3, 65, -1, 0, 0, 4, 953, -1), - (955, -1, -1, 955, 955, 3, 61, -1, 0, 0, 4, -1, 956), - (956, -1, -1, 955, 955, 3, 62, -1, 0, 0, 4, 955, 957), - (957, -1, -1, 955, 955, 3, 63, -1, 0, 0, 4, 956, 958), - (958, -1, -1, 955, 955, 3, 64, -1, 0, 0, 4, 957, 959), - (959, -1, -1, 955, 955, 3, 65, -1, 0, 0, 4, 958, -1), - (960, 960, 960, 960, 960, 9, 59, 2760, 7, 4320, 3, -1, -1), - (961, 961, 961, 961, 961, 9, 59, 2759, 11, 4320, 3, -1, -1), - (962, -1, -1, 962, 962, 5, 65, -1, 0, 0, 7, -1, 963), - (963, -1, -1, 962, 962, 5, 65, -1, 0, 0, 7, 962, 964), - (964, -1, -1, 962, 962, 5, 65, -1, 0, 0, 7, 963, 965), - (965, -1, -1, 962, 962, 5, 65, -1, 0, 0, 7, 964, 966), - (966, -1, -1, 962, 962, 5, 65, -1, 0, 0, 7, 965, 6223), - (967, 967, 967, 967, 967, 3, 65, 4564, 10, 1800, 7, -1, 968), - (968, 967, 967, 967, 967, 6, 65, 4565, 10, 1800, 7, 967, 969), - (969, 967, 967, 967, 967, 9, 65, 4566, 10, 1800, 7, 968, 6464), - (970, 970, 970, 970, 970, 5, 65, 4828, 6, 1800, 7, -1, 971), - (971, 970, 970, 970, 970, 5, 65, 4829, 6, 1800, 7, 970, 972), - (972, 970, 970, 970, 970, 5, 65, 4830, 6, 1800, 7, 971, 973), - (973, 970, 970, 970, 970, 5, 65, 4831, 6, 1800, 7, 972, 974), - (974, 970, 970, 970, 970, 5, 65, 4832, 6, 1800, 7, 973, 1324), - (975, -1, -1, 498, 498, 5, 65, -1, 0, 0, 15, 887, 13262), - (976, -1, -1, 976, 976, 5, 59, -1, 0, 0, 15, -1, -1), - (977, 977, 977, 977, 977, 6, 64, 13835, 72, 600, 15, -1, -1), - (978, -1, -1, 71, 71, 5, 68, -1, 0, 0, 8, 677, -1), - (979, -1, -1, 979, 979, 3, 59, -1, 0, 0, 8, -1, 980), - (980, -1, -1, 979, 979, 6, 59, -1, 0, 0, 8, 979, 981), - (981, -1, -1, 979, 979, 9, 59, -1, 0, 0, 8, 980, -1), - (982, -1, -1, 982, 982, 3, 59, -1, 0, 0, 8, -1, 983), - (983, -1, -1, 982, 982, 6, 59, -1, 0, 0, 8, 982, 984), - (984, -1, -1, 982, 982, 9, 59, -1, 0, 0, 8, 983, -1), - (985, -1, -1, 985, 985, 3, 59, -1, 0, 0, 8, -1, 986), - (986, -1, -1, 985, 985, 6, 59, -1, 0, 0, 8, 985, 987), - (987, -1, -1, 985, 985, 9, 59, -1, 0, 0, 8, 986, -1), - (988, -1, -1, 988, 988, 3, 59, -1, 0, 0, 8, -1, 989), - (989, -1, -1, 988, 988, 6, 59, -1, 0, 0, 8, 988, 990), - (990, -1, -1, 988, 988, 9, 59, -1, 0, 0, 8, 989, -1), - (991, -1, -1, 991, 991, 3, 59, -1, 0, 0, 8, -1, 992), - (992, -1, -1, 991, 991, 6, 59, -1, 0, 0, 8, 991, 993), - (993, -1, -1, 991, 991, 9, 59, -1, 0, 0, 8, 992, -1), - (994, -1, -1, 994, 994, 3, 59, -1, 0, 0, 8, -1, 995), - (995, -1, -1, 994, 994, 6, 59, -1, 0, 0, 8, 994, 996), - (996, -1, -1, 994, 994, 9, 59, -1, 0, 0, 8, 995, -1), - (997, -1, -1, 997, 997, 5, 60, -1, 0, 0, 8, -1, 998), - (998, -1, -1, 997, 997, 5, 65, -1, 0, 0, 8, 997, 999), - (999, -1, -1, 997, 997, 5, 70, -1, 0, 0, 8, 998, 1113), - (1000, 1000, -1, 1000, 1000, 0, 5, 5824, 20, 1080, 0, -1, -1), - (1001, -1, -1, 418, 418, 5, 66, -1, 0, 0, 8, 422, 1002), - (1002, -1, -1, 418, 418, 5, 67, -1, 0, 0, 8, 1001, 1003), - (1003, -1, -1, 418, 418, 5, 68, -1, 0, 0, 8, 1002, 1004), - (1004, -1, -1, 418, 418, 5, 69, -1, 0, 0, 8, 1003, 1005), - (1005, -1, -1, 418, 418, 5, 70, -1, 0, 0, 8, 1004, 4678), - (1006, -1, -1, 1006, 1006, 5, 66, -1, 0, 0, 8, -1, 1007), - (1007, -1, -1, 1006, 1006, 5, 67, -1, 0, 0, 8, 1006, 1008), - (1008, -1, -1, 1006, 1006, 5, 68, -1, 0, 0, 8, 1007, 1009), - (1009, -1, -1, 1006, 1006, 5, 69, -1, 0, 0, 8, 1008, 1010), - (1010, -1, -1, 1006, 1006, 5, 70, -1, 0, 0, 8, 1009, 7516), - (1011, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, -1, 1012), - (1012, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, 1011, 1013), - (1013, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, 1012, 1014), - (1014, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, 1013, 1015), - (1015, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, 1014, 1016), - (1016, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, 1015, -1), - (1017, 1017, 1017, 1017, 1017, 6, 59, 16531, 75, 15, 15, -1, 13726), - (1018, 1018, 1018, 1018, 1018, 2, 63, 16455, 69, 1, 15, -1, -1), - (1019, 718, 718, 718, 718, 12, 65, 21746, 7, 4320, 16, 720, 13454), - (1021, -1, -1, 1021, 1021, 5, 51, -1, 0, 0, 8, -1, 1022), - (1022, -1, -1, 1021, 1021, 5, 55, -1, 0, 0, 8, 1021, 1023), - (1023, -1, -1, 1021, 1021, 5, 60, -1, 0, 0, 8, 1022, 1024), - (1024, -1, -1, 1021, 1021, 5, 65, -1, 0, 0, 8, 1023, 1025), - (1025, -1, -1, 1021, 1021, 5, 70, -1, 0, 0, 8, 1024, 6521), - (1026, -1, -1, 1026, 1026, 3, 66, -1, 0, 0, 8, -1, 1027), - (1027, -1, -1, 1026, 1026, 3, 67, -1, 0, 0, 8, 1026, 1028), - (1028, -1, -1, 1026, 1026, 3, 68, -1, 0, 0, 8, 1027, 1029), - (1029, -1, -1, 1026, 1026, 3, 69, -1, 0, 0, 8, 1028, 1030), - (1030, -1, -1, 1026, 1026, 3, 70, -1, 0, 0, 8, 1029, 1389), - (1031, -1, -1, 65, 661, 3, 66, -1, 0, 0, 8, 675, 1032), - (1032, -1, -1, 65, 661, 3, 67, -1, 0, 0, 8, 1031, 1033), - (1033, -1, -1, 65, 661, 3, 68, -1, 0, 0, 8, 1032, 1034), - (1034, -1, -1, 65, 661, 3, 69, -1, 0, 0, 8, 1033, 1035), - (1035, -1, -1, 65, 661, 3, 70, -1, 0, 0, 8, 1034, 4693), - (1036, -1, -1, 683, 683, 5, 66, -1, 0, 0, 8, 685, 1037), - (1037, -1, -1, 683, 683, 5, 68, -1, 0, 0, 8, 1036, 1038), - (1038, -1, -1, 683, 683, 5, 70, -1, 0, 0, 8, 1037, 5301), - (1041, -1, -1, 1041, 1041, 3, 67, -1, 0, 0, 8, -1, 1042), - (1042, -1, -1, 1041, 1041, 6, 68, -1, 0, 0, 8, 1041, 1043), - (1043, -1, -1, 1041, 1041, 9, 69, -1, 0, 0, 8, 1042, 4707), - (1044, -1, -1, 1044, 1044, 3, 67, -1, 0, 0, 8, -1, 1045), - (1045, -1, -1, 1044, 1044, 6, 68, -1, 0, 0, 8, 1044, 1046), - (1046, -1, -1, 1044, 1044, 9, 69, -1, 0, 0, 8, 1045, 4710), - (1047, -1, -1, 1047, 1047, 3, 67, -1, 0, 0, 8, -1, 1048), - (1048, -1, -1, 1047, 1047, 6, 68, -1, 0, 0, 8, 1047, 1049), - (1049, -1, -1, 1047, 1047, 9, 69, -1, 0, 0, 8, 1048, 4713), - (1050, -1, -1, 1050, 1050, 3, 67, -1, 0, 0, 8, -1, 1051), - (1051, -1, -1, 1050, 1050, 6, 68, -1, 0, 0, 8, 1050, 1052), - (1052, -1, -1, 1050, 1050, 9, 69, -1, 0, 0, 8, 1051, 4716), - (1053, -1, -1, 119, 119, 3, 66, -1, 0, 0, 8, 442, 1054), - (1054, -1, -1, 119, 119, 3, 68, -1, 0, 0, 8, 1053, 1055), - (1055, -1, -1, 119, 119, 3, 70, -1, 0, 0, 8, 1054, 4722), - (1056, -1, -1, 1056, 1056, 5, 71, -1, 0, 0, 12, -1, 1057), - (1057, -1, -1, 1056, 1056, 5, 72, -1, 0, 0, 12, 1056, 1058), - (1058, -1, -1, 1056, 1056, 5, 73, -1, 0, 0, 12, 1057, 1059), - (1059, -1, -1, 1056, 1056, 5, 74, -1, 0, 0, 12, 1058, 1060), - (1060, -1, -1, 1056, 1056, 5, 75, -1, 0, 0, 12, 1059, 6431), - (1061, -1, -1, 125, 125, 5, 66, -1, 0, 0, 8, 453, 1062), - (1062, -1, -1, 125, 125, 5, 67, -1, 0, 0, 8, 1061, 1063), - (1063, -1, -1, 125, 125, 5, 68, -1, 0, 0, 8, 1062, 1064), - (1064, -1, -1, 125, 125, 5, 69, -1, 0, 0, 8, 1063, 1065), - (1065, -1, -1, 125, 125, 5, 70, -1, 0, 0, 8, 1064, 1394), - (1066, -1, -1, 122, 122, 5, 66, -1, 0, 0, 8, 458, 1067), - (1067, -1, -1, 122, 122, 5, 67, -1, 0, 0, 8, 1066, 1068), - (1068, -1, -1, 122, 122, 5, 68, -1, 0, 0, 8, 1067, 1069), - (1069, -1, -1, 122, 122, 5, 69, -1, 0, 0, 8, 1068, 1070), - (1070, -1, -1, 122, 122, 5, 70, -1, 0, 0, 8, 1069, 1399), - (1071, -1, -1, 1071, 1071, 3, 55, -1, 0, 0, 8, -1, 4764), - (1072, -1, -1, 1072, 1072, 5, 66, -1, 0, 0, 8, -1, 1073), - (1073, -1, -1, 1072, 1072, 5, 67, -1, 0, 0, 8, 1072, 1074), - (1074, -1, -1, 1072, 1072, 5, 68, -1, 0, 0, 8, 1073, 1075), - (1075, -1, -1, 1072, 1072, 5, 69, -1, 0, 0, 8, 1074, 1076), - (1076, -1, -1, 1072, 1072, 5, 70, -1, 0, 0, 8, 1075, 4744), - (1083, -1, -1, 77, 77, 3, 66, -1, 0, 0, 8, 436, 1084), - (1084, -1, -1, 77, 77, 6, 68, -1, 0, 0, 8, 1083, 1085), - (1085, -1, -1, 77, 77, 9, 70, -1, 0, 0, 8, 1084, 12449), - (1086, -1, -1, 80, 80, 3, 66, -1, 0, 0, 8, 439, 1087), - (1087, -1, -1, 80, 80, 6, 68, -1, 0, 0, 8, 1086, 1088), - (1088, -1, -1, 80, 80, 9, 70, -1, 0, 0, 8, 1087, 4779), - (1089, -1, -1, 1089, 1089, 3, 59, -1, 0, 0, 8, -1, 1090), - (1090, -1, -1, 1089, 1089, 6, 59, -1, 0, 0, 8, 1089, 1091), - (1091, -1, -1, 1089, 1089, 9, 59, -1, 0, 0, 8, 1090, -1), - (1092, -1, -1, 1092, 1092, 7, 67, -1, 0, 0, 8, -1, -1), - (1093, -1, -1, 1093, 1093, 3, 66, -1, 0, 0, 8, -1, 1094), - (1094, -1, -1, 1093, 1093, 3, 67, -1, 0, 0, 8, 1093, 1095), - (1095, -1, -1, 1093, 1093, 3, 68, -1, 0, 0, 8, 1094, 1096), - (1096, -1, -1, 1093, 1093, 3, 69, -1, 0, 0, 8, 1095, 1097), - (1097, -1, -1, 1093, 1093, 3, 70, -1, 0, 0, 8, 1096, -1), - (1099, -1, -1, 767, 767, 3, 67, -1, 0, 0, 8, 769, 1100), - (1100, -1, -1, 767, 767, 6, 68, -1, 0, 0, 8, 1099, 1101), - (1101, -1, -1, 767, 767, 9, 69, -1, 0, 0, 8, 1100, 12423), - (1102, 592, 592, 592, 592, 3, 66, 5825, 2, 18, 8, 706, 1103), - (1103, 592, 592, 592, 592, 3, 67, 5826, 2, 18, 8, 1102, 1104), - (1104, 592, 592, 592, 592, 3, 68, 5827, 2, 18, 8, 1103, 1105), - (1105, 592, 592, 592, 592, 3, 69, 5828, 2, 18, 8, 1104, 1106), - (1106, 592, 592, 592, 592, 3, 70, 5829, 2, 18, 8, 1105, 4975), - (1107, -1, -1, 1107, 1107, 3, 66, -1, 0, 0, 8, -1, 1108), - (1108, -1, -1, 1107, 1107, 6, 68, -1, 0, 0, 8, 1107, 1109), - (1109, -1, -1, 1107, 1107, 9, 70, -1, 0, 0, 8, 1108, 5286), - (1110, 1110, 1110, 1110, 1110, 3, 68, 5830, 3, 2160, 8, -1, 1111), - (1111, 1110, 1110, 1110, 1110, 6, 69, 5831, 3, 2160, 8, 1110, 1112), - (1112, 1110, 1110, 1110, 1110, 9, 70, 5832, 3, 2160, 8, 1111, 6400), - (1113, -1, -1, 997, 997, 5, 75, -1, 0, 0, 16, 999, 1114), - (1114, -1, -1, 997, 997, 5, 80, -1, 0, 0, 16, 1113, 1115), - (1115, -1, -1, 997, 997, 5, 85, -1, 0, 0, 16, 1114, -1), - (1116, 1116, 1116, 1116, 1116, 3, 68, 5837, 4, 2160, 8, -1, 1117), - (1117, 1116, 1116, 1116, 1116, 6, 69, 5838, 4, 2160, 8, 1116, 1118), - (1118, 1116, 1116, 1116, 1116, 9, 70, 5839, 4, 2160, 8, 1117, 4980), - (1119, 1119, 1119, 1119, 1119, 3, 68, 5841, 8, 900, 8, -1, 1120), - (1120, 1119, 1119, 1119, 1119, 6, 69, 5842, 8, 900, 8, 1119, 1121), - (1121, 1119, 1119, 1119, 1119, 9, 70, 5843, 8, 900, 8, 1120, 4964), - (1122, -1, -1, 1122, 1122, 7, 67, -1, 0, 0, 8, -1, -1), - (1123, 291, 291, 291, 291, 5, 66, 5854, 5, 900, 8, 291, 1124), - (1124, 291, 291, 291, 291, 5, 68, 5855, 5, 900, 8, 1123, 1125), - (1125, 291, 291, 291, 291, 5, 70, 5856, 5, 900, 8, 1124, 4969), - (1126, 1126, 1126, 1126, 1126, 3, 67, 5845, 2, 2160, 8, -1, 1127), - (1127, 1126, 1126, 1126, 1126, 6, 68, 5846, 2, 2160, 8, 1126, 1128), - (1128, 1126, 1126, 1126, 1126, 9, 69, 5847, 2, 2160, 8, 1127, 5513), - (1129, -1, -1, 1129, 1129, 5, 67, -1, 0, 0, 8, -1, 1130), - (1130, -1, -1, 1129, 1129, 3, 69, -1, 0, 0, 8, 1129, -1), - (1131, -1, -1, 1131, 1131, 3, 59, -1, 0, 0, 3, -1, 1132), - (1132, -1, -1, 1131, 1131, 6, 59, -1, 0, 0, 3, 1131, 1133), - (1133, -1, -1, 1131, 1131, 9, 59, -1, 0, 0, 3, 1132, 11082), - (1134, -1, -1, 1134, 1134, 3, 61, -1, 0, 0, 4, -1, 1135), - (1135, -1, -1, 1134, 1134, 4, 63, -1, 0, 0, 4, 1134, 1136), - (1136, -1, -1, 1134, 1134, 5, 65, -1, 0, 0, 4, 1135, 1158), - (1137, -1, -1, 1137, 1137, 3, 59, -1, 0, 0, 3, -1, 1138), - (1138, -1, -1, 1137, 1137, 6, 59, -1, 0, 0, 3, 1137, 1139), - (1139, -1, -1, 1137, 1137, 9, 59, -1, 0, 0, 3, 1138, -1), - (1140, -1, -1, 1140, 1140, 3, 61, -1, 0, 0, 4, -1, 1141), - (1141, -1, -1, 1140, 1140, 3, 63, -1, 0, 0, 4, 1140, 1142), - (1142, -1, -1, 1140, 1140, 3, 65, -1, 0, 0, 4, 1141, -1), - (1146, 1146, 1146, 1146, 1146, 3, 59, 6040, 3, 1500, 3, -1, 1147), - (1147, 1146, 1146, 1146, 1146, 6, 59, 6041, 3, 1200, 3, 1146, 1148), - (1148, 1146, 1146, 1146, 1146, 9, 59, 6042, 3, 900, 3, 1147, -1), - (1149, 1149, -1, 1149, 1149, 12, 65, 5853, 5, 1320, 7, -1, -1), - (1150, 1150, 1150, 1150, 1150, 3, 65, 5848, 2, 2160, 7, -1, 1151), - (1151, 1150, 1150, 1150, 1150, 6, 65, 5849, 2, 2160, 7, 1150, 1152), - (1152, 1150, 1150, 1150, 1150, 9, 65, 5850, 2, 2160, 7, 1151, -1), - (1155, -1, -1, 1155, 1155, 3, 65, -1, 0, 0, 7, -1, 1156), - (1156, -1, -1, 1155, 1155, 6, 65, -1, 0, 0, 7, 1155, 1157), - (1157, -1, -1, 1155, 1155, 9, 65, -1, 0, 0, 7, 1156, -1), - (1158, -1, -1, 1134, 1134, 4, 66, -1, 0, 0, 8, 1136, 1159), - (1159, -1, -1, 1134, 1134, 4, 67, -1, 0, 0, 8, 1158, 1160), - (1160, -1, -1, 1134, 1134, 4, 68, -1, 0, 0, 8, 1159, 1161), - (1161, -1, -1, 1134, 1134, 4, 69, -1, 0, 0, 8, 1160, 1162), - (1162, -1, -1, 1134, 1134, 4, 70, -1, 0, 0, 8, 1161, 4790), - (1163, -1, -1, 255, 255, 5, 67, -1, 0, 0, 8, 544, 1164), - (1164, -1, -1, 255, 255, 5, 68, -1, 0, 0, 8, 1163, 1165), - (1165, -1, -1, 255, 255, 5, 69, -1, 0, 0, 8, 1164, 4795), - (1166, -1, -1, 1143, 1143, 3, 65, -1, 0, 0, 15, -1, 1167), - (1167, -1, -1, 1143, 1143, 6, 65, -1, 0, 0, 15, 1166, 1168), - (1168, -1, -1, 1143, 1143, 9, 65, -1, 0, 0, 15, 1167, 6911), - (1172, -1, -1, 631, 631, 5, 67, -1, 0, 0, 8, 633, 1173), - (1173, -1, -1, 631, 631, 5, 68, -1, 0, 0, 8, 1172, 1174), - (1174, -1, -1, 631, 631, 5, 69, -1, 0, 0, 8, 1173, 4798), - (1178, 1178, 1178, 1178, 1178, 3, 68, 5857, 4, 900, 8, -1, 1179), - (1179, 1178, 1178, 1178, 1178, 6, 69, 5858, 4, 900, 8, 1178, 1180), - (1180, 1178, 1178, 1178, 1178, 9, 70, 5859, 4, 900, 8, 1179, 5779), - (1181, -1, -1, 1181, 1181, 3, 66, -1, 0, 0, 8, -1, 1182), - (1182, -1, -1, 1181, 1181, 3, 67, -1, 0, 0, 8, 1181, 1183), - (1183, -1, -1, 1181, 1181, 3, 68, -1, 0, 0, 8, 1182, 1184), - (1184, -1, -1, 1181, 1181, 3, 69, -1, 0, 0, 8, 1183, 1185), - (1185, -1, -1, 1181, 1181, 3, 70, -1, 0, 0, 8, 1184, -1), - (1186, -1, -1, 1186, 1186, 3, 66, -1, 0, 0, 8, -1, 1187), - (1187, -1, -1, 1186, 1186, 6, 68, -1, 0, 0, 8, 1186, 1188), - (1188, -1, -1, 1186, 1186, 9, 70, -1, 0, 0, 8, 1187, 4776), - (1189, 459, 459, 459, 459, 3, 66, 5860, 8, 180, 8, 461, 1190), - (1190, 459, 459, 459, 459, 6, 68, 5861, 8, 180, 8, 1189, 1191), - (1191, 459, 459, 459, 459, 9, 70, 5862, 8, 180, 8, 1190, 5062), - (1192, 1192, 1192, 1192, 1192, 5, 67, 5863, 12, 1320, 8, -1, 1193), - (1193, 1192, 1192, 1192, 1192, 5, 68, 5864, 12, 1320, 8, 1192, 1194), - (1194, 1192, 1192, 1192, 1192, 5, 69, 5865, 12, 1320, 8, 1193, 5076), - (1195, 1195, 1195, 1195, 1195, 12, 70, 5866, 13, 2160, 8, -1, 5079), - (1196, -1, -1, 1196, 1196, 2, 81, -1, 0, 0, 15, -1, 1197), - (1197, -1, -1, 1196, 1196, 2, 81, -1, 0, 0, 15, 1196, 1198), - (1198, -1, -1, 1196, 1196, 2, 81, -1, 0, 0, 15, 1197, 1199), - (1199, -1, -1, 1196, 1196, 2, 81, -1, 0, 0, 15, 1198, 1200), - (1200, -1, -1, 1196, 1196, 2, 81, -1, 0, 0, 15, 1199, 10743), - (1203, 131, 131, 131, 131, 5, 67, 5869, 4, 900, 8, 532, 1204), - (1204, 131, 131, 131, 131, 5, 68, 5870, 4, 900, 8, 1203, 1205), - (1205, 131, 131, 131, 131, 5, 69, 5988, 4, 900, 8, 1204, 5070), - (1206, 749, 749, 749, 749, 5, 66, 5871, 11, 1800, 8, 753, 1207), - (1207, 749, 749, 749, 749, 5, 68, 5872, 11, 1800, 8, 1206, 1208), - (1208, 749, 749, 749, 749, 5, 70, 5873, 11, 1800, 8, 1207, 17298), - (1209, 1209, -1, 1209, 1209, 12, 70, 5912, 14, 4320, 8, -1, -1), - (1210, -1, -1, 1210, 1210, 3, 66, -1, 0, 0, 8, -1, 1211), - (1211, -1, -1, 1210, 1210, 6, 68, -1, 0, 0, 8, 1210, 1212), - (1212, -1, -1, 1210, 1210, 9, 70, -1, 0, 0, 8, 1211, 1483), - (1213, -1, -1, 1210, 1213, 3, 66, -1, 0, 0, 8, -1, 1214), - (1214, -1, -1, 1210, 1213, 6, 68, -1, 0, 0, 8, 1213, 1215), - (1215, -1, -1, 1210, 1213, 9, 70, -1, 0, 0, 8, 1214, 4755), - (1216, -1, -1, 83, 83, 3, 81, -1, 0, 0, 16, -1, 1217), - (1217, -1, -1, 83, 83, 6, 81, -1, 0, 0, 16, 1216, 1218), - (1218, -1, -1, 83, 83, 9, 81, -1, 0, 0, 16, 1217, 15422), - (1219, -1, -1, 1435, 1435, 10, 71, -1, 0, 0, 16, -1, 1220), - (1220, -1, -1, 1435, 1435, 11, 71, -1, 0, 0, 16, 1219, 1221), - (1221, -1, -1, 1435, 1435, 12, 71, -1, 0, 0, 16, 1220, 1648), - (1222, 757, -1, 757, 1222, 5, 66, 5877, 6, 1800, 8, 761, 1223), - (1223, 757, -1, 757, 1222, 5, 68, 5878, 6, 1800, 8, 1222, 1224), - (1224, 757, -1, 757, 1222, 5, 70, 5879, 6, 1800, 8, 1223, 5051), - (1225, 548, 548, 548, 548, 5, 67, 5881, 5, 900, 8, 550, 1226), - (1226, 548, 548, 548, 548, 5, 68, 5882, 5, 900, 8, 1225, 1227), - (1227, 548, 548, 548, 548, 5, 69, 5883, 5, 900, 8, 1226, 5054), - (1228, 1228, 1228, 1228, 1228, 9, 70, 5880, 9, 600, 8, -1, -1), - (1229, 1229, 1229, 1229, 1229, 7, 66, 6094, 10, 600, 8, -1, -1), - (1230, -1, -1, 1230, 1230, 1, 51, -1, 0, 0, 8, -1, 1231), - (1231, -1, -1, 1230, 1230, 2, 53, -1, 0, 0, 8, 1230, 1232), - (1232, -1, -1, 1230, 1230, 3, 55, -1, 0, 0, 8, 1231, 5000), - (1233, 1233, -1, 1233, 1233, 3, 68, 5887, 7, 2160, 8, -1, 1234), - (1234, 1233, -1, 1233, 1233, 6, 69, 5888, 7, 2160, 8, 1233, 1235), - (1235, 1233, -1, 1233, 1233, 9, 70, 5889, 7, 2160, 8, 1234, -1), - (1239, 1239, 1239, 1239, 1239, 12, 70, 5903, 6, 600, 8, -1, 5868), - (1242, 1242, 1242, 1242, 1242, 3, 67, 5906, 9, 1320, 8, -1, 1243), - (1243, 1242, 1242, 1242, 1242, 6, 68, 5907, 9, 1320, 8, 1242, 1244), - (1244, 1242, 1242, 1242, 1242, 9, 69, 5908, 9, 1320, 8, 1243, 5857), - (1245, 1245, 1245, 1245, 1245, 3, 66, 5909, 8, 2160, 8, -1, 1246), - (1246, 1245, 1245, 1245, 1245, 6, 68, 5910, 8, 2160, 8, 1245, 1247), - (1247, 1245, 1245, 1245, 1245, 9, 70, 5911, 8, 2160, 8, 1246, 15459), - (1248, 616, 616, 616, 616, 3, 68, 6226, 7, 900, 8, 618, 1249), - (1249, 616, 616, 616, 616, 6, 69, 6227, 7, 900, 8, 1248, 1250), - (1250, 616, 616, 616, 616, 9, 70, 6228, 7, 900, 8, 1249, 6254), - (1251, 1251, 1251, 1251, 1251, 9, 70, 5915, 9, 1320, 8, -1, -1), - (1252, 1252, 1252, 1252, 1252, 9, 68, 5913, 9, 1320, 8, -1, -1), - (1253, 1253, 1253, 1253, 1253, 9, 67, 5916, 16, 1320, 8, -1, -1), - (1254, 1254, 1254, 1254, 1254, 9, 69, 5914, 16, 1320, 8, -1, -1), - (1255, 1255, 1255, 1255, 1255, 9, 70, 5918, 4, 1080, 8, -1, -1), - (1265, -1, -1, 820, 820, 5, 66, -1, 0, 0, 8, 822, 1266), - (1266, -1, -1, 820, 820, 5, 68, -1, 0, 0, 8, 1265, 1267), - (1267, -1, -1, 820, 820, 5, 70, -1, 0, 0, 8, 1266, 4813), - (1268, -1, -1, 807, 807, 5, 66, -1, 0, 0, 8, 809, 1269), - (1269, -1, -1, 807, 807, 5, 68, -1, 0, 0, 8, 1268, 1270), - (1270, -1, -1, 807, 807, 5, 70, -1, 0, 0, 8, 1269, 5922), - (1272, 209, 209, 209, 1272, 5, 66, 5919, 12, 5, 8, -1, 6378), - (1274, 1274, 1274, 1274, 1274, 3, 68, 5921, 9, 540, 8, -1, 1275), - (1275, 1274, 1274, 1274, 1274, 6, 69, 5922, 9, 540, 8, 1274, 1276), - (1276, 1274, 1274, 1274, 1274, 9, 70, 5923, 9, 540, 8, 1275, 4864), - (1277, 188, 188, 188, 188, 9, 68, 5924, 2, 30, 8, 188, 5044), - (1278, 534, 534, 534, 534, 5, 67, 5927, 4, 2160, 8, 717, 1279), - (1279, 534, 534, 534, 534, 5, 68, 5928, 4, 2160, 8, 1278, 1280), - (1280, 534, 534, 534, 534, 5, 69, 5929, 4, 2160, 8, 1279, 5041), - (1284, -1, -1, 1284, 1284, 3, 66, -1, 0, 0, 8, -1, 1285), - (1285, -1, -1, 1284, 1284, 6, 68, -1, 0, 0, 8, 1284, 1286), - (1286, -1, -1, 1284, 1284, 9, 70, -1, 0, 0, 8, 1285, 5035), - (1287, -1, -1, 1287, 1287, 3, 67, -1, 0, 0, 8, -1, 1288), - (1288, -1, -1, 1287, 1287, 6, 68, -1, 0, 0, 8, 1287, 1289), - (1289, -1, -1, 1287, 1287, 9, 69, -1, 0, 0, 8, 1288, 5516), - (1290, -1, -1, 864, 864, 3, 66, -1, 0, 0, 8, 866, 1291), - (1291, -1, -1, 864, 864, 6, 68, -1, 0, 0, 8, 1290, 1292), - (1292, -1, -1, 864, 864, 9, 70, -1, 0, 0, 8, 1291, 4983), - (1293, 545, 545, 545, 545, 3, 68, 6079, 3, 900, 8, 547, 1294), - (1294, 545, 545, 545, 545, 6, 69, 6080, 3, 900, 8, 1293, 1295), - (1295, 545, 545, 545, 545, 9, 70, 6081, 3, 900, 8, 1294, 4997), - (1296, -1, -1, 1296, 1296, 3, 66, -1, 0, 0, 8, -1, 1297), - (1297, -1, -1, 1296, 1296, 3, 67, -1, 0, 0, 8, 1296, 1298), - (1298, -1, -1, 1296, 1296, 3, 68, -1, 0, 0, 8, 1297, 1299), - (1299, -1, -1, 1296, 1296, 3, 69, -1, 0, 0, 8, 1298, 1300), - (1300, -1, -1, 1296, 1296, 3, 70, -1, 0, 0, 8, 1299, -1), - (1301, -1, -1, 846, 846, 3, 66, -1, 0, 0, 8, 848, 1302), - (1302, -1, -1, 846, 846, 6, 68, -1, 0, 0, 8, 1301, 1303), - (1303, -1, -1, 846, 846, 9, 70, -1, 0, 0, 8, 1302, 4948), - (1304, -1, -1, 1304, 1304, 3, 66, -1, 0, 0, 8, -1, 1305), - (1305, -1, -1, 1304, 1304, 6, 68, -1, 0, 0, 8, 1304, 1306), - (1306, -1, -1, 1304, 1304, 9, 70, -1, 0, 0, 8, 1305, 6029), - (1307, -1, -1, 1307, 1307, 5, 66, -1, 0, 0, 8, -1, 1308), - (1308, -1, -1, 1307, 1307, 5, 67, -1, 0, 0, 8, 1307, 1309), - (1309, -1, -1, 1307, 1307, 5, 68, -1, 0, 0, 8, 1308, 1310), - (1310, -1, -1, 1307, 1307, 5, 69, -1, 0, 0, 8, 1309, 1311), - (1311, -1, -1, 1307, 1307, 5, 70, -1, 0, 0, 8, 1310, 6660), - (1313, -1, -1, 1313, 1313, 3, 68, -1, 0, 0, 8, -1, 1314), - (1314, -1, -1, 1313, 1313, 6, 69, -1, 0, 0, 8, 1313, 1315), - (1315, -1, -1, 1313, 1313, 9, 70, -1, 0, 0, 8, 1314, 5029), - (1316, -1, -1, 210, 210, 5, 67, -1, 0, 0, 8, 212, 1317), - (1317, -1, -1, 210, 210, 5, 68, -1, 0, 0, 8, 1316, 1318), - (1318, -1, -1, 210, 210, 5, 69, -1, 0, 0, 8, 1317, 6072), - (1319, -1, -1, 634, 634, 5, 67, -1, 0, 0, 8, 845, 1320), - (1320, -1, -1, 634, 634, 5, 68, -1, 0, 0, 8, 1319, 1321), - (1321, -1, -1, 634, 634, 5, 69, -1, 0, 0, 8, 1320, 5032), - (1323, 1323, 1323, 1323, 1323, 12, 70, 5932, 7, 2160, 8, -1, -1), - (1324, 970, 970, 970, 970, 5, 66, 6030, 6, 1800, 8, 974, 1325), - (1325, 970, 970, 970, 970, 5, 68, 6031, 6, 1800, 8, 1324, 1326), - (1326, 970, 970, 970, 970, 5, 70, 6032, 6, 1800, 8, 1325, 17311), - (1327, 1327, 1327, 1327, 1327, 5, 67, 5933, 10, 900, 8, -1, 1328), - (1328, 1327, 1327, 1327, 1327, 5, 68, 5934, 10, 900, 8, 1327, 1329), - (1329, 1327, 1327, 1327, 1327, 5, 69, 5935, 10, 900, 8, 1328, 5314), - (1330, 912, 912, 912, 912, 3, 66, 5936, 4, 3600, 8, 914, 1331), - (1331, 912, 912, 912, 912, 6, 68, 5937, 4, 3600, 8, 1330, 1332), - (1332, 912, 912, 912, 912, 9, 70, 5938, 4, 3600, 8, 1331, 7119), - (1334, 1334, 1334, 1334, 1334, 3, 66, 5943, 11, 4320, 8, -1, 1335), - (1335, 1334, 1334, 1334, 1334, 6, 68, 5944, 11, 4320, 8, 1334, 1336), - (1336, 1334, 1334, 1334, 1334, 9, 70, 5945, 11, 4320, 8, 1335, 6152), - (1337, 1337, 1337, 1337, 1337, 5, 67, 5946, 13, 4320, 8, -1, 1338), - (1338, 1337, 1337, 1337, 1337, 5, 68, 5947, 13, 4320, 8, 1337, 1339), - (1339, 1337, 1337, 1337, 1337, 5, 69, 5948, 13, 4320, 8, 1338, 6158), - (1340, 921, 921, 921, 921, 12, 69, 5950, 8, 60, 8, 921, 5280), - (1341, 922, 922, 922, 922, 12, 68, 5951, 8, 60, 8, 922, 5281), - (1342, 923, 923, 923, 923, 12, 67, 5952, 8, 60, 8, 923, 5282), - (1343, 1343, 1343, 1343, 1343, 9, 69, 5953, 9, 300, 8, -1, -1), - (1344, 155, 155, 155, 155, 12, 70, 5949, 8, 60, 8, 533, 5279), - (1345, 1345, 1345, 1345, 1345, 5, 67, 6132, 6, 900, 8, -1, 1346), - (1346, 1345, 1345, 1345, 1345, 5, 68, 6133, 6, 900, 8, 1345, 1347), - (1347, 1345, 1345, 1345, 1345, 5, 69, 6134, 6, 900, 8, 1346, 5003), - (1348, 1348, 1348, 1348, 1348, 3, 68, 6090, 0, 3600, 8, -1, 1349), - (1349, 1348, 1348, 1348, 1348, 6, 69, 6091, 0, 3600, 8, 1348, 1350), - (1350, 1348, 1348, 1348, 1348, 9, 70, 6092, 0, 3600, 8, 1349, 5770), - (1351, 1351, 1351, 1351, 1351, 5, 67, 5939, 5, 30, 8, -1, 6133), - (1352, 1352, 1352, 1352, 1352, 3, 67, 6067, 3, 60, 8, -1, 1353), - (1353, 1352, 1352, 1352, 1352, 6, 68, 6068, 3, 60, 8, 1352, 1354), - (1354, 1352, 1352, 1352, 1352, 9, 69, 6069, 3, 60, 8, 1353, 6313), - (1355, 1355, 1355, 1355, 1355, 3, 68, 6070, 3, 60, 8, -1, 1356), - (1356, 1355, 1355, 1355, 1355, 6, 69, 6071, 3, 60, 8, 1355, 1357), - (1357, 1355, 1355, 1355, 1355, 9, 70, 6072, 3, 60, 8, 1356, 5240), - (1358, 1358, 1358, 1358, 1358, 3, 66, 6073, 3, 60, 8, -1, 1359), - (1359, 1358, 1358, 1358, 1358, 6, 67, 6074, 3, 60, 8, 1358, 1360), - (1360, 1358, 1358, 1358, 1358, 9, 68, 6075, 3, 60, 8, 1359, 6307), - (1361, -1, -1, 1361, 1361, 0, 65, -1, 0, 0, 3, -1, -1), - (1362, -1, -1, 1362, 1362, 0, 65, -1, 0, 0, 3, -1, -1), - (1363, -1, -1, 1363, 1363, 0, 68, -1, 0, 0, 3, -1, -1), - (1364, -1, -1, 1364, 1364, 0, 68, -1, 0, 0, 3, -1, -1), - (1365, -1, -1, 1365, 1365, 0, 68, -1, 0, 0, 3, -1, -1), - (1366, -1, -1, 1366, 1366, 0, 65, -1, 0, 0, 3, -1, -1), - (1367, -1, -1, 1367, 1367, 0, 65, -1, 0, 0, 3, -1, -1), - (1368, -1, -1, 1368, 1368, 0, 68, -1, 0, 0, 3, -1, -1), - (1369, -1, -1, 1369, 1369, 0, 68, -1, 0, 0, 3, -1, -1), - (1370, -1, -1, 1370, 1370, 0, 68, -1, 0, 0, 3, -1, -1), - (1371, 1371, 1371, 1371, 1371, 0, 1, 6880, 23, 72000, 0, -1, -1), - (1372, 1372, 1372, 1372, 1372, 0, 1, 6881, 24, 72000, 0, -1, -1), - (1373, 1373, 1373, 1373, 1373, 0, 1, 6882, 25, 72000, 0, -1, -1), - (1374, 1374, 1374, 1374, 1374, 0, 1, 6883, 26, 590400, 0, -1, -1), - (1375, 1375, 1375, 1375, 1375, 0, 1, 6884, 27, 72000, 0, -1, -1), - (1376, 1376, 1376, 1376, 1376, 0, 1, 6885, 28, 244800, 0, -1, -1), - (1377, 1377, 1377, 1377, 1377, 0, 1, 6886, 29, 14400, 0, -1, -1), - (1378, -1, -1, 1378, 1378, 0, 1, -1, 0, 0, 10, -1, 1379), - (1379, -1, -1, 1379, 1379, 0, 1, -1, 0, 0, 10, 1378, 1380), - (1380, -1, -1, 1380, 1380, 0, 1, -1, 0, 0, 10, 1379, 1381), - (1382, -1, -1, 1382, 1382, 0, 1, -1, 0, 0, 10, 1381, -1), - (1383, 1383, 1383, 1383, 1383, 3, 59, 8048, 6, 300, 3, -1, 1384), - (1384, 1383, 1383, 1383, 1383, 6, 59, 8049, 6, 300, 3, 1383, 1385), - (1385, 1383, 1383, 1383, 1383, 9, 59, 8050, 6, 300, 3, 1384, 1386), - (1386, 1383, 1383, 1383, 1383, 9, 65, 8052, 6, 300, 4, 1385, 1387), - (1387, 1383, 1383, 1383, 1383, 9, 70, 8053, 6, 300, 10, 1386, 5084), - (1388, -1, -1, 1388, 1388, 9, 70, -1, 0, 0, 10, -1, -1), - (1389, -1, -1, 1026, 1026, 5, 70, -1, 0, 0, 10, 1030, 1390), - (1390, -1, -1, 1026, 1026, 5, 70, -1, 0, 0, 10, 1389, 1391), - (1391, -1, -1, 1026, 1026, 5, 70, -1, 0, 0, 10, 1390, 1392), - (1392, -1, -1, 1026, 1026, 5, 70, -1, 0, 0, 10, 1391, 1393), - (1393, -1, -1, 1026, 1026, 5, 70, -1, 0, 0, 10, 1392, 4683), - (1394, -1, -1, 125, 125, 5, 70, -1, 0, 0, 10, 1065, 1395), - (1395, -1, -1, 125, 125, 5, 70, -1, 0, 0, 10, 1394, 1396), - (1396, -1, -1, 125, 125, 5, 70, -1, 0, 0, 10, 1395, 1397), - (1397, -1, -1, 125, 125, 5, 70, -1, 0, 0, 10, 1396, 1398), - (1398, -1, -1, 125, 125, 5, 70, -1, 0, 0, 10, 1397, 5519), - (1399, -1, -1, 122, 122, 5, 70, -1, 0, 0, 10, 1070, 1400), - (1400, -1, -1, 122, 122, 5, 70, -1, 0, 0, 10, 1399, 1401), - (1401, -1, -1, 122, 122, 5, 70, -1, 0, 0, 10, 1400, 1402), - (1402, -1, -1, 122, 122, 5, 70, -1, 0, 0, 10, 1401, 1403), - (1403, -1, -1, 122, 122, 5, 70, -1, 0, 0, 10, 1402, 5524), - (1404, 1404, 1404, 1404, 1404, 5, 66, 8054, 15, 2160, 10, -1, 1405), - (1405, 1404, 1404, 1404, 1404, 5, 67, 8055, 15, 2160, 10, 1404, 1406), - (1406, 1404, 1404, 1404, 1404, 5, 68, 8056, 15, 2160, 10, 1405, 1407), - (1407, 1404, 1404, 1404, 1404, 5, 69, 8057, 15, 2160, 10, 1406, 1408), - (1408, 1404, 1404, 1404, 1404, 5, 70, 8058, 15, 2160, 10, 1407, 12880), - (1409, 1409, 1409, 1409, 1409, 5, 66, 8054, 15, 2160, 10, -1, 1410), - (1410, 1409, 1409, 1409, 1409, 5, 67, 8055, 15, 2160, 10, 1409, 1411), - (1411, 1409, 1409, 1409, 1409, 5, 68, 8056, 15, 2160, 10, 1410, 1412), - (1412, 1409, 1409, 1409, 1409, 5, 69, 8057, 15, 2160, 10, 1411, 1413), - (1413, 1409, 1409, 1409, 1409, 5, 70, 8058, 15, 2160, 10, 1412, -1), - (1414, -1, -1, 1414, 1414, 5, 66, -1, 0, 0, 10, -1, 1415), - (1415, -1, -1, 1414, 1414, 5, 67, -1, 0, 0, 10, 1414, 1416), - (1416, -1, -1, 1414, 1414, 5, 68, -1, 0, 0, 10, 1415, 1417), - (1417, -1, -1, 1414, 1414, 5, 69, -1, 0, 0, 10, 1416, 1418), - (1418, -1, -1, 1414, 1414, 5, 70, -1, 0, 0, 10, 1417, 12874), - (1419, 1419, 1419, 1419, 1419, 9, 74, 16441, 52, 300, 15, -1, -1), - (1420, -1, -1, 1420, 1420, 3, 66, -1, 0, 0, 10, -1, 1421), - (1421, -1, -1, 1420, 1420, 3, 67, -1, 0, 0, 10, 1420, 1422), - (1422, -1, -1, 1420, 1420, 3, 68, -1, 0, 0, 10, 1421, 1423), - (1423, -1, -1, 1420, 1420, 3, 69, -1, 0, 0, 10, 1422, 1424), - (1424, -1, -1, 1420, 1420, 3, 70, -1, 0, 0, 10, 1423, -1), - (1425, 1425, 1425, 1425, 1425, 5, 70, 8060, 2, 2160, 10, -1, 1426), - (1426, 1425, 1425, 1425, 1425, 5, 70, 8061, 2, 2160, 10, 1425, 1427), - (1427, 1425, 1425, 1425, 1425, 5, 70, 8063, 2, 2160, 10, 1426, 1428), - (1428, 1425, 1425, 1425, 1425, 5, 70, 8066, 2, 2160, 10, 1427, 1429), - (1429, 1425, 1425, 1425, 1425, 5, 70, 8070, 2, 2160, 10, 1428, 5759), - (1430, -1, -1, 795, 795, 3, 70, -1, 0, 0, 10, 799, 1431), - (1431, -1, -1, 795, 795, 6, 70, -1, 0, 0, 10, 1430, 1432), - (1432, -1, -1, 795, 795, 9, 70, -1, 0, 0, 10, 1431, 4897), - (1435, -1, -1, 1435, 1435, 3, 66, -1, 0, 0, 10, -1, 1436), - (1436, -1, -1, 1435, 1435, 6, 68, -1, 0, 0, 10, 1435, 1437), - (1437, -1, -1, 1435, 1435, 9, 70, -1, 0, 0, 10, 1436, 4773), - (1440, 517, 517, 517, 517, 5, 66, 8109, 12, 600, 10, 519, 1441), - (1441, 517, 517, 517, 517, 5, 67, 8110, 12, 600, 10, 1440, 1442), - (1442, 517, 517, 517, 517, 5, 68, 8111, 12, 600, 10, 1441, 1443), - (1443, 517, 517, 517, 517, 5, 69, 8112, 12, 600, 10, 1442, 1444), - (1444, 517, 517, 517, 517, 5, 70, 8113, 12, 600, 10, 1443, 7296), - (1453, -1, -1, 1453, 1453, 5, 66, -1, 0, 0, 10, -1, 1454), - (1454, -1, -1, 1453, 1453, 5, 67, -1, 0, 0, 10, 1453, 1455), - (1455, -1, -1, 1453, 1453, 5, 68, -1, 0, 0, 10, 1454, 1456), - (1456, -1, -1, 1453, 1453, 5, 69, -1, 0, 0, 10, 1455, 1457), - (1457, -1, -1, 1453, 1453, 5, 70, -1, 0, 0, 10, 1456, -1), - (1458, 1458, 1458, 1458, 1458, 12, 70, 8124, 6, 4320, 10, -1, -1), - (1459, 1459, 1459, 1459, 1459, 7, 70, 8125, 11, 1800, 10, -1, 1460), - (1460, 1459, 1459, 1459, 1459, 7, 70, 8126, 11, 1800, 10, 1459, 1461), - (1461, 1459, 1459, 1459, 1459, 7, 70, 8127, 11, 1800, 10, 1460, 5080), - (1462, 1462, 1462, 1462, 1462, 3, 59, 8133, 5, 300, 3, -1, 1463), - (1463, 1462, 1462, 1462, 1462, 6, 59, 8134, 5, 300, 3, 1462, 1464), - (1464, 1462, 1462, 1462, 1462, 9, 59, 8135, 5, 300, 3, 1463, 1465), - (1465, 1462, 1462, 1462, 1462, 9, 65, 8137, 5, 300, 4, 1464, 1466), - (1466, 1462, 1462, 1462, 1462, 9, 70, 8138, 5, 300, 10, 1465, 4900), - (1467, -1, -1, 729, 729, 3, 70, -1, 0, 0, 10, 733, 1468), - (1468, -1, -1, 729, 729, 6, 70, -1, 0, 0, 10, 1467, 1469), - (1469, -1, -1, 729, 729, 9, 70, -1, 0, 0, 10, 1468, 4960), - (1471, -1, -1, 1471, 1471, 5, 70, -1, 0, 0, 10, -1, 1472), - (1472, -1, -1, 1471, 1471, 5, 70, -1, 0, 0, 10, 1471, 1473), - (1473, -1, -1, 1471, 1471, 5, 70, -1, 0, 0, 10, 1472, 1474), - (1474, -1, -1, 1471, 1471, 5, 70, -1, 0, 0, 10, 1473, 1475), - (1475, -1, -1, 1471, 1471, 5, 70, -1, 0, 0, 10, 1474, 6442), - (1477, 1477, 1477, 1477, 1477, 9, 70, 8149, 3, 4320, 10, -1, -1), - (1478, 1478, -1, 1478, 1478, 3, 66, 8406, 0, 1, 10, -1, 1479), - (1479, 1478, -1, 1478, 1478, 6, 68, 8407, 0, 1, 10, 1478, 1480), - (1480, 1478, -1, 1478, 1478, 9, 70, 8408, 0, 1, 10, 1479, 6161), - (1483, -1, -1, 1210, 1210, 7, 70, -1, 0, 0, 10, 1212, 1484), - (1484, -1, -1, 1210, 1210, 7, 70, -1, 0, 0, 10, 1483, 1485), - (1485, -1, -1, 1210, 1210, 7, 70, -1, 0, 0, 10, 1484, 4752), - (1486, -1, -1, 1486, 1486, 5, 66, -1, 0, 0, 10, -1, 1487), - (1487, -1, -1, 1486, 1486, 5, 67, -1, 0, 0, 10, 1486, 1488), - (1488, -1, -1, 1486, 1486, 5, 68, -1, 0, 0, 10, 1487, 1489), - (1489, -1, -1, 1486, 1486, 5, 69, -1, 0, 0, 10, 1488, 1490), - (1490, -1, -1, 1486, 1486, 5, 70, -1, 0, 0, 10, 1489, 5529), - (1491, 746, 746, 746, 746, 3, 70, 8156, 10, 2160, 10, 748, 1492), - (1492, 746, 746, 746, 746, 6, 70, 8157, 10, 2160, 10, 1491, 1493), - (1493, 746, 746, 746, 746, 9, 70, 8158, 10, 2160, 10, 1492, 5800), - (1494, 1494, 1494, 1494, 1494, 12, 70, 8170, 2, 7, 10, -1, -1), - (1495, 1495, 1495, 1495, 1495, 3, 70, 8190, 30, 900, 10, -1, 1496), - (1496, 1495, 1495, 1495, 1495, 6, 70, 8191, 30, 900, 10, 1495, 1497), - (1497, 1495, 1495, 1495, 1495, 9, 70, 8192, 30, 900, 10, 1496, 5311), - (1498, 1498, 1498, 1498, 1498, 3, 70, 8193, 12, 1320, 10, -1, 1499), - (1499, 1498, 1498, 1498, 1498, 6, 70, 8194, 12, 1320, 10, 1498, 1500), - (1500, 1498, 1498, 1498, 1498, 9, 70, 8195, 12, 1320, 10, 1499, 5058), - (1501, 1501, 1501, 1501, 1501, 3, 70, 8196, 10, 4320, 10, -1, 1502), - (1502, 1501, 1501, 1501, 1501, 6, 70, 8197, 10, 4320, 10, 1501, 1503), - (1503, 1501, 1501, 1501, 1501, 9, 70, 8198, 10, 4320, 10, 1502, 1558), - (1504, -1, -1, 1504, 1504, 5, 70, -1, 0, 0, 10, -1, 1505), - (1505, -1, -1, 1504, 1504, 5, 70, -1, 0, 0, 10, 1504, 1506), - (1506, -1, -1, 1504, 1504, 5, 70, -1, 0, 0, 10, 1505, 5880), - (1507, 520, 520, 520, 520, 3, 70, 8201, 6, 540, 10, 522, 1508), - (1508, 520, 520, 520, 520, 6, 70, 8202, 6, 540, 10, 1507, 1509), - (1509, 520, 520, 520, 520, 9, 70, 8203, 6, 540, 10, 1508, 5883), - (1510, 1510, -1, 1510, 1510, 12, 70, 8205, 13, 2160, 10, -1, 7202), - (1511, -1, -1, 1511, 1511, 5, 70, -1, 0, 0, 10, -1, 1512), - (1512, -1, -1, 1511, 1511, 5, 70, -1, 0, 0, 10, 1511, 1513), - (1513, -1, -1, 1511, 1511, 5, 70, -1, 0, 0, 10, 1512, 5950), - (1514, -1, -1, 1514, 1514, 7, 70, -1, 0, 0, 10, -1, 1515), - (1515, -1, -1, 1514, 1514, 7, 70, -1, 0, 0, 10, 1514, 1516), - (1516, -1, -1, 1514, 1514, 7, 70, -1, 0, 0, 10, 1515, 13404), - (1519, 153, 153, 153, 153, 9, 70, 8216, 3, 2160, 10, 153, 5068), - (1520, 1520, 1520, 1520, 1520, 3, 70, 8218, 11, 900, 10, -1, 1521), - (1521, 1520, 1520, 1520, 1520, 6, 70, 8219, 11, 900, 10, 1520, 1522), - (1522, 1520, 1520, 1520, 1520, 9, 70, 8220, 11, 900, 10, 1521, 6449), - (1523, 1523, 1523, 1523, 1523, 12, 70, 8221, 7, 7, 10, -1, -1), - (1524, -1, -1, 190, 190, 7, 70, -1, 0, 0, 10, 192, 1526), - (1525, -1, -1, 190, 190, 7, 70, -1, 0, 0, 10, 1526, 5038), - (1526, -1, -1, 190, 190, 7, 70, -1, 0, 0, 10, 1524, 1525), - (1527, 1527, 1527, 1527, 1527, 12, 70, 8223, 3, 7, 10, -1, -1), - (1528, -1, -1, 1528, 4819, 5, 66, -1, 0, 0, 10, -1, 1529), - (1529, -1, -1, 1528, 4819, 5, 67, -1, 0, 0, 10, 1528, 1530), - (1530, -1, -1, 1528, 4819, 5, 68, -1, 0, 0, 10, 1529, 1531), - (1531, -1, -1, 1528, 4819, 5, 69, -1, 0, 0, 10, 1530, 1532), - (1532, -1, -1, 1528, 4819, 5, 70, -1, 0, 0, 10, 1531, 4819), - (1533, -1, -1, 602, 602, 3, 70, -1, 0, 0, 10, 604, 1534), - (1534, -1, -1, 602, 602, 6, 70, -1, 0, 0, 10, 1533, 1535), - (1535, -1, -1, 602, 602, 9, 70, -1, 0, 0, 10, 1534, 4758), - (1536, -1, -1, 599, 599, 3, 70, -1, 0, 0, 10, 601, 1537), - (1537, -1, -1, 599, 599, 6, 70, -1, 0, 0, 10, 1536, 1538), - (1538, -1, -1, 599, 599, 9, 70, -1, 0, 0, 10, 1537, 5534), - (1539, -1, -1, 878, 878, 7, 70, -1, 0, 0, 10, 880, 1540), - (1540, -1, -1, 878, 878, 7, 70, -1, 0, 0, 10, 1539, 1541), - (1541, -1, -1, 878, 878, 7, 70, -1, 0, 0, 10, 1540, 4957), - (1542, 1542, -1, 1542, 1542, 3, 60, 8240, 0, 1, 10, -1, -1), - (1543, -1, -1, 1543, 1543, 5, 70, -1, 0, 0, 10, -1, 1544), - (1544, -1, -1, 1543, 1543, 5, 70, -1, 0, 0, 10, 1543, 1545), - (1545, -1, -1, 1543, 1543, 5, 70, -1, 0, 0, 10, 1544, 4951), - (1546, -1, -1, 1546, 1546, 5, 70, -1, 0, 0, 10, -1, 1547), - (1547, -1, -1, 1546, 1546, 5, 70, -1, 0, 0, 10, 1546, 1548), - (1548, -1, -1, 1546, 1546, 5, 70, -1, 0, 0, 10, 1547, 4829), - (1549, -1, -1, 1549, 1549, 3, 66, -1, 0, 0, 10, -1, 1550), - (1550, -1, -1, 1549, 1549, 6, 68, -1, 0, 0, 10, 1549, 1551), - (1551, -1, -1, 1549, 1549, 9, 70, -1, 0, 0, 10, 1550, -1), - (1552, -1, -1, 1552, 1552, 3, 66, -1, 0, 0, 10, -1, 1553), - (1553, -1, -1, 1552, 1552, 6, 68, -1, 0, 0, 10, 1552, 1554), - (1554, -1, -1, 1552, 1552, 9, 70, -1, 0, 0, 10, 1553, -1), - (1555, -1, -1, 1555, 1555, 5, 70, -1, 0, 0, 10, -1, 1556), - (1556, -1, -1, 1555, 1555, 5, 70, -1, 0, 0, 10, 1555, 1557), - (1557, -1, -1, 1555, 1555, 5, 70, -1, 0, 0, 10, 1556, 12727), - (1558, 1501, 1501, 1501, 1501, 6, 75, 16444, 10, 4320, 15, 1503, 1559), - (1559, 1501, 1501, 1501, 1501, 6, 80, 16445, 10, 4320, 15, 1558, 1560), - (1560, 1501, 1501, 1501, 1501, 6, 85, 16446, 10, 4320, 15, 1559, 13244), - (1563, -1, -1, 556, 556, 5, 66, -1, 0, 0, 10, 560, 1564), - (1564, -1, -1, 556, 556, 5, 67, -1, 0, 0, 10, 1563, 1565), - (1565, -1, -1, 556, 556, 5, 68, -1, 0, 0, 10, 1564, 1566), - (1566, -1, -1, 556, 556, 5, 69, -1, 0, 0, 10, 1565, 1567), - (1567, -1, -1, 556, 556, 5, 70, -1, 0, 0, 10, 1566, 17004), - (1569, 1569, 1569, 1569, 1569, 3, 70, 8256, 5, 1800, 10, -1, 1570), - (1570, 1569, 1569, 1569, 1569, 6, 70, 8257, 5, 1800, 10, 1569, 1571), - (1571, 1569, 1569, 1569, 1569, 9, 70, 8258, 5, 1800, 10, 1570, 5713), - (1572, -1, -1, 1572, 1572, 5, 66, -1, 0, 0, 10, -1, 1573), - (1573, -1, -1, 1572, 1572, 5, 67, -1, 0, 0, 10, 1572, 1574), - (1574, -1, -1, 1572, 1572, 5, 68, -1, 0, 0, 10, 1573, 1575), - (1575, -1, -1, 1572, 1572, 5, 69, -1, 0, 0, 10, 1574, 1576), - (1576, -1, -1, 1572, 1572, 5, 70, -1, 0, 0, 10, 1575, 10554), - (1577, -1, -1, 1577, 1577, 3, 66, -1, 0, 0, 10, -1, 1578), - (1578, -1, -1, 1577, 1577, 6, 68, -1, 0, 0, 10, 1577, 1579), - (1579, -1, -1, 1577, 1577, 9, 70, -1, 0, 0, 10, 1578, 5886), - (1583, -1, -1, 1583, 1583, 5, 70, -1, 0, 0, 10, -1, 1584), - (1584, -1, -1, 1583, 1583, 5, 70, -1, 0, 0, 10, 1583, 1585), - (1585, -1, -1, 1583, 1583, 5, 70, -1, 0, 0, 10, 1584, 1586), - (1586, -1, -1, 1583, 1583, 5, 70, -1, 0, 0, 10, 1585, 1587), - (1587, -1, -1, 1583, 1583, 5, 70, -1, 0, 0, 10, 1586, -1), - (1588, -1, -1, 1587, 1587, 3, 66, -1, 0, 0, 10, -1, 1589), - (1589, -1, -1, 1587, 1587, 6, 68, -1, 0, 0, 10, 1588, 1590), - (1590, -1, -1, 1587, 1587, 9, 70, -1, 0, 0, 10, 1589, -1), - (1591, -1, -1, 1586, 1586, 12, 70, -1, 0, 0, 10, -1, -1), - (1592, -1, -1, 1592, 1592, 5, 66, -1, 0, 0, 10, -1, 1593), - (1593, -1, -1, 1592, 1592, 5, 67, -1, 0, 0, 10, 1592, 1594), - (1594, -1, -1, 1592, 1592, 5, 68, -1, 0, 0, 10, 1593, 1595), - (1595, -1, -1, 1592, 1592, 5, 69, -1, 0, 0, 10, 1594, 1596), - (1596, -1, -1, 1592, 1592, 5, 70, -1, 0, 0, 10, 1595, 4725), - (1597, 1597, 1597, 1597, 1597, 9, 70, 8271, 6, 10, 10, -1, 6606), - (1598, 1598, -1, 1598, 1598, 3, 70, 8272, 6, 900, 10, -1, 1599), - (1599, 1598, -1, 1598, 1598, 6, 70, 8273, 6, 900, 10, 1598, 1600), - (1600, 1598, -1, 1598, 1598, 9, 70, 8274, 6, 900, 10, 1599, 4972), - (1601, -1, -1, 644, 644, 5, 61, -1, 0, 0, 10, 644, 1602), - (1602, -1, -1, 644, 644, 5, 63, -1, 0, 0, 10, 1601, 1603), - (1603, -1, -1, 644, 644, 5, 65, -1, 0, 0, 10, 1602, 4986), - (1604, -1, -1, 1604, 1604, 5, 60, -1, 0, 0, 10, -1, 1605), - (1605, -1, -1, 1604, 1604, 5, 61, -1, 0, 0, 10, 1604, 1606), - (1606, -1, -1, 1604, 1604, 5, 62, -1, 0, 0, 10, 1605, 5290), - (1607, 289, 289, 289, 289, 9, 70, 8278, 3, 300, 10, 289, 5742), - (1608, -1, -1, 1608, 1608, 3, 66, -1, 0, 0, 10, -1, 1609), - (1609, -1, -1, 1608, 1608, 6, 68, -1, 0, 0, 10, 1608, 1610), - (1610, -1, -1, 1608, 1608, 9, 70, -1, 0, 0, 10, 1609, 4989), - (1611, -1, -1, 1417, 1417, 3, 66, -1, 0, 0, 10, -1, 1612), - (1612, -1, -1, 1417, 1417, 3, 67, -1, 0, 0, 10, 1611, 1613), - (1613, -1, -1, 1417, 1417, 3, 68, -1, 0, 0, 10, 1612, 1614), - (1614, -1, -1, 1417, 1417, 3, 69, -1, 0, 0, 10, 1613, 1615), - (1615, -1, -1, 1417, 1417, 3, 70, -1, 0, 0, 10, 1614, -1), - (1616, -1, -1, 1616, 1616, 5, 66, -1, 0, 0, 10, -1, 1617), - (1617, -1, -1, 1616, 1616, 5, 67, -1, 0, 0, 10, 1616, 1618), - (1618, -1, -1, 1616, 1616, 5, 68, -1, 0, 0, 10, 1617, 1619), - (1619, -1, -1, 1616, 1616, 5, 69, -1, 0, 0, 10, 1618, 1620), - (1620, -1, -1, 1616, 1616, 5, 70, -1, 0, 0, 10, 1619, 4992), - (1621, -1, -1, 564, 564, 7, 70, -1, 0, 0, 10, 566, 1622), - (1622, -1, -1, 564, 564, 7, 70, -1, 0, 0, 10, 1621, 1623), - (1623, -1, -1, 564, 564, 7, 70, -1, 0, 0, 10, 1622, -1), - (1624, -1, -1, 561, 561, 7, 70, -1, 0, 0, 10, 563, 1625), - (1625, -1, -1, 561, 561, 7, 70, -1, 0, 0, 10, 1624, 1626), - (1626, -1, -1, 561, 561, 7, 70, -1, 0, 0, 10, 1625, -1), - (1627, -1, -1, 1627, 1627, 3, 66, -1, 0, 0, 10, -1, 1628), - (1628, -1, -1, 1627, 1627, 6, 68, -1, 0, 0, 10, 1627, 1629), - (1629, -1, -1, 1627, 1627, 9, 70, -1, 0, 0, 10, 1628, -1), - (1630, 1474, 1474, 1474, 1474, 3, 70, 8146, 14, 300, 10, -1, 1631), - (1631, 1474, 1474, 1474, 1474, 6, 70, 8147, 14, 300, 10, 1630, 1632), - (1632, 1474, 1474, 1474, 1474, 9, 70, 8148, 14, 300, 10, 1631, -1), - (1633, -1, -1, 551, 551, 5, 66, -1, 0, 0, 10, 555, 1634), - (1634, -1, -1, 551, 551, 5, 67, -1, 0, 0, 10, 1633, 1635), - (1635, -1, -1, 551, 551, 5, 68, -1, 0, 0, 10, 1634, 1636), - (1636, -1, -1, 551, 551, 5, 69, -1, 0, 0, 10, 1635, 1637), - (1637, -1, -1, 551, 551, 5, 70, -1, 0, 0, 10, 1636, 6905), - (1638, 1638, 1638, 1638, 1638, 5, 59, 8450, 7, 4320, 3, -1, -1), - (1639, 1639, 1639, 1639, 1639, 9, 65, 8451, 7, 4320, 4, -1, -1), - (1640, 1640, 1640, 1640, 1640, 12, 70, 8452, 7, 4320, 10, -1, -1), - (1641, -1, -1, 1641, 1641, 15, 70, -1, 0, 0, 3, -1, -1), - (1642, -1, -1, 1642, 1642, 15, 70, -1, 0, 0, 3, -1, -1), - (1643, 1643, 1643, 1643, 1643, 0, 59, 8975, 0, 1, 11, -1, -1), - (1644, 1644, 1644, 1644, 1644, 0, 59, 8900, 0, 1, 11, -1, -1), - (1645, 1645, 1645, 1645, 1645, 9, 70, 8977, 0, 1, 3, -1, -1), - (1646, 1646, 1646, 1646, 1646, 9, 70, 8978, 0, 1, 3, -1, -1), - (1647, 1647, 1647, 1647, 1647, 0, 68, 8771, 21, 900, 3, -1, -1), - (1648, -1, -1, 1435, 4773, 9, 71, -1, 0, 0, 16, 1221, 1649), - (1649, -1, -1, 1435, 4773, 9, 76, -1, 0, 0, 16, 1648, 1650), - (1650, -1, -1, 1435, 4773, 9, 81, -1, 0, 0, 16, 1649, 13091), - (1651, -1, -1, 8210, 8210, 5, 85, -1, 0, 0, 16, 8214, 1652), - (1652, -1, -1, 8210, 8210, 5, 85, -1, 0, 0, 16, 1651, 1653), - (1653, -1, -1, 8210, 8210, 5, 85, -1, 0, 0, 16, 1652, 1654), - (1654, -1, -1, 8210, 8210, 5, 85, -1, 0, 0, 16, 1653, 1655), - (1655, -1, -1, 8210, 8210, 5, 85, -1, 0, 0, 16, 1654, 13149), - (1656, -1, -1, 8204, 8204, 4, 85, -1, 0, 0, 16, 8206, 1657), - (1657, -1, -1, 8204, 8204, 4, 85, -1, 0, 0, 16, 1656, -1), - (1659, -1, -1, 8207, 8207, 4, 85, -1, 0, 0, 16, 8209, 1660), - (1660, -1, -1, 8207, 8207, 4, 85, -1, 0, 0, 16, 1659, -1), - (1662, -1, -1, 1662, 1662, 3, 65, -1, 0, 0, 17, -1, 1663), - (1663, -1, -1, 1662, 1662, 3, 66, -1, 0, 0, 17, 1662, 1664), - (1664, -1, -1, 1662, 1662, 3, 67, -1, 0, 0, 17, 1663, 1665), - (1665, -1, -1, 1662, 1662, 3, 68, -1, 0, 0, 17, 1664, 1666), - (1666, -1, -1, 1662, 1662, 3, 69, -1, 0, 0, 17, 1665, -1), - (1667, 1667, 1667, 1667, 1667, 9, 85, 23602, 0, 1, 16, -1, -1), - (2400, -1, -1, 2400, 2400, 9, 81, 0, 0, 0, 17, -1, 2401), - (2401, -1, -1, 2400, 2400, 12, 83, 0, 0, 0, 17, 2400, 2402), - (2402, -1, -1, 2400, 2400, 15, 85, 0, 0, 0, 17, 2401, 15344), - (3676, 3676, 3676, 3676, 3676, 9, 85, 23606, 67, 30, 16, -1, -1), - (4665, 4665, 4665, 4665, 4665, 0, 1, 9177, 19, 4320, 0, -1, -1), - (4666, -1, -1, 4844, 4844, 5, 81, -1, 0, 0, 16, -1, 4667), - (4667, -1, -1, 4844, 4844, 5, 82, -1, 0, 0, 16, 4666, 4668), - (4668, -1, -1, 4844, 4844, 5, 83, -1, 0, 0, 16, 4667, 4669), - (4669, -1, -1, 4844, 4844, 5, 84, -1, 0, 0, 16, 4668, 4670), - (4670, -1, -1, 4844, 4844, 5, 85, -1, 0, 0, 16, 4669, -1), - (4672, -1, -1, 4672, 4672, 3, 59, -1, 0, 0, 8, -1, 4673), - (4673, -1, -1, 4672, 4672, 6, 59, -1, 0, 0, 8, 4672, 4674), - (4674, -1, -1, 4672, 4672, 9, 59, -1, 0, 0, 8, 4673, -1), - (4675, -1, -1, 4675, 4675, 3, 59, -1, 0, 0, 3, -1, 4676), - (4676, -1, -1, 4675, 4675, 6, 59, -1, 0, 0, 3, 4675, 4677), - (4677, -1, -1, 4675, 4675, 9, 59, -1, 0, 0, 3, 4676, -1), - (4678, -1, -1, 418, 418, 5, 71, -1, 0, 0, 12, 1005, 4679), - (4679, -1, -1, 418, 418, 5, 72, -1, 0, 0, 12, 4678, 4680), - (4680, -1, -1, 418, 418, 5, 73, -1, 0, 0, 12, 4679, 4681), - (4681, -1, -1, 418, 418, 5, 74, -1, 0, 0, 12, 4680, 4682), - (4682, -1, -1, 418, 418, 5, 75, -1, 0, 0, 12, 4681, 7547), - (4683, -1, -1, 1026, 1026, 5, 71, -1, 0, 0, 12, 1393, 4684), - (4684, -1, -1, 1026, 1026, 5, 72, -1, 0, 0, 12, 4683, 4685), - (4685, -1, -1, 1026, 1026, 5, 73, -1, 0, 0, 12, 4684, 4686), - (4686, -1, -1, 1026, 1026, 5, 74, -1, 0, 0, 12, 4685, 4687), - (4687, -1, -1, 1026, 1026, 5, 75, -1, 0, 0, 12, 4686, 6523), - (4688, -1, -1, 4688, 4688, 3, 71, -1, 0, 0, 12, -1, 4689), - (4689, -1, -1, 4688, 4688, 3, 72, -1, 0, 0, 12, 4688, 4690), - (4690, -1, -1, 4688, 4688, 3, 73, -1, 0, 0, 12, 4689, 4691), - (4691, -1, -1, 4688, 4688, 3, 74, -1, 0, 0, 12, 4690, 4692), - (4692, -1, -1, 4688, 4688, 3, 75, -1, 0, 0, 12, 4691, -1), - (4693, -1, -1, 65, 661, 3, 71, -1, 0, 0, 12, 1035, 4694), - (4694, -1, -1, 65, 661, 3, 72, -1, 0, 0, 12, 4693, 4695), - (4695, -1, -1, 65, 661, 3, 73, -1, 0, 0, 12, 4694, 4696), - (4696, -1, -1, 65, 661, 3, 74, -1, 0, 0, 12, 4695, 4697), - (4697, -1, -1, 65, 661, 3, 75, -1, 0, 0, 12, 4696, 6390), - (4698, -1, -1, 4698, 4698, 5, 51, -1, 0, 0, 12, -1, 6545), - (4699, -1, -1, 4699, 4699, 5, 51, -1, 0, 0, 12, -1, 6540), - (4700, 1037, 1037, 1037, 1037, 0, 1, 7619, 33, 72000, 0, -1, -1), - (4702, 4702, 4702, 4702, 4702, 3, 71, 9475, 31, 600, 12, -1, -1), - (4704, 4704, 4704, 4704, 4704, 4, 71, 9477, 31, 600, 12, -1, -1), - (4705, 4705, 4705, 4705, 4705, 3, 71, 9478, 31, 600, 12, -1, -1), - (4706, 4706, 4706, 4706, 4706, 3, 71, 9479, 31, 600, 12, -1, -1), - (4707, -1, -1, 1041, 1041, 6, 71, -1, 0, 0, 12, 1043, 4708), - (4708, -1, -1, 1041, 1041, 6, 73, -1, 0, 0, 12, 4707, 4709), - (4709, -1, -1, 1041, 1041, 6, 75, -1, 0, 0, 12, 4708, 5542), - (4710, -1, -1, 1044, 1044, 6, 71, -1, 0, 0, 12, 1046, 4711), - (4711, -1, -1, 1044, 1044, 6, 73, -1, 0, 0, 12, 4710, 4712), - (4712, -1, -1, 1044, 1044, 6, 75, -1, 0, 0, 12, 4711, 5545), - (4713, -1, -1, 1047, 1047, 6, 71, -1, 0, 0, 12, 1049, 4714), - (4714, -1, -1, 1047, 1047, 6, 73, -1, 0, 0, 12, 4713, 4715), - (4715, -1, -1, 1047, 1047, 6, 75, -1, 0, 0, 12, 4714, 5548), - (4716, -1, -1, 1050, 1050, 6, 71, -1, 0, 0, 12, 1052, 4717), - (4717, -1, -1, 1050, 1050, 6, 73, -1, 0, 0, 12, 4716, 4718), - (4718, -1, -1, 1050, 1050, 6, 75, -1, 0, 0, 12, 4717, 5551), - (4722, -1, -1, 119, 119, 3, 71, -1, 0, 0, 12, 1055, 4723), - (4723, -1, -1, 119, 119, 3, 73, -1, 0, 0, 12, 4722, 4724), - (4724, -1, -1, 119, 119, 3, 75, -1, 0, 0, 12, 4723, 5554), - (4725, -1, -1, 1592, 1592, 5, 71, -1, 0, 0, 12, 1596, 4726), - (4726, -1, -1, 1592, 1592, 5, 72, -1, 0, 0, 12, 4725, 4727), - (4727, -1, -1, 1592, 1592, 5, 73, -1, 0, 0, 12, 4726, 4728), - (4728, -1, -1, 1592, 1592, 5, 74, -1, 0, 0, 12, 4727, 4729), - (4729, -1, -1, 1592, 1592, 5, 75, -1, 0, 0, 12, 4728, 5557), - (4733, -1, -1, 625, 625, 3, 71, -1, 0, 0, 12, 627, 4734), - (4734, -1, -1, 625, 625, 3, 73, -1, 0, 0, 12, 4733, 4735), - (4735, -1, -1, 625, 625, 3, 75, -1, 0, 0, 12, 4734, 7641), - (4739, -1, -1, 4739, 4739, 3, 71, -1, 0, 0, 12, -1, 4740), - (4740, -1, -1, 4739, 4739, 6, 73, -1, 0, 0, 12, 4739, 4741), - (4741, -1, -1, 4739, 4739, 9, 75, -1, 0, 0, 12, 4740, 5562), - (4742, 4742, 4742, 4742, 4742, 9, 71, 11024, 12, 600, 12, -1, 5565), - (4744, -1, -1, 1072, 1072, 5, 71, -1, 0, 0, 12, 1076, 4745), - (4745, -1, -1, 1072, 1072, 5, 72, -1, 0, 0, 12, 4744, 4746), - (4746, -1, -1, 1072, 1072, 5, 73, -1, 0, 0, 12, 4745, 4747), - (4747, -1, -1, 1072, 1072, 5, 74, -1, 0, 0, 12, 4746, 4748), - (4748, -1, -1, 1072, 1072, 5, 75, -1, 0, 0, 12, 4747, 5566), - (4749, -1, -1, 637, 637, 6, 71, -1, 0, 0, 12, 772, 4750), - (4750, -1, -1, 637, 637, 6, 73, -1, 0, 0, 12, 4749, 4751), - (4751, -1, -1, 637, 637, 6, 75, -1, 0, 0, 12, 4750, 5571), - (4752, -1, -1, 1210, 1210, 7, 71, -1, 0, 0, 12, 1485, 4753), - (4753, -1, -1, 1210, 1210, 7, 73, -1, 0, 0, 12, 4752, 4754), - (4754, -1, -1, 1210, 1210, 7, 75, -1, 0, 0, 12, 4753, 5574), - (4755, -1, -1, 1210, 1213, 6, 71, -1, 0, 0, 12, 1215, 4756), - (4756, -1, -1, 1210, 1213, 6, 73, -1, 0, 0, 12, 4755, 4757), - (4757, -1, -1, 1210, 1213, 6, 75, -1, 0, 0, 12, 4756, 5577), - (4758, -1, -1, 602, 602, 6, 71, -1, 0, 0, 12, 1535, 4759), - (4759, -1, -1, 602, 602, 6, 73, -1, 0, 0, 12, 4758, 4760), - (4760, -1, -1, 602, 602, 6, 75, -1, 0, 0, 12, 4759, 5580), - (4761, -1, -1, 4761, 4761, 7, 71, -1, 0, 0, 12, -1, 4762), - (4762, -1, -1, 4761, 4761, 7, 73, -1, 0, 0, 12, 4761, 4763), - (4763, -1, -1, 4761, 4761, 7, 75, -1, 0, 0, 12, 4762, 6500), - (4764, -1, -1, 1071, 1071, 6, 75, -1, 0, 0, 14, 1071, 7553), - (4767, -1, -1, 98, 98, 4, 71, -1, 0, 0, 12, 100, 4768), - (4768, -1, -1, 98, 98, 4, 73, -1, 0, 0, 12, 4767, 4769), - (4769, -1, -1, 98, 98, 4, 75, -1, 0, 0, 12, 4768, 5586), - (4773, -1, -1, 1435, 4773, 9, 71, -1, 0, 0, 12, 1437, 6517), - (4776, -1, -1, 1186, 1186, 6, 71, -1, 0, 0, 12, 1188, 4777), - (4777, -1, -1, 1186, 1186, 6, 73, -1, 0, 0, 12, 4776, 4778), - (4778, -1, -1, 1186, 1186, 6, 75, -1, 0, 0, 12, 4777, 5589), - (4779, -1, -1, 80, 80, 6, 71, -1, 0, 0, 12, 1088, 4780), - (4780, -1, -1, 80, 80, 6, 73, -1, 0, 0, 12, 4779, 4781), - (4781, -1, -1, 80, 80, 6, 75, -1, 0, 0, 12, 4780, 5592), - (4790, -1, -1, 1134, 1134, 5, 71, -1, 0, 0, 12, 1162, 4791), - (4791, -1, -1, 1134, 1134, 5, 72, -1, 0, 0, 12, 4790, 4792), - (4792, -1, -1, 1134, 1134, 5, 73, -1, 0, 0, 12, 4791, 4793), - (4793, -1, -1, 1134, 1134, 5, 74, -1, 0, 0, 12, 4792, 4794), - (4794, -1, -1, 1134, 1134, 5, 75, -1, 0, 0, 12, 4793, 4804), - (4795, -1, -1, 255, 255, 5, 71, -1, 0, 0, 12, 1165, 4796), - (4796, -1, -1, 255, 255, 5, 73, -1, 0, 0, 12, 4795, 4797), - (4797, -1, -1, 255, 255, 5, 75, -1, 0, 0, 12, 4796, 5595), - (4798, -1, -1, 631, 631, 5, 71, -1, 0, 0, 12, 1174, 4799), - (4799, -1, -1, 631, 631, 5, 73, -1, 0, 0, 12, 4798, 4800), - (4800, -1, -1, 631, 631, 5, 75, -1, 0, 0, 12, 4799, -1), - (4801, -1, -1, 4801, 4801, 6, 74, -1, 0, 0, 14, -1, 4802), - (4802, -1, -1, 4801, 4801, 6, 76, -1, 0, 0, 14, 4801, 4803), - (4803, -1, -1, 4801, 4801, 6, 78, -1, 0, 0, 14, 4802, 7160), - (4804, -1, -1, 1134, 1134, 5, 76, -1, 0, 0, 15, 4794, 4805), - (4805, -1, -1, 1134, 1134, 5, 77, -1, 0, 0, 15, 4804, 4806), - (4806, -1, -1, 1134, 1134, 5, 78, -1, 0, 0, 15, 4805, 4807), - (4807, -1, -1, 1134, 1134, 5, 79, -1, 0, 0, 15, 4806, 4808), - (4808, -1, -1, 1134, 1134, 5, 80, -1, 0, 0, 15, 4807, 10311), - (4809, -1, -1, 4809, 4809, 5, 81, -1, 0, 0, 15, -1, 4810), - (4810, -1, -1, 4809, 4809, 5, 83, -1, 0, 0, 15, 4809, 4811), - (4811, -1, -1, 4809, 4809, 5, 85, -1, 0, 0, 15, 4810, 10316), - (4813, -1, -1, 820, 820, 5, 71, -1, 0, 0, 12, 1267, 4814), - (4814, -1, -1, 820, 820, 5, 73, -1, 0, 0, 12, 4813, 4815), - (4815, -1, -1, 820, 820, 5, 75, -1, 0, 0, 12, 4814, 5917), - (4819, -1, -1, 1528, 4819, 5, 71, -1, 0, 0, 12, 1532, 4820), - (4820, -1, -1, 1528, 4819, 5, 72, -1, 0, 0, 12, 4819, 4821), - (4821, -1, -1, 1528, 4819, 5, 73, -1, 0, 0, 12, 4820, 4822), - (4822, -1, -1, 1528, 4819, 5, 74, -1, 0, 0, 12, 4821, 4823), - (4823, -1, -1, 1528, 4819, 5, 75, -1, 0, 0, 12, 4822, 15188), - (4824, -1, -1, 810, 810, 5, 71, -1, 0, 0, 12, 814, 4825), - (4825, -1, -1, 810, 810, 5, 72, -1, 0, 0, 12, 4824, 4826), - (4826, -1, -1, 810, 810, 5, 73, -1, 0, 0, 12, 4825, 4827), - (4827, -1, -1, 810, 810, 5, 74, -1, 0, 0, 12, 4826, 4828), - (4828, -1, -1, 810, 810, 5, 75, -1, 0, 0, 12, 4827, 15426), - (4829, -1, -1, 1546, 1546, 5, 71, -1, 0, 0, 12, 1548, 4830), - (4830, -1, -1, 1546, 1546, 5, 72, -1, 0, 0, 12, 4829, 4831), - (4831, -1, -1, 1546, 1546, 5, 73, -1, 0, 0, 12, 4830, 6441), - (4836, 4836, 4836, 4836, 4836, 5, 71, 11033, 5, 30, 12, -1, -1), - (4844, -1, -1, 4844, 4844, 5, 71, -1, 0, 0, 12, -1, 4845), - (4845, -1, -1, 4844, 4844, 5, 72, -1, 0, 0, 12, 4844, 4846), - (4846, -1, -1, 4844, 4844, 5, 73, -1, 0, 0, 12, 4845, 4847), - (4847, -1, -1, 4844, 4844, 5, 74, -1, 0, 0, 12, 4846, 4848), - (4848, -1, -1, 4844, 4844, 5, 75, -1, 0, 0, 12, 4847, 7122), - (4849, 4849, 4849, 4849, 4849, 9, 71, 11041, 7, 1800, 12, -1, 6134), - (4854, 4854, 4854, 4854, 4854, 3, 71, 11046, 8, 600, 12, -1, 4855), - (4855, 4854, 4854, 4854, 4854, 6, 73, 11047, 8, 600, 12, 4854, 4856), - (4856, 4854, 4854, 4854, 4854, 9, 75, 11048, 8, 600, 12, 4855, 5764), - (4857, 4857, 4857, 4857, 4857, 3, 71, 11049, 7, 600, 12, -1, 4858), - (4858, 4857, 4857, 4857, 4857, 6, 73, 11050, 7, 600, 12, 4857, 4859), - (4859, 4857, 4857, 4857, 4857, 9, 75, 11051, 7, 600, 12, 4858, 5767), - (4860, 4860, 4860, 4860, 4860, 9, 75, 11052, 13, 60, 12, -1, 5606), - (4861, -1, -1, 4861, 4861, 6, 71, -1, 0, 0, 12, -1, 4862), - (4862, -1, -1, 4861, 4861, 6, 73, -1, 0, 0, 12, 4861, 4863), - (4863, -1, -1, 4861, 4861, 6, 75, -1, 0, 0, 12, 4862, 5954), - (4864, 1274, 1274, 1274, 1274, 6, 73, 11053, 9, 540, 12, 1276, 4865), - (4865, 1274, 1274, 1274, 1274, 6, 74, 11054, 9, 540, 12, 4864, 4866), - (4866, 1274, 1274, 1274, 1274, 6, 75, 11055, 9, 540, 12, 4865, 5947), - (4887, -1, -1, 4887, 4887, 6, 71, -1, 0, 0, 12, -1, 4888), - (4888, -1, -1, 4887, 4887, 6, 73, -1, 0, 0, 12, 4887, 4889), - (4889, -1, -1, 4887, 4887, 6, 75, -1, 0, 0, 12, 4888, -1), - (4890, 4890, -1, 4890, 4890, 9, 75, 11056, 3, 8640, 12, -1, 5869), - (4894, 4894, 4894, 4894, 4894, 6, 73, 11057, 7, 2160, 12, -1, 4895), - (4895, 4894, 4894, 4894, 4894, 6, 74, 11058, 7, 2160, 12, 4894, 4896), - (4896, 4894, 4894, 4894, 4894, 6, 75, 11059, 7, 2160, 12, 4895, 6352), - (4897, -1, -1, 795, 795, 6, 71, -1, 0, 0, 12, 1432, 4898), - (4898, -1, -1, 795, 795, 6, 73, -1, 0, 0, 12, 4897, 4899), - (4899, -1, -1, 795, 795, 6, 75, -1, 0, 0, 12, 4898, 5889), - (4900, 1462, 1462, 1462, 1462, 6, 71, 11061, 5, 300, 12, 1466, 4901), - (4901, 1462, 1462, 1462, 1462, 6, 73, 11062, 5, 300, 12, 4900, 4902), - (4902, 1462, 1462, 1462, 1462, 6, 75, 11063, 5, 300, 12, 4901, 14739), - (4903, 4903, 4903, 4903, 4903, 9, 71, 11064, 9, 1320, 12, -1, 5892), - (4906, 4906, 4906, 4906, 4906, 9, 71, 11065, 9, 1320, 12, -1, 5893), - (4909, 4909, 4909, 4909, 4909, 9, 71, 11066, 16, 1320, 12, -1, 5894), - (4912, 4912, 4912, 4912, 4912, 9, 71, 11067, 16, 1320, 12, -1, 5895), - (4915, 4915, 4915, 4915, 4915, 9, 71, 11068, 7, 4320, 12, -1, 4916), - (4916, 4915, 4915, 4915, 4915, 9, 73, 11069, 7, 4320, 12, 4915, 4917), - (4917, 4915, 4915, 4915, 4915, 9, 75, 11070, 7, 4320, 12, 4916, 5607), - (4921, -1, -1, 480, 480, 2, 71, -1, 0, 0, 12, 482, 4922), - (4922, -1, -1, 480, 480, 2, 73, -1, 0, 0, 12, 4921, 4923), - (4923, -1, -1, 480, 480, 2, 75, -1, 0, 0, 12, 4922, -1), - (4924, -1, -1, 4924, 4924, 5, 75, -1, 0, 0, 12, -1, 4925), - (4925, -1, -1, 4924, 4924, 5, 75, -1, 0, 0, 12, 4924, 4926), - (4926, -1, -1, 4924, 4924, 5, 75, -1, 0, 0, 12, 4925, 5944), - (4927, 4927, 4927, 4927, 4927, 9, 71, 11076, 14, 600, 12, -1, 7209), - (4931, 4931, 4931, 4931, 4931, 6, 71, 11083, 4, 600, 12, -1, 4932), - (4932, 4931, 4931, 4931, 4931, 6, 73, 11084, 4, 600, 12, 4931, 4933), - (4933, 4931, 4931, 4931, 4931, 6, 75, 11085, 4, 600, 12, 4932, 6054), - (4934, 4934, 4934, 4934, 4934, 7, 71, 11086, 13, 300, 12, -1, 7295), - (4935, 4935, 4935, 4935, 4935, 7, 71, 11087, 14, 300, 12, -1, 7294), - (4938, 4938, 4938, 4938, 4938, 9, 75, 11092, 35, 1800, 12, -1, 5610), - (4943, 4943, 4943, 4943, 4943, 7, 75, 11098, 17, 1800, 12, -1, -1), - (4944, 4944, -1, 4944, 4944, 3, 71, 11103, 0, 1, 12, -1, 4945), - (4945, 4944, -1, 4944, 4944, 6, 73, 11104, 0, 1, 12, 4944, 4946), - (4946, 4944, -1, 4944, 4944, 9, 75, 11105, 0, 1, 12, 4945, 6155), - (4948, -1, -1, 846, 846, 3, 71, -1, 0, 0, 12, 1303, 4949), - (4949, -1, -1, 846, 846, 6, 73, -1, 0, 0, 12, 4948, 4950), - (4950, -1, -1, 846, 846, 9, 75, -1, 0, 0, 12, 4949, 6035), - (4951, -1, -1, 1543, 1543, 5, 71, -1, 0, 0, 12, 1545, 4952), - (4952, -1, -1, 1543, 1543, 5, 73, -1, 0, 0, 12, 4951, 4953), - (4953, -1, -1, 1543, 1543, 5, 75, -1, 0, 0, 12, 4952, 6042), - (4957, -1, -1, 878, 878, 7, 71, -1, 0, 0, 12, 1541, 4958), - (4958, -1, -1, 878, 878, 7, 73, -1, 0, 0, 12, 4957, 4959), - (4959, -1, -1, 878, 878, 7, 75, -1, 0, 0, 12, 4958, 6331), - (4960, -1, -1, 729, 729, 6, 71, -1, 0, 0, 12, 1469, 4961), - (4961, -1, -1, 729, 729, 6, 73, -1, 0, 0, 12, 4960, 4962), - (4962, -1, -1, 729, 729, 6, 75, -1, 0, 0, 12, 4961, 5738), - (4963, 723, 723, 723, 723, 9, 71, 11205, 6, 30, 12, 723, 5737), - (4964, 1119, 1119, 1119, 1119, 6, 73, 11206, 8, 900, 12, 1121, 4965), - (4965, 1119, 1119, 1119, 1119, 6, 74, 11207, 8, 900, 12, 4964, 4966), - (4966, 1119, 1119, 1119, 1119, 6, 75, 11208, 8, 900, 12, 4965, 5734), - (4969, 291, 291, 291, 291, 5, 71, 11212, 5, 900, 12, 1125, 4970), - (4970, 291, 291, 291, 291, 5, 73, 11213, 5, 900, 12, 4969, 4971), - (4971, 291, 291, 291, 291, 5, 75, 11214, 5, 900, 12, 4970, 5743), - (4972, 1598, -1, 1598, 1598, 6, 71, 11215, 6, 900, 12, 1600, 4973), - (4973, 1598, -1, 1598, 1598, 6, 73, 11216, 6, 900, 12, 4972, 4974), - (4974, 1598, -1, 1598, 1598, 6, 75, 11217, 6, 900, 12, 4973, 5710), - (4975, 592, 592, 592, 592, 3, 71, 11218, 2, 18, 12, 1106, 4976), - (4976, 592, 592, 592, 592, 3, 72, 11219, 2, 18, 12, 4975, 4977), - (4977, 592, 592, 592, 592, 3, 73, 11220, 2, 18, 12, 4976, 4978), - (4978, 592, 592, 592, 592, 3, 74, 11221, 2, 18, 12, 4977, 4979), - (4979, 592, 592, 592, 592, 3, 75, 11222, 2, 18, 12, 4978, 5702), - (4980, 1116, 1116, 1116, 1116, 6, 73, 11223, 4, 2160, 12, 1118, 4981), - (4981, 1116, 1116, 1116, 1116, 6, 74, 11224, 4, 2160, 12, 4980, 4982), - (4982, 1116, 1116, 1116, 1116, 6, 75, 11225, 4, 2160, 12, 4981, 5699), - (4983, -1, -1, 864, 864, 6, 71, -1, 0, 0, 12, 1292, 4984), - (4984, -1, -1, 864, 864, 6, 73, -1, 0, 0, 12, 4983, 4985), - (4985, -1, -1, 864, 864, 6, 75, -1, 0, 0, 12, 4984, 6011), - (4986, -1, -1, 644, 644, 5, 67, -1, 0, 0, 12, 1603, 4987), - (4987, -1, -1, 644, 644, 5, 69, -1, 0, 0, 12, 4986, 4988), - (4988, -1, -1, 644, 644, 5, 71, -1, 0, 0, 12, 4987, 6017), - (4989, -1, -1, 1608, 1608, 6, 71, -1, 0, 0, 12, 1610, 4990), - (4990, -1, -1, 1608, 1608, 6, 73, -1, 0, 0, 12, 4989, 4991), - (4991, -1, -1, 1608, 1608, 6, 75, -1, 0, 0, 12, 4990, 7378), - (4992, -1, -1, 1616, 1616, 5, 71, -1, 0, 0, 12, 1620, 4993), - (4993, -1, -1, 1616, 1616, 5, 72, -1, 0, 0, 12, 4992, 4994), - (4994, -1, -1, 1616, 1616, 5, 73, -1, 0, 0, 12, 4993, 4995), - (4995, -1, -1, 1616, 1616, 5, 74, -1, 0, 0, 12, 4994, 4996), - (4996, -1, -1, 1616, 1616, 5, 75, -1, 0, 0, 12, 4995, 6003), - (4997, 545, 545, 545, 545, 6, 73, 11226, 3, 900, 12, 1295, 4998), - (4998, 545, 545, 545, 545, 6, 74, 11227, 3, 900, 12, 4997, 4999), - (4999, 545, 545, 545, 545, 6, 75, 11228, 3, 900, 12, 4998, 6000), - (5000, -1, -1, 1230, 1230, 2, 71, -1, 0, 0, 12, 1232, 5001), - (5001, -1, -1, 1230, 1230, 2, 73, -1, 0, 0, 12, 5000, 5002), - (5002, -1, -1, 1230, 1230, 2, 75, -1, 0, 0, 12, 5001, -1), - (5003, 1345, 1345, 1345, 1345, 5, 73, 11229, 6, 900, 12, 1347, 5004), - (5004, 1345, 1345, 1345, 1345, 5, 74, 11230, 6, 900, 12, 5003, 5005), - (5005, 1345, 1345, 1345, 1345, 5, 75, 11231, 6, 900, 12, 5004, 6008), - (5006, 5006, 5006, 5006, 5006, 0, 0, 27673, 96, 72000, 0, -1, -1), - (5007, 5007, 5007, 5007, 5007, 3, 71, 11233, 8, 2160, 12, -1, 5008), - (5008, 5007, 5007, 5007, 5007, 6, 73, 11234, 8, 2160, 12, 5007, 5009), - (5009, 5007, 5007, 5007, 5007, 9, 75, 11235, 8, 2160, 12, 5008, 6425), - (5010, -1, -1, 1007, 1007, 8, 81, -1, 0, 0, 16, -1, 5011), - (5011, -1, -1, 1007, 1007, 10, 83, -1, 0, 0, 16, 5010, 5012), - (5012, -1, -1, 1007, 1007, 12, 85, -1, 0, 0, 16, 5011, 15317), - (5013, -1, -1, 1284, 1284, 6, 83, -1, 0, 0, 16, 5037, 5014), - (5014, -1, -1, 1284, 1284, 6, 85, -1, 0, 0, 16, 5013, -1), - (5015, 5015, 5015, 5015, 5015, 5, 75, 11241, 9, 900, 12, -1, 5741), - (5017, 5017, 5017, 5017, 5017, 3, 71, 11243, 8, 600, 12, -1, 5018), - (5018, 5017, 5017, 5017, 5017, 6, 73, 11244, 8, 600, 12, 5017, 5019), - (5019, 5017, 5017, 5017, 5017, 9, 75, 11245, 8, 600, 12, 5018, 7454), - (5020, 5020, 5020, 5020, 5020, 9, 75, 11246, 9, 300, 12, -1, 5716), - (5021, 5021, 5021, 5021, 5021, 9, 71, 11341, 7, 60, 12, -1, 10868), - (5022, 5022, 5022, 5022, 5022, 3, 71, 11247, 5, 600, 12, -1, 5023), - (5023, 5022, 5022, 5022, 5022, 6, 73, 23986, 5, 600, 12, 5022, 5024), - (5024, 5022, 5022, 5022, 5022, 9, 75, 23987, 5, 600, 12, 5023, 6038), - (5025, 5025, 5025, 5025, 5025, 3, 71, 11251, 6, 180, 12, -1, 5026), - (5026, 5025, 5025, 5025, 5025, 6, 73, 11252, 6, 180, 12, 5025, 5027), - (5027, 5025, 5025, 5025, 5025, 9, 75, 11253, 6, 180, 12, 5026, -1), - (5028, 5028, -1, 5028, 5028, 9, 75, 11254, 4, 900, 12, -1, 6041), - (5029, -1, -1, 1313, 1313, 6, 71, -1, 0, 0, 8, 1315, 5030), - (5030, -1, -1, 1313, 1313, 6, 73, -1, 0, 0, 8, 5029, 5031), - (5031, -1, -1, 1313, 1313, 6, 75, -1, 0, 0, 8, 5030, 6066), - (5032, -1, -1, 634, 634, 5, 72, -1, 0, 0, 12, 1321, 5033), - (5033, -1, -1, 634, 634, 5, 73, -1, 0, 0, 12, 5032, 5034), - (5034, -1, -1, 634, 634, 5, 74, -1, 0, 0, 12, 5033, 5611), - (5035, -1, -1, 1284, 1284, 6, 71, -1, 0, 0, 12, 1286, 5036), - (5036, -1, -1, 1284, 1284, 6, 73, -1, 0, 0, 12, 5035, 5037), - (5037, -1, -1, 1284, 1284, 6, 75, -1, 0, 0, 12, 5036, 5013), - (5038, -1, -1, 190, 190, 7, 71, -1, 0, 0, 12, 1525, 5039), - (5039, -1, -1, 190, 190, 7, 73, -1, 0, 0, 12, 5038, 5040), - (5040, -1, -1, 190, 190, 7, 75, -1, 0, 0, 12, 5039, 15141), - (5041, 534, 534, 534, 534, 5, 72, 11255, 4, 2160, 12, 1280, 5042), - (5042, 534, 534, 534, 534, 5, 73, 11256, 4, 2160, 12, 5041, 5043), - (5043, 534, 534, 534, 534, 5, 74, 11257, 4, 2160, 12, 5042, 5969), - (5044, 188, 188, 188, 188, 9, 73, 11258, 2, 30, 12, 1277, 7339), - (5045, -1, -1, 1057, 1057, 9, 85, -1, 0, 0, 16, -1, -1), - (5051, 757, -1, 757, 757, 5, 71, 11262, 6, 1800, 12, 1224, 5052), - (5052, 757, -1, 757, 757, 5, 73, 11263, 6, 1800, 12, 5051, 5053), - (5053, 757, -1, 757, 757, 5, 75, 11264, 6, 1800, 12, 5052, 5822), - (5054, 548, 548, 548, 548, 5, 72, 11265, 5, 900, 12, 1227, 5055), - (5055, 548, 548, 548, 548, 5, 73, 11266, 5, 900, 12, 5054, 5056), - (5056, 548, 548, 548, 548, 5, 74, 11267, 5, 900, 12, 5055, 5829), - (5058, 1498, 1498, 1498, 1498, 6, 71, 11269, 12, 1320, 12, 1500, 5059), - (5059, 1498, 1498, 1498, 1498, 6, 73, 11270, 12, 1320, 12, 5058, 5060), - (5060, 1498, 1498, 1498, 1498, 6, 75, 11271, 12, 1320, 12, 5059, 5819), - (5061, -1, -1, 567, 567, 5, 72, -1, 0, 0, 12, 567, 5825), - (5062, 459, 459, 459, 459, 6, 71, 11272, 8, 180, 12, 1191, 5063), - (5063, 459, 459, 459, 459, 6, 73, 11273, 8, 180, 12, 5062, 5064), - (5064, 459, 459, 459, 459, 6, 75, 11274, 8, 180, 12, 5063, -1), - (5068, 153, 153, 153, 153, 9, 75, 11279, 3, 2160, 12, 1519, 6101), - (5069, 146, 146, 146, 146, 5, 72, 11281, 2, 180, 12, 146, 6102), - (5070, 131, 131, 131, 131, 5, 72, 11282, 4, 900, 12, 1205, 5071), - (5071, 131, 131, 131, 131, 5, 73, 11283, 4, 900, 12, 5070, 5072), - (5072, 131, 131, 131, 131, 5, 74, 11284, 4, 900, 12, 5071, 5791), - (5076, 1192, 1192, 1192, 1192, 5, 72, 11288, 12, 1320, 12, 1194, 5077), - (5077, 1192, 1192, 1192, 1192, 5, 73, 11289, 12, 1320, 12, 5076, 5078), - (5078, 1192, 1192, 1192, 1192, 5, 74, 11290, 12, 1320, 12, 5077, 5794), - (5079, 1195, 1195, 1195, 1195, 9, 75, 11291, 13, 2160, 12, 1195, 5790), - (5080, 1459, 1459, 1459, 1459, 5, 71, 11293, 11, 1800, 12, 1461, 5081), - (5081, 1459, 1459, 1459, 1459, 5, 73, 11294, 11, 1800, 12, 5080, 5082), - (5082, 1459, 1459, 1459, 1459, 5, 75, 11295, 11, 1800, 12, 5081, 5803), - (5084, 1383, 1383, 1383, 1383, 12, 75, 11296, 6, 300, 12, 1387, 5789), - (5085, -1, -1, 5085, 5085, 3, 71, -1, 0, 0, 12, -1, 5086), - (5086, -1, -1, 5085, 5085, 6, 73, -1, 0, 0, 12, 5085, 5087), - (5087, -1, -1, 5085, 5085, 9, 75, -1, 0, 0, 12, 5086, 6406), - (5095, 5095, 5095, 5095, 5095, 3, 71, 11307, 10, 900, 12, -1, 5096), - (5096, 5095, 5095, 5095, 5095, 6, 73, 11308, 10, 900, 12, 5095, 5097), - (5097, 5095, 5095, 5095, 5095, 9, 75, 11309, 10, 900, 12, 5096, 5975), - (5098, 5098, 5098, 5098, 5098, 9, 75, 11310, 2, 30, 12, -1, -1), - (5105, 5105, 5105, 5105, 5105, 9, 75, 11317, 11, 600, 12, -1, 5832), - (5109, 5109, 5109, 5109, 5109, 9, 75, 11321, 0, 1, 12, -1, 6448), - (5118, -1, -1, 5083, 5083, 3, 71, -1, 0, 0, 12, -1, 5119), - (5119, -1, -1, 5083, 5083, 3, 73, -1, 0, 0, 12, 5118, 5120), - (5120, -1, -1, 5083, 5083, 3, 75, -1, 0, 0, 12, 5119, 5797), - (5127, -1, -1, 5127, 5127, 3, 71, -1, 0, 0, 12, -1, 5128), - (5128, -1, -1, 5127, 5127, 3, 73, -1, 0, 0, 12, 5127, 5129), - (5129, -1, -1, 5127, 5127, 3, 75, -1, 0, 0, 12, 5128, -1), - (5130, 860, 860, 860, 860, 6, 71, 5860, 5, 180, 12, 862, 5131), - (5131, 860, 860, 860, 860, 6, 73, 5861, 5, 180, 12, 5130, 5132), - (5132, 860, 860, 860, 860, 6, 75, 5862, 5, 180, 12, 5131, -1), - (5133, -1, -1, 267, 267, 6, 71, -1, 0, 0, 12, 925, 5134), - (5134, -1, -1, 267, 267, 6, 73, -1, 0, 0, 12, 5133, 5135), - (5135, -1, -1, 267, 267, 6, 75, -1, 0, 0, 12, 5134, 5617), - (5136, -1, -1, 4688, 4688, 3, 71, -1, 0, 0, 12, -1, 5137), - (5137, -1, -1, 4688, 4688, 3, 72, -1, 0, 0, 12, 5136, 5138), - (5138, -1, -1, 4688, 4688, 3, 73, -1, 0, 0, 12, 5137, 5139), - (5139, -1, -1, 4688, 4688, 3, 74, -1, 0, 0, 12, 5138, 5140), - (5140, -1, -1, 4688, 4688, 3, 75, -1, 0, 0, 12, 5139, -1), - (5141, -1, -1, 815, 815, 5, 71, -1, 0, 0, 12, 819, 5142), - (5142, -1, -1, 815, 815, 5, 72, -1, 0, 0, 12, 5141, 5143), - (5143, -1, -1, 815, 815, 5, 73, -1, 0, 0, 12, 5142, 5144), - (5144, -1, -1, 815, 815, 5, 74, -1, 0, 0, 12, 5143, 5145), - (5145, -1, -1, 815, 815, 5, 75, -1, 0, 0, 12, 5144, 5909), - (5150, 5150, 5150, 5150, 5150, 0, 1, 11112, 22, 300, 3, -1, 5151), - (5165, 5165, 5165, 5165, 5165, 0, 1, 11127, 22, 300, 3, -1, 5166), - (5180, 5180, 5180, 5180, 5180, 0, 1, 11142, 22, 300, 3, -1, 5181), - (5195, 5195, 5195, 5195, 5195, 0, 1, 11157, 22, 300, 3, -1, 5196), - (5210, 5210, 5210, 5210, 5210, 0, 1, 11172, 22, 300, 3, -1, 5211), - (5225, 5225, 5225, 5225, 5225, 0, 1, 11187, 22, 300, 3, -1, 5226), - (5240, 1355, 1355, 1355, 1355, 6, 71, 11611, 3, 60, 12, 1357, 5241), - (5241, 1355, 1355, 1355, 1355, 6, 73, 11612, 3, 60, 12, 5240, 5242), - (5242, 1355, 1355, 1355, 1355, 6, 75, 11613, 3, 60, 12, 5241, 5914), - (5243, -1, -1, 907, 907, 7, 71, -1, 0, 0, 12, 911, 5244), - (5244, -1, -1, 907, 907, 7, 72, -1, 0, 0, 12, 5243, 5245), - (5245, -1, -1, 907, 907, 7, 73, -1, 0, 0, 12, 5244, 5246), - (5246, -1, -1, 907, 907, 7, 74, -1, 0, 0, 12, 5245, 5247), - (5247, -1, -1, 907, 907, 7, 75, -1, 0, 0, 12, 5246, -1), - (5248, -1, -1, 5248, 5248, 3, 71, -1, 0, 0, 12, -1, 5249), - (5249, -1, -1, 5248, 5248, 6, 73, -1, 0, 0, 12, 5248, 5250), - (5250, -1, -1, 5248, 5248, 9, 75, -1, 0, 0, 12, 5249, 6014), - (5251, 5251, 5251, 5251, 5251, 5, 71, 11615, 13, 900, 12, -1, 5252), - (5252, 5251, 5251, 5251, 5251, 5, 73, 11616, 13, 900, 12, 5251, 5253), - (5253, 5251, 5251, 5251, 5251, 5, 75, 11617, 13, 900, 12, 5252, 6092), - (5254, -1, -1, 724, 724, 3, 71, -1, 0, 0, 12, 728, 5255), - (5255, -1, -1, 724, 724, 3, 72, -1, 0, 0, 12, 5254, 5256), - (5256, -1, -1, 724, 724, 3, 73, -1, 0, 0, 12, 5255, 5257), - (5257, -1, -1, 724, 724, 3, 74, -1, 0, 0, 12, 5256, 5258), - (5258, -1, -1, 724, 724, 3, 75, -1, 0, 0, 12, 5257, 5729), - (5259, -1, -1, 790, 790, 3, 71, -1, 0, 0, 12, 794, 5260), - (5260, -1, -1, 790, 790, 3, 72, -1, 0, 0, 12, 5259, 5261), - (5261, -1, -1, 790, 790, 3, 73, -1, 0, 0, 12, 5260, 5262), - (5262, -1, -1, 790, 790, 3, 74, -1, 0, 0, 12, 5261, 5263), - (5263, -1, -1, 790, 790, 3, 75, -1, 0, 0, 12, 5262, 5320), - (5264, -1, -1, 5264, 5264, 3, 71, -1, 0, 0, 12, -1, 5265), - (5265, -1, -1, 5264, 5264, 3, 72, -1, 0, 0, 12, 5264, 5266), - (5266, -1, -1, 5264, 5264, 3, 73, -1, 0, 0, 12, 5265, 5267), - (5267, -1, -1, 5264, 5264, 3, 74, -1, 0, 0, 12, 5266, 5268), - (5268, -1, -1, 5264, 5264, 3, 75, -1, 0, 0, 12, 5267, 5939), - (5269, -1, -1, 5269, 5269, 3, 71, -1, 0, 0, 12, -1, -1), - (5270, -1, -1, 589, 589, 7, 71, -1, 0, 0, 12, 894, 5271), - (5271, -1, -1, 589, 589, 7, 73, -1, 0, 0, 12, 5270, 5272), - (5272, -1, -1, 589, 589, 7, 75, -1, 0, 0, 12, 5271, 6063), - (5276, -1, -1, 5276, 5276, 3, 71, -1, 0, 0, 12, -1, 5277), - (5277, -1, -1, 5276, 5276, 6, 73, -1, 0, 0, 12, 5276, 5278), - (5278, -1, -1, 5276, 5276, 9, 75, -1, 0, 0, 12, 5277, 15238), - (5279, 155, 155, 155, 155, 12, 75, 11624, 8, 60, 12, 1344, 5289), - (5280, 921, 921, 921, 921, 9, 74, 11625, 8, 60, 12, 1340, 6149), - (5281, 922, 922, 922, 922, 9, 73, 11626, 8, 60, 12, 1341, 6150), - (5282, 923, 923, 923, 923, 9, 72, 11627, 8, 60, 12, 1342, 6151), - (5283, -1, -1, 5263, 5263, 3, 71, -1, 0, 0, 12, -1, 5284), - (5284, -1, -1, 5263, 5263, 6, 73, -1, 0, 0, 12, 5283, 5285), - (5285, -1, -1, 5263, 5263, 9, 75, -1, 0, 0, 12, 5284, 5620), - (5286, -1, -1, 1107, 1107, 6, 71, -1, 0, 0, 12, 1109, 5287), - (5287, -1, -1, 1107, 1107, 6, 73, -1, 0, 0, 12, 5286, 5288), - (5288, -1, -1, 1107, 1107, 6, 75, -1, 0, 0, 12, 5287, 6403), - (5289, 155, 155, 155, 155, 12, 77, 13227, 8, 60, 14, 5279, 7238), - (5290, -1, -1, 1604, 1604, 5, 63, -1, 0, 0, 12, 1606, 5291), - (5291, -1, -1, 1604, 1604, 5, 64, -1, 0, 0, 12, 5290, 5292), - (5292, -1, -1, 1604, 1604, 5, 65, -1, 0, 0, 12, 5291, 5293), - (5293, -1, -1, 1604, 1604, 5, 66, -1, 0, 0, 12, 5292, 5294), - (5294, -1, -1, 1604, 1604, 5, 67, -1, 0, 0, 12, 5293, 6032), - (5295, -1, -1, 5295, 5295, 3, 71, -1, 0, 0, 12, -1, 5296), - (5296, -1, -1, 5295, 5295, 6, 73, -1, 0, 0, 12, 5295, 5297), - (5297, -1, -1, 5295, 5295, 9, 75, -1, 0, 0, 12, 5296, 6531), - (5298, 5298, 5298, 5298, 5298, 3, 71, 11630, 32, 1800, 12, -1, 5299), - (5299, 5298, 5298, 5298, 5298, 6, 73, 11631, 32, 1800, 12, 5298, 5300), - (5300, 5298, 5298, 5298, 5298, 9, 75, 11632, 32, 1800, 12, 5299, 5707), - (5301, -1, -1, 683, 683, 5, 71, -1, 0, 0, 12, 1038, 5302), - (5302, -1, -1, 683, 683, 5, 72, -1, 0, 0, 12, 5301, 5303), - (5303, -1, -1, 683, 683, 5, 73, -1, 0, 0, 12, 5302, 5304), - (5304, -1, -1, 683, 683, 5, 74, -1, 0, 0, 12, 5303, 5305), - (5305, -1, -1, 683, 683, 5, 75, -1, 0, 0, 12, 5304, 6080), - (5306, -1, -1, 658, 658, 5, 71, -1, 0, 0, 12, 660, 5307), - (5307, -1, -1, 658, 658, 5, 72, -1, 0, 0, 12, 5306, 5308), - (5308, -1, -1, 658, 658, 5, 73, -1, 0, 0, 12, 5307, 5309), - (5309, -1, -1, 658, 658, 5, 74, -1, 0, 0, 12, 5308, 5310), - (5310, -1, -1, 658, 658, 5, 75, -1, 0, 0, 12, 5309, 5623), - (5311, 1495, 1495, 1495, 1495, 5, 71, 11639, 30, 900, 12, 1497, 5312), - (5312, 1495, 1495, 1495, 1495, 5, 73, 11640, 30, 900, 12, 5311, 5313), - (5313, 1495, 1495, 1495, 1495, 5, 75, 11641, 30, 900, 12, 5312, 5826), - (5314, 1327, 1327, 1327, 1327, 5, 71, 11642, 10, 900, 12, 1329, 5315), - (5315, 1327, 1327, 1327, 1327, 5, 73, 11643, 10, 900, 12, 5314, 5316), - (5316, 1327, 1327, 1327, 1327, 5, 75, 11644, 10, 900, 12, 5315, 6098), - (5317, -1, -1, 98, 738, 4, 71, -1, 0, 0, 12, 740, 5318), - (5318, -1, -1, 98, 738, 4, 73, -1, 0, 0, 12, 5317, 5319), - (5319, -1, -1, 98, 738, 4, 75, -1, 0, 0, 12, 5318, 5628), - (5320, -1, -1, 790, 790, 6, 76, -1, 0, 0, 14, 5263, 5321), - (5321, -1, -1, 790, 790, 6, 77, -1, 0, 0, 14, 5320, 5322), - (5322, -1, -1, 790, 790, 6, 78, -1, 0, 0, 14, 5321, 5323), - (5323, -1, -1, 790, 790, 6, 79, -1, 0, 0, 14, 5322, 5324), - (5324, -1, -1, 790, 790, 6, 80, -1, 0, 0, 14, 5323, 7270), - (5325, -1, -1, 839, 839, 6, 70, -1, 0, 0, 14, 843, 5326), - (5326, -1, -1, 839, 839, 6, 70, -1, 0, 0, 14, 5325, 5327), - (5327, -1, -1, 839, 839, 6, 70, -1, 0, 0, 14, 5326, 5328), - (5328, -1, -1, 839, 839, 6, 70, -1, 0, 0, 14, 5327, 5329), - (5329, -1, -1, 839, 839, 6, 70, -1, 0, 0, 14, 5328, 7210), - (5330, 1327, 1327, 1327, 1327, 12, 91, 30870, 10, 900, 18, 10189, 5331), - (5333, 1520, 1520, 1520, 1520, 9, 91, 30873, 11, 900, 18, 12999, 5334), - (5336, 12989, 12989, 12989, 12989, 11, 91, 30876, 73, 1800, 18, 12991, 5337), - (5339, -1, -1, 6383, 6383, 11, 91, -1, 0, 0, 18, 12803, 5340), - (5342, 6692, 6692, 6692, 6692, 9, 91, 30879, 42, 600, 18, 6696, 5343), - (5347, -1, -1, 6375, 6375, 12, 91, -1, 0, 0, 18, 10086, 5348), - (5348, -1, -1, 6375, 6375, 15, 93, -1, 0, 0, 18, 5347, 5349), - (5350, 12992, 12992, 12992, 12992, 12, 91, 30884, 0, 1, 18, 12994, 5351), - (5353, 6706, 6706, 6706, 6706, 9, 91, 30887, 44, 600, 18, 10181, 5354), - (5356, 5109, 5109, 5109, 5109, 12, 92, 30890, 0, 1, 18, 13016, 17323), - (5357, 528, 528, 528, 528, 12, 91, 30891, 5, 720, 18, 13163, 5358), - (5360, -1, -1, 9503, 9503, 11, 91, -1, 0, 0, 18, 12794, 5361), - (5363, 5251, 5251, 5251, 5251, 15, 91, 30894, 13, 900, 18, 10199, 5364), - (5366, -1, -1, 5002, 5002, 12, 91, -1, 34, 0, 18, -1, 5367), - (5369, 5001, 5001, 5001, 5001, 12, 91, 30900, 32, 600, 18, -1, 5370), - (5500, -1, -1, 852, 852, 9, 78, -1, 0, 0, 14, 854, 5501), - (5501, -1, -1, 852, 852, 10, 79, -1, 0, 0, 14, 5500, 5502), - (5502, -1, -1, 852, 852, 12, 80, -1, 0, 0, 14, 5501, 7678), - (5513, 1126, 1126, 1126, 1126, 8, 77, 12668, 2, 2160, 14, 1128, 5514), - (5514, 1126, 1126, 1126, 1126, 9, 78, 12669, 2, 2160, 14, 5513, 5515), - (5515, 1126, 1126, 1126, 1126, 10, 79, 12670, 2, 2160, 14, 5514, 13253), - (5516, -1, -1, 1287, 1287, 8, 77, -1, 0, 0, 14, 1289, 5517), - (5517, -1, -1, 1287, 1287, 9, 78, -1, 0, 0, 14, 5516, 5518), - (5518, -1, -1, 1287, 1287, 10, 79, -1, 0, 0, 14, 5517, 12469), - (5519, -1, -1, 125, 125, 6, 76, -1, 0, 0, 14, 1398, 5520), - (5520, -1, -1, 125, 125, 7, 77, -1, 0, 0, 14, 5519, 5521), - (5521, -1, -1, 125, 125, 8, 78, -1, 0, 0, 14, 5520, 5522), - (5522, -1, -1, 125, 125, 9, 79, -1, 0, 0, 14, 5521, 5523), - (5523, -1, -1, 125, 125, 10, 80, -1, 0, 0, 14, 5522, 7501), - (5524, -1, -1, 122, 122, 6, 76, -1, 0, 0, 14, 1403, 5525), - (5525, -1, -1, 122, 122, 7, 77, -1, 0, 0, 14, 5524, 5526), - (5526, -1, -1, 122, 122, 8, 78, -1, 0, 0, 14, 5525, 5527), - (5527, -1, -1, 122, 122, 9, 79, -1, 0, 0, 14, 5526, 5528), - (5528, -1, -1, 122, 122, 10, 80, -1, 0, 0, 14, 5527, 7506), - (5529, -1, -1, 1486, 1486, 7, 76, -1, 0, 0, 14, 1490, 5530), - (5530, -1, -1, 1486, 1486, 8, 77, -1, 0, 0, 14, 5529, 5531), - (5531, -1, -1, 1486, 1486, 9, 78, -1, 0, 0, 14, 5530, 5532), - (5532, -1, -1, 1486, 1486, 10, 79, -1, 0, 0, 14, 5531, 5533), - (5533, -1, -1, 1486, 1486, 12, 80, -1, 0, 0, 14, 5532, 7554), - (5534, -1, -1, 599, 599, 9, 78, -1, 0, 0, 14, 1538, 5535), - (5535, -1, -1, 599, 599, 10, 79, -1, 0, 0, 14, 5534, 5536), - (5536, -1, -1, 599, 599, 12, 80, -1, 0, 0, 14, 5535, 7559), - (5542, -1, -1, 1041, 1041, 7, 76, -1, 0, 0, 14, 4709, 5543), - (5543, -1, -1, 1041, 1041, 9, 78, -1, 0, 0, 14, 5542, 5544), - (5544, -1, -1, 1041, 1041, 12, 80, -1, 0, 0, 14, 5543, 7562), - (5545, -1, -1, 1044, 1044, 7, 76, -1, 0, 0, 14, 4712, 5546), - (5546, -1, -1, 1044, 1044, 9, 78, -1, 0, 0, 14, 5545, 5547), - (5547, -1, -1, 1044, 1044, 12, 80, -1, 0, 0, 14, 5546, 7650), - (5548, -1, -1, 1047, 1047, 7, 76, -1, 0, 0, 14, 4715, 5549), - (5549, -1, -1, 1047, 1047, 9, 78, -1, 0, 0, 14, 5548, 5550), - (5550, -1, -1, 1047, 1047, 12, 80, -1, 0, 0, 14, 5549, 7653), - (5551, -1, -1, 1050, 1050, 7, 76, -1, 0, 0, 14, 4718, 5552), - (5552, -1, -1, 1050, 1050, 9, 78, -1, 0, 0, 14, 5551, 5553), - (5553, -1, -1, 1050, 1050, 12, 80, -1, 0, 0, 14, 5552, 7656), - (5554, -1, -1, 119, 119, 7, 76, -1, 0, 0, 14, 4724, 5555), - (5555, -1, -1, 119, 119, 9, 78, -1, 0, 0, 14, 5554, 5556), - (5556, -1, -1, 119, 119, 12, 80, -1, 0, 0, 14, 5555, 7565), - (5557, -1, -1, 1592, 1592, 7, 76, -1, 0, 0, 14, 4729, 5558), - (5558, -1, -1, 1592, 1592, 8, 77, -1, 0, 0, 14, 5557, 5559), - (5559, -1, -1, 1592, 1592, 9, 78, -1, 0, 0, 14, 5558, 5560), - (5560, -1, -1, 1592, 1592, 10, 79, -1, 0, 0, 14, 5559, 5561), - (5561, -1, -1, 1592, 1592, 12, 80, -1, 0, 0, 14, 5560, 7568), - (5562, -1, -1, 4739, 4739, 7, 76, -1, 0, 0, 14, 4741, 5563), - (5563, -1, -1, 4739, 4739, 9, 78, -1, 0, 0, 14, 5562, 5564), - (5564, -1, -1, 4739, 4739, 12, 80, -1, 0, 0, 14, 5563, 7573), - (5565, 4742, 4742, 4742, 4742, 7, 76, 12671, 12, 600, 14, 4742, -1), - (5566, -1, -1, 1072, 1072, 7, 76, -1, 0, 0, 14, 4748, 5567), - (5567, -1, -1, 1072, 1072, 8, 77, -1, 0, 0, 14, 5566, 5568), - (5568, -1, -1, 1072, 1072, 9, 78, -1, 0, 0, 14, 5567, 5569), - (5569, -1, -1, 1072, 1072, 10, 79, -1, 0, 0, 14, 5568, 5570), - (5570, -1, -1, 1072, 1072, 12, 80, -1, 0, 0, 14, 5569, 7576), - (5571, -1, -1, 637, 637, 7, 76, -1, 0, 0, 14, 4751, 5572), - (5572, -1, -1, 637, 637, 9, 78, -1, 0, 0, 14, 5571, 5573), - (5573, -1, -1, 637, 637, 12, 80, -1, 0, 0, 14, 5572, 12435), - (5574, -1, -1, 1210, 1210, 7, 76, -1, 0, 0, 14, 4754, 5575), - (5575, -1, -1, 1210, 1210, 9, 78, -1, 0, 0, 14, 5574, 5576), - (5576, -1, -1, 1210, 1210, 12, 80, -1, 0, 0, 14, 5575, 7232), - (5577, -1, -1, 1210, 1213, 7, 76, -1, 0, 0, 14, 4757, 5578), - (5578, -1, -1, 1210, 1213, 9, 78, -1, 0, 0, 14, 5577, 5579), - (5579, -1, -1, 1210, 1213, 12, 80, -1, 0, 0, 14, 5578, 7581), - (5580, -1, -1, 602, 602, 7, 76, -1, 0, 0, 14, 4760, 5581), - (5581, -1, -1, 602, 602, 9, 78, -1, 0, 0, 14, 5580, 5582), - (5582, -1, -1, 602, 602, 12, 80, -1, 0, 0, 14, 5581, 10685), - (5586, -1, -1, 98, 98, 7, 76, -1, 0, 0, 14, 4769, 5587), - (5587, -1, -1, 98, 98, 9, 78, -1, 0, 0, 14, 5586, 5588), - (5588, -1, -1, 98, 98, 12, 80, -1, 0, 0, 14, 5587, 7584), - (5589, -1, -1, 1186, 1186, 7, 76, -1, 0, 0, 14, 4778, 5590), - (5590, -1, -1, 1186, 1186, 9, 78, -1, 0, 0, 14, 5589, 5591), - (5591, -1, -1, 1186, 1186, 12, 80, -1, 0, 0, 14, 5590, 7587), - (5592, -1, -1, 80, 80, 7, 76, -1, 0, 0, 14, 4781, 5593), - (5593, -1, -1, 80, 80, 9, 78, -1, 0, 0, 14, 5592, 5594), - (5594, -1, -1, 80, 80, 12, 80, -1, 0, 0, 14, 5593, 7590), - (5595, -1, -1, 255, 255, 7, 76, -1, 0, 0, 14, 4797, 5596), - (5596, -1, -1, 255, 255, 9, 78, -1, 0, 0, 14, 5595, 5597), - (5597, -1, -1, 255, 255, 12, 80, -1, 0, 0, 14, 5596, 7631), - (5606, 4860, 4860, 4860, 4860, 12, 80, 11688, 13, 60, 14, 4860, 7127), - (5607, 4915, 4915, 4915, 4915, 7, 76, 12673, 7, 4320, 14, 4917, 5608), - (5608, 4915, 4915, 4915, 4915, 9, 78, 12674, 7, 4320, 14, 5607, 5609), - (5609, 4915, 4915, 4915, 4915, 12, 80, 12675, 7, 4320, 14, 5608, 7246), - (5610, 4938, 4938, 4938, 4938, 12, 80, 12676, 35, 1800, 14, 4938, 5614), - (5611, -1, -1, 634, 634, 7, 76, -1, 0, 0, 14, 5034, 5612), - (5612, -1, -1, 634, 634, 9, 78, -1, 0, 0, 14, 5611, 5613), - (5613, -1, -1, 634, 634, 12, 80, -1, 0, 0, 14, 5612, 7713), - (5614, 4938, 4938, 4938, 4938, 9, 85, 16852, 35, 1800, 16, 5610, 12875), - (5617, -1, -1, 267, 267, 7, 76, -1, 0, 0, 14, 5135, 5618), - (5618, -1, -1, 267, 267, 9, 78, -1, 0, 0, 14, 5617, 5619), - (5619, -1, -1, 267, 267, 12, 80, -1, 0, 0, 14, 5618, 12860), - (5620, -1, -1, 5263, 5263, 7, 76, -1, 0, 0, 14, 5285, 5621), - (5621, -1, -1, 5263, 5263, 9, 78, -1, 0, 0, 14, 5620, 5622), - (5622, -1, -1, 5263, 5263, 12, 80, -1, 0, 0, 14, 5621, 12466), - (5623, -1, -1, 658, 658, 5, 76, -1, 0, 0, 14, 5310, 5624), - (5624, -1, -1, 658, 658, 5, 77, -1, 0, 0, 14, 5623, 5625), - (5625, -1, -1, 658, 658, 5, 78, -1, 0, 0, 14, 5624, 5626), - (5626, -1, -1, 658, 658, 5, 79, -1, 0, 0, 14, 5625, 5627), - (5627, -1, -1, 658, 658, 5, 80, -1, 0, 0, 14, 5626, 7593), - (5628, -1, -1, 98, 738, 7, 76, -1, 0, 0, 14, 5319, 5629), - (5629, -1, -1, 98, 738, 9, 78, -1, 0, 0, 14, 5628, 5630), - (5630, -1, -1, 98, 738, 12, 80, -1, 0, 0, 14, 5629, 7598), - (5699, 1116, 1116, 1116, 1116, 7, 76, 12500, 4, 2160, 14, 4982, 5700), - (5700, 1116, 1116, 1116, 1116, 9, 78, 12501, 4, 2160, 14, 5699, 5701), - (5701, 1116, 1116, 1116, 1116, 12, 80, 12502, 4, 2160, 14, 5700, 7430), - (5702, 592, 592, 592, 592, 4, 76, 12503, 2, 18, 14, 4979, 5703), - (5703, 592, 592, 592, 592, 4, 77, 12504, 2, 18, 14, 5702, 5704), - (5704, 592, 592, 592, 592, 4, 78, 12505, 2, 18, 14, 5703, 5705), - (5705, 592, 592, 592, 592, 4, 79, 12506, 2, 18, 14, 5704, 5706), - (5706, 592, 592, 592, 592, 4, 80, 12507, 2, 18, 14, 5705, 7433), - (5707, 5298, 5298, 5298, 5298, 9, 78, 12508, 32, 1800, 14, 5300, 5708), - (5708, 5298, 5298, 5298, 5298, 10, 79, 12509, 32, 1800, 14, 5707, 5709), - (5709, 5298, 5298, 5298, 5298, 12, 80, 12510, 32, 1800, 14, 5708, 7438), - (5710, 1598, -1, 1598, 1598, 7, 76, 12511, 6, 900, 14, 4974, 5711), - (5711, 1598, -1, 1598, 1598, 9, 78, 12512, 6, 900, 14, 5710, 5712), - (5712, 1598, -1, 1598, 1598, 12, 80, 12513, 6, 900, 14, 5711, 7441), - (5713, 1569, 1569, 1569, 1569, 7, 76, 12514, 5, 1800, 14, 1571, 5714), - (5714, 1569, 1569, 1569, 1569, 9, 78, 12515, 5, 1800, 14, 5713, 5715), - (5715, 1569, 1569, 1569, 1569, 12, 80, 12516, 5, 1800, 14, 5714, 7457), - (5716, 5020, 5020, 5020, 5020, 9, 77, 12517, 9, 300, 14, 5020, 7444), - (5717, 5717, 5717, 5717, 5717, 10, 76, 12519, 17, 600, 14, -1, -1), - (5729, -1, -1, 724, 724, 7, 76, -1, 0, 0, 14, 5258, 5730), - (5730, -1, -1, 724, 724, 8, 77, -1, 0, 0, 14, 5729, 5731), - (5731, -1, -1, 724, 724, 9, 78, -1, 0, 0, 14, 5730, 5732), - (5732, -1, -1, 724, 724, 10, 79, -1, 0, 0, 14, 5731, 5733), - (5733, -1, -1, 724, 724, 12, 80, -1, 0, 0, 14, 5732, 7489), - (5734, 1119, 1119, 1119, 1119, 7, 78, 12520, 8, 900, 14, 4966, 5735), - (5735, 1119, 1119, 1119, 1119, 8, 79, 12521, 8, 900, 14, 5734, 5736), - (5736, 1119, 1119, 1119, 1119, 9, 80, 12522, 8, 900, 14, 5735, 7479), - (5737, 723, 723, 723, 723, 7, 76, 12523, 6, 30, 14, 4963, 7482), - (5738, -1, -1, 729, 729, 7, 76, -1, 0, 0, 14, 4962, 5739), - (5739, -1, -1, 729, 729, 8, 77, -1, 0, 0, 14, 5738, 5740), - (5740, -1, -1, 729, 729, 9, 78, -1, 0, 0, 14, 5739, 7494), - (5741, 5015, 5015, 5015, 5015, 12, 80, 12524, 9, 900, 14, 5015, 7483), - (5742, 289, 289, 289, 289, 12, 80, 12525, 3, 300, 14, 1607, 7484), - (5743, 291, 291, 291, 291, 9, 78, 12526, 5, 900, 14, 4971, 5744), - (5744, 291, 291, 291, 291, 10, 79, 12527, 5, 900, 14, 5743, 5745), - (5745, 291, 291, 291, 291, 12, 80, 12528, 5, 900, 14, 5744, 7485), - (5759, 1425, 1425, 1425, 1425, 7, 78, 13565, 2, 2160, 14, 1429, 5760), - (5760, 1425, 1425, 1425, 1425, 8, 78, 13570, 2, 2160, 14, 5759, 5761), - (5761, 1425, 1425, 1425, 1425, 9, 79, 13575, 2, 2160, 14, 5760, 5762), - (5762, 1425, 1425, 1425, 1425, 10, 79, 13580, 2, 2160, 14, 5761, 5763), - (5763, 1425, 1425, 1425, 1425, 11, 80, 13585, 2, 2160, 14, 5762, -1), - (5764, 4854, 4854, 4854, 4854, 7, 76, 12534, 8, 600, 14, 4856, 5765), - (5765, 4854, 4854, 4854, 4854, 9, 78, 12535, 8, 600, 14, 5764, 5766), - (5766, 4854, 4854, 4854, 4854, 12, 80, 12536, 8, 600, 14, 5765, 7178), - (5767, 4857, 4857, 4857, 4857, 7, 76, 12537, 7, 600, 14, 4859, 5768), - (5768, 4857, 4857, 4857, 4857, 9, 78, 12538, 7, 600, 14, 5767, 5769), - (5769, 4857, 4857, 4857, 4857, 12, 80, 12539, 7, 600, 14, 5768, 17030), - (5770, 1348, 1348, 1348, 1348, 9, 78, 12540, 0, 3600, 14, 1350, 5771), - (5771, 1348, 1348, 1348, 1348, 10, 79, 12541, 0, 3600, 14, 5770, 5772), - (5772, 1348, 1348, 1348, 1348, 12, 80, 12542, 0, 3600, 14, 5771, 7184), - (5776, -1, -1, 5776, 5776, 7, 76, -1, 0, 0, 14, -1, 5777), - (5777, -1, -1, 5776, 5776, 9, 78, -1, 0, 0, 14, 5776, 5778), - (5778, -1, -1, 5776, 5776, 12, 80, -1, 0, 0, 14, 5777, 7196), - (5779, 1178, 1178, 1178, 1178, 7, 76, 12546, 4, 900, 14, 1180, 5780), - (5780, 1178, 1178, 1178, 1178, 8, 77, 12547, 4, 900, 14, 5779, 5781), - (5781, 1178, 1178, 1178, 1178, 9, 78, 12548, 4, 900, 14, 5780, 7187), - (5789, 1383, 1383, 1383, 1383, 12, 80, 12549, 6, 300, 14, 5084, 7299), - (5790, 1195, 1195, 1195, 1195, 9, 80, 12550, 13, 2160, 14, 5079, 7300), - (5791, 131, 131, 131, 131, 8, 77, 12551, 4, 900, 14, 5072, 5792), - (5792, 131, 131, 131, 131, 9, 78, 12552, 4, 900, 14, 5791, 5793), - (5793, 131, 131, 131, 131, 10, 79, 12553, 4, 900, 14, 5792, 7301), - (5794, 1192, 1192, 1192, 1192, 8, 77, 12554, 12, 1320, 14, 5078, 5795), - (5795, 1192, 1192, 1192, 1192, 9, 78, 12555, 12, 1320, 14, 5794, 5796), - (5796, 1192, 1192, 1192, 1192, 10, 79, 12556, 12, 1320, 14, 5795, 7304), - (5797, -1, -1, 5083, 5083, 7, 76, -1, 0, 0, 14, 5120, 5798), - (5798, -1, -1, 5083, 5083, 9, 78, -1, 0, 0, 14, 5797, 5799), - (5799, -1, -1, 5083, 5083, 12, 80, -1, 0, 0, 14, 5798, -1), - (5800, 746, 746, 746, 746, 9, 78, 12557, 10, 2160, 14, 1493, 5801), - (5801, 746, 746, 746, 746, 10, 79, 12558, 10, 2160, 14, 5800, 5802), - (5802, 746, 746, 746, 746, 12, 80, 12559, 10, 2160, 14, 5801, 7307), - (5803, 1459, 1459, 1459, 1459, 7, 76, 12560, 11, 1800, 14, 5082, 5804), - (5804, 1459, 1459, 1459, 1459, 9, 78, 12561, 11, 1800, 14, 5803, 5805), - (5805, 1459, 1459, 1459, 1459, 12, 80, 12562, 11, 1800, 14, 5804, 7310), - (5806, -1, -1, 255, 255, 7, 59, -1, 0, 0, 16, -1, 5807), - (5807, -1, -1, 255, 255, 9, 59, -1, 0, 0, 16, 5806, 5808), - (5808, -1, -1, 255, 255, 12, 59, -1, 0, 0, 16, 5807, 10623), - (5809, 5833, 5833, 5833, 5833, 9, 85, 20184, 72, 900, 16, -1, -1), - (5819, 1498, 1498, 1498, 1498, 7, 76, 12563, 12, 1320, 14, 5060, 5820), - (5820, 1498, 1498, 1498, 1498, 9, 78, 12564, 12, 1320, 14, 5819, 5821), - (5821, 1498, 1498, 1498, 1498, 12, 80, 12565, 12, 1320, 14, 5820, 7408), - (5822, 757, -1, 757, 757, 7, 76, 12566, 6, 1800, 14, 5053, 5823), - (5823, 757, -1, 757, 757, 9, 78, 12567, 6, 1800, 14, 5822, 5824), - (5824, 757, -1, 757, 757, 12, 80, 12568, 6, 1800, 14, 5823, 7411), - (5825, -1, -1, 567, 567, 7, 76, -1, 0, 0, 14, 5061, -1), - (5826, 1495, 1495, 1495, 1495, 7, 76, 12569, 30, 900, 14, 5313, 5827), - (5827, 1495, 1495, 1495, 1495, 9, 78, 12570, 30, 900, 14, 5826, 5828), - (5828, 1495, 1495, 1495, 1495, 12, 80, 12571, 30, 900, 14, 5827, 7414), - (5829, 548, 548, 548, 548, 8, 77, 12572, 5, 900, 14, 5056, 5830), - (5830, 548, 548, 548, 548, 9, 78, 12573, 5, 900, 14, 5829, 5831), - (5831, 548, 548, 548, 548, 10, 79, 12574, 5, 900, 14, 5830, 7417), - (5832, 5105, 5105, 5105, 5105, 12, 80, 12575, 11, 600, 14, 5105, 7420), - (5849, 54009, 54009, 54009, 54009, 7, 73, 12576, 22, 12, 14, -1, 12923), - (5850, -1, -1, 781, 781, 8, 77, -1, 0, 0, 14, 781, 7284), - (5854, 773, -1, 773, 773, 7, 76, 12580, 5, 1800, 14, 775, 5855), - (5855, 773, -1, 773, 773, 9, 78, 12581, 5, 1800, 14, 5854, 5856), - (5856, 773, -1, 773, 773, 12, 80, 12582, 5, 1800, 14, 5855, 7276), - (5857, 1242, 1242, 1242, 1242, 7, 76, 12577, 9, 1320, 14, 1244, 5858), - (5858, 1242, 1242, 1242, 1242, 9, 78, 12578, 9, 1320, 14, 5857, 5859), - (5859, 1242, 1242, 1242, 1242, 12, 80, 12579, 9, 1320, 14, 5858, 7285), - (5860, -1, -1, 649, 649, 7, 76, -1, 0, 0, 14, 651, 5861), - (5861, -1, -1, 649, 649, 9, 78, -1, 0, 0, 14, 5860, 5862), - (5862, -1, -1, 649, 649, 12, 80, -1, 0, 0, 14, 5861, -1), - (5868, 1239, 1239, 1239, 1239, 12, 80, 13224, 6, 600, 14, 1239, 7275), - (5869, 4890, -1, 4890, 4890, 9, 77, 12587, 3, 8640, 14, 4890, 5871), - (5870, 54010, 54010, 54010, 54010, 7, 73, 12828, 22, 6, 14, -1, -1), - (5871, 4890, -1, 4890, 4890, 9, 79, 16440, 3, 8640, 15, 5869, 5872), - (5872, 4890, -1, 4890, 4890, 9, 81, 21745, 3, 8640, 16, 5871, 14280), - (5879, 167, 167, 167, 167, 10, 79, 12588, 14, 900, 14, 167, 7249), - (5880, -1, -1, 1504, 1504, 5, 76, -1, 0, 0, 14, 1506, 5881), - (5881, -1, -1, 1504, 1504, 5, 78, -1, 0, 0, 14, 5880, 5882), - (5882, -1, -1, 1504, 1504, 5, 80, -1, 0, 0, 14, 5881, 7260), - (5883, 520, 520, 520, 520, 12, 76, 12589, 6, 540, 14, 1509, 5884), - (5884, 520, 520, 520, 520, 12, 78, 12590, 6, 540, 14, 5883, 5885), - (5885, 520, 520, 520, 520, 12, 80, 12591, 6, 540, 14, 5884, 7250), - (5886, -1, -1, 1577, 1577, 7, 76, -1, 0, 0, 14, 1579, 5887), - (5887, -1, -1, 1577, 1577, 9, 78, -1, 0, 0, 14, 5886, 5888), - (5888, -1, -1, 1577, 1577, 12, 80, -1, 0, 0, 14, 5887, 7263), - (5889, -1, -1, 795, 795, 7, 76, -1, 0, 0, 14, 4899, 5890), - (5890, -1, -1, 795, 795, 9, 78, -1, 0, 0, 14, 5889, 5891), - (5891, -1, -1, 795, 795, 12, 80, -1, 0, 0, 14, 5890, 7267), - (5892, 4903, 4903, 4903, 4903, 9, 76, 12592, 9, 1320, 14, 4903, 7253), - (5893, 4906, 4906, 4906, 4906, 9, 76, 12593, 9, 1320, 14, 4906, 7254), - (5894, 4909, 4909, 4909, 4909, 9, 76, 12594, 16, 1320, 14, 4909, 7255), - (5895, 4912, 4912, 4912, 4912, 9, 76, 12595, 16, 1320, 14, 4912, 7256), - (5909, -1, -1, 815, 815, 7, 76, -1, 0, 0, 14, 5145, 5910), - (5910, -1, -1, 815, 815, 8, 77, -1, 0, 0, 14, 5909, 5911), - (5911, -1, -1, 815, 815, 9, 78, -1, 0, 0, 14, 5910, 5912), - (5912, -1, -1, 815, 815, 10, 79, -1, 0, 0, 14, 5911, 5913), - (5913, -1, -1, 815, 815, 12, 80, -1, 0, 0, 14, 5912, 7634), - (5914, 1355, 1355, 1355, 1355, 6, 76, 12596, 3, 60, 14, 5242, 5915), - (5915, 1355, 1355, 1355, 1355, 6, 78, 12597, 3, 60, 14, 5914, 5916), - (5916, 1355, 1355, 1355, 1355, 6, 80, 12598, 3, 60, 14, 5915, 7172), - (5917, -1, -1, 820, 820, 5, 76, -1, 0, 0, 14, 4815, 5918), - (5918, -1, -1, 820, 820, 5, 78, -1, 0, 0, 14, 5917, 5919), - (5919, -1, -1, 820, 820, 5, 80, -1, 0, 0, 14, 5918, 7163), - (5922, -1, -1, 807, 807, 5, 76, -1, 0, 0, 14, 1270, 5923), - (5923, -1, -1, 807, 807, 5, 78, -1, 0, 0, 14, 5922, 5924), - (5924, -1, -1, 807, 807, 5, 80, -1, 0, 0, 14, 5923, 7628), - (5939, -1, -1, 5264, 5264, 7, 76, -1, 0, 0, 14, 5268, 5940), - (5940, -1, -1, 5264, 5264, 8, 77, -1, 0, 0, 14, 5939, 5941), - (5941, -1, -1, 5264, 5264, 9, 78, -1, 0, 0, 14, 5940, 5942), - (5942, -1, -1, 5264, 5264, 10, 79, -1, 0, 0, 14, 5941, 5943), - (5943, -1, -1, 5264, 5264, 12, 80, -1, 0, 0, 14, 5942, 7204), - (5944, -1, -1, 4924, 4924, 9, 78, -1, 0, 0, 14, 4926, 5945), - (5945, -1, -1, 4924, 4924, 10, 79, -1, 0, 0, 14, 5944, 5946), - (5946, -1, -1, 4924, 4924, 12, 80, -1, 0, 0, 14, 5945, -1), - (5947, 1274, 1274, 1274, 1274, 9, 78, 12599, 9, 540, 14, 4866, 5948), - (5948, 1274, 1274, 1274, 1274, 10, 79, 12600, 9, 540, 14, 5947, 5949), - (5949, 1274, 1274, 1274, 1274, 12, 80, 12601, 9, 540, 14, 5948, 7199), - (5950, -1, -1, 1511, 1511, 12, 80, -1, 0, 0, 14, 1513, 5951), - (5951, -1, -1, 1511, 1511, 12, 80, -1, 0, 0, 14, 5950, 5952), - (5952, -1, -1, 1511, 1511, 12, 80, -1, 0, 0, 14, 5951, -1), - (5953, 184, 184, 184, 184, 10, 79, 12602, 5, 4320, 14, 184, 7203), - (5954, -1, -1, 4861, 4861, 7, 76, -1, 0, 0, 14, 4863, 5955), - (5955, -1, -1, 4861, 4861, 9, 78, -1, 0, 0, 14, 5954, 5956), - (5956, -1, -1, 4861, 4861, 12, 80, -1, 0, 0, 14, 5955, 7215), - (5969, 534, 534, 534, 534, 7, 76, 12603, 4, 2160, 14, 5043, 5970), - (5970, 534, 534, 534, 534, 9, 78, 12604, 4, 2160, 14, 5969, 5971), - (5971, 534, 534, 534, 534, 12, 80, 12605, 4, 2160, 14, 5970, 7329), - (5972, -1, -1, 593, 593, 7, 76, -1, 0, 0, 14, 595, -1), - (5973, -1, -1, 596, 596, 7, 76, -1, 0, 0, 14, 598, -1), - (5975, 5095, 5095, 5095, 5095, 7, 76, 12606, 10, 900, 14, 5097, 5976), - (5976, 5095, 5095, 5095, 5095, 9, 78, 12607, 10, 900, 14, 5975, 5977), - (5977, 5095, 5095, 5095, 5095, 12, 80, 12608, 10, 900, 14, 5976, 7332), - (5984, 5984, 5984, 5984, 5984, 12, 80, 12609, 2, 30, 14, -1, 7335), - (5999, 645, -1, 645, 645, 10, 79, 12610, 4, 5, 14, 645, 10739), - (6000, 545, 545, 545, 545, 7, 76, 12611, 3, 900, 14, 4999, 6001), - (6001, 545, 545, 545, 545, 9, 78, 12612, 3, 900, 14, 6000, 6002), - (6002, 545, 545, 545, 545, 12, 80, 12613, 3, 900, 14, 6001, 7344), - (6003, -1, -1, 1616, 1616, 7, 76, -1, 0, 0, 14, 4996, 6004), - (6004, -1, -1, 1616, 1616, 8, 77, -1, 0, 0, 14, 6003, 6005), - (6005, -1, -1, 1616, 1616, 9, 78, -1, 0, 0, 14, 6004, 6006), - (6006, -1, -1, 1616, 1616, 10, 79, -1, 0, 0, 14, 6005, 6007), - (6007, -1, -1, 1616, 1616, 12, 80, -1, 0, 0, 14, 6006, 7637), - (6008, 1345, 1345, 1345, 1345, 8, 77, 12614, 6, 900, 14, 5005, 6009), - (6009, 1345, 1345, 1345, 1345, 9, 78, 12615, 6, 900, 14, 6008, 6010), - (6010, 1345, 1345, 1345, 1345, 10, 79, 12616, 6, 900, 14, 6009, 7347), - (6011, -1, -1, 864, 864, 12, 80, -1, 0, 0, 14, 4985, 6012), - (6012, -1, -1, 864, 864, 12, 80, -1, 0, 0, 14, 6011, 6013), - (6013, -1, -1, 864, 864, 12, 80, -1, 0, 0, 14, 6012, 7353), - (6014, -1, -1, 5248, 5248, 7, 76, -1, 0, 0, 14, 5250, 6015), - (6015, -1, -1, 5248, 5248, 9, 78, -1, 0, 0, 14, 6014, 6016), - (6016, -1, -1, 5248, 5248, 12, 80, -1, 0, 0, 14, 6015, 7356), - (6017, -1, -1, 644, 644, 7, 73, -1, 0, 0, 14, 4988, 6018), - (6018, -1, -1, 644, 644, 9, 75, -1, 0, 0, 14, 6017, 6019), - (6019, -1, -1, 644, 644, 12, 77, -1, 0, 0, 14, 6018, 7359), - (6020, -1, -1, 6020, 6020, 2, 65, -1, 0, 0, 14, -1, 6021), - (6021, -1, -1, 6020, 6020, 2, 65, -1, 0, 0, 14, 6020, 6022), - (6022, -1, -1, 6020, 6020, 2, 65, -1, 0, 0, 14, 6021, 6045), - (6023, -1, -1, 119, 119, 12, 85, -1, 0, 0, 16, 7567, 6024), - (6024, -1, -1, 119, 119, 12, 85, -1, 0, 0, 16, 6023, 6025), - (6025, -1, -1, 119, 119, 12, 85, -1, 0, 0, 16, 6024, 12548), - (6026, -1, -1, 1004, 1004, 7, 81, -1, 0, 0, 16, -1, 6027), - (6027, -1, -1, 1004, 1004, 9, 81, -1, 0, 0, 16, 6026, 6028), - (6028, -1, -1, 1004, 1004, 12, 81, -1, 0, 0, 16, 6027, -1), - (6029, -1, -1, 1304, 1304, 7, 76, -1, 0, 0, 14, 1306, 6030), - (6030, -1, -1, 1304, 1304, 9, 78, -1, 0, 0, 14, 6029, 6031), - (6031, -1, -1, 1304, 1304, 12, 80, -1, 0, 0, 14, 6030, 7148), - (6032, -1, -1, 1604, 1604, 7, 69, -1, 0, 0, 14, 5294, 6033), - (6033, -1, -1, 1604, 1604, 9, 71, -1, 0, 0, 14, 6032, 6034), - (6034, -1, -1, 1604, 1604, 12, 73, -1, 0, 0, 14, 6033, 7131), - (6035, -1, -1, 846, 846, 7, 76, -1, 0, 0, 14, 4950, 6036), - (6036, -1, -1, 846, 846, 9, 78, -1, 0, 0, 14, 6035, 6037), - (6037, -1, -1, 846, 846, 12, 80, -1, 0, 0, 14, 6036, 7151), - (6038, 5022, 5022, 5022, 5022, 7, 76, 23988, 5, 600, 14, 5024, 6039), - (6039, 5022, 5022, 5022, 5022, 9, 78, 23989, 5, 600, 14, 6038, 6040), - (6040, 5022, 5022, 5022, 5022, 12, 80, 23990, 5, 600, 14, 6039, 15628), - (6041, 5028, -1, 5028, 5028, 9, 78, 12621, 4, 900, 14, 5028, -1), - (6042, -1, -1, 1543, 1543, 7, 76, -1, 0, 0, 14, 4953, 6043), - (6043, -1, -1, 1543, 1543, 9, 78, -1, 0, 0, 14, 6042, 6044), - (6044, -1, -1, 1543, 1543, 12, 80, -1, 0, 0, 14, 6043, 7134), - (6045, -1, -1, 6020, 6020, 2, 66, -1, 0, 0, 14, 6022, 6046), - (6046, -1, -1, 6020, 6020, 2, 68, -1, 0, 0, 14, 6045, 6047), - (6047, -1, -1, 6020, 6020, 2, 70, -1, 0, 0, 14, 6046, 6048), - (6048, -1, -1, 6020, 6020, 2, 71, -1, 0, 0, 14, 6047, 6049), - (6049, -1, -1, 6020, 6020, 2, 73, -1, 0, 0, 14, 6048, 6050), - (6050, -1, -1, 6020, 6020, 2, 75, -1, 0, 0, 14, 6049, 6057), - (6051, -1, -1, 6051, 6051, 3, 76, -1, 0, 0, 14, -1, 6052), - (6052, -1, -1, 6051, 6051, 3, 78, -1, 0, 0, 14, 6051, 6053), - (6053, -1, -1, 6051, 6051, 3, 80, -1, 0, 0, 14, 6052, 7601), - (6054, 4931, 4931, 4931, 4931, 7, 76, 12756, 4, 600, 14, 4933, 6055), - (6055, 4931, 4931, 4931, 4931, 7, 78, 12757, 4, 600, 14, 6054, 6056), - (6056, 4931, 4931, 4931, 4931, 7, 80, 12758, 4, 600, 14, 6055, 7291), - (6057, -1, -1, 6020, 6020, 2, 76, -1, 0, 0, 14, 6050, 6058), - (6058, -1, -1, 6020, 6020, 2, 78, -1, 0, 0, 14, 6057, 6059), - (6059, -1, -1, 6020, 6020, 2, 80, -1, 0, 0, 14, 6058, 7169), - (6060, -1, -1, 6540, 6540, 8, 76, -1, 0, 0, 14, -1, 6061), - (6061, -1, -1, 6540, 6540, 8, 76, -1, 0, 0, 14, 6060, 6470), - (6063, -1, -1, 589, 589, 7, 76, -1, 0, 0, 14, 5272, 6064), - (6064, -1, -1, 589, 589, 9, 78, -1, 0, 0, 14, 6063, 6065), - (6065, -1, -1, 589, 589, 12, 80, -1, 0, 0, 14, 6064, 7390), - (6066, -1, -1, 1313, 1313, 7, 76, -1, 0, 0, 14, 5031, 6067), - (6067, -1, -1, 1313, 1313, 7, 76, -1, 0, 0, 14, 6066, 6068), - (6068, -1, -1, 1313, 1313, 8, 77, -1, 0, 0, 14, 6067, 6069), - (6069, -1, -1, 1313, 1313, 9, 78, -1, 0, 0, 14, 6068, 6070), - (6070, -1, -1, 1313, 1313, 10, 79, -1, 0, 0, 14, 6069, 6071), - (6071, -1, -1, 1313, 1313, 12, 80, -1, 0, 0, 14, 6070, 7393), - (6072, -1, -1, 210, 210, 8, 77, -1, 0, 0, 14, 1318, 6073), - (6073, -1, -1, 210, 210, 9, 78, -1, 0, 0, 14, 6072, 6074), - (6074, -1, -1, 210, 210, 10, 79, -1, 0, 0, 14, 6073, 7399), - (6075, -1, -1, 895, 895, 7, 76, -1, 0, 0, 14, 899, 6076), - (6076, -1, -1, 895, 895, 8, 77, -1, 0, 0, 14, 6075, 6077), - (6077, -1, -1, 895, 895, 9, 78, -1, 0, 0, 14, 6076, 6078), - (6078, -1, -1, 895, 895, 10, 79, -1, 0, 0, 14, 6077, 6079), - (6079, -1, -1, 895, 895, 12, 80, -1, 0, 0, 14, 6078, 7402), - (6080, -1, -1, 683, 683, 5, 75, -1, 0, 0, 14, 5305, 6081), - (6081, -1, -1, 683, 683, 5, 75, -1, 0, 0, 14, 6080, 7604), - (6082, -1, -1, 6084, 6084, 5, 85, 0, 0, 0, 17, -1, 6083), - (6083, -1, -1, 6084, 6084, 5, 87, 0, 0, 0, 17, 6082, 6084), - (6084, -1, -1, 6084, 6084, 5, 89, 0, 0, 0, 17, 6083, 13366), - (6085, -1, -1, 6761, 6761, 10, 81, -1, 0, 0, 16, 6763, 6086), - (6086, -1, -1, 6761, 6761, 11, 83, -1, 0, 0, 16, 6085, 6087), - (6087, -1, -1, 6761, 6761, 12, 85, -1, 0, 0, 16, 6086, 10763), - (6088, -1, -1, 6088, 6088, 9, 85, 0, 0, 0, 17, -1, 6089), - (6089, -1, -1, 6088, 6088, 12, 87, 0, 0, 0, 17, 6088, 6090), - (6090, -1, -1, 6088, 6088, 15, 89, 0, 0, 0, 17, 6089, -1), - (6092, 5251, 5251, 5251, 5251, 7, 76, 12635, 13, 900, 14, 5253, 6093), - (6093, 5251, 5251, 5251, 5251, 9, 78, 12636, 13, 900, 14, 6092, 6094), - (6094, 5251, 5251, 5251, 5251, 12, 80, 12637, 13, 900, 14, 6093, 7472), - (6095, 513, 513, 513, 513, 7, 76, 12638, 4, 120, 14, 515, 6096), - (6096, 513, 513, 513, 513, 9, 78, 12639, 4, 120, 14, 6095, 6097), - (6097, 513, 513, 513, 513, 12, 80, 12640, 4, 120, 14, 6096, 7475), - (6098, 1327, 1327, 1327, 1327, 7, 76, 12641, 10, 900, 14, 5316, 6099), - (6099, 1327, 1327, 1327, 1327, 9, 78, 12642, 10, 900, 14, 6098, 6100), - (6100, 1327, 1327, 1327, 1327, 12, 80, 12643, 10, 900, 14, 6099, 7460), - (6101, 153, 153, 153, 153, 12, 80, 12644, 3, 2160, 14, 5068, 7468), - (6102, 146, 146, 146, 146, 8, 77, 12645, 2, 180, 14, 5069, 7466), - (6103, 528, 528, 528, 528, 7, 76, 12646, 5, 720, 14, 901, 6104), - (6104, 528, 528, 528, 528, 9, 78, 12647, 5, 720, 14, 6103, 6105), - (6105, 528, 528, 528, 528, 12, 80, 12648, 5, 720, 14, 6104, 7469), - (6106, 6106, 6106, 6106, 6106, 4, 67, 21965, 13, 4320, 16, -1, 6107), - (6107, 6106, 6106, 6106, 6106, 5, 68, 21966, 13, 4320, 16, 6106, 6108), - (6108, 6106, 6106, 6106, 6106, 6, 69, 21967, 13, 4320, 16, 6107, 6109), - (6109, 6106, 6106, 6106, 6106, 7, 77, 21968, 13, 4320, 16, 6108, 6110), - (6110, 6106, 6106, 6106, 6106, 8, 78, 21969, 13, 4320, 16, 6109, 6111), - (6111, 6106, 6106, 6106, 6106, 9, 79, 21970, 13, 4320, 16, 6110, -1), - (6112, -1, -1, 6112, 6112, 5, 85, -1, 0, 0, 17, -1, 12966), - (6113, -1, -1, 6113, 6113, 9, 85, 0, 0, 0, 17, -1, 6114), - (6114, -1, -1, 6113, 6113, 12, 87, 0, 0, 0, 17, 6113, 6115), - (6115, -1, -1, 6113, 6113, 15, 89, 0, 0, 0, 17, 6114, -1), - (6119, -1, -1, 6119, 6119, 6, 76, -1, 0, 0, 14, -1, 6120), - (6120, -1, -1, 6119, 6119, 6, 77, -1, 0, 0, 14, 6119, 6121), - (6121, -1, -1, 6119, 6119, 6, 78, -1, 0, 0, 14, 6120, 6122), - (6122, -1, -1, 6119, 6119, 6, 79, -1, 0, 0, 14, 6121, 6123), - (6123, -1, -1, 6119, 6119, 6, 80, -1, 0, 0, 14, 6122, 7526), - (6124, -1, -1, 5263, 5263, 3, 71, -1, 0, 0, 12, -1, 6125), - (6125, -1, -1, 5263, 5263, 6, 73, -1, 0, 0, 12, 6124, 6126), - (6126, -1, -1, 5263, 5263, 9, 75, -1, 0, 0, 12, 6125, 6127), - (6127, -1, -1, 5263, 5263, 10, 76, -1, 0, 0, 14, 6126, 6128), - (6128, -1, -1, 5263, 5263, 11, 78, -1, 0, 0, 14, 6127, 6129), - (6129, -1, -1, 5263, 5263, 12, 80, -1, 0, 0, 14, 6128, 12463), - (6130, -1, -1, 586, 586, 7, 76, -1, 0, 0, 14, 588, 6131), - (6131, -1, -1, 586, 586, 7, 76, -1, 0, 0, 14, 6130, 6132), - (6132, -1, -1, 586, 586, 7, 76, -1, 0, 0, 14, 6131, -1), - (6133, 1351, 1351, 1351, 1351, 8, 77, 12649, 5, 30, 14, 1351, 7109), - (6134, 4849, 4849, 4849, 4849, 7, 76, 12650, 7, 1800, 14, 4849, 7110), - (6135, 54006, 54006, 54006, 54006, 7, 76, 12651, 18, 180, 14, -1, 7111), - (6136, -1, -1, 6136, 6136, 7, 76, -1, 0, 0, 10, -1, 6137), - (6149, 921, 921, 921, 921, 9, 79, 12652, 8, 60, 14, 5280, 7245), - (6150, 922, 922, 922, 922, 9, 78, 12653, 8, 60, 14, 5281, 7236), - (6151, 923, 923, 923, 923, 9, 77, 12654, 8, 60, 14, 5282, 7235), - (6152, 1334, 1334, 1334, 1334, 9, 78, 12655, 11, 4320, 14, 1336, 6153), - (6153, 1334, 1334, 1334, 1334, 10, 79, 12656, 11, 4320, 14, 6152, 6154), - (6154, 1334, 1334, 1334, 1334, 12, 80, 12657, 11, 4320, 14, 6153, 7239), - (6155, 4944, -1, 4944, 4944, 7, 76, 12658, 0, 1, 14, 4946, 6156), - (6156, 4944, -1, 4944, 4944, 9, 78, 12659, 0, 1, 14, 6155, 6157), - (6157, 4944, -1, 4944, 4944, 12, 80, 12660, 0, 1, 14, 6156, 7229), - (6158, 1337, 1337, 1337, 1337, 8, 77, 12661, 13, 4320, 14, 1339, 6159), - (6159, 1337, 1337, 1337, 1337, 9, 78, 12662, 13, 4320, 14, 6158, 6160), - (6160, 1337, 1337, 1337, 1337, 10, 79, 12663, 13, 4320, 14, 6159, 14338), - (6161, 1478, -1, 1478, 1478, 9, 78, 12664, 0, 1, 14, 1480, 6162), - (6162, 1478, -1, 1478, 1478, 10, 79, 12665, 0, 1, 14, 6161, 6163), - (6163, 1478, -1, 1478, 1478, 12, 80, 12666, 0, 1, 14, 6162, 7242), - (6200, 6533, 6533, 6533, 6533, 10, 79, 12768, 15, 600, 14, -1, 7428), - (6201, 6534, 6534, 6534, 6534, 9, 78, 12769, 16, 900, 14, -1, 7429), - (6202, -1, -1, 6535, 6535, 5, 70, -1, 0, 0, 14, -1, 6203), - (6203, -1, -1, 6535, 6535, 5, 70, -1, 0, 0, 14, 6202, 6204), - (6204, -1, -1, 6535, 6535, 5, 70, -1, 0, 0, 14, 6203, -1), - (6205, 6536, 6536, 6536, 6536, 7, 76, 12712, 39, 5, 14, -1, -1), - (6206, 6537, 6537, 6537, 6537, 7, 76, 12770, 30, 900, 14, -1, 6207), - (6207, 6537, 6537, 6537, 6537, 8, 77, 12771, 30, 900, 14, 6206, 6208), - (6208, 6537, 6537, 6537, 6537, 9, 78, 12772, 30, 900, 14, 6207, 7606), - (6209, -1, -1, 6538, 6538, 7, 76, -1, 0, 0, 14, -1, 6210), - (6210, -1, -1, 6538, 6538, 9, 78, -1, 0, 0, 14, 6209, 6211), - (6211, -1, -1, 6538, 6538, 12, 80, -1, 0, 0, 14, 6210, 7478), - (6212, 6539, 6539, 6539, 6539, 6, 71, 12776, 18, 1800, 14, -1, 6213), - (6213, 6539, 6539, 6539, 6539, 6, 74, 12777, 18, 1800, 14, 6212, 6214), - (6214, 6539, 6539, 6539, 6539, 6, 77, 12778, 18, 1800, 14, 6213, 7609), - (6215, -1, -1, 6540, 6540, 8, 71, -1, 0, 0, 14, -1, 6216), - (6216, -1, -1, 6540, 6540, 8, 72, -1, 0, 0, 14, 6215, 6217), - (6217, -1, -1, 6540, 6540, 8, 73, -1, 0, 0, 14, 6216, 6300), - (6218, 6218, 6218, 6218, 6218, 7, 76, 12782, 0, 1, 14, -1, 7488), - (6219, 6542, 6542, 6542, 6542, 7, 76, 12783, 18, 1800, 14, -1, 6220), - (6220, 6542, 6542, 6542, 6542, 9, 78, 12784, 18, 1800, 14, 6219, 6221), - (6221, 6542, 6542, 6542, 6542, 12, 80, 12785, 18, 1800, 14, 6220, -1), - (6222, 6543, 6543, 6543, 6543, 9, 72, 13143, 18, 25, 14, -1, -1), - (6223, -1, -1, 962, 962, 5, 76, -1, 0, 0, 14, 966, 6224), - (6224, -1, -1, 962, 962, 5, 77, -1, 0, 0, 14, 6223, 6225), - (6225, -1, -1, 962, 962, 5, 78, -1, 0, 0, 14, 6224, 6226), - (6226, -1, -1, 962, 962, 5, 79, -1, 0, 0, 14, 6225, 6227), - (6227, -1, -1, 962, 962, 5, 80, -1, 0, 0, 14, 6226, 10361), - (6228, -1, -1, 6545, 6545, 2, 70, -1, 0, 0, 14, -1, 6229), - (6229, -1, -1, 6545, 6545, 2, 70, -1, 0, 0, 14, 6228, 6230), - (6230, -1, -1, 6545, 6545, 2, 70, -1, 0, 0, 14, 6229, 6231), - (6231, -1, -1, 6545, 6545, 2, 70, -1, 0, 0, 14, 6230, -1), - (6232, 6232, 6232, 6232, 6232, 12, 80, 14413, 18, 900, 14, -1, 7421), - (6233, -1, -1, 477, 477, 2, 70, -1, 0, 0, 14, 479, 6234), - (6234, -1, -1, 477, 477, 2, 71, -1, 0, 0, 14, 6233, 6235), - (6235, -1, -1, 477, 477, 2, 72, -1, 0, 0, 14, 6234, 16094), - (6236, -1, -1, 6548, 6548, 6, 73, -1, 0, 0, 14, -1, 6237), - (6237, -1, -1, 6548, 6548, 6, 75, -1, 0, 0, 14, 6236, 6238), - (6238, -1, -1, 6548, 6548, 8, 77, -1, 0, 0, 14, 6237, 12929), - (6240, -1, -1, 767, 767, 3, 65, -1, 0, 0, 14, -1, 6241), - (6241, -1, -1, 767, 767, 6, 65, -1, 0, 0, 14, 6240, 6242), - (6242, -1, -1, 767, 767, 9, 65, -1, 0, 0, 14, 6241, 6243), - (6243, -1, -1, 767, 767, 3, 67, -1, 0, 0, 14, 6242, 6244), - (6244, -1, -1, 767, 767, 6, 68, -1, 0, 0, 14, 6243, 6245), - (6245, -1, -1, 767, 767, 9, 69, -1, 0, 0, 14, 6244, 12426), - (6249, 6552, 6552, 6552, 6552, 5, 70, -1, 0, 0, 14, -1, 6250), - (6250, 6552, 6552, 6552, 6552, 6, 72, -1, 0, 0, 14, 6249, 6251), - (6251, 6552, 6552, 6552, 6552, 6, 74, -1, 0, 0, 14, 6250, 6252), - (6252, 6552, 6552, 6552, 6552, 7, 76, -1, 0, 0, 14, 6251, 6253), - (6253, 6552, 6552, 6552, 6552, 9, 78, -1, 0, 0, 14, 6252, 7279), - (6254, 616, 616, 616, 616, 6, 73, 12765, 7, 900, 14, 1250, 6255), - (6255, 616, 616, 616, 616, 7, 76, 12766, 7, 900, 14, 6254, 6256), - (6256, 616, 616, 616, 616, 10, 79, 12767, 7, 900, 14, 6255, 7257), - (6257, -1, -1, 86, 86, 2, 55, -1, 0, 0, 14, -1, 6258), - (6258, -1, -1, 86, 86, 4, 55, -1, 0, 0, 14, 6257, 6259), - (6259, -1, -1, 86, 86, 6, 55, -1, 0, 0, 14, 6258, 8223), - (6260, -1, -1, 495, 495, 6, 73, -1, 0, 0, 14, 497, 6261), - (6261, -1, -1, 495, 495, 7, 76, -1, 0, 0, 14, 6260, 6262), - (6262, -1, -1, 495, 495, 10, 79, -1, 0, 0, 14, 6261, 10666), - (6266, -1, -1, 6557, 6557, 6, 73, -1, 0, 0, 14, -1, 6267), - (6267, -1, -1, 6557, 6557, 7, 76, -1, 0, 0, 14, 6266, 6268), - (6268, -1, -1, 6557, 6557, 10, 79, -1, 0, 0, 14, 6267, -1), - (6269, -1, -1, 6558, 6558, 6, 73, -1, 0, 0, 14, -1, 6270), - (6270, -1, -1, 6558, 6558, 7, 76, -1, 0, 0, 14, 6269, 6271), - (6271, -1, -1, 6558, 6558, 10, 79, -1, 0, 0, 14, 6270, -1), - (6272, -1, -1, 6559, 6559, 6, 73, -1, 0, 0, 14, -1, 6273), - (6273, -1, -1, 6559, 6559, 7, 75, -1, 0, 0, 14, 6272, 6274), - (6274, -1, -1, 6559, 6559, 10, 77, -1, 0, 0, 14, 6273, 7137), - (6275, -1, -1, 6560, 6560, 6, 73, -1, 0, 0, 14, -1, 6276), - (6276, -1, -1, 6560, 6560, 7, 76, -1, 0, 0, 14, 6275, 6277), - (6277, -1, -1, 6560, 6560, 10, 79, -1, 0, 0, 14, 6276, 16266), - (6278, 6561, 6561, 6561, 6561, 7, 76, 12795, 32, 30, 14, -1, 6279), - (6279, 6561, 6561, 6561, 6561, 7, 76, 12796, 32, 30, 14, 6278, 6280), - (6280, 6561, 6561, 6561, 6561, 7, 76, 12797, 32, 30, 14, 6279, 7422), - (6281, 6563, 6563, 6563, 6563, 9, 78, 13144, 36, 8, 14, -1, 12995), - (6282, 6562, 6562, 6562, 6562, 6, 72, 12798, 39, 1, 14, -1, -1), - (6283, -1, -1, 6564, 6564, 6, 73, -1, 0, 0, 14, -1, 6284), - (6284, -1, -1, 6564, 6564, 7, 76, -1, 0, 0, 14, 6283, 6285), - (6285, -1, -1, 6564, 6564, 10, 79, -1, 0, 0, 14, 6284, 7112), - (6286, 6565, 6565, 6565, 6565, 7, 76, 12802, 17, 45, 14, -1, 7115), - (6287, -1, -1, 6566, 6566, 6, 73, -1, 0, 0, 14, -1, 6288), - (6288, -1, -1, 6566, 6566, 7, 76, -1, 0, 0, 14, 6287, 6289), - (6289, -1, -1, 6566, 6566, 10, 79, -1, 0, 0, 14, 6288, -1), - (6290, 6290, 6290, 6290, 6290, 6, 71, 12803, 0, 1, 14, -1, 6291), - (6291, 6290, 6290, 6290, 6290, 6, 73, 12804, 0, 1, 14, 6290, 6292), - (6292, 6290, 6290, 6290, 6290, 6, 75, 12805, 0, 1, 14, 6291, 6293), - (6293, 6290, 6290, 6290, 6290, 7, 76, 12806, 0, 1, 14, 6292, 6294), - (6294, 6290, 6290, 6290, 6290, 9, 78, 12807, 0, 1, 14, 6293, 6295), - (6295, 6290, 6290, 6290, 6290, 12, 80, 12808, 0, 1, 14, 6294, 7223), - (6296, 619, 619, 619, 619, 6, 73, 12759, 6, 900, 14, 722, 6297), - (6297, 619, 619, 619, 619, 6, 73, 12760, 6, 900, 14, 6296, 6298), - (6298, 619, 619, 619, 619, 6, 73, 12761, 6, 900, 14, 6297, 7226), - (6299, 6299, 6299, 6299, 6299, 9, 65, 12786, 18, 12, 14, -1, -1), - (6300, -1, -1, 6540, 6540, 8, 74, -1, 0, 0, 14, 6217, 6301), - (6301, -1, -1, 6540, 6540, 8, 75, -1, 0, 0, 14, 6300, 6472), - (6302, -1, -1, 6302, 6302, 5, 81, 0, 0, 0, 16, -1, 6303), - (6303, -1, -1, 6302, 6302, 5, 83, 0, 0, 0, 16, 6302, 6304), - (6304, -1, -1, 6302, 6302, 5, 85, 0, 0, 0, 16, 6303, 11011), - (6307, 1358, 1358, 1358, 1358, 6, 71, 13168, 3, 60, 14, 1360, 6308), - (6308, 1358, 1358, 1358, 1358, 6, 73, 13169, 3, 60, 14, 6307, 6309), - (6309, 1358, 1358, 1358, 1358, 6, 75, 13170, 3, 60, 14, 6308, 6310), - (6310, 1358, 1358, 1358, 1358, 6, 76, 13171, 3, 60, 14, 6309, 6311), - (6311, 1358, 1358, 1358, 1358, 6, 78, 13172, 3, 60, 14, 6310, 6312), - (6312, 1358, 1358, 1358, 1358, 6, 80, 13173, 3, 60, 14, 6311, 7157), - (6313, 1352, 1352, 1352, 1352, 6, 71, 13174, 3, 60, 14, 1354, 6314), - (6314, 1352, 1352, 1352, 1352, 6, 73, 13175, 3, 60, 14, 6313, 6315), - (6315, 1352, 1352, 1352, 1352, 6, 75, 13177, 3, 60, 14, 6314, 6316), - (6316, 1352, 1352, 1352, 1352, 6, 76, 13178, 3, 60, 14, 6315, 6317), - (6317, 1352, 1352, 1352, 1352, 6, 78, 13179, 3, 60, 14, 6316, 6318), - (6318, 1352, 1352, 1352, 1352, 6, 80, 13180, 3, 60, 14, 6317, 7154), - (6319, -1, -1, 501, 501, 6, 73, -1, 0, 0, 14, 503, 6320), - (6320, -1, -1, 501, 501, 6, 75, -1, 0, 0, 14, 6319, 6321), - (6321, -1, -1, 501, 501, 6, 77, -1, 0, 0, 14, 6320, 6528), - (6322, -1, -1, 6322, 6322, 6, 73, -1, 0, 0, 14, -1, 6323), - (6323, -1, -1, 6322, 6322, 6, 75, -1, 0, 0, 14, 6322, 6324), - (6324, -1, -1, 6322, 6322, 6, 77, -1, 0, 0, 14, 6323, -1), - (6325, 6325, 6325, 6325, 6325, 7, 73, 13213, 18, 600, 14, -1, 6326), - (6326, 6325, 6325, 6325, 6325, 7, 75, 13214, 18, 600, 14, 6325, 6327), - (6327, 6325, 6325, 6325, 6325, 7, 77, 13215, 18, 600, 14, 6326, 6361), - (6328, 6328, 6328, 6328, 6328, 7, 74, 13204, 10, 600, 14, -1, 6329), - (6329, 6328, 6328, 6328, 6328, 7, 76, 13205, 10, 600, 14, 6328, 6330), - (6330, 6328, 6328, 6328, 6328, 7, 78, 13212, 10, 600, 14, 6329, 7143), - (6331, -1, -1, 878, 878, 7, 76, -1, 0, 0, 14, 4959, 6332), - (6332, -1, -1, 878, 878, 7, 78, -1, 0, 0, 14, 6331, 7146), - (6333, 6333, 6333, 6333, 6333, 9, 59, 13167, 3, 600, 14, -1, 7266), - (6334, -1, -1, 6334, 6334, 6, 73, -1, 0, 0, 14, -1, 6335), - (6335, -1, -1, 6334, 6334, 6, 75, -1, 0, 0, 14, 6334, 6336), - (6336, -1, -1, 6334, 6334, 6, 77, -1, 0, 0, 14, 6335, -1), - (6337, -1, -1, 6337, 6337, 6, 74, -1, 0, 0, 14, -1, 6338), - (6338, -1, -1, 6337, 6337, 6, 76, -1, 0, 0, 14, 6337, 6339), - (6339, -1, -1, 6337, 6337, 6, 78, -1, 0, 0, 14, 6338, 7448), - (6340, -1, -1, 6340, 6340, 6, 74, -1, 0, 0, 14, -1, 6341), - (6341, -1, -1, 6340, 6340, 6, 76, -1, 0, 0, 14, 6340, 6342), - (6342, -1, -1, 6340, 6340, 6, 78, -1, 0, 0, 14, 6341, 7451), - (6343, -1, -1, 6343, 6343, 6, 74, -1, 0, 0, 14, -1, 6344), - (6344, -1, -1, 6343, 6343, 6, 76, -1, 0, 0, 14, 6343, 6345), - (6345, -1, -1, 6343, 6343, 6, 78, -1, 0, 0, 14, 6344, 7166), - (6346, -1, -1, 6346, 6346, 6, 74, -1, 0, 0, 14, -1, 6347), - (6347, -1, -1, 6346, 6346, 6, 76, -1, 0, 0, 14, 6346, 6348), - (6348, -1, -1, 6346, 6346, 6, 78, -1, 0, 0, 14, 6347, 7615), - (6349, -1, -1, 6349, 6349, 6, 74, -1, 0, 0, 14, -1, 6350), - (6350, -1, -1, 6349, 6349, 6, 76, -1, 0, 0, 14, 6349, 6351), - (6351, -1, -1, 6349, 6349, 6, 78, -1, 0, 0, 14, 6350, 7618), - (6352, 4894, 4894, 4894, 4894, 6, 76, 13181, 7, 2160, 14, 4896, 6353), - (6353, 4894, 4894, 4894, 4894, 6, 77, 13182, 7, 2160, 14, 6352, 6354), - (6354, 4894, 4894, 4894, 4894, 6, 78, 13183, 7, 2160, 14, 6353, 7288), - (6355, -1, -1, 6355, 6355, 6, 73, -1, 0, 0, 14, -1, 6356), - (6356, -1, -1, 6355, 6355, 6, 74, -1, 0, 0, 14, 6355, 6357), - (6357, -1, -1, 6355, 6355, 6, 75, -1, 0, 0, 14, 6356, 6358), - (6358, -1, -1, 6355, 6355, 6, 76, -1, 0, 0, 14, 6357, 6359), - (6359, -1, -1, 6355, 6355, 6, 77, -1, 0, 0, 14, 6358, 6360), - (6360, -1, -1, 6355, 6355, 6, 80, -1, 0, 0, 16, 6359, 14101), - (6361, 6325, 6325, 6325, 6325, 7, 81, 16861, 18, 600, 16, 6327, 12633), - (6362, -1, -1, 6362, 6362, 5, 77, 0, 0, 0, 16, -1, 6363), - (6363, -1, -1, 6362, 6362, 5, 79, 0, 0, 0, 16, 6362, 6364), - (6364, -1, -1, 6362, 6362, 5, 81, 0, 0, 0, 16, 6363, 6365), - (6365, -1, -1, 6362, 6362, 5, 83, 0, 0, 0, 16, 6364, 6366), - (6366, -1, -1, 6362, 6362, 5, 85, 0, 0, 0, 16, 6365, 16327), - (6370, 6370, 6370, 6370, 6370, 6, 76, 13188, 7, 600, 14, -1, 6371), - (6371, 6370, 6370, 6370, 6370, 6, 77, 13189, 7, 600, 14, 6370, 6372), - (6372, 6370, 6370, 6370, 6370, 6, 78, 13190, 7, 600, 14, 6371, 7350), - (6375, -1, -1, 6375, 6375, 6, 76, -1, 0, 0, 14, -1, 6376), - (6376, -1, -1, 6375, 6375, 6, 77, -1, 0, 0, 14, 6375, 6377), - (6377, -1, -1, 6375, 6375, 6, 78, -1, 0, 0, 14, 6376, 7644), - (6378, 209, 209, 209, 1272, 6, 76, 13501, 12, 5, 14, 1272, -1), - (6379, 6379, 6379, 6379, 6379, 6, 60, 13500, 37, 5, 14, -1, -1), - (6380, 6380, 6380, 6380, 6380, 6, 78, 13209, 39, 120, 14, -1, 6381), - (6381, 6380, 6380, 6380, 6380, 6, 79, 13210, 39, 120, 14, 6380, 6382), - (6382, 6380, 6380, 6380, 6380, 6, 80, 13211, 39, 120, 14, 6381, 7497), - (6383, -1, -1, 6383, 6383, 3, 70, -1, 0, 0, 14, -1, 6384), - (6384, -1, -1, 6383, 6383, 6, 70, -1, 0, 0, 14, 6383, 6385), - (6385, -1, -1, 6383, 6383, 9, 70, -1, 0, 0, 14, 6384, 10607), - (6386, -1, -1, 6386, 6386, 7, 72, -1, 0, 0, 14, -1, 6387), - (6387, -1, -1, 6386, 6386, 7, 74, -1, 0, 0, 14, 6386, 6388), - (6388, -1, -1, 6386, 6386, 7, 76, -1, 0, 0, 14, 6387, 6389), - (6389, -1, -1, 6386, 6386, 7, 78, -1, 0, 0, 14, 6388, 13521), - (6390, -1, -1, 65, 661, 3, 76, -1, 0, 0, 14, 4697, 6391), - (6391, -1, -1, 65, 661, 3, 77, -1, 0, 0, 14, 6390, 6392), - (6392, -1, -1, 65, 661, 3, 78, -1, 0, 0, 14, 6391, 6393), - (6393, -1, -1, 65, 661, 3, 79, -1, 0, 0, 14, 6392, 6394), - (6394, -1, -1, 65, 661, 3, 80, -1, 0, 0, 14, 6393, 7534), - (6395, -1, -1, 6395, 6395, 7, 76, -1, 0, 0, 14, -1, 6396), - (6396, -1, -1, 6395, 6395, 7, 77, -1, 0, 0, 14, 6395, 6397), - (6397, -1, -1, 6395, 6395, 7, 78, -1, 0, 0, 14, 6396, 7336), - (6398, 516, 516, 516, 516, 6, 72, 13198, 5, 480, 14, 516, 7237), - (6400, 1110, 1110, 1110, 1110, 6, 73, 13192, 3, 2160, 14, 1112, 6401), - (6401, 1110, 1110, 1110, 1110, 6, 75, 13193, 3, 2160, 14, 6400, 6402), - (6402, 1110, 1110, 1110, 1110, 6, 76, 13194, 3, 2160, 14, 6401, 7445), - (6403, -1, -1, 1107, 1107, 7, 76, -1, 0, 0, 14, 5288, 6404), - (6404, -1, -1, 1107, 1107, 9, 78, -1, 0, 0, 14, 6403, 6405), - (6405, -1, -1, 1107, 1107, 12, 80, -1, 0, 0, 14, 6404, 12432), - (6406, -1, -1, 5085, 5085, 6, 76, -1, 0, 0, 14, 5087, 6407), - (6407, -1, -1, 5085, 5085, 6, 78, -1, 0, 0, 14, 6406, 6408), - (6408, -1, -1, 5085, 5085, 6, 80, -1, 0, 0, 14, 6407, 7384), - (6409, -1, -1, 6540, 6540, 8, 71, -1, 0, 0, 14, -1, 6410), - (6410, -1, -1, 6540, 6540, 8, 72, -1, 0, 0, 14, 6409, 6411), - (6411, -1, -1, 6540, 6540, 8, 73, -1, 0, 0, 14, 6410, 6412), - (6412, -1, -1, 6540, 6540, 8, 74, -1, 0, 0, 14, 6411, 6413), - (6413, -1, -1, 6540, 6540, 8, 75, -1, 0, 0, 14, 6412, 6414), - (6414, -1, -1, 6540, 6540, 8, 76, -1, 0, 0, 14, 6413, 6415), - (6415, -1, -1, 6540, 6540, 8, 77, -1, 0, 0, 14, 6414, 6416), - (6416, -1, -1, 6540, 6540, 8, 78, -1, 0, 0, 14, 6415, 6417), - (6417, -1, -1, 6540, 6540, 8, 79, -1, 0, 0, 14, 6416, 6418), - (6418, -1, -1, 6540, 6540, 8, 80, -1, 0, 0, 14, 6417, 6474), - (6419, -1, -1, 6540, 6540, 8, 71, -1, 0, 0, 14, -1, 6420), - (6420, -1, -1, 6540, 6540, 8, 72, -1, 0, 0, 14, 6419, 6421), - (6421, -1, -1, 6540, 6540, 8, 73, -1, 0, 0, 14, 6420, 6476), - (6422, -1, -1, 6422, 6422, 3, 61, -1, 0, 0, 14, -1, 6423), - (6423, -1, -1, 6422, 6422, 3, 63, -1, 0, 0, 14, 6422, 6424), - (6424, -1, -1, 6422, 6422, 3, 65, -1, 0, 0, 14, 6423, -1), - (6425, 5007, 5007, 5007, 5007, 9, 76, 13509, 8, 2160, 14, 5009, 6426), - (6426, 5007, 5007, 5007, 5007, 9, 78, 13510, 8, 2160, 14, 6425, 6427), - (6427, 5007, 5007, 5007, 5007, 9, 80, 13511, 8, 2160, 14, 6426, 7341), - (6428, -1, -1, 1287, 1287, 3, 67, -1, 0, 0, 14, -1, 6429), - (6429, -1, -1, 1287, 1287, 6, 68, -1, 0, 0, 14, 6428, 6430), - (6430, -1, -1, 1287, 1287, 9, 69, -1, 0, 0, 14, 6429, 12472), - (6431, -1, -1, 1056, 1056, 5, 76, -1, 0, 0, 14, 1060, 6432), - (6432, -1, -1, 1056, 1056, 5, 77, -1, 0, 0, 14, 6431, 6433), - (6433, -1, -1, 1056, 1056, 5, 78, -1, 0, 0, 14, 6432, 6434), - (6434, -1, -1, 1056, 1056, 5, 79, -1, 0, 0, 14, 6433, 6435), - (6435, -1, -1, 1056, 1056, 5, 80, -1, 0, 0, 14, 6434, 7521), - (6436, -1, -1, 6436, 6436, 6, 73, -1, 0, 0, 14, -1, 6437), - (6437, -1, -1, 6436, 6436, 6, 75, -1, 0, 0, 14, 6436, 6438), - (6438, -1, -1, 6436, 6436, 8, 77, -1, 0, 0, 14, 6437, 7313), - (6439, -1, -1, 468, 468, 2, 67, -1, 0, 0, 14, 470, 6440), - (6440, -1, -1, 468, 468, 2, 69, -1, 0, 0, 14, 6439, 7316), - (6441, -1, -1, 1546, 1546, 5, 76, -1, 0, 0, 14, 4831, 12673), - (6442, -1, -1, 1471, 1471, 6, 76, -1, 0, 0, 14, 1475, 6443), - (6443, -1, -1, 1471, 1471, 6, 77, -1, 0, 0, 14, 6442, -1), - (6445, -1, -1, 6445, 6445, 2, 62, -1, 0, 0, 14, -1, 6446), - (6446, -1, -1, 6445, 6445, 2, 64, -1, 0, 0, 14, 6445, 6447), - (6447, -1, -1, 6445, 6445, 2, 66, -1, 0, 0, 14, 6446, -1), - (6448, 5109, 5109, 5109, 5109, 9, 77, 13515, 0, 1, 14, 5109, 7467), - (6449, 1520, 1520, 1520, 1520, 9, 70, 13516, 11, 900, 14, 1522, 6450), - (6450, 1520, 1520, 1520, 1520, 9, 70, 13517, 11, 900, 14, 6449, 6451), - (6451, 1520, 1520, 1520, 1520, 9, 70, 13518, 11, 900, 14, 6450, 7463), - (6452, -1, -1, 6452, 6452, 2, 71, -1, 0, 0, 14, -1, 6453), - (6453, -1, -1, 6452, 6452, 2, 72, -1, 0, 0, 14, 6452, 6454), - (6454, -1, -1, 6452, 6452, 2, 73, -1, 0, 0, 14, 6453, -1), - (6455, 6455, 6455, 6455, 6455, 2, 72, 14750, 36, 30, 14, -1, 6456), - (6456, 6455, 6455, 6455, 6455, 2, 74, 14751, 36, 30, 14, 6455, 6457), - (6457, 6455, 6455, 6455, 6455, 2, 76, 14752, 36, 30, 14, 6456, -1), - (6458, -1, -1, 6458, 6458, 3, 78, -1, 0, 0, 14, -1, 6459), - (6459, -1, -1, 6458, 6458, 3, 78, -1, 0, 0, 14, 6458, 6460), - (6460, -1, -1, 6458, 6458, 3, 78, -1, 0, 0, 14, 6459, -1), - (6461, -1, -1, 6461, 6461, 3, 78, -1, 0, 0, 14, -1, 6462), - (6462, -1, -1, 6461, 6461, 3, 78, -1, 0, 0, 14, 6461, 6463), - (6463, -1, -1, 6461, 6461, 3, 78, -1, 0, 0, 14, 6462, -1), - (6464, 967, 967, 967, 967, 6, 76, 13897, 10, 1800, 14, 969, 6465), - (6465, 967, 967, 967, 967, 6, 77, 13898, 10, 1800, 14, 6464, 6466), - (6466, 967, 967, 967, 967, 6, 78, 13899, 10, 1800, 14, 6465, 7217), - (6467, -1, -1, 6467, 6467, 3, 61, -1, 0, 0, 15, -1, 6468), - (6468, -1, -1, 6467, 6467, 3, 63, -1, 0, 0, 15, 6467, 6469), - (6469, -1, -1, 6467, 6467, 3, 65, -1, 0, 0, 15, 6468, -1), - (6470, -1, -1, 6540, 6540, 8, 76, -1, 0, 0, 15, 6061, 6471), - (6471, -1, -1, 6540, 6540, 8, 81, -1, 0, 0, 15, 6470, 12487), - (6472, -1, -1, 6540, 6540, 8, 81, -1, 0, 0, 15, 6301, 6473), - (6473, -1, -1, 6540, 6540, 8, 83, -1, 0, 0, 15, 6472, 12481), - (6474, -1, -1, 6540, 6540, 8, 81, -1, 0, 0, 15, 6418, 6475), - (6475, -1, -1, 6540, 6540, 8, 83, -1, 0, 0, 15, 6474, 12483), - (6476, -1, -1, 6540, 6540, 8, 81, -1, 0, 0, 15, 6421, 6477), - (6477, -1, -1, 6540, 6540, 8, 83, -1, 0, 0, 15, 6476, 12485), - (6478, 0, 0, 6478, 6478, 3, 81, -1, 0, 0, 16, -1, 6479), - (6479, 0, 0, 6478, 6478, 5, 83, -1, 0, 0, 16, 6478, 6480), - (6480, 0, 0, 6478, 6478, 7, 85, -1, 0, 0, 16, 6479, -1), - (6481, 0, 0, 6481, 6481, 5, 85, -1, 0, 0, 16, -1, 6482), - (6482, 0, 0, 6481, 6481, 7, 85, -1, 0, 0, 16, 6481, 6483), - (6483, 0, 0, 6481, 6481, 9, 85, -1, 0, 0, 16, 6482, 15314), - (6484, -1, -1, 7940, 7940, 5, 85, -1, 0, 0, 16, 10032, 6485), - (6485, -1, -1, 7940, 7940, 7, 85, -1, 0, 0, 16, 6484, 6486), - (6486, -1, -1, 7940, 7940, 9, 85, -1, 0, 0, 16, 6485, 15320), - (6487, 1383, 1383, 1383, 1383, 12, 85, 21812, 6, 300, 16, 10014, 14221), - (6488, 6488, 6488, 6488, 6488, 12, 85, 21806, 32, 900, 16, -1, 13383), - (6489, -1, -1, 6489, 6489, 5, 81, -1, 0, 0, 16, -1, 6490), - (6490, -1, -1, 6489, 6489, 7, 83, -1, 0, 0, 16, 6489, 6491), - (6491, -1, -1, 6489, 6489, 9, 85, -1, 0, 0, 16, 6490, 17239), - (6492, 6492, 6492, 6492, 6492, 7, 75, 21692, 52, 720, 16, -1, 6493), - (6493, 6492, 6492, 6492, 6492, 7, 77, 21693, 52, 720, 16, 6492, 6494), - (6494, 6492, 6492, 6492, 6492, 7, 79, 21694, 52, 720, 16, 6493, 6495), - (6495, 6492, 6492, 6492, 6492, 7, 81, 21695, 52, 720, 16, 6494, 6496), - (6496, 6492, 6492, 6492, 6492, 7, 83, 21696, 52, 720, 16, 6495, 6497), - (6497, 6492, 6492, 6492, 6492, 7, 85, 21697, 52, 720, 16, 6496, 10679), - (6499, 6499, 6499, 6499, 6499, 3, 75, 13512, 13, 60, 14, -1, -1), - (6500, -1, -1, 4761, 4761, 7, 76, -1, 0, 0, 14, 4763, 6501), - (6501, -1, -1, 4761, 4761, 7, 78, -1, 0, 0, 14, 6500, 6502), - (6502, -1, -1, 4761, 4761, 7, 80, -1, 0, 0, 14, 6501, -1), - (6503, -1, -1, 6503, 6503, 6, 72, -1, 0, 0, 14, -1, 6504), - (6504, -1, -1, 6503, 6503, 6, 72, -1, 0, 0, 14, 6503, 6505), - (6505, -1, -1, 6503, 6503, 6, 72, -1, 0, 0, 14, 6504, 6506), - (6506, -1, -1, 6503, 6503, 6, 72, -1, 0, 0, 14, 6505, -1), - (6508, 6508, 6508, 6508, 6508, 7, 74, 13195, 38, 600, 14, -1, 6509), - (6509, 6508, 6508, 6508, 6508, 7, 76, 13196, 38, 600, 14, 6508, 6510), - (6510, 6508, 6508, 6508, 6508, 7, 78, 13197, 38, 600, 14, 6509, 7387), - (6511, -1, -1, 6511, 6511, 6, 73, -1, 0, 0, 14, -1, 6512), - (6512, -1, -1, 6511, 6511, 6, 75, -1, 0, 0, 14, 6511, 6513), - (6513, -1, -1, 6511, 6511, 6, 77, -1, 0, 0, 14, 6512, -1), - (6514, -1, -1, 6514, 6514, 2, 72, -1, 0, 0, 14, -1, 6515), - (6515, -1, -1, 6514, 6514, 2, 72, -1, 0, 0, 14, 6514, 6516), - (6516, -1, -1, 6514, 6514, 2, 72, -1, 0, 0, 14, 6515, -1), - (6517, -1, -1, 1435, 4773, 9, 76, -1, 0, 0, 14, 4773, 7621), - (6518, -1, -1, 678, 678, 3, 65, -1, 0, 0, 14, 682, 6519), - (6519, -1, -1, 678, 678, 3, 65, -1, 0, 0, 14, 6518, 6520), - (6520, -1, -1, 678, 678, 3, 65, -1, 0, 0, 14, 6519, 7544), - (6521, -1, -1, 1021, 1021, 5, 75, -1, 0, 0, 14, 1025, 6522), - (6522, -1, -1, 1021, 1021, 5, 80, -1, 0, 0, 14, 6521, 7539), - (6523, -1, -1, 1026, 1026, 5, 76, -1, 0, 0, 14, 4687, 6524), - (6524, -1, -1, 1026, 1026, 5, 77, -1, 0, 0, 14, 6523, 6525), - (6525, -1, -1, 1026, 1026, 5, 78, -1, 0, 0, 14, 6524, 6526), - (6526, -1, -1, 1026, 1026, 5, 79, -1, 0, 0, 14, 6525, 6527), - (6527, -1, -1, 1026, 1026, 5, 80, -1, 0, 0, 14, 6526, 7511), - (6528, -1, -1, 501, 501, 5, 96, -1, 0, 0, 19, 6321, 6529), - (6531, -1, -1, 5295, 5295, 6, 76, -1, 0, 0, 14, 5297, 6532), - (6532, -1, -1, 5295, 5295, 6, 78, -1, 0, 0, 14, 6531, 6533), - (6533, -1, -1, 5295, 5295, 6, 80, -1, 0, 0, 14, 6532, 7220), - (6534, 8000, 8000, 8000, 8000, 12, 90, 23607, 73, 600, 17, -1, 14216), - (6540, -1, -1, 4699, 4699, 5, 56, -1, 0, 0, 14, 4699, 7500), - (6545, -1, -1, 4698, 4698, 5, 56, -1, 0, 0, 14, 4698, -1), - (6546, -1, -1, 6546, 6546, 0, 55, -1, 0, 0, 3, -1, 6547), - (6547, -1, -1, 6546, 6546, 0, 56, -1, 0, 0, 3, 6546, 6548), - (6548, -1, -1, 6546, 6546, 0, 57, -1, 0, 0, 3, 6547, 6549), - (6549, -1, -1, 6546, 6546, 0, 58, -1, 0, 0, 3, 6548, 6550), - (6550, -1, -1, 6546, 6546, 0, 59, -1, 0, 0, 3, 6549, 6551), - (6551, -1, -1, 6546, 6546, 0, 60, -1, 0, 0, 3, 6550, 6552), - (6552, -1, -1, 6546, 6546, 0, 61, -1, 0, 0, 3, 6551, 6553), - (6553, -1, -1, 6546, 6546, 0, 62, -1, 0, 0, 3, 6552, 6554), - (6554, -1, -1, 6546, 6546, 0, 63, -1, 0, 0, 3, 6553, 6555), - (6555, -1, -1, 6546, 6546, 0, 64, -1, 0, 0, 3, 6554, 6556), - (6556, -1, -1, 6546, 6546, 0, 65, -1, 0, 0, 3, 6555, 6557), - (6557, -1, -1, 6546, 6546, 0, 66, -1, 0, 0, 3, 6556, 6558), - (6558, -1, -1, 6546, 6546, 0, 67, -1, 0, 0, 3, 6557, 6559), - (6559, -1, -1, 6546, 6546, 0, 68, -1, 0, 0, 3, 6558, 6560), - (6560, -1, -1, 6546, 6546, 0, 69, -1, 0, 0, 3, 6559, 6561), - (6561, -1, -1, 6546, 6546, 0, 70, -1, 0, 0, 3, 6560, 6562), - (6562, -1, -1, 6546, 6546, 0, 71, -1, 0, 0, 3, 6561, 6563), - (6563, -1, -1, 6546, 6546, 0, 72, -1, 0, 0, 3, 6562, 6564), - (6564, -1, -1, 6546, 6546, 0, 73, -1, 0, 0, 3, 6563, 6565), - (6565, -1, -1, 6546, 6546, 0, 74, -1, 0, 0, 3, 6564, 6566), - (6566, -1, -1, 6546, 6546, 0, 75, -1, 0, 0, 3, 6565, 6567), - (6567, -1, -1, 6546, 6546, 0, 76, -1, 0, 0, 3, 6566, 6568), - (6568, -1, -1, 6546, 6546, 0, 77, -1, 0, 0, 3, 6567, 6569), - (6569, -1, -1, 6546, 6546, 0, 78, -1, 0, 0, 3, 6568, 6570), - (6570, -1, -1, 6546, 6546, 0, 79, -1, 0, 0, 3, 6569, 6571), - (6571, -1, -1, 6546, 6546, 0, 80, -1, 0, 0, 3, 6570, 7373), - (6601, -1, -1, 6601, 6601, 6, 72, -1, 0, 0, 14, -1, 6602), - (6602, -1, -1, 6601, 6601, 6, 73, -1, 0, 0, 14, 6601, 6603), - (6603, -1, -1, 6601, 6601, 6, 74, -1, 0, 0, 14, 6602, 6604), - (6604, -1, -1, 6601, 6601, 6, 75, -1, 0, 0, 14, 6603, 6605), - (6605, -1, -1, 6601, 6601, 6, 76, -1, 0, 0, 14, 6604, 7318), - (6606, 1597, 1597, 1597, 1597, 9, 75, 16095, 6, 10, 15, 1597, 10571), - (6607, 6607, 6607, 6607, 6607, 9, 75, 16092, 61, 600, 15, -1, 6608), - (6608, 6607, 6607, 6607, 6607, 9, 80, 16093, 61, 600, 15, 6607, 6609), - (6609, 6607, 6607, 6607, 6607, 9, 85, 16094, 61, 600, 15, 6608, 16324), - (6610, 6610, 6610, 6610, 6610, 2, 55, 16096, 41, 30, 15, -1, 10003), - (6611, -1, -1, 6611, 6611, 2, 60, -1, 0, 0, 15, -1, 6612), - (6612, -1, -1, 6611, 6611, 4, 63, -1, 0, 0, 15, 6611, 6613), - (6613, -1, -1, 6611, 6611, 6, 66, -1, 0, 0, 15, 6612, 6618), - (6614, -1, -1, 6614, 6614, 2, 60, -1, 0, 0, 15, -1, 6615), - (6615, -1, -1, 6614, 6614, 4, 63, -1, 0, 0, 15, 6614, 6616), - (6616, -1, -1, 6614, 6614, 6, 66, -1, 0, 0, 15, 6615, 10004), - (6617, 6617, 6617, 6617, 6617, 6, 83, 16097, 42, 3600, 15, -1, 10572), - (6618, -1, -1, 6611, 6611, 6, 69, -1, 0, 0, 15, 6613, 6619), - (6619, -1, -1, 6611, 6611, 6, 72, -1, 0, 0, 15, 6618, 10574), - (6630, -1, -1, 6630, 6630, 6, 70, -1, 0, 0, 15, -1, 6631), - (6631, -1, -1, 6630, 6630, 6, 70, -1, 0, 0, 15, 6630, 6632), - (6632, -1, -1, 6630, 6630, 6, 70, -1, 0, 0, 15, 6631, 6633), - (6633, -1, -1, 6630, 6630, 6, 70, -1, 0, 0, 15, 6632, 6634), - (6634, -1, -1, 6630, 6630, 6, 70, -1, 0, 0, 15, 6633, 10070), - (6635, 6635, 6635, 6635, 6635, 7, 70, 16098, 41, 600, 15, -1, -1), - (6636, -1, -1, 6636, 6636, 3, 70, -1, 0, 0, 15, -1, 6637), - (6637, -1, -1, 6636, 6636, 6, 70, -1, 0, 0, 15, 6636, 6638), - (6638, -1, -1, 6636, 6636, 9, 70, -1, 0, 0, 15, 6637, 10041), - (6639, 6639, 6639, 6639, 6639, 7, 70, 16099, 42, 300, 15, -1, 15173), - (6640, 6640, 6640, 6640, 6640, 7, 81, 16100, 43, 60, 15, -1, 12585), - (6641, -1, -1, 6641, 6641, 7, 81, -1, 0, 0, 15, -1, 6642), - (6642, -1, -1, 6641, 6641, 8, 83, -1, 0, 0, 15, 6641, 6643), - (6643, -1, -1, 6641, 6641, 9, 85, -1, 0, 0, 15, 6642, 10075), - (6644, 6644, 6644, 6644, 6644, 2, 70, 16104, 44, 20, 15, -1, 12586), - (6645, 6645, 6645, 6645, 6645, 6, 80, 16105, 45, 60, 15, -1, 13107), - (6646, 6646, 6646, 6646, 6646, 6, 70, 16106, 46, 6, 15, -1, -1), - (6660, -1, -1, 1307, 1307, 5, 73, -1, 0, 0, 15, 1311, 6661), - (6661, -1, -1, 1307, 1307, 5, 74, -1, 0, 0, 15, 6660, 6662), - (6662, -1, -1, 1307, 1307, 5, 75, -1, 0, 0, 15, 6661, 13210), - (6663, 6663, 6663, 6663, 6663, 7, 73, 16107, 59, 600, 15, -1, 6664), - (6664, 6663, 6663, 6663, 6663, 7, 75, 16108, 59, 600, 15, 6663, 6665), - (6665, 6663, 6663, 6663, 6663, 7, 77, 16109, 59, 600, 15, 6664, 10162), - (6666, -1, -1, 6666, 6666, 8, 81, -1, 0, 0, 15, -1, 6667), - (6667, -1, -1, 6666, 6666, 8, 83, -1, 0, 0, 15, 6666, -1), - (6668, -1, -1, 6668, 6668, 3, 76, -1, 0, 0, 15, -1, 6669), - (6669, -1, -1, 6668, 6668, 3, 77, -1, 0, 0, 15, 6668, 6670), - (6670, -1, -1, 6668, 6668, 3, 78, -1, 0, 0, 15, 6669, -1), - (6671, 6671, 6671, 6671, 6671, 4, 65, 16148, 60, 60, 15, -1, -1), - (6672, 6672, 6672, 6672, 6672, 4, 67, 16149, 60, 60, 15, -1, -1), - (6673, 6673, 6673, 6673, 6673, 4, 69, 16150, 60, 60, 15, -1, -1), - (6674, 6674, 6674, 6674, 6674, 4, 71, 16151, 60, 60, 15, -1, -1), - (6675, 6675, 6675, 6675, 6675, 4, 73, 16152, 60, 60, 15, -1, -1), - (6676, 6676, 6676, 6676, 6676, 4, 75, 16153, 60, 60, 15, -1, -1), - (6691, 6691, 6691, 6691, 6691, 9, 81, 16114, 41, 30, 15, -1, -1), - (6692, 6692, 6692, 6692, 6692, 7, 65, 16115, 42, 600, 15, -1, 6693), - (6693, 6692, 6692, 6692, 6692, 7, 70, 16116, 42, 600, 15, 6692, 6694), - (6694, 6692, 6692, 6692, 6692, 7, 75, 16117, 42, 600, 15, 6693, 6695), - (6695, 6692, 6692, 6692, 6692, 7, 80, 16118, 42, 600, 15, 6694, 6696), - (6696, 6692, 6692, 6692, 6692, 7, 85, 16119, 42, 600, 15, 6695, 5342), - (6697, -1, -1, 6697, 6697, 7, 65, -1, 0, 0, 15, -1, 6698), - (6698, -1, -1, 6697, 6697, 7, 70, -1, 0, 0, 15, 6697, 6699), - (6699, -1, -1, 6697, 6697, 7, 75, -1, 0, 0, 15, 6698, 6700), - (6700, -1, -1, 6697, 6697, 7, 80, -1, 0, 0, 15, 6699, 6701), - (6701, -1, -1, 6697, 6697, 7, 85, -1, 0, 0, 15, 6700, -1), - (6702, 6702, 6702, 6702, 6702, 9, 75, 16120, 43, 120, 15, -1, -1), - (6703, -1, -1, 6703, 6703, 3, 65, -1, 0, 0, 15, -1, 6704), - (6704, -1, -1, 6703, 6703, 3, 65, -1, 0, 0, 15, 6703, 6705), - (6705, -1, -1, 6703, 6703, 3, 65, -1, 0, 0, 15, 6704, 10176), - (6706, 6706, 6706, 6706, 6706, 7, 75, 16121, 44, 600, 15, -1, 6707), - (6707, 6706, 6706, 6706, 6706, 7, 80, 16122, 44, 600, 15, 6706, 6708), - (6708, 6706, 6706, 6706, 6706, 7, 85, 16123, 44, 600, 15, 6707, 10179), - (6709, -1, -1, 6709, 6709, 3, 60, -1, 0, 0, 15, -1, 6710), - (6710, -1, -1, 6709, 6709, 3, 61, -1, 0, 0, 15, 6709, 6711), - (6711, -1, -1, 6709, 6709, 3, 62, -1, 0, 0, 15, 6710, -1), - (6712, -1, -1, 6712, 6712, 7, 65, -1, 0, 0, 15, -1, 6713), - (6713, -1, -1, 6712, 6712, 7, 70, -1, 0, 0, 15, 6712, 6714), - (6714, -1, -1, 6712, 6712, 7, 75, -1, 0, 0, 15, 6713, 6715), - (6715, -1, -1, 6712, 6712, 7, 80, -1, 0, 0, 15, 6714, 6716), - (6716, -1, -1, 6712, 6712, 7, 85, -1, 0, 0, 15, 6715, 10182), - (6750, 6750, 6750, 6750, 6750, 9, 85, 16127, 60, 120, 15, -1, 13899), - (6751, -1, -1, 6751, 6751, 6, 75, -1, 0, 0, 15, -1, 6752), - (6752, -1, -1, 6751, 6751, 6, 75, -1, 0, 0, 15, 6751, 6753), - (6753, -1, -1, 6751, 6751, 6, 75, -1, 0, 0, 15, 6752, 6768), - (6754, 6754, 6754, 6754, 6754, 7, 70, 16130, 41, 1200, 15, -1, 10053), - (6755, 6755, 6755, 6755, 6755, 7, 81, 16131, 42, 900, 15, -1, 6756), - (6756, 6755, 6755, 6755, 6755, 9, 83, 16132, 42, 900, 15, 6755, 6757), - (6757, 6755, 6755, 6755, 6755, 12, 85, 16133, 42, 900, 15, 6756, 13542), - (6758, 6758, 6758, 6758, 6758, 3, 81, 16134, 43, 900, 15, -1, 6759), - (6759, 6758, 6758, 6758, 6758, 6, 83, 16135, 43, 900, 15, 6758, 6760), - (6760, 6758, 6758, 6758, 6758, 9, 85, 16136, 43, 900, 15, 6759, 10054), - (6761, -1, -1, 6761, 6761, 3, 65, -1, 0, 0, 15, -1, 6762), - (6762, -1, -1, 6761, 6761, 6, 65, -1, 0, 0, 15, 6761, 6763), - (6763, -1, -1, 6761, 6761, 9, 65, -1, 0, 0, 15, 6762, 6085), - (6764, 6764, 6764, 6764, 6764, 7, 75, 16137, 52, 600, 15, -1, 10057), - (6765, -1, -1, 6765, 6765, 3, 70, -1, 0, 0, 15, -1, 6766), - (6766, -1, -1, 6765, 6765, 6, 75, -1, 0, 0, 15, 6765, 6767), - (6767, -1, -1, 6765, 6765, 9, 80, -1, 0, 0, 15, 6766, 10058), - (6768, -1, -1, 6751, 6751, 6, 75, -1, 0, 0, 15, 6753, 6769), - (6769, -1, -1, 6751, 6751, 6, 75, -1, 0, 0, 15, 6768, 10769), - (6791, -1, -1, 6791, 6791, 6, 75, -1, 0, 0, 15, -1, 6792), - (6792, -1, -1, 6791, 6791, 6, 80, -1, 0, 0, 15, 6791, 6793), - (6793, -1, -1, 6791, 6791, 6, 85, -1, 0, 0, 15, 6792, 10044), - (6794, 6794, 6794, 6794, 6794, 6, 75, 16142, 41, 60, 15, -1, -1), - (6815, 6815, 6815, 6815, 6815, 8, 75, 16144, 60, 600, 15, -1, 6816), - (6816, 6815, 6815, 6815, 6815, 8, 80, 16145, 60, 600, 15, 6815, 6817), - (6817, 6815, 6815, 6815, 6815, 8, 85, 16146, 60, 600, 15, 6816, 10200), - (6818, 6818, 6818, 6818, 6818, 6, 70, 16147, 44, 20, 15, -1, -1), - (6819, -1, -1, 6819, 6819, 6, 72, -1, 0, 0, 15, -1, 6820), - (6820, -1, -1, 6819, 6819, 6, 74, -1, 0, 0, 15, 6819, 6821), - (6821, -1, -1, 6819, 6819, 6, 76, -1, 0, 0, 15, 6820, 10203), - (6822, 6822, 6822, 6822, 6822, 12, 80, 16154, 42, 120, 15, -1, 13683), - (6823, -1, -1, 6823, 6823, 4, 65, -1, 0, 0, 15, -1, 6824), - (6824, -1, -1, 6823, 6823, 4, 67, -1, 0, 0, 15, 6823, 6825), - (6825, -1, -1, 6823, 6823, 4, 69, -1, 0, 0, 15, 6824, 6826), - (6826, -1, -1, 6823, 6823, 4, 71, -1, 0, 0, 15, 6825, 6827), - (6827, -1, -1, 6823, 6823, 4, 73, -1, 0, 0, 15, 6826, 10206), - (6828, 6828, 6828, 6828, 6828, 12, 80, 16155, 43, 60, 15, -1, 10208), - (6870, -1, -1, 6870, 6870, 6, 75, -1, 0, 0, 15, -1, 6871), - (6871, -1, -1, 6870, 6870, 6, 75, -1, 0, 0, 15, 6870, 6872), - (6872, -1, -1, 6870, 6870, 6, 75, -1, 0, 0, 15, 6871, 10130), - (6873, -1, -1, 255, 255, 3, 76, -1, 0, 0, 15, -1, 6874), - (6874, -1, -1, 255, 255, 6, 76, -1, 0, 0, 15, 6873, 6875), - (6875, -1, -1, 255, 255, 9, 76, -1, 0, 0, 15, 6874, 10133), - (6876, -1, -1, 6375, 6375, 6, 76, -1, 0, 0, 15, -1, 6877), - (6877, -1, -1, 6375, 6375, 6, 77, -1, 0, 0, 15, 6876, 6878), - (6878, -1, -1, 6375, 6375, 6, 78, -1, 0, 0, 15, 6877, 10136), - (6879, -1, -1, 649, 649, 2, 66, -1, 0, 0, 15, -1, 6880), - (6880, -1, -1, 649, 649, 4, 68, -1, 0, 0, 15, 6879, 6881), - (6881, -1, -1, 649, 649, 6, 70, -1, 0, 0, 15, 6880, -1), - (6882, -1, -1, 776, 776, 3, 70, -1, 0, 0, 15, -1, 6883), - (6883, -1, -1, 776, 776, 3, 70, -1, 0, 0, 15, 6882, 6884), - (6884, -1, -1, 776, 776, 3, 70, -1, 0, 0, 15, 6883, -1), - (6900, -1, -1, 6935, 6935, 6, 81, -1, 0, 0, 16, 6937, 6901), - (6901, -1, -1, 6935, 6935, 6, 82, -1, 0, 0, 16, 6900, 6902), - (6902, -1, -1, 6935, 6935, 6, 83, -1, 0, 0, 16, 6901, 6903), - (6903, -1, -1, 6935, 6935, 6, 84, -1, 0, 0, 16, 6902, 6904), - (6904, -1, -1, 6935, 6935, 6, 85, -1, 0, 0, 16, 6903, 14196), - (6905, -1, -1, 551, 551, 5, 81, -1, 0, 0, 16, 1637, 6906), - (6906, -1, -1, 551, 551, 5, 83, -1, 0, 0, 16, 6905, 6907), - (6907, -1, -1, 551, 551, 5, 85, -1, 0, 0, 16, 6906, 12843), - (6908, -1, -1, 6908, 6908, 6, 81, -1, 0, 0, 16, -1, 6909), - (6909, -1, -1, 6908, 6908, 6, 83, -1, 0, 0, 16, 6908, 6910), - (6910, -1, -1, 6908, 6908, 6, 85, -1, 0, 0, 16, 6909, 14199), - (6911, -1, -1, 1143, 1143, 5, 65, -1, 0, 0, 16, 1168, 6912), - (6912, -1, -1, 1143, 1143, 7, 65, -1, 0, 0, 16, 6911, 6913), - (6913, -1, -1, 1143, 1143, 9, 65, -1, 0, 0, 16, 6912, -1), - (6930, 6930, 6930, 6930, 6930, 12, 80, 16156, 13, 60, 15, -1, -1), - (6931, 6931, 6931, 6931, 6931, 12, 85, 16157, 41, 600, 15, -1, 10319), - (6932, 6932, 6932, 6932, 6932, 7, 81, 16158, 42, 1200, 15, -1, 6933), - (6933, 6932, 6932, 6932, 6932, 7, 83, 16159, 42, 1200, 15, 6932, 6934), - (6934, 6932, 6932, 6932, 6932, 7, 85, 16160, 42, 1200, 15, 6933, 10320), - (6935, -1, -1, 6935, 6935, 6, 75, -1, 0, 0, 15, -1, 6936), - (6936, -1, -1, 6935, 6935, 6, 77, -1, 0, 0, 15, 6935, 6937), - (6937, -1, -1, 6935, 6935, 6, 79, -1, 0, 0, 15, 6936, 6900), - (6938, -1, -1, 6938, 6938, 7, 81, -1, 0, 0, 15, -1, 6939), - (6939, -1, -1, 6938, 6938, 7, 83, -1, 0, 0, 15, 6938, 6940), - (6940, -1, -1, 6938, 6938, 7, 85, -1, 0, 0, 15, 6939, -1), - (6941, -1, -1, 6941, 6941, 6, 81, -1, 0, 0, 15, -1, 6942), - (6942, -1, -1, 6941, 6941, 6, 81, -1, 0, 0, 15, 6941, 6943), - (6943, -1, -1, 6941, 6941, 6, 81, -1, 0, 0, 15, 6942, 6944), - (6944, -1, -1, 6941, 6941, 6, 81, -1, 0, 0, 15, 6943, 6945), - (6945, -1, -1, 6941, 6941, 6, 81, -1, 0, 0, 15, 6944, -1), - (6970, 6970, 6970, 6970, 6970, 6, 70, 16167, 61, 6, 15, -1, -1), - (6971, 6971, 6971, 6971, 6971, 7, 78, 16168, 41, 600, 15, -1, 6972), - (6972, 6971, 6971, 6971, 6971, 7, 80, 16169, 41, 600, 15, 6971, 6973), - (6973, 6971, 6971, 6971, 6971, 7, 82, 16170, 41, 600, 15, 6972, 10288), - (6974, -1, -1, 6974, 6974, 5, 81, -1, 0, 0, 15, -1, 6975), - (6975, -1, -1, 6974, 6974, 5, 83, -1, 0, 0, 15, 6974, 6976), - (6976, -1, -1, 6974, 6974, 5, 85, -1, 0, 0, 15, 6975, 10291), - (6977, -1, -1, 6977, 6977, 5, 81, -1, 0, 0, 15, -1, 6978), - (6978, -1, -1, 6977, 6977, 5, 83, -1, 0, 0, 15, 6977, 6979), - (6979, -1, -1, 6977, 6977, 5, 85, -1, 0, 0, 15, 6978, 12840), - (6980, -1, -1, 6980, 6980, 5, 81, -1, 0, 0, 15, -1, 6981), - (6981, -1, -1, 6980, 6980, 5, 83, -1, 0, 0, 15, 6980, 6982), - (6982, -1, -1, 6980, 6980, 5, 85, -1, 0, 0, 15, 6981, 12834), - (6983, 6983, 6983, 6983, 6983, 7, 83, 16439, 66, 720, 15, -1, 16246), - (6984, 6984, 6984, 6984, 6984, 6, 73, 16172, 60, 60, 15, -1, 10294), - (6985, 6985, 6985, 6985, 6985, 6, 73, 16173, 60, 60, 15, -1, 10295), - (6986, 6986, 6986, 6986, 6986, 6, 73, 16174, 60, 60, 15, -1, 10296), - (6987, -1, -1, 6987, 6987, 12, 81, -1, 0, 0, 15, -1, -1), - (6988, -1, -1, 6988, 6988, 5, 83, 0, 0, 0, 16, -1, 6989), - (6989, -1, -1, 6988, 6988, 5, 84, 0, 0, 0, 16, 6988, 6990), - (6990, -1, -1, 6988, 6988, 5, 83, 0, 0, 0, 16, 6989, 14278), - (7000, 7000, 7000, 7000, 7000, 4, 65, 12748, 31, 600, 3, -1, -1), - (7002, 7002, 7002, 7002, 7002, 4, 65, 12750, 31, 600, 3, -1, -1), - (7003, 7003, 7003, 7003, 7003, 4, 65, 12751, 31, 600, 3, -1, -1), - (7004, 7004, 7004, 7004, 7004, 4, 65, 12752, 31, 300, 3, -1, -1), - (7005, -1, -1, 7005, 7005, 2, 73, -1, 0, 0, 15, -1, 7006), - (7006, -1, -1, 7005, 7005, 2, 74, -1, 0, 0, 15, 7005, 7007), - (7007, -1, -1, 7005, 7005, 2, 75, -1, 0, 0, 15, 7006, 15632), - (7008, -1, -1, 1604, 1604, 9, 81, -1, 0, 0, 16, 7133, 7009), - (7009, -1, -1, 1604, 1604, 12, 83, -1, 0, 0, 16, 7008, 12612), - (7010, -1, -1, 7010, 7010, 6, 81, -1, 0, 0, 16, -1, 7011), - (7011, -1, -1, 7010, 7010, 6, 83, -1, 0, 0, 16, 7010, 7012), - (7012, -1, -1, 7010, 7010, 6, 85, -1, 0, 0, 16, 7011, 7013), - (7013, -1, -1, 7010, 7010, 6, 85, -1, 0, 0, 16, 7012, 7014), - (7014, -1, -1, 7010, 7010, 6, 85, -1, 0, 0, 16, 7013, 7015), - (7015, -1, -1, 7010, 7010, 6, 85, -1, 0, 0, 16, 7014, 13533), - (7016, 7016, 7016, 7016, 7016, 5, 85, 21658, 31, 600, 3, -1, -1), - (7017, 7017, 7017, 7017, 7017, 5, 85, 21659, 31, 600, 3, -1, -1), - (7018, 7018, 7018, 7018, 7018, 5, 85, 21660, 31, 600, 3, -1, -1), - (7019, 7019, 7019, 7019, 7019, 5, 85, 21661, 31, 600, 3, -1, -1), - (7020, 7020, 7020, 7020, 7020, 0, 85, 21658, 31, 600, 3, -1, -1), - (7021, 7021, 7021, 7021, 7021, 0, 85, 21659, 31, 600, 3, -1, -1), - (7022, 7022, 7022, 7022, 7022, 0, 85, 21660, 31, 600, 3, -1, -1), - (7023, 7023, 7023, 7023, 7023, 0, 85, 21661, 31, 600, 3, -1, -1), - (7024, 7024, 7024, 7024, 7024, 0, 0, 9475, 31, 600, 12, -1, -1), - (7025, 7025, 7025, 7025, 7025, 0, 0, 9477, 31, 600, 12, -1, -1), - (7026, 7026, 7026, 7026, 7026, 0, 0, 9478, 31, 600, 12, -1, -1), - (7027, 7027, 7027, 7027, 7027, 0, 0, 9479, 31, 600, 12, -1, -1), - (7028, 7028, 7028, 7028, 7028, 0, 0, 12748, 31, 600, 3, -1, -1), - (7030, 7030, 7030, 7030, 7030, 0, 0, 12750, 31, 600, 3, -1, -1), - (7031, 7031, 7031, 7031, 7031, 0, 0, 12751, 31, 600, 3, -1, -1), - (7032, 7032, 7032, 7032, 7032, 0, 0, 12752, 31, 300, 3, -1, -1), - (7033, -1, -1, 7033, 7033, 6, 85, 0, 0, 0, 16, -1, 7034), - (7034, -1, -1, 7033, 7033, 9, 85, 0, 0, 0, 16, 7033, 7035), - (7035, -1, -1, 7033, 7033, 12, 85, 0, 0, 0, 16, 7034, 15746), - (7036, -1, -1, 7036, 7036, 7, 81, -1, 0, 0, 16, -1, 7037), - (7037, -1, -1, 7036, 7036, 9, 81, -1, 0, 0, 16, 7036, 7038), - (7038, -1, -1, 7036, 7036, 12, 81, -1, 0, 0, 16, 7037, 10579), - (7050, -1, -1, 446, 735, 5, 67, -1, 0, 0, 8, 448, 7051), - (7051, -1, -1, 446, 735, 5, 68, -1, 0, 0, 8, 7050, 7052), - (7052, -1, -1, 446, 735, 5, 69, -1, 0, 0, 8, 7051, 7053), - (7053, -1, -1, 446, 735, 7, 72, -1, 0, 0, 12, 7052, 7054), - (7054, -1, -1, 446, 735, 7, 73, -1, 0, 0, 12, 7053, 7055), - (7055, -1, -1, 446, 735, 7, 74, -1, 0, 0, 12, 7054, 7063), - (7056, -1, -1, 735, 735, 5, 67, -1, 0, 0, 8, 737, 7057), - (7057, -1, -1, 735, 735, 5, 68, -1, 0, 0, 8, 7056, 7058), - (7058, -1, -1, 735, 735, 5, 69, -1, 0, 0, 8, 7057, 7059), - (7059, -1, -1, 735, 735, 7, 72, -1, 0, 0, 12, 7058, 7060), - (7060, -1, -1, 735, 735, 7, 73, -1, 0, 0, 12, 7059, 7061), - (7061, -1, -1, 735, 735, 7, 74, -1, 0, 0, 12, 7060, 7066), - (7062, -1, -1, 7062, 7062, 3, 51, -1, 0, 0, 0, -1, -1), - (7063, -1, -1, 446, 735, 8, 76, -1, 0, 0, 14, 7055, 7064), - (7064, -1, -1, 446, 735, 8, 77, -1, 0, 0, 14, 7063, 7065), - (7065, -1, -1, 446, 735, 8, 78, -1, 0, 0, 14, 7064, 7622), - (7066, -1, -1, 735, 735, 8, 76, -1, 0, 0, 14, 7061, 7067), - (7067, -1, -1, 735, 735, 8, 77, -1, 0, 0, 14, 7066, 7068), - (7068, -1, -1, 735, 735, 8, 78, -1, 0, 0, 14, 7067, 7625), - (7069, 7069, 7069, 7069, 7069, 3, 71, 13219, 39, 7, 14, -1, -1), - (7100, -1, -1, 7100, 7100, 6, 76, -1, 0, 0, 14, -1, 7101), - (7101, -1, -1, 7100, 7100, 6, 77, -1, 0, 0, 14, 7100, 7102), - (7102, -1, -1, 7100, 7100, 6, 78, -1, 0, 0, 14, 7101, 7323), - (7103, -1, -1, 7103, 7103, 2, 65, -1, 0, 0, 14, -1, 7104), - (7104, -1, -1, 7103, 7103, 2, 65, -1, 0, 0, 14, 7103, 7105), - (7105, -1, -1, 7103, 7103, 2, 65, -1, 0, 0, 14, 7104, 7326), - (7106, -1, -1, 7106, 7106, 6, 73, -1, 0, 0, 14, -1, 7107), - (7107, -1, -1, 7106, 7106, 7, 76, -1, 0, 0, 14, 7106, 7108), - (7108, -1, -1, 7106, 7106, 10, 79, -1, 0, 0, 14, 7107, -1), - (7109, 1351, 1351, 1351, 1351, 8, 82, 13499, 5, 30, 15, 6133, 13109), - (7110, 4849, 4849, 4849, 4849, 7, 81, 13593, 7, 1800, 15, 6134, 13914), - (7111, 54006, 54006, 54006, 54006, 7, 81, 13594, 18, 180, 15, 6135, 10006), - (7112, -1, -1, 6564, 6564, 6, 78, -1, 0, 0, 15, 6285, 7113), - (7113, -1, -1, 6564, 6564, 7, 81, -1, 0, 0, 15, 7112, 7114), - (7114, -1, -1, 6564, 6564, 10, 84, -1, 0, 0, 15, 7113, 10007), - (7115, 6565, 6565, 6565, 6565, 7, 81, 13595, 17, 45, 15, 6286, 10010), - (7116, -1, -1, 489, 489, 3, 68, -1, 0, 0, 15, 491, 7117), - (7117, -1, -1, 489, 489, 3, 69, -1, 0, 0, 15, 7116, 7118), - (7118, -1, -1, 489, 489, 3, 70, -1, 0, 0, 15, 7117, -1), - (7119, 912, 912, 912, 912, 3, 71, 13496, 4, 3600, 15, 1332, 7120), - (7120, 912, 912, 912, 912, 6, 73, 13497, 4, 3600, 15, 7119, 7121), - (7121, 912, 912, 912, 912, 9, 75, 13498, 4, 3600, 15, 7120, 10011), - (7122, -1, -1, 4844, 4844, 5, 76, -1, 0, 0, 15, 4848, 7123), - (7123, -1, -1, 4844, 4844, 5, 77, -1, 0, 0, 15, 7122, 7124), - (7124, -1, -1, 4844, 4844, 5, 78, -1, 0, 0, 15, 7123, 7125), - (7125, -1, -1, 4844, 4844, 5, 79, -1, 0, 0, 15, 7124, 7126), - (7126, -1, -1, 4844, 4844, 5, 80, -1, 0, 0, 15, 7125, 7686), - (7127, 4860, 4860, 4860, 4860, 12, 85, 13599, 13, 60, 15, 5606, -1), - (7128, -1, -1, 492, 492, 2, 68, -1, 0, 0, 15, 494, 7129), - (7129, -1, -1, 492, 492, 2, 69, -1, 0, 0, 15, 7128, 7130), - (7130, -1, -1, 492, 492, 2, 70, -1, 0, 0, 15, 7129, 10576), - (7131, -1, -1, 1604, 1604, 7, 75, -1, 0, 0, 15, 6034, 7132), - (7132, -1, -1, 1604, 1604, 9, 77, -1, 0, 0, 15, 7131, 7133), - (7133, -1, -1, 1604, 1604, 12, 79, -1, 0, 0, 15, 7132, 7008), - (7134, -1, -1, 1543, 1543, 7, 81, -1, 0, 0, 15, 6044, 7135), - (7135, -1, -1, 1543, 1543, 9, 83, -1, 0, 0, 15, 7134, 7136), - (7136, -1, -1, 1543, 1543, 12, 85, -1, 0, 0, 15, 7135, 10165), - (7137, -1, -1, 6559, 6559, 6, 79, -1, 0, 0, 15, 6274, 7138), - (7138, -1, -1, 6559, 6559, 7, 81, -1, 0, 0, 15, 7137, 7139), - (7139, -1, -1, 6559, 6559, 10, 83, -1, 0, 0, 15, 7138, -1), - (7143, 6328, 6328, 6328, 6328, 7, 79, 13601, 10, 600, 15, 6330, 7144), - (7144, 6328, 6328, 6328, 6328, 7, 81, 13602, 10, 600, 15, 7143, 7145), - (7145, 6328, 6328, 6328, 6328, 7, 83, 13603, 10, 600, 15, 7144, 10168), - (7146, -1, -1, 878, 878, 7, 81, -1, 0, 0, 15, 6332, 7147), - (7147, -1, -1, 878, 878, 7, 83, -1, 0, 0, 15, 7146, 10171), - (7148, -1, -1, 1304, 1304, 7, 81, -1, 0, 0, 15, 6031, 7149), - (7149, -1, -1, 1304, 1304, 9, 83, -1, 0, 0, 15, 7148, 7150), - (7150, -1, -1, 1304, 1304, 12, 85, -1, 0, 0, 15, 7149, 10865), - (7151, -1, -1, 846, 846, 7, 81, -1, 0, 0, 15, 6037, 7152), - (7152, -1, -1, 846, 846, 9, 83, -1, 0, 0, 15, 7151, 7153), - (7153, -1, -1, 846, 846, 12, 85, -1, 0, 0, 15, 7152, 10173), - (7154, 1352, 1352, 1352, 1352, 6, 81, 13613, 3, 60, 15, 6318, 7155), - (7155, 1352, 1352, 1352, 1352, 6, 83, 13614, 3, 60, 15, 7154, 7156), - (7156, 1352, 1352, 1352, 1352, 6, 85, 13615, 3, 60, 15, 7155, 10113), - (7157, 1358, 1358, 1358, 1358, 6, 81, 13610, 3, 60, 15, 6312, 7158), - (7158, 1358, 1358, 1358, 1358, 6, 83, 13611, 3, 60, 15, 7157, 7159), - (7159, 1358, 1358, 1358, 1358, 6, 85, 13612, 3, 60, 15, 7158, 10116), - (7160, -1, -1, 4801, 4801, 6, 79, -1, 0, 0, 15, 4803, 7161), - (7161, -1, -1, 4801, 4801, 6, 81, -1, 0, 0, 15, 7160, 7162), - (7162, -1, -1, 4801, 4801, 6, 83, -1, 0, 0, 15, 7161, 10122), - (7163, -1, -1, 820, 820, 5, 81, -1, 0, 0, 15, 5919, 7164), - (7164, -1, -1, 820, 820, 5, 83, -1, 0, 0, 15, 7163, 7165), - (7165, -1, -1, 820, 820, 5, 85, -1, 0, 0, 15, 7164, 10660), - (7166, -1, -1, 6343, 6343, 6, 79, -1, 0, 0, 15, 6345, 7167), - (7167, -1, -1, 6343, 6343, 6, 81, -1, 0, 0, 15, 7166, 7168), - (7168, -1, -1, 6343, 6343, 6, 83, -1, 0, 0, 15, 7167, -1), - (7169, -1, -1, 6020, 6020, 2, 81, -1, 0, 0, 15, 6059, 7170), - (7170, -1, -1, 6020, 6020, 2, 83, -1, 0, 0, 15, 7169, 7171), - (7171, -1, -1, 6020, 6020, 2, 85, -1, 0, 0, 15, 7170, 10663), - (7172, 1355, 1355, 1355, 1355, 6, 81, 13607, 3, 60, 15, 5916, 7173), - (7173, 1355, 1355, 1355, 1355, 6, 83, 13608, 3, 60, 15, 7172, 7174), - (7174, 1355, 1355, 1355, 1355, 6, 85, 13609, 3, 60, 15, 7173, 10119), - (7175, -1, -1, 611, 611, 2, 68, -1, 0, 0, 15, 615, 7176), - (7176, -1, -1, 611, 611, 2, 69, -1, 0, 0, 15, 7175, 7177), - (7177, -1, -1, 611, 611, 2, 70, -1, 0, 0, 15, 7176, 10124), - (7178, 4854, 4854, 4854, 4854, 7, 81, 13616, 8, 600, 15, 5766, 7179), - (7179, 4854, 4854, 4854, 4854, 9, 83, 13617, 8, 600, 15, 7178, 7180), - (7180, 4854, 4854, 4854, 4854, 12, 85, 13618, 8, 600, 15, 7179, 10323), - (7184, 1348, 1348, 1348, 1348, 12, 91, 13622, 0, 3600, 18, 5772, 7185), - (7187, 1178, 1178, 1178, 1178, 7, 81, 13625, 4, 900, 15, 5781, 7188), - (7188, 1178, 1178, 1178, 1178, 8, 82, 13626, 4, 900, 15, 7187, 7189), - (7189, 1178, 1178, 1178, 1178, 9, 83, 13627, 4, 900, 15, 7188, 10326), - (7196, -1, -1, 5776, 5776, 7, 81, -1, 0, 0, 16, 5778, 7197), - (7197, -1, -1, 5776, 5776, 9, 83, -1, 0, 0, 16, 7196, 7198), - (7198, -1, -1, 5776, 5776, 12, 85, -1, 0, 0, 16, 7197, 13043), - (7199, 1274, 1274, 1274, 1274, 9, 83, 13657, 9, 540, 15, 5949, 7200), - (7200, 1274, 1274, 1274, 1274, 10, 84, 13658, 9, 540, 15, 7199, 7201), - (7201, 1274, 1274, 1274, 1274, 12, 85, 13659, 9, 540, 15, 7200, 10209), - (7202, 1510, -1, 1510, 1510, 12, 75, 13664, 13, 2160, 15, 1510, 10212), - (7203, 184, 184, 184, 184, 10, 84, 13660, 5, 4320, 15, 5953, -1), - (7204, -1, -1, 5264, 5264, 7, 81, -1, 0, 0, 15, 5943, 7205), - (7205, -1, -1, 5264, 5264, 8, 82, -1, 0, 0, 15, 7204, 7206), - (7206, -1, -1, 5264, 5264, 9, 83, -1, 0, 0, 15, 7205, 7207), - (7207, -1, -1, 5264, 5264, 10, 84, -1, 0, 0, 15, 7206, 7208), - (7208, -1, -1, 5264, 5264, 12, 85, -1, 0, 0, 15, 7207, 10213), - (7209, 4927, 4927, 4927, 4927, 9, 76, 13656, 14, 600, 15, 4927, 10218), - (7210, -1, -1, 839, 839, 6, 75, -1, 0, 0, 15, 5329, 7211), - (7211, -1, -1, 839, 839, 6, 75, -1, 0, 0, 15, 7210, 7212), - (7212, -1, -1, 839, 839, 6, 75, -1, 0, 0, 15, 7211, 7213), - (7213, -1, -1, 839, 839, 6, 75, -1, 0, 0, 15, 7212, 7214), - (7214, -1, -1, 839, 839, 6, 75, -1, 0, 0, 15, 7213, 10219), - (7215, -1, -1, 4861, 4861, 9, 83, -1, 0, 0, 15, 5956, 7216), - (7216, -1, -1, 4861, 4861, 12, 85, -1, 0, 0, 15, 7215, 7682), - (7217, 967, 967, 967, 967, 6, 81, 13661, 10, 1800, 15, 6466, 7218), - (7218, 967, 967, 967, 967, 6, 82, 13662, 10, 1800, 15, 7217, 7219), - (7219, 967, 967, 967, 967, 6, 83, 13663, 10, 1800, 15, 7218, 10224), - (7220, -1, -1, 5295, 5295, 6, 81, -1, 0, 0, 15, 6533, 7221), - (7221, -1, -1, 5295, 5295, 6, 83, -1, 0, 0, 15, 7220, 7222), - (7222, -1, -1, 5295, 5295, 6, 85, -1, 0, 0, 15, 7221, 10227), - (7223, 6290, 6290, 6290, 6290, 7, 81, 13689, 0, 1, 15, 6295, 7224), - (7224, 6290, 6290, 6290, 6290, 9, 83, 13690, 0, 1, 15, 7223, 7225), - (7225, 6290, 6290, 6290, 6290, 12, 85, 13691, 0, 1, 15, 7224, 11064), - (7226, 619, 619, 619, 619, 6, 78, 13686, 6, 900, 15, 6298, 7227), - (7227, 619, 619, 619, 619, 6, 78, 13687, 6, 900, 15, 7226, 7228), - (7228, 619, 619, 619, 619, 6, 78, 13688, 6, 900, 15, 7227, 10230), - (7229, 4944, -1, 4944, 4944, 7, 81, 13677, 0, 1, 15, 6157, 7230), - (7230, 4944, -1, 4944, 4944, 9, 83, 13678, 0, 1, 15, 7229, 7231), - (7231, 4944, -1, 4944, 4944, 12, 85, 13679, 0, 1, 15, 7230, 11067), - (7232, -1, -1, 1210, 1210, 7, 81, -1, 0, 0, 15, 5576, 7233), - (7233, -1, -1, 1210, 1210, 9, 83, -1, 0, 0, 15, 7232, 7234), - (7234, -1, -1, 1210, 1210, 12, 85, -1, 0, 0, 15, 7233, 12523), - (7235, 923, 923, 923, 923, 9, 82, 13673, 8, 60, 15, 6151, -1), - (7236, 922, 922, 922, 922, 9, 83, 13672, 8, 60, 15, 6150, -1), - (7237, 516, 516, 516, 516, 6, 77, 13692, 5, 480, 15, 6398, 10233), - (7238, 155, 155, 155, 155, 12, 82, 13693, 8, 60, 15, 5289, 14324), - (7239, 1334, 1334, 1334, 1334, 9, 83, 13674, 11, 4320, 15, 6154, 7240), - (7240, 1334, 1334, 1334, 1334, 10, 84, 13675, 11, 4320, 15, 7239, 7241), - (7241, 1334, 1334, 1334, 1334, 12, 85, 13676, 11, 4320, 15, 7240, 10234), - (7242, 1478, -1, 1478, 1478, 9, 83, 13680, 0, 1, 15, 6163, 7243), - (7243, 1478, -1, 1478, 1478, 10, 84, 13681, 0, 1, 15, 7242, 7244), - (7244, 1478, -1, 1478, 1478, 12, 85, 13682, 0, 1, 15, 7243, 11070), - (7245, 921, 921, 921, 921, 9, 84, 13671, 8, 60, 15, 6149, -1), - (7246, 4915, 4915, 4915, 4915, 7, 81, 13683, 7, 4320, 15, 5609, 7247), - (7247, 4915, 4915, 4915, 4915, 9, 83, 13684, 7, 4320, 15, 7246, 7248), - (7248, 4915, 4915, 4915, 4915, 12, 85, 13685, 7, 4320, 15, 7247, -1), - (7249, 167, 167, 167, 167, 10, 84, 13703, 14, 900, 15, 5879, 8343), - (7250, 520, 520, 520, 520, 12, 81, 13704, 6, 540, 15, 5885, 7251), - (7251, 520, 520, 520, 520, 12, 83, 13705, 6, 540, 15, 7250, 7252), - (7252, 520, 520, 520, 520, 12, 85, 13706, 6, 540, 15, 7251, 10252), - (7253, 4903, 4903, 4903, 4903, 9, 81, 13707, 9, 1320, 15, 5892, 10255), - (7254, 4906, 4906, 4906, 4906, 9, 81, 13708, 9, 1320, 15, 5893, 10256), - (7255, 4909, 4909, 4909, 4909, 9, 81, 13709, 16, 1320, 15, 5894, 10257), - (7256, 4912, 4912, 4912, 4912, 9, 81, 13710, 16, 1320, 15, 5895, 10258), - (7257, 616, 616, 616, 616, 6, 78, 13711, 7, 900, 15, 6256, 7258), - (7258, 616, 616, 616, 616, 7, 81, 13712, 7, 900, 15, 7257, 7259), - (7259, 616, 616, 616, 616, 10, 84, 13713, 7, 900, 15, 7258, 10259), - (7260, -1, -1, 1504, 1504, 5, 81, -1, 0, 0, 15, 5882, 7261), - (7261, -1, -1, 1504, 1504, 5, 83, -1, 0, 0, 15, 7260, 7262), - (7262, -1, -1, 1504, 1504, 5, 85, -1, 0, 0, 15, 7261, -1), - (7263, -1, -1, 1577, 1577, 7, 81, -1, 0, 0, 15, 5888, 7264), - (7264, -1, -1, 1577, 1577, 9, 83, -1, 0, 0, 15, 7263, 7265), - (7265, -1, -1, 1577, 1577, 12, 85, -1, 0, 0, 15, 7264, 10262), - (7266, 6333, 6333, 6333, 6333, 6, 64, 13714, 3, 600, 15, 6333, 13920), - (7267, -1, -1, 795, 795, 7, 81, -1, 0, 0, 15, 5891, 7268), - (7268, -1, -1, 795, 795, 9, 83, -1, 0, 0, 15, 7267, 7269), - (7269, -1, -1, 795, 795, 12, 85, -1, 0, 0, 15, 7268, 10265), - (7270, -1, -1, 790, 790, 6, 81, -1, 0, 0, 15, 5324, 7271), - (7271, -1, -1, 790, 790, 6, 82, -1, 0, 0, 15, 7270, 7272), - (7272, -1, -1, 790, 790, 6, 83, -1, 0, 0, 15, 7271, 7273), - (7273, -1, -1, 790, 790, 6, 84, -1, 0, 0, 15, 7272, 7274), - (7274, -1, -1, 790, 790, 6, 85, -1, 0, 0, 15, 7273, 12950), - (7275, 1239, 1239, 1239, 1239, 12, 85, 13735, 6, 600, 15, 5868, 13251), - (7276, 773, -1, 773, 773, 7, 81, 13726, 5, 1800, 15, 5856, 7277), - (7277, 773, -1, 773, 773, 9, 83, 13727, 5, 1800, 15, 7276, 7278), - (7278, 773, -1, 773, 773, 12, 85, 13728, 5, 1800, 15, 7277, 10564), - (7279, 6552, 6552, 6552, 6552, 5, 75, -1, 0, 0, 15, 6253, 7280), - (7280, 6552, 6552, 6552, 6552, 6, 77, -1, 0, 0, 15, 7279, 7281), - (7281, 6552, 6552, 6552, 6552, 6, 79, -1, 0, 0, 15, 7280, 7282), - (7282, 6552, 6552, 6552, 6552, 7, 81, -1, 0, 0, 15, 7281, 7283), - (7283, 6552, 6552, 6552, 6552, 9, 83, -1, 0, 0, 15, 7282, -1), - (7284, -1, -1, 781, 781, 8, 82, -1, 0, 0, 15, 5850, 13763), - (7285, 1242, 1242, 1242, 1242, 7, 81, 13723, 9, 1320, 15, 5859, 7286), - (7286, 1242, 1242, 1242, 1242, 9, 83, 13724, 9, 1320, 15, 7285, 7287), - (7287, 1242, 1242, 1242, 1242, 12, 85, 13725, 9, 1320, 15, 7286, 10271), - (7288, 4894, 4894, 4894, 4894, 6, 81, 13732, 7, 2160, 15, 6354, 7289), - (7289, 4894, 4894, 4894, 4894, 6, 82, 13733, 7, 2160, 15, 7288, 7290), - (7290, 4894, 4894, 4894, 4894, 6, 83, 13734, 7, 2160, 15, 7289, 13247), - (7291, 4931, 4931, 4931, 4931, 7, 81, 13729, 4, 600, 15, 6056, 7292), - (7292, 4931, 4931, 4931, 4931, 7, 83, 13730, 4, 600, 15, 7291, 7293), - (7293, 4931, 4931, 4931, 4931, 7, 85, 13731, 4, 600, 15, 7292, 10274), - (7294, 4935, 4935, 4935, 4935, 7, 76, 13722, 14, 300, 15, 4935, 10277), - (7295, 4934, 4934, 4934, 4934, 7, 76, 13721, 13, 300, 15, 4934, 10278), - (7296, 517, 517, 517, 517, 5, 73, 13718, 12, 600, 15, 1444, 7297), - (7297, 517, 517, 517, 517, 5, 74, 13719, 12, 600, 15, 7296, 7298), - (7298, 517, 517, 517, 517, 5, 75, 13720, 12, 600, 15, 7297, 10279), - (7299, 1383, 1383, 1383, 1383, 12, 85, 16000, 6, 300, 15, 5789, 10014), - (7300, 1195, 1195, 1195, 1195, 9, 85, 16001, 13, 2160, 15, 5790, 10015), - (7301, 131, 131, 131, 131, 8, 82, 16002, 4, 900, 15, 5793, 7302), - (7302, 131, 131, 131, 131, 9, 83, 16003, 4, 900, 15, 7301, 7303), - (7303, 131, 131, 131, 131, 10, 84, 16004, 4, 900, 15, 7302, 10016), - (7304, 1192, 1192, 1192, 1192, 8, 82, 16005, 12, 1320, 15, 5796, 7305), - (7305, 1192, 1192, 1192, 1192, 9, 83, 16006, 12, 1320, 15, 7304, 7306), - (7306, 1192, 1192, 1192, 1192, 10, 84, 16007, 12, 1320, 15, 7305, 10019), - (7307, 746, 746, 746, 746, 9, 83, 16008, 10, 2160, 15, 5802, 7308), - (7308, 746, 746, 746, 746, 10, 84, 16009, 10, 2160, 15, 7307, 7309), - (7309, 746, 746, 746, 746, 12, 85, 16010, 10, 2160, 15, 7308, 10022), - (7310, 1459, 1459, 1459, 1459, 7, 81, 16011, 11, 1800, 15, 5805, 7311), - (7311, 1459, 1459, 1459, 1459, 9, 83, 16012, 11, 1800, 15, 7310, 7312), - (7312, 1459, 1459, 1459, 1459, 12, 85, 16013, 11, 1800, 15, 7311, -1), - (7313, -1, -1, 6436, 6436, 6, 78, -1, 0, 0, 15, 6438, 7314), - (7314, -1, -1, 6436, 6436, 6, 80, -1, 0, 0, 15, 7313, 7315), - (7315, -1, -1, 6436, 6436, 8, 82, -1, 0, 0, 15, 7314, -1), - (7316, -1, -1, 468, 468, 2, 72, -1, 0, 0, 15, 6440, 7317), - (7317, -1, -1, 468, 468, 2, 74, -1, 0, 0, 15, 7316, 17288), - (7318, -1, -1, 6601, 6601, 6, 77, -1, 0, 0, 15, 6605, 7319), - (7319, -1, -1, 6601, 6601, 6, 78, -1, 0, 0, 15, 7318, 7320), - (7320, -1, -1, 6601, 6601, 6, 79, -1, 0, 0, 15, 7319, 7321), - (7321, -1, -1, 6601, 6601, 6, 80, -1, 0, 0, 15, 7320, 7322), - (7322, -1, -1, 6601, 6601, 6, 81, -1, 0, 0, 15, 7321, 10025), - (7323, -1, -1, 7100, 7100, 6, 81, -1, 0, 0, 15, 7102, 7324), - (7324, -1, -1, 7100, 7100, 6, 82, -1, 0, 0, 15, 7323, 7325), - (7325, -1, -1, 7100, 7100, 6, 83, -1, 0, 0, 15, 7324, 8427), - (7326, -1, -1, 7103, 7103, 2, 70, -1, 0, 0, 15, 7105, 7327), - (7327, -1, -1, 7103, 7103, 2, 70, -1, 0, 0, 15, 7326, 7328), - (7328, -1, -1, 7103, 7103, 2, 70, -1, 0, 0, 15, 7327, 10750), - (7329, 534, 534, 534, 534, 7, 81, 16021, 4, 2160, 15, 5971, 7330), - (7330, 534, 534, 534, 534, 9, 83, 16022, 4, 2160, 15, 7329, 7331), - (7331, 534, 534, 534, 534, 12, 85, 16023, 4, 2160, 15, 7330, 10047), - (7332, 5095, 5095, 5095, 5095, 7, 81, 16024, 10, 900, 15, 5977, 7333), - (7333, 5095, 5095, 5095, 5095, 9, 83, 16025, 10, 900, 15, 7332, 7334), - (7334, 5095, 5095, 5095, 5095, 12, 85, 16026, 10, 900, 15, 7333, 10640), - (7335, 5984, 5984, 5984, 5984, 12, 85, 16027, 2, 30, 15, 5984, 7710), - (7336, -1, -1, 6395, 6395, 7, 81, -1, 0, 0, 15, 6397, 7337), - (7337, -1, -1, 6395, 6395, 7, 82, -1, 0, 0, 15, 7336, 7338), - (7338, -1, -1, 6395, 6395, 7, 83, -1, 0, 0, 15, 7337, 10050), - (7339, 188, 188, 188, 188, 9, 78, 16020, 2, 30, 14, 5044, 7662), - (7340, 7850, 7850, 7850, 7850, 8, 81, 16028, 39, 4320, 0, 7865, 10618), - (7341, 5007, 5007, 5007, 5007, 9, 81, 16047, 8, 2160, 15, 6427, 7342), - (7342, 5007, 5007, 5007, 5007, 9, 83, 16048, 8, 2160, 15, 7341, 7343), - (7343, 5007, 5007, 5007, 5007, 9, 85, 16049, 8, 2160, 15, 7342, 10061), - (7344, 545, 545, 545, 545, 7, 81, 16038, 3, 900, 15, 6002, 7345), - (7345, 545, 545, 545, 545, 9, 83, 16039, 3, 900, 15, 7344, 7346), - (7346, 545, 545, 545, 545, 12, 85, 16040, 3, 900, 15, 7345, 10758), - (7347, 1345, 1345, 1345, 1345, 8, 82, 16041, 6, 900, 15, 6010, 7348), - (7348, 1345, 1345, 1345, 1345, 9, 83, 16042, 6, 900, 15, 7347, 7349), - (7349, 1345, 1345, 1345, 1345, 10, 84, 16043, 6, 900, 15, 7348, 10740), - (7350, 6370, 6370, 6370, 6370, 6, 81, 16044, 7, 600, 15, 6372, 7351), - (7351, 6370, 6370, 6370, 6370, 6, 82, 16045, 7, 600, 15, 7350, 7352), - (7352, 6370, 6370, 6370, 6370, 6, 83, 16046, 7, 600, 15, 7351, 14112), - (7353, -1, -1, 864, 864, 6, 85, -1, 0, 0, 15, 6013, 7354), - (7354, -1, -1, 864, 864, 6, 85, -1, 0, 0, 15, 7353, 7355), - (7355, -1, -1, 864, 864, 6, 85, -1, 0, 0, 15, 7354, -1), - (7356, -1, -1, 5248, 5248, 7, 81, -1, 0, 0, 15, 6016, 7357), - (7357, -1, -1, 5248, 5248, 9, 83, -1, 0, 0, 15, 7356, 7358), - (7358, -1, -1, 5248, 5248, 12, 85, -1, 0, 0, 15, 7357, 16170), - (7359, -1, -1, 644, 644, 7, 79, -1, 0, 0, 15, 6019, 7360), - (7360, -1, -1, 644, 644, 9, 81, -1, 0, 0, 15, 7359, 7361), - (7361, -1, -1, 644, 644, 12, 83, -1, 0, 0, 15, 7360, 13092), - (7362, -1, -1, 867, 867, 5, 70, -1, 0, 0, 15, 871, 7363), - (7363, -1, -1, 867, 867, 5, 70, -1, 0, 0, 15, 7362, 7364), - (7364, -1, -1, 867, 867, 5, 70, -1, 0, 0, 15, 7363, 7365), - (7365, -1, -1, 867, 867, 5, 70, -1, 0, 0, 15, 7364, 7366), - (7366, -1, -1, 867, 867, 5, 70, -1, 0, 0, 15, 7365, 10748), - (7367, 872, 872, 872, 872, 3, 70, 16032, 5, 180, 15, 874, 7368), - (7368, 872, 872, 872, 872, 6, 70, 16033, 5, 180, 15, 7367, 7369), - (7369, 872, 872, 872, 872, 9, 70, 16034, 5, 180, 15, 7368, 10772), - (7370, 875, 875, 875, 875, 3, 70, 16035, 5, 180, 15, 877, 7371), - (7371, 875, 875, 875, 875, 6, 73, 16036, 5, 180, 15, 7370, 7372), - (7372, 875, 875, 875, 875, 9, 75, 16037, 5, 180, 15, 7371, 10775), - (7373, -1, -1, 6546, 6546, 0, 81, -1, 0, 0, 15, 6571, 7374), - (7374, -1, -1, 6546, 6546, 0, 82, -1, 0, 0, 15, 7373, 7375), - (7375, -1, -1, 6546, 6546, 0, 83, -1, 0, 0, 15, 7374, 7376), - (7376, -1, -1, 6546, 6546, 0, 84, -1, 0, 0, 15, 7375, 7377), - (7377, -1, -1, 6546, 6546, 0, 85, -1, 0, 0, 15, 7376, 13122), - (7378, -1, -1, 1608, 1608, 3, 71, -1, 0, 0, 15, 4991, 7379), - (7379, -1, -1, 1608, 1608, 6, 73, -1, 0, 0, 15, 7378, 7380), - (7380, -1, -1, 1608, 1608, 9, 75, -1, 0, 0, 15, 7379, 7381), - (7381, -1, -1, 1608, 1608, 6, 76, -1, 0, 0, 15, 7380, 7382), - (7382, -1, -1, 1608, 1608, 6, 78, -1, 0, 0, 15, 7381, 7383), - (7383, -1, -1, 1608, 1608, 6, 80, -1, 0, 0, 15, 7382, 10064), - (7384, -1, -1, 5085, 5085, 6, 81, -1, 0, 0, 15, 6408, 7385), - (7385, -1, -1, 5085, 5085, 6, 83, -1, 0, 0, 15, 7384, 7386), - (7386, -1, -1, 5085, 5085, 6, 85, -1, 0, 0, 15, 7385, 10383), - (7387, 6508, 6508, 6508, 6508, 7, 79, 16059, 38, 600, 15, 6510, 7388), - (7388, 6508, 6508, 6508, 6508, 7, 81, 16060, 38, 600, 15, 7387, 7389), - (7389, 6508, 6508, 6508, 6508, 7, 83, 16061, 38, 600, 15, 7388, 10078), - (7390, -1, -1, 589, 589, 7, 81, -1, 0, 0, 15, 6065, 7391), - (7391, -1, -1, 589, 589, 7, 83, -1, 0, 0, 15, 7390, 7392), - (7392, -1, -1, 589, 589, 7, 85, -1, 0, 0, 15, 7391, 7707), - (7393, -1, -1, 1313, 1313, 7, 81, -1, 0, 0, 15, 6071, 7394), - (7394, -1, -1, 1313, 1313, 7, 81, -1, 0, 0, 15, 7393, 7395), - (7395, -1, -1, 1313, 1313, 8, 82, -1, 0, 0, 15, 7394, 7396), - (7396, -1, -1, 1313, 1313, 9, 83, -1, 0, 0, 15, 7395, 7397), - (7397, -1, -1, 1313, 1313, 10, 84, -1, 0, 0, 15, 7396, 7398), - (7398, -1, -1, 1313, 1313, 12, 85, -1, 0, 0, 15, 7397, 10081), - (7399, -1, -1, 210, 210, 8, 82, -1, 0, 0, 15, 6074, 7400), - (7400, -1, -1, 210, 210, 9, 83, -1, 0, 0, 15, 7399, 7401), - (7401, -1, -1, 210, 210, 10, 84, -1, 0, 0, 15, 7400, 15172), - (7402, -1, -1, 895, 895, 7, 81, -1, 0, 0, 15, 6079, 7403), - (7403, -1, -1, 895, 895, 8, 82, -1, 0, 0, 15, 7402, 7404), - (7404, -1, -1, 895, 895, 9, 83, -1, 0, 0, 15, 7403, 7405), - (7405, -1, -1, 895, 895, 10, 84, -1, 0, 0, 15, 7404, 7406), - (7406, -1, -1, 895, 895, 12, 85, -1, 0, 0, 15, 7405, 10906), - (7407, -1, -1, 7407, 7407, 12, 85, 0, 0, 0, 16, -1, -1), - (7408, 1498, 1498, 1498, 1498, 7, 81, 16075, 12, 1320, 15, 5821, 7409), - (7409, 1498, 1498, 1498, 1498, 9, 83, 16076, 12, 1320, 15, 7408, 7410), - (7410, 1498, 1498, 1498, 1498, 12, 85, 16077, 12, 1320, 15, 7409, 10090), - (7411, 757, -1, 757, 757, 7, 81, 16078, 6, 1800, 15, 5824, 7412), - (7412, 757, -1, 757, 757, 9, 83, 16079, 6, 1800, 15, 7411, 7413), - (7413, 757, -1, 757, 757, 12, 85, 16080, 6, 1800, 15, 7412, 12658), - (7414, 1495, 1495, 1495, 1495, 7, 81, 16081, 30, 900, 15, 5828, 7415), - (7415, 1495, 1495, 1495, 1495, 9, 83, 16082, 30, 900, 15, 7414, 7416), - (7416, 1495, 1495, 1495, 1495, 12, 85, 16083, 30, 900, 15, 7415, 10093), - (7417, 548, 548, 548, 548, 8, 82, 16084, 5, 900, 15, 5831, 7418), - (7418, 548, 548, 548, 548, 9, 83, 16085, 5, 900, 15, 7417, 7419), - (7419, 548, 548, 548, 548, 10, 84, 16086, 5, 900, 15, 7418, 10096), - (7420, 5105, 5105, 5105, 5105, 12, 85, 16087, 11, 600, 15, 5832, 10509), - (7421, 6232, 6232, 6232, 6232, 12, 85, 16091, 18, 900, 15, 6232, -1), - (7422, 6561, 6561, 6561, 6561, 7, 81, 16088, 32, 30, 15, 6280, 7423), - (7423, 6561, 6561, 6561, 6561, 7, 81, 16089, 32, 30, 15, 7422, 7424), - (7424, 6561, 6561, 6561, 6561, 7, 81, 16090, 32, 30, 15, 7423, 10099), - (7425, 510, 510, 510, 510, 3, 66, 16072, 37, 240, 15, 512, 7426), - (7426, 510, 510, 510, 510, 3, 68, 16073, 37, 240, 15, 7425, 7427), - (7427, 510, 510, 510, 510, 3, 70, 16074, 37, 240, 15, 7426, 10102), - (7428, 6533, 6533, 6533, 6533, 10, 84, 13785, 15, 600, 15, 6200, 10139), - (7429, 6534, 6534, 6534, 6534, 9, 83, 13777, 16, 900, 15, 6201, 13524), - (7430, 1116, 1116, 1116, 1116, 7, 81, 13762, 4, 2160, 15, 5701, 7431), - (7431, 1116, 1116, 1116, 1116, 9, 83, 13763, 4, 2160, 15, 7430, 7432), - (7432, 1116, 1116, 1116, 1116, 12, 85, 13764, 4, 2160, 15, 7431, 10140), - (7433, 592, 592, 592, 592, 5, 81, 13765, 2, 18, 15, 5706, 7434), - (7434, 592, 592, 592, 592, 5, 82, 13766, 2, 18, 15, 7433, 7435), - (7435, 592, 592, 592, 592, 5, 83, 13767, 2, 18, 15, 7434, 7436), - (7436, 592, 592, 592, 592, 5, 84, 13768, 2, 18, 15, 7435, 7437), - (7437, 592, 592, 592, 592, 5, 85, 13769, 2, 18, 15, 7436, 12749), - (7438, 5298, 5298, 5298, 5298, 9, 83, 13770, 32, 1800, 15, 5709, 7439), - (7439, 5298, 5298, 5298, 5298, 10, 84, 13771, 32, 1800, 15, 7438, 7440), - (7440, 5298, 5298, 5298, 5298, 12, 85, 13772, 32, 1800, 15, 7439, 10143), - (7441, 1598, -1, 1598, 1598, 7, 81, 13773, 6, 900, 15, 5712, 7442), - (7442, 1598, -1, 1598, 1598, 9, 83, 13774, 6, 900, 15, 7441, 7443), - (7443, 1598, -1, 1598, 1598, 12, 85, 13775, 6, 900, 15, 7442, 10146), - (7444, 5020, 5020, 5020, 5020, 9, 82, 13776, 9, 300, 15, 5716, 10149), - (7445, 1110, 1110, 1110, 1110, 6, 78, 13778, 3, 2160, 15, 6402, 7446), - (7446, 1110, 1110, 1110, 1110, 6, 80, 13779, 3, 2160, 15, 7445, 7447), - (7447, 1110, 1110, 1110, 1110, 6, 81, 13780, 3, 2160, 15, 7446, 10150), - (7448, -1, -1, 6337, 6337, 6, 79, -1, 0, 0, 15, 6339, 7449), - (7449, -1, -1, 6337, 6337, 6, 81, -1, 0, 0, 15, 7448, 7450), - (7450, -1, -1, 6337, 6337, 6, 83, -1, 0, 0, 15, 7449, 10153), - (7451, -1, -1, 6340, 6340, 6, 79, -1, 0, 0, 15, 6342, 7452), - (7452, -1, -1, 6340, 6340, 6, 81, -1, 0, 0, 15, 7451, 7453), - (7453, -1, -1, 6340, 6340, 6, 83, -1, 0, 0, 15, 7452, 16306), - (7454, 5017, 5017, 5017, 5017, 3, 76, 13759, 8, 600, 15, 5019, 7455), - (7455, 5017, 5017, 5017, 5017, 6, 78, 13760, 8, 600, 15, 7454, 7456), - (7456, 5017, 5017, 5017, 5017, 9, 80, 13761, 8, 600, 15, 7455, 10156), - (7457, 1569, 1569, 1569, 1569, 7, 82, 13756, 5, 1800, 15, 5715, 7458), - (7458, 1569, 1569, 1569, 1569, 7, 83, 13757, 5, 1800, 15, 7457, 7459), - (7459, 1569, 1569, 1569, 1569, 7, 85, 13758, 5, 1800, 15, 7458, 10159), - (7460, 1327, 1327, 1327, 1327, 7, 81, 13792, 10, 900, 15, 6100, 7461), - (7461, 1327, 1327, 1327, 1327, 9, 83, 13793, 10, 900, 15, 7460, 7462), - (7462, 1327, 1327, 1327, 1327, 12, 85, 13794, 10, 900, 15, 7461, 10187), - (7463, 1520, 1520, 1520, 1520, 9, 75, 13801, 11, 900, 15, 6451, 7464), - (7464, 1520, 1520, 1520, 1520, 9, 75, 13802, 11, 900, 15, 7463, 7465), - (7465, 1520, 1520, 1520, 1520, 9, 75, 13803, 11, 900, 15, 7464, 10190), - (7466, 146, 146, 146, 146, 8, 82, 13796, 2, 180, 15, 6102, 7691), - (7467, 5109, 5109, 5109, 5109, 9, 82, 13800, 0, 1, 15, 6448, 13016), - (7468, 153, 153, 153, 153, 12, 85, 13795, 3, 2160, 15, 6101, 10193), - (7469, 528, 528, 528, 528, 7, 81, 13797, 5, 720, 15, 6105, 7470), - (7470, 528, 528, 528, 528, 9, 83, 13798, 5, 720, 15, 7469, 7471), - (7471, 528, 528, 528, 528, 12, 85, 13799, 5, 720, 15, 7470, 10194), - (7472, 5251, 5251, 5251, 5251, 7, 81, 13786, 13, 900, 15, 6094, 7473), - (7473, 5251, 5251, 5251, 5251, 9, 83, 13787, 13, 900, 15, 7472, 7474), - (7474, 5251, 5251, 5251, 5251, 12, 85, 13788, 13, 900, 15, 7473, 10197), - (7475, 513, 513, 513, 513, 7, 81, 13789, 4, 120, 15, 6097, 7476), - (7476, 513, 513, 513, 513, 9, 83, 13790, 4, 120, 15, 7475, 7477), - (7477, 513, 513, 513, 513, 12, 85, 13791, 4, 120, 15, 7476, -1), - (7478, -1, -1, 6538, 6538, 12, 85, -1, 0, 0, 15, 6211, 15421), - (7479, 1119, 1119, 1119, 1119, 7, 83, 13805, 8, 900, 15, 5736, 7480), - (7480, 1119, 1119, 1119, 1119, 8, 84, 13806, 8, 900, 15, 7479, 7481), - (7481, 1119, 1119, 1119, 1119, 9, 85, 13807, 8, 900, 15, 7480, 10297), - (7482, 723, 723, 723, 723, 7, 81, 13808, 6, 30, 15, 5737, 10300), - (7483, 5015, 5015, 5015, 5015, 12, 85, 13809, 9, 900, 15, 5741, 10301), - (7484, 289, 289, 289, 289, 12, 85, 13810, 3, 300, 15, 5742, -1), - (7485, 291, 291, 291, 291, 9, 83, 13811, 5, 900, 15, 5745, 7486), - (7486, 291, 291, 291, 291, 10, 84, 13812, 5, 900, 15, 7485, 7487), - (7487, 291, 291, 291, 291, 12, 85, 13813, 5, 900, 15, 7486, 10302), - (7488, 6218, 6218, 6218, 6218, 7, 81, 13814, 0, 1, 15, 6218, 14272), - (7489, -1, -1, 724, 724, 7, 81, -1, 0, 0, 15, 5733, 7490), - (7490, -1, -1, 724, 724, 8, 82, -1, 0, 0, 15, 7489, 7491), - (7491, -1, -1, 724, 724, 9, 83, -1, 0, 0, 15, 7490, 7492), - (7492, -1, -1, 724, 724, 10, 84, -1, 0, 0, 15, 7491, 7493), - (7493, -1, -1, 724, 724, 12, 85, -1, 0, 0, 15, 7492, 16890), - (7494, -1, -1, 729, 729, 7, 81, -1, 0, 0, 15, 5740, 7495), - (7495, -1, -1, 729, 729, 8, 82, -1, 0, 0, 15, 7494, 7496), - (7496, -1, -1, 729, 729, 9, 83, -1, 0, 0, 15, 7495, 10305), - (7497, 6380, 6380, 6380, 6380, 6, 83, 13815, 39, 120, 15, 6382, 7498), - (7498, 6380, 6380, 6380, 6380, 6, 84, 13816, 39, 120, 15, 7497, 7499), - (7499, 6380, 6380, 6380, 6380, 6, 85, 13817, 39, 120, 15, 7498, 10308), - (7500, -1, -1, 4699, 4699, 5, 61, -1, 0, 0, 15, 6540, 10788), - (7501, -1, -1, 125, 125, 6, 81, -1, 0, 0, 15, 5523, 7502), - (7502, -1, -1, 125, 125, 7, 82, -1, 0, 0, 15, 7501, 7503), - (7503, -1, -1, 125, 125, 8, 83, -1, 0, 0, 15, 7502, 7504), - (7504, -1, -1, 125, 125, 9, 84, -1, 0, 0, 15, 7503, 7505), - (7505, -1, -1, 125, 125, 10, 85, -1, 0, 0, 15, 7504, 12396), - (7506, -1, -1, 122, 122, 6, 81, -1, 0, 0, 15, 5528, 7507), - (7507, -1, -1, 122, 122, 7, 82, -1, 0, 0, 15, 7506, 7508), - (7508, -1, -1, 122, 122, 8, 83, -1, 0, 0, 15, 7507, 7509), - (7509, -1, -1, 122, 122, 9, 84, -1, 0, 0, 15, 7508, 7510), - (7510, -1, -1, 122, 122, 10, 85, -1, 0, 0, 15, 7509, 12401), - (7511, -1, -1, 1026, 1026, 5, 81, -1, 0, 0, 15, 6527, 7512), - (7512, -1, -1, 1026, 1026, 5, 82, -1, 0, 0, 15, 7511, 7513), - (7513, -1, -1, 1026, 1026, 5, 83, -1, 0, 0, 15, 7512, 7514), - (7514, -1, -1, 1026, 1026, 5, 84, -1, 0, 0, 15, 7513, 7515), - (7515, -1, -1, 1026, 1026, 5, 85, -1, 0, 0, 15, 7514, 7886), - (7516, -1, -1, 1006, 1006, 5, 71, -1, 0, 0, 15, 1010, 7517), - (7517, -1, -1, 1006, 1006, 5, 72, -1, 0, 0, 15, 7516, 7518), - (7518, -1, -1, 1006, 1006, 5, 73, -1, 0, 0, 15, 7517, 7519), - (7519, -1, -1, 1006, 1006, 5, 74, -1, 0, 0, 15, 7518, 7520), - (7520, -1, -1, 1006, 1006, 5, 75, -1, 0, 0, 15, 7519, 7837), - (7521, -1, -1, 1056, 1056, 5, 81, -1, 0, 0, 15, 6435, 7522), - (7522, -1, -1, 1056, 1056, 5, 82, -1, 0, 0, 15, 7521, 7523), - (7523, -1, -1, 1056, 1056, 5, 83, -1, 0, 0, 15, 7522, 7524), - (7524, -1, -1, 1056, 1056, 5, 84, -1, 0, 0, 15, 7523, 7525), - (7525, -1, -1, 1056, 1056, 5, 85, -1, 0, 0, 15, 7524, 16414), - (7526, -1, -1, 6119, 6119, 6, 81, -1, 0, 0, 15, 6123, 7527), - (7527, -1, -1, 6119, 6119, 6, 82, -1, 0, 0, 15, 7526, 7528), - (7528, -1, -1, 6119, 6119, 6, 83, -1, 0, 0, 15, 7527, 7529), - (7529, -1, -1, 6119, 6119, 6, 84, -1, 0, 0, 15, 7528, 7530), - (7530, -1, -1, 6119, 6119, 6, 85, -1, 0, 0, 15, 7529, 12406), - (7534, -1, -1, 65, 661, 3, 81, -1, 0, 0, 15, 6394, 7535), - (7535, -1, -1, 65, 661, 3, 82, -1, 0, 0, 15, 7534, 7536), - (7536, -1, -1, 65, 661, 3, 83, -1, 0, 0, 15, 7535, 7537), - (7537, -1, -1, 65, 661, 3, 84, -1, 0, 0, 15, 7536, 7538), - (7538, -1, -1, 65, 661, 3, 85, -1, 0, 0, 15, 7537, 7904), - (7539, -1, -1, 1021, 1021, 5, 80, -1, 0, 0, 16, 6522, 7540), - (7540, -1, -1, 1021, 1021, 5, 85, -1, 0, 0, 16, 7539, 7683), - (7541, -1, -1, 107, 107, 2, 60, -1, 0, 0, 15, 109, 7542), - (7542, -1, -1, 107, 107, 4, 60, -1, 0, 0, 15, 7541, 7543), - (7543, -1, -1, 107, 107, 6, 60, -1, 0, 0, 15, 7542, -1), - (7544, -1, -1, 678, 678, 3, 70, -1, 0, 0, 15, 6520, 7545), - (7545, -1, -1, 678, 678, 3, 70, -1, 0, 0, 15, 7544, 7546), - (7546, -1, -1, 678, 678, 3, 70, -1, 0, 0, 15, 7545, -1), - (7547, -1, -1, 418, 418, 5, 76, -1, 0, 0, 15, 4682, 7548), - (7548, -1, -1, 418, 418, 5, 77, -1, 0, 0, 15, 7547, 7549), - (7549, -1, -1, 418, 418, 5, 78, -1, 0, 0, 15, 7548, 7550), - (7550, -1, -1, 418, 418, 5, 79, -1, 0, 0, 15, 7549, 7551), - (7551, -1, -1, 418, 418, 5, 80, -1, 0, 0, 15, 7550, -1), - (7553, -1, -1, 1071, 1071, 6, 80, -1, 0, 0, 16, 4764, 7681), - (7554, -1, -1, 1486, 1486, 7, 81, -1, 0, 0, 15, 5533, 7555), - (7555, -1, -1, 1486, 1486, 8, 82, -1, 0, 0, 15, 7554, 7556), - (7556, -1, -1, 1486, 1486, 9, 83, -1, 0, 0, 15, 7555, 7557), - (7557, -1, -1, 1486, 1486, 10, 84, -1, 0, 0, 15, 7556, 7558), - (7558, -1, -1, 1486, 1486, 12, 85, -1, 0, 0, 15, 7557, 7722), - (7559, -1, -1, 599, 599, 9, 83, -1, 0, 0, 15, 5536, 7560), - (7560, -1, -1, 599, 599, 10, 84, -1, 0, 0, 15, 7559, 7561), - (7561, -1, -1, 599, 599, 12, 85, -1, 0, 0, 15, 7560, 13026), - (7562, -1, -1, 1041, 1041, 7, 81, -1, 0, 0, 15, 5544, 7563), - (7563, -1, -1, 1041, 1041, 9, 83, -1, 0, 0, 15, 7562, 7564), - (7564, -1, -1, 1041, 1041, 12, 85, -1, 0, 0, 15, 7563, 12697), - (7565, -1, -1, 119, 119, 7, 81, -1, 0, 0, 15, 5556, 7566), - (7566, -1, -1, 119, 119, 9, 83, -1, 0, 0, 15, 7565, 7567), - (7567, -1, -1, 119, 119, 12, 85, -1, 0, 0, 15, 7566, 6023), - (7568, -1, -1, 1592, 1592, 7, 81, -1, 0, 0, 15, 5561, 7569), - (7569, -1, -1, 1592, 1592, 8, 82, -1, 0, 0, 15, 7568, 7570), - (7570, -1, -1, 1592, 1592, 9, 83, -1, 0, 0, 15, 7569, 7571), - (7571, -1, -1, 1592, 1592, 10, 84, -1, 0, 0, 15, 7570, 7572), - (7572, -1, -1, 1592, 1592, 12, 85, -1, 0, 0, 15, 7571, 12439), - (7573, -1, -1, 4739, 4739, 7, 81, -1, 0, 0, 15, 5564, 7574), - (7574, -1, -1, 4739, 4739, 9, 83, -1, 0, 0, 15, 7573, 7575), - (7575, -1, -1, 4739, 4739, 12, 85, -1, 0, 0, 15, 7574, -1), - (7576, -1, -1, 1072, 1072, 7, 81, -1, 0, 0, 15, 5570, 7577), - (7577, -1, -1, 1072, 1072, 8, 82, -1, 0, 0, 15, 7576, 7578), - (7578, -1, -1, 1072, 1072, 9, 83, -1, 0, 0, 15, 7577, 7579), - (7579, -1, -1, 1072, 1072, 10, 84, -1, 0, 0, 15, 7578, 7580), - (7580, -1, -1, 1072, 1072, 12, 85, -1, 0, 0, 15, 7579, 12444), - (7581, -1, -1, 1210, 1213, 7, 81, -1, 0, 0, 15, 5579, 7582), - (7582, -1, -1, 1210, 1213, 9, 83, -1, 0, 0, 15, 7581, 7583), - (7583, -1, -1, 1210, 1213, 12, 85, -1, 0, 0, 15, 7582, 8344), - (7584, -1, -1, 98, 98, 7, 81, -1, 0, 0, 15, 5588, 7585), - (7585, -1, -1, 98, 98, 9, 83, -1, 0, 0, 15, 7584, 7586), - (7586, -1, -1, 98, 98, 12, 85, -1, 0, 0, 15, 7585, 11061), - (7587, -1, -1, 1186, 1186, 7, 81, -1, 0, 0, 15, 5591, 7588), - (7588, -1, -1, 1186, 1186, 9, 83, -1, 0, 0, 15, 7587, 7589), - (7589, -1, -1, 1186, 1186, 12, 85, -1, 0, 0, 15, 7588, 7692), - (7590, -1, -1, 80, 80, 7, 81, -1, 0, 0, 15, 5594, 7591), - (7591, -1, -1, 80, 80, 9, 83, -1, 0, 0, 15, 7590, 7592), - (7592, -1, -1, 80, 80, 12, 85, -1, 0, 0, 15, 7591, 12452), - (7593, -1, -1, 658, 658, 5, 81, -1, 0, 0, 15, 5627, 7594), - (7594, -1, -1, 658, 658, 5, 82, -1, 0, 0, 15, 7593, 7595), - (7595, -1, -1, 658, 658, 5, 83, -1, 0, 0, 15, 7594, 7596), - (7596, -1, -1, 658, 658, 5, 84, -1, 0, 0, 15, 7595, 7597), - (7597, -1, -1, 658, 658, 5, 85, -1, 0, 0, 15, 7596, 12455), - (7598, -1, -1, 98, 738, 7, 81, -1, 0, 0, 15, 5630, 7599), - (7599, -1, -1, 98, 738, 9, 83, -1, 0, 0, 15, 7598, 7600), - (7600, -1, -1, 98, 738, 12, 85, -1, 0, 0, 15, 7599, 13924), - (7601, -1, -1, 6051, 6051, 3, 81, -1, 0, 0, 15, 6053, 7602), - (7602, -1, -1, 6051, 6051, 3, 83, -1, 0, 0, 15, 7601, 7603), - (7603, -1, -1, 6051, 6051, 3, 85, -1, 0, 0, 15, 7602, 10604), - (7604, -1, -1, 683, 683, 5, 80, -1, 0, 0, 15, 6081, 7605), - (7605, -1, -1, 683, 683, 5, 80, -1, 0, 0, 15, 7604, 12694), - (7606, 6537, 6537, 6537, 6537, 7, 81, 13821, 30, 900, 15, 6208, 7607), - (7607, 6537, 6537, 6537, 6537, 8, 82, 13822, 30, 900, 15, 7606, 7608), - (7608, 6537, 6537, 6537, 6537, 9, 83, 13823, 30, 900, 15, 7607, 12460), - (7609, 6539, 6539, 6539, 6539, 6, 76, 13824, 18, 1800, 15, 6214, 7610), - (7610, 6539, 6539, 6539, 6539, 6, 79, 13825, 18, 1800, 15, 7609, 7611), - (7611, 6539, 6539, 6539, 6539, 6, 82, 13826, 18, 1800, 15, 7610, 12942), - (7612, -1, -1, 270, 665, 2, 66, -1, 0, 0, 15, 670, 7613), - (7613, -1, -1, 270, 665, 2, 67, -1, 0, 0, 15, 7612, 7614), - (7614, -1, -1, 270, 665, 2, 68, -1, 0, 0, 15, 7613, -1), - (7615, -1, -1, 6346, 6346, 6, 79, -1, 0, 0, 15, 6348, 7616), - (7616, -1, -1, 6346, 6346, 6, 81, -1, 0, 0, 15, 7615, 7617), - (7617, -1, -1, 6346, 6346, 6, 83, -1, 0, 0, 15, 7616, 15397), - (7618, -1, -1, 6349, 6349, 6, 79, -1, 0, 0, 15, 6351, 7619), - (7619, -1, -1, 6349, 6349, 6, 81, -1, 0, 0, 15, 7618, 7620), - (7620, -1, -1, 6349, 6349, 6, 83, -1, 0, 0, 15, 7619, 11053), - (7621, -1, -1, 1435, 4773, 9, 81, -1, 0, 0, 15, 6517, 13090), - (7622, -1, -1, 446, 735, 8, 81, -1, 0, 0, 15, 7065, 7623), - (7623, -1, -1, 446, 735, 8, 82, -1, 0, 0, 15, 7622, 7624), - (7624, -1, -1, 446, 735, 8, 83, -1, 0, 0, 15, 7623, 10473), - (7625, -1, -1, 735, 735, 8, 81, -1, 0, 0, 15, 7068, 7626), - (7626, -1, -1, 735, 735, 8, 82, -1, 0, 0, 15, 7625, 7627), - (7627, -1, -1, 735, 735, 8, 83, -1, 0, 0, 15, 7626, 10632), - (7628, -1, -1, 807, 807, 5, 81, -1, 0, 0, 15, 5924, 7629), - (7629, -1, -1, 807, 807, 5, 83, -1, 0, 0, 15, 7628, 7630), - (7630, -1, -1, 807, 807, 5, 85, -1, 0, 0, 15, 7629, 12685), - (7631, -1, -1, 255, 255, 7, 81, -1, 0, 0, 15, 5597, 7632), - (7632, -1, -1, 255, 255, 9, 83, -1, 0, 0, 15, 7631, 7633), - (7633, -1, -1, 255, 255, 12, 85, -1, 0, 0, 15, 7632, 17441), - (7634, -1, -1, 815, 815, 9, 83, -1, 0, 0, 15, 5913, 7635), - (7635, -1, -1, 815, 815, 10, 84, -1, 0, 0, 15, 7634, 7636), - (7636, -1, -1, 815, 815, 12, 85, -1, 0, 0, 15, 7635, 15441), - (7637, -1, -1, 1616, 1616, 5, 83, -1, 0, 0, 15, 6007, 7638), - (7638, -1, -1, 1616, 1616, 5, 84, -1, 0, 0, 15, 7637, 7639), - (7639, -1, -1, 1616, 1616, 5, 85, -1, 0, 0, 15, 7638, -1), - (7640, -1, -1, 686, 686, 5, 60, -1, 0, 0, 15, 690, 12438), - (7641, -1, -1, 625, 625, 3, 76, -1, 0, 0, 15, 4735, 7642), - (7642, -1, -1, 625, 625, 3, 78, -1, 0, 0, 15, 7641, 7643), - (7643, -1, -1, 625, 625, 3, 80, -1, 0, 0, 15, 7642, -1), - (7644, -1, -1, 6375, 6375, 6, 81, -1, 0, 0, 15, 6377, 7645), - (7645, -1, -1, 6375, 6375, 6, 82, -1, 0, 0, 15, 7644, 7646), - (7646, -1, -1, 6375, 6375, 6, 83, -1, 0, 0, 15, 7645, 7663), - (7647, -1, -1, 692, 692, 6, 60, -1, 0, 0, 15, 694, 7648), - (7648, -1, -1, 692, 692, 6, 60, -1, 0, 0, 15, 7647, 7649), - (7649, -1, -1, 692, 692, 6, 60, -1, 0, 0, 15, 7648, 7670), - (7650, -1, -1, 1044, 1044, 7, 81, -1, 0, 0, 15, 5547, 7651), - (7651, -1, -1, 1044, 1044, 9, 83, -1, 0, 0, 15, 7650, 7652), - (7652, -1, -1, 1044, 1044, 12, 85, -1, 0, 0, 15, 7651, 13074), - (7653, -1, -1, 1047, 1047, 7, 81, -1, 0, 0, 15, 5550, 7654), - (7654, -1, -1, 1047, 1047, 9, 83, -1, 0, 0, 15, 7653, 7655), - (7655, -1, -1, 1047, 1047, 12, 85, -1, 0, 0, 15, 7654, 13077), - (7656, -1, -1, 1050, 1050, 7, 81, -1, 0, 0, 15, 5553, 7657), - (7657, -1, -1, 1050, 1050, 9, 83, -1, 0, 0, 15, 7656, 7658), - (7658, -1, -1, 1050, 1050, 12, 85, -1, 0, 0, 15, 7657, 13023), - (7659, -1, -1, 754, 754, 3, 70, -1, 0, 0, 15, 756, 7660), - (7660, -1, -1, 754, 754, 6, 70, -1, 0, 0, 15, 7659, 7661), - (7661, -1, -1, 754, 754, 9, 70, -1, 0, 0, 15, 7660, -1), - (7662, 188, 188, 188, 188, 9, 83, 16431, 2, 30, 15, 7339, 10647), - (7663, -1, -1, 6375, 6375, 6, 83, -1, 0, 0, 15, 7646, 10084), - (7664, -1, -1, 7664, 7664, 2, 73, -1, 0, 0, 15, -1, 7665), - (7665, -1, -1, 7664, 7664, 2, 74, -1, 0, 0, 15, 7664, 7666), - (7666, -1, -1, 7664, 7664, 2, 75, -1, 0, 0, 15, 7665, 7667), - (7667, -1, -1, 7664, 7664, 2, 76, -1, 0, 0, 15, 7666, 7668), - (7668, -1, -1, 7664, 7664, 2, 77, -1, 0, 0, 15, 7667, 10105), - (7669, 7669, 7669, 7669, 7669, 3, 81, 13838, 35, 5, 15, -1, -1), - (7670, -1, -1, 692, 692, 7, 75, -1, 0, 0, 16, 7649, 7671), - (7671, -1, -1, 692, 692, 9, 80, -1, 0, 0, 16, 7670, 7672), - (7672, -1, -1, 692, 692, 12, 85, -1, 0, 0, 16, 7671, 12767), - (7673, -1, -1, 855, 855, 5, 75, -1, 0, 0, 16, 859, 7674), - (7674, -1, -1, 855, 855, 5, 75, -1, 0, 0, 16, 7673, 7675), - (7675, -1, -1, 855, 855, 5, 75, -1, 0, 0, 16, 7674, 7676), - (7676, -1, -1, 855, 855, 5, 75, -1, 0, 0, 16, 7675, 7677), - (7677, -1, -1, 855, 855, 5, 75, -1, 0, 0, 16, 7676, 10688), - (7678, -1, -1, 852, 852, 9, 81, -1, 0, 0, 16, 5502, 7679), - (7679, -1, -1, 852, 852, 10, 83, -1, 0, 0, 16, 7678, 7680), - (7680, -1, -1, 852, 852, 12, 85, -1, 0, 0, 16, 7679, 12576), - (7681, -1, -1, 1071, 1071, 6, 80, -1, 0, 0, 16, 7553, -1), - (7682, -1, -1, 4861, 4861, 12, 85, -1, 0, 0, 16, 7216, 12757), - (7683, -1, -1, 1021, 1021, 5, 85, -1, 0, 0, 16, 7540, 7684), - (7684, -1, -1, 1021, 1021, 5, 85, -1, 0, 0, 16, 7683, 7685), - (7685, -1, -1, 1021, 1021, 5, 85, -1, 0, 0, 16, 7684, 13894), - (7686, -1, -1, 4844, 4844, 5, 81, -1, 0, 0, 16, 7126, 7687), - (7687, -1, -1, 4844, 4844, 5, 83, -1, 0, 0, 16, 7686, 7688), - (7688, -1, -1, 4844, 4844, 5, 85, -1, 0, 0, 16, 7687, -1), - (7689, 7689, 7689, 7689, 7689, 12, 85, 21820, 94, 180, 16, -1, -1), - (7690, -1, -1, 7690, 7690, 12, 85, -1, 0, 0, 16, -1, -1), - (7691, 146, 146, 146, 146, 8, 85, 16862, 2, 180, 16, 7466, 13256), - (7692, -1, -1, 1186, 1186, 12, 85, -1, 0, 0, 16, 7589, 7693), - (7693, -1, -1, 1186, 1186, 12, 85, -1, 0, 0, 16, 7692, 7694), - (7694, -1, -1, 1186, 1186, 12, 85, -1, 0, 0, 16, 7693, 12564), - (7695, -1, -1, 7695, 7695, 6, 85, -1, 0, 0, 16, -1, 7696), - (7696, -1, -1, 7695, 7695, 6, 85, -1, 0, 0, 16, 7695, 7697), - (7697, -1, -1, 7695, 7695, 6, 85, -1, 0, 0, 16, 7696, -1), - (7698, 7698, 7698, 7698, 7698, 6, 85, 21763, 17, 6, 16, -1, -1), - (7699, -1, -1, 7699, 7699, 12, 85, 0, 0, 0, 16, -1, -1), - (7700, -1, -1, 255, 255, 7, 81, -1, 0, 0, 16, -1, 7701), - (7701, -1, -1, 255, 255, 9, 83, -1, 0, 0, 16, 7700, 7702), - (7702, -1, -1, 255, 255, 12, 85, -1, 0, 0, 16, 7701, 12610), - (7703, 7703, 7703, 7703, 7703, 12, 85, 21754, 16, 600, 16, -1, -1), - (7704, -1, -1, 8195, 8195, 5, 81, -1, 0, 0, 16, 8197, 7705), - (7705, -1, -1, 8195, 8195, 5, 83, -1, 0, 0, 16, 7704, 7706), - (7706, -1, -1, 8195, 8195, 5, 85, -1, 0, 0, 16, 7705, -1), - (7707, -1, -1, 589, 589, 7, 85, -1, 0, 0, 16, 7392, 7708), - (7708, -1, -1, 589, 589, 7, 85, -1, 0, 0, 16, 7707, 7709), - (7709, -1, -1, 589, 589, 7, 85, -1, 0, 0, 16, 7708, 13104), - (7710, 5984, 5984, 5984, 5984, 12, 85, 21679, 2, 30, 16, 7335, 7711), - (7711, 5984, 5984, 5984, 5984, 12, 85, 21680, 2, 30, 16, 7710, 10626), - (7712, 7712, 7712, 7712, 7712, 12, 85, 21682, 2, 30, 16, -1, 10646), - (7713, -1, -1, 634, 634, 12, 81, -1, 0, 0, 16, 5613, 7714), - (7714, -1, -1, 634, 634, 12, 83, -1, 0, 0, 16, 7713, 10778), - (7715, -1, -1, 7715, 7715, 5, 77, 0, 0, 0, 16, -1, 7716), - (7716, -1, -1, 7715, 7715, 5, 79, 0, 0, 0, 16, 7715, 7717), - (7717, -1, -1, 7715, 7715, 5, 81, 0, 0, 0, 16, 7716, 14314), - (7718, -1, -1, 574, 574, 3, 81, -1, 0, 0, 16, 576, -1), - (7722, -1, -1, 1486, 1486, 7, 86, -1, 0, 0, 17, 7558, 7723), - (7723, -1, -1, 1486, 1486, 8, 87, -1, 0, 0, 17, 7722, 7724), - (7724, -1, -1, 1486, 1486, 9, 88, -1, 0, 0, 17, 7723, 7725), - (7725, -1, -1, 1486, 1486, 10, 89, -1, 0, 0, 17, 7724, 7726), - (7726, -1, -1, 1486, 1486, 12, 90, -1, 0, 0, 17, 7725, 7842), - (7732, 7732, 7732, 7732, 7732, 0, 60, 7732, 34, 3600, 14, -1, -1), - (7733, -1, -1, 288, 288, 6, 65, -1, 0, 0, 14, -1, -1), - (7734, 7734, 7734, 7734, 7734, 0, 61, 7734, 34, 28800, 14, -1, -1), - (7735, 7735, 7735, 7735, 7735, 0, 51, 7731, 32, 3600, 9, -1, -1), - (7736, 7736, 7736, 7736, 7736, 0, 52, 7865, 32, 10800, 9, -1, -1), - (7737, 7737, 7737, 7737, 7737, 0, 53, 7733, 32, 10800, 9, -1, -1), - (7738, 7738, 7738, 7738, 7738, 0, 54, 7990, 32, 21600, 9, -1, -1), - (7739, 7739, 7739, 7739, 7739, 0, 65, 13064, 36, 3600, 0, -1, -1), - (7740, 7740, 7740, 7740, 7740, 0, 66, 13065, 36, 28800, 0, -1, -1), - (7741, 7741, 7741, 7741, 7741, 0, 70, 21854, 50, 3600, 0, -1, -1), - (7742, 7742, 7742, 7742, 7742, 0, 71, 21855, 50, 28800, 0, -1, -1), - (7743, -1, -1, 7743, 7743, 5, 61, -1, 0, 0, 16, -1, 7744), - (7744, -1, -1, 7743, 7743, 7, 61, -1, 0, 0, 16, 7743, 7745), - (7745, -1, -1, 7743, 7743, 9, 61, -1, 0, 0, 16, 7744, 10717), - (7746, -1, -1, 7746, 7746, 5, 85, -1, 0, 0, 16, -1, 7763), - (7747, 7747, 7747, 7747, 7747, 9, 85, 21790, 32, 180, 16, -1, -1), - (7748, -1, -1, 7748, 7748, 3, 81, -1, 0, 0, 16, -1, 7749), - (7749, -1, -1, 7748, 7748, 6, 83, -1, 0, 0, 16, 7748, 7750), - (7750, -1, -1, 7748, 7748, 9, 85, -1, 0, 0, 16, 7749, -1), - (7751, -1, -1, 7751, 7751, 5, 85, -1, 0, 0, 16, -1, 7752), - (7752, -1, -1, 7751, 7751, 5, 85, -1, 0, 0, 16, 7751, 7753), - (7753, -1, -1, 7751, 7751, 5, 85, -1, 0, 0, 16, 7752, 14132), - (7754, 7754, 7754, 7754, 7754, 9, 85, 21803, 0, 1, 16, -1, -1), - (7755, 7755, 7755, 7755, 7755, 9, 81, 21804, 53, 900, 16, -1, 15782), - (7756, 7756, 7756, 7756, 7756, 12, 85, 21805, 54, 120, 16, -1, -1), - (7757, -1, -1, 7757, 7757, 5, 85, -1, 0, 0, 16, -1, 7758), - (7758, -1, -1, 7757, 7757, 7, 85, -1, 0, 0, 16, 7757, 7759), - (7759, -1, -1, 7757, 7757, 9, 85, -1, 0, 0, 16, 7758, 12587), - (7760, -1, -1, 7760, 7760, 5, 85, -1, 0, 0, 16, -1, 7761), - (7761, -1, -1, 7760, 7760, 7, 85, -1, 0, 0, 16, 7760, 7762), - (7762, -1, -1, 7760, 7760, 9, 85, -1, 0, 0, 16, 7761, -1), - (7763, -1, -1, 7746, 7746, 5, 85, -1, 0, 0, 16, 7746, 7764), - (7764, -1, -1, 7746, 7746, 5, 85, -1, 0, 0, 16, 7763, -1), - (7765, -1, -1, 7765, 7765, 5, 86, 0, 0, 0, 17, -1, 7766), - (7766, -1, -1, 7765, 7765, 7, 87, 0, 0, 0, 17, 7765, 7767), - (7767, -1, -1, 7765, 7765, 9, 88, 0, 0, 0, 17, 7766, 7768), - (7768, -1, -1, 7765, 7765, 12, 89, 0, 0, 0, 17, 7767, 7769), - (7770, 131, 131, 131, 131, 9, 86, 27655, 4, 900, 17, 10018, 7771), - (7771, 131, 131, 131, 131, 12, 88, 27656, 4, 900, 17, 7770, 7772), - (7772, 131, 131, 131, 131, 15, 90, 27657, 4, 900, 17, 7771, 13374), - (7773, 7951, 7951, 7951, 7951, 9, 86, 27658, 61, 900, 17, 10040, 7774), - (7774, 7951, 7951, 7951, 7951, 9, 88, 27659, 61, 900, 17, 7773, 7775), - (7775, 7951, 7951, 7951, 7951, 9, 90, 27660, 61, 900, 17, 7774, 13377), - (7800, 7800, 7800, 7800, 7800, 0, 1, 13531, 39, 4320, 0, -1, 7801), - (7801, 7800, 7800, 7800, 7800, 0, 6, 13532, 39, 4320, 0, 7800, 7802), - (7802, 7800, 7800, 7800, 7800, 0, 11, 13533, 39, 4320, 0, 7801, 7803), - (7803, 7800, 7800, 7800, 7800, 0, 16, 13534, 39, 4320, 0, 7802, 7804), - (7804, 7800, 7800, 7800, 7800, 0, 21, 13535, 39, 4320, 0, 7803, 7805), - (7805, 7800, 7800, 7800, 7800, 0, 26, 13536, 39, 4320, 0, 7804, 7806), - (7806, 7800, 7800, 7800, 7800, 0, 31, 13537, 39, 4320, 0, 7805, 7807), - (7807, 7800, 7800, 7800, 7800, 0, 36, 13538, 39, 4320, 0, 7806, 7808), - (7808, 7800, 7800, 7800, 7800, 0, 41, 13539, 39, 4320, 0, 7807, 7809), - (7809, 7800, 7800, 7800, 7800, 0, 46, 13540, 39, 4320, 0, 7808, 7810), - (7810, 7800, 7800, 7800, 7800, 3, 51, 13541, 39, 4320, 0, 7809, 7811), - (7811, 7800, 7800, 7800, 7800, 4, 56, 13542, 39, 4320, 0, 7810, 7812), - (7812, 7800, 7800, 7800, 7800, 5, 61, 13543, 39, 4320, 0, 7811, 7813), - (7813, 7800, 7800, 7800, 7800, 6, 66, 13544, 39, 4320, 0, 7812, 7814), - (7814, 7800, 7800, 7800, 7800, 7, 71, 13545, 39, 4320, 0, 7813, 7815), - (7815, 7800, 7800, 7800, 7800, 8, 76, 13562, 39, 4320, 0, 7814, 7816), - (7816, 7800, 7800, 7800, 7800, 8, 81, 16062, 39, 4320, 0, 7815, 7817), - (7817, 7800, 7800, 7800, 7800, 9, 83, 16855, 39, 4320, 0, 7816, 10786), - (7818, -1, -1, 7818, 7818, 12, 85, 21750, 0, 0, 16, -1, 13029), - (7819, -1, -1, 9512, 9512, 7, 85, -1, 0, 0, 16, 9514, 7820), - (7820, -1, -1, 9512, 9512, 7, 85, -1, 0, 0, 16, 7819, 7821), - (7821, -1, -1, 9512, 9512, 7, 85, -1, 0, 0, 16, 7820, 7881), - (7822, -1, -1, 7822, 7822, 5, 77, 0, 0, 0, 16, -1, 7823), - (7823, -1, -1, 7822, 7822, 5, 79, 0, 0, 0, 16, 7822, 7824), - (7824, -1, -1, 7822, 7822, 5, 81, 0, 0, 0, 16, 7823, 7825), - (7825, -1, -1, 7822, 7822, 5, 83, 0, 0, 0, 16, 7824, 7826), - (7826, -1, -1, 7822, 7822, 5, 85, 0, 0, 0, 16, 7825, 14328), - (7827, -1, -1, 7827, 7827, 5, 81, 0, 0, 0, 16, -1, -1), - (7828, -1, -1, 7828, 7828, 5, 79, 0, 0, 0, 16, -1, 7829), - (7829, -1, -1, 7828, 7828, 5, 81, 0, 0, 0, 16, 7828, 7830), - (7830, -1, -1, 7828, 7828, 5, 83, 0, 0, 0, 16, 7829, -1), - (7832, -1, -1, 7832, 7832, 5, 85, 0, 0, 0, 16, -1, 7833), - (7833, -1, -1, 7832, 7832, 5, 85, 0, 0, 0, 16, 7832, 7834), - (7834, -1, -1, 7832, 7832, 5, 85, 0, 0, 0, 16, 7833, 7835), - (7835, -1, -1, 7832, 7832, 5, 85, 0, 0, 0, 16, 7834, 7836), - (7836, -1, -1, 7832, 7832, 5, 85, 0, 0, 0, 16, 7835, -1), - (7837, -1, -1, 1006, 1006, 5, 76, -1, 0, 0, 17, 7520, 7838), - (7838, -1, -1, 1006, 1006, 5, 77, -1, 0, 0, 17, 7837, 7839), - (7839, -1, -1, 1006, 1006, 5, 78, -1, 0, 0, 17, 7838, 7840), - (7840, -1, -1, 1006, 1006, 5, 79, -1, 0, 0, 17, 7839, 7841), - (7841, -1, -1, 1006, 1006, 5, 80, -1, 0, 0, 17, 7840, 8470), - (7842, -1, -1, 1486, 1486, 12, 91, -1, 0, 0, 18, 7726, 7843), - (7843, -1, -1, 1486, 1486, 12, 92, -1, 0, 0, 18, 7842, 7844), - (7844, -1, -1, 1486, 1486, 12, 93, -1, 0, 0, 18, 7843, 7845), - (7850, 7850, 7850, 7850, 7850, 0, 1, 13546, 39, 4320, 0, -1, 7851), - (7851, 7850, 7850, 7850, 7850, 0, 6, 13547, 39, 4320, 0, 7850, 7852), - (7852, 7850, 7850, 7850, 7850, 0, 11, 13548, 39, 4320, 0, 7851, 7853), - (7853, 7850, 7850, 7850, 7850, 0, 16, 13549, 39, 4320, 0, 7852, 7854), - (7854, 7850, 7850, 7850, 7850, 0, 21, 13550, 39, 4320, 0, 7853, 7855), - (7855, 7850, 7850, 7850, 7850, 0, 26, 13551, 39, 4320, 0, 7854, 7856), - (7856, 7850, 7850, 7850, 7850, 0, 31, 13552, 39, 4320, 0, 7855, 7857), - (7857, 7850, 7850, 7850, 7850, 0, 36, 13553, 39, 4320, 0, 7856, 7858), - (7858, 7850, 7850, 7850, 7850, 0, 41, 13554, 39, 4320, 0, 7857, 7859), - (7859, 7850, 7850, 7850, 7850, 0, 46, 13555, 39, 4320, 0, 7858, 7860), - (7860, 7850, 7850, 7850, 7850, 3, 51, 13556, 39, 4320, 0, 7859, 7861), - (7861, 7850, 7850, 7850, 7850, 4, 56, 13557, 39, 4320, 0, 7860, 7862), - (7862, 7850, 7850, 7850, 7850, 5, 61, 13558, 39, 4320, 0, 7861, 7863), - (7863, 7850, 7850, 7850, 7850, 6, 66, 13559, 39, 4320, 0, 7862, 7864), - (7864, 7850, 7850, 7850, 7850, 7, 71, 13560, 39, 4320, 0, 7863, 7865), - (7865, 7850, 7850, 7850, 7850, 8, 76, 13561, 39, 4320, 0, 7864, 7340), - (7869, 7869, 7869, 7869, 7869, 6, 73, 16175, 60, 30, 15, -1, 7870), - (7870, 7869, 7869, 7869, 7869, 6, 77, 16176, 60, 30, 15, 7869, 7871), - (7871, 7869, 7869, 7869, 7869, 6, 81, 16177, 60, 30, 15, 7870, -1), - (7872, 7872, 7872, 7872, 7872, 6, 76, 16178, 41, 600, 15, -1, 7873), - (7873, 7872, 7872, 7872, 7872, 6, 81, 16179, 41, 600, 15, 7872, 7874), - (7874, 7872, 7872, 7872, 7872, 6, 85, 16180, 41, 600, 15, 7873, 10127), - (7875, 7875, 7875, 7875, 7875, 6, 76, 16181, 42, 600, 15, -1, 7876), - (7876, 7875, 7875, 7875, 7875, 6, 81, 16182, 42, 600, 15, 7875, 7877), - (7877, 7875, 7875, 7875, 7875, 6, 85, 16183, 42, 600, 15, 7876, 7878), - (7878, 7875, 7875, 7875, 7875, 6, 85, 16859, 42, 600, 16, 7877, 7879), - (7879, 7875, 7875, 7875, 7875, 6, 85, 21823, 42, 600, 16, 7878, 7880), - (7880, 7875, 7875, 7875, 7875, 6, 85, 21824, 42, 600, 16, 7879, 13816), - (7881, -1, -1, 9512, 9512, 7, 85, -1, 0, 0, 16, 7821, 7882), - (7882, -1, -1, 9512, 9512, 7, 85, -1, 0, 0, 16, 7881, 7883), - (7883, -1, -1, 9512, 9512, 7, 85, -1, 0, 0, 16, 7882, 13187), - (7884, -1, -1, 7884, 7884, 9, 85, -1, 0, 0, 16, -1, 12689), - (7885, -1, -1, 7885, 7885, 9, 85, -1, 0, 0, 16, -1, 12690), - (7886, -1, -1, 1026, 1026, 5, 85, -1, 0, 0, 17, 7515, 7887), - (7887, -1, -1, 1026, 1026, 5, 86, -1, 0, 0, 17, 7886, 7888), - (7888, -1, -1, 1026, 1026, 5, 87, -1, 0, 0, 17, 7887, 7889), - (7889, -1, -1, 1026, 1026, 5, 88, -1, 0, 0, 17, 7888, 7890), - (7890, -1, -1, 1026, 1026, 5, 89, -1, 0, 0, 17, 7889, 8430), - (7900, -1, -1, 7900, 7900, 4, 60, -1, 0, 0, 15, -1, 7901), - (7901, -1, -1, 7900, 7900, 4, 65, -1, 0, 0, 15, 7900, 7902), - (7902, -1, -1, 7900, 7900, 4, 70, -1, 0, 0, 15, 7901, 10268), - (7903, 7903, 7903, 7903, 7903, 6, 75, 16188, 60, 30, 15, -1, 12976), - (7904, -1, -1, 65, 661, 3, 85, -1, 0, 0, 17, 7538, 7905), - (7905, -1, -1, 65, 661, 3, 86, -1, 0, 0, 17, 7904, 7906), - (7906, -1, -1, 65, 661, 3, 87, -1, 0, 0, 17, 7905, 7907), - (7907, -1, -1, 65, 661, 3, 88, -1, 0, 0, 17, 7906, 7908), - (7908, -1, -1, 65, 661, 3, 89, -1, 0, 0, 17, 7907, 8435), - (7940, -1, -1, 7940, 7940, 6, 60, -1, 0, 0, 15, -1, 7941), - (7941, -1, -1, 7940, 7940, 6, 65, -1, 0, 0, 15, 7940, 7942), - (7942, -1, -1, 7940, 7940, 6, 70, -1, 0, 0, 15, 7941, 10030), - (7943, 7943, 7943, 7943, 7943, 6, 79, 16192, 60, 8640, 15, -1, 7993), - (7944, 7944, 7944, 7944, 7944, 7, 79, 16193, 34, 1800, 15, -1, -1), - (7945, -1, -1, 7945, 7945, 6, 81, -1, 0, 0, 15, -1, 7946), - (7946, -1, -1, 7945, 7945, 6, 82, -1, 0, 0, 15, 7945, 7947), - (7947, -1, -1, 7945, 7945, 6, 83, -1, 0, 0, 15, 7946, 10033), - (7948, -1, -1, 7948, 7948, 6, 75, -1, 0, 0, 15, -1, 7949), - (7949, -1, -1, 7948, 7948, 6, 80, -1, 0, 0, 15, 7948, 7950), - (7950, -1, -1, 7948, 7948, 6, 85, -1, 0, 0, 15, 7949, 10035), - (7951, 7951, 7951, 7951, 7951, 6, 82, 16200, 61, 900, 15, -1, 7952), - (7952, 7951, 7951, 7951, 7951, 6, 83, 16201, 61, 900, 15, 7951, 7953), - (7953, 7951, 7951, 7951, 7951, 6, 84, 16202, 61, 900, 15, 7952, 10038), - (7980, -1, -1, 7980, 7980, 6, 70, -1, 0, 0, 15, -1, 7981), - (7981, -1, -1, 7980, 7980, 6, 73, -1, 0, 0, 15, 7980, 7982), - (7982, -1, -1, 7980, 7980, 6, 76, -1, 0, 0, 15, 7981, -1), - (7983, -1, -1, 7983, 7983, 6, 70, -1, 0, 0, 15, -1, 7984), - (7984, -1, -1, 7983, 7983, 6, 73, -1, 0, 0, 15, 7983, 7985), - (7985, -1, -1, 7983, 7983, 6, 76, -1, 0, 0, 15, 7984, 10110), - (7986, 7986, 7986, 7986, 7986, 9, 75, 16203, 11, 600, 15, -1, 7987), - (7987, 7986, 7986, 7986, 7986, 12, 80, 16204, 11, 600, 15, 7986, 7988), - (7988, 7986, 7986, 7986, 7986, 12, 85, 16205, 11, 600, 15, 7987, 10510), - (7989, -1, -1, 7989, 7989, 6, 75, -1, 0, 0, 15, -1, 7990), - (7990, -1, -1, 7989, 7989, 6, 80, -1, 0, 0, 15, 7989, 7991), - (7991, -1, -1, 7989, 7989, 6, 85, -1, 0, 0, 15, 7990, 7992), - (7992, -1, -1, 7989, 7989, 6, 85, -1, 0, 0, 15, 7991, 13415), - (7993, 7943, 7943, 7943, 7943, 6, 85, 23601, 60, 8640, 17, 7943, -1), - (7994, -1, -1, 462, 462, 2, 81, -1, 0, 0, 17, 464, 7995), - (7995, -1, -1, 462, 462, 2, 85, -1, 0, 0, 17, 7994, -1), - (8000, -1, -1, 8001, 8001, 0, 50, -1, 0, 0, 8, -1, -1), - (8030, 8030, 8030, 8030, 8030, 6, 70, 16206, 60, 900, 15, -1, -1), - (8031, -1, -1, 8031, 8031, 6, 75, -1, 0, 0, 15, -1, 8032), - (8032, -1, -1, 8031, 8031, 6, 77, -1, 0, 0, 15, 8031, 8033), - (8033, -1, -1, 8031, 8031, 6, 79, -1, 0, 0, 15, 8032, 10282), - (8034, 8034, 8034, 8034, 8034, 6, 81, 16207, 59, 600, 15, -1, -1), - (8035, -1, -1, 8035, 8035, 6, 73, -1, 0, 0, 15, -1, 8036), - (8036, -1, -1, 8035, 8035, 6, 75, -1, 0, 0, 15, 8035, 8037), - (8037, -1, -1, 8035, 8035, 6, 77, -1, 0, 0, 15, 8036, 10285), - (8038, 8038, 8038, 8038, 8038, 6, 81, 16210, 56, 12, 15, -1, 17541), - (8039, 8039, 8039, 8039, 8039, 6, 83, 16211, 58, 7, 15, -1, 15462), - (8040, -1, -1, 8040, 8040, 4, 65, -1, 0, 0, 15, -1, 8041), - (8041, -1, -1, 8040, 8040, 4, 70, -1, 0, 0, 15, 8040, 8042), - (8042, -1, -1, 8040, 8040, 4, 75, -1, 0, 0, 15, 8041, 8043), - (8043, -1, -1, 8040, 8040, 4, 78, -1, 0, 0, 15, 8042, 8313), - (8059, -1, -1, 8232, 8232, 4, 78, -1, 0, 0, 15, 8234, 8261), - (8060, 8060, 8060, 8060, 8060, 7, 75, 16238, 41, 1800, 15, -1, 8061), - (8061, 8060, 8060, 8060, 8060, 7, 78, 16239, 41, 1800, 15, 8060, 8062), - (8062, 8060, 8060, 8060, 8060, 7, 81, 16240, 41, 1800, 15, 8061, 10237), - (8063, 8063, 8063, 8063, 8063, 7, 75, 16241, 41, 1800, 15, -1, 8064), - (8064, 8063, 8063, 8063, 8063, 7, 78, 16242, 41, 1800, 15, 8063, 8065), - (8065, 8063, 8063, 8063, 8063, 7, 81, 16243, 41, 1800, 15, 8064, 10240), - (8066, 8066, 8066, 8066, 8066, 7, 75, 16244, 41, 1800, 15, -1, 8067), - (8067, 8066, 8066, 8066, 8066, 7, 78, 16245, 41, 1800, 15, 8066, 8068), - (8068, 8066, 8066, 8066, 8066, 7, 81, 16246, 41, 1800, 15, 8067, 10243), - (8069, -1, -1, 8069, 8069, 5, 71, -1, 0, 0, 15, -1, 8070), - (8070, -1, -1, 8069, 8069, 5, 72, -1, 0, 0, 15, 8069, 8071), - (8071, -1, -1, 8069, 8069, 5, 73, -1, 0, 0, 15, 8070, 15606), - (8072, 8072, 8072, 8072, 8072, 7, 75, 16221, 37, 20, 15, -1, 8073), - (8073, 8072, 8072, 8072, 8072, 7, 75, 16222, 37, 20, 15, 8072, 8074), - (8074, 8072, 8072, 8072, 8072, 7, 75, 16223, 37, 20, 15, 8073, 10246), - (8075, 8075, 8075, 8075, 8075, 7, 81, 16224, 42, 6, 15, -1, -1), - (8076, -1, -1, 8076, 8076, 5, 77, -1, 0, 0, 15, -1, 8077), - (8077, -1, -1, 8076, 8076, 5, 78, -1, 0, 0, 15, 8076, 8078), - (8078, -1, -1, 8076, 8076, 5, 79, -1, 0, 0, 15, 8077, 8079), - (8079, -1, -1, 8076, 8076, 5, 80, -1, 0, 0, 15, 8078, 8080), - (8080, -1, -1, 8076, 8076, 5, 81, -1, 0, 0, 15, 8079, 8081), - (8081, -1, -1, 8076, 8076, 5, 82, -1, 0, 0, 15, 8080, -1), - (8082, -1, -1, 8082, 8082, 3, 65, -1, 0, 0, 15, -1, 8083), - (8083, -1, -1, 8082, 8082, 3, 67, -1, 0, 0, 15, 8082, 8084), - (8084, -1, -1, 8082, 8082, 3, 69, -1, 0, 0, 15, 8083, 10249), - (8190, -1, -1, 8190, 8190, 7, 75, -1, 0, 0, 15, -1, 8191), - (8191, -1, -1, 8190, 8190, 7, 75, -1, 0, 0, 15, 8190, 8192), - (8192, -1, -1, 8190, 8190, 7, 75, -1, 0, 0, 15, 8191, -1), - (8193, -1, -1, 8193, 8193, 7, 75, -1, 0, 0, 15, -1, -1), - (8194, 8194, 8194, 8194, 8194, 7, 75, 16226, 47, 12, 15, -1, -1), - (8195, -1, -1, 8195, 8195, 4, 75, -1, 0, 0, 15, -1, 8196), - (8196, -1, -1, 8195, 8195, 4, 75, -1, 0, 0, 15, 8195, 8197), - (8197, -1, -1, 8195, 8195, 4, 75, -1, 0, 0, 15, 8196, 7704), - (8198, -1, -1, 8198, 8198, 4, 65, -1, 0, 0, 15, -1, 8199), - (8199, -1, -1, 8198, 8198, 4, 65, -1, 0, 0, 15, 8198, 8200), - (8200, -1, -1, 8198, 8198, 4, 65, -1, 0, 0, 15, 8199, -1), - (8201, -1, -1, 8201, 8201, 7, 81, -1, 0, 0, 15, -1, 8202), - (8202, -1, -1, 8201, 8201, 7, 81, -1, 0, 0, 15, 8201, 8203), - (8203, -1, -1, 8201, 8201, 7, 81, -1, 0, 0, 15, 8202, 16475), - (8204, -1, -1, 8204, 8204, 4, 75, -1, 0, 0, 15, -1, 8205), - (8205, -1, -1, 8204, 8204, 4, 75, -1, 0, 0, 15, 8204, 8206), - (8206, -1, -1, 8204, 8204, 4, 75, -1, 0, 0, 15, 8205, 1656), - (8207, -1, -1, 8207, 8207, 4, 75, -1, 0, 0, 15, -1, 8208), - (8208, -1, -1, 8207, 8207, 4, 75, -1, 0, 0, 15, 8207, 8209), - (8209, -1, -1, 8207, 8207, 4, 75, -1, 0, 0, 15, 8208, 1659), - (8210, -1, -1, 8210, 8210, 5, 65, -1, 0, 0, 15, -1, 8211), - (8211, -1, -1, 8210, 8210, 5, 70, -1, 0, 0, 15, 8210, 8212), - (8212, -1, -1, 8210, 8210, 5, 75, -1, 0, 0, 15, 8211, 8213), - (8213, -1, -1, 8210, 8210, 5, 80, -1, 0, 0, 15, 8212, 8214), - (8214, -1, -1, 8210, 8210, 5, 85, -1, 0, 0, 15, 8213, 1651), - (8215, -1, -1, 8215, 8215, 5, 65, -1, 0, 0, 15, -1, 8216), - (8216, -1, -1, 8215, 8215, 5, 70, -1, 0, 0, 15, 8215, 8217), - (8217, -1, -1, 8215, 8215, 5, 75, -1, 0, 0, 15, 8216, 8218), - (8218, -1, -1, 8215, 8215, 5, 80, -1, 0, 0, 15, 8217, 8219), - (8219, -1, -1, 8215, 8215, 5, 85, -1, 0, 0, 15, 8218, 12559), - (8220, 8220, 8220, 8220, 8220, 5, 76, 16227, 39, 15, 15, -1, -1), - (8221, 8221, 8221, 8221, 8221, 9, 81, 16228, 45, 600, 15, -1, -1), - (8222, 8222, 8222, 8222, 8222, 7, 75, 16229, 70, 10, 15, -1, -1), - (8223, -1, -1, 86, 86, 8, 59, -1, 0, 0, 15, 6259, 8262), - (8224, -1, -1, 8224, 8224, 5, 75, -1, 0, 0, 15, -1, 8225), - (8225, -1, -1, 8224, 8224, 5, 80, -1, 0, 0, 15, 8224, 8226), - (8226, -1, -1, 8224, 8224, 5, 85, -1, 0, 0, 15, 8225, 8421), - (8227, 8227, 8227, 8227, 8227, 3, 55, 16233, 71, 10, 15, -1, 12810), - (8228, -1, -1, 8228, 8228, 5, 75, -1, 0, 0, 15, -1, 8229), - (8229, -1, -1, 8228, 8228, 5, 80, -1, 0, 0, 15, 8228, 8230), - (8230, -1, -1, 8228, 8228, 5, 85, -1, 0, 0, 15, 8229, -1), - (8231, 8231, -1, 8231, 8231, 3, 55, 16234, 38, 60, 15, -1, -1), - (8232, -1, -1, 8232, 8232, 4, 65, -1, 0, 0, 15, -1, 8233), - (8233, -1, -1, 8232, 8232, 4, 70, -1, 0, 0, 15, 8232, 8234), - (8234, -1, -1, 8232, 8232, 4, 75, -1, 0, 0, 15, 8233, 8059), - (8235, -1, -1, 8235, 8235, 6, 81, -1, 0, 0, 15, -1, 8236), - (8236, -1, -1, 8235, 8235, 6, 81, -1, 0, 0, 15, 8235, 8237), - (8237, -1, -1, 8235, 8235, 6, 81, -1, 0, 0, 15, 8236, 8238), - (8238, -1, -1, 8235, 8235, 6, 81, -1, 0, 0, 15, 8237, 8239), - (8239, -1, -1, 8235, 8235, 6, 81, -1, 0, 0, 15, 8238, 8304), - (8240, -1, -1, 8240, 8240, 6, 81, -1, 0, 0, 15, -1, 8241), - (8241, -1, -1, 8240, 8240, 6, 81, -1, 0, 0, 15, 8240, 8242), - (8242, -1, -1, 8240, 8240, 6, 81, -1, 0, 0, 15, 8241, 8243), - (8243, -1, -1, 8240, 8240, 6, 81, -1, 0, 0, 15, 8242, 8244), - (8244, -1, -1, 8240, 8240, 6, 81, -1, 0, 0, 15, 8243, 10781), - (8245, -1, -1, 8245, 8245, 6, 81, -1, 0, 0, 15, -1, 8246), - (8246, -1, -1, 8245, 8245, 6, 81, -1, 0, 0, 15, 8245, 8247), - (8247, -1, -1, 8245, 8245, 6, 81, -1, 0, 0, 15, 8246, 8248), - (8248, -1, -1, 8245, 8245, 6, 81, -1, 0, 0, 15, 8247, 8249), - (8249, -1, -1, 8245, 8245, 6, 81, -1, 0, 0, 15, 8248, 8422), - (8250, -1, -1, 8250, 8250, 6, 81, -1, 0, 0, 15, -1, 8251), - (8251, -1, -1, 8250, 8250, 6, 81, -1, 0, 0, 15, 8250, 8252), - (8252, -1, -1, 8250, 8250, 6, 81, -1, 0, 0, 15, 8251, 8253), - (8253, -1, -1, 8250, 8250, 6, 81, -1, 0, 0, 15, 8252, 8254), - (8254, -1, -1, 8250, 8250, 6, 81, -1, 0, 0, 15, 8253, 13046), - (8255, -1, -1, 8255, 8255, 6, 81, -1, 0, 0, 15, -1, 8256), - (8256, -1, -1, 8255, 8255, 6, 81, -1, 0, 0, 15, 8255, 8257), - (8257, -1, -1, 8255, 8255, 6, 81, -1, 0, 0, 15, 8256, 8258), - (8258, -1, -1, 8255, 8255, 6, 81, -1, 0, 0, 15, 8257, 8259), - (8259, -1, -1, 8255, 8255, 6, 81, -1, 0, 0, 15, 8258, 12411), - (8260, 8005, 8005, 8005, 8005, 9, 85, 20185, 45, 600, 16, -1, -1), - (8261, -1, -1, 8232, 8232, 4, 80, -1, 0, 0, 16, 8059, 15772), - (8262, -1, -1, 86, 86, 8, 65, -1, 0, 0, 16, 8223, -1), - (8263, -1, -1, 8263, 8263, 5, 81, -1, 0, 0, 16, -1, 8264), - (8264, -1, -1, 8263, 8263, 5, 82, -1, 0, 0, 16, 8263, 8265), - (8265, -1, -1, 8263, 8263, 5, 83, -1, 0, 0, 16, 8264, 8266), - (8266, -1, -1, 8263, 8263, 5, 84, -1, 0, 0, 16, 8265, 8267), - (8267, -1, -1, 8263, 8263, 5, 85, -1, 0, 0, 16, 8266, 8351), - (8268, -1, -1, 8268, 8268, 5, 81, -1, 0, 0, 16, -1, 8269), - (8269, -1, -1, 8268, 8268, 5, 82, -1, 0, 0, 16, 8268, 8270), - (8270, -1, -1, 8268, 8268, 5, 83, -1, 0, 0, 16, 8269, 8271), - (8271, -1, -1, 8268, 8268, 5, 84, -1, 0, 0, 16, 8270, 8272), - (8272, -1, -1, 8268, 8268, 5, 85, -1, 0, 0, 16, 8271, 8361), - (8273, -1, -1, 8273, 8273, 5, 81, -1, 0, 0, 16, -1, 8274), - (8274, -1, -1, 8273, 8273, 5, 82, -1, 0, 0, 16, 8273, 8275), - (8275, -1, -1, 8273, 8273, 5, 83, -1, 0, 0, 16, 8274, 8276), - (8276, -1, -1, 8273, 8273, 5, 84, -1, 0, 0, 16, 8275, 8277), - (8277, -1, -1, 8273, 8273, 5, 85, -1, 0, 0, 16, 8276, 8371), - (8278, -1, -1, 8278, 8278, 5, 81, -1, 0, 0, 16, -1, 8279), - (8279, -1, -1, 8278, 8278, 5, 82, -1, 0, 0, 16, 8278, 8280), - (8280, -1, -1, 8278, 8278, 5, 83, -1, 0, 0, 16, 8279, 8281), - (8281, -1, -1, 8278, 8278, 5, 84, -1, 0, 0, 16, 8280, 8282), - (8282, -1, -1, 8278, 8278, 5, 85, -1, 0, 0, 16, 8281, 8381), - (8283, -1, -1, 8283, 8283, 5, 81, -1, 0, 0, 16, -1, 8284), - (8284, -1, -1, 8283, 8283, 5, 82, -1, 0, 0, 16, 8283, 8285), - (8285, -1, -1, 8283, 8283, 5, 83, -1, 0, 0, 16, 8284, 8286), - (8286, -1, -1, 8283, 8283, 5, 84, -1, 0, 0, 16, 8285, 8287), - (8287, -1, -1, 8283, 8283, 5, 85, -1, 0, 0, 16, 8286, 8391), - (8288, -1, -1, 8288, 8288, 5, 81, -1, 0, 0, 16, -1, 8289), - (8289, -1, -1, 8288, 8288, 5, 82, -1, 0, 0, 16, 8288, 8290), - (8290, -1, -1, 8288, 8288, 5, 83, -1, 0, 0, 16, 8289, 8291), - (8291, -1, -1, 8288, 8288, 5, 84, -1, 0, 0, 16, 8290, 8292), - (8292, -1, -1, 8288, 8288, 5, 85, -1, 0, 0, 16, 8291, 8401), - (8293, -1, -1, 8293, 8293, 5, 81, -1, 0, 0, 16, -1, 8294), - (8294, -1, -1, 8293, 8293, 5, 82, -1, 0, 0, 16, 8293, 8295), - (8295, -1, -1, 8293, 8293, 5, 83, -1, 0, 0, 16, 8294, 8296), - (8296, -1, -1, 8293, 8293, 5, 84, -1, 0, 0, 16, 8295, 8297), - (8297, -1, -1, 8293, 8293, 5, 85, -1, 0, 0, 16, 8296, 8411), - (8300, 8300, 8300, 8300, 8300, 5, 81, 21778, 8, 900, 16, -1, 8301), - (8301, 8300, 8300, 8300, 8300, 7, 83, 21779, 8, 900, 16, 8300, 8302), - (8302, 8300, 8300, 8300, 8300, 9, 85, 21780, 8, 900, 16, 8301, 15111), - (8303, 8303, 8303, 8303, 8303, 12, 85, 21773, 9, 1800, 16, -1, -1), - (8304, -1, -1, 8235, 8235, 6, 85, -1, 0, 0, 16, 8239, 8305), - (8305, -1, -1, 8235, 8235, 6, 85, -1, 0, 0, 16, 8304, 8306), - (8306, -1, -1, 8235, 8235, 6, 85, -1, 0, 0, 16, 8305, 8307), - (8307, -1, -1, 8235, 8235, 6, 85, -1, 0, 0, 16, 8306, 8308), - (8308, -1, -1, 8235, 8235, 6, 85, -1, 0, 0, 16, 8307, 13353), - (8309, 260, -1, 260, 260, 5, 81, 21687, 3, 2160, 16, 262, 8310), - (8310, 260, -1, 260, 260, 7, 83, 21688, 3, 2160, 16, 8309, 8311), - (8311, 260, -1, 260, 260, 9, 85, 21689, 3, 2160, 16, 8310, -1), - (8312, 8312, 8312, 8312, 8312, 12, 85, 21690, 2, 900, 16, -1, -1), - (8313, -1, -1, 8040, 8040, 4, 80, -1, 0, 0, 16, 8043, 15773), - (8314, -1, -1, 8314, 8314, 7, 85, -1, 0, 0, 16, -1, 8315), - (8315, -1, -1, 8314, 8314, 9, 85, -1, 0, 0, 16, 8314, 8316), - (8316, -1, -1, 8314, 8314, 12, 85, -1, 0, 0, 16, 8315, 13508), - (8317, -1, -1, 8317, 8317, 5, 85, -1, 0, 0, 16, -1, 8318), - (8318, -1, -1, 8317, 8317, 5, 85, -1, 0, 0, 16, 8317, -1), - (8319, -1, -1, 8319, 8319, 5, 85, -1, 0, 0, 16, -1, 8320), - (8320, -1, -1, 8319, 8319, 5, 85, -1, 0, 0, 16, 8319, 8321), - (8321, -1, -1, 8319, 8319, 5, 85, -1, 0, 0, 16, 8320, -1), - (8322, -1, -1, 8322, 8322, 5, 81, 0, 0, 0, 16, -1, 8323), - (8323, -1, -1, 8322, 8322, 7, 83, 0, 0, 0, 16, 8322, 8324), - (8324, -1, -1, 8322, 8322, 9, 85, 0, 0, 0, 16, 8323, 13199), - (8325, -1, -1, 8325, 8325, 7, 81, 0, 0, 0, 16, -1, 8326), - (8326, -1, -1, 8325, 8325, 9, 81, 0, 0, 0, 16, 8325, 8327), - (8327, -1, -1, 8325, 8325, 11, 81, 0, 0, 0, 16, 8326, 13219), - (8328, -1, -1, 244, 244, 12, 59, -1, 0, 0, 3, 246, -1), - (8329, -1, -1, 622, 622, 3, 71, -1, 0, 0, 16, 624, -1), - (8331, -1, -1, 8331, 8331, 9, 85, 0, 0, 0, 16, -1, -1), - (8332, -1, -1, 8332, 8332, 7, 85, 0, 0, 0, 16, -1, 8333), - (8333, -1, -1, 8332, 8332, 7, 85, 0, 0, 0, 16, 8332, 8334), - (8334, -1, -1, 8332, 8332, 7, 85, 0, 0, 0, 16, 8333, -1), - (8335, -1, -1, 8335, 8335, 5, 81, 0, 0, 0, 16, -1, 8336), - (8336, -1, -1, 8335, 8335, 5, 82, 0, 0, 0, 16, 8335, 8337), - (8337, -1, -1, 8335, 8335, 5, 83, 0, 0, 0, 16, 8336, 8338), - (8338, -1, -1, 8335, 8335, 5, 84, 0, 0, 0, 16, 8337, 8339), - (8339, -1, -1, 8335, 8335, 5, 85, 0, 0, 0, 16, 8338, -1), - (8341, 8341, 8341, 8341, 8341, 12, 85, 21829, 53, 450, 16, -1, -1), - (8342, 8342, 8342, 8342, 8342, 12, 85, 21843, 54, 240, 16, -1, 14729), - (8343, 167, 167, 167, 167, 10, 85, 21837, 14, 900, 16, 7249, 12955), - (8344, -1, -1, 1210, 1213, 12, 85, -1, 0, 0, 16, 7583, 8345), - (8345, -1, -1, 1210, 1213, 12, 85, -1, 0, 0, 16, 8344, 8346), - (8346, -1, -1, 1210, 1213, 12, 85, -1, 0, 0, 16, 8345, 12526), - (8347, -1, -1, 8347, 8347, 7, 81, 0, 0, 0, 16, -1, 8348), - (8348, -1, -1, 8347, 8347, 9, 83, 0, 0, 0, 16, 8347, 8349), - (8349, -1, -1, 8347, 8347, 11, 85, 0, 0, 0, 16, 8348, -1), - (8350, -1, -1, 8350, 8350, 12, 85, 0, 0, 0, 16, -1, -1), - (8351, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8267, 8352), - (8352, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8351, 8353), - (8353, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8352, 8354), - (8354, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8353, 8355), - (8355, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8354, 8356), - (8356, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8355, 8357), - (8357, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8356, 8358), - (8358, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8357, 8359), - (8359, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8358, 8360), - (8360, -1, -1, 8263, 8263, 3, 85, -1, 0, 0, 17, 8359, 13933), - (8361, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8272, 8362), - (8362, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8361, 8363), - (8363, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8362, 8364), - (8364, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8363, 8365), - (8365, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8364, 8366), - (8366, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8365, 8367), - (8367, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8366, 8368), - (8368, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8367, 8369), - (8369, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8368, 8370), - (8370, -1, -1, 8268, 8268, 3, 85, -1, 0, 0, 17, 8369, 13943), - (8371, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8277, 8372), - (8372, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8371, 8373), - (8373, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8372, 8374), - (8374, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8373, 8375), - (8375, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8374, 8376), - (8376, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8375, 8377), - (8377, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8376, 8378), - (8378, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8377, 8379), - (8379, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8378, 8380), - (8380, -1, -1, 8273, 8273, 3, 85, -1, 0, 0, 17, 8379, 13953), - (8381, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8282, 8382), - (8382, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8381, 8383), - (8383, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8382, 8384), - (8384, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8383, 8385), - (8385, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8384, 8386), - (8386, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8385, 8387), - (8387, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8386, 8388), - (8388, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8387, 8389), - (8389, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8388, 8390), - (8390, -1, -1, 8278, 8278, 3, 85, -1, 0, 0, 17, 8389, 13963), - (8391, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8287, 8392), - (8392, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8391, 8393), - (8393, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8392, 8394), - (8394, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8393, 8395), - (8395, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8394, 8396), - (8396, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8395, 8397), - (8397, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8396, 8398), - (8398, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8397, 8399), - (8399, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8398, 8400), - (8400, -1, -1, 8283, 8283, 3, 85, -1, 0, 0, 17, 8399, 13973), - (8401, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8292, 8402), - (8402, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8401, 8403), - (8403, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8402, 8404), - (8404, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8403, 8405), - (8405, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8404, 8406), - (8406, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8405, 8407), - (8407, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8406, 8408), - (8408, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8407, 8409), - (8409, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8408, 8410), - (8410, -1, -1, 8288, 8288, 3, 85, -1, 0, 0, 17, 8409, 13983), - (8411, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8297, 8412), - (8412, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8411, 8413), - (8413, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8412, 8414), - (8414, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8413, 8415), - (8415, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8414, 8416), - (8416, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8415, 8417), - (8417, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8416, 8418), - (8418, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8417, 8419), - (8419, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8418, 8420), - (8420, -1, -1, 8293, 8293, 3, 85, -1, 0, 0, 17, 8419, 13993), - (8421, -1, -1, 8224, 8224, 5, 90, -1, 0, 0, 17, 8226, -1), - (8422, -1, -1, 8245, 8245, 6, 86, -1, 0, 0, 17, 8249, 8423), - (8423, -1, -1, 8245, 8245, 6, 87, -1, 0, 0, 17, 8422, 8424), - (8424, -1, -1, 8245, 8245, 6, 88, -1, 0, 0, 17, 8423, 8425), - (8425, -1, -1, 8245, 8245, 6, 89, -1, 0, 0, 17, 8424, 8426), - (8426, -1, -1, 8245, 8245, 6, 90, -1, 0, 0, 17, 8425, 13338), - (8427, -1, -1, 7100, 7100, 6, 85, -1, 0, 0, 17, 7325, 8428), - (8428, -1, -1, 7100, 7100, 6, 87, -1, 0, 0, 17, 8427, 8429), - (8429, -1, -1, 7100, 7100, 6, 89, -1, 0, 0, 17, 8428, -1), - (8430, -1, -1, 1026, 1026, 10, 91, -1, 0, 0, 18, 7890, 8431), - (8435, -1, -1, 65, 661, 8, 91, -1, 0, 0, 18, 7908, 8436), - (8440, -1, -1, 122, 122, 13, 91, -1, 0, 0, 18, 13089, 8441), - (8445, -1, -1, 12636, 12636, 0, 1, -1, 0, 0, 16, 12637, 8446), - (8446, -1, -1, 12636, 12636, 0, 1, -1, 0, 0, 16, 8445, 8447), - (8447, -1, -1, 12636, 12636, 0, 1, -1, 0, 0, 16, 8446, 16419), - (8448, -1, -1, 6119, 6119, 8, 91, -1, 0, 0, 18, 12496, 8449), - (8463, -1, -1, 125, 125, 10, 91, -1, 0, 0, 18, 13084, 8464), - (8464, -1, -1, 125, 125, 11, 91, -1, 0, 0, 18, 8463, 8465), - (8470, -1, -1, 1006, 1006, 10, 91, -1, 0, 0, 18, 7841, 8471), - (9000, 9000, 9000, 9000, 9000, 0, 1, 16995, 49, 72000, 0, -1, -1), - (9001, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, -1, 9002), - (9002, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9001, 9003), - (9003, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9002, 9004), - (9004, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9003, 9005), - (9005, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9004, 9006), - (9006, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9005, 9007), - (9007, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9006, 9008), - (9008, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9007, 9009), - (9009, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9008, 9010), - (9010, -1, -1, 9101, 9101, 2, 51, -1, 0, 0, 15, 9009, -1), - (9011, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, -1, 9012), - (9012, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9011, 9013), - (9013, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9012, 9014), - (9014, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9013, 9015), - (9015, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9014, 9016), - (9016, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9015, 9017), - (9017, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9016, 9018), - (9018, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9017, 9019), - (9019, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9018, 9020), - (9020, -1, -1, 9111, 9111, 4, 51, -1, 0, 0, 15, 9019, -1), - (9021, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, -1, 9022), - (9022, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9021, 9023), - (9023, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9022, 9024), - (9024, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9023, 9025), - (9025, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9024, 9026), - (9026, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9025, 9027), - (9027, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9026, 9028), - (9028, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9027, 9029), - (9029, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9028, 9030), - (9030, -1, -1, 9121, 9121, 3, 51, -1, 0, 0, 15, 9029, -1), - (9031, 9031, 9031, 9031, 9031, 0, 1, 16601, 65, 72000, 0, -1, -1), - (9032, 9032, 9032, 9032, 9032, 0, 0, 21815, 51, 72000, 0, -1, -1), - (9033, -1, -1, 9033, 9033, 0, 1, -1, 0, 0, 0, -1, -1), - (9100, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, -1, 9101), - (9101, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, 9100, 9102), - (9102, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, 9101, 9103), - (9103, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, 9102, 9104), - (9104, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, 9103, 9105), - (9105, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, 9104, 9106), - (9106, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, 9105, 9107), - (9107, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, 9106, 9108), - (9108, -1, -1, 9100, 9100, 1, 85, -1, 0, 0, 15, 9107, -1), - (9109, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, -1, 9110), - (9110, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, 9109, 9111), - (9111, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, 9110, 9112), - (9112, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, 9111, 9113), - (9113, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, 9112, 9114), - (9114, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, 9113, 9115), - (9115, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, 9114, 9116), - (9116, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, 9115, 9117), - (9117, -1, -1, 9109, 9109, 1, 85, -1, 0, 0, 15, 9116, -1), - (9118, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, -1, 9119), - (9119, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, 9118, 9120), - (9120, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, 9119, 9121), - (9121, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, 9120, 9122), - (9122, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, 9121, 9123), - (9123, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, 9122, 9124), - (9124, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, 9123, 9125), - (9125, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, 9124, 9126), - (9126, -1, -1, 9118, 9118, 1, 85, -1, 0, 0, 15, 9125, -1), - (9127, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, -1, 9128), - (9128, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, 9127, 9129), - (9129, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, 9128, 9130), - (9130, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, 9129, 9131), - (9131, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, 9130, 9132), - (9132, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, 9131, 9133), - (9133, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, 9132, 9134), - (9134, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, 9133, 9135), - (9135, -1, -1, 9127, 9127, 1, 85, -1, 0, 0, 15, 9134, -1), - (9136, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, -1, 9137), - (9137, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, 9136, 9138), - (9138, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, 9137, 9139), - (9139, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, 9138, 9140), - (9140, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, 9139, 9141), - (9141, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, 9140, 9142), - (9142, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, 9141, 9143), - (9143, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, 9142, 9144), - (9144, -1, -1, 9136, 9136, 1, 85, -1, 0, 0, 15, 9143, -1), - (9145, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, -1, 9146), - (9146, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, 9145, 9147), - (9147, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, 9146, 9148), - (9148, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, 9147, 9149), - (9149, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, 9148, 9150), - (9150, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, 9149, 9151), - (9151, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, 9150, 9152), - (9152, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, 9151, 9153), - (9153, -1, -1, 9145, 9145, 1, 85, -1, 0, 0, 15, 9152, -1), - (9154, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, -1, 9155), - (9155, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, 9154, 9156), - (9156, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, 9155, 9157), - (9157, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, 9156, 9158), - (9158, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, 9157, 9159), - (9159, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, 9158, 9160), - (9160, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, 9159, 9161), - (9161, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, 9160, 9162), - (9162, -1, -1, 9154, 9154, 1, 85, -1, 0, 0, 15, 9161, -1), - (9163, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, -1, 9164), - (9164, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, 9163, 9165), - (9165, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, 9164, 9166), - (9166, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, 9165, 9167), - (9167, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, 9166, 9168), - (9168, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, 9167, 9169), - (9169, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, 9168, 9170), - (9170, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, 9169, 9171), - (9171, -1, -1, 9163, 9163, 1, 85, -1, 0, 0, 15, 9170, -1), - (9172, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, -1, 9173), - (9173, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, 9172, 9174), - (9174, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, 9173, 9175), - (9175, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, 9174, 9176), - (9176, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, 9175, 9177), - (9177, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, 9176, 9178), - (9178, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, 9177, 9179), - (9179, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, 9178, 9180), - (9180, -1, -1, 9172, 9172, 1, 85, -1, 0, 0, 15, 9179, -1), - (9181, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, -1, 9182), - (9182, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, 9181, 9183), - (9183, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, 9182, 9184), - (9184, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, 9183, 9185), - (9185, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, 9184, 9186), - (9186, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, 9185, 9187), - (9187, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, 9186, 9188), - (9188, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, 9187, 9189), - (9189, -1, -1, 9181, 9181, 1, 85, -1, 0, 0, 15, 9188, -1), - (9190, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, -1, 9191), - (9191, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, 9190, 9192), - (9192, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, 9191, 9193), - (9193, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, 9192, 9194), - (9194, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, 9193, 9195), - (9195, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, 9194, 9196), - (9196, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, 9195, 9197), - (9197, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, 9196, 9198), - (9198, -1, -1, 9190, 9190, 1, 85, -1, 0, 0, 15, 9197, -1), - (9199, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, -1, 9200), - (9200, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, 9199, 9201), - (9201, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, 9200, 9202), - (9202, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, 9201, 9203), - (9203, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, 9202, 9204), - (9204, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, 9203, 9205), - (9205, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, 9204, 9206), - (9206, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, 9205, 9207), - (9207, -1, -1, 9199, 9199, 1, 85, -1, 0, 0, 15, 9206, -1), - (9208, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, -1, 9209), - (9209, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, 9208, 9210), - (9210, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, 9209, 9211), - (9211, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, 9210, 9212), - (9212, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, 9211, 9213), - (9213, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, 9212, 9214), - (9214, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, 9213, 9215), - (9215, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, 9214, 9216), - (9216, -1, -1, 9208, 9208, 1, 85, -1, 0, 0, 15, 9215, -1), - (9217, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, -1, 9218), - (9218, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, 9217, 9219), - (9219, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, 9218, 9220), - (9220, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, 9219, 9221), - (9221, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, 9220, 9222), - (9222, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, 9221, 9223), - (9223, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, 9222, 9224), - (9224, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, 9223, 9225), - (9225, -1, -1, 9217, 9217, 1, 85, -1, 0, 0, 15, 9224, -1), - (9226, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, -1, 9227), - (9227, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, 9226, 9228), - (9228, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, 9227, 9229), - (9229, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, 9228, 9230), - (9230, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, 9229, 9231), - (9231, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, 9230, 9232), - (9232, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, 9231, 9233), - (9233, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, 9232, 9234), - (9234, -1, -1, 9226, 9226, 1, 85, -1, 0, 0, 15, 9233, -1), - (9235, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, -1, 9236), - (9236, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, 9235, 9237), - (9237, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, 9236, 9238), - (9238, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, 9237, 9239), - (9239, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, 9238, 9240), - (9240, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, 9239, 9241), - (9241, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, 9240, 9242), - (9242, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, 9241, 9243), - (9243, -1, -1, 9235, 9235, 1, 85, -1, 0, 0, 15, 9242, -1), - (9300, 9300, 9300, 9300, 9300, 5, 85, 16212, 40, 600, 15, -1, 9301), - (9301, 9300, 9300, 9300, 9300, 5, 85, 16213, 40, 600, 15, 9300, 9302), - (9302, 9300, 9300, 9300, 9300, 5, 85, 16214, 40, 600, 15, 9301, -1), - (9303, 9303, 9303, 9303, 9303, 5, 85, 16215, 40, 600, 15, -1, 9304), - (9304, 9303, 9303, 9303, 9303, 5, 85, 16216, 40, 600, 15, 9303, 9305), - (9305, 9303, 9303, 9303, 9303, 5, 85, 16217, 40, 600, 15, 9304, -1), - (9306, 9306, 9306, 9306, 9306, 5, 85, 16218, 40, 600, 15, -1, 9307), - (9307, 9306, 9306, 9306, 9306, 5, 85, 16219, 40, 600, 15, 9306, 9308), - (9308, 9306, 9306, 9306, 9306, 5, 85, 16220, 40, 600, 15, 9307, -1), - (9309, 9309, 9309, 9309, 9309, 5, 85, 16249, 40, 600, 15, -1, 9310), - (9310, 9309, 9309, 9309, 9309, 5, 85, 16250, 40, 600, 15, 9309, 9311), - (9311, 9309, 9309, 9309, 9309, 5, 85, 16251, 40, 600, 15, 9310, -1), - (9312, 9312, 9312, 9312, 9312, 5, 85, 16252, 40, 600, 15, -1, 9313), - (9313, 9312, 9312, 9312, 9312, 5, 85, 16253, 40, 600, 15, 9312, 9314), - (9314, 9312, 9312, 9312, 9312, 5, 85, 16254, 40, 600, 15, 9313, -1), - (9315, 9315, 9315, 9315, 9315, 5, 85, 16255, 40, 600, 15, -1, 9316), - (9316, 9315, 9315, 9315, 9315, 5, 85, 16256, 40, 600, 15, 9315, 9317), - (9317, 9315, 9315, 9315, 9315, 5, 85, 16257, 40, 600, 15, 9316, -1), - (9318, 9318, 9318, 9318, 9318, 5, 85, 16261, 40, 600, 15, -1, 9319), - (9319, 9318, 9318, 9318, 9318, 5, 85, 16262, 40, 600, 15, 9318, 9320), - (9320, 9318, 9318, 9318, 9318, 5, 85, 16263, 40, 600, 15, 9319, -1), - (9321, 9321, 9321, 9321, 9321, 5, 85, 16264, 40, 600, 15, -1, 9322), - (9322, 9321, 9321, 9321, 9321, 5, 85, 16265, 40, 600, 15, 9321, 9323), - (9323, 9321, 9321, 9321, 9321, 5, 85, 16266, 40, 600, 15, 9322, -1), - (9324, 9324, 9324, 9324, 9324, 5, 85, 16267, 40, 600, 15, -1, 9325), - (9325, 9324, 9324, 9324, 9324, 5, 85, 16268, 40, 600, 15, 9324, 9326), - (9326, 9324, 9324, 9324, 9324, 5, 85, 16269, 40, 600, 15, 9325, -1), - (9327, 9327, 9327, 9327, 9327, 5, 85, 16270, 40, 600, 15, -1, 9328), - (9328, 9327, 9327, 9327, 9327, 5, 85, 16271, 40, 600, 15, 9327, 9329), - (9329, 9327, 9327, 9327, 9327, 5, 85, 16272, 40, 600, 15, 9328, -1), - (9330, 9330, 9330, 9330, 9330, 5, 85, 16273, 40, 600, 15, -1, 9331), - (9331, 9330, 9330, 9330, 9330, 5, 85, 16274, 40, 600, 15, 9330, 9332), - (9332, 9330, 9330, 9330, 9330, 5, 85, 16275, 40, 600, 15, 9331, -1), - (9333, 9333, 9333, 9333, 9333, 5, 85, 16276, 40, 600, 15, -1, 9334), - (9334, 9333, 9333, 9333, 9333, 5, 85, 16277, 40, 600, 15, 9333, 9335), - (9335, 9333, 9333, 9333, 9333, 5, 85, 16278, 40, 600, 15, 9334, -1), - (9336, 9336, 9336, 9336, 9336, 5, 85, 16284, 40, 600, 15, -1, 9337), - (9337, 9336, 9336, 9336, 9336, 5, 85, 16285, 40, 600, 15, 9336, 9338), - (9338, 9336, 9336, 9336, 9336, 5, 85, 16286, 40, 600, 15, 9337, -1), - (9339, 9339, 9339, 9339, 9339, 5, 85, 16287, 40, 600, 15, -1, 9340), - (9340, 9339, 9339, 9339, 9339, 5, 85, 16288, 40, 600, 15, 9339, 9341), - (9341, 9339, 9339, 9339, 9339, 5, 85, 16289, 40, 600, 15, 9340, -1), - (9342, 9342, 9342, 9342, 9342, 5, 85, 16290, 40, 600, 15, -1, 9343), - (9343, 9342, 9342, 9342, 9342, 5, 85, 16291, 40, 600, 15, 9342, 9344), - (9344, 9342, 9342, 9342, 9342, 5, 85, 16292, 40, 600, 15, 9343, -1), - (9345, 9345, 9345, 9345, 9345, 5, 85, 16293, 40, 600, 15, -1, 9346), - (9346, 9345, 9345, 9345, 9345, 5, 85, 16294, 40, 600, 15, 9345, 9347), - (9347, 9345, 9345, 9345, 9345, 5, 85, 16295, 40, 600, 15, 9346, -1), - (9348, 9348, 9348, 9348, 9348, 5, 85, 16296, 40, 600, 15, -1, 9349), - (9349, 9348, 9348, 9348, 9348, 5, 85, 16297, 40, 600, 15, 9348, 9350), - (9350, 9348, 9348, 9348, 9348, 5, 85, 16298, 40, 600, 15, 9349, -1), - (9351, 9351, 9351, 9351, 9351, 5, 85, 16299, 40, 600, 15, -1, 9352), - (9352, 9351, 9351, 9351, 9351, 5, 85, 16300, 40, 600, 15, 9351, 9353), - (9353, 9351, 9351, 9351, 9351, 5, 85, 16301, 40, 600, 15, 9352, -1), - (9354, 9354, 9354, 9354, 9354, 5, 85, 16305, 40, 600, 15, -1, 9355), - (9355, 9354, 9354, 9354, 9354, 5, 85, 16306, 40, 600, 15, 9354, 9356), - (9356, 9354, 9354, 9354, 9354, 5, 85, 16307, 40, 600, 15, 9355, 12626), - (9357, 9357, 9357, 9357, 9357, 5, 85, 16308, 40, 600, 15, -1, 9358), - (9358, 9357, 9357, 9357, 9357, 5, 85, 16309, 40, 600, 15, 9357, 9359), - (9359, 9357, 9357, 9357, 9357, 5, 85, 16310, 40, 600, 15, 9358, 12629), - (9360, 9360, 9360, 9360, 9360, 5, 85, 16311, 40, 600, 15, -1, 9361), - (9361, 9360, 9360, 9360, 9360, 5, 85, 16312, 40, 600, 15, 9360, 9362), - (9362, 9360, 9360, 9360, 9360, 5, 85, 16313, 40, 600, 15, 9361, 12632), - (9363, 9363, 9363, 9363, 9363, 5, 85, 16317, 40, 600, 15, -1, 9364), - (9364, 9363, 9363, 9363, 9363, 5, 85, 16318, 40, 600, 15, 9363, 9365), - (9365, 9363, 9363, 9363, 9363, 5, 85, 16319, 40, 600, 15, 9364, -1), - (9366, 9366, 9366, 9366, 9366, 5, 85, 16320, 40, 600, 15, -1, 9367), - (9367, 9366, 9366, 9366, 9366, 5, 85, 16321, 40, 600, 15, 9366, 9368), - (9368, 9366, 9366, 9366, 9366, 5, 85, 16322, 40, 600, 15, 9367, -1), - (9369, 9369, 9369, 9369, 9369, 5, 85, 16323, 40, 600, 15, -1, 9370), - (9370, 9369, 9369, 9369, 9369, 5, 85, 16324, 40, 600, 15, 9369, 9371), - (9371, 9369, 9369, 9369, 9369, 5, 85, 16325, 40, 600, 15, 9370, -1), - (9372, 9372, 9372, 9372, 9372, 5, 85, 16326, 40, 600, 15, -1, 9373), - (9373, 9372, 9372, 9372, 9372, 5, 85, 16327, 40, 600, 15, 9372, 9374), - (9374, 9372, 9372, 9372, 9372, 5, 85, 16328, 40, 600, 15, 9373, -1), - (9375, 9375, 9375, 9375, 9375, 5, 85, 16329, 40, 600, 15, -1, 9376), - (9376, 9375, 9375, 9375, 9375, 5, 85, 16330, 40, 600, 15, 9375, 9377), - (9377, 9375, 9375, 9375, 9375, 5, 85, 16331, 40, 600, 15, 9376, -1), - (9378, 9378, 9378, 9378, 9378, 5, 85, 16332, 40, 600, 15, -1, 9379), - (9379, 9378, 9378, 9378, 9378, 5, 85, 16333, 40, 600, 15, 9378, 9380), - (9380, 9378, 9378, 9378, 9378, 5, 85, 16334, 40, 600, 15, 9379, -1), - (9381, 9381, 9381, 9381, 9381, 5, 85, 16335, 40, 600, 15, -1, 9382), - (9382, 9381, 9381, 9381, 9381, 5, 85, 16336, 40, 600, 15, 9381, 9383), - (9383, 9381, 9381, 9381, 9381, 5, 85, 16337, 40, 600, 15, 9382, -1), - (9384, 9384, 9384, 9384, 9384, 5, 85, 16338, 40, 600, 15, -1, 9385), - (9385, 9384, 9384, 9384, 9384, 5, 85, 16339, 40, 600, 15, 9384, 9386), - (9386, 9384, 9384, 9384, 9384, 5, 85, 16340, 40, 600, 15, 9385, -1), - (9387, 9387, 9387, 9387, 9387, 5, 85, 16341, 40, 600, 15, -1, 9388), - (9388, 9387, 9387, 9387, 9387, 5, 85, 16342, 40, 600, 15, 9387, 9389), - (9389, 9387, 9387, 9387, 9387, 5, 85, 16343, 40, 600, 15, 9388, -1), - (9390, 9390, 9390, 9390, 9390, 5, 85, 16344, 40, 600, 15, -1, 9391), - (9391, 9390, 9390, 9390, 9390, 5, 85, 16345, 40, 600, 15, 9390, 9392), - (9392, 9390, 9390, 9390, 9390, 5, 85, 16346, 40, 600, 15, 9391, -1), - (9393, 9393, 9393, 9393, 9393, 5, 85, 16347, 40, 600, 15, -1, 9394), - (9394, 9393, 9393, 9393, 9393, 5, 85, 16348, 40, 600, 15, 9393, 9395), - (9395, 9393, 9393, 9393, 9393, 5, 85, 16349, 40, 600, 15, 9394, -1), - (9396, 9396, 9396, 9396, 9396, 5, 85, 16350, 40, 600, 15, -1, 9397), - (9397, 9396, 9396, 9396, 9396, 5, 85, 16351, 40, 600, 15, 9396, 9398), - (9398, 9396, 9396, 9396, 9396, 5, 85, 16352, 40, 600, 15, 9397, -1), - (9399, 9399, 9399, 9399, 9399, 5, 85, 16359, 40, 600, 15, -1, 9400), - (9400, 9399, 9399, 9399, 9399, 5, 85, 16360, 40, 600, 15, 9399, 9401), - (9401, 9399, 9399, 9399, 9399, 5, 85, 16361, 40, 600, 15, 9400, -1), - (9402, 9402, 9402, 9402, 9402, 5, 85, 16362, 40, 600, 15, -1, 9403), - (9403, 9402, 9402, 9402, 9402, 5, 85, 16363, 40, 600, 15, 9402, 9404), - (9404, 9402, 9402, 9402, 9402, 5, 85, 16364, 40, 600, 15, 9403, -1), - (9405, 9405, 9405, 9405, 9405, 5, 85, 16365, 40, 600, 15, -1, 9406), - (9406, 9405, 9405, 9405, 9405, 5, 85, 16366, 40, 600, 15, 9405, 9407), - (9407, 9405, 9405, 9405, 9405, 5, 85, 16367, 40, 600, 15, 9406, -1), - (9408, 9408, 9408, 9408, 9408, 5, 85, 16368, 40, 600, 15, -1, 9409), - (9409, 9408, 9408, 9408, 9408, 5, 85, 16369, 40, 600, 15, 9408, 9410), - (9410, 9408, 9408, 9408, 9408, 5, 85, 16370, 40, 600, 15, 9409, -1), - (9411, 9411, 9411, 9411, 9411, 5, 85, 16371, 40, 600, 15, -1, 9412), - (9412, 9411, 9411, 9411, 9411, 5, 85, 16372, 40, 600, 15, 9411, 9413), - (9413, 9411, 9411, 9411, 9411, 5, 85, 16373, 40, 600, 15, 9412, -1), - (9414, 9414, 9414, 9414, 9414, 5, 85, 16374, 40, 600, 15, -1, 9415), - (9415, 9414, 9414, 9414, 9414, 5, 85, 16375, 40, 600, 15, 9414, 9416), - (9416, 9414, 9414, 9414, 9414, 5, 85, 16376, 40, 600, 15, 9415, -1), - (9417, 9417, 9417, 9417, 9417, 5, 85, 16377, 40, 600, 15, -1, 9418), - (9418, 9417, 9417, 9417, 9417, 5, 85, 16378, 40, 600, 15, 9417, 9419), - (9419, 9417, 9417, 9417, 9417, 5, 85, 16379, 40, 600, 15, 9418, -1), - (9420, 9420, 9420, 9420, 9420, 5, 85, 16380, 40, 600, 15, -1, 9421), - (9421, 9420, 9420, 9420, 9420, 5, 85, 16381, 40, 600, 15, 9420, 9422), - (9422, 9420, 9420, 9420, 9420, 5, 85, 16382, 40, 600, 15, 9421, -1), - (9423, 9423, 9423, 9423, 9423, 5, 85, 16386, 40, 600, 15, -1, 9424), - (9424, 9423, 9423, 9423, 9423, 5, 85, 16387, 40, 600, 15, 9423, 9425), - (9425, 9423, 9423, 9423, 9423, 5, 85, 16388, 40, 600, 15, 9424, -1), - (9426, 9426, 9426, 9426, 9426, 5, 85, 16389, 40, 600, 15, -1, 9427), - (9427, 9426, 9426, 9426, 9426, 5, 85, 16390, 40, 600, 15, 9426, 9428), - (9428, 9426, 9426, 9426, 9426, 5, 85, 16391, 40, 600, 15, 9427, -1), - (9429, 9429, 9429, 9429, 9429, 5, 85, 16392, 40, 600, 15, -1, 9430), - (9430, 9429, 9429, 9429, 9429, 5, 85, 16393, 40, 600, 15, 9429, 9431), - (9431, 9429, 9429, 9429, 9429, 5, 85, 16394, 40, 600, 15, 9430, -1), - (9432, 9432, 9432, 9432, 9432, 5, 85, 16395, 40, 600, 15, -1, 9433), - (9433, 9432, 9432, 9432, 9432, 5, 85, 16396, 40, 600, 15, 9432, 9434), - (9434, 9432, 9432, 9432, 9432, 5, 85, 16397, 40, 600, 15, 9433, -1), - (9435, 9435, 9435, 9435, 9435, 5, 85, 16398, 40, 600, 15, -1, 9436), - (9436, 9435, 9435, 9435, 9435, 5, 85, 16399, 40, 600, 15, 9435, 9437), - (9437, 9435, 9435, 9435, 9435, 5, 85, 16400, 40, 600, 15, 9436, -1), - (9438, 9438, 9438, 9438, 9438, 5, 85, 16401, 40, 600, 15, -1, 9439), - (9439, 9438, 9438, 9438, 9438, 5, 85, 16402, 40, 600, 15, 9438, 9440), - (9440, 9438, 9438, 9438, 9438, 5, 85, 16403, 40, 600, 15, 9439, -1), - (9441, 9441, 9441, 9441, 9441, 5, 85, 16404, 40, 600, 15, -1, 9442), - (9442, 9441, 9441, 9441, 9441, 5, 85, 16405, 40, 600, 15, 9441, 9443), - (9443, 9441, 9441, 9441, 9441, 5, 85, 16406, 40, 600, 15, 9442, -1), - (9500, 9500, 9500, 9500, 9500, 3, 76, 16247, 47, 60, 15, -1, -1), - (9501, 9501, 9501, 9501, 9501, 9, 85, 16247, 47, 600, 15, -1, -1), - (9502, 9502, 9502, 9502, 9502, 7, 81, 16248, 48, 3600, 15, -1, -1), - (9503, -1, -1, 9503, 9503, 7, 83, -1, 0, 0, 15, -1, 9504), - (9504, -1, -1, 9503, 9503, 7, 84, -1, 0, 0, 15, 9503, 9505), - (9505, -1, -1, 9503, 9503, 7, 85, -1, 0, 0, 15, 9504, 10087), - (9506, -1, -1, 9506, 9506, 7, 81, -1, 0, 0, 15, -1, 9507), - (9507, -1, -1, 9506, 9506, 7, 83, -1, 0, 0, 15, 9506, 9508), - (9508, -1, -1, 9506, 9506, 7, 85, -1, 0, 0, 15, 9507, 13630), - (9509, -1, -1, 9509, 9509, 7, 81, -1, 0, 0, 15, -1, 9510), - (9510, -1, -1, 9509, 9509, 7, 82, -1, 0, 0, 15, 9509, 9511), - (9511, -1, -1, 9509, 9509, 7, 83, -1, 0, 0, 15, 9510, 9515), - (9512, -1, -1, 9512, 9512, 7, 81, -1, 0, 0, 15, -1, 9513), - (9513, -1, -1, 9512, 9512, 7, 82, -1, 0, 0, 15, 9512, 9514), - (9514, -1, -1, 9512, 9512, 7, 83, -1, 0, 0, 15, 9513, 7819), - (9515, -1, -1, 9509, 9509, 7, 86, -1, 0, 0, 17, 9511, 16361), - (10003, 6610, 6610, 6610, 6610, 5, 60, 16494, 41, 30, 16, 6610, 10573), - (10004, -1, -1, 6614, 6614, 6, 70, -1, 0, 0, 16, 6616, 10005), - (10005, -1, -1, 6614, 6614, 9, 70, -1, 0, 0, 16, 10004, 10575), - (10006, 54006, 54006, 54006, 54006, 7, 85, 16495, 18, 180, 16, 7111, 13425), - (10007, -1, -1, 6564, 6564, 10, 85, -1, 0, 0, 16, 7114, 10008), - (10008, -1, -1, 6564, 6564, 10, 85, -1, 0, 0, 16, 10007, 10009), - (10009, -1, -1, 6564, 6564, 10, 85, -1, 0, 0, 16, 10008, 10568), - (10010, 6565, 6565, 6565, 6565, 7, 85, 16496, 17, 45, 16, 7115, 10517), - (10011, 912, 912, 912, 912, 9, 80, 16497, 4, 3600, 16, 7121, 10012), - (10012, 912, 912, 912, 912, 9, 80, 16498, 4, 3600, 16, 10011, 10013), - (10013, 912, 912, 912, 912, 9, 80, 16499, 4, 3600, 16, 10012, 10585), - (10014, 1383, 1383, 1383, 1383, 12, 85, 21766, 6, 300, 16, 7299, 6487), - (10015, 1195, 1195, 1195, 1195, 9, 85, 16504, 13, 2160, 16, 7300, 13259), - (10016, 131, 131, 131, 131, 10, 85, 16505, 4, 900, 16, 7303, 10017), - (10017, 131, 131, 131, 131, 10, 85, 16506, 4, 900, 16, 10016, 10018), - (10018, 131, 131, 131, 131, 10, 85, 16507, 4, 900, 16, 10017, 7770), - (10019, 1192, 1192, 1192, 1192, 10, 85, 20177, 12, 1320, 16, 7306, 10020), - (10020, 1192, 1192, 1192, 1192, 10, 85, 21652, 12, 1320, 16, 10019, 10021), - (10021, 1192, 1192, 1192, 1192, 10, 85, 21704, 12, 1320, 16, 10020, 13363), - (10022, 746, 746, 746, 746, 12, 85, 16511, 10, 2160, 16, 7309, 10023), - (10023, 746, 746, 746, 746, 12, 85, 16512, 10, 2160, 16, 10022, 10024), - (10024, 746, 746, 746, 746, 12, 85, 16513, 10, 2160, 16, 10023, 15321), - (10025, -1, -1, 6601, 6601, 6, 85, -1, 0, 0, 16, 7322, 10026), - (10026, -1, -1, 6601, 6601, 6, 85, -1, 0, 0, 16, 10025, 10027), - (10027, -1, -1, 6601, 6601, 6, 85, -1, 0, 0, 16, 10026, 10028), - (10028, -1, -1, 6601, 6601, 6, 85, -1, 0, 0, 16, 10027, 10029), - (10029, -1, -1, 6601, 6601, 6, 85, -1, 0, 0, 16, 10028, 10437), - (10030, -1, -1, 7940, 7940, 5, 75, -1, 0, 0, 16, 7942, 10031), - (10031, -1, -1, 7940, 7940, 7, 75, -1, 0, 0, 16, 10030, 10032), - (10032, -1, -1, 7940, 7940, 9, 75, -1, 0, 0, 16, 10031, 6484), - (10033, -1, -1, 7945, 7945, 6, 85, -1, 0, 0, 16, 7947, 10034), - (10034, -1, -1, 7945, 7945, 6, 85, -1, 0, 0, 16, 10033, 10347), - (10035, -1, -1, 7948, 7948, 6, 85, -1, 0, 0, 16, 7950, 10036), - (10036, -1, -1, 7948, 7948, 6, 85, -1, 0, 0, 16, 10035, 10037), - (10037, -1, -1, 7948, 7948, 6, 85, -1, 0, 0, 16, 10036, 15328), - (10038, 7951, 7951, 7951, 7951, 6, 85, 16514, 61, 900, 16, 7953, 10039), - (10039, 7951, 7951, 7951, 7951, 6, 85, 16515, 61, 900, 16, 10038, 10040), - (10040, 7951, 7951, 7951, 7951, 6, 85, 16516, 61, 900, 16, 10039, 7773), - (10041, -1, -1, 6636, 6636, 9, 75, -1, 0, 0, 16, 6638, 10042), - (10042, -1, -1, 6636, 6636, 10, 75, -1, 0, 0, 16, 10041, 10043), - (10043, -1, -1, 6636, 6636, 11, 75, -1, 0, 0, 16, 10042, 12529), - (10044, -1, -1, 6791, 6791, 6, 85, -1, 0, 0, 16, 6793, 10045), - (10045, -1, -1, 6791, 6791, 6, 85, -1, 0, 0, 16, 10044, 10046), - (10046, -1, -1, 6791, 6791, 6, 85, -1, 0, 0, 16, 10045, 10676), - (10047, 534, 534, 534, 534, 12, 85, 16561, 4, 2160, 16, 7331, 10048), - (10048, 534, 534, 534, 534, 12, 85, 16562, 4, 2160, 16, 10047, 10049), - (10049, 534, 534, 534, 534, 12, 85, 16563, 4, 2160, 16, 10048, 10708), - (10050, -1, -1, 6395, 6395, 7, 85, -1, 0, 0, 16, 7338, 10051), - (10051, -1, -1, 6395, 6395, 7, 85, -1, 0, 0, 16, 10050, 10052), - (10052, -1, -1, 6395, 6395, 7, 85, -1, 0, 0, 16, 10051, 10705), - (10053, 6754, 6754, 6754, 6754, 9, 75, 16570, 41, 1200, 16, 6754, 14111), - (10054, 6758, 6758, 6758, 6758, 10, 85, 16571, 43, 900, 16, 6760, 10055), - (10055, 6758, 6758, 6758, 6758, 11, 85, 16572, 43, 900, 16, 10054, 10056), - (10056, 6758, 6758, 6758, 6758, 12, 85, 16573, 43, 900, 16, 10055, 13546), - (10057, 6764, 6764, 6764, 6764, 9, 80, 16574, 52, 600, 16, 6764, 16716), - (10058, -1, -1, 6765, 6765, 9, 85, -1, 0, 0, 16, 6767, 10059), - (10059, -1, -1, 6765, 6765, 9, 85, -1, 0, 0, 16, 10058, 10060), - (10060, -1, -1, 6765, 6765, 9, 85, -1, 0, 0, 16, 10059, 10766), - (10061, 5007, 5007, 5007, 5007, 9, 85, 16575, 8, 2160, 16, 7343, 10062), - (10062, 5007, 5007, 5007, 5007, 9, 85, 16576, 8, 2160, 16, 10061, 10063), - (10063, 5007, 5007, 5007, 5007, 9, 85, 16577, 8, 2160, 16, 10062, 13119), - (10064, -1, -1, 1608, 1608, 6, 85, -1, 0, 0, 16, 7383, 10065), - (10065, -1, -1, 1608, 1608, 7, 85, -1, 0, 0, 16, 10064, 10066), - (10066, -1, -1, 1608, 1608, 8, 85, -1, 0, 0, 16, 10065, 10067), - (10067, -1, -1, 1608, 1608, 9, 85, -1, 0, 0, 16, 10066, 10068), - (10068, -1, -1, 1608, 1608, 10, 85, -1, 0, 0, 16, 10067, 10069), - (10069, -1, -1, 1608, 1608, 11, 85, -1, 0, 0, 16, 10068, 16730), - (10070, -1, -1, 6630, 6630, 6, 75, -1, 0, 0, 16, 6634, 10071), - (10071, -1, -1, 6630, 6630, 6, 75, -1, 0, 0, 16, 10070, 10072), - (10072, -1, -1, 6630, 6630, 6, 75, -1, 0, 0, 16, 10071, 10073), - (10073, -1, -1, 6630, 6630, 6, 75, -1, 0, 0, 16, 10072, 10074), - (10074, -1, -1, 6630, 6630, 6, 75, -1, 0, 0, 16, 10073, 13621), - (10075, -1, -1, 6641, 6641, 9, 85, -1, 0, 0, 16, 6643, 10076), - (10076, -1, -1, 6641, 6641, 9, 85, -1, 0, 0, 16, 10075, 10077), - (10077, -1, -1, 6641, 6641, 9, 85, -1, 0, 0, 16, 10076, 16192), - (10078, 6508, 6508, 6508, 6508, 7, 85, 16578, 38, 600, 16, 7389, 10079), - (10079, 6508, 6508, 6508, 6508, 7, 85, 16579, 38, 600, 16, 10078, 10080), - (10080, 6508, 6508, 6508, 6508, 7, 85, 16580, 38, 600, 16, 10079, 15775), - (10081, -1, -1, 1313, 1313, 12, 85, -1, 0, 0, 16, 7398, 10082), - (10082, -1, -1, 1313, 1313, 12, 85, -1, 0, 0, 16, 10081, 10083), - (10083, -1, -1, 1313, 1313, 12, 85, -1, 0, 0, 16, 10082, 12579), - (10084, -1, -1, 6375, 6375, 6, 85, -1, 0, 0, 16, 7663, 10085), - (10085, -1, -1, 6375, 6375, 6, 85, -1, 0, 0, 16, 10084, 10086), - (10086, -1, -1, 6375, 6375, 6, 85, -1, 0, 0, 16, 10085, 5347), - (10087, -1, -1, 9503, 9503, 7, 85, -1, 0, 0, 16, 9505, 10088), - (10088, -1, -1, 9503, 9503, 7, 85, -1, 0, 0, 16, 10087, 10089), - (10089, -1, -1, 9503, 9503, 7, 85, -1, 0, 0, 16, 10088, 12792), - (10090, 1498, 1498, 1498, 1498, 12, 85, 16590, 12, 1320, 16, 7410, 10091), - (10091, 1498, 1498, 1498, 1498, 12, 85, 16591, 12, 1320, 16, 10090, 10092), - (10092, 1498, 1498, 1498, 1498, 12, 85, 16602, 12, 1320, 16, 10091, 13401), - (10093, 1495, 1495, 1495, 1495, 9, 86, 16603, 30, 900, 17, 7416, 10094), - (10096, 548, 548, 548, 548, 10, 85, 16606, 5, 900, 16, 7419, 10097), - (10097, 548, 548, 548, 548, 10, 85, 16607, 5, 900, 16, 10096, 10098), - (10098, 548, 548, 548, 548, 10, 85, 16608, 5, 900, 16, 10097, 13158), - (10099, 6561, 6561, 6561, 6561, 7, 85, 16609, 32, 30, 16, 7424, 10100), - (10100, 6561, 6561, 6561, 6561, 7, 85, 16610, 32, 30, 16, 10099, 10101), - (10101, 6561, 6561, 6561, 6561, 7, 85, 16611, 32, 30, 16, 10100, 10418), - (10102, 510, 510, 510, 510, 3, 75, 16587, 37, 240, 16, 7427, 10103), - (10103, 510, 510, 510, 510, 3, 75, 16588, 37, 240, 16, 10102, 10104), - (10104, 510, 510, 510, 510, 3, 75, 16589, 37, 240, 16, 10103, 10824), - (10105, -1, -1, 7664, 7664, 2, 82, -1, 0, 0, 16, 7668, 10106), - (10106, -1, -1, 7664, 7664, 2, 82, -1, 0, 0, 16, 10105, 10107), - (10107, -1, -1, 7664, 7664, 2, 82, -1, 0, 0, 16, 10106, 10108), - (10108, -1, -1, 7664, 7664, 2, 82, -1, 0, 0, 16, 10107, 10109), - (10109, -1, -1, 7664, 7664, 2, 82, -1, 0, 0, 16, 10108, 17350), - (10110, -1, -1, 7983, 7983, 6, 81, -1, 0, 0, 16, 7985, 10111), - (10111, -1, -1, 7983, 7983, 6, 81, -1, 0, 0, 16, 10110, 10112), - (10112, -1, -1, 7983, 7983, 6, 81, -1, 0, 0, 16, 10111, -1), - (10113, 1352, 1352, 1352, 1352, 6, 85, 16618, 3, 60, 16, 7156, 10114), - (10114, 1352, 1352, 1352, 1352, 6, 85, 16619, 3, 60, 16, 10113, 10115), - (10115, 1352, 1352, 1352, 1352, 6, 85, 16620, 3, 60, 16, 10114, 13807), - (10116, 1358, 1358, 1358, 1358, 6, 85, 16615, 3, 60, 16, 7159, 10117), - (10117, 1358, 1358, 1358, 1358, 6, 85, 16616, 3, 60, 16, 10116, 10118), - (10118, 1358, 1358, 1358, 1358, 6, 85, 16617, 3, 60, 16, 10117, 13810), - (10119, 1355, 1355, 1355, 1355, 6, 85, 16612, 3, 60, 16, 7174, 10120), - (10120, 1355, 1355, 1355, 1355, 6, 85, 16613, 3, 60, 16, 10119, 10121), - (10121, 1355, 1355, 1355, 1355, 6, 85, 16614, 3, 60, 16, 10120, 12700), - (10122, -1, -1, 4801, 4801, 6, 85, -1, 0, 0, 16, 7162, 10123), - (10123, -1, -1, 4801, 4801, 6, 85, -1, 0, 0, 16, 10122, 12674), - (10124, -1, -1, 611, 611, 2, 75, -1, 0, 0, 16, 7177, 10125), - (10125, -1, -1, 611, 611, 2, 75, -1, 0, 0, 16, 10124, 10126), - (10126, -1, -1, 611, 611, 2, 75, -1, 0, 0, 16, 10125, 12703), - (10127, 7872, 7872, 7872, 7872, 6, 85, 16621, 41, 600, 16, 7874, 10128), - (10128, 7872, 7872, 7872, 7872, 6, 85, 16622, 41, 600, 16, 10127, 10129), - (10129, 7872, 7872, 7872, 7872, 6, 85, 16623, 41, 600, 16, 10128, 12682), - (10130, -1, -1, 6870, 6870, 6, 80, -1, 0, 0, 16, 6872, 10131), - (10131, -1, -1, 6870, 6870, 6, 80, -1, 0, 0, 16, 10130, 10132), - (10132, -1, -1, 6870, 6870, 6, 80, -1, 0, 0, 16, 10131, -1), - (10133, -1, -1, 255, 255, 9, 80, -1, 0, 0, 16, 6875, 10134), - (10134, -1, -1, 255, 255, 9, 80, -1, 0, 0, 16, 10133, 10135), - (10135, -1, -1, 255, 255, 9, 80, -1, 0, 0, 16, 10134, 13196), - (10136, -1, -1, 6375, 6375, 6, 83, -1, 0, 0, 16, 6878, 10137), - (10137, -1, -1, 6375, 6375, 6, 83, -1, 0, 0, 16, 10136, 10138), - (10138, -1, -1, 6375, 6375, 6, 83, -1, 0, 0, 16, 10137, 12734), - (10139, 6533, 6533, 6533, 6533, 10, 85, 16631, 15, 600, 16, 7428, 12740), - (10140, 1116, 1116, 1116, 1116, 12, 85, 16647, 4, 2160, 16, 7432, 10141), - (10141, 1116, 1116, 1116, 1116, 12, 85, 16648, 4, 2160, 16, 10140, 10142), - (10142, 1116, 1116, 1116, 1116, 12, 85, 16649, 4, 2160, 16, 10141, 12743), - (10143, 5298, 5298, 5298, 5298, 12, 85, 16632, 32, 1800, 16, 7440, 10144), - (10144, 5298, 5298, 5298, 5298, 12, 85, 16633, 32, 1800, 16, 10143, 10145), - (10145, 5298, 5298, 5298, 5298, 12, 85, 16634, 32, 1800, 16, 10144, 12746), - (10146, 1598, -1, 1598, 1598, 12, 85, 16638, 6, 900, 16, 7443, 10147), - (10147, 1598, -1, 1598, 1598, 12, 85, 16639, 6, 900, 16, 10146, 10148), - (10148, 1598, -1, 1598, 1598, 12, 85, 16640, 6, 900, 16, 10147, 13193), - (10149, 5020, 5020, 5020, 5020, 9, 85, 16630, 9, 300, 16, 7444, 13490), - (10150, 1110, 1110, 1110, 1110, 6, 85, 16641, 3, 2160, 16, 7447, 10151), - (10151, 1110, 1110, 1110, 1110, 6, 85, 16642, 3, 2160, 16, 10150, 10152), - (10152, 1110, 1110, 1110, 1110, 6, 85, 16643, 3, 2160, 16, 10151, 13190), - (10153, -1, -1, 6337, 6337, 6, 85, -1, 0, 0, 16, 7450, 10154), - (10154, -1, -1, 6337, 6337, 6, 85, -1, 0, 0, 16, 10153, 10155), - (10155, -1, -1, 6337, 6337, 6, 85, -1, 0, 0, 16, 10154, 16297), - (10156, 5017, 5017, 5017, 5017, 9, 85, 16627, 8, 600, 16, 7456, 10157), - (10157, 5017, 5017, 5017, 5017, 9, 85, 16628, 8, 600, 16, 10156, 10158), - (10158, 5017, 5017, 5017, 5017, 9, 85, 16629, 8, 600, 16, 10157, 14189), - (10159, 1569, 1569, 1569, 1569, 7, 85, 16624, 5, 1800, 16, 7459, 10160), - (10160, 1569, 1569, 1569, 1569, 7, 85, 16625, 5, 1800, 16, 10159, 10161), - (10161, 1569, 1569, 1569, 1569, 7, 85, 16626, 5, 1800, 16, 10160, 17276), - (10162, 6663, 6663, 6663, 6663, 7, 82, 16653, 59, 600, 16, 6665, 10163), - (10163, 6663, 6663, 6663, 6663, 7, 82, 16654, 59, 600, 16, 10162, 10164), - (10164, 6663, 6663, 6663, 6663, 7, 82, 16655, 59, 600, 16, 10163, -1), - (10165, -1, -1, 1543, 1543, 12, 85, -1, 0, 0, 16, 7136, 10166), - (10166, -1, -1, 1543, 1543, 12, 85, -1, 0, 0, 16, 10165, 10167), - (10167, -1, -1, 1543, 1543, 12, 85, -1, 0, 0, 16, 10166, 13213), - (10168, 6328, 6328, 6328, 6328, 7, 85, 16650, 10, 600, 16, 7145, 10169), - (10169, 6328, 6328, 6328, 6328, 7, 85, 16651, 10, 600, 16, 10168, 10170), - (10170, 6328, 6328, 6328, 6328, 7, 85, 16652, 10, 600, 16, 10169, 13770), - (10171, -1, -1, 878, 878, 7, 85, -1, 0, 0, 16, 7147, 10172), - (10172, -1, -1, 878, 878, 7, 85, -1, 0, 0, 16, 10171, -1), - (10173, -1, -1, 846, 846, 12, 85, -1, 0, 0, 16, 7153, 10174), - (10174, -1, -1, 846, 846, 12, 85, -1, 0, 0, 16, 10173, 10175), - (10175, -1, -1, 846, 846, 12, 85, -1, 0, 0, 16, 10174, 13795), - (10176, -1, -1, 6703, 6703, 3, 70, -1, 0, 0, 16, 6705, 10177), - (10177, -1, -1, 6703, 6703, 3, 70, -1, 0, 0, 16, 10176, 10178), - (10178, -1, -1, 6703, 6703, 3, 70, -1, 0, 0, 16, 10177, 13005), - (10179, 6706, 6706, 6706, 6706, 7, 85, 16675, 44, 600, 16, 6708, 10180), - (10180, 6706, 6706, 6706, 6706, 7, 85, 16676, 44, 600, 16, 10179, 10181), - (10181, 6706, 6706, 6706, 6706, 7, 85, 16677, 44, 600, 16, 10180, 5353), - (10182, -1, -1, 6712, 6712, 7, 85, -1, 0, 0, 16, 6716, 10183), - (10183, -1, -1, 6712, 6712, 7, 85, -1, 0, 0, 16, 10182, 10184), - (10184, -1, -1, 6712, 6712, 7, 85, -1, 0, 0, 16, 10183, 10185), - (10185, -1, -1, 6712, 6712, 7, 85, -1, 0, 0, 16, 10184, 10186), - (10186, -1, -1, 6712, 6712, 7, 85, -1, 0, 0, 16, 10185, -1), - (10187, 1327, 1327, 1327, 1327, 12, 85, 16665, 10, 900, 16, 7462, 10188), - (10188, 1327, 1327, 1327, 1327, 12, 85, 16666, 10, 900, 16, 10187, 10189), - (10189, 1327, 1327, 1327, 1327, 12, 85, 16667, 10, 900, 16, 10188, 5330), - (10190, 1520, 1520, 1520, 1520, 9, 80, 16672, 11, 900, 16, 7465, 10191), - (10191, 1520, 1520, 1520, 1520, 9, 80, 16673, 11, 900, 16, 10190, 10192), - (10192, 1520, 1520, 1520, 1520, 9, 80, 16674, 11, 900, 16, 10191, 12997), - (10193, 153, 153, 153, 153, 12, 85, 16668, 3, 2160, 16, 7468, 11081), - (10194, 528, 528, 528, 528, 12, 85, 16669, 5, 720, 16, 7471, 10195), - (10195, 528, 528, 528, 528, 12, 85, 16670, 5, 720, 16, 10194, 10196), - (10196, 528, 528, 528, 528, 12, 85, 16671, 5, 720, 16, 10195, 13161), - (10197, 5251, 5251, 5251, 5251, 12, 85, 16662, 13, 900, 16, 7474, 10198), - (10198, 5251, 5251, 5251, 5251, 12, 85, 16663, 13, 900, 16, 10197, 10199), - (10199, 5251, 5251, 5251, 5251, 12, 85, 16664, 13, 900, 16, 10198, 5363), - (10200, 6815, 6815, 6815, 6815, 8, 85, 16691, 60, 600, 16, 6817, 10201), - (10201, 6815, 6815, 6815, 6815, 8, 85, 16692, 60, 600, 16, 10200, 10202), - (10202, 6815, 6815, 6815, 6815, 8, 85, 16693, 60, 600, 16, 10201, 12786), - (10203, -1, -1, 6819, 6819, 6, 77, -1, 0, 0, 16, 6821, 10204), - (10204, -1, -1, 6819, 6819, 6, 77, -1, 0, 0, 16, 10203, 10205), - (10205, -1, -1, 6819, 6819, 6, 77, -1, 0, 0, 16, 10204, -1), - (10206, -1, -1, 6823, 6823, 4, 75, -1, 0, 0, 16, 6827, 10207), - (10207, -1, -1, 6823, 6823, 4, 77, -1, 0, 0, 16, 10206, -1), - (10208, 6828, 6828, 6828, 6828, 12, 85, 16686, 43, 60, 16, 6828, 17534), - (10209, 1274, 1274, 1274, 1274, 12, 85, 16683, 9, 540, 16, 7201, 10210), - (10210, 1274, 1274, 1274, 1274, 12, 85, 16684, 9, 540, 16, 10209, 10211), - (10211, 1274, 1274, 1274, 1274, 12, 85, 16685, 9, 540, 16, 10210, 12760), - (10212, 1510, -1, 1510, 1510, 12, 80, 16690, 13, 2160, 16, 7202, -1), - (10213, -1, -1, 5264, 5264, 12, 85, -1, 0, 0, 16, 7208, 10214), - (10214, -1, -1, 5264, 5264, 12, 85, -1, 0, 0, 16, 10213, 10215), - (10215, -1, -1, 5264, 5264, 12, 85, -1, 0, 0, 16, 10214, 10216), - (10216, -1, -1, 5264, 5264, 12, 85, -1, 0, 0, 16, 10215, 10217), - (10217, -1, -1, 5264, 5264, 12, 85, -1, 0, 0, 16, 10216, 12798), - (10218, 4927, 4927, 4927, 4927, 9, 85, 16682, 14, 600, 16, 7209, -1), - (10219, -1, -1, 839, 839, 6, 80, -1, 0, 0, 16, 7214, 10220), - (10220, -1, -1, 839, 839, 6, 80, -1, 0, 0, 16, 10219, 10221), - (10221, -1, -1, 839, 839, 6, 80, -1, 0, 0, 16, 10220, 10222), - (10222, -1, -1, 839, 839, 6, 80, -1, 0, 0, 16, 10221, 10223), - (10223, -1, -1, 839, 839, 6, 80, -1, 0, 0, 16, 10222, -1), - (10224, 967, 967, 967, 967, 6, 85, 16687, 10, 1800, 16, 7219, 10225), - (10225, 967, 967, 967, 967, 6, 85, 16688, 10, 1800, 16, 10224, 10226), - (10226, 967, 967, 967, 967, 6, 85, 16689, 10, 1800, 16, 10225, 12789), - (10227, -1, -1, 5295, 5295, 6, 85, -1, 0, 0, 16, 7222, 10228), - (10228, -1, -1, 5295, 5295, 6, 85, -1, 0, 0, 16, 10227, 10229), - (10229, -1, -1, 5295, 5295, 6, 85, -1, 0, 0, 16, 10228, 13226), - (10230, 619, 619, 619, 619, 6, 83, 16704, 6, 900, 16, 7228, 10231), - (10231, 619, 619, 619, 619, 6, 83, 16705, 6, 900, 16, 10230, 10232), - (10232, 619, 619, 619, 619, 6, 83, 16706, 6, 900, 16, 10231, -1), - (10233, 516, 516, 516, 516, 6, 82, 16707, 5, 480, 16, 7237, 12879), - (10234, 1334, 1334, 1334, 1334, 12, 85, 16701, 11, 4320, 16, 7241, 10235), - (10235, 1334, 1334, 1334, 1334, 12, 85, 16702, 11, 4320, 16, 10234, 10236), - (10236, 1334, 1334, 1334, 1334, 12, 85, 16703, 11, 4320, 16, 10235, 12868), - (10237, 8060, 8060, 8060, 8060, 7, 85, 16711, 41, 1800, 16, 8062, 10238), - (10238, 8060, 8060, 8060, 8060, 7, 85, 16712, 41, 1800, 16, 10237, 10239), - (10239, 8060, 8060, 8060, 8060, 7, 85, 16713, 41, 1800, 16, 10238, 13650), - (10240, 8063, 8063, 8063, 8063, 7, 85, 16714, 41, 1800, 16, 8065, 10241), - (10241, 8063, 8063, 8063, 8063, 7, 85, 16715, 41, 1800, 16, 10240, 10242), - (10242, 8063, 8063, 8063, 8063, 7, 85, 16716, 41, 1800, 16, 10241, 13653), - (10243, 8066, 8066, 8066, 8066, 7, 85, 16717, 41, 1800, 16, 8068, 10244), - (10244, 8066, 8066, 8066, 8066, 7, 85, 16718, 41, 1800, 16, 10243, 10245), - (10245, 8066, 8066, 8066, 8066, 7, 85, 16719, 41, 1800, 16, 10244, 13656), - (10246, 8072, 8072, 8072, 8072, 7, 80, 16708, 37, 20, 16, 8074, 10247), - (10247, 8072, 8072, 8072, 8072, 7, 80, 16709, 37, 20, 16, 10246, 10248), - (10248, 8072, 8072, 8072, 8072, 7, 80, 16710, 37, 20, 16, 10247, 12857), - (10249, -1, -1, 8082, 8082, 3, 74, -1, 0, 0, 16, 8084, 10250), - (10250, -1, -1, 8082, 8082, 3, 74, -1, 0, 0, 16, 10249, 10251), - (10251, -1, -1, 8082, 8082, 3, 74, -1, 0, 0, 16, 10250, -1), - (10252, 520, 520, 520, 520, 12, 85, 16723, 6, 540, 16, 7252, 10253), - (10253, 520, 520, 520, 520, 12, 85, 16724, 6, 540, 16, 10252, 10254), - (10254, 520, 520, 520, 520, 12, 85, 16725, 6, 540, 16, 10253, 12985), - (10255, 4903, 4903, 4903, 4903, 9, 81, 16726, 9, 1320, 16, 7253, 12956), - (10256, 4906, 4906, 4906, 4906, 9, 81, 16727, 9, 1320, 16, 7254, 12959), - (10257, 4909, 4909, 4909, 4909, 9, 81, 16728, 16, 1320, 16, 7255, 12957), - (10258, 4912, 4912, 4912, 4912, 9, 81, 16729, 16, 1320, 16, 7256, 12958), - (10259, 616, 616, 616, 616, 10, 85, 16733, 7, 900, 16, 7259, 10260), - (10260, 616, 616, 616, 616, 10, 85, 16734, 7, 900, 16, 10259, 10261), - (10261, 616, 616, 616, 616, 10, 85, 16735, 7, 900, 16, 10260, 14730), - (10262, -1, -1, 1577, 1577, 12, 85, -1, 0, 0, 16, 7265, 10263), - (10263, -1, -1, 1577, 1577, 12, 85, -1, 0, 0, 16, 10262, 10264), - (10264, -1, -1, 1577, 1577, 12, 85, -1, 0, 0, 16, 10263, 13707), - (10265, -1, -1, 795, 795, 12, 85, -1, 0, 0, 16, 7269, 10266), - (10266, -1, -1, 795, 795, 12, 85, -1, 0, 0, 16, 10265, 10267), - (10267, -1, -1, 795, 795, 12, 85, -1, 0, 0, 16, 10266, 12945), - (10268, -1, -1, 7900, 7900, 4, 70, -1, 0, 0, 16, 7902, 10269), - (10269, -1, -1, 7900, 7900, 4, 70, -1, 0, 0, 16, 10268, 10270), - (10270, -1, -1, 7900, 7900, 4, 70, -1, 0, 0, 16, 10269, -1), - (10271, 1242, 1242, 1242, 1242, 12, 85, 16744, 9, 1320, 16, 7287, 10272), - (10272, 1242, 1242, 1242, 1242, 12, 85, 16745, 9, 1320, 16, 10271, 10273), - (10273, 1242, 1242, 1242, 1242, 12, 85, 16746, 9, 1320, 16, 10272, 12934), - (10274, 4931, 4931, 4931, 4931, 7, 85, 16747, 4, 600, 16, 7293, 10275), - (10275, 4931, 4931, 4931, 4931, 7, 85, 16748, 4, 600, 16, 10274, 10276), - (10276, 4931, 4931, 4931, 4931, 7, 85, 16749, 4, 600, 16, 10275, 10428), - (10277, 4935, 4935, 4935, 4935, 7, 81, 16743, 14, 300, 16, 7294, 17540), - (10278, 4934, 4934, 4934, 4934, 7, 81, 16742, 13, 300, 16, 7295, 17539), - (10279, 517, 517, 517, 517, 5, 80, 16739, 12, 600, 16, 7298, 10280), - (10280, 517, 517, 517, 517, 5, 80, 16740, 12, 600, 16, 10279, 10281), - (10281, 517, 517, 517, 517, 5, 80, 16741, 12, 600, 16, 10280, 12917), - (10282, -1, -1, 8031, 8031, 6, 84, -1, 0, 0, 16, 8033, 10283), - (10283, -1, -1, 8031, 8031, 6, 84, -1, 0, 0, 16, 10282, 10284), - (10284, -1, -1, 8031, 8031, 6, 84, -1, 0, 0, 16, 10283, 10431), - (10285, -1, -1, 8035, 8035, 6, 82, -1, 0, 0, 16, 8037, 10286), - (10286, -1, -1, 8035, 8035, 6, 82, -1, 0, 0, 16, 10285, 10287), - (10287, -1, -1, 8035, 8035, 6, 82, -1, 0, 0, 16, 10286, 15472), - (10288, 6971, 6971, 6971, 6971, 7, 85, 16761, 41, 600, 16, 6973, 10289), - (10289, 6971, 6971, 6971, 6971, 7, 85, 16762, 41, 600, 16, 10288, 10290), - (10290, 6971, 6971, 6971, 6971, 7, 85, 16763, 41, 600, 16, 10289, 14274), - (10291, -1, -1, 6974, 6974, 5, 85, -1, 0, 0, 16, 6976, 10292), - (10292, -1, -1, 6974, 6974, 5, 85, -1, 0, 0, 16, 10291, 10293), - (10293, -1, -1, 6974, 6974, 5, 85, -1, 0, 0, 16, 10292, -1), - (10294, 6984, 6984, 6984, 6984, 6, 78, 16765, 60, 60, 16, 6984, 13177), - (10295, 6985, 6985, 6985, 6985, 6, 78, 16766, 60, 60, 16, 6985, 13179), - (10296, 6986, 6986, 6986, 6986, 6, 78, 16767, 60, 60, 16, 6986, 13178), - (10297, 1119, 1119, 1119, 1119, 9, 85, 16750, 8, 900, 16, 7481, 10298), - (10298, 1119, 1119, 1119, 1119, 9, 85, 16751, 8, 900, 16, 10297, 10299), - (10299, 1119, 1119, 1119, 1119, 9, 85, 16752, 8, 900, 16, 10298, 16883), - (10300, 723, 723, 723, 723, 7, 85, 16753, 6, 30, 16, 7482, 14273), - (10301, 5015, 5015, 5015, 5015, 12, 85, 16754, 9, 900, 16, 7483, 17382), - (10302, 291, 291, 291, 291, 12, 85, 16755, 5, 900, 16, 7487, 10303), - (10303, 291, 291, 291, 291, 12, 85, 16756, 5, 900, 16, 10302, 10304), - (10304, 291, 291, 291, 291, 12, 85, 16757, 5, 900, 16, 10303, 12828), - (10305, -1, -1, 729, 729, 9, 85, -1, 0, 0, 16, 7496, 10306), - (10306, -1, -1, 729, 729, 9, 85, -1, 0, 0, 16, 10305, 10307), - (10307, -1, -1, 729, 729, 9, 85, -1, 0, 0, 16, 10306, 16887), - (10308, 6380, 6380, 6380, 6380, 6, 85, 16758, 39, 120, 16, 7499, 10309), - (10309, 6380, 6380, 6380, 6380, 6, 85, 16759, 39, 120, 16, 10308, 10310), - (10310, 6380, 6380, 6380, 6380, 6, 85, 16760, 39, 120, 16, 10309, 13170), - (10311, -1, -1, 1134, 1134, 3, 85, -1, 0, 0, 16, 4808, 10312), - (10312, -1, -1, 1134, 1134, 3, 85, -1, 0, 0, 16, 10311, 10313), - (10313, -1, -1, 1134, 1134, 3, 85, -1, 0, 0, 16, 10312, 10314), - (10314, -1, -1, 1134, 1134, 3, 85, -1, 0, 0, 16, 10313, 10315), - (10315, -1, -1, 1134, 1134, 3, 85, -1, 0, 0, 16, 10314, 13035), - (10316, -1, -1, 4809, 4809, 5, 85, -1, 0, 0, 16, 4811, 10317), - (10317, -1, -1, 4809, 4809, 5, 85, -1, 0, 0, 16, 10316, 10318), - (10318, -1, -1, 4809, 4809, 5, 85, -1, 0, 0, 16, 10317, 13040), - (10319, 6931, 6931, 6931, 6931, 12, 85, 16774, 41, 600, 16, 6931, 13058), - (10320, 6932, 6932, 6932, 6932, 7, 85, 16775, 42, 1200, 16, 6934, 10321), - (10321, 6932, 6932, 6932, 6932, 7, 85, 16776, 42, 1200, 16, 10320, 10322), - (10322, 6932, 6932, 6932, 6932, 7, 85, 16777, 42, 1200, 16, 10321, 13062), - (10323, 4854, 4854, 4854, 4854, 12, 85, 16768, 8, 600, 16, 7180, 10324), - (10324, 4854, 4854, 4854, 4854, 12, 85, 16769, 8, 600, 16, 10323, 10325), - (10325, 4854, 4854, 4854, 4854, 12, 85, 16770, 8, 600, 16, 10324, 13059), - (10326, 1178, 1178, 1178, 1178, 9, 85, 16771, 4, 900, 16, 7189, 10327), - (10327, 1178, 1178, 1178, 1178, 9, 85, 16772, 4, 900, 16, 10326, 10328), - (10328, 1178, 1178, 1178, 1178, 9, 85, 16773, 4, 900, 16, 10327, 13845), - (10329, -1, -1, 10329, 10329, 5, 85, 0, 0, 0, 16, -1, 10398), - (10330, 10330, 10330, 10330, 10330, 7, 85, 16785, 35, 30, 16, -1, 13203), - (10331, 10331, 10331, 10331, 10331, 6, 85, 16787, 44, 20, 16, -1, -1), - (10332, -1, -1, 10332, 10332, 3, 85, -1, 0, 0, 16, -1, 12733), - (10333, 10333, 10333, 10333, 10333, 5, 85, 16788, 55, 120, 16, -1, 10334), - (10334, 10333, 10333, 10333, 10333, 7, 85, 16789, 55, 120, 16, 10333, 10335), - (10335, 10333, 10333, 10333, 10333, 9, 85, 16790, 55, 120, 16, 10334, 12724), - (10336, 10336, 10336, 10336, 10336, 5, 85, 16791, 58, 8, 16, -1, 10337), - (10337, 10336, 10336, 10336, 10336, 7, 85, 16792, 58, 8, 16, 10336, 10338), - (10338, 10336, 10336, 10336, 10336, 9, 85, 16793, 58, 8, 16, 10337, 12730), - (10339, 10339, 10339, 10339, 10339, 12, 85, 16786, 48, 1800, 16, -1, -1), - (10340, -1, -1, 10340, 10340, 3, 80, -1, 0, 0, 16, -1, 10341), - (10341, -1, -1, 10340, 10340, 6, 83, -1, 0, 0, 16, 10340, 10342), - (10342, -1, -1, 10340, 10340, 9, 85, -1, 0, 0, 16, 10341, 13184), - (10343, -1, -1, 10343, 10343, 5, 85, 0, 0, 0, 16, -1, 10344), - (10344, -1, -1, 10343, 10343, 7, 85, 0, 0, 0, 16, 10343, 10345), - (10345, -1, -1, 10343, 10343, 9, 85, 0, 0, 0, 16, 10344, 13841), - (10346, 10346, 10346, 10346, 10346, 9, 85, 21783, 46, 600, 16, -1, 13183), - (10347, -1, -1, 7945, 7945, 6, 85, -1, 0, 0, 16, 10034, 17310), - (10348, 0, 0, 10348, 10348, 5, 80, -1, 0, 0, 16, -1, 10349), - (10349, 0, 0, 10348, 10348, 7, 83, -1, 0, 0, 16, 10348, 10350), - (10350, 0, 0, 10348, 10348, 9, 85, -1, 0, 0, 16, 10349, 13578), - (10351, 10351, 10351, 10351, 10351, 12, 85, 21785, 34, 600, 16, -1, 10682), - (10352, 10352, 10352, 10352, 10352, 12, 85, 21786, 34, 600, 16, -1, 10683), - (10353, 10353, 10353, 10353, 10353, 12, 85, 21787, 34, 600, 16, -1, 10684), - (10354, 10354, 10354, 10354, 10354, 8, 85, 21653, 39, 4320, 16, -1, 14016), - (10355, -1, -1, 10355, 10355, 6, 83, -1, 0, 0, 16, -1, 10356), - (10356, -1, -1, 10355, 10355, 8, 84, -1, 0, 0, 16, 10355, 10357), - (10357, -1, -1, 10355, 10355, 10, 85, -1, 0, 0, 16, 10356, 10643), - (10358, -1, -1, 10358, 10358, 7, 80, -1, 0, 0, 16, -1, 10359), - (10359, -1, -1, 10358, 10358, 9, 83, -1, 0, 0, 16, 10358, 10360), - (10360, -1, -1, 10358, 10358, 12, 85, -1, 0, 0, 16, 10359, 14210), - (10361, -1, -1, 962, 962, 5, 83, -1, 0, 0, 16, 6227, 10362), - (10362, -1, -1, 962, 962, 5, 84, -1, 0, 0, 16, 10361, 10363), - (10363, -1, -1, 962, 962, 5, 85, -1, 0, 0, 16, 10362, 14218), - (10364, -1, -1, 10364, 10364, 5, 85, -1, 0, 0, 16, -1, 10365), - (10365, -1, -1, 10364, 10364, 7, 85, -1, 0, 0, 16, 10364, 10366), - (10366, -1, -1, 10364, 10364, 9, 85, -1, 0, 0, 16, 10365, 10442), - (10367, 10367, 10367, 10367, 10367, 12, 85, 21751, 30, 360, 16, -1, 10630), - (10368, 10368, 10368, 10368, 10368, 6, 85, 21654, 46, 900, 16, -1, 10369), - (10369, 10368, 10368, 10368, 10368, 9, 85, 21655, 46, 900, 16, 10368, 10386), - (10370, -1, -1, 10370, 10370, 3, 60, -1, 0, 0, 16, -1, 10371), - (10371, -1, -1, 10370, 10370, 3, 60, -1, 0, 0, 16, 10370, 10372), - (10372, -1, -1, 10370, 10370, 3, 60, -1, 0, 0, 16, 10371, 13927), - (10373, 10373, 10373, 10373, 10373, 6, 75, 16806, 62, 6, 16, -1, -1), - (10374, 10374, 10374, 10374, 10374, 6, 85, 16800, 63, 900, 16, -1, 10375), - (10375, 10374, 10374, 10374, 10374, 6, 85, 16801, 63, 900, 16, 10374, 10376), - (10376, 10374, 10374, 10374, 10374, 6, 85, 16802, 63, 900, 16, 10375, 13174), - (10377, 10377, 10377, 10377, 10377, 6, 85, 16794, 64, 60, 16, -1, 10378), - (10378, 10377, 10377, 10377, 10377, 6, 85, 16795, 64, 60, 16, 10377, 10379), - (10379, 10377, 10377, 10377, 10377, 6, 85, 16796, 64, 60, 16, 10378, 13180), - (10380, -1, -1, 10380, 10380, 6, 85, -1, 0, 0, 16, -1, 10381), - (10381, -1, -1, 10380, 10380, 6, 85, -1, 0, 0, 16, 10380, 10382), - (10382, -1, -1, 10380, 10380, 6, 85, -1, 0, 0, 16, 10381, 13477), - (10383, -1, -1, 5085, 5085, 6, 85, -1, 0, 0, 16, 7386, 10384), - (10384, -1, -1, 5085, 5085, 6, 85, -1, 0, 0, 16, 10383, 10385), - (10385, -1, -1, 5085, 5085, 6, 85, -1, 0, 0, 16, 10384, -1), - (10386, 10368, 10368, 10368, 10368, 12, 85, 21656, 46, 900, 16, 10369, -1), - (10387, 10387, 10387, 10387, 10387, 9, 85, 21835, 45, 1200, 16, -1, -1), - (10388, -1, -1, 10388, 10388, 12, 85, -1, 0, 0, 16, -1, 13545), - (10389, -1, -1, 10389, 10389, 9, 83, 0, 0, 0, 16, -1, 10390), - (10390, -1, -1, 10389, 10389, 11, 84, 0, 0, 0, 16, 10389, 10391), - (10391, -1, -1, 10389, 10389, 12, 85, 0, 0, 0, 16, 10390, -1), - (10392, 10392, 10392, 10392, 10392, 12, 85, 21751, 11, 480, 16, -1, 10631), - (10393, 10393, 10393, 10393, 10393, 9, 81, 3246, 42, 2, 16, -1, -1), - (10394, 10394, 10394, 10394, 10394, 12, 85, 21821, 30, 600, 16, -1, 10704), - (10395, 10395, 10395, 10395, 10395, 3, 80, 21748, 62, 5, 16, -1, 12590), - (10396, 10396, 10396, 10396, 10396, 12, 85, 16857, 14, 600, 16, -1, 10790), - (10397, 10397, 10397, 10397, 10397, 12, 85, 16858, 14, 600, 16, -1, 10791), - (10398, -1, -1, 10329, 10329, 7, 85, 0, 0, 0, 16, 10329, 10399), - (10399, -1, -1, 10329, 10329, 9, 85, 0, 0, 0, 16, 10398, -1), - (10400, 10400, 10400, 10400, 10400, 6, 85, 16807, 62, 900, 16, -1, 15558), - (10401, -1, -1, 10401, 10401, 6, 85, -1, 0, 0, 16, -1, 10402), - (10402, -1, -1, 10401, 10401, 6, 85, -1, 0, 0, 16, 10401, 10403), - (10403, -1, -1, 10401, 10401, 6, 85, -1, 0, 0, 16, 10402, 13052), - (10404, -1, -1, 10404, 10404, 6, 85, -1, 0, 0, 16, -1, 13051), - (10405, -1, -1, 10405, 10405, 7, 81, 0, 0, 0, 16, -1, 10406), - (10406, -1, -1, 10405, 10405, 7, 82, 0, 0, 0, 16, 10405, 10407), - (10407, -1, -1, 10405, 10405, 7, 83, 0, 0, 0, 16, 10406, 10408), - (10408, -1, -1, 10405, 10405, 7, 84, 0, 0, 0, 16, 10407, 10409), - (10409, -1, -1, 10405, 10405, 7, 85, 0, 0, 0, 16, 10408, 10671), - (10410, -1, -1, 10410, 10410, 8, 85, -1, 0, 0, 16, -1, 10411), - (10413, -1, -1, 10413, 10413, 5, 81, 0, 0, 0, 16, -1, 10414), - (10414, -1, -1, 10413, 10413, 5, 81, 0, 0, 0, 16, 10413, 10415), - (10415, -1, -1, 10413, 10413, 5, 81, 0, 0, 0, 16, 10414, 10416), - (10416, -1, -1, 10413, 10413, 5, 81, 0, 0, 0, 16, 10415, 10417), - (10417, -1, -1, 10413, 10413, 5, 81, 0, 0, 0, 16, 10416, -1), - (10418, 6561, 6561, 6561, 6561, 7, 85, 21808, 32, 30, 16, 10101, 10419), - (10419, 6561, 6561, 6561, 6561, 7, 85, 21810, 32, 30, 16, 10418, 10420), - (10420, 6561, 6561, 6561, 6561, 7, 85, 21811, 32, 30, 16, 10419, 14256), - (10421, 10506, 10506, 10506, 10506, 9, 85, 23521, 66, 120, 16, 10508, -1), - (10424, 10424, 10424, 10424, 10424, 7, 81, 21813, 41, 6, 16, -1, -1), - (10425, 10425, 10425, 10425, 10425, 7, 81, 21814, 39, 6, 16, -1, -1), - (10426, 10426, 10426, 10426, 10426, 10, 85, 21816, 5, 900, 16, -1, -1), - (10427, 10427, 10427, 10427, 10427, 12, 85, 21818, 30, 900, 16, -1, -1), - (10428, 4931, 4931, 4931, 4931, 7, 85, 21838, 4, 600, 16, 10276, 10429), - (10429, 4931, 4931, 4931, 4931, 7, 85, 21839, 4, 600, 16, 10428, 10430), - (10430, 4931, 4931, 4931, 4931, 7, 85, 21844, 4, 600, 16, 10429, 13241), - (10431, -1, -1, 8031, 8031, 6, 85, -1, 0, 0, 16, 10284, 10432), - (10432, -1, -1, 8031, 8031, 6, 85, -1, 0, 0, 16, 10431, 10433), - (10433, -1, -1, 8031, 8031, 6, 85, -1, 0, 0, 16, 10432, -1), - (10434, -1, -1, 10434, 10434, 7, 85, 0, 0, 0, 16, -1, 10435), - (10435, -1, -1, 10434, 10434, 9, 85, 0, 0, 0, 16, 10434, 10436), - (10436, -1, -1, 10434, 10434, 12, 85, 0, 0, 0, 16, 10435, -1), - (10437, -1, -1, 6601, 6601, 6, 86, -1, 0, 0, 17, 10029, 10438), - (10438, -1, -1, 6601, 6601, 6, 87, -1, 0, 0, 17, 10437, 10439), - (10439, -1, -1, 6601, 6601, 6, 88, -1, 0, 0, 17, 10438, 10440), - (10440, -1, -1, 6601, 6601, 6, 89, -1, 0, 0, 17, 10439, 10441), - (10442, -1, -1, 10364, 10364, 9, 86, -1, 0, 0, 17, 10366, 10443), - (10443, -1, -1, 10364, 10364, 9, 88, -1, 0, 0, 17, 10442, -1), - (10450, 10450, 10450, 10450, 10450, 7, 85, 16808, 63, 900, 16, -1, 10451), - (10451, 10450, 10450, 10450, 10450, 7, 85, 16809, 63, 900, 16, 10450, 10452), - (10452, 10450, 10450, 10450, 10450, 7, 85, 16810, 63, 900, 16, 10451, 10468), - (10453, -1, -1, 10453, 10453, 5, 85, -1, 0, 0, 16, -1, 10454), - (10454, -1, -1, 10453, 10453, 7, 85, -1, 0, 0, 16, 10453, 10455), - (10455, -1, -1, 10453, 10453, 9, 85, -1, 0, 0, 16, 10454, 13607), - (10456, -1, -1, 10456, 10456, 5, 85, -1, 0, 0, 16, -1, 10457), - (10457, -1, -1, 10456, 10456, 7, 85, -1, 0, 0, 16, 10456, 10458), - (10458, -1, -1, 10456, 10456, 9, 85, -1, 0, 0, 16, 10457, -1), - (10459, -1, -1, 10459, 10459, 5, 65, -1, 0, 0, 16, -1, 10460), - (10460, -1, -1, 10459, 10459, 7, 65, -1, 0, 0, 16, 10459, 10461), - (10461, -1, -1, 10459, 10459, 9, 65, -1, 0, 0, 16, 10460, -1), - (10462, 10462, 10462, 10462, 10462, 12, 85, 16811, 14, 4320, 16, -1, -1), - (10463, 10463, 10463, 10463, 10463, 12, 85, 16812, 16, 4320, 16, -1, -1), - (10464, -1, -1, 10464, 10464, 5, 80, -1, 0, 0, 16, -1, 10465), - (10465, -1, -1, 10464, 10464, 7, 80, -1, 0, 0, 16, 10464, 10466), - (10466, -1, -1, 10464, 10464, 9, 80, -1, 0, 0, 16, 10465, 13140), - (10467, -1, -1, 86, 86, 8, 85, -1, 0, 0, 17, 266, -1), - (10468, 10450, 10450, 10450, 10450, 7, 85, 23603, 63, 900, 17, 10452, 10469), - (10469, 10450, 10450, 10450, 10450, 7, 85, 23604, 63, 900, 17, 10468, 10670), - (10470, -1, -1, 10470, 10470, 9, 86, -1, 0, 0, 17, -1, 10471), - (10471, -1, -1, 10470, 10470, 12, 88, -1, 0, 0, 17, 10470, 10472), - (10472, -1, -1, 10470, 10470, 15, 90, -1, 0, 0, 17, 10471, 15828), - (10473, -1, -1, 446, 735, 10, 86, -1, 0, 0, 17, 7624, 10474), - (10474, -1, -1, 446, 735, 10, 87, -1, 0, 0, 17, 10473, 10475), - (10475, -1, -1, 446, 735, 10, 88, -1, 0, 0, 17, 10474, 10476), - (10476, -1, -1, 446, 735, 10, 89, -1, 0, 0, 17, 10475, 10477), - (10477, -1, -1, 446, 735, 10, 90, -1, 0, 0, 17, 10476, 13308), - (10478, -1, -1, 10478, 10478, 15, 101, -1, 0, 0, 21, -1, 10479), - (10481, 10481, 10481, 10481, 10481, 21, 105, 46249, 90, 600, 21, -1, -1), - (10500, 10500, 10500, 10500, 10500, 7, 85, 16813, 62, 12, 16, -1, -1), - (10501, 10501, 10501, 10501, 10501, 7, 85, 16814, 63, 1, 16, -1, -1), - (10502, 10502, -1, 10502, 10502, 7, 85, 1566, 64, 120, 16, -1, 12647), - (10503, 10503, 10503, 10503, 10503, 9, 85, 16816, 13, 600, 16, -1, 10504), - (10504, 10503, 10503, 10503, 10503, 9, 85, 16817, 13, 600, 16, 10503, 10505), - (10505, 10503, 10503, 10503, 10503, 9, 85, 16818, 13, 600, 16, 10504, 12648), - (10506, 10506, 10506, 10506, 10506, 9, 85, 16819, 66, 120, 16, -1, 10507), - (10507, 10506, 10506, 10506, 10506, 9, 85, 16820, 66, 120, 16, 10506, 10508), - (10508, 10506, 10506, 10506, 10506, 9, 85, 16821, 66, 120, 16, 10507, 10421), - (10509, 5105, 5105, 5105, 5105, 12, 85, 16822, 11, 600, 16, 7420, 13154), - (10510, 7986, 7986, 7986, 7986, 12, 85, 16823, 11, 600, 16, 7988, 13155), - (10511, -1, -1, 10511, 10511, 6, 85, -1, 0, 0, 16, -1, 10512), - (10512, -1, -1, 10511, 10511, 6, 85, -1, 0, 0, 16, 10511, 10513), - (10513, -1, -1, 10511, 10511, 6, 85, -1, 0, 0, 16, 10512, 12642), - (10514, -1, -1, 10514, 10514, 6, 85, -1, 0, 0, 16, -1, 10516), - (10515, -1, -1, 10514, 10514, 6, 85, -1, 0, 0, 16, 10516, 12639), - (10516, -1, -1, 10514, 10514, 6, 85, -1, 0, 0, 16, 10514, 10515), - (10517, 6565, 6565, 6565, 6565, 9, 88, 23608, 17, 45, 17, 10010, 10518), - (10519, -1, -1, 10519, 10519, 9, 86, 0, 0, 0, 17, -1, 10520), - (10522, -1, -1, 10522, 10522, 7, 86, 0, 0, 0, 17, -1, 10523), - (10527, -1, -1, 10527, 10527, 5, 86, 0, 0, 0, 17, -1, 10528), - (10532, -1, -1, 10532, 10532, 5, 86, 0, 0, 0, 17, -1, 10533), - (10537, -1, -1, 10537, 10537, 5, 86, 0, 0, 0, 17, -1, 10538), - (10545, 10545, 10545, 10545, 10545, 12, 85, 23531, 73, 600, 17, -1, -1), - (10546, 10546, 10546, 10546, 10546, 12, 85, 23528, 74, 600, 17, -1, -1), - (10548, -1, -1, 10548, 10548, 9, 86, -1, 0, 0, 17, -1, 10549), - (10550, 10550, 10550, 10550, 10550, 7, 85, 16824, 61, 120, 16, -1, 13250), - (10551, -1, -1, 10551, 10551, 6, 85, -1, 0, 0, 16, -1, 10552), - (10552, -1, -1, 10551, 10551, 6, 85, -1, 0, 0, 16, 10551, 10553), - (10553, -1, -1, 10551, 10551, 6, 85, -1, 0, 0, 16, 10552, 14764), - (10554, -1, -1, 1572, 1572, 5, 80, -1, 0, 0, 16, 1576, 10555), - (10555, -1, -1, 1572, 1572, 5, 80, -1, 0, 0, 16, 10554, 10556), - (10556, -1, -1, 1572, 1572, 5, 80, -1, 0, 0, 16, 10555, 16062), - (10557, 12395, 12395, 12395, 12395, 9, 75, 16828, 11, 900, 16, -1, -1), - (10558, -1, -1, 10558, 10558, 6, 80, -1, 0, 0, 16, -1, 10559), - (10559, -1, -1, 10558, 10558, 6, 83, -1, 0, 0, 16, 10558, 10560), - (10560, -1, -1, 10558, 10558, 6, 85, -1, 0, 0, 16, 10559, 15469), - (10561, -1, -1, 10561, 10561, 6, 85, -1, 0, 0, 16, -1, 10562), - (10562, -1, -1, 10561, 10561, 6, 85, -1, 0, 0, 16, 10561, 10563), - (10563, -1, -1, 10561, 10561, 6, 85, -1, 0, 0, 16, 10562, 15466), - (10564, 773, -1, 773, 773, 12, 85, 16829, 5, 1800, 16, 7278, 10565), - (10565, 773, -1, 773, 773, 12, 85, 16830, 5, 1800, 16, 10564, 10566), - (10566, 773, -1, 773, 773, 12, 85, 16831, 5, 1800, 16, 10565, 13734), - (10568, -1, -1, 6564, 6564, 10, 86, -1, 0, 0, 17, 10009, 10569), - (10571, 1597, 1597, 1597, 1597, 9, 85, 23611, 6, 10, 17, 6606, -1), - (10572, 6617, 6617, 6617, 6617, 12, 86, 23612, 42, 3600, 17, 6617, 14036), - (10573, 6610, 6610, 6610, 6610, 9, 86, 23613, 41, 30, 17, 10003, 13422), - (10574, -1, -1, 6611, 6611, 6, 85, -1, 0, 0, 17, 6619, 16121), - (10575, -1, -1, 6614, 6614, 9, 85, -1, 0, 0, 17, 10005, -1), - (10576, -1, -1, 492, 492, 2, 87, -1, 0, 0, 17, 7130, -1), - (10578, 258, -1, 258, 258, 9, 86, 27520, 1, 600, 17, 258, 16003), - (10579, -1, -1, 7036, 10579, 9, 85, 0, 0, 0, 17, 7038, 10580), - (10580, -1, -1, 7036, 10579, 12, 87, 0, 0, 0, 17, 10579, 10581), - (10585, 912, 912, 912, 912, 9, 86, 23617, 4, 3600, 17, 10013, 10586), - (10588, -1, -1, 10588, 10588, 5, 86, 0, 0, 0, 17, -1, 10589), - (10589, -1, -1, 10588, 10588, 5, 87, 0, 0, 0, 17, 10588, 10590), - (10590, -1, -1, 10588, 10588, 5, 88, 0, 0, 0, 17, 10589, 10591), - (10591, -1, -1, 10588, 10588, 5, 89, 0, 0, 0, 17, 10590, 10592), - (10592, -1, -1, 10588, 10588, 5, 90, 0, 0, 0, 17, 10591, 17206), - (10600, 10600, 10600, 10600, 10600, 7, 85, 16832, 73, 20, 16, -1, 10601), - (10601, 10600, 10600, 10600, 10600, 7, 85, 16833, 73, 20, 16, 10600, 10602), - (10602, 10600, 10600, 10600, 10600, 7, 85, 16834, 73, 20, 16, 10601, 12982), - (10603, 10601, 10601, 10601, 10601, 3, 85, 16835, 62, 6, 16, -1, -1), - (10604, -1, -1, 6051, 6051, 3, 85, -1, 0, 0, 16, 7603, 10605), - (10605, -1, -1, 6051, 6051, 3, 85, -1, 0, 0, 16, 10604, 10606), - (10606, -1, -1, 6051, 6051, 3, 85, -1, 0, 0, 16, 10605, 12795), - (10607, -1, -1, 6383, 6383, 9, 80, -1, 0, 0, 16, 6385, 10608), - (10608, -1, -1, 6383, 6383, 9, 80, -1, 0, 0, 16, 10607, 10609), - (10609, -1, -1, 6383, 6383, 9, 80, -1, 0, 0, 16, 10608, 12801), - (10610, -1, -1, 10610, 10610, 3, 70, -1, 0, 0, 16, -1, 10611), - (10611, -1, -1, 10610, 10610, 3, 70, -1, 0, 0, 16, 10610, 10612), - (10612, -1, -1, 10610, 10610, 3, 70, -1, 0, 0, 16, 10611, -1), - (10618, 7850, 7850, 7850, 7850, 9, 86, 23532, 39, 4320, 17, 7340, 10619), - (10619, 7850, 7850, 7850, 7850, 12, 88, 23533, 39, 4320, 17, 10618, 10620), - (10620, 7850, 7850, 7850, 7850, 15, 90, 23534, 39, 4320, 17, 10619, 13604), - (10621, -1, -1, 849, 849, 9, 85, -1, 0, 0, 17, 851, 10622), - (10622, -1, -1, 849, 849, 9, 87, -1, 0, 0, 17, 10621, 16604), - (10623, -1, -1, 255, 255, 9, 85, -1, 0, 0, 17, 5808, 10624), - (10624, -1, -1, 255, 255, 12, 87, -1, 0, 0, 17, 10623, 10625), - (10625, -1, -1, 255, 255, 15, 89, -1, 0, 0, 17, 10624, 13589), - (10626, 5984, 5984, 5984, 5984, 12, 90, 23535, 2, 30, 17, 7711, 13592), - (10627, -1, -1, 10627, 10627, 3, 59, 0, 0, 0, 3, -1, 10628), - (10628, -1, -1, 10627, 10627, 3, 59, 0, 0, 0, 3, 10627, 10629), - (10629, -1, -1, 10627, 10627, 3, 59, 0, 0, 0, 3, 10628, -1), - (10630, 10367, 10367, 10367, 10367, 12, 90, 27642, 30, 360, 17, 10367, 13434), - (10631, 10392, 10392, 10392, 10392, 12, 90, 27642, 11, 480, 17, 10392, -1), - (10632, -1, -1, 735, 735, 10, 86, -1, 0, 0, 17, 7627, 10633), - (10633, -1, -1, 735, 735, 10, 87, -1, 0, 0, 17, 10632, 10634), - (10634, -1, -1, 735, 735, 10, 88, -1, 0, 0, 17, 10633, 10635), - (10635, -1, -1, 735, 735, 10, 89, -1, 0, 0, 17, 10634, 10636), - (10636, -1, -1, 735, 735, 10, 90, -1, 0, 0, 17, 10635, 13884), - (10637, -1, -1, 1287, 1287, 9, 86, -1, 0, 0, 17, 12471, 10638), - (10638, -1, -1, 1287, 1287, 12, 88, -1, 0, 0, 17, 10637, 10639), - (10639, -1, -1, 1287, 1287, 15, 90, -1, 0, 0, 17, 10638, 13323), - (10640, 5095, 5095, 5095, 5095, 9, 85, 23620, 10, 900, 17, 7334, 10641), - (10641, 5095, 5095, 5095, 5095, 12, 87, 23621, 10, 900, 17, 10640, 10642), - (10642, 5095, 5095, 5095, 5095, 15, 89, 23622, 10, 900, 17, 10641, 13575), - (10643, -1, -1, 10355, 10355, 10, 86, -1, 0, 0, 17, 10357, 10644), - (10644, -1, -1, 10355, 10355, 10, 88, -1, 0, 0, 17, 10643, 10645), - (10645, -1, -1, 10355, 10355, 10, 90, -1, 0, 0, 17, 10644, 14094), - (10646, 7712, 7712, 7712, 7712, 15, 90, 23536, 2, 30, 17, 7712, 13585), - (10647, 188, 188, 188, 188, 9, 88, 23537, 2, 30, 17, 7662, 13586), - (10650, -1, -1, 10650, 10650, 7, 85, -1, 0, 0, 16, -1, 10651), - (10651, -1, -1, 10650, 10650, 9, 85, -1, 0, 0, 16, 10650, 10652), - (10652, -1, -1, 10650, 10650, 12, 85, -1, 0, 0, 16, 10651, 13804), - (10653, -1, -1, 10653, 10653, 7, 85, -1, 0, 0, 16, -1, 10654), - (10654, -1, -1, 10653, 10653, 7, 85, -1, 0, 0, 16, 10653, 10655), - (10655, -1, -1, 10653, 10653, 7, 85, -1, 0, 0, 16, 10654, 17406), - (10656, -1, -1, 10656, 10656, 7, 85, -1, 0, 0, 16, -1, 12678), - (10657, -1, -1, 10657, 10657, 7, 85, -1, 0, 0, 16, -1, 10658), - (10658, -1, -1, 10657, 10657, 7, 85, -1, 0, 0, 16, 10657, 10659), - (10659, -1, -1, 10657, 10657, 7, 85, -1, 0, 0, 16, 10658, 12679), - (10660, -1, -1, 820, 820, 5, 85, -1, 0, 0, 16, 7165, 10661), - (10661, -1, -1, 820, 820, 5, 85, -1, 0, 0, 16, 10660, 10662), - (10662, -1, -1, 820, 820, 5, 85, -1, 0, 0, 16, 10661, 12667), - (10663, -1, -1, 6020, 6020, 2, 85, -1, 0, 0, 16, 7171, 10664), - (10664, -1, -1, 6020, 6020, 2, 85, -1, 0, 0, 16, 10663, 10665), - (10665, -1, -1, 6020, 6020, 2, 85, -1, 0, 0, 16, 10664, 12670), - (10666, -1, -1, 495, 495, 6, 85, -1, 0, 0, 16, 6262, 10667), - (10667, -1, -1, 495, 495, 5, 85, -1, 0, 0, 16, 10666, 10668), - (10668, -1, -1, 495, 495, 7, 85, -1, 0, 0, 16, 10667, 17391), - (10670, 10450, 10450, 10450, 10450, 7, 85, 23605, 63, 900, 17, 10469, 15839), - (10671, -1, -1, 10405, 10405, 9, 86, 0, 0, 0, 17, 10409, 10672), - (10672, -1, -1, 10405, 10405, 9, 87, 0, 0, 0, 17, 10671, 10673), - (10673, -1, -1, 10405, 10405, 9, 88, 0, 0, 0, 17, 10672, 10674), - (10674, -1, -1, 10405, 10405, 9, 89, 0, 0, 0, 17, 10673, 10675), - (10675, -1, -1, 10405, 10405, 9, 90, 0, 0, 0, 17, 10674, -1), - (10676, -1, -1, 6791, 6791, 6, 86, -1, 0, 0, 17, 10046, 10677), - (10677, -1, -1, 6791, 6791, 6, 88, -1, 0, 0, 17, 10676, 10678), - (10678, -1, -1, 6791, 6791, 6, 90, -1, 0, 0, 17, 10677, 13598), - (10679, 6492, 6492, 6492, 6492, 9, 85, 23626, 52, 720, 17, 6497, 10680), - (10680, 6492, 6492, 6492, 6492, 9, 87, 23627, 52, 720, 17, 10679, 10681), - (10681, 6492, 6492, 6492, 6492, 9, 89, 23628, 52, 720, 17, 10680, 14003), - (10682, 10351, 10351, 10351, 10351, 15, 90, 23538, 34, 600, 17, 10351, -1), - (10683, 10352, 10352, 10352, 10352, 15, 90, 23539, 34, 600, 17, 10352, -1), - (10684, 10353, 10353, 10353, 10353, 15, 90, 23540, 34, 600, 17, 10353, -1), - (10685, -1, -1, 602, 602, 9, 86, -1, 0, 0, 17, 5582, 10686), - (10686, -1, -1, 602, 602, 12, 88, -1, 0, 0, 17, 10685, 10687), - (10687, -1, -1, 602, 602, 15, 90, -1, 0, 0, 17, 10686, 13610), - (10688, -1, -1, 855, 855, 7, 86, -1, 0, 0, 17, 7677, 10689), - (10689, -1, -1, 855, 855, 7, 87, -1, 0, 0, 17, 10688, 10690), - (10690, -1, -1, 855, 855, 7, 88, -1, 0, 0, 17, 10689, 10691), - (10691, -1, -1, 855, 855, 7, 89, -1, 0, 0, 17, 10690, 10692), - (10692, -1, -1, 855, 855, 7, 90, -1, 0, 0, 17, 10691, 13613), - (10700, 10700, 10700, 10700, 10700, 7, 85, 16839, 61, 10, 16, -1, -1), - (10701, 10701, 10701, 10701, 10701, 7, 85, 21662, 32, 360, 16, -1, 10702), - (10702, 10701, 10701, 10701, 10701, 9, 85, 21663, 32, 360, 16, 10701, 10703), - (10703, 10701, 10701, 10701, 10701, 12, 85, 21664, 32, 360, 16, 10702, 12754), - (10704, 10394, 10394, 10394, 10394, 12, 85, 23541, 30, 300, 17, 10394, 13584), - (10705, -1, -1, 6395, 6395, 9, 86, -1, 0, 0, 17, 10052, 10706), - (10706, -1, -1, 6395, 6395, 9, 88, -1, 0, 0, 17, 10705, 10707), - (10707, -1, -1, 6395, 6395, 9, 90, -1, 0, 0, 17, 10706, 14097), - (10708, 534, 534, 534, 534, 12, 86, 23545, 4, 2160, 17, 10049, 10709), - (10709, 534, 534, 534, 534, 12, 88, 23546, 4, 2160, 17, 10708, 10710), - (10710, 534, 534, 534, 534, 12, 90, 23547, 4, 2160, 17, 10709, 13595), - (10711, 10711, 10711, 10711, 10711, 9, 86, 23548, 75, 1200, 17, -1, 10712), - (10712, 10711, 10711, 10711, 10711, 12, 88, 23549, 75, 1200, 17, 10711, 10713), - (10713, 10711, 10711, 10711, 10711, 15, 90, 23550, 75, 1200, 17, 10712, 14006), - (10714, -1, -1, 10714, 10714, 9, 86, 0, 0, 0, 17, -1, 10715), - (10715, -1, -1, 10714, 10714, 12, 88, 0, 0, 0, 17, 10714, 10716), - (10717, -1, -1, 7743, 7743, 9, 61, -1, 0, 0, 17, 7745, 10718), - (10718, -1, -1, 7743, 7743, 9, 61, -1, 0, 0, 17, 10717, 15258), - (10719, -1, -1, 10719, 10719, 9, 75, 0, 0, 0, 17, -1, 10720), - (10720, -1, -1, 10719, 10719, 12, 75, 0, 0, 0, 17, 10719, 10721), - (10721, -1, -1, 10719, 10719, 15, 75, 0, 0, 0, 17, 10720, 13562), - (10722, -1, -1, 10722, 10722, 5, 81, 0, 0, 0, 17, -1, 10723), - (10723, -1, -1, 10722, 10722, 5, 82, 0, 0, 0, 17, 10722, 10724), - (10724, -1, -1, 10722, 10722, 7, 83, 0, 0, 0, 17, 10723, 10725), - (10725, -1, -1, 10722, 10722, 9, 84, 0, 0, 0, 17, 10724, 10726), - (10726, -1, -1, 10722, 10722, 12, 85, 0, 0, 0, 17, 10725, 15280), - (10727, -1, -1, 10727, 10727, 7, 86, 0, 0, 0, 17, -1, 10728), - (10728, -1, -1, 10727, 10727, 9, 88, 0, 0, 0, 17, 10727, 10729), - (10730, -1, -1, 10730, 10730, 7, 86, 0, 0, 0, 17, -1, 10731), - (10731, -1, -1, 10730, 10730, 9, 88, 0, 0, 0, 17, 10730, 10732), - (10733, -1, -1, 10733, 10733, 7, 81, 0, 0, 0, 17, -1, 10734), - (10734, -1, -1, 10733, 10733, 9, 83, 0, 0, 0, 17, 10733, 10735), - (10735, -1, -1, 10733, 10733, 12, 85, 0, 0, 0, 17, 10734, -1), - (10736, 10736, 10736, 10736, 10736, 7, 86, 23632, 5, 180, 17, -1, 10737), - (10737, 10736, 10736, 10736, 10736, 9, 88, 23633, 5, 180, 17, 10736, 10738), - (10739, 645, -1, 645, 645, 12, 86, 23551, 4, 5, 17, 5999, 13410), - (10740, 1345, 1345, 1345, 1345, 9, 86, 23552, 6, 900, 17, 7349, 10741), - (10741, 1345, 1345, 1345, 1345, 12, 88, 23553, 6, 900, 17, 10740, 10742), - (10743, -1, -1, 1196, 1196, 5, 86, -1, 0, 0, 17, 1200, 10744), - (10744, -1, -1, 1196, 1196, 5, 87, -1, 0, 0, 17, 10743, 10745), - (10745, -1, -1, 1196, 1196, 5, 88, -1, 0, 0, 17, 10744, 10746), - (10748, -1, -1, 867, 867, 7, 86, -1, 0, 0, 17, 7366, 10749), - (10749, -1, -1, 867, 867, 7, 87, -1, 0, 0, 17, 10748, 10755), - (10750, -1, -1, 7103, 7103, 2, 70, -1, 0, 0, 16, 7328, 10751), - (10751, -1, -1, 7103, 7103, 2, 70, -1, 0, 0, 16, 10750, -1), - (10752, 10752, 10752, 10752, 10752, 6, 85, 16843, 72, 600, 16, -1, -1), - (10753, 10753, 10753, 10753, 10753, 12, 80, 16844, 6, 4320, 16, -1, -1), - (10754, 10754, 10754, 10754, 10754, 2, 70, 16845, 62, 5, 16, -1, -1), - (10755, -1, -1, 867, 867, 7, 88, -1, 0, 0, 17, 10749, 10756), - (10758, 545, 545, 545, 545, 12, 86, 23638, 3, 900, 17, 7346, 10759), - (10759, 545, 545, 545, 545, 12, 87, 23639, 3, 900, 17, 10758, 10760), - (10760, 545, 545, 545, 545, 12, 88, 23640, 3, 900, 17, 10759, 10761), - (10763, -1, -1, 6761, 6761, 12, 86, -1, 0, 0, 17, 6087, 10764), - (10764, -1, -1, 6761, 6761, 12, 88, -1, 0, 0, 17, 10763, 10765), - (10766, -1, -1, 6765, 6765, 9, 85, -1, 0, 0, 17, 10060, 10767), - (10767, -1, -1, 6765, 6765, 9, 87, -1, 0, 0, 17, 10766, 10768), - (10768, -1, -1, 6765, 6765, 9, 89, -1, 0, 0, 17, 10767, 13553), - (10769, -1, -1, 6751, 6751, 9, 86, -1, 0, 0, 17, 6769, 10770), - (10770, -1, -1, 6751, 6751, 9, 88, -1, 0, 0, 17, 10769, 10771), - (10772, 872, 872, 872, 872, 9, 85, 23555, 5, 180, 17, 7369, 10773), - (10773, 872, 872, 872, 872, 9, 87, 23556, 5, 180, 17, 10772, 10774), - (10774, 872, 872, 872, 872, 9, 89, 23557, 5, 180, 17, 10773, -1), - (10775, 875, 875, 875, 875, 9, 85, 23561, 5, 180, 17, 7372, 10776), - (10776, 875, 875, 875, 875, 9, 87, 23562, 5, 180, 17, 10775, 10777), - (10777, 875, 875, 875, 875, 9, 89, 23563, 5, 180, 17, 10776, 13536), - (10778, -1, -1, 634, 634, 12, 85, -1, 0, 0, 17, 7714, 10779), - (10779, -1, -1, 634, 634, 12, 87, -1, 0, 0, 17, 10778, 10780), - (10780, -1, -1, 634, 634, 12, 89, -1, 0, 0, 17, 10779, 15585), - (10781, -1, -1, 8240, 8240, 9, 85, -1, 0, 0, 17, 8244, 10782), - (10782, -1, -1, 8240, 8240, 9, 86, -1, 0, 0, 17, 10781, 10783), - (10783, -1, -1, 8240, 8240, 9, 87, -1, 0, 0, 17, 10782, 10784), - (10784, -1, -1, 8240, 8240, 9, 88, -1, 0, 0, 17, 10783, 10785), - (10785, -1, -1, 8240, 8240, 9, 89, -1, 0, 0, 17, 10784, 13343), - (10786, 7800, 7800, 7800, 7800, 12, 85, 23567, 39, 4320, 17, 7817, 10787), - (10787, 7800, 7800, 7800, 7800, 12, 87, 23568, 39, 4320, 17, 10786, 13619), - (10788, -1, -1, 4699, 4699, 7, 65, -1, 0, 0, 17, 7500, -1), - (10789, 10789, 10789, 10789, 10789, 15, 90, 23575, 41, 6, 17, -1, 14261), - (10790, 10396, 10396, 10396, 10396, 15, 90, 23576, 14, 600, 17, 10396, 14024), - (10791, 10397, 10397, 10397, 10397, 15, 90, 23577, 14, 600, 17, 10397, 14025), - (10792, -1, -1, 10792, 10792, 5, 86, 0, 0, 0, 17, -1, 10793), - (10793, -1, -1, 10792, 10792, 7, 87, 0, 0, 0, 17, 10792, 10794), - (10794, -1, -1, 10792, 10792, 9, 88, 0, 0, 0, 17, 10793, 10795), - (10795, -1, -1, 10792, 10792, 11, 89, 0, 0, 0, 17, 10794, 10796), - (10796, -1, -1, 10792, 10792, 13, 90, 0, 0, 0, 17, 10795, 17365), - (10800, -1, -1, 10800, 10800, 6, 70, -1, 0, 0, 16, -1, 10801), - (10801, -1, -1, 10800, 10800, 9, 70, -1, 0, 0, 16, 10800, 10802), - (10802, -1, -1, 10800, 10800, 12, 70, -1, 0, 0, 16, 10801, 17476), - (10803, -1, -1, 10803, 10803, 6, 76, -1, 0, 0, 16, -1, 10804), - (10804, -1, -1, 10803, 10803, 6, 78, -1, 0, 0, 16, 10803, 10805), - (10805, -1, -1, 10803, 10803, 6, 80, -1, 0, 0, 16, 10804, -1), - (10806, 10806, 10806, 10806, 10806, 10, 80, 16846, 71, 540, 16, -1, 10807), - (10807, 10806, 10806, 10806, 10806, 11, 80, 16847, 71, 540, 16, 10806, 10808), - (10808, 10806, 10806, 10806, 10806, 12, 80, 16848, 71, 540, 16, 10807, 15298), - (10809, 10809, 10809, 10809, 10809, 10, 80, 16849, 71, 540, 16, -1, 10810), - (10810, 10809, 10809, 10809, 10809, 11, 80, 16850, 71, 540, 16, 10809, 10811), - (10811, 10809, 10809, 10809, 10809, 12, 80, 16851, 71, 540, 16, 10810, 15301), - (10815, 10815, 10815, 10815, 10815, 6, 80, -1, 0, 0, 16, -1, 10816), - (10816, 10815, 10815, 10815, 10815, 9, 80, -1, 0, 0, 16, 10815, 10817), - (10817, 10815, 10815, 10815, 10815, 12, 80, -1, 0, 0, 16, 10816, 13110), - (10818, 10818, 10818, 10818, 10818, 6, 80, -1, 0, 0, 16, -1, 10819), - (10819, 10818, 10818, 10818, 10818, 9, 80, -1, 0, 0, 16, 10818, 10820), - (10820, 10818, 10818, 10818, 10818, 12, 80, -1, 0, 0, 16, 10819, 13113), - (10821, 10821, 10821, 10821, 10821, 6, 80, -1, 0, 0, 16, -1, 10822), - (10822, 10821, 10821, 10821, 10821, 9, 80, -1, 0, 0, 16, 10821, 10823), - (10823, 10821, 10821, 10821, 10821, 12, 80, -1, 0, 0, 16, 10822, 13116), - (10824, 510, 510, 510, 510, 6, 86, 23578, 37, 240, 17, 10104, 10825), - (10850, -1, -1, 10850, 10850, 6, 85, 16864, 0, 0, 16, -1, 10851), - (10851, -1, -1, 10850, 10850, 6, 85, 16865, 0, 0, 16, 10850, 10852), - (10852, -1, -1, 10850, 10850, 6, 85, 16866, 0, 0, 16, 10851, 13207), - (10853, -1, -1, 10853, 10853, 3, 65, -1, 0, 0, 16, -1, 10854), - (10854, -1, -1, 10853, 10853, 6, 65, -1, 0, 0, 16, 10853, 10855), - (10855, -1, -1, 10853, 10853, 9, 65, -1, 0, 0, 16, 10854, 10856), - (10856, -1, -1, 10853, 10853, 5, 66, -1, 0, 0, 16, 10855, 10857), - (10857, -1, -1, 10853, 10853, 5, 68, -1, 0, 0, 16, 10856, 10858), - (10858, -1, -1, 10853, 10853, 5, 70, -1, 0, 0, 16, 10857, 10859), - (10859, -1, -1, 10853, 10853, 5, 76, -1, 0, 0, 16, 10858, 10860), - (10860, -1, -1, 10853, 10853, 5, 78, -1, 0, 0, 16, 10859, 10861), - (10861, -1, -1, 10853, 10853, 5, 80, -1, 0, 0, 16, 10860, 10862), - (10862, -1, -1, 10853, 10853, 5, 81, -1, 0, 0, 16, 10861, 10863), - (10863, -1, -1, 10853, 10853, 5, 83, -1, 0, 0, 16, 10862, 10864), - (10864, -1, -1, 10853, 10853, 5, 85, -1, 0, 0, 16, 10863, 15954), - (10865, -1, -1, 1304, 1304, 12, 85, -1, 0, 0, 16, 7150, 10866), - (10866, -1, -1, 1304, 1304, 12, 85, -1, 0, 0, 16, 10865, 10867), - (10867, -1, -1, 1304, 1304, 12, 85, -1, 0, 0, 16, 10866, 13218), - (10868, 5021, 5021, 5021, 5021, 9, 76, 16867, 7, 60, 16, 5021, 10869), - (10869, 5021, 5021, 5021, 5021, 9, 81, 16868, 7, 60, 16, 10868, 10870), - (10870, 5021, 5021, 5021, 5021, 9, 85, 16869, 7, 60, 16, 10869, 12618), - (10900, 10900, 10900, 10900, 10900, 9, 85, 16870, 55, 120, 16, -1, 10901), - (10901, 10900, 10900, 10900, 10900, 9, 85, 16871, 55, 120, 16, 10900, 10902), - (10902, 10900, 10900, 10900, 10900, 9, 85, 16872, 55, 120, 16, 10901, 13624), - (10903, -1, -1, 10903, 10903, 6, 81, -1, 0, 0, 16, -1, 10904), - (10904, -1, -1, 10903, 10903, 6, 83, -1, 0, 0, 16, 10903, 10905), - (10905, -1, -1, 10903, 10903, 6, 85, -1, 0, 0, 16, 10904, -1), - (10906, -1, -1, 895, 895, 12, 85, -1, 0, 0, 16, 7406, 10907), - (10907, -1, -1, 895, 895, 12, 85, -1, 0, 0, 16, 10906, 10908), - (10908, -1, -1, 895, 895, 12, 85, -1, 0, 0, 16, 10907, 13627), - (10909, -1, -1, 10909, 10909, 6, 85, -1, 0, 0, 16, -1, 10910), - (10910, -1, -1, 10909, 10909, 6, 85, -1, 0, 0, 16, 10909, 10911), - (10911, -1, -1, 10909, 10909, 6, 85, -1, 0, 0, 16, 10910, -1), - (10912, 10912, 10912, 10912, 10912, 6, 85, 16873, 69, 1800, 16, -1, 10913), - (10913, 10912, 10912, 10912, 10912, 6, 85, 16874, 69, 1800, 16, 10912, 10914), - (10914, 10912, 10912, 10912, 10912, 6, 85, 16875, 69, 1800, 16, 10913, 14053), - (10915, -1, -1, 10915, 10915, 9, 85, -1, 0, 0, 16, -1, 10916), - (10916, -1, -1, 10915, 10915, 9, 85, -1, 0, 0, 16, 10915, 10917), - (10917, -1, -1, 10915, 10915, 9, 85, -1, 0, 0, 16, 10916, 16189), - (10950, -1, -1, 10950, 10950, 6, 85, -1, 0, 0, 16, -1, -1), - (10951, -1, -1, 10951, 10951, 12, 85, -1, 0, 0, 16, -1, 10952), - (10952, -1, -1, 10951, 10951, 12, 85, -1, 0, 0, 16, 10951, 10953), - (10953, -1, -1, 10951, 10951, 12, 85, -1, 0, 0, 16, 10952, 15363), - (10954, -1, -1, 10954, 10954, 12, 85, -1, 0, 0, 16, -1, 10955), - (10955, -1, -1, 10954, 10954, 12, 85, -1, 0, 0, 16, 10954, 10956), - (10956, -1, -1, 10954, 10954, 12, 85, -1, 0, 0, 16, 10955, -1), - (10957, 10957, 10957, 10957, 10957, 6, 85, 16879, 61, 5, 16, -1, -1), - (10958, 10958, 10958, 10958, 10958, 12, 85, 16880, 62, 900, 16, -1, 13000), - (10959, 10959, 10959, 10959, 10959, 12, 85, 16881, 63, 600, 16, -1, 10961), - (10961, 10959, 10959, 10959, 10959, 12, 85, 21717, 63, 600, 16, 10959, 10962), - (10962, 10959, 10959, 10959, 10959, 12, 85, 21718, 63, 600, 16, 10961, 12988), - (11000, -1, -1, 11000, 11000, 6, 85, -1, 0, 0, 16, -1, 11001), - (11001, -1, -1, 11000, 11000, 9, 85, -1, 0, 0, 16, 11000, 11002), - (11002, -1, -1, 11000, 11000, 12, 85, -1, 0, 0, 16, 11001, -1), - (11003, -1, -1, 11003, 11003, 6, 85, -1, 0, 0, 16, -1, -1), - (11004, -1, -1, 11004, 11004, 6, 85, -1, 0, 0, 16, -1, 11005), - (11005, -1, -1, 11004, 11004, 6, 85, -1, 0, 0, 16, 11004, 11006), - (11006, -1, -1, 11004, 11004, 6, 85, -1, 0, 0, 16, 11005, -1), - (11011, -1, -1, 6302, 6302, 5, 85, 0, 0, 0, 16, 6304, 11012), - (11012, -1, -1, 6302, 6302, 5, 85, 0, 0, 0, 16, 11011, 11013), - (11013, -1, -1, 6302, 6302, 5, 85, 0, 0, 0, 16, 11012, 15552), - (11014, -1, -1, 11007, 11007, 5, 80, -1, 0, 0, 16, -1, 11015), - (11015, -1, -1, 11007, 11007, 7, 82, -1, 0, 0, 16, 11014, 11016), - (11016, -1, -1, 11007, 11007, 9, 85, -1, 0, 0, 16, 11015, 11020), - (11020, -1, -1, 11007, 11007, 12, 86, -1, 0, 0, 17, 11016, -1), - (11050, -1, -1, 11050, 11050, 6, 85, -1, 0, 0, 16, -1, 11051), - (11051, -1, -1, 11050, 11050, 6, 85, -1, 0, 0, 16, 11050, 11052), - (11052, -1, -1, 11050, 11050, 6, 85, -1, 0, 0, 16, 11051, 11059), - (11053, -1, -1, 6349, 6349, 6, 83, -1, 0, 0, 16, 7620, 11054), - (11054, -1, -1, 6349, 6349, 6, 83, -1, 0, 0, 16, 11053, -1), - (11055, 11055, 11055, 11055, 11055, 3, 85, 16884, 63, 20, 16, -1, -1), - (11056, 11056, 11056, 11056, 11056, 6, 85, 16885, 64, 180, 16, -1, -1), - (11057, 11057, 11057, 11057, 11057, 2, 85, 1422, 65, 10, 16, -1, -1), - (11058, 11058, 11058, 11058, 11058, 2, 85, 3243, 66, 10, 16, -1, -1), - (11059, -1, -1, 11050, 11050, 6, 85, -1, 0, 0, 16, 11052, 11060), - (11060, -1, -1, 11050, 11050, 6, 85, -1, 0, 0, 16, 11059, 12871), - (11061, -1, -1, 98, 98, 12, 85, -1, 0, 0, 16, 7586, 11062), - (11062, -1, -1, 98, 98, 12, 85, -1, 0, 0, 16, 11061, 11063), - (11063, -1, -1, 98, 98, 12, 85, -1, 0, 0, 16, 11062, 13921), - (11064, 6290, 6290, 6290, 6290, 7, 85, 23500, 0, 1, 16, 7225, 11065), - (11065, 6290, 6290, 6290, 6290, 9, 85, 23501, 0, 1, 16, 11064, 11066), - (11066, 6290, 6290, 6290, 6290, 12, 85, 23502, 0, 1, 16, 11065, 13229), - (11067, 4944, -1, 4944, 4944, 7, 85, 23506, 0, 1, 16, 7231, 11068), - (11068, 4944, -1, 4944, 4944, 9, 85, 23507, 0, 1, 16, 11067, 11069), - (11069, 4944, -1, 4944, 4944, 12, 85, 23508, 0, 1, 16, 11068, 13232), - (11070, 1478, -1, 1478, 1478, 9, 85, 23512, 0, 1, 16, 7244, 11071), - (11071, 1478, -1, 1478, 1478, 10, 85, 23513, 0, 1, 16, 11070, 11072), - (11072, 1478, -1, 1478, 1478, 12, 85, 23514, 0, 1, 16, 11071, 13235), - (11073, 11073, 11073, 11073, 11073, 12, 85, 23518, 53, 30, 16, -1, 13447), - (11074, -1, -1, 11074, 11074, 5, 81, 0, 0, 0, 16, -1, 11075), - (11075, -1, -1, 11074, 11074, 7, 83, 0, 0, 0, 16, 11074, 11076), - (11076, -1, -1, 11074, 11074, 9, 85, 0, 0, 0, 16, 11075, -1), - (11077, -1, -1, 11077, 11077, 5, 81, 0, 0, 0, 16, -1, 15895), - (11078, -1, -1, 11078, 11078, 5, 81, 0, 0, 0, 16, -1, 15891), - (11079, -1, -1, 11079, 11079, 5, 81, 0, 0, 0, 16, -1, 15893), - (11080, 11080, 11080, 11080, 11080, 7, 85, 23519, 10, 20, 16, -1, 13472), - (11081, 153, 153, 153, 153, 12, 85, 23599, 3, 2160, 16, 10193, 12996), - (11082, -1, -1, 1131, 1131, 6, 81, -1, 0, 0, 16, 1133, 11083), - (11083, -1, -1, 1131, 1131, 9, 83, -1, 0, 0, 16, 11082, 11084), - (11084, -1, -1, 1131, 1131, 12, 85, -1, 0, 0, 16, 11083, 13032), - (11085, -1, -1, 11085, 11085, 7, 85, 0, 0, 0, 16, -1, 11086), - (11086, -1, -1, 11085, 11085, 9, 85, 0, 0, 0, 16, 11085, 11087), - (11087, -1, -1, 11085, 11085, 12, 85, 0, 0, 0, 16, 11086, 13021), - (11088, -1, -1, 11088, 11088, 6, 75, 0, 0, 0, 16, -1, 11089), - (11089, -1, -1, 11088, 11088, 6, 75, 0, 0, 0, 16, 11088, 11090), - (11090, -1, -1, 11088, 11088, 6, 75, 0, 0, 0, 16, 11089, 11091), - (11091, -1, -1, 11088, 11088, 6, 75, 0, 0, 0, 16, 11090, -1), - (12396, -1, -1, 125, 125, 8, 85, -1, 0, 0, 16, 7505, 12397), - (12397, -1, -1, 125, 125, 9, 85, -1, 0, 0, 16, 12396, 12398), - (12398, -1, -1, 125, 125, 10, 85, -1, 0, 0, 16, 12397, 12399), - (12399, -1, -1, 125, 125, 11, 85, -1, 0, 0, 16, 12398, 12400), - (12400, -1, -1, 125, 125, 12, 85, -1, 0, 0, 16, 12399, 13080), - (12401, -1, -1, 122, 122, 8, 85, -1, 0, 0, 16, 7510, 12402), - (12402, -1, -1, 122, 122, 9, 85, -1, 0, 0, 16, 12401, 12403), - (12403, -1, -1, 122, 122, 10, 85, -1, 0, 0, 16, 12402, 12404), - (12404, -1, -1, 122, 122, 11, 85, -1, 0, 0, 16, 12403, 12405), - (12405, -1, -1, 122, 122, 12, 85, -1, 0, 0, 16, 12404, 13085), - (12406, -1, -1, 6119, 6119, 6, 85, -1, 0, 0, 16, 7530, 12407), - (12407, -1, -1, 6119, 6119, 6, 85, -1, 0, 0, 16, 12406, 12408), - (12408, -1, -1, 6119, 6119, 6, 85, -1, 0, 0, 16, 12407, 12409), - (12409, -1, -1, 6119, 6119, 6, 85, -1, 0, 0, 16, 12408, 12410), - (12410, -1, -1, 6119, 6119, 6, 85, -1, 0, 0, 16, 12409, 12492), - (12411, -1, -1, 8255, 8255, 6, 85, -1, 0, 0, 16, 8259, 12412), - (12412, -1, -1, 8255, 8255, 6, 85, -1, 0, 0, 16, 12411, 12413), - (12413, -1, -1, 8255, 8255, 6, 85, -1, 0, 0, 16, 12412, 12414), - (12414, -1, -1, 8255, 8255, 6, 85, -1, 0, 0, 16, 12413, 12415), - (12415, -1, -1, 8255, 8255, 6, 85, -1, 0, 0, 16, 12414, 13358), - (12416, -1, -1, 12416, 12416, 7, 83, -1, 0, 0, 16, -1, 12417), - (12417, -1, -1, 12416, 12416, 9, 84, -1, 0, 0, 16, 12416, 12418), - (12418, -1, -1, 12416, 12416, 12, 85, -1, 0, 0, 16, 12417, 13413), - (12419, -1, -1, 12419, 12419, 5, 83, -1, 0, 0, 16, -1, 12420), - (12420, -1, -1, 12419, 12419, 5, 84, -1, 0, 0, 16, 12419, 12421), - (12421, -1, -1, 12419, 12419, 5, 85, -1, 0, 0, 16, 12420, 12575), - (12422, 12422, 12422, 12422, 12422, 12, 85, 13994, 47, 12, 16, -1, -1), - (12423, -1, -1, 767, 767, 9, 81, -1, 0, 0, 16, 1101, 12424), - (12424, -1, -1, 767, 767, 10, 83, -1, 0, 0, 16, 12423, 12425), - (12425, -1, -1, 767, 767, 12, 85, -1, 0, 0, 16, 12424, -1), - (12426, -1, -1, 767, 767, 3, 81, -1, 0, 0, 16, 6245, 12427), - (12427, -1, -1, 767, 767, 6, 83, -1, 0, 0, 16, 12426, 12428), - (12428, -1, -1, 767, 767, 9, 85, -1, 0, 0, 16, 12427, -1), - (12432, -1, -1, 1107, 1107, 10, 81, -1, 0, 0, 16, 6405, 12433), - (12433, -1, -1, 1107, 1107, 11, 83, -1, 0, 0, 16, 12432, 12434), - (12434, -1, -1, 1107, 1107, 12, 85, -1, 0, 0, 16, 12433, 12556), - (12435, -1, -1, 637, 637, 8, 81, -1, 0, 0, 16, 5573, 12436), - (12436, -1, -1, 637, 637, 10, 83, -1, 0, 0, 16, 12435, 12437), - (12437, -1, -1, 637, 637, 12, 85, -1, 0, 0, 16, 12436, 12553), - (12438, -1, -1, 686, 686, 5, 85, -1, 0, 0, 16, 7640, -1), - (12439, -1, -1, 1592, 1592, 9, 85, -1, 0, 0, 16, 7572, 12440), - (12440, -1, -1, 1592, 1592, 10, 85, -1, 0, 0, 16, 12439, 12441), - (12441, -1, -1, 1592, 1592, 11, 85, -1, 0, 0, 16, 12440, 12442), - (12442, -1, -1, 1592, 1592, 12, 85, -1, 0, 0, 16, 12441, 12443), - (12443, -1, -1, 1592, 1592, 12, 85, -1, 0, 0, 16, 12442, 12532), - (12444, -1, -1, 1072, 1072, 8, 85, -1, 0, 0, 16, 7580, 12445), - (12445, -1, -1, 1072, 1072, 9, 85, -1, 0, 0, 16, 12444, 12446), - (12446, -1, -1, 1072, 1072, 10, 85, -1, 0, 0, 16, 12445, 12447), - (12447, -1, -1, 1072, 1072, 11, 85, -1, 0, 0, 16, 12446, 12448), - (12448, -1, -1, 1072, 1072, 12, 85, -1, 0, 0, 16, 12447, 12537), - (12449, -1, -1, 77, 77, 10, 81, -1, 0, 0, 16, 1085, 12450), - (12450, -1, -1, 77, 77, 11, 83, -1, 0, 0, 16, 12449, 12451), - (12451, -1, -1, 77, 77, 12, 85, -1, 0, 0, 16, 12450, 12497), - (12452, -1, -1, 80, 80, 12, 85, -1, 0, 0, 16, 7592, 12453), - (12453, -1, -1, 80, 80, 12, 85, -1, 0, 0, 16, 12452, 12454), - (12454, -1, -1, 80, 80, 12, 85, -1, 0, 0, 16, 12453, 12567), - (12455, -1, -1, 658, 658, 5, 85, -1, 0, 0, 16, 7597, 12456), - (12456, -1, -1, 658, 658, 5, 85, -1, 0, 0, 16, 12455, 12457), - (12457, -1, -1, 658, 658, 5, 85, -1, 0, 0, 16, 12456, 12458), - (12458, -1, -1, 658, 658, 5, 85, -1, 0, 0, 16, 12457, 12459), - (12459, -1, -1, 658, 658, 5, 85, -1, 0, 0, 16, 12458, 12570), - (12460, 6537, 6537, 6537, 6537, 7, 83, 20172, 30, 900, 16, 7608, 12461), - (12461, 6537, 6537, 6537, 6537, 8, 83, 20173, 30, 900, 16, 12460, 12462), - (12462, 6537, 6537, 6537, 6537, 9, 83, 20174, 30, 900, 16, 12461, 12520), - (12463, -1, -1, 5263, 5263, 7, 81, -1, 0, 0, 16, 6129, 12464), - (12464, -1, -1, 5263, 5263, 8, 81, -1, 0, 0, 16, 12463, 12465), - (12465, -1, -1, 5263, 5263, 9, 81, -1, 0, 0, 16, 12464, 16173), - (12466, -1, -1, 5263, 5263, 7, 81, -1, 0, 0, 16, 5622, 12467), - (12467, -1, -1, 5263, 5263, 9, 81, -1, 0, 0, 16, 12466, 12468), - (12468, -1, -1, 5263, 5263, 12, 81, -1, 0, 0, 16, 12467, 15714), - (12469, -1, -1, 1287, 1287, 7, 81, -1, 0, 0, 16, 5518, 12470), - (12470, -1, -1, 1287, 1287, 9, 81, -1, 0, 0, 16, 12469, 12471), - (12471, -1, -1, 1287, 1287, 12, 81, -1, 0, 0, 16, 12470, 10637), - (12472, -1, -1, 1287, 1287, 8, 81, -1, 0, 0, 16, 6430, 12473), - (12473, -1, -1, 1287, 1287, 9, 81, -1, 0, 0, 16, 12472, 12474), - (12474, -1, -1, 1287, 1287, 10, 81, -1, 0, 0, 16, 12473, 13238), - (12475, -1, -1, 12430, 12430, 5, 85, 0, 0, 0, 16, -1, 12476), - (12476, -1, -1, 12430, 12430, 7, 85, 0, 0, 0, 16, 12475, 12477), - (12477, -1, -1, 12430, 12430, 9, 85, 0, 0, 0, 16, 12476, 12876), - (12478, -1, -1, 12478, 12478, 5, 85, 0, 0, 0, 16, -1, 12479), - (12479, -1, -1, 12478, 12478, 7, 85, 0, 0, 0, 16, 12478, 12480), - (12480, -1, -1, 12478, 12478, 9, 85, 0, 0, 0, 16, 12479, -1), - (12481, -1, -1, 6540, 6540, 8, 85, -1, 0, 0, 16, 6473, 12482), - (12482, -1, -1, 6540, 6540, 8, 85, -1, 0, 0, 16, 12481, 12508), - (12483, -1, -1, 6540, 6540, 8, 85, -1, 0, 0, 16, 6475, 12484), - (12484, -1, -1, 6540, 6540, 8, 85, -1, 0, 0, 16, 12483, 12511), - (12485, -1, -1, 6540, 6540, 8, 85, -1, 0, 0, 16, 6477, 12486), - (12486, -1, -1, 6540, 6540, 8, 85, -1, 0, 0, 16, 12485, 12514), - (12487, -1, -1, 6540, 6540, 8, 83, -1, 0, 0, 16, 6471, 12488), - (12488, -1, -1, 6540, 6540, 8, 85, -1, 0, 0, 16, 12487, 12517), - (12492, -1, -1, 6119, 6119, 6, 85, -1, 0, 0, 17, 12410, 12493), - (12493, -1, -1, 6119, 6119, 6, 86, -1, 0, 0, 17, 12492, 12494), - (12494, -1, -1, 6119, 6119, 6, 87, -1, 0, 0, 17, 12493, 12495), - (12495, -1, -1, 6119, 6119, 6, 88, -1, 0, 0, 17, 12494, 12496), - (12496, -1, -1, 6119, 6119, 6, 89, -1, 0, 0, 17, 12495, 8448), - (12497, -1, -1, 77, 77, 12, 86, -1, 0, 0, 17, 12451, 12498), - (12498, -1, -1, 77, 77, 12, 88, -1, 0, 0, 17, 12497, 12499), - (12499, -1, -1, 77, 77, 12, 90, -1, 0, 0, 17, 12498, 13296), - (12500, -1, -1, 12500, 12500, 5, 81, -1, 0, 0, 16, -1, 12501), - (12501, -1, -1, 12500, 12500, 7, 81, -1, 0, 0, 16, 12500, 12502), - (12502, -1, -1, 12500, 12500, 9, 81, -1, 0, 0, 16, 12501, 12505), - (12505, -1, -1, 12500, 12500, 11, 83, -1, 0, 0, 16, 12502, 12506), - (12506, -1, -1, 12500, 12500, 12, 85, -1, 0, 0, 16, 12505, -1), - (12507, -1, -1, 199, 199, 12, 81, -1, 0, 0, 16, 201, -1), - (12508, -1, -1, 6540, 6540, 8, 86, -1, 0, 0, 17, 12482, 12509), - (12509, -1, -1, 6540, 6540, 8, 88, -1, 0, 0, 17, 12508, 12510), - (12510, -1, -1, 6540, 6540, 8, 90, -1, 0, 0, 17, 12509, 16440), - (12511, -1, -1, 6540, 6540, 8, 86, -1, 0, 0, 17, 12484, 12512), - (12512, -1, -1, 6540, 6540, 8, 88, -1, 0, 0, 17, 12511, 12513), - (12513, -1, -1, 6540, 6540, 8, 90, -1, 0, 0, 17, 12512, 12591), - (12514, -1, -1, 6540, 6540, 8, 86, -1, 0, 0, 17, 12486, 12515), - (12515, -1, -1, 6540, 6540, 8, 88, -1, 0, 0, 17, 12514, 12516), - (12516, -1, -1, 6540, 6540, 8, 90, -1, 0, 0, 17, 12515, 12594), - (12517, -1, -1, 6540, 6540, 8, 86, -1, 0, 0, 17, 12488, 12518), - (12518, -1, -1, 6540, 6540, 8, 88, -1, 0, 0, 17, 12517, 12519), - (12519, -1, -1, 6540, 6540, 8, 90, -1, 0, 0, 17, 12518, 12597), - (12520, 6537, 6537, 6537, 6537, 7, 86, 23974, 30, 900, 17, 12462, 12521), - (12521, 6537, 6537, 6537, 6537, 8, 88, 23975, 30, 900, 17, 12520, 12522), - (12522, 6537, 6537, 6537, 6537, 9, 90, 23976, 30, 900, 17, 12521, 13275), - (12523, -1, -1, 1210, 1210, 7, 86, -1, 0, 0, 17, 7234, 12524), - (12526, -1, -1, 1210, 1213, 12, 86, -1, 0, 0, 17, 8346, 12527), - (12527, -1, -1, 1210, 1213, 12, 88, -1, 0, 0, 17, 12526, 12528), - (12528, -1, -1, 1210, 1213, 12, 90, -1, 0, 0, 17, 12527, 14349), - (12529, -1, -1, 6636, 6636, 9, 86, -1, 0, 0, 17, 10043, 12530), - (12530, -1, -1, 6636, 6636, 10, 88, -1, 0, 0, 17, 12529, 12531), - (12531, -1, -1, 6636, 6636, 11, 90, -1, 0, 0, 17, 12530, 16164), - (12532, -1, -1, 1592, 1592, 9, 86, -1, 0, 0, 17, 12443, 12533), - (12533, -1, -1, 1592, 1592, 10, 87, -1, 0, 0, 17, 12532, 12534), - (12534, -1, -1, 1592, 1592, 11, 88, -1, 0, 0, 17, 12533, 12535), - (12535, -1, -1, 1592, 1592, 12, 89, -1, 0, 0, 17, 12534, 12536), - (12536, -1, -1, 1592, 1592, 12, 90, -1, 0, 0, 17, 12535, 13930), - (12537, -1, -1, 1072, 1072, 8, 86, -1, 0, 0, 17, 12448, 12538), - (12538, -1, -1, 1072, 1072, 9, 87, -1, 0, 0, 17, 12537, 12539), - (12539, -1, -1, 1072, 1072, 10, 88, -1, 0, 0, 17, 12538, 12540), - (12540, -1, -1, 1072, 1072, 11, 89, -1, 0, 0, 17, 12539, 12541), - (12541, -1, -1, 1072, 1072, 12, 90, -1, 0, 0, 17, 12540, 13281), - (12548, -1, -1, 119, 119, 12, 86, -1, 0, 0, 17, 6025, 12549), - (12549, -1, -1, 119, 119, 12, 87, -1, 0, 0, 17, 12548, 12550), - (12550, -1, -1, 119, 119, 12, 88, -1, 0, 0, 17, 12549, 12551), - (12551, -1, -1, 119, 119, 12, 89, -1, 0, 0, 17, 12550, 12552), - (12552, -1, -1, 119, 119, 12, 90, -1, 0, 0, 17, 12551, 13286), - (12553, -1, -1, 637, 637, 8, 86, -1, 0, 0, 17, 12437, 12554), - (12554, -1, -1, 637, 637, 10, 88, -1, 0, 0, 17, 12553, 12555), - (12555, -1, -1, 637, 637, 12, 90, -1, 0, 0, 17, 12554, 14361), - (12556, -1, -1, 1107, 1107, 10, 86, -1, 0, 0, 17, 12434, 12557), - (12557, -1, -1, 1107, 1107, 11, 88, -1, 0, 0, 17, 12556, 12558), - (12558, -1, -1, 1107, 1107, 12, 90, -1, 0, 0, 17, 12557, 16489), - (12559, -1, -1, 8215, 8215, 5, 86, -1, 0, 0, 17, 8219, 12560), - (12560, -1, -1, 8215, 8215, 5, 87, -1, 0, 0, 17, 12559, 12561), - (12561, -1, -1, 8215, 8215, 5, 88, -1, 0, 0, 17, 12560, 12562), - (12562, -1, -1, 8215, 8215, 5, 89, -1, 0, 0, 17, 12561, 12563), - (12563, -1, -1, 8215, 8215, 5, 90, -1, 0, 0, 17, 12562, 15694), - (12564, -1, -1, 1186, 1186, 12, 86, -1, 0, 0, 17, 7694, 12565), - (12565, -1, -1, 1186, 1186, 12, 88, -1, 0, 0, 17, 12564, 12566), - (12566, -1, -1, 1186, 1186, 12, 90, -1, 0, 0, 17, 12565, 13299), - (12567, -1, -1, 80, 80, 12, 86, -1, 0, 0, 17, 12454, 12568), - (12568, -1, -1, 80, 80, 12, 88, -1, 0, 0, 17, 12567, 12569), - (12569, -1, -1, 80, 80, 12, 90, -1, 0, 0, 17, 12568, 13302), - (12570, -1, -1, 658, 658, 5, 86, -1, 0, 0, 17, 12459, 12571), - (12571, -1, -1, 658, 658, 5, 87, -1, 0, 0, 17, 12570, 12572), - (12572, -1, -1, 658, 658, 5, 88, -1, 0, 0, 17, 12571, 12573), - (12573, -1, -1, 658, 658, 5, 89, -1, 0, 0, 17, 12572, 12574), - (12574, -1, -1, 658, 658, 5, 90, -1, 0, 0, 17, 12573, 13313), - (12575, -1, -1, 12419, 12419, 9, 90, -1, 0, 0, 17, 12421, 13520), - (12576, -1, -1, 852, 852, 12, 86, -1, 0, 0, 17, 7680, 12577), - (12577, -1, -1, 852, 852, 12, 88, -1, 0, 0, 17, 12576, 12578), - (12578, -1, -1, 852, 852, 12, 90, -1, 0, 0, 17, 12577, 13601), - (12579, -1, -1, 1313, 1313, 12, 86, -1, 0, 0, 17, 10083, 12580), - (12580, -1, -1, 1313, 1313, 12, 88, -1, 0, 0, 17, 12579, 12581), - (12581, -1, -1, 1313, 1313, 12, 90, -1, 0, 0, 17, 12580, 14043), - (12582, -1, -1, 12582, 12582, 7, 85, 0, 0, 0, 17, -1, 12583), - (12583, -1, -1, 12582, 12582, 9, 87, 0, 0, 0, 17, 12582, 12584), - (12584, -1, -1, 12582, 12582, 12, 89, 0, 0, 0, 17, 12583, 15174), - (12585, 6640, 6640, 6640, 6640, 9, 86, 23572, 43, 60, 17, 6640, -1), - (12586, 6644, 6644, 6644, 6644, 2, 86, 23573, 44, 20, 17, 6644, -1), - (12587, -1, -1, 7757, 7757, 9, 86, -1, 0, 0, 17, 7759, 12588), - (12588, -1, -1, 7757, 7757, 9, 88, -1, 0, 0, 17, 12587, 12589), - (12589, -1, -1, 7757, 7757, 9, 90, -1, 0, 0, 17, 12588, 15182), - (12590, 10395, 10395, 10395, 10395, 5, 85, 23574, 62, 5, 17, 10395, -1), - (12591, -1, -1, 6540, 6540, 15, 91, -1, 0, 0, 18, 12513, 12592), - (12594, -1, -1, 6540, 6540, 11, 91, -1, 0, 0, 18, 12516, 12595), - (12597, -1, -1, 6540, 6540, 9, 91, -1, 0, 0, 18, 12519, 12598), - (12598, -1, -1, 6540, 6540, 11, 93, -1, 0, 0, 18, 12597, 12599), - (12600, -1, -1, 12600, 12600, 7, 85, 0, 0, 0, 17, -1, 13072), - (12603, -1, -1, 12603, 12603, 10, 70, 0, 0, 0, 17, -1, -1), - (12606, -1, -1, 12606, 12606, 6, 85, 0, 0, 0, 17, -1, -1), - (12607, -1, -1, 12607, 12607, 6, 74, 0, 0, 0, 17, -1, 14140), - (12610, -1, -1, 255, 255, 9, 87, -1, 0, 0, 17, 7702, 13773), - (12612, -1, -1, 1604, 1604, 10, 85, -1, 0, 0, 17, 7009, 12613), - (12613, -1, -1, 1604, 1604, 12, 87, -1, 0, 0, 17, 12612, 13095), - (12615, -1, -1, 12615, 12615, 10, 85, 0, 0, 0, 17, -1, 12616), - (12616, -1, -1, 12615, 12615, 12, 87, 0, 0, 0, 17, 12615, 12617), - (12617, -1, -1, 12615, 12615, 14, 89, 0, 0, 0, 17, 12616, 14138), - (12618, 5021, 5021, 5021, 5021, 9, 86, 24009, 7, 60, 17, 10870, 12619), - (12619, 5021, 5021, 5021, 5021, 9, 87, 24010, 7, 60, 17, 12618, 12620), - (12620, 5021, 5021, 5021, 5021, 9, 88, 24011, 7, 60, 17, 12619, 12621), - (12621, 5021, 5021, 5021, 5021, 9, 89, 24012, 7, 60, 17, 12620, 13785), - (12626, 9354, 9354, 9354, 9354, 5, 86, 23996, 40, 600, 17, 9356, -1), - (12629, 9357, 9357, 9357, 9357, 5, 86, 24002, 40, 600, 17, 9359, -1), - (12632, 9360, 9360, 9360, 9360, 5, 86, 24005, 40, 600, 17, 9362, -1), - (12633, 6325, 6325, 6325, 6325, 7, 85, 24008, 18, 600, 17, 6361, 13792), - (12635, 12635, 12635, 12635, 12635, 12, 90, 23643, 12, 5, 17, -1, -1), - (12636, -1, -1, 12636, 12636, 0, 1, -1, 0, 0, 16, -1, 12637), - (12637, -1, -1, 12636, 12636, 0, 1, -1, 0, 0, 16, 12636, 8445), - (12638, 12638, 12638, 12638, 12638, 9, 85, 23581, 68, 10, 17, -1, -1), - (12639, -1, -1, 10514, 10514, 6, 86, -1, 0, 0, 17, 10515, 12640), - (12642, -1, -1, 10511, 10511, 6, 86, -1, 0, 0, 17, 10513, 12643), - (12645, -1, -1, 12645, 12645, 9, 90, 0, 0, 0, 17, -1, 15386), - (12646, -1, -1, 12646, 12646, 9, 90, 0, 0, 0, 17, -1, 15388), - (12647, 10502, -1, 10502, 10502, 7, 90, 16815, 64, 120, 17, 10502, -1), - (12648, 10503, 10503, 10503, 10503, 9, 86, 23582, 13, 600, 17, 10505, 12649), - (12651, 12651, 12651, 12651, 12651, 15, 90, 23585, 69, 600, 17, -1, 17352), - (12652, -1, -1, 12652, 12652, 9, 86, 0, 0, 0, 17, -1, 12653), - (12653, -1, -1, 12652, 12652, 12, 88, 0, 0, 0, 17, 12652, 12654), - (12654, -1, -1, 12652, 12652, 15, 90, 0, 0, 0, 17, 12653, 13411), - (12655, 12655, 12655, 12655, 12655, 9, 86, 23586, 70, 1800, 17, -1, 12656), - (12658, 757, -1, 757, 757, 12, 86, 23589, 6, 1800, 17, 7413, 12659), - (12661, 12661, 12661, 12661, 12661, 9, 86, 23592, 73, 2700, 17, -1, 12662), - (12664, -1, -1, 12664, 12664, 7, 86, 0, 0, 0, 17, -1, 12665), - (12667, -1, -1, 820, 820, 5, 86, -1, 0, 0, 17, 10662, 12668), - (12668, -1, -1, 820, 820, 5, 88, -1, 0, 0, 17, 12667, 12669), - (12669, -1, -1, 820, 820, 5, 90, -1, 0, 0, 17, 12668, 13820), - (12670, -1, -1, 6020, 6020, 2, 86, -1, 0, 0, 17, 10665, 12671), - (12671, -1, -1, 6020, 6020, 2, 87, -1, 0, 0, 17, 12670, 12672), - (12672, -1, -1, 6020, 6020, 2, 88, -1, 0, 0, 17, 12671, 12692), - (12673, -1, -1, 1546, 1546, 5, 80, -1, 0, 0, 17, 6441, -1), - (12674, -1, -1, 4801, 4801, 6, 86, -1, 0, 0, 17, 10123, 12675), - (12675, -1, -1, 4801, 4801, 6, 88, -1, 0, 0, 17, 12674, 12676), - (12676, -1, -1, 4801, 4801, 6, 90, -1, 0, 0, 17, 12675, -1), - (12677, -1, -1, 230, 230, 6, 90, -1, 0, 0, 17, 541, 16249), - (12678, -1, -1, 10656, 10656, 12, 90, 0, 0, 0, 17, 10656, -1), - (12679, -1, -1, 10657, 10657, 7, 86, 0, 0, 0, 17, 10659, 12680), - (12680, -1, -1, 10657, 10657, 9, 88, 0, 0, 0, 17, 12679, 12681), - (12681, -1, -1, 10657, 10657, 12, 90, 0, 0, 0, 17, 12680, 14154), - (12682, 7872, 7872, 7872, 7872, 6, 86, 23595, 41, 600, 17, 10129, 12683), - (12683, 7872, 7872, 7872, 7872, 6, 88, 23596, 41, 600, 17, 12682, 12684), - (12684, 7872, 7872, 7872, 7872, 6, 90, 23597, 41, 600, 17, 12683, 13838), - (12685, -1, -1, 807, 807, 5, 86, -1, 0, 0, 17, 7630, 12686), - (12686, -1, -1, 807, 807, 5, 88, -1, 0, 0, 17, 12685, 12687), - (12687, -1, -1, 807, 807, 5, 90, -1, 0, 0, 17, 12686, -1), - (12688, -1, -1, 12688, 12688, 12, 90, 0, 0, 0, 17, -1, -1), - (12689, -1, -1, 7884, 7884, 12, 87, -1, 0, 0, 17, 7884, -1), - (12690, -1, -1, 7885, 7885, 12, 86, -1, 0, 0, 17, 7885, -1), - (12691, -1, -1, 12691, 12691, 12, 88, 0, 0, 0, 17, -1, -1), - (12692, -1, -1, 6020, 6020, 2, 89, -1, 0, 0, 17, 12672, 12693), - (12693, -1, -1, 6020, 6020, 2, 90, -1, 0, 0, 17, 12692, 13823), - (12694, -1, -1, 683, 683, 5, 86, -1, 0, 0, 17, 7605, 12695), - (12695, -1, -1, 683, 683, 5, 88, -1, 0, 0, 17, 12694, 12696), - (12696, -1, -1, 683, 683, 5, 90, -1, 0, 0, 17, 12695, 13305), - (12697, -1, -1, 1041, 1041, 12, 86, -1, 0, 0, 17, 7564, 12698), - (12698, -1, -1, 1041, 1041, 12, 88, -1, 0, 0, 17, 12697, 12699), - (12699, -1, -1, 1041, 1041, 12, 90, -1, 0, 0, 17, 12698, 13332), - (12700, 1355, 1355, 1355, 1355, 9, 86, 23644, 3, 60, 17, 10121, 12701), - (12701, 1355, 1355, 1355, 1355, 9, 88, 23645, 3, 60, 17, 12700, 12702), - (12702, 1355, 1355, 1355, 1355, 9, 90, 23646, 3, 60, 17, 12701, 13832), - (12703, -1, -1, 611, 611, 4, 86, -1, 0, 0, 17, 10126, 12704), - (12704, -1, -1, 611, 611, 4, 88, -1, 0, 0, 17, 12703, 12705), - (12705, -1, -1, 611, 611, 4, 90, -1, 0, 0, 17, 12704, 13835), - (12706, -1, -1, 12706, 12706, 7, 86, 0, 0, 0, 17, -1, 12707), - (12707, -1, -1, 12706, 12706, 9, 88, 0, 0, 0, 17, 12706, 12708), - (12708, -1, -1, 12706, 12706, 12, 90, 0, 0, 0, 17, 12707, 13813), - (12709, -1, -1, 12709, 12709, 9, 86, -1, 0, 0, 17, -1, -1), - (12710, -1, -1, 12710, 12710, 9, 86, 0, 0, 0, 17, -1, 12711), - (12711, -1, -1, 12710, 12710, 12, 88, 0, 0, 0, 17, 12710, 12712), - (12712, -1, -1, 12710, 12710, 15, 90, 0, 0, 0, 17, 12711, 14173), - (12713, -1, -1, 12713, 12713, 7, 86, 0, 0, 0, 17, -1, 12714), - (12714, -1, -1, 12713, 12713, 7, 88, 0, 0, 0, 17, 12713, 12715), - (12715, -1, -1, 12713, 12713, 7, 90, 0, 0, 0, 17, 12714, -1), - (12716, -1, -1, 12716, 12716, 7, 86, 0, 0, 0, 17, -1, 12717), - (12717, -1, -1, 12716, 12716, 7, 88, 0, 0, 0, 17, 12716, 12718), - (12718, -1, -1, 12716, 12716, 7, 90, 0, 0, 0, 17, 12717, 15526), - (12719, -1, -1, 12719, 12719, 9, 90, 0, 0, 0, 17, -1, -1), - (12720, -1, -1, 12720, 12720, 9, 86, 0, 0, 0, 17, -1, -1), - (12721, -1, -1, 12721, 12721, 7, 86, 0, 0, 0, 17, -1, 12722), - (12722, -1, -1, 12721, 12721, 9, 88, 0, 0, 0, 17, 12721, 12723), - (12723, -1, -1, 12721, 12721, 12, 90, 0, 0, 0, 17, 12722, 16303), - (12724, 10333, 10333, 10333, 10333, 9, 86, 23647, 55, 120, 17, 10335, 12725), - (12725, 10333, 10333, 10333, 10333, 9, 86, 23648, 55, 120, 17, 12724, 12726), - (12726, 10333, 10333, 10333, 10333, 9, 86, 23649, 55, 120, 17, 12725, 15988), - (12727, -1, -1, 1555, 1555, 7, 86, 0, 0, 0, 17, 1557, 12728), - (12728, -1, -1, 1555, 1555, 7, 88, 0, 0, 0, 17, 12727, 12729), - (12729, -1, -1, 1555, 1555, 7, 90, 0, 0, 0, 17, 12728, -1), - (12730, 10336, 10336, 10336, 10336, 9, 86, 23650, 58, 8, 17, 10338, 12731), - (12731, 10336, 10336, 10336, 10336, 12, 88, 23651, 58, 8, 17, 12730, 12732), - (12732, 10336, 10336, 10336, 10336, 15, 90, 23652, 58, 8, 17, 12731, 13517), - (12733, -1, -1, 10332, 10332, 7, 90, -1, 0, 0, 17, 10332, -1), - (12734, -1, -1, 6375, 6375, 9, 86, -1, 0, 0, 17, 10138, 12735), - (12735, -1, -1, 6375, 6375, 9, 88, -1, 0, 0, 17, 12734, 12736), - (12736, -1, -1, 6375, 6375, 9, 90, -1, 0, 0, 17, 12735, 13502), - (12737, -1, -1, 12737, 12737, 9, 86, 0, 0, 0, 17, -1, 12738), - (12738, -1, -1, 12737, 12737, 9, 88, 0, 0, 0, 17, 12737, 12739), - (12739, -1, -1, 12737, 12737, 9, 90, 0, 0, 0, 17, 12738, 15961), - (12740, 6533, 6533, 6533, 6533, 10, 86, 23653, 15, 600, 17, 10139, 12741), - (12741, 6533, 6533, 6533, 6533, 10, 88, 23654, 15, 600, 17, 12740, 12742), - (12742, 6533, 6533, 6533, 6533, 10, 90, 23655, 15, 600, 17, 12741, 13505), - (12743, 1116, 1116, 1116, 1116, 12, 86, 23656, 4, 2160, 17, 10142, 12744), - (12744, 1116, 1116, 1116, 1116, 12, 88, 23657, 4, 2160, 17, 12743, 12745), - (12745, 1116, 1116, 1116, 1116, 12, 90, 23658, 4, 2160, 17, 12744, 13530), - (12746, 5298, 5298, 5298, 5298, 12, 86, 23659, 32, 1800, 17, 10145, 12747), - (12747, 5298, 5298, 5298, 5298, 12, 88, 23660, 32, 1800, 17, 12746, 12748), - (12748, 5298, 5298, 5298, 5298, 12, 90, 23661, 32, 1800, 17, 12747, 13514), - (12749, 592, 592, 592, 592, 5, 86, 23665, 2, 18, 17, 7437, 12750), - (12750, 592, 592, 592, 592, 5, 88, 23666, 2, 18, 17, 12749, 12751), - (12751, 592, 592, 592, 592, 5, 90, 23667, 2, 18, 17, 12750, 13499), - (12754, 10701, 10701, 10701, 10701, 12, 86, 23668, 32, 360, 17, 10703, 12755), - (12755, 10701, 10701, 10701, 10701, 12, 88, 23669, 32, 360, 17, 12754, 12756), - (12756, 10701, 10701, 10701, 10701, 12, 90, 23670, 32, 360, 17, 12755, 15588), - (12757, -1, -1, 4861, 4861, 12, 86, -1, 0, 0, 17, 7682, 12758), - (12758, -1, -1, 4861, 4861, 12, 88, -1, 0, 0, 17, 12757, 12759), - (12759, -1, -1, 4861, 4861, 12, 90, -1, 0, 0, 17, 12758, -1), - (12760, 1274, 1274, 1274, 1274, 12, 86, 23674, 9, 540, 17, 10211, 12761), - (12761, 1274, 1274, 1274, 1274, 12, 88, 23675, 9, 540, 17, 12760, 12762), - (12762, 1274, 1274, 1274, 1274, 12, 90, 23676, 9, 540, 17, 12761, 14352), - (12766, 12766, 12766, 12766, 12766, 15, 90, 23677, 69, 3600, 17, -1, 13682), - (12767, -1, -1, 692, 692, 12, 86, -1, 0, 0, 17, 7672, 12768), - (12768, -1, -1, 692, 692, 12, 88, -1, 0, 0, 17, 12767, 12769), - (12769, -1, -1, 692, 692, 12, 90, -1, 0, 0, 17, 12768, 17295), - (12770, 12770, 12770, 12770, 12770, 9, 85, 23678, 52, 120, 17, -1, 12771), - (12771, 12770, 12770, 12770, 12770, 12, 87, 23679, 52, 120, 17, 12770, 12772), - (12772, 12770, 12770, 12770, 12770, 15, 89, 23680, 52, 120, 17, 12771, -1), - (12773, -1, -1, 12773, 12773, 7, 86, 0, 0, 0, 17, -1, 12774), - (12774, -1, -1, 12773, 12773, 7, 87, 0, 0, 0, 17, 12773, 12775), - (12775, -1, -1, 12773, 12773, 7, 88, 0, 0, 0, 17, 12774, 12776), - (12776, -1, -1, 12773, 12773, 7, 89, 0, 0, 0, 17, 12775, 12777), - (12777, -1, -1, 12773, 12773, 7, 90, 0, 0, 0, 17, 12776, -1), - (12778, 12778, 12778, 12778, 12778, 12, 90, 23681, 74, 1200, 17, -1, 13678), - (12779, -1, -1, 12779, 12779, 7, 85, 0, 0, 0, 17, -1, 12780), - (12780, -1, -1, 12779, 12779, 9, 87, 0, 0, 0, 17, 12779, 12781), - (12781, -1, -1, 12779, 12779, 12, 89, 0, 0, 0, 17, 12780, -1), - (12782, -1, -1, 12782, 12782, 7, 86, 0, 0, 0, 17, -1, 12783), - (12783, -1, -1, 12782, 12782, 9, 88, 0, 0, 0, 17, 12782, 12784), - (12784, -1, -1, 12782, 12782, 12, 90, 0, 0, 0, 17, 12783, -1), - (12785, 12785, 12785, 12785, 12785, 12, 90, 23683, 80, 30, 17, -1, 17131), - (12786, 6815, 6815, 6815, 6815, 8, 86, 23684, 60, 600, 17, 10202, 12787), - (12787, 6815, 6815, 6815, 6815, 8, 88, 23685, 60, 600, 17, 12786, 12788), - (12788, 6815, 6815, 6815, 6815, 8, 90, 23686, 60, 600, 17, 12787, 14355), - (12789, 967, 967, 967, 967, 7, 85, 23687, 10, 1800, 17, 10226, 12790), - (12790, 967, 967, 967, 967, 7, 87, 23688, 10, 1800, 17, 12789, 12791), - (12791, 967, 967, 967, 967, 7, 89, 23689, 10, 1800, 17, 12790, 17535), - (12792, -1, -1, 9503, 9503, 7, 86, -1, 0, 0, 17, 10089, 12793), - (12793, -1, -1, 9503, 9503, 7, 88, -1, 0, 0, 17, 12792, 12794), - (12794, -1, -1, 9503, 9503, 7, 90, -1, 0, 0, 17, 12793, 5360), - (12795, -1, -1, 6051, 6051, 5, 85, -1, 0, 0, 17, 10606, 12796), - (12796, -1, -1, 6051, 6051, 5, 87, -1, 0, 0, 17, 12795, 12797), - (12797, -1, -1, 6051, 6051, 5, 89, -1, 0, 0, 17, 12796, 13278), - (12798, -1, -1, 5264, 5264, 12, 86, -1, 0, 0, 17, 10217, 12799), - (12799, -1, -1, 5264, 5264, 12, 88, -1, 0, 0, 17, 12798, 12800), - (12800, -1, -1, 5264, 5264, 12, 90, -1, 0, 0, 17, 12799, 13675), - (12801, -1, -1, 6383, 6383, 9, 85, -1, 0, 0, 17, 10609, 12802), - (12802, -1, -1, 6383, 6383, 9, 87, -1, 0, 0, 17, 12801, 12803), - (12803, -1, -1, 6383, 6383, 9, 89, -1, 0, 0, 17, 12802, 5339), - (12804, 12804, 12804, 12804, 12804, 7, 86, 23693, 75, 900, 17, -1, 12805), - (12807, 12807, 12807, 12807, 12807, 7, 86, 23699, 73, 1200, 17, -1, 12808), - (12810, 8227, 8227, 8227, 12810, 5, 85, 27402, 71, 10, 17, 8227, 12811), - (12811, 8227, 8227, 8227, 12810, 7, 87, 27403, 71, 10, 17, 12810, 12812), - (12812, 8227, 8227, 8227, 12810, 9, 89, 27404, 71, 10, 17, 12811, -1), - (12813, -1, -1, 1287, 1287, 5, 75, -1, 0, 0, 17, -1, 12814), - (12814, -1, -1, 1287, 1287, 5, 77, -1, 0, 0, 17, 12813, 12815), - (12815, -1, -1, 1287, 1287, 5, 79, -1, 0, 0, 17, 12814, 14279), - (12816, -1, -1, 12816, 12816, 7, 86, 0, 0, 0, 17, -1, 12817), - (12819, -1, -1, 12819, 12819, 9, 85, 0, 0, 0, 17, -1, 12820), - (12820, -1, -1, 12819, 12819, 12, 87, 0, 0, 0, 17, 12819, 12821), - (12822, -1, -1, 12822, 12822, 9, 86, 0, 0, 0, 17, -1, 12823), - (12828, 291, 291, 291, 12828, 12, 86, 27409, 5, 900, 17, 10304, 12829), - (12831, -1, -1, 12831, 12831, 7, 86, 0, 0, 0, 17, -1, 12832), - (12834, -1, -1, 6980, 6980, 5, 85, -1, 0, 0, 17, 6982, 12835), - (12835, -1, -1, 6980, 6980, 5, 87, -1, 0, 0, 17, 12834, 12836), - (12837, 12837, 12837, 12837, 12837, 7, 86, 27412, 74, 420, 17, -1, 12838), - (12840, -1, -1, 6977, 6977, 5, 85, -1, 0, 0, 17, 6979, 12841), - (12841, -1, -1, 6977, 6977, 5, 87, -1, 0, 0, 17, 12840, 12842), - (12843, -1, -1, 551, 551, 5, 86, -1, 0, 0, 17, 6907, 12844), - (12846, -1, -1, 12846, 12846, 7, 86, 6499, 0, 0, 17, -1, 12847), - (12849, -1, -1, 12849, 12849, 7, 86, 0, 0, 0, 17, -1, 12850), - (12857, 8072, 8072, 8072, 8072, 7, 86, 27419, 37, 20, 17, 10248, 12858), - (12860, -1, -1, 267, 267, 12, 86, -1, 0, 0, 17, 5619, 12861), - (12863, -1, -1, 141, 12863, 12, 59, -1, 0, 0, 17, 143, 15396), - (12864, 12864, -1, 12864, 12864, 5, 59, 27422, 73, 10, 17, -1, 17486), - (12865, 12865, 12865, 12865, 12865, 12, 90, 27423, 42, 6, 17, -1, -1), - (12866, 12866, 12866, 12866, 12866, 12, 86, 27424, 74, 1800, 17, -1, 15605), - (12867, 12867, 12867, 12867, 12867, 12, 86, 27426, 13, 4320, 17, -1, -1), - (12868, 1334, 1334, 1334, 1334, 12, 86, 27427, 11, 4320, 17, 10236, 12869), - (12871, -1, -1, 11050, 11050, 9, 85, -1, 0, 0, 17, 11060, 12872), - (12872, -1, -1, 11050, 11050, 12, 87, -1, 0, 0, 17, 12871, 12873), - (12874, -1, -1, 1414, 1414, 5, 86, -1, 0, 0, 17, 1418, 17490), - (12875, 4938, 4938, 4938, 4938, 12, 90, 27430, 35, 1800, 17, 5614, 13727), - (12876, -1, -1, 12430, 12430, 7, 86, 0, 0, 0, 17, 12477, 12877), - (12877, -1, -1, 12430, 12430, 9, 88, 0, 0, 0, 17, 12876, 12878), - (12878, -1, -1, 12430, 12430, 12, 90, 0, 0, 0, 17, 12877, 15270), - (12879, 516, 516, 516, 516, 6, 86, 27431, 5, 480, 17, 10233, 13659), - (12880, 1404, 1404, 1404, 1404, 7, 85, 27432, 15, 2160, 17, 1408, -1), - (12881, -1, -1, 12881, 12881, 9, 86, 0, 0, 0, 17, -1, 12882), - (12885, 12885, 12885, 12885, 12885, 12, 86, 27435, 75, 90, 17, -1, 17491), - (12886, -1, -1, 12886, 12886, 2, 85, -1, 0, 0, 17, -1, -1), - (12887, -1, -1, 12887, 12887, 2, 87, -1, 0, 0, 17, -1, -1), - (12888, -1, -1, 12888, 12888, 2, 89, -1, 0, 0, 17, -1, -1), - (12889, -1, -1, 12889, 12889, 2, 85, -1, 0, 0, 17, -1, 12890), - (12890, -1, -1, 12889, 12889, 2, 87, -1, 0, 0, 17, 12889, 12891), - (12892, 12892, 12892, 12892, 12892, 3, 90, 27434, 8, 60, 17, -1, 13666), - (12893, 12893, 12893, 12893, 12893, 12, 90, 27436, 76, 1800, 17, -1, 13663), - (12894, -1, -1, 12894, 12894, 5, 86, 0, 0, 0, 17, -1, 12895), - (12899, -1, -1, 471, 471, 2, 85, -1, 0, 0, 17, 473, 12900), - (12900, -1, -1, 471, 471, 2, 87, -1, 0, 0, 17, 12899, 12901), - (12902, -1, -1, 12902, 12902, 5, 85, 0, 0, 0, 17, -1, 12903), - (12903, -1, -1, 12902, 12902, 5, 86, 0, 0, 0, 17, 12902, 12904), - (12907, -1, -1, 12907, 12907, 5, 85, 0, 0, 0, 17, -1, 12908), - (12908, -1, -1, 12907, 12907, 5, 86, 0, 0, 0, 17, 12907, 12909), - (12912, -1, -1, 12912, 12912, 5, 85, 0, 0, 0, 17, -1, 12913), - (12913, -1, -1, 12912, 12912, 5, 86, 0, 0, 0, 17, 12912, 12914), - (12917, 517, 517, 517, 517, 5, 85, 27437, 12, 600, 17, 10281, 12918), - (12918, 517, 517, 517, 517, 5, 87, 27438, 12, 600, 17, 12917, 12919), - (12920, -1, -1, 12920, 12920, 5, 86, 0, 0, 0, 17, -1, 12921), - (12923, 54009, 54009, 54009, 12923, 3, 85, 27440, 22, 12, 17, 5849, 12924), - (12924, 54009, 54009, 54009, 12923, 3, 87, 27441, 22, 12, 17, 12923, 12925), - (12929, -1, -1, 6548, 6548, 8, 85, -1, 0, 0, 17, 6238, 12930), - (12930, -1, -1, 6548, 6548, 8, 90, -1, 0, 0, 17, 12929, 15463), - (12931, 12931, 12931, 12931, 12931, 7, 86, 27443, 73, 3600, 17, -1, 12932), - (12934, 1242, 1242, 1242, 1242, 12, 86, 27446, 9, 1320, 17, 10273, 12935), - (12937, 12937, 12937, 12937, 12937, 12, 86, 27449, 16, 420, 17, -1, 13733), - (12938, 12938, 12938, 12938, 12938, 15, 88, 27450, 75, 2700, 17, -1, 13743), - (12939, 12939, 12939, 12939, 12939, 12, 90, 27451, 77, 1800, 17, -1, 14756), - (12941, 12941, 12941, 12941, 12941, 5, 85, 27453, 77, 1, 17, -1, -1), - (12942, 6539, 6539, 6539, 6539, 6, 86, 27454, 18, 1800, 17, 7611, 12943), - (12943, 6539, 6539, 6539, 6539, 6, 88, 27455, 18, 1800, 17, 12942, 12944), - (12944, 6539, 6539, 6539, 6539, 6, 90, 27456, 18, 1800, 17, 12943, 13291), - (12945, -1, -1, 795, 795, 12, 85, -1, 0, 0, 17, 10267, 12946), - (12946, -1, -1, 795, 795, 12, 86, -1, 0, 0, 17, 12945, 12947), - (12947, -1, -1, 795, 795, 12, 87, -1, 0, 0, 17, 12946, 12948), - (12948, -1, -1, 795, 795, 12, 88, -1, 0, 0, 17, 12947, 12949), - (12949, -1, -1, 795, 795, 12, 89, -1, 0, 0, 17, 12948, 13710), - (12950, -1, -1, 790, 790, 6, 86, -1, 0, 0, 17, 7274, 12951), - (12951, -1, -1, 790, 790, 6, 87, -1, 0, 0, 17, 12950, 12952), - (12952, -1, -1, 790, 790, 6, 88, -1, 0, 0, 17, 12951, 12953), - (12953, -1, -1, 790, 790, 6, 89, -1, 0, 0, 17, 12952, 12954), - (12954, -1, -1, 790, 790, 6, 90, -1, 0, 0, 17, 12953, 13713), - (12955, 167, 167, 167, 167, 10, 86, 27457, 14, 900, 17, 8343, 13718), - (12956, 4903, 4903, 4903, 4903, 9, 85, 27460, 9, 1320, 17, 10255, 13698), - (12957, 4909, 4909, 4909, 4909, 9, 85, 27461, 16, 1320, 17, 10257, 14733), - (12958, 4912, 4912, 4912, 4912, 9, 85, 27459, 16, 1320, 17, 10258, 13704), - (12959, 4906, 4906, 4906, 4906, 9, 85, 27458, 9, 1320, 17, 10256, 13701), - (12963, 12963, 12963, 12963, 12963, 7, 86, 27465, 81, 5, 17, -1, -1), - (12964, 12964, 12964, 12964, 12964, 7, 88, 27466, 81, 5, 17, -1, -1), - (12965, 12965, 12965, 12965, 12965, 7, 90, 27467, 81, 5, 17, -1, -1), - (12966, -1, -1, 6112, 6112, 5, 87, -1, 0, 0, 17, 6112, 12967), - (12967, -1, -1, 6112, 6112, 5, 89, -1, 0, 0, 17, 12966, 16402), - (12968, -1, -1, 12968, 12968, 7, 85, 0, 0, 0, 17, -1, 12969), - (12969, -1, -1, 12968, 12968, 7, 87, 0, 0, 0, 17, 12968, 12970), - (12970, -1, -1, 12968, 12968, 7, 89, 0, 0, 0, 17, 12969, 14238), - (12971, 12971, 12971, 12971, 12971, 5, 86, 27471, 79, 2160, 17, -1, 12972), - (12972, 12971, 12971, 12971, 12971, 7, 87, 27472, 79, 2160, 17, 12971, 12973), - (12973, 12971, 12971, 12971, 12971, 9, 88, 27473, 79, 2160, 17, 12972, 12974), - (12974, 12971, 12971, 12971, 12971, 12, 89, 27474, 79, 2160, 17, 12973, 12975), - (12975, 12971, 12971, 12971, 12971, 15, 90, 27475, 79, 2160, 17, 12974, -1), - (12976, 7903, 7903, 7903, 7903, 6, 85, 27476, 60, 30, 17, 7903, 14734), - (12977, -1, -1, 12977, 12977, 5, 85, 0, 0, 0, 17, -1, 12978), - (12978, -1, -1, 12977, 12977, 5, 86, 0, 0, 0, 17, 12977, 12979), - (12979, -1, -1, 12977, 12977, 5, 87, 0, 0, 0, 17, 12978, 12980), - (12980, -1, -1, 12977, 12977, 5, 88, 0, 0, 0, 17, 12979, 12981), - (12981, -1, -1, 12977, 12977, 5, 89, 0, 0, 0, 17, 12980, 17334), - (12982, 10600, 10600, 10600, 10600, 7, 86, 27477, 73, 20, 17, 10602, 12983), - (12983, 10600, 10600, 10600, 10600, 7, 88, 27478, 73, 20, 17, 12982, 12984), - (12984, 10600, 10600, 10600, 10600, 7, 90, 27479, 73, 20, 17, 12983, 13720), - (12985, 520, 520, 520, 520, 12, 86, 27480, 6, 540, 17, 10254, 12986), - (12986, 520, 520, 520, 520, 12, 88, 27481, 6, 540, 17, 12985, 12987), - (12987, 520, 520, 520, 520, 12, 90, 27482, 6, 540, 17, 12986, -1), - (12988, -1, -1, 10959, 12988, 12, 90, -1, 0, 0, 17, 10962, -1), - (12989, 12989, 12989, 12989, 12989, 7, 86, 27486, 73, 1800, 17, -1, 12990), - (12990, 12989, 12989, 12989, 12989, 9, 88, 27487, 73, 1800, 17, 12989, 12991), - (12991, 12989, 12989, 12989, 12989, 12, 90, 27488, 73, 1800, 17, 12990, 5336), - (12992, 12992, 12992, 12992, 12992, 9, 86, 27489, 0, 1, 17, -1, 12993), - (12993, 12992, 12992, 12992, 12992, 12, 88, 27490, 0, 1, 17, 12992, 12994), - (12994, 12992, 12992, 12992, 12992, 15, 90, 27491, 0, 1, 17, 12993, 5350), - (12995, 6563, 6563, 6563, 6563, 12, 86, 27492, 36, 8, 17, 6281, -1), - (12996, 153, 153, 153, 153, 12, 90, 27493, 3, 2160, 17, 11081, 17333), - (12997, 1520, 1520, 1520, 1520, 9, 85, 27494, 11, 900, 17, 10192, 12998), - (12998, 1520, 1520, 1520, 1520, 9, 87, 27495, 11, 900, 17, 12997, 12999), - (12999, 1520, 1520, 1520, 1520, 9, 89, 27496, 11, 900, 17, 12998, 5333), - (13000, 10958, 10958, 10958, 10958, 15, 90, 27497, 62, 900, 17, 10958, 16214), - (13001, -1, -1, 13001, 13001, 7, 86, -1, 0, 0, 17, -1, 13002), - (13002, -1, -1, 13001, 13001, 7, 88, -1, 0, 0, 17, 13001, 13003), - (13003, -1, -1, 13001, 13001, 7, 90, -1, 0, 0, 17, 13002, 15348), - (13004, 13004, 13004, 13004, 13004, 9, 86, 27499, 78, 300, 17, -1, 15855), - (13005, -1, -1, 6703, 6703, 3, 86, -1, 0, 0, 17, 10178, 13006), - (13006, -1, -1, 6703, 6703, 3, 88, -1, 0, 0, 17, 13005, 13007), - (13007, -1, -1, 6703, 6703, 3, 90, -1, 0, 0, 17, 13006, -1), - (13008, 13008, 13008, 13008, 13008, 9, 90, 27500, 86, 300, 17, -1, -1), - (13009, 13009, 13009, 13009, 13009, 6, 86, 27501, 39, 1, 17, -1, -1), - (13010, -1, -1, 13010, 13010, 6, 85, 0, 0, 0, 17, -1, 13011), - (13011, -1, -1, 13010, 13010, 6, 87, 0, 0, 0, 17, 13010, 13012), - (13012, -1, -1, 13010, 13010, 6, 89, 0, 0, 0, 17, 13011, 14223), - (13013, -1, -1, 13013, 13013, 6, 86, 0, 0, 0, 17, -1, 13014), - (13014, -1, -1, 13013, 13013, 6, 88, 0, 0, 0, 17, 13013, 13015), - (13015, -1, -1, 13013, 13013, 6, 90, 0, 0, 0, 17, 13014, -1), - (13016, 5109, 5109, 5109, 5109, 9, 86, 27502, 0, 1, 17, 7467, 5356), - (13017, -1, -1, 13017, 13017, 9, 86, -1, 0, 0, 17, -1, 13018), - (13018, -1, -1, 13017, 13017, 12, 88, -1, 0, 0, 17, 13017, 13019), - (13019, -1, -1, 13017, 13017, 15, 90, -1, 0, 0, 17, 13018, 13396), - (13020, 13020, 13020, 13020, 13020, 12, 86, 27503, 76, 420, 17, -1, -1), - (13021, -1, -1, 11085, 11085, 12, 86, 0, 0, 0, 17, 11087, 13022), - (13023, -1, -1, 1050, 1050, 12, 86, -1, 0, 0, 17, 7658, 13024), - (13026, -1, -1, 599, 599, 12, 86, -1, 0, 0, 17, 7561, 13027), - (13027, -1, -1, 599, 599, 12, 88, -1, 0, 0, 17, 13026, 13028), - (13028, -1, -1, 599, 599, 12, 90, -1, 0, 0, 17, 13027, 13438), - (13029, -1, -1, 7818, 7818, 9, 86, 31681, 0, 0, 17, 7818, 13030), - (13032, -1, -1, 1131, 1131, 9, 85, -1, 0, 0, 17, 11084, 13033), - (13033, -1, -1, 1131, 1131, 12, 87, -1, 0, 0, 17, 13032, 13034), - (13035, -1, -1, 1134, 1134, 3, 86, -1, 0, 0, 17, 10315, 13036), - (13040, -1, -1, 4809, 4809, 5, 86, -1, 0, 0, 17, 10318, 13041), - (13043, -1, -1, 5776, 5776, 9, 86, -1, 0, 0, 17, 7198, 13044), - (13046, -1, -1, 8250, 8250, 6, 85, -1, 0, 0, 17, 8254, 13047), - (13047, -1, -1, 8250, 8250, 6, 86, -1, 0, 0, 17, 13046, 13048), - (13048, -1, -1, 8250, 8250, 6, 87, -1, 0, 0, 17, 13047, 13049), - (13049, -1, -1, 8250, 8250, 6, 88, -1, 0, 0, 17, 13048, 13050), - (13050, -1, -1, 8250, 8250, 6, 89, -1, 0, 0, 17, 13049, 13348), - (13051, -1, -1, 10404, 10404, 6, 90, -1, 0, 0, 17, 10404, -1), - (13052, -1, -1, 10401, 10401, 6, 86, -1, 0, 0, 17, 10403, 13053), - (13055, -1, -1, 13055, 13055, 6, 86, 0, 0, 0, 17, -1, 13056), - (13058, 6931, 6931, 6931, 6931, 12, 90, 27504, 41, 600, 17, 10319, 13857), - (13059, 4854, 4854, 4854, 4854, 9, 86, 27505, 8, 600, 17, 10325, 13060), - (13062, 6932, 6932, 6932, 6932, 7, 86, 27508, 42, 1200, 17, 10322, 13063), - (13065, 13065, 13065, 13065, 13065, 12, 86, 27514, 70, 90, 17, -1, -1), - (13066, 13066, 13066, 13066, 13066, 9, 85, 27516, 71, 1800, 17, -1, -1), - (13067, -1, -1, 13067, 13067, 6, 86, 0, 0, 0, 17, -1, 13068), - (13072, -1, -1, 12600, 12600, 7, 87, 0, 0, 0, 17, 12600, 13073), - (13073, -1, -1, 12600, 12600, 7, 89, 0, 0, 0, 17, 13072, 13222), - (13074, -1, -1, 1044, 1044, 9, 86, -1, 0, 0, 17, 7652, 13075), - (13075, -1, -1, 1044, 1044, 12, 88, -1, 0, 0, 17, 13074, 13076), - (13076, -1, -1, 1044, 1044, 15, 90, -1, 0, 0, 17, 13075, 13326), - (13077, -1, -1, 1047, 1047, 9, 86, -1, 0, 0, 17, 7655, 13078), - (13078, -1, -1, 1047, 1047, 12, 88, -1, 0, 0, 17, 13077, 13079), - (13080, -1, -1, 125, 125, 9, 86, -1, 0, 0, 17, 12400, 13081), - (13081, -1, -1, 125, 125, 10, 87, -1, 0, 0, 17, 13080, 13082), - (13082, -1, -1, 125, 125, 11, 88, -1, 0, 0, 17, 13081, 13083), - (13083, -1, -1, 125, 125, 12, 89, -1, 0, 0, 17, 13082, 13084), - (13084, -1, -1, 125, 125, 13, 90, -1, 0, 0, 17, 13083, 8463), - (13085, -1, -1, 122, 122, 9, 86, -1, 0, 0, 17, 12405, 13086), - (13086, -1, -1, 122, 122, 10, 87, -1, 0, 0, 17, 13085, 13087), - (13087, -1, -1, 122, 122, 11, 88, -1, 0, 0, 17, 13086, 13088), - (13088, -1, -1, 122, 122, 12, 89, -1, 0, 0, 17, 13087, 13089), - (13089, -1, -1, 122, 122, 13, 90, -1, 0, 0, 17, 13088, 8440), - (13090, -1, -1, 1435, 4773, 9, 86, -1, 0, 0, 17, 7621, 13295), - (13091, -1, -1, 1435, 4773, 9, 86, -1, 0, 0, 17, 1650, 13294), - (13092, -1, -1, 644, 644, 9, 85, -1, 0, 0, 17, 7361, 13093), - (13093, -1, -1, 644, 644, 12, 87, -1, 0, 0, 17, 13092, 13094), - (13094, -1, -1, 644, 644, 15, 89, -1, 0, 0, 17, 13093, 13265), - (13095, -1, -1, 1604, 1604, 15, 89, -1, 0, 0, 17, 12613, 13767), - (13096, -1, -1, 13096, 13096, 12, 86, -1, 0, 0, 17, -1, 13097), - (13097, -1, -1, 13096, 13096, 12, 88, -1, 0, 0, 17, 13096, 13098), - (13098, -1, -1, 13096, 13096, 12, 90, -1, 0, 0, 17, 13097, 13127), - (13099, -1, -1, 83, 83, 9, 55, -1, 0, 0, 17, 85, -1), - (13100, 13100, 13100, 13100, 13100, 9, 86, 27534, 86, 300, 17, -1, 15140), - (13101, -1, -1, 13101, 13101, 7, 86, 0, 0, 0, 17, -1, 13102), - (13102, -1, -1, 13101, 13101, 9, 88, 0, 0, 0, 17, 13101, 13103), - (13103, -1, -1, 13101, 13101, 12, 90, 0, 0, 0, 17, 13102, 14082), - (13104, -1, -1, 589, 589, 9, 86, -1, 0, 0, 17, 7709, 13105), - (13105, -1, -1, 589, 589, 9, 88, -1, 0, 0, 17, 13104, 13106), - (13106, -1, -1, 589, 589, 9, 90, -1, 0, 0, 17, 13105, 15778), - (13107, 6645, 6645, 6645, 6645, 9, 90, 27541, 45, 60, 17, 6645, 13633), - (13108, 13108, 13108, 13108, 13108, 5, 90, 27542, 89, 30, 17, -1, -1), - (13109, 1351, 1351, 1351, 1351, 8, 90, 27543, 5, 30, 17, 7109, -1), - (13110, 10815, 10815, 10815, 10815, 9, 86, -1, 0, 0, 17, 10817, 13111), - (13111, 10815, 10815, 10815, 10815, 11, 88, -1, 0, 0, 17, 13110, 13112), - (13113, 10818, 10818, 10818, 10818, 9, 86, -1, 0, 0, 17, 10820, 13114), - (13114, 10818, 10818, 10818, 10818, 11, 88, -1, 0, 0, 17, 13113, 13115), - (13116, 10821, 10821, 10821, 10821, 9, 86, -1, 0, 0, 17, 10823, 13117), - (13117, 10821, 10821, 10821, 10821, 11, 88, -1, 0, 0, 17, 13116, 13118), - (13119, 5007, 5007, 5007, 5007, 9, 86, 27544, 8, 2160, 17, 10063, 13120), - (13120, 5007, 5007, 5007, 5007, 9, 88, 27545, 8, 2160, 17, 13119, 13121), - (13122, -1, -1, 6546, 6546, 0, 86, -1, 0, 0, 17, 7377, 13123), - (13123, -1, -1, 6546, 6546, 0, 87, -1, 0, 0, 17, 13122, 13124), - (13124, -1, -1, 6546, 6546, 0, 88, -1, 0, 0, 17, 13123, 13125), - (13127, -1, -1, 13096, 13096, 12, 91, -1, 0, 0, 18, 13098, 13128), - (13130, 13130, 13130, 13130, 13130, 15, 95, 32440, 48, 30, 18, -1, -1), - (13133, 7756, 7756, 7756, 7756, 12, 85, 21805, 85, 120, 17, -1, -1), - (13134, 13134, 13134, 13134, 13134, 7, 86, 27547, 74, 900, 17, -1, 13135), - (13135, 13134, 13134, 13134, 13134, 7, 88, 27548, 74, 900, 17, 13134, 13136), - (13136, 13134, 13134, 13134, 13134, 7, 90, 27549, 74, 900, 17, 13135, 13380), - (13140, -1, -1, 10464, 10464, 7, 86, -1, 0, 0, 17, 10466, 13141), - (13141, -1, -1, 10464, 10464, 9, 88, -1, 0, 0, 17, 13140, 13142), - (13142, -1, -1, 10464, 10464, 11, 90, -1, 0, 0, 17, 13141, -1), - (13143, -1, -1, 13143, 13143, 5, 86, 0, 0, 0, 17, -1, 13144), - (13144, -1, -1, 13143, 13143, 5, 88, 0, 0, 0, 17, 13143, 13145), - (13145, -1, -1, 13143, 13143, 5, 90, 0, 0, 0, 17, 13144, -1), - (13146, -1, -1, 13146, 13146, 5, 86, 0, 0, 0, 17, -1, 13147), - (13147, -1, -1, 13146, 13146, 5, 88, 0, 0, 0, 17, 13146, 13148), - (13148, -1, -1, 13146, 13146, 5, 90, 0, 0, 0, 17, 13147, -1), - (13149, -1, -1, 8210, 8210, 5, 86, -1, 0, 0, 17, 1655, 13150), - (13150, -1, -1, 8210, 8210, 5, 87, -1, 0, 0, 17, 13149, 13151), - (13151, -1, -1, 8210, 8210, 5, 88, -1, 0, 0, 17, 13150, 13152), - (13152, -1, -1, 8210, 8210, 5, 89, -1, 0, 0, 17, 13151, 13153), - (13153, -1, -1, 8210, 8210, 5, 90, -1, 0, 0, 17, 13152, 13318), - (13154, 5105, 5105, 5105, 5105, 12, 90, 27550, 11, 600, 17, 10509, 14023), - (13155, 7986, 7986, 7986, 7986, 12, 90, 27551, 11, 600, 17, 10510, 14022), - (13158, 548, 548, 548, 548, 10, 86, 27552, 5, 900, 17, 10098, 13159), - (13161, 528, 528, 528, 528, 12, 86, 27555, 5, 720, 17, 10196, 13162), - (13162, 528, 528, 528, 528, 12, 88, 27556, 5, 720, 17, 13161, 13163), - (13163, 528, 528, 528, 528, 12, 90, 27557, 5, 720, 17, 13162, 5357), - (13164, 13164, 13164, 13164, 13164, 9, 86, 27540, 99, 180, 17, -1, -1), - (13165, 13165, 13165, 13165, 13165, 9, 86, 27559, 56, 60, 17, -1, -1), - (13166, -1, -1, 13166, 13166, 7, 86, 0, 0, 0, 17, -1, 13167), - (13167, -1, -1, 13166, 13166, 7, 88, 0, 0, 0, 17, 13166, 13168), - (13168, -1, -1, 13166, 13166, 7, 90, 0, 0, 0, 17, 13167, -1), - (13169, 13169, 13169, 13169, 13169, 9, 90, 27560, 99, 180, 17, -1, 17221), - (13170, 6380, 6380, 6380, 6380, 6, 86, 27561, 39, 120, 17, 10310, 13171), - (13173, 290, 290, 290, 290, 8, 86, 27564, 4, 720, 17, 290, 13448), - (13174, 10374, 10374, 10374, 10374, 6, 85, 27565, 63, 900, 17, 10376, 13175), - (13175, 10374, 10374, 10374, 10374, 8, 87, 27566, 63, 900, 17, 13174, 13176), - (13177, 6984, 6984, 6984, 6984, 6, 83, 27568, 60, 60, 17, 10294, 13466), - (13178, 6986, 6986, 6986, 6986, 6, 83, 27570, 60, 60, 17, 10296, 13468), - (13179, 6985, 6985, 6985, 6985, 6, 83, 27569, 60, 60, 17, 10295, 13467), - (13180, 10377, 10377, 10377, 10377, 6, 86, 16796, 64, 60, 17, 10379, 13181), - (13183, 10346, 10346, 10346, 10346, 9, 90, 27574, 46, 600, 17, 10346, 13819), - (13184, -1, -1, 10340, 10340, 9, 86, -1, 0, 0, 17, 10342, 13185), - (13185, -1, -1, 10340, 10340, 9, 88, -1, 0, 0, 17, 13184, 13186), - (13186, -1, -1, 10340, 10340, 9, 90, -1, 0, 0, 17, 13185, 13829), - (13187, -1, -1, 9512, 9512, 7, 86, -1, 0, 0, 17, 7883, 13188), - (13188, -1, -1, 9512, 9512, 7, 88, -1, 0, 0, 17, 13187, 13189), - (13189, -1, -1, 9512, 9512, 7, 90, -1, 0, 0, 17, 13188, 13826), - (13190, 1110, 1110, 1110, 1110, 6, 86, 27576, 3, 2160, 17, 10152, 13191), - (13191, 1110, 1110, 1110, 1110, 6, 88, 27577, 3, 2160, 17, 13190, 13192), - (13192, 1110, 1110, 1110, 1110, 6, 90, 27578, 3, 2160, 17, 13191, 13496), - (13193, 1598, -1, 1598, 1598, 9, 86, 27582, 6, 900, 17, 10148, 13194), - (13194, 1598, -1, 1598, 1598, 11, 88, 27583, 6, 900, 17, 13193, 13195), - (13195, 1598, -1, 1598, 1598, 13, 90, 27584, 6, 900, 17, 13194, 13493), - (13196, -1, -1, 255, 255, 9, 86, -1, 0, 0, 17, 10135, 13197), - (13197, -1, -1, 255, 255, 9, 88, -1, 0, 0, 17, 13196, 13198), - (13198, -1, -1, 255, 255, 9, 90, -1, 0, 0, 17, 13197, 13511), - (13199, -1, -1, 8322, 8322, 9, 86, 0, 0, 0, 17, 8324, 13200), - (13200, -1, -1, 8322, 8322, 9, 88, 0, 0, 0, 17, 13199, 13201), - (13201, -1, -1, 8322, 8322, 9, 90, 0, 0, 0, 17, 13200, -1), - (13202, 13202, 13202, 13202, 13202, 2, 81, 27585, 98, 20, 17, -1, 14009), - (13203, 10330, 10330, 10330, 10330, 7, 90, 27586, 35, 30, 17, 10330, 13492), - (13204, -1, -1, 13204, 13204, 7, 86, -1, 0, 0, 17, -1, 13205), - (13205, -1, -1, 13204, 13204, 7, 88, -1, 0, 0, 17, 13204, 13206), - (13206, -1, -1, 13204, 13204, 7, 90, -1, 0, 0, 17, 13205, 14176), - (13207, -1, -1, 10850, 10850, 9, 86, 27587, 0, 0, 17, 10852, 13208), - (13208, -1, -1, 10850, 10850, 9, 88, 27588, 0, 0, 17, 13207, 13209), - (13209, -1, -1, 10850, 10850, 9, 90, 27589, 0, 0, 17, 13208, 13779), - (13210, -1, -1, 1307, 1307, 5, 81, -1, 0, 0, 17, 6662, 13211), - (13211, -1, -1, 1307, 1307, 5, 83, -1, 0, 0, 17, 13210, 13212), - (13212, -1, -1, 1307, 1307, 5, 85, -1, 0, 0, 17, 13211, -1), - (13213, -1, -1, 1543, 1543, 7, 86, -1, 0, 0, 17, 10167, 13214), - (13214, -1, -1, 1543, 1543, 7, 87, -1, 0, 0, 17, 13213, 13215), - (13215, -1, -1, 1543, 1543, 7, 88, -1, 0, 0, 17, 13214, 13216), - (13216, -1, -1, 1543, 1543, 7, 89, -1, 0, 0, 17, 13215, 13217), - (13217, -1, -1, 1543, 1543, 7, 90, -1, 0, 0, 17, 13216, 13782), - (13218, -1, -1, 1304, 1304, 12, 90, -1, 0, 0, 17, 10867, 13789), - (13219, -1, -1, 8325, 8325, 7, 85, 0, 0, 0, 17, 8327, 13220), - (13220, -1, -1, 8325, 8325, 9, 87, 0, 0, 0, 17, 13219, 13221), - (13221, -1, -1, 8325, 8325, 11, 89, 0, 0, 0, 17, 13220, 13798), - (13222, -1, -1, 12600, 12600, 7, 89, 0, 0, 0, 17, 13073, 13223), - (13223, -1, -1, 12600, 12600, 7, 89, 0, 0, 0, 17, 13222, -1), - (13224, 13224, -1, 13224, 13224, 3, 86, 27590, 98, 1, 17, -1, 15559), - (13225, 13225, 13225, 13225, 13225, 6, 86, 27592, 0, 4, 17, -1, 13688), - (13226, -1, -1, 5295, 5295, 6, 86, -1, 0, 0, 17, 10229, 13227), - (13229, 6290, 6290, 6290, 6290, 9, 86, 27596, 0, 1, 17, 11066, 13230), - (13232, 4944, -1, 4944, 4944, 9, 86, 27602, 0, 1, 17, 11069, 13233), - (13235, 1478, -1, 1478, 1478, 9, 86, 27608, 0, 1, 17, 11072, 13236), - (13238, -1, -1, 1287, 1287, 9, 86, -1, 0, 0, 17, 12474, 13239), - (13239, -1, -1, 1287, 1287, 10, 88, -1, 0, 0, 17, 13238, 13240), - (13240, -1, -1, 1287, 1287, 11, 90, -1, 0, 0, 17, 13239, 15719), - (13241, 4931, 4931, 4931, 4931, 7, 86, 27614, 4, 600, 17, 10430, 13242), - (13244, 1501, 1501, 1501, 1501, 6, 86, 27617, 10, 4320, 17, 1560, 13245), - (13247, 4894, 4894, 4894, 4894, 6, 86, 27620, 7, 2160, 17, 7290, 13248), - (13250, 10550, 10550, 10550, 10550, 7, 90, 27626, 61, 120, 17, 10550, 13728), - (13251, 1239, 1239, 1239, 1239, 9, 90, 27627, 6, 600, 17, 7275, 13732), - (13252, 13252, 13252, 13252, 13252, 9, 86, 27629, 95, 4, 17, -1, 16065), - (13253, 1126, 1126, 1126, 1126, 7, 85, 27630, 2, 2160, 17, 5515, 13254), - (13254, 1126, 1126, 1126, 1126, 7, 87, 27631, 2, 2160, 17, 13253, 13255), - (13255, 1126, 1126, 1126, 1126, 7, 89, 27632, 2, 2160, 17, 13254, 13723), - (13256, 146, 146, 146, 146, 8, 86, 27633, 2, 180, 17, 7691, 13257), - (13257, 146, 146, 146, 146, 8, 88, 27634, 2, 180, 17, 13256, 13258), - (13258, 146, 146, 146, 146, 8, 90, 27635, 2, 180, 17, 13257, 14222), - (13259, 1195, 1195, 1195, 1195, 9, 90, 27661, 13, 2160, 17, 10015, 15334), - (13260, 13260, 13260, 13260, 13260, 0, 80, 27664, 98, 3600, 17, -1, -1), - (13261, 13261, 13261, 13261, 13261, 0, 81, 27665, 98, 28800, 17, -1, -1), - (13262, -1, -1, 498, 498, 5, 70, -1, 0, 0, 16, 975, 13263), - (13263, -1, -1, 498, 498, 5, 75, -1, 0, 0, 16, 13262, 13264), - (13264, -1, -1, 498, 498, 5, 80, -1, 0, 0, 16, 13263, -1), - (13271, 13271, 13271, 13271, 13271, 0, 80, 27691, 97, 3600, 18, -1, -1), - (13272, 13272, 13272, 13272, 13272, 0, 81, 27692, 97, 28800, 18, -1, -1), - (13275, 6537, 6537, 6537, 6537, 10, 91, 30638, 30, 900, 18, 12522, 13276), - (13278, -1, -1, 6051, 6051, 10, 91, -1, 0, 0, 18, 12797, 13279), - (13281, -1, -1, 1072, 1072, 12, 91, -1, 0, 0, 18, 12541, 13282), - (13286, -1, -1, 119, 119, 12, 91, -1, 0, 0, 18, 12552, 13287), - (13291, 6539, 6539, 6539, 6539, 9, 91, 30641, 18, 1800, 18, 12944, 13292), - (13294, -1, -1, 1435, 4773, 12, 91, -1, 0, 0, 18, 13091, 14490), - (13295, -1, -1, 1435, 4773, 12, 91, -1, 0, 0, 18, 13090, 14491), - (13296, -1, -1, 77, 77, 12, 91, -1, 0, 0, 18, 12499, 13297), - (13297, -1, -1, 77, 77, 12, 93, -1, 0, 0, 18, 13296, 13298), - (13299, -1, -1, 1186, 1186, 12, 91, -1, 0, 0, 18, 12566, 13300), - (13302, -1, -1, 80, 80, 12, 91, -1, 0, 0, 18, 12569, 13303), - (13305, -1, -1, 683, 683, 10, 91, -1, 0, 0, 18, 12696, 13306), - (13308, -1, -1, 446, 735, 10, 91, -1, 0, 0, 18, 10477, 13309), - (13313, -1, -1, 658, 658, 8, 91, -1, 0, 0, 18, 12574, 13314), - (13318, -1, -1, 8210, 8210, 10, 91, -1, 0, 0, 18, 13153, 13319), - (13323, -1, -1, 1287, 1287, 12, 91, -1, 0, 0, 18, 10639, 13324), - (13326, -1, -1, 1044, 1044, 10, 91, -1, 0, 0, 18, 13076, 13327), - (13332, -1, -1, 1041, 1041, 11, 91, -1, 0, 0, 18, 12699, 13333), - (13338, -1, -1, 8245, 8245, 11, 91, -1, 0, 0, 18, 8426, 13339), - (13343, -1, -1, 8240, 8240, 11, 91, -1, 0, 0, 18, 10785, 13344), - (13348, -1, -1, 8250, 8250, 11, 91, -1, 0, 0, 18, 13050, 13349), - (13353, -1, -1, 8235, 8235, 11, 91, -1, 0, 0, 18, 8308, 13354), - (13358, -1, -1, 8255, 8255, 11, 91, -1, 0, 0, 18, 12415, 13359), - (13363, 1192, 1192, 1192, 1192, 9, 91, 30645, 12, 1320, 18, 10021, 13364), - (13383, 6488, 6488, 6488, 6488, 15, 91, 30657, 32, 900, 18, 6488, 13384), - (13385, 13385, 13385, 13385, 13385, 12, 91, 30659, 75, 600, 18, -1, 13386), - (13388, 13388, 13388, 13388, 13388, 12, 91, 30665, 79, 180, 18, -1, -1), - (13389, 13389, -1, 13389, 13389, 5, 91, 30666, 77, 12, 18, -1, 15832), - (13396, -1, -1, 13017, 13017, 15, 91, -1, 0, 0, 18, 13019, 13397), - (13401, 1498, 1498, 1498, 1498, 15, 91, 30679, 12, 1320, 18, 10092, 13402), - (13404, -1, -1, 1514, 1514, 11, 91, -1, 0, 0, 18, 1516, 13405), - (13410, 645, -1, 645, 645, 15, 95, 30682, 4, 5, 18, 10739, -1), - (13411, -1, -1, 12652, 12652, 15, 92, 0, 0, 0, 18, 12654, 13412), - (13413, -1, -1, 12416, 12416, 15, 91, -1, 0, 0, 18, 12418, 13414), - (13415, -1, -1, 7989, 7989, 9, 95, -1, 0, 0, 18, 7992, -1), - (13416, -1, -1, 13416, 13416, 9, 91, 0, 0, 0, 18, -1, 13417), - (13419, 13419, 13419, 13419, 13419, 12, 91, 30683, 99, 600, 18, -1, 13420), - (13425, 54006, 54006, 54006, 54006, 9, 91, 30692, 18, 180, 18, 10006, 13426), - (13438, -1, -1, 599, 599, 13, 91, -1, 0, 0, 18, 13028, 13439), - (13444, 13444, 13444, 13444, 13444, 9, 91, 30699, 75, 600, 18, -1, 13445), - (13447, 11073, 11073, 11073, 11073, 12, 95, 30705, 53, 30, 18, 11073, 15412), - (13449, -1, -1, 13449, 13449, 5, 91, -1, 0, 0, 18, -1, 13450), - (13454, 718, 718, 718, 718, 12, 91, 30711, 7, 4320, 18, 1019, 14855), - (13463, -1, -1, 13463, 13463, 7, 91, -1, 0, 0, 18, -1, 13464), - (13466, 6984, 6984, 6984, 6984, 9, 91, 30721, 60, 60, 18, 13177, 13469), - (13467, 6985, 6985, 6985, 6985, 9, 91, 30723, 60, 60, 18, 13179, 13470), - (13468, 6986, 6986, 6986, 6986, 12, 92, 30725, 60, 60, 18, 13178, 13471), - (13472, 11080, 11080, 11080, 11080, 11, 91, 30727, 10, 20, 18, 11080, 13473), - (13474, -1, -1, 13474, 13474, 9, 91, -1, 0, 0, 18, -1, 13475), - (13477, -1, -1, 10380, 10380, 11, 91, -1, 0, 0, 18, 10382, 13478), - (13483, 13483, 13483, 13483, 13483, 5, 91, 30735, 68, 20, 18, -1, -1), - (13484, 13484, -1, 13484, 13484, 12, 95, 30736, 76, 720, 18, -1, 15879), - (13485, -1, -1, 13485, 13485, 7, 91, -1, 0, 0, 18, -1, 13486), - (13490, 5020, 5020, 5020, 5020, 9, 91, 30742, 9, 300, 18, 10149, 13491), - (13492, 10330, 10330, 10330, 10330, 12, 95, 30744, 35, 30, 18, 13203, 14797), - (13493, 1598, -1, 1598, 1598, 11, 91, 30745, 6, 900, 18, 13195, 13494), - (13496, 1110, 1110, 1110, 1110, 9, 91, 30748, 3, 2160, 18, 13192, 13497), - (13499, 592, 592, 592, 592, 9, 91, 30754, 2, 18, 18, 12751, 13500), - (13502, -1, -1, 6375, 6375, 9, 91, -1, 0, 0, 18, 12736, 13503), - (13505, 6533, 6533, 6533, 6533, 11, 91, 30757, 15, 600, 18, 12742, 13506), - (13508, -1, -1, 8314, 8314, 9, 91, -1, 0, 0, 18, 8316, 13509), - (13511, -1, -1, 255, 255, 9, 91, -1, 0, 0, 18, 13198, 13512), - (13514, 5298, 5298, 5298, 5298, 12, 91, 30760, 32, 1800, 18, 12748, 13515), - (13517, 10336, 10336, 10336, 10336, 11, 91, 30766, 58, 8, 18, 12732, 13518), - (13520, -1, -1, 12419, 12419, 15, 95, -1, 0, 0, 18, 12575, 16886), - (13521, -1, -1, 6386, 6386, 9, 91, -1, 0, 0, 18, 6389, 13522), - (13524, 6534, 6534, 6534, 6534, 11, 91, 30769, 16, 900, 18, 7429, 13525), - (13527, 13527, 13527, 13527, 13527, 9, 91, 30772, 18, 9, 18, -1, 15964), - (13528, 13528, 13528, 13528, 13528, 10, 91, 30773, 42, 60, 18, -1, -1), - (13529, 13529, 13529, 13529, 13529, 15, 95, 30774, 41, 120, 18, -1, -1), - (13530, 1116, 1116, 1116, 1116, 12, 91, 30775, 4, 2160, 18, 12745, 13531), - (13533, -1, -1, 7010, 7010, 9, 91, -1, 0, 0, 18, 7015, 13534), - (13542, 6755, 6755, 6755, 6755, 12, 91, 30784, 42, 900, 18, 6757, 13543), - (13545, -1, -1, 10388, 10388, 12, 95, -1, 0, 0, 18, 10388, 15293), - (13546, 6758, 6758, 6758, 6758, 11, 91, 32360, 43, 900, 18, 10056, 13547), - (13549, 13549, 13549, 13549, 13549, 15, 95, 30788, 64, 180, 18, -1, -1), - (13556, 13556, 13556, 13556, 13556, 9, 91, 30792, 44, 600, 18, -1, 13557), - (13562, -1, -1, 10719, 10719, 15, 91, 0, 0, 0, 18, 10721, 13563), - (13565, -1, -1, 13565, 13565, 11, 91, 0, 0, 0, 18, -1, 13566), - (13568, -1, -1, 13568, 13568, 11, 91, 0, 0, 0, 18, -1, 13569), - (13571, 13571, 13571, 13571, 13571, 12, 91, 30795, 50, 60, 18, -1, -1), - (13575, 5095, 5095, 5095, 5095, 11, 91, 30796, 10, 900, 18, 10642, 13576), - (13578, 0, 0, 10348, 10348, 9, 91, -1, 0, 0, 18, 10350, 13579), - (13584, 10394, 10394, 10394, 10394, 15, 91, 30799, 30, 300, 18, 10704, 14981), - (13585, 7712, 7712, 7712, 7712, 15, 95, 30800, 2, 30, 18, 10646, 15095), - (13586, 188, 188, 188, 188, 12, 91, 30801, 2, 30, 18, 10647, 13587), - (13589, -1, -1, 255, 255, 13, 91, -1, 0, 0, 18, 10625, 13590), - (13590, -1, -1, 255, 255, 15, 93, -1, 0, 0, 18, 13589, 13591), - (13592, 5984, 5984, 5984, 5984, 12, 91, 30803, 2, 30, 18, 10626, 13593), - (13595, 534, 534, 534, 534, 12, 91, 30806, 4, 2160, 18, 10710, 13596), - (13598, -1, -1, 6791, 6791, 11, 91, -1, 0, 0, 18, 10678, 13599), - (13601, -1, -1, 852, 852, 11, 91, -1, 0, 0, 18, 12578, 13602), - (13604, 7850, 7850, 7850, 7850, 15, 91, 30812, 39, 4320, 18, 10620, 13605), - (13607, -1, -1, 10453, 10453, 11, 91, -1, 0, 0, 18, 10455, 13608), - (13610, -1, -1, 602, 602, 12, 91, -1, 0, 0, 18, 10687, 13611), - (13613, -1, -1, 855, 855, 11, 91, -1, 0, 0, 18, 10692, 13614), - (13616, -1, -1, 13616, 13616, 7, 91, -1, 0, 0, 18, -1, 13617), - (13617, -1, -1, 13616, 13616, 9, 93, -1, 0, 0, 18, 13616, 13618), - (13618, -1, -1, 13616, 13616, 12, 95, -1, 0, 0, 18, 13617, 14786), - (13619, 7800, 7800, 7800, 7800, 15, 91, 30815, 39, 4320, 18, 10787, 13620), - (13621, -1, -1, 6630, 6630, 9, 91, -1, 0, 0, 18, 10074, 13622), - (13624, 10900, 10900, 10900, 10900, 9, 91, 30817, 55, 120, 18, 10902, 13625), - (13627, -1, -1, 895, 895, 9, 91, -1, 0, 0, 18, 10908, 13628), - (13628, -1, -1, 895, 895, 12, 93, -1, 0, 0, 18, 13627, 13629), - (13630, -1, -1, 9506, 9506, 11, 91, -1, 0, 0, 18, 9508, 13631), - (13633, 6645, 6645, 6645, 6645, 15, 95, 30820, 45, 60, 18, 13107, 15178), - (13646, 13646, 13646, 13646, 13646, 15, 91, 30837, 45, 600, 18, -1, -1), - (13650, 8060, 8060, 8060, 8060, 9, 91, 31524, 41, 1800, 18, 10239, 13651), - (13653, 8063, 8063, 8063, 8063, 9, 91, 31527, 41, 1800, 18, 10242, 13654), - (13656, 8066, 8066, 8066, 8066, 11, 91, 31530, 41, 1800, 18, 10245, 13657), - (13663, 12893, 12893, 12893, 12893, 15, 91, 31534, 76, 1800, 18, 12893, 13664), - (13667, -1, -1, 13667, 13667, 11, 91, -1, 0, 0, 18, -1, 13668), - (13670, 13670, 13670, 13670, 13670, 12, 91, 31538, 43, 1800, 18, -1, 13671), - (13673, 13673, 13673, 13673, 13673, 18, 95, 32050, 0, 1, 18, -1, -1), - (13674, 13674, 13674, 13674, 13674, 18, 95, 32058, 0, 1, 18, -1, -1), - (13675, -1, -1, 5264, 5264, 12, 91, -1, 0, 0, 18, 12800, 13676), - (13678, 13678, 13678, 13678, 13678, 15, 95, 31543, 74, 1200, 18, 12778, -1), - (13682, 12766, 12766, 12766, 12766, 18, 95, 31545, 69, 3600, 18, 12766, -1), - (13683, 6822, 6822, 6822, 6822, 15, 91, 31546, 42, 120, 18, 6822, 14780), - (13684, -1, -1, 13684, 13684, 9, 91, -1, 0, 0, 18, -1, 13685), - (13685, -1, -1, 13684, 13684, 12, 93, -1, 0, 0, 18, 13684, 13686), - (13686, -1, -1, 13684, 13684, 15, 95, -1, 0, 0, 18, 13685, 16653), - (13687, 13687, 13687, 13687, 13687, 15, 91, 31547, 75, 300, 18, -1, 17521), - (13688, 13225, 13225, 13225, 13225, 12, 91, 31548, 0, 4, 18, 13225, 15620), - (13689, -1, -1, 13689, 13689, 9, 91, -1, 0, 0, 18, -1, 13690), - (13692, 12208, 12208, 12208, 12208, 6, 91, 31549, 17, 12, 18, -1, -1), - (13693, 13693, 13693, 13693, 13693, 18, 95, 31550, 76, 500, 18, -1, 17531), - (13695, 13695, 13695, 13695, 13695, 12, 91, 31577, 91, 1320, 18, -1, 13696), - (13698, 4903, 4903, 4903, 4903, 12, 91, 31580, 9, 1320, 18, 12956, 13699), - (13701, 4906, 4906, 4906, 4906, 12, 91, 31583, 9, 1320, 18, 12959, 13702), - (13704, 4912, 4912, 4912, 4912, 12, 91, 31586, 16, 1320, 18, 12958, 13705), - (13707, -1, -1, 1577, 1577, 12, 91, -1, 0, 0, 18, 10264, 13708), - (13710, -1, -1, 795, 795, 9, 91, -1, 0, 0, 18, 12949, 13711), - (13713, -1, -1, 790, 790, 6, 91, -1, 0, 0, 18, 12954, 13714), - (13718, 167, 167, 167, 167, 12, 91, 31589, 14, 900, 18, 12955, 13719), - (13720, 10600, 10600, 10600, 10600, 11, 91, 31591, 73, 20, 18, 12984, 13721), - (13723, 1126, 1126, 1126, 1126, 11, 91, 31594, 2, 2160, 18, 13255, 13724), - (13726, 1017, 1017, 1017, 1017, 12, 91, 31597, 75, 15, 18, 1017, -1), - (13727, 4938, 4938, 4938, 4938, 12, 95, 31598, 35, 1800, 18, 12875, 16031), - (13734, 773, -1, 773, 773, 9, 91, 31606, 5, 1800, 18, 10566, 13735), - (13753, -1, -1, 13753, 13753, 5, 91, -1, 0, 0, 18, -1, 13754), - (13758, -1, -1, 13758, 13758, 5, 91, -1, 0, 0, 18, -1, 13759), - (13763, -1, -1, 781, 781, 12, 95, -1, 0, 0, 18, 7284, -1), - (13764, -1, -1, 13764, 13764, 9, 91, -1, 0, 0, 18, -1, 13765), - (13767, -1, -1, 1604, 1604, 12, 91, -1, 0, 0, 18, 13095, 13768), - (13770, 6328, 6328, 6328, 6328, 9, 91, 31628, 10, 600, 18, 10170, 13771), - (13771, 6328, 6328, 6328, 6328, 12, 93, 31629, 10, 600, 18, 13770, 13772), - (13773, -1, -1, 255, 255, 11, 91, -1, 0, 0, 18, 12610, 13774), - (13774, -1, -1, 255, 255, 13, 92, -1, 0, 0, 18, 13773, 13775), - (13775, -1, -1, 255, 255, 15, 93, -1, 0, 0, 18, 13774, 14126), - (13779, -1, -1, 10850, 10850, 12, 91, 31637, 0, 0, 18, 13209, 13780), - (13782, -1, -1, 1543, 1543, 9, 91, -1, 0, 0, 18, 13217, 13783), - (13785, 5021, 5021, 5021, 5021, 11, 91, 31640, 7, 60, 18, 12621, 13786), - (13788, 13788, 13788, 13788, 13788, 25, 51, 31643, 31, 2, 3, -1, -1), - (13789, -1, -1, 1304, 1304, 11, 91, -1, 0, 0, 18, 13218, 13790), - (13790, -1, -1, 1304, 1304, 13, 93, -1, 0, 0, 18, 13789, 13791), - (13792, 13792, 13792, 13792, 13792, 9, 91, 31644, 18, 600, 18, 12633, 13793), - (13795, -1, -1, 846, 846, 12, 91, -1, 0, 0, 18, 10175, 13796), - (13798, -1, -1, 8325, 8325, 9, 91, -1, 0, 0, 18, 13221, 13799), - (13804, -1, -1, 10650, 10650, 9, 91, -1, 0, 0, 18, 10652, 13805), - (13807, 1352, 1352, 1352, 1352, 9, 91, 31647, 3, 60, 18, 10115, 13808), - (13810, 1358, 1358, 1358, 1358, 9, 91, 31650, 3, 60, 18, 10118, 13811), - (13813, -1, -1, 12706, 12706, 12, 91, 0, 0, 0, 18, 12708, 13814), - (13816, 7875, 7875, 7875, 7875, 9, 91, 31653, 42, 600, 18, 7880, 13817), - (13819, 10346, 10346, 10346, 10346, 12, 95, 31659, 46, 600, 18, 13183, 16924), - (13820, -1, -1, 820, 820, 9, 91, -1, 0, 0, 18, 12669, 13821), - (13823, -1, -1, 6020, 6020, 9, 91, -1, 0, 0, 18, 12693, 13824), - (13826, -1, -1, 9512, 9512, 9, 91, -1, 0, 0, 18, 13189, 13827), - (13829, -1, -1, 10340, 10340, 12, 91, -1, 0, 0, 18, 13186, 13830), - (13832, 1355, 1355, 1355, 1355, 11, 91, 31661, 3, 60, 18, 12702, 13833), - (13835, -1, -1, 611, 611, 9, 91, -1, 0, 0, 18, 12705, 13836), - (13838, 7872, 7872, 7872, 7872, 9, 91, 31664, 41, 600, 18, 12684, 13839), - (13841, -1, -1, 10343, 10343, 9, 91, 0, 0, 0, 18, 10345, 13842), - (13845, 1178, 1178, 1178, 1178, 9, 91, 31669, 4, 900, 18, 10328, 13846), - (13872, 13872, 13872, 13872, 13872, 15, 95, 31694, 63, 60, 18, -1, 16002), - (13873, -1, -1, 13873, 13873, 7, 91, 0, 0, 0, 18, -1, 13874), - (13878, -1, -1, 13878, 13878, 9, 91, 0, 0, 0, 18, -1, 13879), - (13881, -1, -1, 13881, 13881, 9, 91, 0, 0, 0, 18, -1, 13882), - (13884, -1, -1, 735, 735, 10, 91, -1, 0, 0, 18, 10636, 13885), - (13889, -1, -1, 13889, 13889, 5, 91, 0, 0, 0, 18, -1, 13890), - (13894, -1, -1, 1021, 1021, 6, 91, -1, 0, 0, 18, 7685, 13895), - (13899, 6750, 6750, 6750, 6750, 15, 95, 32100, 60, 120, 18, 6750, 15294), - (13905, -1, -1, 13905, 13905, 10, 91, -1, 0, 0, 18, -1, 13906), - (13908, -1, -1, 13908, 13908, 10, 91, -1, 0, 0, 18, -1, 13909), - (13911, -1, -1, 13911, 13911, 12, 91, -1, 0, 0, 18, -1, 13912), - (13914, 4849, 4849, 4849, 4849, 12, 91, 32103, 7, 1800, 18, 7110, 13915), - (13917, -1, -1, 13917, 13917, 9, 91, -1, 0, 0, 18, -1, 13918), - (13920, 6333, 6333, 6333, 6333, 15, 91, 32140, 3, 600, 18, 7266, 16032), - (13921, -1, -1, 98, 98, 12, 91, -1, 0, 0, 18, 11063, 13922), - (13924, -1, -1, 98, 738, 12, 91, -1, 0, 0, 18, 7600, 13925), - (13927, -1, -1, 10370, 10370, 10, 91, -1, 0, 0, 18, 10372, 13928), - (13930, -1, -1, 1592, 1592, 12, 91, -1, 0, 0, 18, 12536, 13931), - (13933, -1, -1, 8263, 8263, 5, 91, -1, 0, 0, 18, 8360, 13934), - (13943, -1, -1, 8268, 8268, 5, 91, -1, 0, 0, 18, 8370, 13944), - (13953, -1, -1, 8273, 8273, 5, 91, -1, 0, 0, 18, 8380, 13954), - (13963, -1, -1, 8278, 8278, 5, 91, -1, 0, 0, 18, 8390, 13964), - (13973, -1, -1, 8283, 8283, 5, 91, -1, 0, 0, 18, 8400, 13974), - (13983, -1, -1, 8288, 8288, 5, 91, -1, 0, 0, 18, 8410, 13984), - (13993, -1, -1, 8293, 8293, 5, 91, -1, 0, 0, 18, 8420, 13994), - (14003, 6492, 6492, 6492, 6492, 12, 91, 32151, 52, 720, 18, 10681, 14004), - (14006, 10711, 10711, 10711, 10711, 15, 91, 32157, 75, 1200, 18, 10713, 14007), - (14009, 13202, 13202, 13202, 13202, 6, 91, 32160, 98, 20, 18, 13202, -1), - (14010, 14010, 14010, 14010, 14010, 15, 95, 32161, 97, 20, 18, -1, -1), - (14011, -1, -1, 14011, 14011, 5, 91, -1, 0, 0, 18, -1, 14012), - (14016, 10354, 10354, 10354, 10354, 15, 95, 32162, 39, 4320, 18, 10354, 14647), - (14017, -1, -1, 14017, 14017, 0, 90, -1, 0, 0, 18, -1, -1), - (14018, -1, -1, 14018, 14018, 0, 91, -1, 0, 0, 18, -1, -1), - (14019, 14019, 14019, 14019, 14019, 12, 91, 32177, 14, 900, 18, -1, 14020), - (14026, -1, -1, 14026, 14026, 12, 91, -1, 0, 0, 18, -1, 14027), - (14029, -1, -1, 14029, 14029, 12, 91, -1, 0, 0, 18, -1, 14030), - (14032, -1, -1, 14032, 14032, 15, 95, -1, 0, 0, 18, -1, -1), - (14037, -1, -1, 14037, 14037, 9, 91, 0, 0, 0, 18, -1, 14038), - (14040, -1, -1, 14040, 14040, 9, 91, 0, 0, 0, 18, -1, 14041), - (14043, -1, -1, 1313, 1313, 12, 91, -1, 0, 0, 18, 12581, 14044), - (14046, -1, -1, 14046, 14046, 5, 91, -1, 0, 0, 18, -1, 14047), - (14051, 14051, 14051, 14051, 14051, 12, 95, 32300, 62, 8, 18, -1, 15774), - (14052, 14052, 14052, 14052, 14052, 21, 95, 32301, 13, 1440, 18, -1, 14793), - (14053, 10912, 10912, 10912, 10912, 9, 91, 32303, 69, 1800, 18, 10914, 14054), - (14054, 10912, 10912, 10912, 10912, 12, 93, 32304, 69, 1800, 18, 14053, 14055), - (14055, 10912, 10912, 10912, 10912, 15, 95, 32305, 69, 1800, 18, 14054, -1), - (14056, -1, -1, 14056, 14056, 9, 91, -1, 0, 0, 18, -1, 14057), - (14059, -1, -1, 14059, 14059, 9, 91, -1, 0, 0, 18, -1, 14060), - (14062, -1, -1, 14062, 14062, 9, 91, -1, 0, 0, 18, -1, 14063), - (14065, -1, -1, 14065, 14065, 9, 91, 0, 0, 0, 18, -1, 14066), - (14068, -1, -1, 14068, 14068, 9, 91, 0, 0, 0, 18, -1, 14069), - (14071, 14071, 14071, 14071, 14071, 9, 91, 32307, 12, 600, 18, -1, 14072), - (14076, -1, -1, 14076, 14076, 9, 91, -1, 0, 0, 18, -1, 14077), - (14080, 14080, 14080, 14080, 14080, 9, 95, 32312, 13, 900, 18, -1, -1), - (14081, 14081, 14081, 14081, 14081, 9, 95, 32313, 14, 120, 18, -1, 17240), - (14082, -1, -1, 13101, 13101, 9, 91, 0, 0, 0, 18, 13103, 14083), - (14085, -1, -1, 14085, 14085, 9, 91, -1, 0, 0, 18, -1, 14086), - (14088, -1, -1, 14088, 14088, 9, 91, -1, 0, 0, 18, -1, 14089), - (14091, -1, -1, 14091, 14091, 9, 91, -1, 0, 0, 18, -1, 14092), - (14094, -1, -1, 10355, 10355, 9, 91, -1, 0, 0, 18, 10645, 14095), - (14097, -1, -1, 6395, 6395, 12, 91, -1, 0, 0, 18, 10707, 14098), - (14100, -1, -1, 14100, 14100, 15, 95, -1, 0, 0, 18, -1, -1), - (14101, -1, -1, 6355, 6355, 9, 91, -1, 0, 0, 18, 6360, 14263), - (14111, 6754, 6754, 6754, 6754, 12, 95, 32326, 41, 1200, 18, 10053, 14839), - (14112, 6370, 6370, 6370, 6370, 9, 91, 32329, 7, 600, 18, 7352, 14113), - (14115, -1, -1, 14115, 14115, 12, 91, -1, 0, 0, 18, -1, 14116), - (14129, -1, -1, 14129, 14129, 12, 91, -1, 0, 0, 18, -1, 14130), - (14130, -1, -1, 14129, 14129, 15, 93, -1, 0, 0, 18, 14129, 14131), - (14132, -1, -1, 7751, 7751, 7, 91, -1, 0, 0, 18, 7753, 14133), - (14135, -1, -1, 14135, 14135, 12, 91, -1, 0, 0, 18, -1, 14136), - (14138, -1, -1, 12615, 12615, 18, 95, -1, 0, 0, 18, 12617, 15499), - (14139, 14139, 14139, 14139, 14139, 15, 95, 32328, 60, 60, 18, -1, -1), - (14140, -1, -1, 12607, 12607, 15, 95, 0, 0, 0, 18, 12607, 15631), - (14141, -1, -1, 14141, 14141, 9, 91, -1, 0, 0, 18, -1, 14142), - (14144, -1, -1, 14144, 14144, 7, 91, -1, 0, 0, 18, -1, 14145), - (14148, -1, -1, 14148, 14148, 9, 91, 0, 0, 0, 18, -1, 14149), - (14151, -1, -1, 14151, 14151, 9, 91, 0, 0, 0, 18, -1, 14152), - (14154, -1, -1, 10657, 10657, 12, 91, 0, 0, 0, 18, 12681, 14155), - (14157, -1, -1, 14157, 14157, 9, 91, 0, 0, 0, 18, -1, 14158), - (14160, -1, -1, 14160, 14160, 9, 91, 0, 0, 0, 18, -1, 14161), - (14163, -1, -1, 14163, 14163, 9, 91, 0, 0, 0, 18, -1, 14164), - (14166, -1, -1, 14166, 14166, 9, 91, 0, 0, 0, 18, -1, 14167), - (14169, -1, -1, 14169, 14169, 7, 91, -1, 0, 0, 18, -1, 14170), - (14173, -1, -1, 12710, 12710, 9, 91, -1, 0, 0, 18, 12712, 14174), - (14176, -1, -1, 13204, 13204, 9, 91, -1, 0, 0, 18, 13206, 14177), - (14179, -1, -1, 14179, 14179, 9, 95, -1, 0, 0, 18, -1, -1), - (14180, -1, -1, 14180, 14180, 9, 95, -1, 0, 0, 18, -1, -1), - (14181, -1, -1, 14181, 14181, 9, 91, -1, 0, 0, 18, -1, 14182), - (14186, -1, -1, 14186, 14186, 9, 91, -1, 0, 0, 18, -1, 14187), - (14189, 5017, 5017, 5017, 5017, 9, 91, 32332, 8, 600, 18, 10158, 14190), - (14192, 14192, 14192, 14192, 14192, 15, 95, 32335, 36, 12, 18, -1, 15525), - (14196, -1, -1, 6935, 6935, 9, 91, -1, 0, 0, 18, 6904, 14197), - (14199, -1, -1, 6908, 6908, 12, 95, -1, 0, 0, 18, 6910, 15560), - (14200, -1, -1, 14200, 14200, 9, 91, 32336, 0, 0, 18, -1, 14201), - (14203, -1, -1, 14203, 14203, 12, 91, -1, 0, 0, 18, -1, 14204), - (14206, 14206, 14206, 14206, 14206, 12, 95, 32339, 41, 600, 18, -1, 15324), - (14207, 14207, 14207, 14207, 14207, 12, 95, 32340, 39, 180, 18, -1, -1), - (14208, 14208, 14208, 14208, 14208, 12, 95, 32341, 17, 180, 18, -1, 14568), - (14209, 14209, 14209, 14209, 14209, 12, 95, 32342, 22, 3, 18, -1, -1), - (14210, -1, -1, 10358, 10358, 12, 91, -1, 0, 0, 18, 10360, 14211), - (14213, -1, -1, 14213, 14213, 11, 91, -1, 0, 0, 18, -1, 14214), - (14218, -1, -1, 962, 962, 9, 91, -1, 0, 0, 18, 10363, 14219), - (14221, 1383, 1383, 1383, 1383, 18, 95, 32345, 6, 300, 18, 6487, 14581), - (14222, 146, 146, 146, 146, 15, 95, 32346, 2, 180, 18, 13258, 14977), - (14223, -1, -1, 13010, 13010, 12, 95, 0, 0, 0, 18, 13012, 16205), - (14224, 14224, -1, 14224, 14224, 9, 91, 345, 61, 5, 18, -1, 15860), - (14225, -1, -1, 14225, 14225, 9, 91, -1, 0, 0, 18, -1, 14226), - (14229, 14229, 14229, 14229, 14229, 12, 100, 37168, 42, 600, 19, -1, -1), - (14231, 14231, 14231, 14231, 14231, 12, 95, 32347, 91, 6, 18, -1, 16207), - (14232, 14232, -1, 14232, 14232, 12, 95, 32348, 92, 6, 18, -1, 14674), - (14233, 14233, 14233, 14233, 14233, 15, 95, 32349, 93, 30, 18, -1, 15621), - (14234, 14234, 14234, 14234, 14234, 9, 91, 32350, 94, 1800, 18, -1, 14235), - (14237, 12638, 12638, 12638, 12638, 9, 91, 23581, 68, 10, 18, -1, -1), - (14238, -1, -1, 12968, 12968, 9, 91, 0, 0, 0, 18, 12970, 14239), - (14241, -1, -1, 14241, 14241, 9, 91, -1, 0, 0, 18, -1, 14242), - (14244, -1, -1, 14244, 14244, 9, 91, -1, 0, 0, 18, -1, 14245), - (14249, -1, -1, 14249, 14249, 9, 91, -1, 0, 0, 18, -1, 14250), - (14254, -1, -1, 14254, 14254, 11, 91, -1, 0, 0, 18, -1, 14255), - (14256, 6561, 6561, 6561, 6561, 9, 91, 32353, 32, 30, 18, 10420, 14257), - (14259, -1, -1, 14259, 14259, 11, 91, -1, 0, 0, 18, -1, 14260), - (14262, 14262, 14262, 14262, 14262, 15, 95, 32357, 95, 180, 18, -1, -1), - (14264, 14264, 14264, 14264, 14264, 12, 95, 32358, 97, 120, 18, -1, 14600), - (14265, 14265, 14265, 14265, 14265, 15, 95, 32359, 68, 30, 18, -1, -1), - (14272, 6218, 6218, 6218, 14272, 12, 95, 32369, 0, 1, 18, 7488, 17381), - (14273, 723, 723, 723, 723, 12, 95, 32370, 6, 30, 18, 10300, 14869), - (14274, 6971, 6971, 6971, 6971, 9, 91, 32371, 41, 600, 18, 10290, 17383), - (14275, -1, -1, 14275, 14275, 7, 91, -1, 0, 0, 18, -1, 14276), - (14278, -1, -1, 14278, 14278, 12, 95, 0, 0, 0, 18, 6990, 16248), - (14279, -1, -1, 1287, 1287, 11, 95, -1, 0, 0, 18, 12815, 16529), - (14280, 4890, -1, 4890, 4890, 12, 95, 32373, 3, 8640, 18, 5872, 14776), - (14281, 14281, 14281, 14281, 14281, 12, 95, 32375, 39, 15, 18, -1, -1), - (14282, 14282, 14282, 14282, 14282, 9, 91, 32374, 39, 7, 18, -1, -1), - (14283, -1, -1, 14283, 14283, 7, 91, -1, 0, 0, 18, -1, 14284), - (14286, -1, -1, 14286, 14286, 9, 91, -1, 0, 0, 18, -1, 14287), - (14289, -1, -1, 14289, 14289, 9, 91, -1, 0, 0, 18, -1, 14290), - (14292, -1, -1, 14292, 14292, 9, 91, -1, 0, 0, 18, -1, 14293), - (14295, -1, -1, 14295, 14295, 9, 95, -1, 0, 0, 18, -1, 14296), - (14301, -1, -1, 14301, 14301, 9, 91, -1, 0, 0, 18, -1, 14302), - (14304, -1, -1, 14304, 14304, 9, 91, -1, 0, 0, 18, -1, 14305), - (14307, 14307, 14307, 14307, 14307, 12, 95, 32376, 92, 1200, 18, -1, 14743), - (14308, -1, -1, 14308, 14308, 9, 91, -1, 0, 0, 18, -1, 14309), - (14311, -1, -1, 14311, 14311, 9, 91, -1, 0, 0, 18, -1, 14312), - (14314, -1, -1, 7715, 7715, 7, 91, -1, 0, 0, 18, 7717, 14315), - (14318, -1, -1, 14318, 14318, 9, 91, -1, 0, 0, 18, -1, 14319), - (14321, 14321, 14321, 14321, 14321, 12, 95, 32378, 92, 8, 18, -1, 14781), - (14322, 14322, 14322, 14322, 14322, 12, 95, 32379, 94, 2160, 18, -1, 14782), - (14323, 14323, 14323, 14323, 14323, 12, 95, 32380, 92, 150, 18, -1, -1), - (14324, 155, 155, 155, 155, 15, 95, 32381, 8, 60, 18, 7238, 15610), - (14328, -1, -1, 7822, 7822, 7, 91, -1, 0, 0, 18, 7826, 14329), - (14331, -1, -1, 14331, 14331, 9, 91, -1, 0, 0, 18, -1, 14332), - (14338, 1337, 1337, 1337, 1337, 12, 91, 32382, 13, 4320, 18, 6160, 14339), - (14341, -1, -1, 14341, 14341, 5, 91, -1, 0, 0, 18, -1, 14342), - (14346, 14346, 14346, 14346, 14346, 9, 91, 32385, 94, 12, 18, -1, 14347), - (14349, -1, -1, 1210, 1213, 12, 91, -1, 0, 0, 18, 12528, 14350), - (14352, 1274, 1274, 1274, 1274, 12, 91, 32391, 9, 540, 18, 12762, 14353), - (14355, 6815, 6815, 6815, 6815, 9, 91, 32394, 60, 600, 18, 12788, 14356), - (14358, 14358, -1, 14358, 14358, 15, 95, 32397, 98, 300, 18, -1, -1), - (14359, 14359, 14359, 14359, 14359, 15, 95, 32399, 93, 1200, 18, -1, -1), - (14360, 14360, 14360, 14360, 14360, 15, 95, 32400, 95, 1800, 18, -1, 16334), - (14361, -1, -1, 637, 637, 12, 91, -1, 0, 0, 18, 12555, 14362), - (14364, -1, -1, 14364, 14364, 9, 91, -1, 0, 0, 18, -1, 14365), - (14367, -1, -1, 14367, 14367, 0, 1, -1, 0, 0, 0, -1, 14368), - (14371, 14371, 14371, 14371, 14371, 0, 1, 32910, 0, 10, 0, -1, -1), - (14372, 13844, 13844, 13844, 13844, 6, 95, 31667, 47, 6, 18, -1, -1), - (14373, 14373, 14373, 14373, 14373, 0, 85, 33106, 87, 3600, 19, -1, -1), - (14374, 14374, 14374, 14374, 14374, 0, 86, 33107, 88, 28800, 19, -1, -1), - (14690, 14690, 14690, 14690, 14690, 15, 96, 37014, 45, 600, 19, -1, 17479), - (14729, 8342, 8342, 8342, 8342, 15, 100, 33909, 54, 240, 19, 8342, 17501), - (14730, 616, 616, 616, 616, 12, 96, 33910, 7, 900, 19, 10261, 14731), - (14733, 4909, 4909, 4909, 4909, 18, 100, 33913, 16, 1320, 19, 12957, 17147), - (14734, 7903, 7903, 7903, 7903, 12, 100, 33914, 60, 30, 19, 12976, 15853), - (14739, 1462, 1462, 1462, 1462, 18, 99, 33919, 5, 300, 19, 4902, 16054), - (14764, -1, -1, 10551, 10551, 12, 96, -1, 0, 0, 19, 10553, 14765), - (14991, 926, 926, 926, 926, 5, 85, 11071, 12, 1800, 17, 930, 14992), - (14992, 926, 926, 926, 926, 5, 86, 11072, 12, 1800, 17, 14991, 14993), - (15073, 15073, -1, 15073, 15073, 0, 1, 37668, 90, 60, 19, -1, -1), - (15074, -1, -1, 15074, 15074, 0, 1, -1, 0, 0, 19, -1, 15075), - (15096, 15096, 15096, 15096, 15096, 5, 96, 38151, 35, 30, 19, -1, 15097), - (15099, 15099, 15099, 15099, 15099, 12, 100, 37187, 15, 45, 19, -1, 16566), - (15100, -1, -1, 15100, 15100, 5, 96, -1, 0, 0, 19, -1, 15101), - (15105, -1, -1, 15105, 15105, 11, 96, -1, 0, 0, 19, -1, 15106), - (15108, -1, -1, 15108, 15108, 9, 98, -1, 0, 0, 19, -1, 15109), - (15111, 8300, 8300, 8300, 8300, 11, 97, 37189, 8, 900, 19, 8302, 15112), - (15113, -1, -1, 15113, 15113, 11, 96, -1, 0, 0, 19, -1, 15114), - (15119, 15119, 15119, 15119, 15119, 12, 100, 37194, 16, 1200, 19, -1, 15749), - (15120, -1, -1, 15120, 15120, 9, 96, -1, 0, 0, 19, -1, 15121), - (15123, -1, -1, 15123, 15123, 9, 96, -1, 0, 0, 19, -1, 15124), - (15126, -1, -1, 15126, 15126, 9, 96, -1, 0, 0, 19, -1, 15127), - (15129, 15129, 15129, 15129, 15129, 12, 100, 37196, 32, 180, 19, -1, 15736), - (15130, 15130, 15130, 15130, 15130, 12, 100, 37197, 32, 180, 19, -1, 15737), - (15131, 15131, 15131, 15131, 15131, 12, 100, 37198, 32, 180, 19, -1, 15738), - (15132, -1, -1, 15132, 15132, 9, 96, -1, 0, 0, 19, -1, 15133), - (15135, -1, -1, 15135, 15135, 9, 100, -1, 0, 0, 19, -1, -1), - (15136, 15136, 15136, 15136, 15136, 9, 96, 38001, 5, 120, 19, -1, 17241), - (15140, 13100, 13100, 13100, 13100, 11, 100, 38002, 86, 300, 19, 13100, -1), - (15141, -1, -1, 190, 190, 9, 96, -1, 0, 0, 19, 5040, 15142), - (15146, 15146, 15146, 15146, 15146, 13, 100, 38006, 95, 9, 19, -1, 15758), - (15147, 15147, 15147, 15147, 15147, 11, 96, 38007, 8, 1200, 19, -1, 15148), - (15150, -1, -1, 15150, 15150, 7, 96, -1, 0, 0, 19, -1, 15151), - (15153, -1, -1, 15153, 15153, 11, 100, -1, 0, 0, 19, -1, -1), - (15154, -1, -1, 15154, 15154, 9, 96, -1, 0, 0, 19, -1, -1), - (15155, -1, -1, 15155, 15155, 5, 96, -1, 0, 0, 19, -1, 15156), - (15158, -1, -1, 15158, 15158, 13, 100, -1, 0, 0, 19, -1, -1), - (15159, -1, -1, 15159, 15159, 7, 96, -1, 0, 0, 19, -1, 15160), - (15162, -1, -1, 15162, 15162, 7, 96, -1, 0, 0, 19, -1, 15163), - (15168, -1, -1, 15168, 15168, 9, 96, -1, 0, 0, 19, -1, 15169), - (15172, -1, -1, 210, 210, 12, 100, -1, 0, 0, 19, 7401, 16658), - (15173, 6639, 6639, 6639, 6639, 9, 100, 38012, 42, 300, 19, 6639, 15788), - (15174, -1, -1, 12582, 12582, 9, 96, -1, 0, 0, 19, 12584, 15175), - (15177, 15177, 15177, 15177, 15177, 9, 100, 38013, 94, 180, 19, -1, -1), - (15179, -1, -1, 15179, 15179, 7, 96, -1, 0, 0, 19, -1, 15180), - (15182, -1, -1, 7757, 7757, 5, 96, -1, 0, 0, 19, 12589, 15183), - (15188, -1, -1, 1528, 4819, 5, 96, -1, 0, 0, 19, 4823, 15189), - (15193, 15193, 15193, 15193, 15193, 15, 100, 38016, 92, 600, 19, -1, -1), - (15194, -1, -1, 15194, 15194, 9, 100, -1, 0, 0, 19, -1, -1), - (15200, 15200, 15200, 15200, 15200, 9, 96, 38304, 32, 1080, 19, -1, 15201), - (15203, 15203, 15203, 15203, 15203, 15, 100, 38307, 34, 480, 19, -1, -1), - (15204, -1, -1, 15204, 15204, 9, 96, -1, 0, 0, 19, -1, 15205), - (15207, -1, -1, 15207, 15207, 9, 96, -1, 0, 0, 19, -1, 15208), - (15210, 15210, 15210, 15210, 15210, 9, 96, 38308, 12, 120, 19, -1, 15211), - (15213, 15213, 15213, 15213, 15213, 15, 100, 38312, 42, 1080, 19, -1, 17509), - (15214, 15214, 15214, 15214, 15214, 9, 96, 38313, 43, 1800, 19, -1, 15215), - (15217, -1, -1, 15217, 15217, 11, 96, -1, 0, 0, 19, -1, 15218), - (15220, -1, -1, 15220, 15220, 9, 100, -1, 0, 0, 19, -1, 15221), - (15223, -1, -1, 15223, 15223, 9, 100, -1, 0, 0, 19, -1, 15224), - (15226, -1, -1, 15226, 15226, 9, 100, -1, 0, 0, 19, -1, 15227), - (15229, -1, -1, 15229, 15229, 9, 100, -1, 0, 0, 19, -1, 15230), - (15232, -1, -1, 15232, 15232, 9, 96, -1, 0, 0, 19, -1, 15233), - (15235, 785, 785, 785, 785, 9, 96, 38325, 8, 900, 19, 789, 15236), - (15238, -1, -1, 5276, 5276, 11, 96, -1, 0, 0, 19, 5278, 15239), - (15241, 168, 168, 168, 168, 11, 96, 38329, 4, 10, 19, 170, 15242), - (15244, 171, 171, 171, 171, 11, 96, 38333, 4, 10, 19, 173, 15245), - (15247, 174, 174, 174, 174, 11, 96, 38336, 4, 10, 19, 176, 15248), - (15250, 177, 177, 177, 177, 11, 96, 38340, 4, 10, 19, 179, 15251), - (15253, -1, -1, 15253, 15253, 4, 96, -1, 0, 0, 19, -1, 15254), - (15258, -1, -1, 7743, 7743, 11, 100, -1, 0, 0, 19, 10718, -1), - (15270, -1, -1, 12430, 12430, 15, 100, -1, 0, 0, 19, 12878, -1), - (15280, -1, -1, 10722, 10722, 9, 96, -1, 0, 0, 19, 10726, 15281), - (15283, -1, -1, 15283, 15283, 5, 96, -1, 0, 0, 19, -1, 15284), - (15288, -1, -1, 15288, 15288, 7, 96, -1, 0, 0, 19, -1, 15289), - (15295, -1, -1, 15295, 15295, 7, 96, -1, 0, 0, 19, -1, 15296), - (15298, 10806, 10806, 10806, 10806, 9, 96, 38025, 71, 540, 19, 10808, 15299), - (15301, 10809, 10809, 10809, 10809, 9, 96, 38028, 71, 540, 19, 10811, 15302), - (15304, 15304, 15304, 15304, 15304, 12, 100, 38031, 91, 360, 19, -1, -1), - (15314, 0, 0, 6481, 6481, 11, 96, -1, 0, 0, 19, 6483, 15315), - (15317, -1, -1, 15317, 15317, 9, 96, -1, 0, 0, 19, 5012, 15318), - (15320, -1, -1, 7940, 7940, 11, 100, -1, 0, 0, 19, 6486, -1), - (15321, 746, 746, 746, 746, 9, 96, 38033, 10, 2160, 19, 10024, 15322), - (15328, -1, -1, 7948, 7948, 9, 96, -1, 0, 0, 19, 10037, 15329), - (15338, 15338, 15338, 15338, 15338, 9, 96, 38054, 30, 600, 19, -1, 15339), - (15341, 136, -1, 136, 136, 7, 100, 38057, 7, 1800, 19, 136, -1), - (15342, -1, -1, 15341, 15341, 7, 100, -1, 0, 0, 19, -1, -1), - (15343, 15343, 15343, 15343, 15343, 12, 100, 38058, 21, 300, 19, -1, -1), - (15344, -1, -1, 2400, 2400, 12, 97, -1, 0, 0, 19, 2402, 15345), - (15348, -1, -1, 13001, 13001, 7, 96, -1, 0, 0, 19, 13003, 15349), - (15356, -1, -1, 15356, 15356, 15, 100, -1, 0, 0, 19, -1, 15851), - (15357, 15357, 15357, 15357, 15357, 9, 96, 38062, 95, 2, 19, -1, -1), - (15358, -1, -1, 15358, 15358, 12, 100, -1, 0, 0, 19, -1, -1), - (15359, -1, -1, 474, 474, 5, 96, -1, 0, 0, 19, 476, 15360), - (15362, 15362, 15362, 15362, 15362, 15, 100, 38063, 89, 20, 19, -1, -1), - (15363, -1, -1, 10951, 10951, 12, 97, -1, 0, 0, 19, 10953, 15364), - (15371, -1, -1, 15371, 15371, 7, 96, -1, 0, 0, 19, -1, 15372), - (15374, -1, -1, 15374, 15374, 9, 96, -1, 0, 0, 19, -1, 15375), - (15377, 15377, 15377, 15377, 15377, 15, 100, 38070, 75, 420, 19, -1, 15852), - (15383, -1, -1, 15383, 15383, 9, 96, -1, 0, 0, 19, -1, 15384), - (15389, -1, -1, 15389, 15389, 9, 96, -1, 0, 0, 19, -1, 15390), - (15396, -1, -1, 141, 12863, 12, 100, -1, 0, 0, 19, 12863, -1), - (15397, -1, -1, 6346, 6346, 9, 96, -1, 0, 0, 19, 7617, 15398), - (15403, -1, -1, 15403, 15403, 7, 96, -1, 0, 0, 19, -1, 15404), - (15406, -1, -1, 15406, 15406, 7, 96, -1, 0, 0, 19, -1, 15407), - (15414, -1, -1, 15414, 15414, 9, 100, -1, 0, 0, 19, -1, -1), - (15421, -1, -1, 6538, 6538, 12, 100, -1, 0, 0, 19, 7478, -1), - (15422, -1, -1, 83, 83, 12, 100, -1, 0, 0, 19, 1218, -1), - (15423, 15423, 15423, 15423, 15423, 15, 100, 38078, 52, 180, 19, -1, 15884), - (15424, 15424, 15424, 15424, 15424, 12, 100, 38079, 78, 1200, 19, -1, -1), - (15425, 15425, 15425, 15425, 15425, 15, 100, 38077, 79, 6, 19, -1, 15903), - (15426, -1, -1, 810, 810, 5, 96, -1, 0, 0, 19, 4828, 15427), - (15429, -1, -1, 15429, 15429, 7, 96, -1, 0, 0, 19, -1, 15430), - (15432, -1, -1, 15432, 15432, 7, 96, -1, 0, 0, 19, -1, 15433), - (15438, -1, -1, 15438, 15438, 9, 96, -1, 0, 0, 19, -1, 15439), - (15441, -1, -1, 815, 815, 10, 96, -1, 0, 0, 19, 7636, 15442), - (15444, -1, -1, 15444, 15444, 9, 96, 38080, 0, 0, 19, -1, 15445), - (15447, 15447, 15447, 15447, 15447, 9, 96, 38083, 78, 180, 19, -1, 15448), - (15450, -1, -1, 15450, 15450, 9, 96, -1, 0, 0, 19, -1, 15451), - (15453, -1, -1, 15453, 15453, 9, 96, -1, 0, 0, 19, -1, 15454), - (15456, -1, -1, 15456, 15456, 9, 96, -1, 0, 0, 19, -1, 15457), - (15459, 1245, 1245, 1245, 1245, 9, 96, 38404, 8, 2160, 19, 1247, 15460), - (15462, 8039, 8039, 8039, 38407, 15, 100, 38407, 58, 7, 19, 8039, 17167), - (15466, -1, -1, 10561, 10561, 9, 96, -1, 0, 0, 19, 10563, 15467), - (15469, -1, -1, 10558, 10558, 9, 96, -1, 0, 0, 19, 10560, 15470), - (15472, -1, -1, 8035, 8035, 9, 96, -1, 0, 0, 19, 10287, 15473), - (15475, 15475, 15475, 15475, 15475, 11, 96, 38408, 41, 600, 20, -1, 15476), - (15478, -1, -1, 15478, 15478, 9, 96, -1, 0, 0, 19, -1, 15479), - (15481, 15481, 15481, 15481, 15481, 18, 100, 38603, 53, 1080, 19, -1, -1), - (15482, 15482, 15482, 15482, 15482, 11, 96, 38414, 42, 1800, 19, -1, 15483), - (15485, -1, -1, 15485, 15485, 18, 100, -1, 0, 0, 19, -1, -1), - (15486, 15486, 15486, 15486, 15486, 12, 96, 38418, 43, 600, 19, -1, 15487), - (15489, 15489, 15489, 15489, 15489, 18, 100, 38421, 52, 10, 19, -1, -1), - (15490, 15490, 15490, 15490, 15490, 11, 96, 38422, 44, 10, 19, -1, 15491), - (15493, -1, -1, 15493, 15493, 9, 96, -1, 0, 0, 19, -1, 15494), - (15496, 15496, 15496, 15496, 15496, 11, 96, 38425, 46, 1800, 19, -1, 15497), - (15502, -1, -1, 15502, 15502, 9, 96, -1, 0, 0, 19, -1, 15503), - (15509, -1, -1, 15509, 15509, 9, 96, -1, 0, 0, 19, -1, 15510), - (15512, -1, -1, 15512, 15512, 9, 96, 38086, 0, 0, 19, -1, 15513), - (15515, 15515, 15515, 15515, 15515, 12, 100, 38089, 11, 90, 19, -1, 17417), - (15516, -1, -1, 15516, 15516, 9, 100, -1, 0, 0, 19, -1, 15960), - (15517, -1, -1, 15517, 15517, 7, 96, -1, 0, 0, 19, -1, 15518), - (15521, 15521, 15521, 15521, 15521, 12, 96, 38090, 42, 60, 19, -1, -1), - (15526, -1, -1, 12716, 12716, 7, 96, -1, 0, 0, 19, 12718, 15527), - (15529, -1, -1, 695, 695, 4, 96, -1, 0, 0, 19, 699, 15530), - (15540, -1, -1, 15540, 15540, 7, 96, -1, 0, 0, 19, -1, 15541), - (15543, -1, -1, 15543, 15543, 7, 96, -1, 0, 0, 19, -1, 15544), - (15546, -1, -1, 15546, 15546, 7, 96, -1, 0, 0, 19, -1, 15547), - (15549, -1, -1, 15549, 15549, 7, 96, -1, 0, 0, 19, -1, 15550), - (15552, -1, -1, 6302, 6302, 5, 96, -1, 0, 0, 19, 11013, 15553), - (15555, -1, -1, 15555, 15555, 11, 96, -1, 0, 0, 19, -1, 15556), - (15558, 10400, 10400, 10400, 10400, 9, 100, 38104, 62, 900, 19, 10400, -1), - (15564, -1, -1, 15564, 15564, 9, 96, -1, 0, 0, 19, -1, 15565), - (15567, 15567, 15567, 15567, 15567, 12, 96, 38106, 11, 1200, 19, -1, 15568), - (15569, 15569, 15569, 15569, 15569, 12, 96, 38108, 13, 60, 19, -1, 15991), - (15570, 15570, 15570, 15570, 15570, 15, 100, 38109, 64, 600, 19, -1, 15992), - (15571, -1, -1, 15571, 15571, 7, 96, -1, 0, 0, 19, -1, 15572), - (15574, 15574, 15574, 15574, 15574, 9, 80, 38110, 73, 4, 15, -1, 15575), - (15575, 15574, 15574, 15574, 15574, 9, 85, 38111, 73, 4, 16, 15574, 15576), - (15576, 15574, 15574, 15574, 15574, 9, 90, 38112, 73, 4, 17, 15575, 15577), - (15577, 15574, 15574, 15574, 15574, 9, 95, 38113, 73, 4, 18, 15576, 15578), - (15579, -1, -1, 15579, 15579, 7, 96, -1, 0, 0, 19, -1, 15580), - (15582, 15582, 15582, 15582, 15582, 9, 96, 38115, 34, 600, 19, -1, 15583), - (15585, -1, -1, 634, 634, 11, 96, -1, 0, 0, 19, 10780, 15586), - (15588, 10701, 10701, 10701, 10701, 12, 96, 38121, 32, 360, 19, 12756, 15589), - (15591, -1, -1, 15591, 15591, 5, 96, -1, 0, 0, 19, -1, 15592), - (15594, 15594, 15594, 15594, 15594, 9, 96, 38197, 39, 30, 19, -1, 15595), - (15598, -1, -1, 15598, 15598, 12, 96, -1, 0, 0, 19, -1, 15599), - (15601, 15601, 15601, 15601, 15601, 12, 96, 38131, 34, 6, 19, -1, 16077), - (15602, -1, -1, 15602, 15602, 9, 96, -1, 0, 0, 19, -1, 15603), - (15605, 12866, 12866, 12866, 12866, 15, 96, 38132, 74, 1800, 19, 12866, -1), - (15606, -1, -1, 8069, 8069, 5, 96, -1, 0, 0, 19, 8071, 15607), - (15609, -1, -1, 15609, 15609, 15, 100, -1, 0, 0, 19, -1, -1), - (15611, 15611, 15611, 15611, 15611, 18, 100, 38136, 32, 900, 19, -1, 16078), - (15612, 15612, 15612, 15612, 15612, 12, 96, 38137, 36, 20, 19, -1, 15613), - (15615, 15615, 15615, 15615, 15615, 12, 96, 38140, 44, 20, 19, -1, 15616), - (15619, 15619, 15619, 15619, 15619, 15, 100, 37188, 32, 600, 19, -1, -1), - (15622, -1, -1, 15622, 15622, 7, 96, -1, 0, 0, 19, -1, 15623), - (15625, -1, -1, 15625, 15625, 9, 96, -1, 0, 0, 19, -1, 15626), - (15628, 5022, 5022, 5022, 5022, 9, 96, 38176, 5, 600, 19, 6040, 15629), - (15632, -1, -1, 7005, 7005, 5, 96, -1, 0, 0, 19, 7007, 15633), - (15634, -1, -1, 15634, 15634, 3, 80, -1, 0, 0, 19, -1, 15635), - (15635, -1, -1, 15634, 15634, 5, 85, -1, 0, 0, 19, 15634, 15636), - (15639, 15639, 15639, 15639, 15639, 12, 96, 38183, 56, 60, 19, -1, -1), - (15640, 15640, 15640, 15640, 15640, 12, 100, 38184, 43, 60, 19, -1, -1), - (15642, 15642, 15642, 15642, 15642, 18, 100, 38187, 13, 1440, 19, -1, -1), - (15643, 15643, 15643, 15643, 15643, 9, 96, 38188, 75, 600, 19, -1, 15644), - (15646, 15646, 15646, 15646, 15646, 15, 100, 38194, 74, 60, 19, -1, 17255), - (15648, -1, -1, 15648, 15648, 9, 96, -1, 0, 0, 19, -1, 15649), - (15694, -1, -1, 8215, 8215, 5, 96, -1, 0, 0, 20, 12563, 15695), - (15714, -1, -1, 5263, 5263, 12, 96, -1, 0, 0, 20, 12468, 15715), - (15719, -1, -1, 1287, 1287, 11, 96, -1, 0, 0, 20, 13240, 15720), - (15746, -1, -1, 7033, 7033, 12, 96, 0, 0, 0, 20, 7035, 15747), - (15768, -1, -1, 15768, 15768, 7, 96, -1, 0, 0, 20, -1, 15769), - (15771, 15771, -1, 15771, 15771, 1, 55, 38274, 0, 3, 20, -1, -1), - (15772, -1, -1, 8232, 8232, 8, 100, -1, 0, 0, 20, 8261, -1), - (15773, -1, -1, 8040, 8040, 8, 100, -1, 0, 0, 20, 8313, -1), - (15775, 6508, 6508, 6508, 6508, 9, 96, 38276, 38, 600, 20, 10080, 15776), - (15778, -1, -1, 589, 589, 12, 96, -1, 0, 0, 20, 13106, 15779), - (15782, 7755, 7755, 7755, 7755, 12, 96, 38280, 53, 900, 20, 7755, 16187), - (15798, 15798, 15798, 15798, 15798, 9, 100, 38297, 34, 18, 20, -1, 15799), - (15819, 15819, 15819, 15819, 15819, 18, 100, 40807, 18, 900, 20, -1, -1), - (15833, -1, -1, 15833, 15833, 9, 96, 0, 0, 0, 20, -1, 15834), - (15836, -1, -1, 15836, 15836, 9, 100, 0, 0, 0, 20, -1, 15837), - (15839, 10450, 10450, 10450, 10450, 7, 96, 40817, 63, 900, 20, 10670, 15840), - (15855, 13004, 13004, 13004, 13004, 9, 96, 40832, 78, 300, 20, 13004, -1), - (15891, -1, -1, 11078, 11078, 9, 96, 0, 0, 0, 20, 11078, 15892), - (15893, -1, -1, 11079, 11079, 9, 96, 0, 0, 0, 20, 11079, 15894), - (15895, -1, -1, 11077, 11077, 9, 96, 0, 0, 0, 20, 11077, 15896), - (15904, 15904, 15904, 15904, 15904, 7, 66, 40874, 54, 600, 20, -1, -1), - (15908, -1, -1, 15908, 15908, 3, 80, -1, 0, 0, 20, -1, 15909), - (15909, -1, -1, 15908, 15908, 5, 85, -1, 0, 0, 20, 15908, 15910), - (15910, -1, -1, 15908, 15908, 7, 90, -1, 0, 0, 20, 15909, 15911), - (15954, -1, -1, 10853, 10853, 5, 90, -1, 0, 0, 20, 10864, 15955), - (15961, -1, -1, 12737, 12737, 9, 96, 0, 0, 0, 20, 12739, 15962), - (15988, 10333, 10333, 10333, 10333, 9, 96, 40894, 55, 120, 20, 12726, 15989), - (16016, 16016, 16016, 16016, 16016, 12, 100, 40919, 17, 12, 20, -1, -1), - (16062, -1, -1, 1572, 1572, 5, 96, -1, 0, 0, 20, 10556, 16063), - (16071, 16071, 16071, 16071, 16071, 15, 100, 40953, 46, 1800, 20, -1, 16072), - (16081, 16081, 16081, 16081, 16081, 15, 100, 40969, 55, 6, 20, -1, -1), - (16082, 16082, 16082, 16082, 16082, 3, 100, 40970, 53, 6, 20, -1, -1), - (16083, 16083, 16083, 16083, 16083, 3, 55, 40971, 46, 6, 20, -1, -1), - (16084, -1, -1, 16084, 16084, 9, 100, 0, 0, 0, 20, -1, 16085), - (16087, -1, -1, 16087, 16087, 5, 100, 0, 0, 6, 20, -1, 16088), - (16094, -1, -1, 477, 477, 2, 100, -1, 0, 0, 20, 6235, 16095), - (16096, 16096, 16096, 16096, 16096, 12, 100, 40972, 36, 6, 20, -1, -1), - (16097, 16097, 16097, 16097, 16097, 12, 100, 40973, 38, 600, 20, -1, 16098), - (16103, 16103, 16103, 16103, 16103, 0, 85, 41071, 35, 180, 16, -1, -1), - (16104, -1, -1, 16104, 16104, 5, 85, 0, 0, 0, 20, -1, -1), - (16105, 16105, 16105, 16105, 16105, 0, 85, 41086, 76, 30, 20, -1, -1), - (16106, 16106, 16106, 16106, 16106, 0, 85, 41087, 76, 30, 20, -1, -1), - (16107, 16107, 16107, 16107, 16107, 0, 85, 41088, 76, 30, 20, -1, -1), - (16108, 16108, 16108, 16108, 16108, 12, 100, 41090, 77, 120, 20, -1, -1), - (16109, -1, -1, 16109, 16109, 11, 96, -1, 0, 0, 20, -1, 16110), - (16113, 16113, 16113, 16113, 16113, 15, 100, 41096, 78, 60, 20, -1, -1), - (16114, -1, -1, 16114, 16114, 5, 96, -1, 0, 0, 20, -1, 16115), - (16117, -1, -1, 16117, 16117, 11, 96, -1, 0, 0, 20, -1, 16118), - (16120, -1, -1, 16120, 16120, 9, 105, -1, 0, 0, 21, -1, -1), - (16121, -1, -1, 6611, 6611, 6, 100, -1, 0, 0, 20, 10574, 16122), - (16124, -1, -1, 16124, 16124, 5, 96, -1, 0, 0, 20, -1, 16125), - (16128, -1, -1, 16128, 16128, 6, 96, -1, 0, 0, 20, -1, 16129), - (16131, -1, -1, 16131, 16131, 5, 96, -1, 0, 0, 20, -1, 16132), - (16137, -1, -1, 16137, 16137, 9, 100, -1, 0, 0, 20, -1, 16138), - (16140, -1, -1, 16140, 16140, 9, 100, -1, 0, 0, 20, -1, -1), - (16146, -1, -1, 16146, 16146, 11, 100, -1, 0, 0, 20, -1, 16147), - (16149, -1, -1, 16149, 16149, 9, 100, -1, 0, 0, 20, -1, 16150), - (16152, -1, -1, 16152, 16152, 11, 100, -1, 0, 0, 20, -1, 16153), - (16156, -1, -1, 16156, 16156, 12, 100, -1, 0, 0, 20, -1, 16157), - (16159, -1, -1, 16159, 16159, 15, 100, -1, 0, 0, 20, -1, -1), - (16160, 16160, 16160, 16160, 16160, 18, 100, 41110, 81, 900, 20, -1, -1), - (16162, 16162, 16162, 16162, 16162, 12, 100, 41112, 80, 180, 20, -1, -1), - (16163, 16163, 16163, 16163, 16163, 18, 100, 41113, 63, 180, 20, -1, 16695), - (16164, -1, -1, 6636, 6636, 9, 96, -1, 0, 0, 20, 12531, 16165), - (16170, -1, -1, 5248, 5248, 12, 96, -1, 0, 0, 20, 7358, 16171), - (16173, -1, -1, 5263, 5263, 9, 101, -1, 0, 0, 21, 12465, 16174), - (16176, -1, -1, 16176, 16176, 7, 100, -1, 0, 0, 20, -1, 16177), - (16179, -1, -1, 16179, 16179, 18, 100, 41122, 0, 0, 20, -1, -1), - (16180, -1, -1, 16180, 16180, 7, 96, -1, 0, 0, 20, -1, 16181), - (16185, 16185, 16185, 16185, 16185, 18, 100, 41124, 68, 600, 20, -1, 16729), - (16186, -1, -1, 16186, 16186, 12, 100, 41125, 0, 0, 20, -1, -1), - (16188, 16188, 16188, 16188, 16188, 12, 100, 41126, 58, 180, 20, -1, -1), - (16189, -1, -1, 10915, 10915, 9, 96, -1, 0, 0, 20, 10917, 16190), - (16192, -1, -1, 6641, 6641, 9, 96, -1, 0, 0, 20, 10077, 16193), - (16195, 16195, 16195, 16195, 16195, 15, 100, 41133, 59, 60, 20, -1, -1), - (16196, 16196, 16196, 16196, 16196, 15, 100, 41134, 60, 900, 20, -1, 16665), - (16197, 16197, 16197, 16197, 16197, 12, 96, 41136, 61, 900, 20, -1, 16198), - (16200, 16200, 16200, 16200, 16200, 9, 96, 41139, 63, 900, 20, -1, 16201), - (16203, 16203, 16203, 16203, 16203, 12, 96, 41143, 98, 120, 20, -1, 16204), - (16208, -1, -1, 16208, 16208, 5, 96, -1, 0, 0, 20, -1, 16209), - (16211, -1, -1, 16211, 16211, 7, 100, -1, 0, 0, 20, -1, 16212), - (16214, 10958, 10958, 10958, 16214, 18, 100, 41148, 62, 900, 20, 13000, -1), - (16215, 16215, 16215, 16215, 16215, 9, 96, 41150, 92, 300, 20, -1, 16216), - (16218, -1, -1, 16218, 16218, 7, 96, -1, 0, 0, 20, -1, 16219), - (16221, -1, -1, 16221, 16221, 9, 100, -1, 0, 0, 20, -1, 16223), - (16222, 16222, -1, 16222, 16222, 9, 100, 41153, 88, 30, 20, -1, -1), - (16225, -1, -1, 16225, 16225, 5, 96, -1, 0, 0, 20, -1, 16226), - (16230, -1, -1, 16230, 16230, 5, 96, -1, 0, 0, 20, -1, 16231), - (16235, -1, -1, 16235, 16235, 7, 96, -1, 0, 0, 20, -1, 16236), - (16238, -1, -1, 16238, 16238, 7, 96, -1, 0, 0, 20, -1, 16239), - (16246, 6983, 6983, 6983, 6983, 9, 96, 41157, 66, 720, 20, 6983, 16247), - (16249, -1, -1, 230, 230, 9, 100, -1, 0, 0, 20, 12677, -1), - (16250, 828, 828, 828, 828, 9, 96, 41159, 2, 3600, 20, 830, -1), - (16257, -1, -1, 16257, 16257, 11, 100, 0, 0, 0, 20, -1, 16258), - (16260, -1, -1, 16260, 16260, 11, 100, -1, 0, 0, 20, -1, 16261), - (16263, 16263, 16263, 16263, 16263, 11, 96, 41161, 95, 600, 20, -1, 16264), - (16266, -1, -1, 6560, 6560, 9, 96, -1, 0, 0, 20, 6277, -1), - (16267, -1, -1, 888, 888, 3, 96, -1, 0, 0, 20, 892, 16268), - (16272, -1, -1, 16272, 16272, 9, 96, -1, 0, 0, 20, -1, 16273), - (16276, -1, -1, 16276, 16276, 5, 96, -1, 0, 0, 20, -1, 16277), - (16287, -1, -1, 16287, 16287, 7, 96, -1, 0, 0, 20, -1, 16288), - (16296, 16296, 16296, 16296, 16296, 13, 100, 41168, 60, 30, 20, -1, -1), - (16297, -1, -1, 6337, 6337, 6, 96, -1, 0, 0, 20, 10155, 16298), - (16300, -1, -1, 16300, 16300, 9, 100, -1, 0, 0, 20, -1, 16301), - (16303, -1, -1, 12721, 12721, 9, 96, 0, 0, 0, 20, 12723, 16304), - (16306, -1, -1, 6340, 6340, 6, 96, -1, 0, 0, 20, 7453, -1), - (16310, 16310, 16310, 16310, 16310, 12, 100, 41169, 97, 600, 20, -1, -1), - (16317, -1, -1, 16317, 16317, 5, 100, -1, 0, 0, 20, -1, 16318), - (16324, 6607, 6607, 6607, 16324, 9, 96, 16491, 61, 600, 20, 6609, 16325), - (16327, -1, -1, 6362, 6362, 7, 96, 0, 0, 0, 20, 6366, 16328), - (16330, -1, -1, 16330, 16330, 9, 96, -1, 0, 0, 20, -1, 16331), - (16336, -1, -1, 16336, 16336, 7, 96, -1, 0, 0, 20, -1, 16337), - (16339, -1, -1, 16339, 16339, 7, 96, -1, 0, 0, 20, -1, 16340), - (16342, -1, -1, 16342, 16342, 7, 96, -1, 0, 0, 20, -1, 16343), - (16360, 16360, 16360, 16360, 16360, 9, 100, 41188, 91, 6, 20, -1, -1), - (16361, -1, -1, 9509, 9509, 7, 96, -1, 0, 0, 20, 9515, -1), - (16363, 16363, 16363, 16363, 16363, 12, 96, 41193, 89, 1800, 20, -1, 16364), - (16366, -1, -1, 16366, 16366, 12, 96, -1, 0, 0, 20, -1, 16367), - (16369, 16369, 16369, 16369, 16369, 15, 100, 41196, 98, 12, 20, -1, -1), - (16370, 16370, -1, 16370, 16370, 5, 100, 41197, 98, 12, 20, -1, -1), - (16371, -1, -1, 16371, 16371, 3, 96, -1, 0, 0, 20, -1, 16372), - (16380, -1, -1, 16380, 16380, 5, 96, -1, 0, 0, 20, -1, 16381), - (16386, -1, -1, 16386, 16386, 7, 96, -1, 0, 0, 20, -1, 16387), - (16392, -1, -1, 16392, 16392, 5, 96, -1, 0, 0, 20, -1, 16393), - (16395, 16395, 16395, 16395, 16395, 7, 100, 41305, 93, 10, 20, -1, -1), - (16396, -1, -1, 16396, 16396, 7, 96, -1, 0, 0, 20, -1, 16397), - (16402, -1, -1, 6112, 6112, 5, 96, -1, 0, 0, 20, 12967, 16403), - (16414, -1, -1, 1056, 1056, 5, 101, -1, 0, 0, 21, 7525, 16415), - (16419, -1, -1, 12636, 12636, 0, 1, -1, 0, 0, 16, 8447, 16420), - (16420, -1, -1, 12636, 12636, 0, 1, -1, 0, 0, 16, 16419, 16421), - (16421, -1, -1, 12636, 12636, 0, 1, -1, 0, 0, 16, 16420, -1), - (16440, -1, -1, 6540, 6540, 10, 101, -1, 0, 0, 21, 12510, 16441), - (16475, -1, -1, 8201, 8201, 9, 101, -1, 0, 0, 21, 8203, 16476), - (16489, -1, -1, 1107, 1107, 9, 101, -1, 0, 0, 21, 12558, 16490), - (16536, -1, -1, 16536, 16536, 5, 101, -1, 0, 0, 21, -1, 16537), - (16604, -1, -1, 849, 849, 11, 105, -1, 0, 0, 21, 10622, -1), - (16644, -1, -1, 16644, 16644, 11, 101, -1, 0, 0, 21, -1, 16645), - (16666, -1, -1, 16666, 16666, 9, 101, -1, 0, 0, 21, -1, 16667), - (16716, 6764, 6764, 6764, 6764, 12, 105, 41308, 52, 600, 21, 10057, -1), - (16730, -1, -1, 1608, 1608, 13, 101, -1, 0, 0, 21, 10069, 16731), - (16745, -1, -1, 16745, 16745, 9, 101, -1, 0, 0, 21, -1, 16746), - (16883, 1119, 1119, 1119, 1119, 12, 101, 41594, 8, 900, 21, 10299, 16884), - (16887, -1, -1, 729, 729, 11, 101, -1, 0, 0, 21, 10307, 16888), - (16890, -1, -1, 724, 724, 15, 101, -1, 0, 0, 21, 7493, 16891), - (17004, -1, -1, 556, 556, 7, 101, -1, 0, 0, 21, 1567, 17005), - (17030, 4857, 4857, 4857, 4857, 15, 101, 41660, 7, 600, 21, 5769, 17031), - (17131, 12785, 12785, 12785, 12785, 15, 105, 41736, 80, 30, 21, 12785, -1), - (17199, 17199, 17199, 17199, 17199, 100, 51, 41819, 31, 2, 21, -1, -1), - (17206, -1, -1, 10588, 10588, 7, 101, 0, 0, 0, 21, 10592, 17207), - (17209, -1, -1, 17209, 17209, 9, 101, -1, 0, 0, 21, -1, 17210), - (17212, -1, -1, 17212, 17212, 12, 101, -1, 0, 0, 21, -1, 17213), - (17215, -1, -1, 17215, 17215, 12, 101, -1, 0, 0, 21, -1, 17216), - (17218, -1, -1, 17218, 17218, 9, 101, -1, 0, 0, 21, -1, 17219), - (17229, -1, -1, 17229, 17229, 9, 101, -1, 0, 0, 21, -1, 17230), - (17235, -1, -1, 17235, 17235, 15, 101, -1, 0, 0, 21, -1, 17236), - (17238, 17238, 17238, 17238, 17238, 24, 105, 41808, 10, 900, 21, -1, -1), - (17239, -1, -1, 6489, 6489, 12, 101, -1, 0, 0, 21, 6491, -1), - (17242, -1, -1, 17242, 17242, 12, 101, -1, 0, 0, 21, -1, 17243), - (17245, -1, -1, 17245, 17245, 12, 101, -1, 0, 0, 21, -1, 17246), - (17248, 17248, 17248, 17248, 17248, 24, 105, 41811, 93, 1080, 21, -1, -1), - (17249, -1, -1, 17249, 17249, 12, 101, -1, 0, 0, 21, -1, 17250), - (17252, -1, -1, 17252, 17252, 9, 101, -1, 0, 0, 21, -1, 17253), - (17256, 17256, 17256, 17256, 17256, 21, 105, 41815, 93, 360, 21, -1, -1), - (17257, 17257, 17257, 17257, 17257, 21, 105, 41816, 98, 300, 21, -1, -1), - (17258, -1, -1, 17258, 17258, 15, 101, 0, 0, 0, 21, -1, 17259), - (17267, -1, -1, 17267, 17267, 9, 101, -1, 0, 0, 21, -1, 17268), - (17273, 17273, 17273, 17273, 17273, 15, 101, 41830, 98, 720, 21, -1, -1), - (17276, 1569, 1569, 1569, 1569, 9, 101, 41831, 5, 1800, 21, 10161, 17277), - (17280, 17280, 17280, 17280, 17280, 21, 105, 41834, 97, 720, 21, -1, -1), - (17281, -1, -1, 17281, 17281, 15, 105, -1, 0, 0, 21, -1, -1), - (17288, -1, -1, 17288, 17288, 9, 105, -1, 0, 0, 21, 7317, -1), - (17289, -1, -1, 17289, 17289, 7, 101, -1, 0, 0, 21, -1, 17290), - (17295, -1, -1, 692, 692, 12, 101, -1, 0, 0, 21, 12769, 17296), - (17298, 749, 749, 749, 749, 15, 105, 41837, 11, 1800, 21, 1208, -1), - (17307, -1, -1, 17307, 17307, 9, 101, -1, 0, 0, 21, -1, 17308), - (17310, -1, -1, 7945, 7945, 9, 105, -1, 0, 0, 21, 10347, -1), - (17311, 970, 970, 970, 970, 9, 101, 41845, 6, 1800, 21, 1326, 17312), - (17317, -1, -1, 17317, 17317, 9, 101, -1, 0, 0, 21, -1, 17318), - (17328, 17328, 17328, 17328, 17328, 21, 105, 41854, 87, 600, 21, -1, -1), - (17329, 17329, 17329, 17329, 17329, 12, 101, 41855, 88, 20, 21, -1, -1), - (17333, 153, 153, 153, 153, 18, 105, 41856, 3, 2160, 21, 12996, -1), - (17334, -1, -1, 12977, 12977, 12, 102, 0, 0, 0, 21, 12981, 17335), - (17336, -1, -1, 17336, 17336, 9, 101, -1, 0, 0, 21, -1, 17337), - (17339, -1, -1, 17339, 17339, 9, 101, -1, 0, 0, 21, -1, 17340), - (17342, 17342, 17342, 17342, 17342, 15, 105, 41857, 85, 60, 21, -1, -1), - (17344, 17344, 17344, 17344, 17344, 15, 101, 41858, 94, 780, 21, -1, 17345), - (17347, 17347, 17347, 17347, 17347, 12, 101, 41861, 32, 30, 21, -1, 17348), - (17350, -1, -1, 7664, 7664, 5, 102, -1, 0, 0, 21, 10109, 17351), - (17357, -1, -1, 17357, 17357, 9, 96, -1, 0, 0, 19, -1, 17358), - (17361, -1, -1, 17361, 17361, 5, 100, -1, 0, 0, 21, -1, 17362), - (17364, 17364, 17364, 17364, 17364, 15, 105, 46160, 87, 120, 21, -1, -1), - (17365, -1, -1, 10792, 10792, 15, 101, 0, 0, 0, 21, 10796, 17366), - (17370, -1, -1, 17370, 17370, 15, 102, 0, 0, 0, 21, -1, 17371), - (17372, 17372, 17372, 17372, 17372, 18, 104, 46161, 85, 300, 21, -1, -1), - (17373, 17373, -1, 17373, 17373, 15, 105, 46162, 98, 900, 21, -1, -1), - (17375, -1, -1, 17375, 17375, 12, 101, -1, 0, 0, 21, -1, 17376), - (17378, 17378, 17378, 17378, 17378, 10, 101, 46164, 97, 3, 21, -1, -1), - (17379, 17378, 17378, 17378, 17378, 10, 101, 46165, 86, 3, 21, -1, -1), - (17380, 17378, 17378, 17378, 17378, 10, 101, 46166, 97, 3, 21, -1, -1), - (17382, 5015, 5015, 5015, 5015, 15, 103, 46168, 9, 900, 21, 10301, -1), - (17384, 17384, 17384, 17384, 17384, 18, 101, 46171, 10, 20, 21, -1, -1), - (17391, -1, -1, 495, 495, 12, 105, -1, 0, 0, 21, 10668, -1), - (17406, -1, -1, 10653, 10653, 12, 103, -1, 0, 0, 21, 10655, -1), - (17409, -1, -1, 17409, 17409, 15, 105, -1, 0, 0, 21, -1, -1), - (17414, -1, -1, 17414, 17414, 9, 101, -1, 0, 0, 21, -1, 17415), - (17418, -1, -1, 17418, 17418, 7, 101, -1, 0, 0, 21, -1, 17419), - (17428, 17428, 17428, 17428, 17428, 15, 101, 46178, 0, 0, 21, -1, 17429), - (17436, -1, -1, 17436, 17436, 7, 101, -1, 0, 0, 21, -1, 17437), - (17439, -1, -1, 17439, 17439, 9, 102, -1, 0, 0, 21, -1, 17440), - (17441, -1, -1, 255, 255, 15, 102, -1, 0, 0, 21, 7633, -1), - (17445, -1, -1, 17445, 17445, 15, 101, 0, 0, 0, 21, -1, 17446), - (17448, -1, -1, 17448, 17448, 15, 102, 0, 0, 0, 21, -1, 17449), - (17476, -1, -1, 10800, 10800, 15, 101, -1, 0, 0, 21, 10802, 17477), - (17486, 12864, -1, 12864, 12864, 12, 105, 46195, 73, 10, 21, 12864, -1), - (17492, -1, -1, 17492, 17492, 9, 101, -1, 0, 0, 21, -1, 17493), - (17495, -1, -1, 17495, 17495, 9, 101, -1, 0, 0, 21, -1, 17496), - (17515, -1, -1, 17515, 17515, 7, 102, -1, 0, 0, 21, -1, 17516), - (17517, -1, -1, 17517, 17517, 9, 101, -1, 0, 0, 21, -1, 17518), - (17522, -1, -1, 17522, 17522, 9, 101, -1, 0, 0, 21, -1, 17523), - (17533, -1, -1, 17533, 17533, 15, 105, -1, 0, 0, 21, -1, -1), - (17534, 6828, 6828, 6828, 6828, 15, 105, 46207, 43, 60, 21, 10208, -1), - (17535, 967, 967, 967, 967, 9, 101, 46208, 10, 1800, 21, 12791, 17536), - (17538, 17538, 17538, 17538, 17538, 21, 105, 46212, 91, 1800, 21, -1, -1), - (17539, 4934, 4934, 4934, 4934, 12, 105, 46214, 13, 300, 21, 10278, -1), - (17540, 4935, 4935, 4935, 4935, 12, 105, 46215, 14, 300, 21, 10277, -1), - (17541, 8038, 8038, 8038, 8038, 12, 105, 46217, 56, 12, 21, 8038, -1), - (17547, -1, -1, 17547, 17547, 12, 102, -1, 0, 0, 21, -1, 17548), - (17549, -1, -1, 17549, 17549, 9, 101, -1, 0, 0, 21, -1, 17550), - (17553, -1, -1, 17553, 17553, 18, 105, -1, 0, 0, 21, -1, -1), - (17554, -1, -1, 17554, 17554, 15, 105, -1, 0, 0, 21, -1, -1), - (17555, -1, -1, 17555, 17555, 5, 101, -1, 0, 0, 21, -1, 17556), - (17558, -1, -1, 17558, 17558, 5, 101, -1, 0, 0, 21, -1, 17559), - (17561, -1, -1, 17561, 17561, 5, 101, -1, 0, 0, 21, -1, 17562), - (17564, -1, -1, 17564, 17564, 5, 101, -1, 0, 0, 21, -1, 17565), - (17567, -1, -1, 17567, 17567, 5, 101, -1, 0, 0, 21, -1, 17568), - (17570, -1, -1, 17570, 17570, 5, 101, -1, 0, 0, 21, -1, 17571), - (17573, -1, -1, 17573, 17573, 5, 101, -1, 0, 0, 21, -1, 17574), - (17576, -1, -1, 17576, 17576, 5, 101, -1, 0, 0, 21, -1, 17577), - (17579, -1, -1, 17579, 17579, 5, 101, -1, 0, 0, 21, -1, 17580), - (17582, -1, -1, 17582, 17582, 5, 101, -1, 0, 0, 21, -1, 17583), - (17585, -1, -1, 17585, 17585, 5, 101, -1, 0, 0, 21, -1, 17586), - (17588, -1, -1, 17588, 17588, 5, 101, -1, 0, 0, 21, -1, 17589), - (17591, -1, -1, 17591, 17591, 5, 101, -1, 0, 0, 21, -1, 17592), - (17594, -1, -1, 17594, 17594, 5, 101, -1, 0, 0, 21, -1, 17595), - (17597, -1, -1, 17597, 17597, 5, 101, -1, 0, 0, 21, -1, 17598), - (17600, -1, -1, 17600, 17600, 5, 101, -1, 0, 0, 21, -1, 17601), - (17603, -1, -1, 17603, 17603, 5, 101, -1, 0, 0, 21, -1, 17604), - (17606, -1, -1, 17606, 17606, 5, 101, -1, 0, 0, 21, -1, 17607), - (17609, -1, -1, 17609, 17609, 5, 101, -1, 0, 0, 21, -1, 17610), - (17612, -1, -1, 17612, 17612, 5, 101, -1, 0, 0, 21, -1, 17613), - (17615, -1, -1, 17615, 17615, 5, 101, -1, 0, 0, 21, -1, 17616), - (17618, -1, -1, 17618, 17618, 5, 101, -1, 0, 0, 21, -1, 17619), - (17621, -1, -1, 17621, 17621, 5, 101, -1, 0, 0, 21, -1, 17622), - (17624, -1, -1, 17624, 17624, 5, 101, -1, 0, 0, 21, -1, 17625), - (17627, -1, -1, 17627, 17627, 5, 101, -1, 0, 0, 21, -1, 17628), - (17630, -1, -1, 17630, 17630, 5, 101, -1, 0, 0, 21, -1, 17631), - (17633, -1, -1, 17633, 17633, 5, 101, -1, 0, 0, 21, -1, 17634), - (17639, -1, -1, 17639, 17639, 9, 91, 0, 0, 0, 18, -1, 17640), - (18972, -1, -1, 279, 279, 15, 105, -1, 0, 0, 21, 279, -1), - (30050, -1, -1, 30050, 30050, 0, 1, -1, 0, 0, 0, -1, 30051), - (30100, -1, -1, 30100, 30100, 0, 1, -1, 0, 0, 0, -1, 30101), - (30150, -1, -1, 30150, 30150, 0, 1, -1, 0, 0, 0, -1, 30151), - (30175, -1, -1, 30175, 30175, 0, 1, -1, 0, 0, 0, -1, 30176), - (30180, -1, -1, 30180, 30180, 0, 1, -1, 0, 0, 0, -1, 30181), - (30185, -1, -1, 30185, 30185, 0, 1, -1, 0, 0, 0, -1, 30186), - (30190, -1, -1, 30190, 30190, 0, 1, -1, 0, 0, 0, -1, 30191), - (30195, -1, -1, 30195, 30195, 0, 1, -1, 0, 0, 0, -1, 30196), - (49999, -1, -1, -1, -1, 0, 71, 0, 0, 0, 0, -1, 1); +-- +-- Dumping data for table `aa_ranks` +-- + +LOCK TABLES `aa_ranks` WRITE; +/*!40000 ALTER TABLE `aa_ranks` DISABLE KEYS */; +INSERT INTO `aa_ranks` VALUES (2,-1,-1,2,2,1,51,-1,0,0,3,-1,3),(3,-1,-1,2,2,1,51,-1,0,0,3,2,4),(4,-1,-1,2,2,1,51,-1,0,0,3,3,5),(5,-1,-1,2,2,1,51,-1,0,0,3,4,6),(6,-1,-1,2,2,1,51,-1,0,0,3,5,292),(7,-1,-1,7,7,1,51,-1,0,0,3,-1,8),(8,-1,-1,7,7,1,51,-1,0,0,3,7,9),(9,-1,-1,7,7,1,51,-1,0,0,3,8,10),(10,-1,-1,7,7,1,51,-1,0,0,3,9,11),(11,-1,-1,7,7,1,51,-1,0,0,3,10,302),(12,-1,-1,12,12,1,51,-1,0,0,3,-1,13),(13,-1,-1,12,12,1,51,-1,0,0,3,12,14),(14,-1,-1,12,12,1,51,-1,0,0,3,13,15),(15,-1,-1,12,12,1,51,-1,0,0,3,14,16),(16,-1,-1,12,12,1,51,-1,0,0,3,15,312),(17,-1,-1,17,17,1,51,-1,0,0,3,-1,18),(18,-1,-1,17,17,1,51,-1,0,0,3,17,19),(19,-1,-1,17,17,1,51,-1,0,0,3,18,20),(20,-1,-1,17,17,1,51,-1,0,0,3,19,21),(21,-1,-1,17,17,1,51,-1,0,0,3,20,322),(22,-1,-1,22,22,1,51,-1,0,0,3,-1,23),(23,-1,-1,22,22,1,51,-1,0,0,3,22,24),(24,-1,-1,22,22,1,51,-1,0,0,3,23,25),(25,-1,-1,22,22,1,51,-1,0,0,3,24,26),(26,-1,-1,22,22,1,51,-1,0,0,3,25,332),(27,-1,-1,27,27,1,51,-1,0,0,3,-1,28),(28,-1,-1,27,27,1,51,-1,0,0,3,27,29),(29,-1,-1,27,27,1,51,-1,0,0,3,28,30),(30,-1,-1,27,27,1,51,-1,0,0,3,29,31),(31,-1,-1,27,27,1,51,-1,0,0,3,30,342),(32,-1,-1,32,32,1,51,-1,0,0,3,-1,33),(33,-1,-1,32,32,1,51,-1,0,0,3,32,34),(34,-1,-1,32,32,1,51,-1,0,0,3,33,35),(35,-1,-1,32,32,1,51,-1,0,0,3,34,36),(36,-1,-1,32,32,1,51,-1,0,0,3,35,352),(37,-1,-1,37,37,1,51,-1,0,0,3,-1,38),(38,-1,-1,37,37,1,51,-1,0,0,3,37,39),(39,-1,-1,37,37,1,51,-1,0,0,3,38,40),(40,-1,-1,37,37,1,51,-1,0,0,3,39,41),(41,-1,-1,37,37,1,51,-1,0,0,3,40,362),(42,-1,-1,42,42,1,51,-1,0,0,3,-1,43),(43,-1,-1,42,42,1,51,-1,0,0,3,42,44),(44,-1,-1,42,42,1,51,-1,0,0,3,43,45),(45,-1,-1,42,42,1,51,-1,0,0,3,44,46),(46,-1,-1,42,42,1,51,-1,0,0,3,45,372),(47,-1,-1,47,47,1,51,-1,0,0,3,-1,48),(48,-1,-1,47,47,1,51,-1,0,0,3,47,49),(49,-1,-1,47,47,1,51,-1,0,0,3,48,50),(50,-1,-1,47,47,1,51,-1,0,0,3,49,51),(51,-1,-1,47,47,1,51,-1,0,0,3,50,382),(52,-1,-1,52,52,1,51,-1,0,0,3,-1,53),(53,-1,-1,52,52,1,51,-1,0,0,3,52,54),(54,-1,-1,52,52,1,51,-1,0,0,3,53,55),(55,-1,-1,52,52,1,51,-1,0,0,3,54,56),(56,-1,-1,52,52,1,51,-1,0,0,3,55,392),(57,-1,-1,57,57,1,51,-1,0,0,3,-1,58),(58,-1,-1,57,57,1,51,-1,0,0,3,57,59),(59,-1,-1,57,57,1,51,-1,0,0,3,58,60),(60,-1,-1,57,57,1,51,-1,0,0,3,59,61),(61,-1,-1,57,57,1,51,-1,0,0,3,60,402),(62,-1,-1,62,62,1,51,-1,0,0,3,-1,63),(63,-1,-1,62,62,1,51,-1,0,0,3,62,64),(64,-1,-1,62,62,1,51,-1,0,0,3,63,672),(68,-1,-1,68,68,1,51,-1,0,0,3,-1,69),(69,-1,-1,68,68,1,51,-1,0,0,3,68,70),(70,-1,-1,68,68,1,51,-1,0,0,3,69,-1),(71,-1,-1,71,71,1,51,-1,0,0,3,-1,72),(72,-1,-1,71,71,1,51,-1,0,0,3,71,73),(73,-1,-1,71,71,1,51,-1,0,0,3,72,676),(74,-1,-1,74,74,1,51,-1,0,0,3,-1,75),(75,-1,-1,74,74,1,51,-1,0,0,3,74,76),(76,-1,-1,74,74,1,51,-1,0,0,3,75,-1),(77,-1,-1,77,77,2,55,-1,0,0,3,-1,78),(78,-1,-1,77,77,4,55,-1,0,0,3,77,79),(79,-1,-1,77,77,6,55,-1,0,0,3,78,434),(80,-1,-1,80,80,2,55,-1,0,0,3,-1,81),(81,-1,-1,80,80,4,55,-1,0,0,3,80,82),(82,-1,-1,80,80,6,55,-1,0,0,3,81,437),(83,-1,-1,83,83,2,55,-1,0,0,3,-1,84),(84,-1,-1,83,83,4,55,-1,0,0,3,83,85),(85,-1,-1,83,83,6,55,-1,0,0,3,84,13099),(86,-1,-1,86,86,2,55,-1,0,0,3,-1,87),(87,-1,-1,86,86,4,55,-1,0,0,3,86,88),(88,-1,-1,86,86,6,55,-1,0,0,3,87,266),(92,-1,-1,92,92,2,55,-1,0,0,3,-1,93),(93,-1,-1,92,92,4,55,-1,0,0,3,92,94),(94,-1,-1,92,92,6,55,-1,0,0,3,93,-1),(98,-1,-1,98,98,2,55,-1,0,0,3,-1,99),(99,-1,-1,98,98,4,55,-1,0,0,3,98,100),(100,-1,-1,98,98,6,55,-1,0,0,3,99,4767),(101,-1,-1,101,101,2,55,-1,0,0,3,-1,102),(102,-1,-1,101,101,4,55,-1,0,0,3,101,103),(103,-1,-1,101,101,6,55,-1,0,0,3,102,-1),(104,-1,-1,104,104,2,55,-1,0,0,3,-1,105),(105,-1,-1,104,104,4,55,-1,0,0,3,104,106),(106,-1,-1,104,104,6,55,-1,0,0,3,105,-1),(107,-1,-1,107,107,2,55,-1,0,0,3,-1,108),(108,-1,-1,107,107,4,55,-1,0,0,3,107,109),(109,-1,-1,107,107,6,55,-1,0,0,3,108,7541),(110,-1,-1,110,110,2,55,-1,0,0,3,-1,111),(111,-1,-1,110,110,4,55,-1,0,0,3,110,112),(112,-1,-1,110,110,6,55,-1,0,0,3,111,-1),(113,-1,-1,113,113,2,55,-1,0,0,3,-1,114),(114,-1,-1,113,113,4,55,-1,0,0,3,113,115),(115,-1,-1,113,113,6,55,-1,0,0,3,114,443),(116,-1,-1,116,116,2,55,-1,0,0,3,-1,117),(117,-1,-1,116,116,4,55,-1,0,0,3,116,118),(118,-1,-1,116,116,6,55,-1,0,0,3,117,-1),(119,-1,-1,119,119,2,55,-1,0,0,3,-1,120),(120,-1,-1,119,119,4,55,-1,0,0,3,119,121),(121,-1,-1,119,119,6,55,-1,0,0,3,120,440),(122,-1,-1,122,122,2,55,-1,0,0,3,-1,123),(123,-1,-1,122,122,4,55,-1,0,0,3,122,124),(124,-1,-1,122,122,6,55,-1,0,0,3,123,454),(125,-1,-1,125,125,2,55,-1,0,0,3,-1,126),(126,-1,-1,125,125,4,55,-1,0,0,3,125,127),(127,-1,-1,125,125,6,55,-1,0,0,3,126,449),(128,128,128,128,128,9,59,5228,1,4320,3,-1,-1),(129,129,129,129,129,5,59,2738,2,64800,3,-1,-1),(130,130,130,130,130,3,59,2739,3,7,3,-1,-1),(131,131,131,131,131,5,59,2740,4,900,3,-1,531),(132,132,132,132,132,6,59,2741,5,600,3,-1,-1),(136,136,-1,136,136,5,59,2742,7,1800,3,-1,15341),(137,-1,-1,137,137,3,59,-1,0,0,3,-1,138),(138,-1,-1,137,137,6,59,-1,0,0,3,137,139),(139,-1,-1,137,137,9,59,-1,0,0,3,138,-1),(140,140,-1,140,140,6,59,2771,3,4320,3,-1,-1),(141,-1,-1,141,12863,3,59,-1,0,0,3,-1,142),(142,-1,-1,141,12863,6,59,-1,0,0,3,141,143),(143,-1,-1,141,12863,9,59,-1,0,0,3,142,12863),(144,-1,-1,144,144,5,59,-1,0,0,3,-1,-1),(145,145,145,145,145,9,59,2761,2,4320,3,-1,-1),(146,146,146,146,146,5,59,2749,2,180,3,-1,5069),(147,-1,-1,147,147,3,59,-1,0,0,3,-1,148),(148,-1,-1,147,147,6,59,-1,0,0,3,147,149),(149,-1,-1,147,147,9,59,-1,0,0,3,148,-1),(150,-1,-1,150,150,3,59,-1,0,0,3,-1,151),(151,-1,-1,150,150,6,59,-1,0,0,3,150,152),(152,-1,-1,150,150,9,59,-1,0,0,3,151,-1),(153,153,153,153,153,5,59,2750,3,2160,3,-1,1519),(155,155,155,155,155,9,59,2758,8,60,3,-1,533),(156,156,156,156,156,6,59,2734,2,4320,3,-1,-1),(158,-1,-1,158,158,3,59,-1,0,0,3,-1,-1),(159,-1,-1,159,159,2,59,-1,0,0,3,-1,160),(160,-1,-1,159,159,4,59,-1,0,0,3,159,161),(161,-1,-1,159,159,6,59,-1,0,0,3,160,-1),(162,162,162,162,162,5,59,2753,3,8640,3,-1,-1),(163,163,163,163,163,5,59,2752,2,2160,3,-1,-1),(167,167,167,167,167,6,59,2754,14,900,3,-1,5879),(168,168,168,168,168,3,59,2795,4,10,3,-1,169),(169,168,168,168,168,6,59,2796,4,10,3,168,170),(170,168,168,168,168,9,59,2797,4,10,3,169,15241),(171,171,171,171,171,3,59,2798,4,10,3,-1,172),(172,171,171,171,171,6,59,2799,4,10,3,171,173),(173,171,171,171,171,9,59,2800,4,10,3,172,15244),(174,174,174,174,174,3,59,2792,4,10,3,-1,175),(175,174,174,174,174,6,59,2793,4,10,3,174,176),(176,174,174,174,174,9,59,2794,4,10,3,175,15247),(177,177,177,177,177,3,59,2789,4,10,3,-1,178),(178,177,177,177,177,6,59,2790,4,10,3,177,179),(179,177,177,177,177,9,59,2791,4,10,3,178,15250),(182,-1,-1,182,182,5,59,-1,0,0,3,-1,-1),(183,183,183,183,183,9,59,2755,4,8640,3,-1,-1),(184,184,184,184,184,3,59,2756,5,4320,3,-1,5953),(185,185,185,185,185,5,59,2757,6,4320,3,-1,-1),(186,186,186,186,186,3,59,2772,7,7,3,-1,-1),(187,187,187,187,187,6,59,2764,8,4320,3,-1,-1),(188,188,188,188,188,9,59,2190,2,30,3,-1,1277),(190,-1,-1,190,190,3,59,-1,0,0,3,-1,191),(191,-1,-1,190,190,6,59,-1,0,0,3,190,192),(192,-1,-1,190,190,9,59,-1,0,0,3,191,1524),(193,193,193,193,193,3,59,2775,3,4320,3,-1,-1),(194,194,194,194,194,5,59,2874,0,1,3,-1,-1),(195,-1,-1,195,195,6,59,-1,0,0,3,-1,-1),(196,-1,-1,196,196,6,59,-1,0,0,3,-1,-1),(197,197,197,197,197,5,59,2765,2,7,3,-1,-1),(198,-1,-1,198,198,9,59,-1,0,0,3,-1,-1),(199,-1,-1,199,199,3,59,-1,0,0,3,-1,200),(200,-1,-1,199,199,6,59,-1,0,0,3,199,201),(201,-1,-1,199,199,9,59,-1,0,0,3,200,12507),(205,-1,-1,205,205,9,59,-1,0,0,3,-1,-1),(206,206,206,206,206,5,59,2875,0,1,3,-1,-1),(208,208,208,208,208,6,59,2766,2,4320,3,-1,-1),(210,-1,-1,210,210,3,59,-1,0,0,3,-1,211),(211,-1,-1,210,210,6,59,-1,0,0,3,210,212),(212,-1,-1,210,210,9,59,-1,0,0,3,211,1316),(213,-1,-1,213,213,3,59,-1,0,0,3,-1,214),(214,-1,-1,213,213,6,59,-1,0,0,3,213,215),(215,-1,-1,213,213,9,59,-1,0,0,3,214,700),(225,-1,-1,225,225,3,59,-1,0,0,3,-1,226),(226,-1,-1,225,225,6,59,-1,0,0,3,225,227),(227,-1,-1,225,225,9,59,-1,0,0,3,226,-1),(230,-1,-1,230,230,3,59,-1,0,0,3,-1,231),(231,-1,-1,230,230,6,59,-1,0,0,3,230,232),(232,-1,-1,230,230,9,59,-1,0,0,3,231,539),(233,233,233,233,233,9,59,5248,1,1800,3,-1,-1),(237,-1,-1,237,237,3,59,-1,0,0,3,-1,238),(238,-1,-1,237,237,6,59,-1,0,0,3,237,239),(239,-1,-1,237,237,9,59,-1,0,0,3,238,-1),(240,-1,-1,240,240,3,59,-1,0,0,3,-1,241),(241,-1,-1,240,240,6,59,-1,0,0,3,240,242),(242,-1,-1,240,240,9,59,-1,0,0,3,241,-1),(243,243,-1,243,243,9,59,5244,1,1440,3,-1,-1),(244,-1,-1,244,244,3,59,-1,0,0,3,-1,245),(245,-1,-1,244,244,6,59,-1,0,0,3,244,246),(246,-1,-1,244,244,9,59,-1,0,0,3,245,8328),(247,-1,-1,247,247,3,59,-1,0,0,3,-1,248),(248,-1,-1,247,247,6,59,-1,0,0,3,247,249),(249,-1,-1,247,247,9,59,-1,0,0,3,248,504),(254,254,254,254,254,5,59,5232,12,4320,3,-1,-1),(255,-1,-1,255,255,3,59,-1,0,0,3,-1,256),(256,-1,-1,255,255,6,59,-1,0,0,3,255,257),(257,-1,-1,255,255,9,59,-1,0,0,3,256,542),(258,258,-1,258,258,5,59,5233,1,600,3,-1,10578),(259,259,259,259,259,5,59,5234,2,900,3,-1,-1),(260,260,-1,260,260,3,59,5229,3,2160,3,-1,261),(261,260,-1,260,260,6,59,5230,3,2160,3,260,262),(262,260,-1,260,260,9,59,5231,3,2160,3,261,8309),(263,-1,-1,263,263,3,59,-1,0,0,3,-1,264),(264,-1,-1,263,263,6,59,-1,0,0,3,263,265),(265,-1,-1,263,263,9,59,-1,0,0,3,264,-1),(266,-1,-1,86,86,8,59,-1,0,0,3,88,10467),(267,-1,-1,267,267,3,59,-1,0,0,3,-1,268),(268,-1,-1,267,267,6,59,-1,0,0,3,267,269),(269,-1,-1,267,267,9,59,-1,0,0,3,268,640),(273,-1,-1,273,273,5,59,2767,0,0,3,-1,-1),(274,274,274,274,274,5,59,2748,4,4320,3,-1,-1),(275,-1,-1,275,275,3,59,-1,0,0,3,-1,276),(276,-1,-1,275,275,6,59,-1,0,0,3,275,277),(277,-1,-1,275,275,9,59,-1,0,0,3,276,701),(278,-1,-1,278,278,5,59,-1,0,0,3,-1,-1),(279,-1,-1,279,279,5,59,-1,0,0,3,-1,18972),(280,-1,-1,280,280,3,59,-1,0,0,3,-1,281),(281,-1,-1,280,280,6,59,-1,0,0,3,280,282),(282,-1,-1,280,280,9,59,-1,0,0,3,281,-1),(283,-1,-1,283,283,3,59,-1,0,0,3,-1,284),(284,-1,-1,283,283,6,59,-1,0,0,3,283,285),(285,-1,-1,283,283,9,59,-1,0,0,3,284,-1),(286,-1,-1,286,286,3,59,-1,0,0,3,-1,-1),(287,-1,-1,287,287,6,59,-1,0,0,3,-1,-1),(288,-1,-1,288,288,6,59,-1,0,0,3,-1,-1),(289,289,289,289,289,5,59,3290,3,300,3,-1,1607),(290,290,290,290,290,4,59,3289,4,720,3,-1,13173),(291,291,291,291,291,6,59,3291,5,900,3,-1,1123),(292,-1,-1,2,2,1,61,-1,0,0,4,6,293),(293,-1,-1,2,2,1,61,-1,0,0,4,292,294),(294,-1,-1,2,2,1,62,-1,0,0,4,293,295),(295,-1,-1,2,2,1,62,-1,0,0,4,294,296),(296,-1,-1,2,2,1,63,-1,0,0,4,295,297),(297,-1,-1,2,2,1,63,-1,0,0,4,296,298),(298,-1,-1,2,2,1,64,-1,0,0,4,297,299),(299,-1,-1,2,2,1,64,-1,0,0,4,298,300),(300,-1,-1,2,2,1,65,-1,0,0,4,299,301),(301,-1,-1,2,2,1,65,-1,0,0,4,300,-1),(302,-1,-1,7,7,1,61,-1,0,0,4,11,303),(303,-1,-1,7,7,1,61,-1,0,0,4,302,304),(304,-1,-1,7,7,1,62,-1,0,0,4,303,305),(305,-1,-1,7,7,1,62,-1,0,0,4,304,306),(306,-1,-1,7,7,1,63,-1,0,0,4,305,307),(307,-1,-1,7,7,1,63,-1,0,0,4,306,308),(308,-1,-1,7,7,1,64,-1,0,0,4,307,309),(309,-1,-1,7,7,1,64,-1,0,0,4,308,310),(310,-1,-1,7,7,1,65,-1,0,0,4,309,311),(311,-1,-1,7,7,1,65,-1,0,0,4,310,-1),(312,-1,-1,12,12,1,61,-1,0,0,4,16,313),(313,-1,-1,12,12,1,61,-1,0,0,4,312,314),(314,-1,-1,12,12,1,62,-1,0,0,4,313,315),(315,-1,-1,12,12,1,62,-1,0,0,4,314,316),(316,-1,-1,12,12,1,63,-1,0,0,4,315,317),(317,-1,-1,12,12,1,63,-1,0,0,4,316,318),(318,-1,-1,12,12,1,64,-1,0,0,4,317,319),(319,-1,-1,12,12,1,64,-1,0,0,4,318,320),(320,-1,-1,12,12,1,65,-1,0,0,4,319,321),(321,-1,-1,12,12,1,65,-1,0,0,4,320,-1),(322,-1,-1,17,17,1,61,-1,0,0,4,21,323),(323,-1,-1,17,17,1,61,-1,0,0,4,322,324),(324,-1,-1,17,17,1,62,-1,0,0,4,323,325),(325,-1,-1,17,17,1,62,-1,0,0,4,324,326),(326,-1,-1,17,17,1,63,-1,0,0,4,325,327),(327,-1,-1,17,17,1,63,-1,0,0,4,326,328),(328,-1,-1,17,17,1,64,-1,0,0,4,327,329),(329,-1,-1,17,17,1,64,-1,0,0,4,328,330),(330,-1,-1,17,17,1,65,-1,0,0,4,329,331),(331,-1,-1,17,17,1,65,-1,0,0,4,330,-1),(332,-1,-1,22,22,1,61,-1,0,0,4,26,333),(333,-1,-1,22,22,1,61,-1,0,0,4,332,334),(334,-1,-1,22,22,1,62,-1,0,0,4,333,335),(335,-1,-1,22,22,1,62,-1,0,0,4,334,336),(336,-1,-1,22,22,1,63,-1,0,0,4,335,337),(337,-1,-1,22,22,1,63,-1,0,0,4,336,338),(338,-1,-1,22,22,1,64,-1,0,0,4,337,339),(339,-1,-1,22,22,1,64,-1,0,0,4,338,340),(340,-1,-1,22,22,1,65,-1,0,0,4,339,341),(341,-1,-1,22,22,1,65,-1,0,0,4,340,-1),(342,-1,-1,27,27,1,61,-1,0,0,4,31,343),(343,-1,-1,27,27,1,61,-1,0,0,4,342,344),(344,-1,-1,27,27,1,62,-1,0,0,4,343,345),(345,-1,-1,27,27,1,62,-1,0,0,4,344,346),(346,-1,-1,27,27,1,63,-1,0,0,4,345,347),(347,-1,-1,27,27,1,63,-1,0,0,4,346,348),(348,-1,-1,27,27,1,64,-1,0,0,4,347,349),(349,-1,-1,27,27,1,64,-1,0,0,4,348,350),(350,-1,-1,27,27,1,65,-1,0,0,4,349,351),(351,-1,-1,27,27,1,65,-1,0,0,4,350,-1),(352,-1,-1,32,32,1,61,-1,0,0,4,36,353),(353,-1,-1,32,32,1,61,-1,0,0,4,352,354),(354,-1,-1,32,32,1,62,-1,0,0,4,353,355),(355,-1,-1,32,32,1,62,-1,0,0,4,354,356),(356,-1,-1,32,32,1,63,-1,0,0,4,355,357),(357,-1,-1,32,32,1,63,-1,0,0,4,356,358),(358,-1,-1,32,32,1,64,-1,0,0,4,357,359),(359,-1,-1,32,32,1,64,-1,0,0,4,358,360),(360,-1,-1,32,32,1,65,-1,0,0,4,359,361),(361,-1,-1,32,32,1,65,-1,0,0,4,360,-1),(362,-1,-1,37,37,1,61,-1,0,0,4,41,363),(363,-1,-1,37,37,1,61,-1,0,0,4,362,364),(364,-1,-1,37,37,1,62,-1,0,0,4,363,365),(365,-1,-1,37,37,1,62,-1,0,0,4,364,366),(366,-1,-1,37,37,1,63,-1,0,0,4,365,367),(367,-1,-1,37,37,1,63,-1,0,0,4,366,368),(368,-1,-1,37,37,1,64,-1,0,0,4,367,369),(369,-1,-1,37,37,1,64,-1,0,0,4,368,370),(370,-1,-1,37,37,1,65,-1,0,0,4,369,371),(371,-1,-1,37,37,1,65,-1,0,0,4,370,-1),(372,-1,-1,42,42,1,61,-1,0,0,4,46,373),(373,-1,-1,42,42,1,61,-1,0,0,4,372,374),(374,-1,-1,42,42,1,62,-1,0,0,4,373,375),(375,-1,-1,42,42,1,62,-1,0,0,4,374,376),(376,-1,-1,42,42,1,63,-1,0,0,4,375,377),(377,-1,-1,42,42,1,63,-1,0,0,4,376,378),(378,-1,-1,42,42,1,64,-1,0,0,4,377,379),(379,-1,-1,42,42,1,64,-1,0,0,4,378,380),(380,-1,-1,42,42,1,65,-1,0,0,4,379,381),(381,-1,-1,42,42,1,65,-1,0,0,4,380,-1),(382,-1,-1,47,47,1,61,-1,0,0,4,51,383),(383,-1,-1,47,47,1,61,-1,0,0,4,382,384),(384,-1,-1,47,47,1,62,-1,0,0,4,383,385),(385,-1,-1,47,47,1,62,-1,0,0,4,384,386),(386,-1,-1,47,47,1,63,-1,0,0,4,385,387),(387,-1,-1,47,47,1,63,-1,0,0,4,386,388),(388,-1,-1,47,47,1,64,-1,0,0,4,387,389),(389,-1,-1,47,47,1,64,-1,0,0,4,388,390),(390,-1,-1,47,47,1,65,-1,0,0,4,389,391),(391,-1,-1,47,47,1,65,-1,0,0,4,390,-1),(392,-1,-1,52,52,1,61,-1,0,0,4,56,393),(393,-1,-1,52,52,1,61,-1,0,0,4,392,394),(394,-1,-1,52,52,1,62,-1,0,0,4,393,395),(395,-1,-1,52,52,1,62,-1,0,0,4,394,396),(396,-1,-1,52,52,1,63,-1,0,0,4,395,397),(397,-1,-1,52,52,1,63,-1,0,0,4,396,398),(398,-1,-1,52,52,1,64,-1,0,0,4,397,399),(399,-1,-1,52,52,1,64,-1,0,0,4,398,400),(400,-1,-1,52,52,1,65,-1,0,0,4,399,401),(401,-1,-1,52,52,1,65,-1,0,0,4,400,-1),(402,-1,-1,57,57,1,61,-1,0,0,4,61,403),(403,-1,-1,57,57,1,61,-1,0,0,4,402,404),(404,-1,-1,57,57,1,62,-1,0,0,4,403,405),(405,-1,-1,57,57,1,62,-1,0,0,4,404,406),(406,-1,-1,57,57,1,63,-1,0,0,4,405,407),(407,-1,-1,57,57,1,63,-1,0,0,4,406,408),(408,-1,-1,57,57,1,64,-1,0,0,4,407,409),(409,-1,-1,57,57,1,64,-1,0,0,4,408,410),(410,-1,-1,57,57,1,65,-1,0,0,4,409,411),(411,-1,-1,57,57,1,65,-1,0,0,4,410,-1),(412,-1,-1,412,412,3,51,-1,0,0,3,-1,413),(413,-1,-1,412,412,3,51,-1,0,0,3,412,414),(414,-1,-1,412,412,3,51,-1,0,0,3,413,415),(415,-1,-1,412,412,3,51,-1,0,0,3,414,416),(416,-1,-1,412,412,3,51,-1,0,0,3,415,417),(417,-1,-1,412,412,3,51,-1,0,0,3,416,-1),(418,-1,-1,418,418,2,61,-1,0,0,4,-1,419),(419,-1,-1,418,418,2,62,-1,0,0,4,418,420),(420,-1,-1,418,418,2,63,-1,0,0,4,419,421),(421,-1,-1,418,418,2,64,-1,0,0,4,420,422),(422,-1,-1,418,418,2,65,-1,0,0,4,421,1001),(423,-1,-1,423,423,3,61,-1,0,0,4,-1,424),(424,-1,-1,423,423,3,63,-1,0,0,4,423,425),(425,-1,-1,423,423,3,65,-1,0,0,4,424,-1),(426,-1,-1,426,426,3,61,-1,0,0,4,-1,427),(427,-1,-1,426,426,3,62,-1,0,0,4,426,428),(428,-1,-1,426,426,3,63,-1,0,0,4,427,429),(429,-1,-1,426,426,3,64,-1,0,0,4,428,430),(430,-1,-1,426,426,3,65,-1,0,0,4,429,-1),(434,-1,-1,77,77,2,62,-1,0,0,4,79,435),(435,-1,-1,77,77,4,63,-1,0,0,4,434,436),(436,-1,-1,77,77,6,64,-1,0,0,4,435,1083),(437,-1,-1,80,80,2,62,-1,0,0,4,82,438),(438,-1,-1,80,80,3,63,-1,0,0,4,437,439),(439,-1,-1,80,80,4,64,-1,0,0,4,438,1086),(440,-1,-1,119,119,2,62,-1,0,0,4,121,441),(441,-1,-1,119,119,2,63,-1,0,0,4,440,442),(442,-1,-1,119,119,2,64,-1,0,0,4,441,1053),(443,-1,-1,113,113,3,62,-1,0,0,4,115,444),(444,-1,-1,113,113,3,63,-1,0,0,4,443,445),(445,-1,-1,113,113,3,64,-1,0,0,4,444,-1),(446,-1,-1,446,735,3,62,-1,0,0,4,-1,447),(447,-1,-1,446,735,3,63,-1,0,0,4,446,448),(448,-1,-1,446,735,3,64,-1,0,0,4,447,7050),(449,-1,-1,125,125,3,61,-1,0,0,4,127,450),(450,-1,-1,125,125,3,62,-1,0,0,4,449,451),(451,-1,-1,125,125,3,63,-1,0,0,4,450,452),(452,-1,-1,125,125,3,64,-1,0,0,4,451,453),(453,-1,-1,125,125,3,65,-1,0,0,4,452,1061),(454,-1,-1,122,122,3,61,-1,0,0,4,124,455),(455,-1,-1,122,122,3,62,-1,0,0,4,454,456),(456,-1,-1,122,122,3,63,-1,0,0,4,455,457),(457,-1,-1,122,122,3,64,-1,0,0,4,456,458),(458,-1,-1,122,122,3,65,-1,0,0,4,457,1066),(459,459,459,459,459,2,61,3297,8,180,4,-1,460),(460,459,459,459,459,4,63,3298,8,180,4,459,461),(461,459,459,459,459,6,65,3299,8,180,4,460,1189),(462,-1,-1,462,462,2,63,-1,0,0,4,-1,463),(463,-1,-1,462,462,2,64,-1,0,0,4,462,464),(464,-1,-1,462,462,2,65,-1,0,0,4,463,7994),(468,-1,-1,468,468,2,63,-1,0,0,4,-1,469),(469,-1,-1,468,468,2,64,-1,0,0,4,468,470),(470,-1,-1,468,468,2,65,-1,0,0,4,469,6439),(471,-1,-1,471,471,2,63,-1,0,0,4,-1,472),(472,-1,-1,471,471,2,64,-1,0,0,4,471,473),(473,-1,-1,471,471,2,65,-1,0,0,4,472,12899),(474,-1,-1,474,474,2,63,-1,0,0,4,-1,475),(475,-1,-1,474,474,2,64,-1,0,0,4,474,476),(476,-1,-1,474,474,2,65,-1,0,0,4,475,15359),(477,-1,-1,477,477,2,63,-1,0,0,4,-1,478),(478,-1,-1,477,477,2,64,-1,0,0,4,477,479),(479,-1,-1,477,477,2,65,-1,0,0,4,478,6233),(480,-1,-1,480,480,2,63,-1,0,0,4,-1,481),(481,-1,-1,480,480,2,64,-1,0,0,4,480,482),(482,-1,-1,480,480,2,65,-1,0,0,4,481,4921),(483,-1,-1,483,483,2,63,-1,0,0,4,-1,484),(484,-1,-1,483,483,2,64,-1,0,0,4,483,485),(485,-1,-1,483,483,2,65,-1,0,0,4,484,-1),(489,-1,-1,489,489,3,63,-1,0,0,4,-1,490),(490,-1,-1,489,489,3,64,-1,0,0,4,489,491),(491,-1,-1,489,489,3,65,-1,0,0,4,490,7116),(492,-1,-1,492,492,2,63,-1,0,0,4,-1,493),(493,-1,-1,492,492,2,64,-1,0,0,4,492,494),(494,-1,-1,492,492,2,65,-1,0,0,4,493,7128),(495,-1,-1,495,495,2,63,-1,0,0,4,-1,496),(496,-1,-1,495,495,2,64,-1,0,0,4,495,497),(497,-1,-1,495,495,2,65,-1,0,0,4,496,6260),(498,-1,-1,498,498,2,63,-1,0,0,4,-1,499),(499,-1,-1,498,498,2,64,-1,0,0,4,498,500),(500,-1,-1,498,498,2,65,-1,0,0,4,499,886),(501,-1,-1,501,501,2,63,-1,0,0,4,-1,502),(502,-1,-1,501,501,2,64,-1,0,0,4,501,503),(503,-1,-1,501,501,2,65,-1,0,0,4,502,6319),(504,-1,-1,247,247,3,62,-1,0,0,4,249,505),(505,-1,-1,247,247,3,63,-1,0,0,4,504,506),(506,-1,-1,247,247,3,64,-1,0,0,4,505,-1),(507,507,507,507,507,3,61,3252,9,180,4,-1,508),(508,507,507,507,507,3,63,3253,9,180,4,507,509),(509,507,507,507,507,3,65,3254,9,180,4,508,-1),(510,510,510,510,510,3,61,3255,37,240,4,-1,511),(511,510,510,510,510,3,63,3256,37,240,4,510,512),(512,510,510,510,510,3,65,3257,37,240,4,511,7425),(513,513,513,513,513,3,61,3274,4,120,4,-1,514),(514,513,513,513,513,3,63,3275,4,120,4,513,515),(515,513,513,513,513,3,65,3276,4,120,4,514,6095),(516,516,516,516,516,2,62,3338,5,480,4,-1,6398),(517,517,517,517,517,3,61,3258,12,600,4,-1,518),(518,517,517,517,517,3,63,3259,12,600,4,517,519),(519,517,517,517,517,3,65,3260,12,600,4,518,1440),(520,520,520,520,520,3,61,3265,6,540,4,-1,521),(521,520,520,520,520,3,63,3266,6,540,4,520,522),(522,520,520,520,520,3,65,3267,6,540,4,521,1507),(523,523,523,523,523,5,61,3268,9,540,4,-1,524),(524,523,523,523,523,4,63,3269,9,540,4,523,525),(525,523,523,523,523,3,65,3270,9,540,4,524,-1),(526,526,526,526,526,5,62,3248,0,1,4,-1,527),(527,526,526,526,526,3,64,3249,0,1,4,526,-1),(528,528,528,528,528,4,61,3283,5,720,4,-1,529),(529,528,528,528,528,3,63,3284,5,720,4,528,530),(530,528,528,528,528,2,65,3285,5,720,4,529,900),(531,131,131,131,131,3,63,3250,4,900,4,131,532),(532,131,131,131,131,6,64,3251,4,900,4,531,1203),(533,155,155,155,155,6,64,3264,8,60,4,155,1344),(534,534,534,534,534,3,61,3261,4,2160,4,-1,535),(535,534,534,534,534,3,63,3262,4,2160,4,534,536),(536,534,534,534,534,3,65,3263,4,2160,4,535,715),(537,-1,-1,537,537,3,63,-1,0,0,4,-1,538),(538,-1,-1,537,537,3,64,-1,0,0,4,537,-1),(539,-1,-1,230,230,2,63,-1,0,0,4,232,540),(540,-1,-1,230,230,4,64,-1,0,0,4,539,541),(541,-1,-1,230,230,6,65,-1,0,0,4,540,12677),(542,-1,-1,255,255,2,63,-1,0,0,4,257,543),(543,-1,-1,255,255,4,64,-1,0,0,4,542,544),(544,-1,-1,255,255,6,65,-1,0,0,4,543,1163),(545,545,545,545,545,3,61,3271,3,900,4,-1,546),(546,545,545,545,545,3,63,3272,3,900,4,545,547),(547,545,545,545,545,3,65,3273,3,900,4,546,1293),(548,548,548,548,548,4,61,3277,5,900,4,-1,549),(549,548,548,548,548,3,63,3278,5,900,4,548,550),(550,548,548,548,548,2,65,3279,5,900,4,549,1225),(551,-1,-1,551,551,2,61,-1,0,0,4,-1,552),(552,-1,-1,551,551,2,62,-1,0,0,4,551,553),(553,-1,-1,551,551,2,63,-1,0,0,4,552,554),(554,-1,-1,551,551,2,64,-1,0,0,4,553,555),(555,-1,-1,551,551,2,65,-1,0,0,4,554,1633),(556,-1,-1,556,556,2,61,-1,0,0,4,-1,557),(557,-1,-1,556,556,2,62,-1,0,0,4,556,558),(558,-1,-1,556,556,2,63,-1,0,0,4,557,559),(559,-1,-1,556,556,2,64,-1,0,0,4,558,560),(560,-1,-1,556,556,2,65,-1,0,0,4,559,1563),(561,-1,-1,561,561,2,61,-1,0,0,4,-1,562),(562,-1,-1,561,561,4,63,-1,0,0,4,561,563),(563,-1,-1,561,561,6,65,-1,0,0,4,562,1624),(564,-1,-1,564,564,3,61,-1,0,0,4,-1,565),(565,-1,-1,564,564,3,63,-1,0,0,4,564,566),(566,-1,-1,564,564,3,65,-1,0,0,4,565,1621),(567,-1,-1,567,567,5,63,-1,0,0,4,-1,5061),(574,-1,-1,574,574,3,61,-1,0,0,4,-1,575),(575,-1,-1,574,574,3,63,-1,0,0,4,574,576),(576,-1,-1,574,574,3,65,-1,0,0,4,575,7718),(577,-1,-1,577,577,2,61,-1,0,0,4,-1,578),(578,-1,-1,577,577,4,63,-1,0,0,4,577,579),(579,-1,-1,577,577,6,65,-1,0,0,4,578,-1),(580,-1,-1,580,580,4,61,-1,0,0,4,-1,581),(581,-1,-1,580,580,3,63,-1,0,0,4,580,582),(582,-1,-1,580,580,2,65,-1,0,0,4,581,-1),(583,-1,-1,583,583,2,63,-1,0,0,4,-1,584),(584,-1,-1,583,583,2,64,-1,0,0,4,583,585),(585,-1,-1,583,583,2,65,-1,0,0,4,584,-1),(586,-1,-1,586,586,2,61,-1,0,0,4,-1,587),(587,-1,-1,586,586,4,63,-1,0,0,4,586,588),(588,-1,-1,586,586,6,65,-1,0,0,4,587,6130),(589,-1,-1,589,589,3,61,-1,0,0,4,-1,590),(590,-1,-1,589,589,3,63,-1,0,0,4,589,591),(591,-1,-1,589,589,3,65,-1,0,0,4,590,893),(592,592,592,592,592,6,63,3282,2,18,4,-1,702),(593,-1,-1,593,593,3,61,-1,0,0,4,-1,594),(594,-1,-1,593,593,3,63,-1,0,0,4,593,595),(595,-1,-1,593,593,3,65,-1,0,0,4,594,5972),(596,-1,-1,596,596,2,61,-1,0,0,4,-1,597),(597,-1,-1,596,596,4,63,-1,0,0,4,596,598),(598,-1,-1,596,596,6,65,-1,0,0,4,597,5973),(599,-1,-1,599,599,2,61,-1,0,0,4,-1,600),(600,-1,-1,599,599,4,63,-1,0,0,4,599,601),(601,-1,-1,599,599,6,65,-1,0,0,4,600,1536),(602,-1,-1,602,602,3,61,-1,0,0,4,-1,603),(603,-1,-1,602,602,3,63,-1,0,0,4,602,604),(604,-1,-1,602,602,3,65,-1,0,0,4,603,1533),(605,-1,-1,605,605,6,63,-1,0,0,4,-1,-1),(606,-1,-1,606,606,1,61,-1,0,0,4,-1,607),(607,-1,-1,606,606,1,62,-1,0,0,4,606,608),(608,-1,-1,606,606,1,63,-1,0,0,4,607,609),(609,-1,-1,606,606,1,64,-1,0,0,4,608,610),(610,-1,-1,606,606,1,65,-1,0,0,4,609,-1),(611,-1,-1,611,611,2,61,-1,0,0,4,-1,612),(612,-1,-1,611,611,2,62,-1,0,0,4,611,613),(613,-1,-1,611,611,2,63,-1,0,0,4,612,614),(614,-1,-1,611,611,2,64,-1,0,0,4,613,615),(615,-1,-1,611,611,2,65,-1,0,0,4,614,7175),(616,616,616,616,616,5,63,3286,7,900,4,-1,617),(617,616,616,616,616,4,64,3287,7,900,4,616,618),(618,616,616,616,616,3,65,3288,7,900,4,617,1248),(619,619,619,619,619,3,61,3292,6,900,4,-1,620),(620,619,619,619,619,2,63,3293,6,900,4,619,621),(621,619,619,619,619,1,65,3294,6,900,4,620,721),(622,-1,-1,622,622,3,61,-1,0,0,4,-1,623),(623,-1,-1,622,622,3,62,-1,0,0,4,622,624),(624,-1,-1,622,622,3,63,-1,0,0,4,623,8329),(625,-1,-1,625,625,1,61,-1,0,0,4,-1,626),(626,-1,-1,625,625,2,63,-1,0,0,4,625,627),(627,-1,-1,625,625,3,65,-1,0,0,4,626,4733),(628,-1,-1,628,628,2,62,-1,0,0,4,-1,629),(629,-1,-1,628,628,4,64,-1,0,0,4,628,-1),(630,630,630,630,630,6,63,5243,7,1,4,-1,-1),(631,-1,-1,631,631,2,61,-1,0,0,4,-1,632),(632,-1,-1,631,631,3,63,-1,0,0,4,631,633),(633,-1,-1,631,631,4,65,-1,0,0,4,632,1172),(634,-1,-1,634,634,1,61,-1,0,0,4,-1,635),(635,-1,-1,634,634,2,63,-1,0,0,4,634,636),(636,-1,-1,634,634,3,65,-1,0,0,4,635,844),(637,-1,-1,637,637,3,61,-1,0,0,4,-1,638),(638,-1,-1,637,637,6,63,-1,0,0,4,637,639),(639,-1,-1,637,637,9,65,-1,0,0,4,638,770),(640,-1,-1,267,267,2,61,-1,0,0,4,269,641),(641,-1,-1,267,267,4,63,-1,0,0,4,640,642),(642,-1,-1,267,267,6,65,-1,0,0,4,641,924),(643,643,643,643,643,4,62,5227,0,1,4,-1,-1),(644,-1,-1,644,644,4,60,-1,0,0,4,-1,1601),(645,645,-1,645,645,4,64,3614,4,5,4,-1,5999),(649,-1,-1,649,649,2,61,-1,0,0,4,-1,650),(650,-1,-1,649,649,4,63,-1,0,0,4,649,651),(651,-1,-1,649,649,6,65,-1,0,0,4,650,5860),(652,-1,-1,652,652,2,61,-1,0,0,4,-1,653),(653,-1,-1,652,652,4,63,-1,0,0,4,652,654),(654,-1,-1,652,652,6,65,-1,0,0,4,653,-1),(655,-1,-1,655,655,3,59,-1,0,0,3,-1,656),(656,-1,-1,655,655,6,59,-1,0,0,3,655,657),(657,-1,-1,655,655,9,59,-1,0,0,3,656,-1),(658,-1,-1,658,658,2,55,-1,0,0,3,-1,659),(659,-1,-1,658,658,4,55,-1,0,0,3,658,660),(660,-1,-1,658,658,6,55,-1,0,0,3,659,5306),(661,-1,-1,65,661,1,51,-1,0,0,3,-1,662),(662,-1,-1,65,661,1,51,-1,0,0,3,661,663),(663,-1,-1,65,661,1,51,-1,0,0,3,662,674),(665,-1,-1,270,665,3,59,-1,0,0,3,-1,666),(666,-1,-1,270,665,6,59,-1,0,0,3,665,667),(667,-1,-1,270,665,9,59,-1,0,0,3,666,668),(668,-1,-1,270,665,2,63,-1,0,0,4,667,669),(669,-1,-1,270,665,2,64,-1,0,0,4,668,670),(670,-1,-1,270,665,2,65,-1,0,0,4,669,7612),(671,-1,-1,671,671,3,59,-1,0,0,3,-1,-1),(672,-1,-1,62,62,5,61,-1,0,0,7,64,673),(673,-1,-1,62,62,5,61,-1,0,0,7,672,-1),(674,-1,-1,65,661,3,61,-1,0,0,7,663,675),(675,-1,-1,65,661,3,61,-1,0,0,7,674,1031),(676,-1,-1,71,71,2,61,-1,0,0,7,73,677),(677,-1,-1,71,71,3,61,-1,0,0,7,676,978),(678,-1,-1,678,678,3,61,-1,0,0,7,-1,679),(679,-1,-1,678,678,3,61,-1,0,0,7,678,680),(680,-1,-1,678,678,3,61,-1,0,0,7,679,681),(681,-1,-1,678,678,3,61,-1,0,0,7,680,682),(682,-1,-1,678,678,3,61,-1,0,0,7,681,6518),(683,-1,-1,683,683,3,61,-1,0,0,7,-1,684),(684,-1,-1,683,683,6,61,-1,0,0,7,683,685),(685,-1,-1,683,683,9,61,-1,0,0,7,684,1036),(686,-1,-1,686,686,5,55,-1,0,0,7,-1,687),(687,-1,-1,686,686,5,55,-1,0,0,7,686,688),(688,-1,-1,686,686,5,55,-1,0,0,7,687,689),(689,-1,-1,686,686,5,55,-1,0,0,7,688,690),(690,-1,-1,686,686,5,55,-1,0,0,7,689,7640),(691,-1,-1,691,691,9,55,-1,0,0,7,-1,-1),(692,-1,-1,692,692,3,55,-1,0,0,7,-1,693),(693,-1,-1,692,692,6,55,-1,0,0,7,692,694),(694,-1,-1,692,692,9,55,-1,0,0,7,693,7647),(695,-1,-1,695,695,4,65,-1,0,0,7,-1,696),(696,-1,-1,695,695,4,65,-1,0,0,7,695,697),(697,-1,-1,695,695,4,65,-1,0,0,7,696,698),(698,-1,-1,695,695,4,65,-1,0,0,7,697,699),(699,-1,-1,695,695,4,65,-1,0,0,7,698,15529),(700,-1,-1,213,213,9,61,-1,0,0,7,215,-1),(701,-1,-1,275,275,9,61,-1,0,0,7,277,-1),(702,592,592,592,592,3,65,4842,2,18,7,592,703),(703,592,592,592,592,3,65,4843,2,18,7,702,704),(704,592,592,592,592,3,65,4844,2,18,7,703,705),(705,592,592,592,592,3,65,4845,2,18,7,704,706),(706,592,592,592,592,3,65,4846,2,18,7,705,1102),(715,534,534,534,534,3,65,5112,4,2160,7,536,716),(716,534,534,534,534,6,65,5113,4,2160,7,715,717),(717,534,534,534,534,9,65,5114,4,2160,7,716,1278),(718,718,718,718,718,3,65,4521,7,4320,7,-1,719),(719,718,718,718,718,6,65,4522,7,4320,7,718,720),(720,718,718,718,718,9,65,4523,7,4320,7,719,1019),(721,619,619,619,619,5,65,5110,6,900,7,621,722),(722,619,619,619,619,5,65,5111,6,900,7,721,6296),(723,723,723,723,723,9,65,4788,6,30,7,-1,4963),(724,-1,-1,724,724,3,65,-1,0,0,7,-1,725),(725,-1,-1,724,724,3,65,-1,0,0,7,724,726),(726,-1,-1,724,724,3,65,-1,0,0,7,725,727),(727,-1,-1,724,724,3,65,-1,0,0,7,726,728),(728,-1,-1,724,724,3,65,-1,0,0,7,727,5254),(729,-1,-1,729,729,5,65,-1,0,0,7,-1,730),(730,-1,-1,729,729,5,65,-1,0,0,7,729,731),(731,-1,-1,729,729,5,65,-1,0,0,7,730,732),(732,-1,-1,729,729,5,65,-1,0,0,7,731,733),(733,-1,-1,729,729,5,65,-1,0,0,7,732,1467),(734,-1,-1,734,734,12,65,-1,0,0,7,-1,-1),(735,-1,-1,735,735,3,62,-1,0,0,7,-1,736),(736,-1,-1,735,735,3,62,-1,0,0,7,735,737),(737,-1,-1,735,735,3,62,-1,0,0,7,736,7056),(738,-1,-1,98,738,3,55,-1,0,0,7,-1,739),(739,-1,-1,98,738,6,55,-1,0,0,7,738,740),(740,-1,-1,98,738,9,55,-1,0,0,7,739,5317),(746,746,746,746,746,3,65,4549,10,2160,7,-1,747),(747,746,746,746,746,6,65,4550,10,2160,7,746,748),(748,746,746,746,746,9,65,4551,10,2160,7,747,1491),(749,749,749,749,749,5,65,4790,11,1800,7,-1,750),(750,749,749,749,749,5,65,4791,11,1800,7,749,751),(751,749,749,749,749,5,65,4792,11,1800,7,750,752),(752,749,749,749,749,5,65,4793,11,1800,7,751,753),(753,749,749,749,749,5,65,4794,11,1800,7,752,1206),(754,-1,-1,754,754,3,65,-1,0,0,7,-1,755),(755,-1,-1,754,754,6,65,-1,0,0,7,754,756),(756,-1,-1,754,754,9,65,-1,0,0,7,755,7659),(757,757,-1,757,757,5,65,4796,6,1800,7,-1,758),(758,757,-1,757,757,5,65,4797,6,1800,7,757,759),(759,757,-1,757,757,5,65,4798,6,1800,7,758,760),(760,757,-1,757,757,5,65,4799,6,1800,7,759,761),(761,757,-1,757,757,5,65,4800,6,1800,7,760,1222),(762,-1,-1,762,762,4,65,-1,0,0,7,-1,763),(763,-1,-1,762,762,4,65,-1,0,0,7,762,764),(764,-1,-1,762,762,4,65,-1,0,0,7,763,765),(765,-1,-1,762,762,4,65,-1,0,0,7,764,766),(766,-1,-1,762,762,4,65,-1,0,0,7,765,-1),(767,-1,-1,767,767,3,65,-1,0,0,7,-1,768),(768,-1,-1,767,767,6,65,-1,0,0,7,767,769),(769,-1,-1,767,767,9,65,-1,0,0,7,768,1099),(770,-1,-1,637,637,3,65,-1,0,0,7,639,771),(771,-1,-1,637,637,6,65,-1,0,0,7,770,772),(772,-1,-1,637,637,9,65,-1,0,0,7,771,4749),(773,773,-1,773,773,3,65,4552,5,1800,7,-1,774),(774,773,-1,773,773,6,65,4553,5,1800,7,773,775),(775,773,-1,773,773,9,65,4554,5,1800,7,774,5854),(776,-1,-1,776,776,3,65,-1,0,0,7,-1,777),(777,-1,-1,776,776,3,65,-1,0,0,7,776,778),(778,-1,-1,776,776,3,65,-1,0,0,7,777,779),(779,-1,-1,776,776,3,65,-1,0,0,7,778,780),(780,-1,-1,776,776,3,65,-1,0,0,7,779,-1),(781,-1,-1,781,781,12,65,-1,0,0,7,-1,5850),(782,-1,-1,782,782,3,65,-1,0,0,7,-1,783),(783,-1,-1,782,782,6,65,-1,0,0,7,782,784),(784,-1,-1,782,782,9,65,-1,0,0,7,783,-1),(785,785,785,785,785,5,65,5235,8,900,7,-1,786),(786,785,785,785,785,5,65,5236,8,900,7,785,787),(787,785,785,785,785,5,65,5237,8,900,7,786,788),(788,785,785,785,785,5,65,5238,8,900,7,787,789),(789,785,785,785,785,5,65,5239,8,900,7,788,15235),(790,-1,-1,790,790,3,65,-1,0,0,7,-1,791),(791,-1,-1,790,790,3,65,-1,0,0,7,790,792),(792,-1,-1,790,790,3,65,-1,0,0,7,791,793),(793,-1,-1,790,790,3,65,-1,0,0,7,792,794),(794,-1,-1,790,790,3,65,-1,0,0,7,793,5259),(795,-1,-1,795,795,5,65,-1,0,0,7,-1,796),(796,-1,-1,795,795,5,65,-1,0,0,7,795,797),(797,-1,-1,795,795,5,65,-1,0,0,7,796,798),(798,-1,-1,795,795,5,65,-1,0,0,7,797,799),(799,-1,-1,795,795,5,65,-1,0,0,7,798,1430),(800,-1,-1,800,800,3,65,-1,0,0,7,-1,801),(801,-1,-1,800,800,6,65,-1,0,0,7,800,802),(802,-1,-1,800,800,9,65,-1,0,0,7,801,-1),(803,-1,-1,803,803,3,65,-1,0,0,7,-1,804),(804,-1,-1,803,803,6,65,-1,0,0,7,803,805),(805,-1,-1,803,803,9,65,-1,0,0,7,804,-1),(806,-1,-1,806,806,12,65,-1,0,0,7,-1,-1),(807,-1,-1,807,807,3,65,-1,0,0,7,-1,808),(808,-1,-1,807,807,6,65,-1,0,0,7,807,809),(809,-1,-1,807,807,9,65,-1,0,0,7,808,1268),(810,-1,-1,810,810,5,65,-1,0,0,7,-1,811),(811,-1,-1,810,810,5,65,-1,0,0,7,810,812),(812,-1,-1,810,810,5,65,-1,0,0,7,811,813),(813,-1,-1,810,810,5,65,-1,0,0,7,812,814),(814,-1,-1,810,810,5,65,-1,0,0,7,813,4824),(815,-1,-1,815,815,4,65,-1,0,0,7,-1,816),(816,-1,-1,815,815,4,65,-1,0,0,7,815,817),(817,-1,-1,815,815,4,65,-1,0,0,7,816,818),(818,-1,-1,815,815,4,65,-1,0,0,7,817,819),(819,-1,-1,815,815,4,65,-1,0,0,7,818,5141),(820,-1,-1,820,820,3,65,-1,0,0,7,-1,821),(821,-1,-1,820,820,6,65,-1,0,0,7,820,822),(822,-1,-1,820,820,9,65,-1,0,0,7,821,1265),(823,-1,-1,823,823,5,65,-1,0,0,7,-1,824),(824,-1,-1,823,823,5,65,-1,0,0,7,823,825),(825,-1,-1,823,823,5,65,-1,0,0,7,824,826),(826,-1,-1,823,823,5,65,-1,0,0,7,825,827),(827,-1,-1,823,823,5,65,-1,0,0,7,826,-1),(828,828,828,828,828,3,65,5240,2,3600,7,-1,829),(829,828,828,828,828,6,65,5241,2,3600,7,828,830),(830,828,828,828,828,9,65,5242,2,3600,7,829,16250),(834,-1,-1,834,834,3,65,-1,0,0,7,-1,835),(835,-1,-1,834,834,3,65,-1,0,0,7,834,836),(836,-1,-1,834,834,3,65,-1,0,0,7,835,837),(837,-1,-1,834,834,3,65,-1,0,0,7,836,838),(838,-1,-1,834,834,3,65,-1,0,0,7,837,-1),(839,-1,-1,839,839,5,65,-1,0,0,7,-1,840),(840,-1,-1,839,839,5,65,-1,0,0,7,839,841),(841,-1,-1,839,839,5,65,-1,0,0,7,840,842),(842,-1,-1,839,839,5,65,-1,0,0,7,841,843),(843,-1,-1,839,839,5,65,-1,0,0,7,842,5325),(844,-1,-1,634,634,5,65,-1,0,0,7,636,845),(845,-1,-1,634,634,5,65,-1,0,0,7,844,1319),(846,-1,-1,846,846,3,65,-1,0,0,7,-1,847),(847,-1,-1,846,846,6,65,-1,0,0,7,846,848),(848,-1,-1,846,846,9,65,-1,0,0,7,847,1301),(849,-1,-1,849,849,3,65,-1,0,0,7,-1,850),(850,-1,-1,849,849,6,65,-1,0,0,7,849,851),(851,-1,-1,849,849,9,65,-1,0,0,7,850,10621),(852,-1,-1,852,852,5,65,-1,0,0,7,-1,853),(853,-1,-1,852,852,5,65,-1,0,0,7,852,854),(854,-1,-1,852,852,5,65,-1,0,0,7,853,5500),(855,-1,-1,855,855,5,65,-1,0,0,7,-1,856),(856,-1,-1,855,855,5,65,-1,0,0,7,855,857),(857,-1,-1,855,855,5,65,-1,0,0,7,856,858),(858,-1,-1,855,855,5,65,-1,0,0,7,857,859),(859,-1,-1,855,855,5,65,-1,0,0,7,858,7673),(860,860,860,860,860,3,65,3297,5,180,7,-1,861),(861,860,860,860,860,6,65,3298,5,180,7,860,862),(862,860,860,860,860,9,65,3299,5,180,7,861,5130),(863,863,-1,863,863,12,65,5248,6,4320,7,-1,-1),(864,-1,-1,864,864,3,65,-1,0,0,7,-1,865),(865,-1,-1,864,864,6,65,-1,0,0,7,864,866),(866,-1,-1,864,864,9,65,-1,0,0,7,865,1290),(867,-1,-1,867,867,5,65,-1,0,0,7,-1,868),(868,-1,-1,867,867,5,65,-1,0,0,7,867,869),(869,-1,-1,867,867,5,65,-1,0,0,7,868,870),(870,-1,-1,867,867,5,65,-1,0,0,7,869,871),(871,-1,-1,867,867,5,65,-1,0,0,7,870,7362),(872,872,872,872,872,3,65,4802,5,180,7,-1,873),(873,872,872,872,872,6,65,4803,5,180,7,872,874),(874,872,872,872,872,9,65,4804,5,180,7,873,7367),(875,875,875,875,875,3,65,4805,5,180,7,-1,876),(876,875,875,875,875,6,65,4806,5,180,7,875,877),(877,875,875,875,875,9,65,4807,5,180,7,876,7370),(878,-1,-1,878,878,3,65,-1,0,0,7,-1,879),(879,-1,-1,878,878,6,65,-1,0,0,7,878,880),(880,-1,-1,878,878,9,65,-1,0,0,7,879,1539),(881,-1,-1,881,881,3,65,-1,0,0,7,-1,882),(882,-1,-1,881,881,3,65,-1,0,0,7,881,883),(883,-1,-1,881,881,3,65,-1,0,0,7,882,884),(884,-1,-1,881,881,3,65,-1,0,0,7,883,885),(885,-1,-1,881,881,3,65,-1,0,0,7,884,-1),(886,-1,-1,498,498,5,65,-1,0,0,7,500,887),(887,-1,-1,498,498,5,65,-1,0,0,7,886,975),(888,-1,-1,888,888,3,65,-1,0,0,7,-1,889),(889,-1,-1,888,888,3,65,-1,0,0,7,888,890),(890,-1,-1,888,888,3,65,-1,0,0,7,889,891),(891,-1,-1,888,888,3,65,-1,0,0,7,890,892),(892,-1,-1,888,888,3,65,-1,0,0,7,891,16267),(893,-1,-1,589,589,5,65,-1,0,0,7,591,894),(894,-1,-1,589,589,5,65,-1,0,0,7,893,5270),(895,-1,-1,895,895,5,65,-1,0,0,7,-1,896),(896,-1,-1,895,895,5,65,-1,0,0,7,895,897),(897,-1,-1,895,895,5,65,-1,0,0,7,896,898),(898,-1,-1,895,895,5,65,-1,0,0,7,897,899),(899,-1,-1,895,895,5,65,-1,0,0,7,898,6075),(900,528,528,528,528,5,65,4826,5,720,7,530,901),(901,528,528,528,528,5,65,4827,5,720,7,900,6103),(907,-1,-1,907,907,5,65,-1,0,0,7,-1,908),(908,-1,-1,907,907,5,65,-1,0,0,7,907,909),(909,-1,-1,907,907,5,65,-1,0,0,7,908,910),(910,-1,-1,907,907,5,65,-1,0,0,7,909,911),(911,-1,-1,907,907,5,65,-1,0,0,7,910,5243),(912,912,912,912,912,3,65,4925,4,3600,7,-1,913),(913,912,912,912,912,6,65,4926,4,3600,7,912,914),(914,912,912,912,912,9,65,4927,4,3600,7,913,1330),(915,-1,-1,915,915,3,65,-1,0,0,7,-1,916),(916,-1,-1,915,915,6,65,-1,0,0,7,915,917),(917,-1,-1,915,915,9,65,-1,0,0,7,916,-1),(918,-1,-1,918,918,3,65,-1,0,0,7,-1,919),(919,-1,-1,918,918,6,65,-1,0,0,7,918,920),(920,-1,-1,918,918,9,65,-1,0,0,7,919,-1),(921,921,921,921,921,12,65,4833,8,60,7,-1,1340),(922,922,922,922,922,12,65,4834,8,60,7,-1,1341),(923,923,923,923,923,12,65,4835,8,60,7,-1,1342),(924,-1,-1,267,267,5,65,-1,0,0,7,642,925),(925,-1,-1,267,267,5,65,-1,0,0,7,924,5133),(926,926,926,926,926,3,65,4836,12,1800,7,-1,927),(927,926,926,926,926,3,65,4837,12,1800,7,926,928),(928,926,926,926,926,3,65,4838,12,1800,7,927,929),(929,926,926,926,926,3,65,4839,12,1800,7,928,930),(930,926,926,926,926,3,65,4840,12,1800,7,929,14991),(931,931,931,931,931,3,65,5245,13,4320,7,-1,932),(932,931,931,931,931,6,65,5246,13,4320,7,931,933),(933,931,931,931,931,9,65,5247,13,4320,7,932,-1),(934,-1,-1,113,934,2,55,-1,0,0,3,-1,935),(935,-1,-1,113,934,4,55,-1,0,0,3,934,936),(936,-1,-1,113,934,6,55,-1,0,0,3,935,943),(937,-1,-1,113,937,2,55,-1,0,0,3,-1,938),(938,-1,-1,113,937,4,55,-1,0,0,3,937,939),(939,-1,-1,113,937,6,55,-1,0,0,3,938,946),(940,-1,-1,113,940,2,55,-1,0,0,3,-1,941),(941,-1,-1,113,940,4,55,-1,0,0,3,940,942),(942,-1,-1,113,940,6,55,-1,0,0,3,941,949),(943,-1,-1,113,934,3,62,-1,0,0,4,936,944),(944,-1,-1,113,934,3,63,-1,0,0,4,943,945),(945,-1,-1,113,934,3,64,-1,0,0,4,944,-1),(946,-1,-1,113,937,3,62,-1,0,0,4,939,947),(947,-1,-1,113,937,3,63,-1,0,0,4,946,948),(948,-1,-1,113,937,3,64,-1,0,0,4,947,-1),(949,-1,-1,113,940,3,62,-1,0,0,4,942,950),(950,-1,-1,113,940,3,63,-1,0,0,4,949,951),(951,-1,-1,113,940,3,64,-1,0,0,4,950,-1),(952,-1,-1,952,952,3,61,-1,0,0,4,-1,953),(953,-1,-1,952,952,3,63,-1,0,0,4,952,954),(954,-1,-1,952,952,3,65,-1,0,0,4,953,-1),(955,-1,-1,955,955,3,61,-1,0,0,4,-1,956),(956,-1,-1,955,955,3,62,-1,0,0,4,955,957),(957,-1,-1,955,955,3,63,-1,0,0,4,956,958),(958,-1,-1,955,955,3,64,-1,0,0,4,957,959),(959,-1,-1,955,955,3,65,-1,0,0,4,958,-1),(960,960,960,960,960,9,59,2760,7,4320,3,-1,-1),(961,961,961,961,961,9,59,2759,11,4320,3,-1,-1),(962,-1,-1,962,962,5,65,-1,0,0,7,-1,963),(963,-1,-1,962,962,5,65,-1,0,0,7,962,964),(964,-1,-1,962,962,5,65,-1,0,0,7,963,965),(965,-1,-1,962,962,5,65,-1,0,0,7,964,966),(966,-1,-1,962,962,5,65,-1,0,0,7,965,6223),(967,967,967,967,967,3,65,4564,10,1800,7,-1,968),(968,967,967,967,967,6,65,4565,10,1800,7,967,969),(969,967,967,967,967,9,65,4566,10,1800,7,968,6464),(970,970,970,970,970,5,65,4828,6,1800,7,-1,971),(971,970,970,970,970,5,65,4829,6,1800,7,970,972),(972,970,970,970,970,5,65,4830,6,1800,7,971,973),(973,970,970,970,970,5,65,4831,6,1800,7,972,974),(974,970,970,970,970,5,65,4832,6,1800,7,973,1324),(975,-1,-1,498,498,5,65,-1,0,0,15,887,13262),(976,-1,-1,976,976,5,59,-1,0,0,15,-1,-1),(977,977,977,977,977,6,64,13835,72,600,15,-1,-1),(978,-1,-1,71,71,5,68,-1,0,0,8,677,-1),(979,-1,-1,979,979,3,59,-1,0,0,8,-1,980),(980,-1,-1,979,979,6,59,-1,0,0,8,979,981),(981,-1,-1,979,979,9,59,-1,0,0,8,980,-1),(982,-1,-1,982,982,3,59,-1,0,0,8,-1,983),(983,-1,-1,982,982,6,59,-1,0,0,8,982,984),(984,-1,-1,982,982,9,59,-1,0,0,8,983,-1),(985,-1,-1,985,985,3,59,-1,0,0,8,-1,986),(986,-1,-1,985,985,6,59,-1,0,0,8,985,987),(987,-1,-1,985,985,9,59,-1,0,0,8,986,-1),(988,-1,-1,988,988,3,59,-1,0,0,8,-1,989),(989,-1,-1,988,988,6,59,-1,0,0,8,988,990),(990,-1,-1,988,988,9,59,-1,0,0,8,989,-1),(991,-1,-1,991,991,3,59,-1,0,0,8,-1,992),(992,-1,-1,991,991,6,59,-1,0,0,8,991,993),(993,-1,-1,991,991,9,59,-1,0,0,8,992,-1),(994,-1,-1,994,994,3,59,-1,0,0,8,-1,995),(995,-1,-1,994,994,6,59,-1,0,0,8,994,996),(996,-1,-1,994,994,9,59,-1,0,0,8,995,-1),(997,-1,-1,997,997,5,60,-1,0,0,8,-1,998),(998,-1,-1,997,997,5,65,-1,0,0,8,997,999),(999,-1,-1,997,997,5,70,-1,0,0,8,998,1113),(1000,1000,-1,1000,1000,0,5,5824,20,1080,0,-1,-1),(1001,-1,-1,418,418,5,66,-1,0,0,8,422,1002),(1002,-1,-1,418,418,5,67,-1,0,0,8,1001,1003),(1003,-1,-1,418,418,5,68,-1,0,0,8,1002,1004),(1004,-1,-1,418,418,5,69,-1,0,0,8,1003,1005),(1005,-1,-1,418,418,5,70,-1,0,0,8,1004,4678),(1006,-1,-1,1006,1006,5,66,-1,0,0,8,-1,1007),(1007,-1,-1,1006,1006,5,67,-1,0,0,8,1006,1008),(1008,-1,-1,1006,1006,5,68,-1,0,0,8,1007,1009),(1009,-1,-1,1006,1006,5,69,-1,0,0,8,1008,1010),(1010,-1,-1,1006,1006,5,70,-1,0,0,8,1009,7516),(1011,-1,-1,1011,1011,0,51,-1,0,0,8,-1,1012),(1012,-1,-1,1011,1011,0,51,-1,0,0,8,1011,1013),(1013,-1,-1,1011,1011,0,51,-1,0,0,8,1012,1014),(1014,-1,-1,1011,1011,0,51,-1,0,0,8,1013,1015),(1015,-1,-1,1011,1011,0,51,-1,0,0,8,1014,1016),(1016,-1,-1,1011,1011,0,51,-1,0,0,8,1015,-1),(1017,1017,1017,1017,1017,6,59,16531,75,15,15,-1,13726),(1018,1018,1018,1018,1018,2,63,16455,69,1,15,-1,-1),(1019,718,718,718,718,12,65,21746,7,4320,16,720,13454),(1021,-1,-1,1021,1021,5,51,-1,0,0,8,-1,1022),(1022,-1,-1,1021,1021,5,55,-1,0,0,8,1021,1023),(1023,-1,-1,1021,1021,5,60,-1,0,0,8,1022,1024),(1024,-1,-1,1021,1021,5,65,-1,0,0,8,1023,1025),(1025,-1,-1,1021,1021,5,70,-1,0,0,8,1024,6521),(1026,-1,-1,1026,1026,3,66,-1,0,0,8,-1,1027),(1027,-1,-1,1026,1026,3,67,-1,0,0,8,1026,1028),(1028,-1,-1,1026,1026,3,68,-1,0,0,8,1027,1029),(1029,-1,-1,1026,1026,3,69,-1,0,0,8,1028,1030),(1030,-1,-1,1026,1026,3,70,-1,0,0,8,1029,1389),(1031,-1,-1,65,661,3,66,-1,0,0,8,675,1032),(1032,-1,-1,65,661,3,67,-1,0,0,8,1031,1033),(1033,-1,-1,65,661,3,68,-1,0,0,8,1032,1034),(1034,-1,-1,65,661,3,69,-1,0,0,8,1033,1035),(1035,-1,-1,65,661,3,70,-1,0,0,8,1034,4693),(1036,-1,-1,683,683,5,66,-1,0,0,8,685,1037),(1037,-1,-1,683,683,5,68,-1,0,0,8,1036,1038),(1038,-1,-1,683,683,5,70,-1,0,0,8,1037,5301),(1041,-1,-1,1041,1041,3,67,-1,0,0,8,-1,1042),(1042,-1,-1,1041,1041,6,68,-1,0,0,8,1041,1043),(1043,-1,-1,1041,1041,9,69,-1,0,0,8,1042,4707),(1044,-1,-1,1044,1044,3,67,-1,0,0,8,-1,1045),(1045,-1,-1,1044,1044,6,68,-1,0,0,8,1044,1046),(1046,-1,-1,1044,1044,9,69,-1,0,0,8,1045,4710),(1047,-1,-1,1047,1047,3,67,-1,0,0,8,-1,1048),(1048,-1,-1,1047,1047,6,68,-1,0,0,8,1047,1049),(1049,-1,-1,1047,1047,9,69,-1,0,0,8,1048,4713),(1050,-1,-1,1050,1050,3,67,-1,0,0,8,-1,1051),(1051,-1,-1,1050,1050,6,68,-1,0,0,8,1050,1052),(1052,-1,-1,1050,1050,9,69,-1,0,0,8,1051,4716),(1053,-1,-1,119,119,3,66,-1,0,0,8,442,1054),(1054,-1,-1,119,119,3,68,-1,0,0,8,1053,1055),(1055,-1,-1,119,119,3,70,-1,0,0,8,1054,4722),(1056,-1,-1,1056,1056,5,71,-1,0,0,12,-1,1057),(1057,-1,-1,1056,1056,5,72,-1,0,0,12,1056,1058),(1058,-1,-1,1056,1056,5,73,-1,0,0,12,1057,1059),(1059,-1,-1,1056,1056,5,74,-1,0,0,12,1058,1060),(1060,-1,-1,1056,1056,5,75,-1,0,0,12,1059,6431),(1061,-1,-1,125,125,5,66,-1,0,0,8,453,1062),(1062,-1,-1,125,125,5,67,-1,0,0,8,1061,1063),(1063,-1,-1,125,125,5,68,-1,0,0,8,1062,1064),(1064,-1,-1,125,125,5,69,-1,0,0,8,1063,1065),(1065,-1,-1,125,125,5,70,-1,0,0,8,1064,1394),(1066,-1,-1,122,122,5,66,-1,0,0,8,458,1067),(1067,-1,-1,122,122,5,67,-1,0,0,8,1066,1068),(1068,-1,-1,122,122,5,68,-1,0,0,8,1067,1069),(1069,-1,-1,122,122,5,69,-1,0,0,8,1068,1070),(1070,-1,-1,122,122,5,70,-1,0,0,8,1069,1399),(1071,-1,-1,1071,1071,3,55,-1,0,0,8,-1,4764),(1072,-1,-1,1072,1072,5,66,-1,0,0,8,-1,1073),(1073,-1,-1,1072,1072,5,67,-1,0,0,8,1072,1074),(1074,-1,-1,1072,1072,5,68,-1,0,0,8,1073,1075),(1075,-1,-1,1072,1072,5,69,-1,0,0,8,1074,1076),(1076,-1,-1,1072,1072,5,70,-1,0,0,8,1075,4744),(1083,-1,-1,77,77,3,66,-1,0,0,8,436,1084),(1084,-1,-1,77,77,6,68,-1,0,0,8,1083,1085),(1085,-1,-1,77,77,9,70,-1,0,0,8,1084,12449),(1086,-1,-1,80,80,3,66,-1,0,0,8,439,1087),(1087,-1,-1,80,80,6,68,-1,0,0,8,1086,1088),(1088,-1,-1,80,80,9,70,-1,0,0,8,1087,4779),(1089,-1,-1,1089,1089,3,59,-1,0,0,8,-1,1090),(1090,-1,-1,1089,1089,6,59,-1,0,0,8,1089,1091),(1091,-1,-1,1089,1089,9,59,-1,0,0,8,1090,-1),(1092,-1,-1,1092,1092,7,67,-1,0,0,8,-1,-1),(1093,-1,-1,1093,1093,3,66,-1,0,0,8,-1,1094),(1094,-1,-1,1093,1093,3,67,-1,0,0,8,1093,1095),(1095,-1,-1,1093,1093,3,68,-1,0,0,8,1094,1096),(1096,-1,-1,1093,1093,3,69,-1,0,0,8,1095,1097),(1097,-1,-1,1093,1093,3,70,-1,0,0,8,1096,-1),(1099,-1,-1,767,767,3,67,-1,0,0,8,769,1100),(1100,-1,-1,767,767,6,68,-1,0,0,8,1099,1101),(1101,-1,-1,767,767,9,69,-1,0,0,8,1100,12423),(1102,592,592,592,592,3,66,5825,2,18,8,706,1103),(1103,592,592,592,592,3,67,5826,2,18,8,1102,1104),(1104,592,592,592,592,3,68,5827,2,18,8,1103,1105),(1105,592,592,592,592,3,69,5828,2,18,8,1104,1106),(1106,592,592,592,592,3,70,5829,2,18,8,1105,4975),(1107,-1,-1,1107,1107,3,66,-1,0,0,8,-1,1108),(1108,-1,-1,1107,1107,6,68,-1,0,0,8,1107,1109),(1109,-1,-1,1107,1107,9,70,-1,0,0,8,1108,5286),(1110,1110,1110,1110,1110,3,68,5830,3,2160,8,-1,1111),(1111,1110,1110,1110,1110,6,69,5831,3,2160,8,1110,1112),(1112,1110,1110,1110,1110,9,70,5832,3,2160,8,1111,6400),(1113,-1,-1,997,997,5,75,-1,0,0,16,999,1114),(1114,-1,-1,997,997,5,80,-1,0,0,16,1113,1115),(1115,-1,-1,997,997,5,85,-1,0,0,16,1114,-1),(1116,1116,1116,1116,1116,3,68,5837,4,2160,8,-1,1117),(1117,1116,1116,1116,1116,6,69,5838,4,2160,8,1116,1118),(1118,1116,1116,1116,1116,9,70,5839,4,2160,8,1117,4980),(1119,1119,1119,1119,1119,3,68,5841,8,900,8,-1,1120),(1120,1119,1119,1119,1119,6,69,5842,8,900,8,1119,1121),(1121,1119,1119,1119,1119,9,70,5843,8,900,8,1120,4964),(1122,-1,-1,1122,1122,7,67,-1,0,0,8,-1,-1),(1123,291,291,291,291,5,66,5854,5,900,8,291,1124),(1124,291,291,291,291,5,68,5855,5,900,8,1123,1125),(1125,291,291,291,291,5,70,5856,5,900,8,1124,4969),(1126,1126,1126,1126,1126,3,67,5845,2,2160,8,-1,1127),(1127,1126,1126,1126,1126,6,68,5846,2,2160,8,1126,1128),(1128,1126,1126,1126,1126,9,69,5847,2,2160,8,1127,5513),(1129,-1,-1,1129,1129,5,67,-1,0,0,8,-1,1130),(1130,-1,-1,1129,1129,3,69,-1,0,0,8,1129,-1),(1131,-1,-1,1131,1131,3,59,-1,0,0,3,-1,1132),(1132,-1,-1,1131,1131,6,59,-1,0,0,3,1131,1133),(1133,-1,-1,1131,1131,9,59,-1,0,0,3,1132,11082),(1134,-1,-1,1134,1134,3,61,-1,0,0,4,-1,1135),(1135,-1,-1,1134,1134,4,63,-1,0,0,4,1134,1136),(1136,-1,-1,1134,1134,5,65,-1,0,0,4,1135,1158),(1137,-1,-1,1137,1137,3,59,-1,0,0,3,-1,1138),(1138,-1,-1,1137,1137,6,59,-1,0,0,3,1137,1139),(1139,-1,-1,1137,1137,9,59,-1,0,0,3,1138,-1),(1140,-1,-1,1140,1140,3,61,-1,0,0,4,-1,1141),(1141,-1,-1,1140,1140,3,63,-1,0,0,4,1140,1142),(1142,-1,-1,1140,1140,3,65,-1,0,0,4,1141,-1),(1146,1146,1146,1146,1146,3,59,6040,3,1500,3,-1,1147),(1147,1146,1146,1146,1146,6,59,6041,3,1200,3,1146,1148),(1148,1146,1146,1146,1146,9,59,6042,3,900,3,1147,-1),(1149,1149,-1,1149,1149,12,65,5853,5,1320,7,-1,-1),(1150,1150,1150,1150,1150,3,65,5848,2,2160,7,-1,1151),(1151,1150,1150,1150,1150,6,65,5849,2,2160,7,1150,1152),(1152,1150,1150,1150,1150,9,65,5850,2,2160,7,1151,-1),(1155,-1,-1,1155,1155,3,65,-1,0,0,7,-1,1156),(1156,-1,-1,1155,1155,6,65,-1,0,0,7,1155,1157),(1157,-1,-1,1155,1155,9,65,-1,0,0,7,1156,-1),(1158,-1,-1,1134,1134,4,66,-1,0,0,8,1136,1159),(1159,-1,-1,1134,1134,4,67,-1,0,0,8,1158,1160),(1160,-1,-1,1134,1134,4,68,-1,0,0,8,1159,1161),(1161,-1,-1,1134,1134,4,69,-1,0,0,8,1160,1162),(1162,-1,-1,1134,1134,4,70,-1,0,0,8,1161,4790),(1163,-1,-1,255,255,5,67,-1,0,0,8,544,1164),(1164,-1,-1,255,255,5,68,-1,0,0,8,1163,1165),(1165,-1,-1,255,255,5,69,-1,0,0,8,1164,4795),(1166,-1,-1,1143,1143,3,65,-1,0,0,15,-1,1167),(1167,-1,-1,1143,1143,6,65,-1,0,0,15,1166,1168),(1168,-1,-1,1143,1143,9,65,-1,0,0,15,1167,6911),(1172,-1,-1,631,631,5,67,-1,0,0,8,633,1173),(1173,-1,-1,631,631,5,68,-1,0,0,8,1172,1174),(1174,-1,-1,631,631,5,69,-1,0,0,8,1173,4798),(1178,1178,1178,1178,1178,3,68,5857,4,900,8,-1,1179),(1179,1178,1178,1178,1178,6,69,5858,4,900,8,1178,1180),(1180,1178,1178,1178,1178,9,70,5859,4,900,8,1179,5779),(1181,-1,-1,1181,1181,3,66,-1,0,0,8,-1,1182),(1182,-1,-1,1181,1181,3,67,-1,0,0,8,1181,1183),(1183,-1,-1,1181,1181,3,68,-1,0,0,8,1182,1184),(1184,-1,-1,1181,1181,3,69,-1,0,0,8,1183,1185),(1185,-1,-1,1181,1181,3,70,-1,0,0,8,1184,-1),(1186,-1,-1,1186,1186,3,66,-1,0,0,8,-1,1187),(1187,-1,-1,1186,1186,6,68,-1,0,0,8,1186,1188),(1188,-1,-1,1186,1186,9,70,-1,0,0,8,1187,4776),(1189,459,459,459,459,3,66,5860,8,180,8,461,1190),(1190,459,459,459,459,6,68,5861,8,180,8,1189,1191),(1191,459,459,459,459,9,70,5862,8,180,8,1190,5062),(1192,1192,1192,1192,1192,5,67,5863,12,1320,8,-1,1193),(1193,1192,1192,1192,1192,5,68,5864,12,1320,8,1192,1194),(1194,1192,1192,1192,1192,5,69,5865,12,1320,8,1193,5076),(1195,1195,1195,1195,1195,12,70,5866,13,2160,8,-1,5079),(1196,-1,-1,1196,1196,2,81,-1,0,0,15,-1,1197),(1197,-1,-1,1196,1196,2,81,-1,0,0,15,1196,1198),(1198,-1,-1,1196,1196,2,81,-1,0,0,15,1197,1199),(1199,-1,-1,1196,1196,2,81,-1,0,0,15,1198,1200),(1200,-1,-1,1196,1196,2,81,-1,0,0,15,1199,10743),(1203,131,131,131,131,5,67,5869,4,900,8,532,1204),(1204,131,131,131,131,5,68,5870,4,900,8,1203,1205),(1205,131,131,131,131,5,69,5988,4,900,8,1204,5070),(1206,749,749,749,749,5,66,5871,11,1800,8,753,1207),(1207,749,749,749,749,5,68,5872,11,1800,8,1206,1208),(1208,749,749,749,749,5,70,5873,11,1800,8,1207,17298),(1209,1209,-1,1209,1209,12,70,5912,14,4320,8,-1,-1),(1210,-1,-1,1210,1210,3,66,-1,0,0,8,-1,1211),(1211,-1,-1,1210,1210,6,68,-1,0,0,8,1210,1212),(1212,-1,-1,1210,1210,9,70,-1,0,0,8,1211,1483),(1213,-1,-1,1210,1213,3,66,-1,0,0,8,-1,1214),(1214,-1,-1,1210,1213,6,68,-1,0,0,8,1213,1215),(1215,-1,-1,1210,1213,9,70,-1,0,0,8,1214,4755),(1216,-1,-1,83,83,3,81,-1,0,0,16,-1,1217),(1217,-1,-1,83,83,6,81,-1,0,0,16,1216,1218),(1218,-1,-1,83,83,9,81,-1,0,0,16,1217,15422),(1219,-1,-1,1435,1435,10,71,-1,0,0,16,-1,1220),(1220,-1,-1,1435,1435,11,71,-1,0,0,16,1219,1221),(1221,-1,-1,1435,1435,12,71,-1,0,0,16,1220,1648),(1222,757,-1,757,1222,5,66,5877,6,1800,8,761,1223),(1223,757,-1,757,1222,5,68,5878,6,1800,8,1222,1224),(1224,757,-1,757,1222,5,70,5879,6,1800,8,1223,5051),(1225,548,548,548,548,5,67,5881,5,900,8,550,1226),(1226,548,548,548,548,5,68,5882,5,900,8,1225,1227),(1227,548,548,548,548,5,69,5883,5,900,8,1226,5054),(1228,1228,1228,1228,1228,9,70,5880,9,600,8,-1,-1),(1229,1229,1229,1229,1229,7,66,6094,10,600,8,-1,-1),(1230,-1,-1,1230,1230,1,51,-1,0,0,8,-1,1231),(1231,-1,-1,1230,1230,2,53,-1,0,0,8,1230,1232),(1232,-1,-1,1230,1230,3,55,-1,0,0,8,1231,5000),(1233,1233,-1,1233,1233,3,68,5887,7,2160,8,-1,1234),(1234,1233,-1,1233,1233,6,69,5888,7,2160,8,1233,1235),(1235,1233,-1,1233,1233,9,70,5889,7,2160,8,1234,-1),(1239,1239,1239,1239,1239,12,70,5903,6,600,8,-1,5868),(1242,1242,1242,1242,1242,3,67,5906,9,1320,8,-1,1243),(1243,1242,1242,1242,1242,6,68,5907,9,1320,8,1242,1244),(1244,1242,1242,1242,1242,9,69,5908,9,1320,8,1243,5857),(1245,1245,1245,1245,1245,3,66,5909,8,2160,8,-1,1246),(1246,1245,1245,1245,1245,6,68,5910,8,2160,8,1245,1247),(1247,1245,1245,1245,1245,9,70,5911,8,2160,8,1246,15459),(1248,616,616,616,616,3,68,6226,7,900,8,618,1249),(1249,616,616,616,616,6,69,6227,7,900,8,1248,1250),(1250,616,616,616,616,9,70,6228,7,900,8,1249,6254),(1251,1251,1251,1251,1251,9,70,5915,9,1320,8,-1,-1),(1252,1252,1252,1252,1252,9,68,5913,9,1320,8,-1,-1),(1253,1253,1253,1253,1253,9,67,5916,16,1320,8,-1,-1),(1254,1254,1254,1254,1254,9,69,5914,16,1320,8,-1,-1),(1255,1255,1255,1255,1255,9,70,5918,4,1080,8,-1,-1),(1265,-1,-1,820,820,5,66,-1,0,0,8,822,1266),(1266,-1,-1,820,820,5,68,-1,0,0,8,1265,1267),(1267,-1,-1,820,820,5,70,-1,0,0,8,1266,4813),(1268,-1,-1,807,807,5,66,-1,0,0,8,809,1269),(1269,-1,-1,807,807,5,68,-1,0,0,8,1268,1270),(1270,-1,-1,807,807,5,70,-1,0,0,8,1269,5922),(1272,209,209,209,1272,5,66,5919,12,5,8,-1,6378),(1274,1274,1274,1274,1274,3,68,5921,9,540,8,-1,1275),(1275,1274,1274,1274,1274,6,69,5922,9,540,8,1274,1276),(1276,1274,1274,1274,1274,9,70,5923,9,540,8,1275,4864),(1277,188,188,188,188,9,68,5924,2,30,8,188,5044),(1278,534,534,534,534,5,67,5927,4,2160,8,717,1279),(1279,534,534,534,534,5,68,5928,4,2160,8,1278,1280),(1280,534,534,534,534,5,69,5929,4,2160,8,1279,5041),(1284,-1,-1,1284,1284,3,66,-1,0,0,8,-1,1285),(1285,-1,-1,1284,1284,6,68,-1,0,0,8,1284,1286),(1286,-1,-1,1284,1284,9,70,-1,0,0,8,1285,5035),(1287,-1,-1,1287,1287,3,67,-1,0,0,8,-1,1288),(1288,-1,-1,1287,1287,6,68,-1,0,0,8,1287,1289),(1289,-1,-1,1287,1287,9,69,-1,0,0,8,1288,5516),(1290,-1,-1,864,864,3,66,-1,0,0,8,866,1291),(1291,-1,-1,864,864,6,68,-1,0,0,8,1290,1292),(1292,-1,-1,864,864,9,70,-1,0,0,8,1291,4983),(1293,545,545,545,545,3,68,6079,3,900,8,547,1294),(1294,545,545,545,545,6,69,6080,3,900,8,1293,1295),(1295,545,545,545,545,9,70,6081,3,900,8,1294,4997),(1296,-1,-1,1296,1296,3,66,-1,0,0,8,-1,1297),(1297,-1,-1,1296,1296,3,67,-1,0,0,8,1296,1298),(1298,-1,-1,1296,1296,3,68,-1,0,0,8,1297,1299),(1299,-1,-1,1296,1296,3,69,-1,0,0,8,1298,1300),(1300,-1,-1,1296,1296,3,70,-1,0,0,8,1299,-1),(1301,-1,-1,846,846,3,66,-1,0,0,8,848,1302),(1302,-1,-1,846,846,6,68,-1,0,0,8,1301,1303),(1303,-1,-1,846,846,9,70,-1,0,0,8,1302,4948),(1304,-1,-1,1304,1304,3,66,-1,0,0,8,-1,1305),(1305,-1,-1,1304,1304,6,68,-1,0,0,8,1304,1306),(1306,-1,-1,1304,1304,9,70,-1,0,0,8,1305,6029),(1307,-1,-1,1307,1307,5,66,-1,0,0,8,-1,1308),(1308,-1,-1,1307,1307,5,67,-1,0,0,8,1307,1309),(1309,-1,-1,1307,1307,5,68,-1,0,0,8,1308,1310),(1310,-1,-1,1307,1307,5,69,-1,0,0,8,1309,1311),(1311,-1,-1,1307,1307,5,70,-1,0,0,8,1310,6660),(1313,-1,-1,1313,1313,3,68,-1,0,0,8,-1,1314),(1314,-1,-1,1313,1313,6,69,-1,0,0,8,1313,1315),(1315,-1,-1,1313,1313,9,70,-1,0,0,8,1314,5029),(1316,-1,-1,210,210,5,67,-1,0,0,8,212,1317),(1317,-1,-1,210,210,5,68,-1,0,0,8,1316,1318),(1318,-1,-1,210,210,5,69,-1,0,0,8,1317,6072),(1319,-1,-1,634,634,5,67,-1,0,0,8,845,1320),(1320,-1,-1,634,634,5,68,-1,0,0,8,1319,1321),(1321,-1,-1,634,634,5,69,-1,0,0,8,1320,5032),(1323,1323,1323,1323,1323,12,70,5932,7,2160,8,-1,-1),(1324,970,970,970,970,5,66,6030,6,1800,8,974,1325),(1325,970,970,970,970,5,68,6031,6,1800,8,1324,1326),(1326,970,970,970,970,5,70,6032,6,1800,8,1325,17311),(1327,1327,1327,1327,1327,5,67,5933,10,900,8,-1,1328),(1328,1327,1327,1327,1327,5,68,5934,10,900,8,1327,1329),(1329,1327,1327,1327,1327,5,69,5935,10,900,8,1328,5314),(1330,912,912,912,912,3,66,5936,4,3600,8,914,1331),(1331,912,912,912,912,6,68,5937,4,3600,8,1330,1332),(1332,912,912,912,912,9,70,5938,4,3600,8,1331,7119),(1334,1334,1334,1334,1334,3,66,5943,11,4320,8,-1,1335),(1335,1334,1334,1334,1334,6,68,5944,11,4320,8,1334,1336),(1336,1334,1334,1334,1334,9,70,5945,11,4320,8,1335,6152),(1337,1337,1337,1337,1337,5,67,5946,13,4320,8,-1,1338),(1338,1337,1337,1337,1337,5,68,5947,13,4320,8,1337,1339),(1339,1337,1337,1337,1337,5,69,5948,13,4320,8,1338,6158),(1340,921,921,921,921,12,69,5950,8,60,8,921,5280),(1341,922,922,922,922,12,68,5951,8,60,8,922,5281),(1342,923,923,923,923,12,67,5952,8,60,8,923,5282),(1343,1343,1343,1343,1343,9,69,5953,9,300,8,-1,-1),(1344,155,155,155,155,12,70,5949,8,60,8,533,5279),(1345,1345,1345,1345,1345,5,67,6132,6,900,8,-1,1346),(1346,1345,1345,1345,1345,5,68,6133,6,900,8,1345,1347),(1347,1345,1345,1345,1345,5,69,6134,6,900,8,1346,5003),(1348,1348,1348,1348,1348,3,68,6090,0,3600,8,-1,1349),(1349,1348,1348,1348,1348,6,69,6091,0,3600,8,1348,1350),(1350,1348,1348,1348,1348,9,70,6092,0,3600,8,1349,5770),(1351,1351,1351,1351,1351,5,67,5939,5,30,8,-1,6133),(1352,1352,1352,1352,1352,3,67,6067,3,60,8,-1,1353),(1353,1352,1352,1352,1352,6,68,6068,3,60,8,1352,1354),(1354,1352,1352,1352,1352,9,69,6069,3,60,8,1353,6313),(1355,1355,1355,1355,1355,3,68,6070,3,60,8,-1,1356),(1356,1355,1355,1355,1355,6,69,6071,3,60,8,1355,1357),(1357,1355,1355,1355,1355,9,70,6072,3,60,8,1356,5240),(1358,1358,1358,1358,1358,3,66,6073,3,60,8,-1,1359),(1359,1358,1358,1358,1358,6,67,6074,3,60,8,1358,1360),(1360,1358,1358,1358,1358,9,68,6075,3,60,8,1359,6307),(1361,-1,-1,1361,1361,0,65,-1,0,0,3,-1,-1),(1362,-1,-1,1362,1362,0,65,-1,0,0,3,-1,-1),(1363,-1,-1,1363,1363,0,68,-1,0,0,3,-1,-1),(1364,-1,-1,1364,1364,0,68,-1,0,0,3,-1,-1),(1365,-1,-1,1365,1365,0,68,-1,0,0,3,-1,-1),(1366,-1,-1,1366,1366,0,65,-1,0,0,3,-1,-1),(1367,-1,-1,1367,1367,0,65,-1,0,0,3,-1,-1),(1368,-1,-1,1368,1368,0,68,-1,0,0,3,-1,-1),(1369,-1,-1,1369,1369,0,68,-1,0,0,3,-1,-1),(1370,-1,-1,1370,1370,0,68,-1,0,0,3,-1,-1),(1371,1371,1371,1371,1371,0,1,6880,23,72000,0,-1,-1),(1372,1372,1372,1372,1372,0,1,6881,24,72000,0,-1,-1),(1373,1373,1373,1373,1373,0,1,6882,25,72000,0,-1,-1),(1374,1374,1374,1374,1374,0,1,6883,26,590400,0,-1,-1),(1375,1375,1375,1375,1375,0,1,6884,27,72000,0,-1,-1),(1376,1376,1376,1376,1376,0,1,6885,28,244800,0,-1,-1),(1377,1377,1377,1377,1377,0,1,6886,29,14400,0,-1,-1),(1378,-1,-1,1378,1378,0,1,-1,0,0,10,-1,1379),(1379,-1,-1,1379,1379,0,1,-1,0,0,10,1378,1380),(1380,-1,-1,1380,1380,0,1,-1,0,0,10,1379,1381),(1382,-1,-1,1382,1382,0,1,-1,0,0,10,1381,-1),(1383,1383,1383,1383,1383,3,59,8048,6,300,3,-1,1384),(1384,1383,1383,1383,1383,6,59,8049,6,300,3,1383,1385),(1385,1383,1383,1383,1383,9,59,8050,6,300,3,1384,1386),(1386,1383,1383,1383,1383,9,65,8052,6,300,4,1385,1387),(1387,1383,1383,1383,1383,9,70,8053,6,300,10,1386,5084),(1388,-1,-1,1388,1388,9,70,-1,0,0,10,-1,-1),(1389,-1,-1,1026,1026,5,70,-1,0,0,10,1030,1390),(1390,-1,-1,1026,1026,5,70,-1,0,0,10,1389,1391),(1391,-1,-1,1026,1026,5,70,-1,0,0,10,1390,1392),(1392,-1,-1,1026,1026,5,70,-1,0,0,10,1391,1393),(1393,-1,-1,1026,1026,5,70,-1,0,0,10,1392,4683),(1394,-1,-1,125,125,5,70,-1,0,0,10,1065,1395),(1395,-1,-1,125,125,5,70,-1,0,0,10,1394,1396),(1396,-1,-1,125,125,5,70,-1,0,0,10,1395,1397),(1397,-1,-1,125,125,5,70,-1,0,0,10,1396,1398),(1398,-1,-1,125,125,5,70,-1,0,0,10,1397,5519),(1399,-1,-1,122,122,5,70,-1,0,0,10,1070,1400),(1400,-1,-1,122,122,5,70,-1,0,0,10,1399,1401),(1401,-1,-1,122,122,5,70,-1,0,0,10,1400,1402),(1402,-1,-1,122,122,5,70,-1,0,0,10,1401,1403),(1403,-1,-1,122,122,5,70,-1,0,0,10,1402,5524),(1404,1404,1404,1404,1404,5,66,8054,15,2160,10,-1,1405),(1405,1404,1404,1404,1404,5,67,8055,15,2160,10,1404,1406),(1406,1404,1404,1404,1404,5,68,8056,15,2160,10,1405,1407),(1407,1404,1404,1404,1404,5,69,8057,15,2160,10,1406,1408),(1408,1404,1404,1404,1404,5,70,8058,15,2160,10,1407,12880),(1409,1409,1409,1409,1409,5,66,8054,15,2160,10,-1,1410),(1410,1409,1409,1409,1409,5,67,8055,15,2160,10,1409,1411),(1411,1409,1409,1409,1409,5,68,8056,15,2160,10,1410,1412),(1412,1409,1409,1409,1409,5,69,8057,15,2160,10,1411,1413),(1413,1409,1409,1409,1409,5,70,8058,15,2160,10,1412,-1),(1414,-1,-1,1414,1414,5,66,-1,0,0,10,-1,1415),(1415,-1,-1,1414,1414,5,67,-1,0,0,10,1414,1416),(1416,-1,-1,1414,1414,5,68,-1,0,0,10,1415,1417),(1417,-1,-1,1414,1414,5,69,-1,0,0,10,1416,1418),(1418,-1,-1,1414,1414,5,70,-1,0,0,10,1417,12874),(1419,1419,1419,1419,1419,9,74,16441,52,300,15,-1,-1),(1420,-1,-1,1420,1420,3,66,-1,0,0,10,-1,1421),(1421,-1,-1,1420,1420,3,67,-1,0,0,10,1420,1422),(1422,-1,-1,1420,1420,3,68,-1,0,0,10,1421,1423),(1423,-1,-1,1420,1420,3,69,-1,0,0,10,1422,1424),(1424,-1,-1,1420,1420,3,70,-1,0,0,10,1423,-1),(1425,1425,1425,1425,1425,5,70,8060,2,2160,10,-1,1426),(1426,1425,1425,1425,1425,5,70,8061,2,2160,10,1425,1427),(1427,1425,1425,1425,1425,5,70,8063,2,2160,10,1426,1428),(1428,1425,1425,1425,1425,5,70,8066,2,2160,10,1427,1429),(1429,1425,1425,1425,1425,5,70,8070,2,2160,10,1428,5759),(1430,-1,-1,795,795,3,70,-1,0,0,10,799,1431),(1431,-1,-1,795,795,6,70,-1,0,0,10,1430,1432),(1432,-1,-1,795,795,9,70,-1,0,0,10,1431,4897),(1435,-1,-1,1435,1435,3,66,-1,0,0,10,-1,1436),(1436,-1,-1,1435,1435,6,68,-1,0,0,10,1435,1437),(1437,-1,-1,1435,1435,9,70,-1,0,0,10,1436,4773),(1440,517,517,517,517,5,66,8109,12,600,10,519,1441),(1441,517,517,517,517,5,67,8110,12,600,10,1440,1442),(1442,517,517,517,517,5,68,8111,12,600,10,1441,1443),(1443,517,517,517,517,5,69,8112,12,600,10,1442,1444),(1444,517,517,517,517,5,70,8113,12,600,10,1443,7296),(1453,-1,-1,1453,1453,5,66,-1,0,0,10,-1,1454),(1454,-1,-1,1453,1453,5,67,-1,0,0,10,1453,1455),(1455,-1,-1,1453,1453,5,68,-1,0,0,10,1454,1456),(1456,-1,-1,1453,1453,5,69,-1,0,0,10,1455,1457),(1457,-1,-1,1453,1453,5,70,-1,0,0,10,1456,-1),(1458,1458,1458,1458,1458,12,70,8124,6,4320,10,-1,-1),(1459,1459,1459,1459,1459,7,70,8125,11,1800,10,-1,1460),(1460,1459,1459,1459,1459,7,70,8126,11,1800,10,1459,1461),(1461,1459,1459,1459,1459,7,70,8127,11,1800,10,1460,5080),(1462,1462,1462,1462,1462,3,59,8133,5,300,3,-1,1463),(1463,1462,1462,1462,1462,6,59,8134,5,300,3,1462,1464),(1464,1462,1462,1462,1462,9,59,8135,5,300,3,1463,1465),(1465,1462,1462,1462,1462,9,65,8137,5,300,4,1464,1466),(1466,1462,1462,1462,1462,9,70,8138,5,300,10,1465,4900),(1467,-1,-1,729,729,3,70,-1,0,0,10,733,1468),(1468,-1,-1,729,729,6,70,-1,0,0,10,1467,1469),(1469,-1,-1,729,729,9,70,-1,0,0,10,1468,4960),(1471,-1,-1,1471,1471,5,70,-1,0,0,10,-1,1472),(1472,-1,-1,1471,1471,5,70,-1,0,0,10,1471,1473),(1473,-1,-1,1471,1471,5,70,-1,0,0,10,1472,1474),(1474,-1,-1,1471,1471,5,70,-1,0,0,10,1473,1475),(1475,-1,-1,1471,1471,5,70,-1,0,0,10,1474,6442),(1477,1477,1477,1477,1477,9,70,8149,3,4320,10,-1,-1),(1478,1478,-1,1478,1478,3,66,8406,0,1,10,-1,1479),(1479,1478,-1,1478,1478,6,68,8407,0,1,10,1478,1480),(1480,1478,-1,1478,1478,9,70,8408,0,1,10,1479,6161),(1483,-1,-1,1210,1210,7,70,-1,0,0,10,1212,1484),(1484,-1,-1,1210,1210,7,70,-1,0,0,10,1483,1485),(1485,-1,-1,1210,1210,7,70,-1,0,0,10,1484,4752),(1486,-1,-1,1486,1486,5,66,-1,0,0,10,-1,1487),(1487,-1,-1,1486,1486,5,67,-1,0,0,10,1486,1488),(1488,-1,-1,1486,1486,5,68,-1,0,0,10,1487,1489),(1489,-1,-1,1486,1486,5,69,-1,0,0,10,1488,1490),(1490,-1,-1,1486,1486,5,70,-1,0,0,10,1489,5529),(1491,746,746,746,746,3,70,8156,10,2160,10,748,1492),(1492,746,746,746,746,6,70,8157,10,2160,10,1491,1493),(1493,746,746,746,746,9,70,8158,10,2160,10,1492,5800),(1494,1494,1494,1494,1494,12,70,8170,2,7,10,-1,-1),(1495,1495,1495,1495,1495,3,70,8190,30,900,10,-1,1496),(1496,1495,1495,1495,1495,6,70,8191,30,900,10,1495,1497),(1497,1495,1495,1495,1495,9,70,8192,30,900,10,1496,5311),(1498,1498,1498,1498,1498,3,70,8193,12,1320,10,-1,1499),(1499,1498,1498,1498,1498,6,70,8194,12,1320,10,1498,1500),(1500,1498,1498,1498,1498,9,70,8195,12,1320,10,1499,5058),(1501,1501,1501,1501,1501,3,70,8196,10,4320,10,-1,1502),(1502,1501,1501,1501,1501,6,70,8197,10,4320,10,1501,1503),(1503,1501,1501,1501,1501,9,70,8198,10,4320,10,1502,1558),(1504,-1,-1,1504,1504,5,70,-1,0,0,10,-1,1505),(1505,-1,-1,1504,1504,5,70,-1,0,0,10,1504,1506),(1506,-1,-1,1504,1504,5,70,-1,0,0,10,1505,5880),(1507,520,520,520,520,3,70,8201,6,540,10,522,1508),(1508,520,520,520,520,6,70,8202,6,540,10,1507,1509),(1509,520,520,520,520,9,70,8203,6,540,10,1508,5883),(1510,1510,-1,1510,1510,12,70,8205,13,2160,10,-1,7202),(1511,-1,-1,1511,1511,5,70,-1,0,0,10,-1,1512),(1512,-1,-1,1511,1511,5,70,-1,0,0,10,1511,1513),(1513,-1,-1,1511,1511,5,70,-1,0,0,10,1512,5950),(1514,-1,-1,1514,1514,7,70,-1,0,0,10,-1,1515),(1515,-1,-1,1514,1514,7,70,-1,0,0,10,1514,1516),(1516,-1,-1,1514,1514,7,70,-1,0,0,10,1515,13404),(1519,153,153,153,153,9,70,8216,3,2160,10,153,5068),(1520,1520,1520,1520,1520,3,70,8218,11,900,10,-1,1521),(1521,1520,1520,1520,1520,6,70,8219,11,900,10,1520,1522),(1522,1520,1520,1520,1520,9,70,8220,11,900,10,1521,6449),(1523,1523,1523,1523,1523,12,70,8221,7,7,10,-1,-1),(1524,-1,-1,190,190,7,70,-1,0,0,10,192,1526),(1525,-1,-1,190,190,7,70,-1,0,0,10,1526,5038),(1526,-1,-1,190,190,7,70,-1,0,0,10,1524,1525),(1527,1527,1527,1527,1527,12,70,8223,3,7,10,-1,-1),(1528,-1,-1,1528,4819,5,66,-1,0,0,10,-1,1529),(1529,-1,-1,1528,4819,5,67,-1,0,0,10,1528,1530),(1530,-1,-1,1528,4819,5,68,-1,0,0,10,1529,1531),(1531,-1,-1,1528,4819,5,69,-1,0,0,10,1530,1532),(1532,-1,-1,1528,4819,5,70,-1,0,0,10,1531,4819),(1533,-1,-1,602,602,3,70,-1,0,0,10,604,1534),(1534,-1,-1,602,602,6,70,-1,0,0,10,1533,1535),(1535,-1,-1,602,602,9,70,-1,0,0,10,1534,4758),(1536,-1,-1,599,599,3,70,-1,0,0,10,601,1537),(1537,-1,-1,599,599,6,70,-1,0,0,10,1536,1538),(1538,-1,-1,599,599,9,70,-1,0,0,10,1537,5534),(1539,-1,-1,878,878,7,70,-1,0,0,10,880,1540),(1540,-1,-1,878,878,7,70,-1,0,0,10,1539,1541),(1541,-1,-1,878,878,7,70,-1,0,0,10,1540,4957),(1542,1542,-1,1542,1542,3,60,8240,0,1,10,-1,-1),(1543,-1,-1,1543,1543,5,70,-1,0,0,10,-1,1544),(1544,-1,-1,1543,1543,5,70,-1,0,0,10,1543,1545),(1545,-1,-1,1543,1543,5,70,-1,0,0,10,1544,4951),(1546,-1,-1,1546,1546,5,70,-1,0,0,10,-1,1547),(1547,-1,-1,1546,1546,5,70,-1,0,0,10,1546,1548),(1548,-1,-1,1546,1546,5,70,-1,0,0,10,1547,4829),(1549,-1,-1,1549,1549,3,66,-1,0,0,10,-1,1550),(1550,-1,-1,1549,1549,6,68,-1,0,0,10,1549,1551),(1551,-1,-1,1549,1549,9,70,-1,0,0,10,1550,-1),(1552,-1,-1,1552,1552,3,66,-1,0,0,10,-1,1553),(1553,-1,-1,1552,1552,6,68,-1,0,0,10,1552,1554),(1554,-1,-1,1552,1552,9,70,-1,0,0,10,1553,-1),(1555,-1,-1,1555,1555,5,70,-1,0,0,10,-1,1556),(1556,-1,-1,1555,1555,5,70,-1,0,0,10,1555,1557),(1557,-1,-1,1555,1555,5,70,-1,0,0,10,1556,12727),(1558,1501,1501,1501,1501,6,75,16444,10,4320,15,1503,1559),(1559,1501,1501,1501,1501,6,80,16445,10,4320,15,1558,1560),(1560,1501,1501,1501,1501,6,85,16446,10,4320,15,1559,13244),(1563,-1,-1,556,556,5,66,-1,0,0,10,560,1564),(1564,-1,-1,556,556,5,67,-1,0,0,10,1563,1565),(1565,-1,-1,556,556,5,68,-1,0,0,10,1564,1566),(1566,-1,-1,556,556,5,69,-1,0,0,10,1565,1567),(1567,-1,-1,556,556,5,70,-1,0,0,10,1566,17004),(1569,1569,1569,1569,1569,3,70,8256,5,1800,10,-1,1570),(1570,1569,1569,1569,1569,6,70,8257,5,1800,10,1569,1571),(1571,1569,1569,1569,1569,9,70,8258,5,1800,10,1570,5713),(1572,-1,-1,1572,1572,5,66,-1,0,0,10,-1,1573),(1573,-1,-1,1572,1572,5,67,-1,0,0,10,1572,1574),(1574,-1,-1,1572,1572,5,68,-1,0,0,10,1573,1575),(1575,-1,-1,1572,1572,5,69,-1,0,0,10,1574,1576),(1576,-1,-1,1572,1572,5,70,-1,0,0,10,1575,10554),(1577,-1,-1,1577,1577,3,66,-1,0,0,10,-1,1578),(1578,-1,-1,1577,1577,6,68,-1,0,0,10,1577,1579),(1579,-1,-1,1577,1577,9,70,-1,0,0,10,1578,5886),(1583,-1,-1,1583,1583,5,70,-1,0,0,10,-1,1584),(1584,-1,-1,1583,1583,5,70,-1,0,0,10,1583,1585),(1585,-1,-1,1583,1583,5,70,-1,0,0,10,1584,1586),(1586,-1,-1,1583,1583,5,70,-1,0,0,10,1585,1587),(1587,-1,-1,1583,1583,5,70,-1,0,0,10,1586,-1),(1588,-1,-1,1587,1587,3,66,-1,0,0,10,-1,1589),(1589,-1,-1,1587,1587,6,68,-1,0,0,10,1588,1590),(1590,-1,-1,1587,1587,9,70,-1,0,0,10,1589,-1),(1591,-1,-1,1586,1586,12,70,-1,0,0,10,-1,-1),(1592,-1,-1,1592,1592,5,66,-1,0,0,10,-1,1593),(1593,-1,-1,1592,1592,5,67,-1,0,0,10,1592,1594),(1594,-1,-1,1592,1592,5,68,-1,0,0,10,1593,1595),(1595,-1,-1,1592,1592,5,69,-1,0,0,10,1594,1596),(1596,-1,-1,1592,1592,5,70,-1,0,0,10,1595,4725),(1597,1597,1597,1597,1597,9,70,8271,6,10,10,-1,6606),(1598,1598,-1,1598,1598,3,70,8272,6,900,10,-1,1599),(1599,1598,-1,1598,1598,6,70,8273,6,900,10,1598,1600),(1600,1598,-1,1598,1598,9,70,8274,6,900,10,1599,4972),(1601,-1,-1,644,644,5,61,-1,0,0,10,644,1602),(1602,-1,-1,644,644,5,63,-1,0,0,10,1601,1603),(1603,-1,-1,644,644,5,65,-1,0,0,10,1602,4986),(1604,-1,-1,1604,1604,5,60,-1,0,0,10,-1,1605),(1605,-1,-1,1604,1604,5,61,-1,0,0,10,1604,1606),(1606,-1,-1,1604,1604,5,62,-1,0,0,10,1605,5290),(1607,289,289,289,289,9,70,8278,3,300,10,289,5742),(1608,-1,-1,1608,1608,3,66,-1,0,0,10,-1,1609),(1609,-1,-1,1608,1608,6,68,-1,0,0,10,1608,1610),(1610,-1,-1,1608,1608,9,70,-1,0,0,10,1609,4989),(1611,-1,-1,1417,1417,3,66,-1,0,0,10,-1,1612),(1612,-1,-1,1417,1417,3,67,-1,0,0,10,1611,1613),(1613,-1,-1,1417,1417,3,68,-1,0,0,10,1612,1614),(1614,-1,-1,1417,1417,3,69,-1,0,0,10,1613,1615),(1615,-1,-1,1417,1417,3,70,-1,0,0,10,1614,-1),(1616,-1,-1,1616,1616,5,66,-1,0,0,10,-1,1617),(1617,-1,-1,1616,1616,5,67,-1,0,0,10,1616,1618),(1618,-1,-1,1616,1616,5,68,-1,0,0,10,1617,1619),(1619,-1,-1,1616,1616,5,69,-1,0,0,10,1618,1620),(1620,-1,-1,1616,1616,5,70,-1,0,0,10,1619,4992),(1621,-1,-1,564,564,7,70,-1,0,0,10,566,1622),(1622,-1,-1,564,564,7,70,-1,0,0,10,1621,1623),(1623,-1,-1,564,564,7,70,-1,0,0,10,1622,-1),(1624,-1,-1,561,561,7,70,-1,0,0,10,563,1625),(1625,-1,-1,561,561,7,70,-1,0,0,10,1624,1626),(1626,-1,-1,561,561,7,70,-1,0,0,10,1625,-1),(1627,-1,-1,1627,1627,3,66,-1,0,0,10,-1,1628),(1628,-1,-1,1627,1627,6,68,-1,0,0,10,1627,1629),(1629,-1,-1,1627,1627,9,70,-1,0,0,10,1628,-1),(1630,1474,1474,1474,1474,3,70,8146,14,300,10,-1,1631),(1631,1474,1474,1474,1474,6,70,8147,14,300,10,1630,1632),(1632,1474,1474,1474,1474,9,70,8148,14,300,10,1631,-1),(1633,-1,-1,551,551,5,66,-1,0,0,10,555,1634),(1634,-1,-1,551,551,5,67,-1,0,0,10,1633,1635),(1635,-1,-1,551,551,5,68,-1,0,0,10,1634,1636),(1636,-1,-1,551,551,5,69,-1,0,0,10,1635,1637),(1637,-1,-1,551,551,5,70,-1,0,0,10,1636,6905),(1638,1638,1638,1638,1638,5,59,8450,7,4320,3,-1,-1),(1639,1639,1639,1639,1639,9,65,8451,7,4320,4,-1,-1),(1640,1640,1640,1640,1640,12,70,8452,7,4320,10,-1,-1),(1641,-1,-1,1641,1641,15,70,-1,0,0,3,-1,-1),(1642,-1,-1,1642,1642,15,70,-1,0,0,3,-1,-1),(1643,1643,1643,1643,1643,0,59,8975,0,1,11,-1,-1),(1644,1644,1644,1644,1644,0,59,8900,0,1,11,-1,-1),(1645,1645,1645,1645,1645,9,70,8977,0,1,3,-1,-1),(1646,1646,1646,1646,1646,9,70,8978,0,1,3,-1,-1),(1647,1647,1647,1647,1647,0,68,8771,21,900,3,-1,-1),(1648,-1,-1,1435,4773,9,71,-1,0,0,16,1221,1649),(1649,-1,-1,1435,4773,9,76,-1,0,0,16,1648,1650),(1650,-1,-1,1435,4773,9,81,-1,0,0,16,1649,13091),(1651,-1,-1,8210,8210,5,85,-1,0,0,16,8214,1652),(1652,-1,-1,8210,8210,5,85,-1,0,0,16,1651,1653),(1653,-1,-1,8210,8210,5,85,-1,0,0,16,1652,1654),(1654,-1,-1,8210,8210,5,85,-1,0,0,16,1653,1655),(1655,-1,-1,8210,8210,5,85,-1,0,0,16,1654,13149),(1656,-1,-1,8204,8204,4,85,-1,0,0,16,8206,1657),(1657,-1,-1,8204,8204,4,85,-1,0,0,16,1656,-1),(1659,-1,-1,8207,8207,4,85,-1,0,0,16,8209,1660),(1660,-1,-1,8207,8207,4,85,-1,0,0,16,1659,-1),(1662,-1,-1,1662,1662,3,65,-1,0,0,17,-1,1663),(1663,-1,-1,1662,1662,3,66,-1,0,0,17,1662,1664),(1664,-1,-1,1662,1662,3,67,-1,0,0,17,1663,1665),(1665,-1,-1,1662,1662,3,68,-1,0,0,17,1664,1666),(1666,-1,-1,1662,1662,3,69,-1,0,0,17,1665,-1),(1667,1667,1667,1667,1667,9,85,23602,0,1,16,-1,-1),(2400,-1,-1,2400,2400,9,81,0,0,0,17,-1,2401),(2401,-1,-1,2400,2400,12,83,0,0,0,17,2400,2402),(2402,-1,-1,2400,2400,15,85,0,0,0,17,2401,15344),(3676,3676,3676,3676,3676,9,85,23606,67,30,16,-1,-1),(4665,4665,4665,4665,4665,0,1,9177,19,4320,0,-1,-1),(4666,-1,-1,4844,4844,5,81,-1,0,0,16,-1,4667),(4667,-1,-1,4844,4844,5,82,-1,0,0,16,4666,4668),(4668,-1,-1,4844,4844,5,83,-1,0,0,16,4667,4669),(4669,-1,-1,4844,4844,5,84,-1,0,0,16,4668,4670),(4670,-1,-1,4844,4844,5,85,-1,0,0,16,4669,-1),(4672,-1,-1,4672,4672,3,59,-1,0,0,8,-1,4673),(4673,-1,-1,4672,4672,6,59,-1,0,0,8,4672,4674),(4674,-1,-1,4672,4672,9,59,-1,0,0,8,4673,-1),(4675,-1,-1,4675,4675,3,59,-1,0,0,3,-1,4676),(4676,-1,-1,4675,4675,6,59,-1,0,0,3,4675,4677),(4677,-1,-1,4675,4675,9,59,-1,0,0,3,4676,-1),(4678,-1,-1,418,418,5,71,-1,0,0,12,1005,4679),(4679,-1,-1,418,418,5,72,-1,0,0,12,4678,4680),(4680,-1,-1,418,418,5,73,-1,0,0,12,4679,4681),(4681,-1,-1,418,418,5,74,-1,0,0,12,4680,4682),(4682,-1,-1,418,418,5,75,-1,0,0,12,4681,7547),(4683,-1,-1,1026,1026,5,71,-1,0,0,12,1393,4684),(4684,-1,-1,1026,1026,5,72,-1,0,0,12,4683,4685),(4685,-1,-1,1026,1026,5,73,-1,0,0,12,4684,4686),(4686,-1,-1,1026,1026,5,74,-1,0,0,12,4685,4687),(4687,-1,-1,1026,1026,5,75,-1,0,0,12,4686,6523),(4688,-1,-1,4688,4688,3,71,-1,0,0,12,-1,4689),(4689,-1,-1,4688,4688,3,72,-1,0,0,12,4688,4690),(4690,-1,-1,4688,4688,3,73,-1,0,0,12,4689,4691),(4691,-1,-1,4688,4688,3,74,-1,0,0,12,4690,4692),(4692,-1,-1,4688,4688,3,75,-1,0,0,12,4691,-1),(4693,-1,-1,65,661,3,71,-1,0,0,12,1035,4694),(4694,-1,-1,65,661,3,72,-1,0,0,12,4693,4695),(4695,-1,-1,65,661,3,73,-1,0,0,12,4694,4696),(4696,-1,-1,65,661,3,74,-1,0,0,12,4695,4697),(4697,-1,-1,65,661,3,75,-1,0,0,12,4696,6390),(4698,-1,-1,4698,4698,5,51,-1,0,0,12,-1,6545),(4699,-1,-1,4699,4699,5,51,-1,0,0,12,-1,6540),(4700,1037,1037,1037,1037,0,1,7619,33,72000,0,-1,-1),(4702,4702,4702,4702,4702,3,71,9475,31,600,12,-1,-1),(4704,4704,4704,4704,4704,4,71,9477,31,600,12,-1,-1),(4705,4705,4705,4705,4705,3,71,9478,31,600,12,-1,-1),(4706,4706,4706,4706,4706,3,71,9479,31,600,12,-1,-1),(4707,-1,-1,1041,1041,6,71,-1,0,0,12,1043,4708),(4708,-1,-1,1041,1041,6,73,-1,0,0,12,4707,4709),(4709,-1,-1,1041,1041,6,75,-1,0,0,12,4708,5542),(4710,-1,-1,1044,1044,6,71,-1,0,0,12,1046,4711),(4711,-1,-1,1044,1044,6,73,-1,0,0,12,4710,4712),(4712,-1,-1,1044,1044,6,75,-1,0,0,12,4711,5545),(4713,-1,-1,1047,1047,6,71,-1,0,0,12,1049,4714),(4714,-1,-1,1047,1047,6,73,-1,0,0,12,4713,4715),(4715,-1,-1,1047,1047,6,75,-1,0,0,12,4714,5548),(4716,-1,-1,1050,1050,6,71,-1,0,0,12,1052,4717),(4717,-1,-1,1050,1050,6,73,-1,0,0,12,4716,4718),(4718,-1,-1,1050,1050,6,75,-1,0,0,12,4717,5551),(4722,-1,-1,119,119,3,71,-1,0,0,12,1055,4723),(4723,-1,-1,119,119,3,73,-1,0,0,12,4722,4724),(4724,-1,-1,119,119,3,75,-1,0,0,12,4723,5554),(4725,-1,-1,1592,1592,5,71,-1,0,0,12,1596,4726),(4726,-1,-1,1592,1592,5,72,-1,0,0,12,4725,4727),(4727,-1,-1,1592,1592,5,73,-1,0,0,12,4726,4728),(4728,-1,-1,1592,1592,5,74,-1,0,0,12,4727,4729),(4729,-1,-1,1592,1592,5,75,-1,0,0,12,4728,5557),(4733,-1,-1,625,625,3,71,-1,0,0,12,627,4734),(4734,-1,-1,625,625,3,73,-1,0,0,12,4733,4735),(4735,-1,-1,625,625,3,75,-1,0,0,12,4734,7641),(4739,-1,-1,4739,4739,3,71,-1,0,0,12,-1,4740),(4740,-1,-1,4739,4739,6,73,-1,0,0,12,4739,4741),(4741,-1,-1,4739,4739,9,75,-1,0,0,12,4740,5562),(4742,4742,4742,4742,4742,9,71,11024,12,600,12,-1,5565),(4744,-1,-1,1072,1072,5,71,-1,0,0,12,1076,4745),(4745,-1,-1,1072,1072,5,72,-1,0,0,12,4744,4746),(4746,-1,-1,1072,1072,5,73,-1,0,0,12,4745,4747),(4747,-1,-1,1072,1072,5,74,-1,0,0,12,4746,4748),(4748,-1,-1,1072,1072,5,75,-1,0,0,12,4747,5566),(4749,-1,-1,637,637,6,71,-1,0,0,12,772,4750),(4750,-1,-1,637,637,6,73,-1,0,0,12,4749,4751),(4751,-1,-1,637,637,6,75,-1,0,0,12,4750,5571),(4752,-1,-1,1210,1210,7,71,-1,0,0,12,1485,4753),(4753,-1,-1,1210,1210,7,73,-1,0,0,12,4752,4754),(4754,-1,-1,1210,1210,7,75,-1,0,0,12,4753,5574),(4755,-1,-1,1210,1213,6,71,-1,0,0,12,1215,4756),(4756,-1,-1,1210,1213,6,73,-1,0,0,12,4755,4757),(4757,-1,-1,1210,1213,6,75,-1,0,0,12,4756,5577),(4758,-1,-1,602,602,6,71,-1,0,0,12,1535,4759),(4759,-1,-1,602,602,6,73,-1,0,0,12,4758,4760),(4760,-1,-1,602,602,6,75,-1,0,0,12,4759,5580),(4761,-1,-1,4761,4761,7,71,-1,0,0,12,-1,4762),(4762,-1,-1,4761,4761,7,73,-1,0,0,12,4761,4763),(4763,-1,-1,4761,4761,7,75,-1,0,0,12,4762,6500),(4764,-1,-1,1071,1071,6,75,-1,0,0,14,1071,7553),(4767,-1,-1,98,98,4,71,-1,0,0,12,100,4768),(4768,-1,-1,98,98,4,73,-1,0,0,12,4767,4769),(4769,-1,-1,98,98,4,75,-1,0,0,12,4768,5586),(4773,-1,-1,1435,4773,9,71,-1,0,0,12,1437,6517),(4776,-1,-1,1186,1186,6,71,-1,0,0,12,1188,4777),(4777,-1,-1,1186,1186,6,73,-1,0,0,12,4776,4778),(4778,-1,-1,1186,1186,6,75,-1,0,0,12,4777,5589),(4779,-1,-1,80,80,6,71,-1,0,0,12,1088,4780),(4780,-1,-1,80,80,6,73,-1,0,0,12,4779,4781),(4781,-1,-1,80,80,6,75,-1,0,0,12,4780,5592),(4790,-1,-1,1134,1134,5,71,-1,0,0,12,1162,4791),(4791,-1,-1,1134,1134,5,72,-1,0,0,12,4790,4792),(4792,-1,-1,1134,1134,5,73,-1,0,0,12,4791,4793),(4793,-1,-1,1134,1134,5,74,-1,0,0,12,4792,4794),(4794,-1,-1,1134,1134,5,75,-1,0,0,12,4793,4804),(4795,-1,-1,255,255,5,71,-1,0,0,12,1165,4796),(4796,-1,-1,255,255,5,73,-1,0,0,12,4795,4797),(4797,-1,-1,255,255,5,75,-1,0,0,12,4796,5595),(4798,-1,-1,631,631,5,71,-1,0,0,12,1174,4799),(4799,-1,-1,631,631,5,73,-1,0,0,12,4798,4800),(4800,-1,-1,631,631,5,75,-1,0,0,12,4799,-1),(4801,-1,-1,4801,4801,6,74,-1,0,0,14,-1,4802),(4802,-1,-1,4801,4801,6,76,-1,0,0,14,4801,4803),(4803,-1,-1,4801,4801,6,78,-1,0,0,14,4802,7160),(4804,-1,-1,1134,1134,5,76,-1,0,0,15,4794,4805),(4805,-1,-1,1134,1134,5,77,-1,0,0,15,4804,4806),(4806,-1,-1,1134,1134,5,78,-1,0,0,15,4805,4807),(4807,-1,-1,1134,1134,5,79,-1,0,0,15,4806,4808),(4808,-1,-1,1134,1134,5,80,-1,0,0,15,4807,10311),(4809,-1,-1,4809,4809,5,81,-1,0,0,15,-1,4810),(4810,-1,-1,4809,4809,5,83,-1,0,0,15,4809,4811),(4811,-1,-1,4809,4809,5,85,-1,0,0,15,4810,10316),(4813,-1,-1,820,820,5,71,-1,0,0,12,1267,4814),(4814,-1,-1,820,820,5,73,-1,0,0,12,4813,4815),(4815,-1,-1,820,820,5,75,-1,0,0,12,4814,5917),(4819,-1,-1,1528,4819,5,71,-1,0,0,12,1532,4820),(4820,-1,-1,1528,4819,5,72,-1,0,0,12,4819,4821),(4821,-1,-1,1528,4819,5,73,-1,0,0,12,4820,4822),(4822,-1,-1,1528,4819,5,74,-1,0,0,12,4821,4823),(4823,-1,-1,1528,4819,5,75,-1,0,0,12,4822,15188),(4824,-1,-1,810,810,5,71,-1,0,0,12,814,4825),(4825,-1,-1,810,810,5,72,-1,0,0,12,4824,4826),(4826,-1,-1,810,810,5,73,-1,0,0,12,4825,4827),(4827,-1,-1,810,810,5,74,-1,0,0,12,4826,4828),(4828,-1,-1,810,810,5,75,-1,0,0,12,4827,15426),(4829,-1,-1,1546,1546,5,71,-1,0,0,12,1548,4830),(4830,-1,-1,1546,1546,5,72,-1,0,0,12,4829,4831),(4831,-1,-1,1546,1546,5,73,-1,0,0,12,4830,6441),(4836,4836,4836,4836,4836,5,71,11033,5,30,12,-1,-1),(4844,-1,-1,4844,4844,5,71,-1,0,0,12,-1,4845),(4845,-1,-1,4844,4844,5,72,-1,0,0,12,4844,4846),(4846,-1,-1,4844,4844,5,73,-1,0,0,12,4845,4847),(4847,-1,-1,4844,4844,5,74,-1,0,0,12,4846,4848),(4848,-1,-1,4844,4844,5,75,-1,0,0,12,4847,7122),(4849,4849,4849,4849,4849,9,71,11041,7,1800,12,-1,6134),(4854,4854,4854,4854,4854,3,71,11046,8,600,12,-1,4855),(4855,4854,4854,4854,4854,6,73,11047,8,600,12,4854,4856),(4856,4854,4854,4854,4854,9,75,11048,8,600,12,4855,5764),(4857,4857,4857,4857,4857,3,71,11049,7,600,12,-1,4858),(4858,4857,4857,4857,4857,6,73,11050,7,600,12,4857,4859),(4859,4857,4857,4857,4857,9,75,11051,7,600,12,4858,5767),(4860,4860,4860,4860,4860,9,75,11052,13,60,12,-1,5606),(4861,-1,-1,4861,4861,6,71,-1,0,0,12,-1,4862),(4862,-1,-1,4861,4861,6,73,-1,0,0,12,4861,4863),(4863,-1,-1,4861,4861,6,75,-1,0,0,12,4862,5954),(4864,1274,1274,1274,1274,6,73,11053,9,540,12,1276,4865),(4865,1274,1274,1274,1274,6,74,11054,9,540,12,4864,4866),(4866,1274,1274,1274,1274,6,75,11055,9,540,12,4865,5947),(4887,-1,-1,4887,4887,6,71,-1,0,0,12,-1,4888),(4888,-1,-1,4887,4887,6,73,-1,0,0,12,4887,4889),(4889,-1,-1,4887,4887,6,75,-1,0,0,12,4888,-1),(4890,4890,-1,4890,4890,9,75,11056,3,8640,12,-1,5869),(4894,4894,4894,4894,4894,6,73,11057,7,2160,12,-1,4895),(4895,4894,4894,4894,4894,6,74,11058,7,2160,12,4894,4896),(4896,4894,4894,4894,4894,6,75,11059,7,2160,12,4895,6352),(4897,-1,-1,795,795,6,71,-1,0,0,12,1432,4898),(4898,-1,-1,795,795,6,73,-1,0,0,12,4897,4899),(4899,-1,-1,795,795,6,75,-1,0,0,12,4898,5889),(4900,1462,1462,1462,1462,6,71,11061,5,300,12,1466,4901),(4901,1462,1462,1462,1462,6,73,11062,5,300,12,4900,4902),(4902,1462,1462,1462,1462,6,75,11063,5,300,12,4901,14739),(4903,4903,4903,4903,4903,9,71,11064,9,1320,12,-1,5892),(4906,4906,4906,4906,4906,9,71,11065,9,1320,12,-1,5893),(4909,4909,4909,4909,4909,9,71,11066,16,1320,12,-1,5894),(4912,4912,4912,4912,4912,9,71,11067,16,1320,12,-1,5895),(4915,4915,4915,4915,4915,9,71,11068,7,4320,12,-1,4916),(4916,4915,4915,4915,4915,9,73,11069,7,4320,12,4915,4917),(4917,4915,4915,4915,4915,9,75,11070,7,4320,12,4916,5607),(4921,-1,-1,480,480,2,71,-1,0,0,12,482,4922),(4922,-1,-1,480,480,2,73,-1,0,0,12,4921,4923),(4923,-1,-1,480,480,2,75,-1,0,0,12,4922,-1),(4924,-1,-1,4924,4924,5,75,-1,0,0,12,-1,4925),(4925,-1,-1,4924,4924,5,75,-1,0,0,12,4924,4926),(4926,-1,-1,4924,4924,5,75,-1,0,0,12,4925,5944),(4927,4927,4927,4927,4927,9,71,11076,14,600,12,-1,7209),(4931,4931,4931,4931,4931,6,71,11083,4,600,12,-1,4932),(4932,4931,4931,4931,4931,6,73,11084,4,600,12,4931,4933),(4933,4931,4931,4931,4931,6,75,11085,4,600,12,4932,6054),(4934,4934,4934,4934,4934,7,71,11086,13,300,12,-1,7295),(4935,4935,4935,4935,4935,7,71,11087,14,300,12,-1,7294),(4938,4938,4938,4938,4938,9,75,11092,35,1800,12,-1,5610),(4943,4943,4943,4943,4943,7,75,11098,17,1800,12,-1,-1),(4944,4944,-1,4944,4944,3,71,11103,0,1,12,-1,4945),(4945,4944,-1,4944,4944,6,73,11104,0,1,12,4944,4946),(4946,4944,-1,4944,4944,9,75,11105,0,1,12,4945,6155),(4948,-1,-1,846,846,3,71,-1,0,0,12,1303,4949),(4949,-1,-1,846,846,6,73,-1,0,0,12,4948,4950),(4950,-1,-1,846,846,9,75,-1,0,0,12,4949,6035),(4951,-1,-1,1543,1543,5,71,-1,0,0,12,1545,4952),(4952,-1,-1,1543,1543,5,73,-1,0,0,12,4951,4953),(4953,-1,-1,1543,1543,5,75,-1,0,0,12,4952,6042),(4957,-1,-1,878,878,7,71,-1,0,0,12,1541,4958),(4958,-1,-1,878,878,7,73,-1,0,0,12,4957,4959),(4959,-1,-1,878,878,7,75,-1,0,0,12,4958,6331),(4960,-1,-1,729,729,6,71,-1,0,0,12,1469,4961),(4961,-1,-1,729,729,6,73,-1,0,0,12,4960,4962),(4962,-1,-1,729,729,6,75,-1,0,0,12,4961,5738),(4963,723,723,723,723,9,71,11205,6,30,12,723,5737),(4964,1119,1119,1119,1119,6,73,11206,8,900,12,1121,4965),(4965,1119,1119,1119,1119,6,74,11207,8,900,12,4964,4966),(4966,1119,1119,1119,1119,6,75,11208,8,900,12,4965,5734),(4969,291,291,291,291,5,71,11212,5,900,12,1125,4970),(4970,291,291,291,291,5,73,11213,5,900,12,4969,4971),(4971,291,291,291,291,5,75,11214,5,900,12,4970,5743),(4972,1598,-1,1598,1598,6,71,11215,6,900,12,1600,4973),(4973,1598,-1,1598,1598,6,73,11216,6,900,12,4972,4974),(4974,1598,-1,1598,1598,6,75,11217,6,900,12,4973,5710),(4975,592,592,592,592,3,71,11218,2,18,12,1106,4976),(4976,592,592,592,592,3,72,11219,2,18,12,4975,4977),(4977,592,592,592,592,3,73,11220,2,18,12,4976,4978),(4978,592,592,592,592,3,74,11221,2,18,12,4977,4979),(4979,592,592,592,592,3,75,11222,2,18,12,4978,5702),(4980,1116,1116,1116,1116,6,73,11223,4,2160,12,1118,4981),(4981,1116,1116,1116,1116,6,74,11224,4,2160,12,4980,4982),(4982,1116,1116,1116,1116,6,75,11225,4,2160,12,4981,5699),(4983,-1,-1,864,864,6,71,-1,0,0,12,1292,4984),(4984,-1,-1,864,864,6,73,-1,0,0,12,4983,4985),(4985,-1,-1,864,864,6,75,-1,0,0,12,4984,6011),(4986,-1,-1,644,644,5,67,-1,0,0,12,1603,4987),(4987,-1,-1,644,644,5,69,-1,0,0,12,4986,4988),(4988,-1,-1,644,644,5,71,-1,0,0,12,4987,6017),(4989,-1,-1,1608,1608,6,71,-1,0,0,12,1610,4990),(4990,-1,-1,1608,1608,6,73,-1,0,0,12,4989,4991),(4991,-1,-1,1608,1608,6,75,-1,0,0,12,4990,7378),(4992,-1,-1,1616,1616,5,71,-1,0,0,12,1620,4993),(4993,-1,-1,1616,1616,5,72,-1,0,0,12,4992,4994),(4994,-1,-1,1616,1616,5,73,-1,0,0,12,4993,4995),(4995,-1,-1,1616,1616,5,74,-1,0,0,12,4994,4996),(4996,-1,-1,1616,1616,5,75,-1,0,0,12,4995,6003),(4997,545,545,545,545,6,73,11226,3,900,12,1295,4998),(4998,545,545,545,545,6,74,11227,3,900,12,4997,4999),(4999,545,545,545,545,6,75,11228,3,900,12,4998,6000),(5000,-1,-1,1230,1230,2,71,-1,0,0,12,1232,5001),(5001,-1,-1,1230,1230,2,73,-1,0,0,12,5000,5002),(5002,-1,-1,1230,1230,2,75,-1,0,0,12,5001,-1),(5003,1345,1345,1345,1345,5,73,11229,6,900,12,1347,5004),(5004,1345,1345,1345,1345,5,74,11230,6,900,12,5003,5005),(5005,1345,1345,1345,1345,5,75,11231,6,900,12,5004,6008),(5006,5006,5006,5006,5006,0,0,27673,96,72000,0,-1,-1),(5007,5007,5007,5007,5007,3,71,11233,8,2160,12,-1,5008),(5008,5007,5007,5007,5007,6,73,11234,8,2160,12,5007,5009),(5009,5007,5007,5007,5007,9,75,11235,8,2160,12,5008,6425),(5010,-1,-1,1007,1007,8,81,-1,0,0,16,-1,5011),(5011,-1,-1,1007,1007,10,83,-1,0,0,16,5010,5012),(5012,-1,-1,1007,1007,12,85,-1,0,0,16,5011,15317),(5013,-1,-1,1284,1284,6,83,-1,0,0,16,5037,5014),(5014,-1,-1,1284,1284,6,85,-1,0,0,16,5013,-1),(5015,5015,5015,5015,5015,5,75,11241,9,900,12,-1,5741),(5017,5017,5017,5017,5017,3,71,11243,8,600,12,-1,5018),(5018,5017,5017,5017,5017,6,73,11244,8,600,12,5017,5019),(5019,5017,5017,5017,5017,9,75,11245,8,600,12,5018,7454),(5020,5020,5020,5020,5020,9,75,11246,9,300,12,-1,5716),(5021,5021,5021,5021,5021,9,71,11341,7,60,12,-1,10868),(5022,5022,5022,5022,5022,3,71,11247,5,600,12,-1,5023),(5023,5022,5022,5022,5022,6,73,23986,5,600,12,5022,5024),(5024,5022,5022,5022,5022,9,75,23987,5,600,12,5023,6038),(5025,5025,5025,5025,5025,3,71,11251,6,180,12,-1,5026),(5026,5025,5025,5025,5025,6,73,11252,6,180,12,5025,5027),(5027,5025,5025,5025,5025,9,75,11253,6,180,12,5026,-1),(5028,5028,-1,5028,5028,9,75,11254,4,900,12,-1,6041),(5029,-1,-1,1313,1313,6,71,-1,0,0,8,1315,5030),(5030,-1,-1,1313,1313,6,73,-1,0,0,8,5029,5031),(5031,-1,-1,1313,1313,6,75,-1,0,0,8,5030,6066),(5032,-1,-1,634,634,5,72,-1,0,0,12,1321,5033),(5033,-1,-1,634,634,5,73,-1,0,0,12,5032,5034),(5034,-1,-1,634,634,5,74,-1,0,0,12,5033,5611),(5035,-1,-1,1284,1284,6,71,-1,0,0,12,1286,5036),(5036,-1,-1,1284,1284,6,73,-1,0,0,12,5035,5037),(5037,-1,-1,1284,1284,6,75,-1,0,0,12,5036,5013),(5038,-1,-1,190,190,7,71,-1,0,0,12,1525,5039),(5039,-1,-1,190,190,7,73,-1,0,0,12,5038,5040),(5040,-1,-1,190,190,7,75,-1,0,0,12,5039,15141),(5041,534,534,534,534,5,72,11255,4,2160,12,1280,5042),(5042,534,534,534,534,5,73,11256,4,2160,12,5041,5043),(5043,534,534,534,534,5,74,11257,4,2160,12,5042,5969),(5044,188,188,188,188,9,73,11258,2,30,12,1277,7339),(5045,-1,-1,1057,1057,9,85,-1,0,0,16,-1,-1),(5051,757,-1,757,757,5,71,11262,6,1800,12,1224,5052),(5052,757,-1,757,757,5,73,11263,6,1800,12,5051,5053),(5053,757,-1,757,757,5,75,11264,6,1800,12,5052,5822),(5054,548,548,548,548,5,72,11265,5,900,12,1227,5055),(5055,548,548,548,548,5,73,11266,5,900,12,5054,5056),(5056,548,548,548,548,5,74,11267,5,900,12,5055,5829),(5058,1498,1498,1498,1498,6,71,11269,12,1320,12,1500,5059),(5059,1498,1498,1498,1498,6,73,11270,12,1320,12,5058,5060),(5060,1498,1498,1498,1498,6,75,11271,12,1320,12,5059,5819),(5061,-1,-1,567,567,5,72,-1,0,0,12,567,5825),(5062,459,459,459,459,6,71,11272,8,180,12,1191,5063),(5063,459,459,459,459,6,73,11273,8,180,12,5062,5064),(5064,459,459,459,459,6,75,11274,8,180,12,5063,-1),(5068,153,153,153,153,9,75,11279,3,2160,12,1519,6101),(5069,146,146,146,146,5,72,11281,2,180,12,146,6102),(5070,131,131,131,131,5,72,11282,4,900,12,1205,5071),(5071,131,131,131,131,5,73,11283,4,900,12,5070,5072),(5072,131,131,131,131,5,74,11284,4,900,12,5071,5791),(5076,1192,1192,1192,1192,5,72,11288,12,1320,12,1194,5077),(5077,1192,1192,1192,1192,5,73,11289,12,1320,12,5076,5078),(5078,1192,1192,1192,1192,5,74,11290,12,1320,12,5077,5794),(5079,1195,1195,1195,1195,9,75,11291,13,2160,12,1195,5790),(5080,1459,1459,1459,1459,5,71,11293,11,1800,12,1461,5081),(5081,1459,1459,1459,1459,5,73,11294,11,1800,12,5080,5082),(5082,1459,1459,1459,1459,5,75,11295,11,1800,12,5081,5803),(5084,1383,1383,1383,1383,12,75,11296,6,300,12,1387,5789),(5085,-1,-1,5085,5085,3,71,-1,0,0,12,-1,5086),(5086,-1,-1,5085,5085,6,73,-1,0,0,12,5085,5087),(5087,-1,-1,5085,5085,9,75,-1,0,0,12,5086,6406),(5095,5095,5095,5095,5095,3,71,11307,10,900,12,-1,5096),(5096,5095,5095,5095,5095,6,73,11308,10,900,12,5095,5097),(5097,5095,5095,5095,5095,9,75,11309,10,900,12,5096,5975),(5098,5098,5098,5098,5098,9,75,11310,2,30,12,-1,-1),(5105,5105,5105,5105,5105,9,75,11317,11,600,12,-1,5832),(5109,5109,5109,5109,5109,9,75,11321,0,1,12,-1,6448),(5118,-1,-1,5083,5083,3,71,-1,0,0,12,-1,5119),(5119,-1,-1,5083,5083,3,73,-1,0,0,12,5118,5120),(5120,-1,-1,5083,5083,3,75,-1,0,0,12,5119,5797),(5127,-1,-1,5127,5127,3,71,-1,0,0,12,-1,5128),(5128,-1,-1,5127,5127,3,73,-1,0,0,12,5127,5129),(5129,-1,-1,5127,5127,3,75,-1,0,0,12,5128,-1),(5130,860,860,860,860,6,71,5860,5,180,12,862,5131),(5131,860,860,860,860,6,73,5861,5,180,12,5130,5132),(5132,860,860,860,860,6,75,5862,5,180,12,5131,-1),(5133,-1,-1,267,267,6,71,-1,0,0,12,925,5134),(5134,-1,-1,267,267,6,73,-1,0,0,12,5133,5135),(5135,-1,-1,267,267,6,75,-1,0,0,12,5134,5617),(5136,-1,-1,4688,4688,3,71,-1,0,0,12,-1,5137),(5137,-1,-1,4688,4688,3,72,-1,0,0,12,5136,5138),(5138,-1,-1,4688,4688,3,73,-1,0,0,12,5137,5139),(5139,-1,-1,4688,4688,3,74,-1,0,0,12,5138,5140),(5140,-1,-1,4688,4688,3,75,-1,0,0,12,5139,-1),(5141,-1,-1,815,815,5,71,-1,0,0,12,819,5142),(5142,-1,-1,815,815,5,72,-1,0,0,12,5141,5143),(5143,-1,-1,815,815,5,73,-1,0,0,12,5142,5144),(5144,-1,-1,815,815,5,74,-1,0,0,12,5143,5145),(5145,-1,-1,815,815,5,75,-1,0,0,12,5144,5909),(5150,5150,5150,5150,5150,0,1,11112,22,300,3,-1,5151),(5165,5165,5165,5165,5165,0,1,11127,22,300,3,-1,5166),(5180,5180,5180,5180,5180,0,1,11142,22,300,3,-1,5181),(5195,5195,5195,5195,5195,0,1,11157,22,300,3,-1,5196),(5210,5210,5210,5210,5210,0,1,11172,22,300,3,-1,5211),(5225,5225,5225,5225,5225,0,1,11187,22,300,3,-1,5226),(5240,1355,1355,1355,1355,6,71,11611,3,60,12,1357,5241),(5241,1355,1355,1355,1355,6,73,11612,3,60,12,5240,5242),(5242,1355,1355,1355,1355,6,75,11613,3,60,12,5241,5914),(5243,-1,-1,907,907,7,71,-1,0,0,12,911,5244),(5244,-1,-1,907,907,7,72,-1,0,0,12,5243,5245),(5245,-1,-1,907,907,7,73,-1,0,0,12,5244,5246),(5246,-1,-1,907,907,7,74,-1,0,0,12,5245,5247),(5247,-1,-1,907,907,7,75,-1,0,0,12,5246,-1),(5248,-1,-1,5248,5248,3,71,-1,0,0,12,-1,5249),(5249,-1,-1,5248,5248,6,73,-1,0,0,12,5248,5250),(5250,-1,-1,5248,5248,9,75,-1,0,0,12,5249,6014),(5251,5251,5251,5251,5251,5,71,11615,13,900,12,-1,5252),(5252,5251,5251,5251,5251,5,73,11616,13,900,12,5251,5253),(5253,5251,5251,5251,5251,5,75,11617,13,900,12,5252,6092),(5254,-1,-1,724,724,3,71,-1,0,0,12,728,5255),(5255,-1,-1,724,724,3,72,-1,0,0,12,5254,5256),(5256,-1,-1,724,724,3,73,-1,0,0,12,5255,5257),(5257,-1,-1,724,724,3,74,-1,0,0,12,5256,5258),(5258,-1,-1,724,724,3,75,-1,0,0,12,5257,5729),(5259,-1,-1,790,790,3,71,-1,0,0,12,794,5260),(5260,-1,-1,790,790,3,72,-1,0,0,12,5259,5261),(5261,-1,-1,790,790,3,73,-1,0,0,12,5260,5262),(5262,-1,-1,790,790,3,74,-1,0,0,12,5261,5263),(5263,-1,-1,790,790,3,75,-1,0,0,12,5262,5320),(5264,-1,-1,5264,5264,3,71,-1,0,0,12,-1,5265),(5265,-1,-1,5264,5264,3,72,-1,0,0,12,5264,5266),(5266,-1,-1,5264,5264,3,73,-1,0,0,12,5265,5267),(5267,-1,-1,5264,5264,3,74,-1,0,0,12,5266,5268),(5268,-1,-1,5264,5264,3,75,-1,0,0,12,5267,5939),(5269,-1,-1,5269,5269,3,71,-1,0,0,12,-1,-1),(5270,-1,-1,589,589,7,71,-1,0,0,12,894,5271),(5271,-1,-1,589,589,7,73,-1,0,0,12,5270,5272),(5272,-1,-1,589,589,7,75,-1,0,0,12,5271,6063),(5276,-1,-1,5276,5276,3,71,-1,0,0,12,-1,5277),(5277,-1,-1,5276,5276,6,73,-1,0,0,12,5276,5278),(5278,-1,-1,5276,5276,9,75,-1,0,0,12,5277,15238),(5279,155,155,155,155,12,75,11624,8,60,12,1344,5289),(5280,921,921,921,921,9,74,11625,8,60,12,1340,6149),(5281,922,922,922,922,9,73,11626,8,60,12,1341,6150),(5282,923,923,923,923,9,72,11627,8,60,12,1342,6151),(5283,-1,-1,5263,5263,3,71,-1,0,0,12,-1,5284),(5284,-1,-1,5263,5263,6,73,-1,0,0,12,5283,5285),(5285,-1,-1,5263,5263,9,75,-1,0,0,12,5284,5620),(5286,-1,-1,1107,1107,6,71,-1,0,0,12,1109,5287),(5287,-1,-1,1107,1107,6,73,-1,0,0,12,5286,5288),(5288,-1,-1,1107,1107,6,75,-1,0,0,12,5287,6403),(5289,155,155,155,155,12,77,13227,8,60,14,5279,7238),(5290,-1,-1,1604,1604,5,63,-1,0,0,12,1606,5291),(5291,-1,-1,1604,1604,5,64,-1,0,0,12,5290,5292),(5292,-1,-1,1604,1604,5,65,-1,0,0,12,5291,5293),(5293,-1,-1,1604,1604,5,66,-1,0,0,12,5292,5294),(5294,-1,-1,1604,1604,5,67,-1,0,0,12,5293,6032),(5295,-1,-1,5295,5295,3,71,-1,0,0,12,-1,5296),(5296,-1,-1,5295,5295,6,73,-1,0,0,12,5295,5297),(5297,-1,-1,5295,5295,9,75,-1,0,0,12,5296,6531),(5298,5298,5298,5298,5298,3,71,11630,32,1800,12,-1,5299),(5299,5298,5298,5298,5298,6,73,11631,32,1800,12,5298,5300),(5300,5298,5298,5298,5298,9,75,11632,32,1800,12,5299,5707),(5301,-1,-1,683,683,5,71,-1,0,0,12,1038,5302),(5302,-1,-1,683,683,5,72,-1,0,0,12,5301,5303),(5303,-1,-1,683,683,5,73,-1,0,0,12,5302,5304),(5304,-1,-1,683,683,5,74,-1,0,0,12,5303,5305),(5305,-1,-1,683,683,5,75,-1,0,0,12,5304,6080),(5306,-1,-1,658,658,5,71,-1,0,0,12,660,5307),(5307,-1,-1,658,658,5,72,-1,0,0,12,5306,5308),(5308,-1,-1,658,658,5,73,-1,0,0,12,5307,5309),(5309,-1,-1,658,658,5,74,-1,0,0,12,5308,5310),(5310,-1,-1,658,658,5,75,-1,0,0,12,5309,5623),(5311,1495,1495,1495,1495,5,71,11639,30,900,12,1497,5312),(5312,1495,1495,1495,1495,5,73,11640,30,900,12,5311,5313),(5313,1495,1495,1495,1495,5,75,11641,30,900,12,5312,5826),(5314,1327,1327,1327,1327,5,71,11642,10,900,12,1329,5315),(5315,1327,1327,1327,1327,5,73,11643,10,900,12,5314,5316),(5316,1327,1327,1327,1327,5,75,11644,10,900,12,5315,6098),(5317,-1,-1,98,738,4,71,-1,0,0,12,740,5318),(5318,-1,-1,98,738,4,73,-1,0,0,12,5317,5319),(5319,-1,-1,98,738,4,75,-1,0,0,12,5318,5628),(5320,-1,-1,790,790,6,76,-1,0,0,14,5263,5321),(5321,-1,-1,790,790,6,77,-1,0,0,14,5320,5322),(5322,-1,-1,790,790,6,78,-1,0,0,14,5321,5323),(5323,-1,-1,790,790,6,79,-1,0,0,14,5322,5324),(5324,-1,-1,790,790,6,80,-1,0,0,14,5323,7270),(5325,-1,-1,839,839,6,70,-1,0,0,14,843,5326),(5326,-1,-1,839,839,6,70,-1,0,0,14,5325,5327),(5327,-1,-1,839,839,6,70,-1,0,0,14,5326,5328),(5328,-1,-1,839,839,6,70,-1,0,0,14,5327,5329),(5329,-1,-1,839,839,6,70,-1,0,0,14,5328,7210),(5330,1327,1327,1327,1327,12,91,30870,10,900,18,10189,5331),(5333,1520,1520,1520,1520,9,91,30873,11,900,18,12999,5334),(5336,12989,12989,12989,12989,11,91,30876,73,1800,18,12991,5337),(5339,-1,-1,6383,6383,11,91,-1,0,0,18,12803,5340),(5342,6692,6692,6692,6692,9,91,30879,42,600,18,6696,5343),(5347,-1,-1,6375,6375,12,91,-1,0,0,18,10086,5348),(5348,-1,-1,6375,6375,15,93,-1,0,0,18,5347,5349),(5350,12992,12992,12992,12992,12,91,30884,0,1,18,12994,5351),(5353,6706,6706,6706,6706,9,91,30887,44,600,18,10181,5354),(5356,5109,5109,5109,5109,12,92,30890,0,1,18,13016,17323),(5357,528,528,528,528,12,91,30891,5,720,18,13163,5358),(5360,-1,-1,9503,9503,11,91,-1,0,0,18,12794,5361),(5363,5251,5251,5251,5251,15,91,30894,13,900,18,10199,5364),(5366,-1,-1,5002,5002,12,91,-1,34,0,18,-1,5367),(5369,5001,5001,5001,5001,12,91,30900,32,600,18,-1,5370),(5500,-1,-1,852,852,9,78,-1,0,0,14,854,5501),(5501,-1,-1,852,852,10,79,-1,0,0,14,5500,5502),(5502,-1,-1,852,852,12,80,-1,0,0,14,5501,7678),(5513,1126,1126,1126,1126,8,77,12668,2,2160,14,1128,5514),(5514,1126,1126,1126,1126,9,78,12669,2,2160,14,5513,5515),(5515,1126,1126,1126,1126,10,79,12670,2,2160,14,5514,13253),(5516,-1,-1,1287,1287,8,77,-1,0,0,14,1289,5517),(5517,-1,-1,1287,1287,9,78,-1,0,0,14,5516,5518),(5518,-1,-1,1287,1287,10,79,-1,0,0,14,5517,12469),(5519,-1,-1,125,125,6,76,-1,0,0,14,1398,5520),(5520,-1,-1,125,125,7,77,-1,0,0,14,5519,5521),(5521,-1,-1,125,125,8,78,-1,0,0,14,5520,5522),(5522,-1,-1,125,125,9,79,-1,0,0,14,5521,5523),(5523,-1,-1,125,125,10,80,-1,0,0,14,5522,7501),(5524,-1,-1,122,122,6,76,-1,0,0,14,1403,5525),(5525,-1,-1,122,122,7,77,-1,0,0,14,5524,5526),(5526,-1,-1,122,122,8,78,-1,0,0,14,5525,5527),(5527,-1,-1,122,122,9,79,-1,0,0,14,5526,5528),(5528,-1,-1,122,122,10,80,-1,0,0,14,5527,7506),(5529,-1,-1,1486,1486,7,76,-1,0,0,14,1490,5530),(5530,-1,-1,1486,1486,8,77,-1,0,0,14,5529,5531),(5531,-1,-1,1486,1486,9,78,-1,0,0,14,5530,5532),(5532,-1,-1,1486,1486,10,79,-1,0,0,14,5531,5533),(5533,-1,-1,1486,1486,12,80,-1,0,0,14,5532,7554),(5534,-1,-1,599,599,9,78,-1,0,0,14,1538,5535),(5535,-1,-1,599,599,10,79,-1,0,0,14,5534,5536),(5536,-1,-1,599,599,12,80,-1,0,0,14,5535,7559),(5542,-1,-1,1041,1041,7,76,-1,0,0,14,4709,5543),(5543,-1,-1,1041,1041,9,78,-1,0,0,14,5542,5544),(5544,-1,-1,1041,1041,12,80,-1,0,0,14,5543,7562),(5545,-1,-1,1044,1044,7,76,-1,0,0,14,4712,5546),(5546,-1,-1,1044,1044,9,78,-1,0,0,14,5545,5547),(5547,-1,-1,1044,1044,12,80,-1,0,0,14,5546,7650),(5548,-1,-1,1047,1047,7,76,-1,0,0,14,4715,5549),(5549,-1,-1,1047,1047,9,78,-1,0,0,14,5548,5550),(5550,-1,-1,1047,1047,12,80,-1,0,0,14,5549,7653),(5551,-1,-1,1050,1050,7,76,-1,0,0,14,4718,5552),(5552,-1,-1,1050,1050,9,78,-1,0,0,14,5551,5553),(5553,-1,-1,1050,1050,12,80,-1,0,0,14,5552,7656),(5554,-1,-1,119,119,7,76,-1,0,0,14,4724,5555),(5555,-1,-1,119,119,9,78,-1,0,0,14,5554,5556),(5556,-1,-1,119,119,12,80,-1,0,0,14,5555,7565),(5557,-1,-1,1592,1592,7,76,-1,0,0,14,4729,5558),(5558,-1,-1,1592,1592,8,77,-1,0,0,14,5557,5559),(5559,-1,-1,1592,1592,9,78,-1,0,0,14,5558,5560),(5560,-1,-1,1592,1592,10,79,-1,0,0,14,5559,5561),(5561,-1,-1,1592,1592,12,80,-1,0,0,14,5560,7568),(5562,-1,-1,4739,4739,7,76,-1,0,0,14,4741,5563),(5563,-1,-1,4739,4739,9,78,-1,0,0,14,5562,5564),(5564,-1,-1,4739,4739,12,80,-1,0,0,14,5563,7573),(5565,4742,4742,4742,4742,7,76,12671,12,600,14,4742,-1),(5566,-1,-1,1072,1072,7,76,-1,0,0,14,4748,5567),(5567,-1,-1,1072,1072,8,77,-1,0,0,14,5566,5568),(5568,-1,-1,1072,1072,9,78,-1,0,0,14,5567,5569),(5569,-1,-1,1072,1072,10,79,-1,0,0,14,5568,5570),(5570,-1,-1,1072,1072,12,80,-1,0,0,14,5569,7576),(5571,-1,-1,637,637,7,76,-1,0,0,14,4751,5572),(5572,-1,-1,637,637,9,78,-1,0,0,14,5571,5573),(5573,-1,-1,637,637,12,80,-1,0,0,14,5572,12435),(5574,-1,-1,1210,1210,7,76,-1,0,0,14,4754,5575),(5575,-1,-1,1210,1210,9,78,-1,0,0,14,5574,5576),(5576,-1,-1,1210,1210,12,80,-1,0,0,14,5575,7232),(5577,-1,-1,1210,1213,7,76,-1,0,0,14,4757,5578),(5578,-1,-1,1210,1213,9,78,-1,0,0,14,5577,5579),(5579,-1,-1,1210,1213,12,80,-1,0,0,14,5578,7581),(5580,-1,-1,602,602,7,76,-1,0,0,14,4760,5581),(5581,-1,-1,602,602,9,78,-1,0,0,14,5580,5582),(5582,-1,-1,602,602,12,80,-1,0,0,14,5581,10685),(5586,-1,-1,98,98,7,76,-1,0,0,14,4769,5587),(5587,-1,-1,98,98,9,78,-1,0,0,14,5586,5588),(5588,-1,-1,98,98,12,80,-1,0,0,14,5587,7584),(5589,-1,-1,1186,1186,7,76,-1,0,0,14,4778,5590),(5590,-1,-1,1186,1186,9,78,-1,0,0,14,5589,5591),(5591,-1,-1,1186,1186,12,80,-1,0,0,14,5590,7587),(5592,-1,-1,80,80,7,76,-1,0,0,14,4781,5593),(5593,-1,-1,80,80,9,78,-1,0,0,14,5592,5594),(5594,-1,-1,80,80,12,80,-1,0,0,14,5593,7590),(5595,-1,-1,255,255,7,76,-1,0,0,14,4797,5596),(5596,-1,-1,255,255,9,78,-1,0,0,14,5595,5597),(5597,-1,-1,255,255,12,80,-1,0,0,14,5596,7631),(5606,4860,4860,4860,4860,12,80,11688,13,60,14,4860,7127),(5607,4915,4915,4915,4915,7,76,12673,7,4320,14,4917,5608),(5608,4915,4915,4915,4915,9,78,12674,7,4320,14,5607,5609),(5609,4915,4915,4915,4915,12,80,12675,7,4320,14,5608,7246),(5610,4938,4938,4938,4938,12,80,12676,35,1800,14,4938,5614),(5611,-1,-1,634,634,7,76,-1,0,0,14,5034,5612),(5612,-1,-1,634,634,9,78,-1,0,0,14,5611,5613),(5613,-1,-1,634,634,12,80,-1,0,0,14,5612,7713),(5614,4938,4938,4938,4938,9,85,16852,35,1800,16,5610,12875),(5617,-1,-1,267,267,7,76,-1,0,0,14,5135,5618),(5618,-1,-1,267,267,9,78,-1,0,0,14,5617,5619),(5619,-1,-1,267,267,12,80,-1,0,0,14,5618,12860),(5620,-1,-1,5263,5263,7,76,-1,0,0,14,5285,5621),(5621,-1,-1,5263,5263,9,78,-1,0,0,14,5620,5622),(5622,-1,-1,5263,5263,12,80,-1,0,0,14,5621,12466),(5623,-1,-1,658,658,5,76,-1,0,0,14,5310,5624),(5624,-1,-1,658,658,5,77,-1,0,0,14,5623,5625),(5625,-1,-1,658,658,5,78,-1,0,0,14,5624,5626),(5626,-1,-1,658,658,5,79,-1,0,0,14,5625,5627),(5627,-1,-1,658,658,5,80,-1,0,0,14,5626,7593),(5628,-1,-1,98,738,7,76,-1,0,0,14,5319,5629),(5629,-1,-1,98,738,9,78,-1,0,0,14,5628,5630),(5630,-1,-1,98,738,12,80,-1,0,0,14,5629,7598),(5699,1116,1116,1116,1116,7,76,12500,4,2160,14,4982,5700),(5700,1116,1116,1116,1116,9,78,12501,4,2160,14,5699,5701),(5701,1116,1116,1116,1116,12,80,12502,4,2160,14,5700,7430),(5702,592,592,592,592,4,76,12503,2,18,14,4979,5703),(5703,592,592,592,592,4,77,12504,2,18,14,5702,5704),(5704,592,592,592,592,4,78,12505,2,18,14,5703,5705),(5705,592,592,592,592,4,79,12506,2,18,14,5704,5706),(5706,592,592,592,592,4,80,12507,2,18,14,5705,7433),(5707,5298,5298,5298,5298,9,78,12508,32,1800,14,5300,5708),(5708,5298,5298,5298,5298,10,79,12509,32,1800,14,5707,5709),(5709,5298,5298,5298,5298,12,80,12510,32,1800,14,5708,7438),(5710,1598,-1,1598,1598,7,76,12511,6,900,14,4974,5711),(5711,1598,-1,1598,1598,9,78,12512,6,900,14,5710,5712),(5712,1598,-1,1598,1598,12,80,12513,6,900,14,5711,7441),(5713,1569,1569,1569,1569,7,76,12514,5,1800,14,1571,5714),(5714,1569,1569,1569,1569,9,78,12515,5,1800,14,5713,5715),(5715,1569,1569,1569,1569,12,80,12516,5,1800,14,5714,7457),(5716,5020,5020,5020,5020,9,77,12517,9,300,14,5020,7444),(5717,5717,5717,5717,5717,10,76,12519,17,600,14,-1,-1),(5729,-1,-1,724,724,7,76,-1,0,0,14,5258,5730),(5730,-1,-1,724,724,8,77,-1,0,0,14,5729,5731),(5731,-1,-1,724,724,9,78,-1,0,0,14,5730,5732),(5732,-1,-1,724,724,10,79,-1,0,0,14,5731,5733),(5733,-1,-1,724,724,12,80,-1,0,0,14,5732,7489),(5734,1119,1119,1119,1119,7,78,12520,8,900,14,4966,5735),(5735,1119,1119,1119,1119,8,79,12521,8,900,14,5734,5736),(5736,1119,1119,1119,1119,9,80,12522,8,900,14,5735,7479),(5737,723,723,723,723,7,76,12523,6,30,14,4963,7482),(5738,-1,-1,729,729,7,76,-1,0,0,14,4962,5739),(5739,-1,-1,729,729,8,77,-1,0,0,14,5738,5740),(5740,-1,-1,729,729,9,78,-1,0,0,14,5739,7494),(5741,5015,5015,5015,5015,12,80,12524,9,900,14,5015,7483),(5742,289,289,289,289,12,80,12525,3,300,14,1607,7484),(5743,291,291,291,291,9,78,12526,5,900,14,4971,5744),(5744,291,291,291,291,10,79,12527,5,900,14,5743,5745),(5745,291,291,291,291,12,80,12528,5,900,14,5744,7485),(5759,1425,1425,1425,1425,7,78,13565,2,2160,14,1429,5760),(5760,1425,1425,1425,1425,8,78,13570,2,2160,14,5759,5761),(5761,1425,1425,1425,1425,9,79,13575,2,2160,14,5760,5762),(5762,1425,1425,1425,1425,10,79,13580,2,2160,14,5761,5763),(5763,1425,1425,1425,1425,11,80,13585,2,2160,14,5762,-1),(5764,4854,4854,4854,4854,7,76,12534,8,600,14,4856,5765),(5765,4854,4854,4854,4854,9,78,12535,8,600,14,5764,5766),(5766,4854,4854,4854,4854,12,80,12536,8,600,14,5765,7178),(5767,4857,4857,4857,4857,7,76,12537,7,600,14,4859,5768),(5768,4857,4857,4857,4857,9,78,12538,7,600,14,5767,5769),(5769,4857,4857,4857,4857,12,80,12539,7,600,14,5768,17030),(5770,1348,1348,1348,1348,9,78,12540,0,3600,14,1350,5771),(5771,1348,1348,1348,1348,10,79,12541,0,3600,14,5770,5772),(5772,1348,1348,1348,1348,12,80,12542,0,3600,14,5771,7184),(5776,-1,-1,5776,5776,7,76,-1,0,0,14,-1,5777),(5777,-1,-1,5776,5776,9,78,-1,0,0,14,5776,5778),(5778,-1,-1,5776,5776,12,80,-1,0,0,14,5777,7196),(5779,1178,1178,1178,1178,7,76,12546,4,900,14,1180,5780),(5780,1178,1178,1178,1178,8,77,12547,4,900,14,5779,5781),(5781,1178,1178,1178,1178,9,78,12548,4,900,14,5780,7187),(5789,1383,1383,1383,1383,12,80,12549,6,300,14,5084,7299),(5790,1195,1195,1195,1195,9,80,12550,13,2160,14,5079,7300),(5791,131,131,131,131,8,77,12551,4,900,14,5072,5792),(5792,131,131,131,131,9,78,12552,4,900,14,5791,5793),(5793,131,131,131,131,10,79,12553,4,900,14,5792,7301),(5794,1192,1192,1192,1192,8,77,12554,12,1320,14,5078,5795),(5795,1192,1192,1192,1192,9,78,12555,12,1320,14,5794,5796),(5796,1192,1192,1192,1192,10,79,12556,12,1320,14,5795,7304),(5797,-1,-1,5083,5083,7,76,-1,0,0,14,5120,5798),(5798,-1,-1,5083,5083,9,78,-1,0,0,14,5797,5799),(5799,-1,-1,5083,5083,12,80,-1,0,0,14,5798,-1),(5800,746,746,746,746,9,78,12557,10,2160,14,1493,5801),(5801,746,746,746,746,10,79,12558,10,2160,14,5800,5802),(5802,746,746,746,746,12,80,12559,10,2160,14,5801,7307),(5803,1459,1459,1459,1459,7,76,12560,11,1800,14,5082,5804),(5804,1459,1459,1459,1459,9,78,12561,11,1800,14,5803,5805),(5805,1459,1459,1459,1459,12,80,12562,11,1800,14,5804,7310),(5806,-1,-1,255,255,7,59,-1,0,0,16,-1,5807),(5807,-1,-1,255,255,9,59,-1,0,0,16,5806,5808),(5808,-1,-1,255,255,12,59,-1,0,0,16,5807,10623),(5809,5833,5833,5833,5833,9,85,20184,72,900,16,-1,-1),(5819,1498,1498,1498,1498,7,76,12563,12,1320,14,5060,5820),(5820,1498,1498,1498,1498,9,78,12564,12,1320,14,5819,5821),(5821,1498,1498,1498,1498,12,80,12565,12,1320,14,5820,7408),(5822,757,-1,757,757,7,76,12566,6,1800,14,5053,5823),(5823,757,-1,757,757,9,78,12567,6,1800,14,5822,5824),(5824,757,-1,757,757,12,80,12568,6,1800,14,5823,7411),(5825,-1,-1,567,567,7,76,-1,0,0,14,5061,-1),(5826,1495,1495,1495,1495,7,76,12569,30,900,14,5313,5827),(5827,1495,1495,1495,1495,9,78,12570,30,900,14,5826,5828),(5828,1495,1495,1495,1495,12,80,12571,30,900,14,5827,7414),(5829,548,548,548,548,8,77,12572,5,900,14,5056,5830),(5830,548,548,548,548,9,78,12573,5,900,14,5829,5831),(5831,548,548,548,548,10,79,12574,5,900,14,5830,7417),(5832,5105,5105,5105,5105,12,80,12575,11,600,14,5105,7420),(5849,54009,54009,54009,54009,7,73,12576,22,12,14,-1,12923),(5850,-1,-1,781,781,8,77,-1,0,0,14,781,7284),(5854,773,-1,773,773,7,76,12580,5,1800,14,775,5855),(5855,773,-1,773,773,9,78,12581,5,1800,14,5854,5856),(5856,773,-1,773,773,12,80,12582,5,1800,14,5855,7276),(5857,1242,1242,1242,1242,7,76,12577,9,1320,14,1244,5858),(5858,1242,1242,1242,1242,9,78,12578,9,1320,14,5857,5859),(5859,1242,1242,1242,1242,12,80,12579,9,1320,14,5858,7285),(5860,-1,-1,649,649,7,76,-1,0,0,14,651,5861),(5861,-1,-1,649,649,9,78,-1,0,0,14,5860,5862),(5862,-1,-1,649,649,12,80,-1,0,0,14,5861,-1),(5868,1239,1239,1239,1239,12,80,13224,6,600,14,1239,7275),(5869,4890,-1,4890,4890,9,77,12587,3,8640,14,4890,5871),(5870,54010,54010,54010,54010,7,73,12828,22,6,14,-1,-1),(5871,4890,-1,4890,4890,9,79,16440,3,8640,15,5869,5872),(5872,4890,-1,4890,4890,9,81,21745,3,8640,16,5871,14280),(5879,167,167,167,167,10,79,12588,14,900,14,167,7249),(5880,-1,-1,1504,1504,5,76,-1,0,0,14,1506,5881),(5881,-1,-1,1504,1504,5,78,-1,0,0,14,5880,5882),(5882,-1,-1,1504,1504,5,80,-1,0,0,14,5881,7260),(5883,520,520,520,520,12,76,12589,6,540,14,1509,5884),(5884,520,520,520,520,12,78,12590,6,540,14,5883,5885),(5885,520,520,520,520,12,80,12591,6,540,14,5884,7250),(5886,-1,-1,1577,1577,7,76,-1,0,0,14,1579,5887),(5887,-1,-1,1577,1577,9,78,-1,0,0,14,5886,5888),(5888,-1,-1,1577,1577,12,80,-1,0,0,14,5887,7263),(5889,-1,-1,795,795,7,76,-1,0,0,14,4899,5890),(5890,-1,-1,795,795,9,78,-1,0,0,14,5889,5891),(5891,-1,-1,795,795,12,80,-1,0,0,14,5890,7267),(5892,4903,4903,4903,4903,9,76,12592,9,1320,14,4903,7253),(5893,4906,4906,4906,4906,9,76,12593,9,1320,14,4906,7254),(5894,4909,4909,4909,4909,9,76,12594,16,1320,14,4909,7255),(5895,4912,4912,4912,4912,9,76,12595,16,1320,14,4912,7256),(5909,-1,-1,815,815,7,76,-1,0,0,14,5145,5910),(5910,-1,-1,815,815,8,77,-1,0,0,14,5909,5911),(5911,-1,-1,815,815,9,78,-1,0,0,14,5910,5912),(5912,-1,-1,815,815,10,79,-1,0,0,14,5911,5913),(5913,-1,-1,815,815,12,80,-1,0,0,14,5912,7634),(5914,1355,1355,1355,1355,6,76,12596,3,60,14,5242,5915),(5915,1355,1355,1355,1355,6,78,12597,3,60,14,5914,5916),(5916,1355,1355,1355,1355,6,80,12598,3,60,14,5915,7172),(5917,-1,-1,820,820,5,76,-1,0,0,14,4815,5918),(5918,-1,-1,820,820,5,78,-1,0,0,14,5917,5919),(5919,-1,-1,820,820,5,80,-1,0,0,14,5918,7163),(5922,-1,-1,807,807,5,76,-1,0,0,14,1270,5923),(5923,-1,-1,807,807,5,78,-1,0,0,14,5922,5924),(5924,-1,-1,807,807,5,80,-1,0,0,14,5923,7628),(5939,-1,-1,5264,5264,7,76,-1,0,0,14,5268,5940),(5940,-1,-1,5264,5264,8,77,-1,0,0,14,5939,5941),(5941,-1,-1,5264,5264,9,78,-1,0,0,14,5940,5942),(5942,-1,-1,5264,5264,10,79,-1,0,0,14,5941,5943),(5943,-1,-1,5264,5264,12,80,-1,0,0,14,5942,7204),(5944,-1,-1,4924,4924,9,78,-1,0,0,14,4926,5945),(5945,-1,-1,4924,4924,10,79,-1,0,0,14,5944,5946),(5946,-1,-1,4924,4924,12,80,-1,0,0,14,5945,-1),(5947,1274,1274,1274,1274,9,78,12599,9,540,14,4866,5948),(5948,1274,1274,1274,1274,10,79,12600,9,540,14,5947,5949),(5949,1274,1274,1274,1274,12,80,12601,9,540,14,5948,7199),(5950,-1,-1,1511,1511,12,80,-1,0,0,14,1513,5951),(5951,-1,-1,1511,1511,12,80,-1,0,0,14,5950,5952),(5952,-1,-1,1511,1511,12,80,-1,0,0,14,5951,-1),(5953,184,184,184,184,10,79,12602,5,4320,14,184,7203),(5954,-1,-1,4861,4861,7,76,-1,0,0,14,4863,5955),(5955,-1,-1,4861,4861,9,78,-1,0,0,14,5954,5956),(5956,-1,-1,4861,4861,12,80,-1,0,0,14,5955,7215),(5969,534,534,534,534,7,76,12603,4,2160,14,5043,5970),(5970,534,534,534,534,9,78,12604,4,2160,14,5969,5971),(5971,534,534,534,534,12,80,12605,4,2160,14,5970,7329),(5972,-1,-1,593,593,7,76,-1,0,0,14,595,-1),(5973,-1,-1,596,596,7,76,-1,0,0,14,598,-1),(5975,5095,5095,5095,5095,7,76,12606,10,900,14,5097,5976),(5976,5095,5095,5095,5095,9,78,12607,10,900,14,5975,5977),(5977,5095,5095,5095,5095,12,80,12608,10,900,14,5976,7332),(5984,5984,5984,5984,5984,12,80,12609,2,30,14,-1,7335),(5999,645,-1,645,645,10,79,12610,4,5,14,645,10739),(6000,545,545,545,545,7,76,12611,3,900,14,4999,6001),(6001,545,545,545,545,9,78,12612,3,900,14,6000,6002),(6002,545,545,545,545,12,80,12613,3,900,14,6001,7344),(6003,-1,-1,1616,1616,7,76,-1,0,0,14,4996,6004),(6004,-1,-1,1616,1616,8,77,-1,0,0,14,6003,6005),(6005,-1,-1,1616,1616,9,78,-1,0,0,14,6004,6006),(6006,-1,-1,1616,1616,10,79,-1,0,0,14,6005,6007),(6007,-1,-1,1616,1616,12,80,-1,0,0,14,6006,7637),(6008,1345,1345,1345,1345,8,77,12614,6,900,14,5005,6009),(6009,1345,1345,1345,1345,9,78,12615,6,900,14,6008,6010),(6010,1345,1345,1345,1345,10,79,12616,6,900,14,6009,7347),(6011,-1,-1,864,864,12,80,-1,0,0,14,4985,6012),(6012,-1,-1,864,864,12,80,-1,0,0,14,6011,6013),(6013,-1,-1,864,864,12,80,-1,0,0,14,6012,7353),(6014,-1,-1,5248,5248,7,76,-1,0,0,14,5250,6015),(6015,-1,-1,5248,5248,9,78,-1,0,0,14,6014,6016),(6016,-1,-1,5248,5248,12,80,-1,0,0,14,6015,7356),(6017,-1,-1,644,644,7,73,-1,0,0,14,4988,6018),(6018,-1,-1,644,644,9,75,-1,0,0,14,6017,6019),(6019,-1,-1,644,644,12,77,-1,0,0,14,6018,7359),(6020,-1,-1,6020,6020,2,65,-1,0,0,14,-1,6021),(6021,-1,-1,6020,6020,2,65,-1,0,0,14,6020,6022),(6022,-1,-1,6020,6020,2,65,-1,0,0,14,6021,6045),(6023,-1,-1,119,119,12,85,-1,0,0,16,7567,6024),(6024,-1,-1,119,119,12,85,-1,0,0,16,6023,6025),(6025,-1,-1,119,119,12,85,-1,0,0,16,6024,12548),(6026,-1,-1,1004,1004,7,81,-1,0,0,16,-1,6027),(6027,-1,-1,1004,1004,9,81,-1,0,0,16,6026,6028),(6028,-1,-1,1004,1004,12,81,-1,0,0,16,6027,-1),(6029,-1,-1,1304,1304,7,76,-1,0,0,14,1306,6030),(6030,-1,-1,1304,1304,9,78,-1,0,0,14,6029,6031),(6031,-1,-1,1304,1304,12,80,-1,0,0,14,6030,7148),(6032,-1,-1,1604,1604,7,69,-1,0,0,14,5294,6033),(6033,-1,-1,1604,1604,9,71,-1,0,0,14,6032,6034),(6034,-1,-1,1604,1604,12,73,-1,0,0,14,6033,7131),(6035,-1,-1,846,846,7,76,-1,0,0,14,4950,6036),(6036,-1,-1,846,846,9,78,-1,0,0,14,6035,6037),(6037,-1,-1,846,846,12,80,-1,0,0,14,6036,7151),(6038,5022,5022,5022,5022,7,76,23988,5,600,14,5024,6039),(6039,5022,5022,5022,5022,9,78,23989,5,600,14,6038,6040),(6040,5022,5022,5022,5022,12,80,23990,5,600,14,6039,15628),(6041,5028,-1,5028,5028,9,78,12621,4,900,14,5028,-1),(6042,-1,-1,1543,1543,7,76,-1,0,0,14,4953,6043),(6043,-1,-1,1543,1543,9,78,-1,0,0,14,6042,6044),(6044,-1,-1,1543,1543,12,80,-1,0,0,14,6043,7134),(6045,-1,-1,6020,6020,2,66,-1,0,0,14,6022,6046),(6046,-1,-1,6020,6020,2,68,-1,0,0,14,6045,6047),(6047,-1,-1,6020,6020,2,70,-1,0,0,14,6046,6048),(6048,-1,-1,6020,6020,2,71,-1,0,0,14,6047,6049),(6049,-1,-1,6020,6020,2,73,-1,0,0,14,6048,6050),(6050,-1,-1,6020,6020,2,75,-1,0,0,14,6049,6057),(6051,-1,-1,6051,6051,3,76,-1,0,0,14,-1,6052),(6052,-1,-1,6051,6051,3,78,-1,0,0,14,6051,6053),(6053,-1,-1,6051,6051,3,80,-1,0,0,14,6052,7601),(6054,4931,4931,4931,4931,7,76,12756,4,600,14,4933,6055),(6055,4931,4931,4931,4931,7,78,12757,4,600,14,6054,6056),(6056,4931,4931,4931,4931,7,80,12758,4,600,14,6055,7291),(6057,-1,-1,6020,6020,2,76,-1,0,0,14,6050,6058),(6058,-1,-1,6020,6020,2,78,-1,0,0,14,6057,6059),(6059,-1,-1,6020,6020,2,80,-1,0,0,14,6058,7169),(6060,-1,-1,6540,6540,8,76,-1,0,0,14,-1,6061),(6061,-1,-1,6540,6540,8,76,-1,0,0,14,6060,6470),(6063,-1,-1,589,589,7,76,-1,0,0,14,5272,6064),(6064,-1,-1,589,589,9,78,-1,0,0,14,6063,6065),(6065,-1,-1,589,589,12,80,-1,0,0,14,6064,7390),(6066,-1,-1,1313,1313,7,76,-1,0,0,14,5031,6067),(6067,-1,-1,1313,1313,7,76,-1,0,0,14,6066,6068),(6068,-1,-1,1313,1313,8,77,-1,0,0,14,6067,6069),(6069,-1,-1,1313,1313,9,78,-1,0,0,14,6068,6070),(6070,-1,-1,1313,1313,10,79,-1,0,0,14,6069,6071),(6071,-1,-1,1313,1313,12,80,-1,0,0,14,6070,7393),(6072,-1,-1,210,210,8,77,-1,0,0,14,1318,6073),(6073,-1,-1,210,210,9,78,-1,0,0,14,6072,6074),(6074,-1,-1,210,210,10,79,-1,0,0,14,6073,7399),(6075,-1,-1,895,895,7,76,-1,0,0,14,899,6076),(6076,-1,-1,895,895,8,77,-1,0,0,14,6075,6077),(6077,-1,-1,895,895,9,78,-1,0,0,14,6076,6078),(6078,-1,-1,895,895,10,79,-1,0,0,14,6077,6079),(6079,-1,-1,895,895,12,80,-1,0,0,14,6078,7402),(6080,-1,-1,683,683,5,75,-1,0,0,14,5305,6081),(6081,-1,-1,683,683,5,75,-1,0,0,14,6080,7604),(6082,-1,-1,6084,6084,5,85,0,0,0,17,-1,6083),(6083,-1,-1,6084,6084,5,87,0,0,0,17,6082,6084),(6084,-1,-1,6084,6084,5,89,0,0,0,17,6083,13366),(6085,-1,-1,6761,6761,10,81,-1,0,0,16,6763,6086),(6086,-1,-1,6761,6761,11,83,-1,0,0,16,6085,6087),(6087,-1,-1,6761,6761,12,85,-1,0,0,16,6086,10763),(6088,-1,-1,6088,6088,9,85,0,0,0,17,-1,6089),(6089,-1,-1,6088,6088,12,87,0,0,0,17,6088,6090),(6090,-1,-1,6088,6088,15,89,0,0,0,17,6089,-1),(6092,5251,5251,5251,5251,7,76,12635,13,900,14,5253,6093),(6093,5251,5251,5251,5251,9,78,12636,13,900,14,6092,6094),(6094,5251,5251,5251,5251,12,80,12637,13,900,14,6093,7472),(6095,513,513,513,513,7,76,12638,4,120,14,515,6096),(6096,513,513,513,513,9,78,12639,4,120,14,6095,6097),(6097,513,513,513,513,12,80,12640,4,120,14,6096,7475),(6098,1327,1327,1327,1327,7,76,12641,10,900,14,5316,6099),(6099,1327,1327,1327,1327,9,78,12642,10,900,14,6098,6100),(6100,1327,1327,1327,1327,12,80,12643,10,900,14,6099,7460),(6101,153,153,153,153,12,80,12644,3,2160,14,5068,7468),(6102,146,146,146,146,8,77,12645,2,180,14,5069,7466),(6103,528,528,528,528,7,76,12646,5,720,14,901,6104),(6104,528,528,528,528,9,78,12647,5,720,14,6103,6105),(6105,528,528,528,528,12,80,12648,5,720,14,6104,7469),(6106,6106,6106,6106,6106,4,67,21965,13,4320,16,-1,6107),(6107,6106,6106,6106,6106,5,68,21966,13,4320,16,6106,6108),(6108,6106,6106,6106,6106,6,69,21967,13,4320,16,6107,6109),(6109,6106,6106,6106,6106,7,77,21968,13,4320,16,6108,6110),(6110,6106,6106,6106,6106,8,78,21969,13,4320,16,6109,6111),(6111,6106,6106,6106,6106,9,79,21970,13,4320,16,6110,-1),(6112,-1,-1,6112,6112,5,85,-1,0,0,17,-1,12966),(6113,-1,-1,6113,6113,9,85,0,0,0,17,-1,6114),(6114,-1,-1,6113,6113,12,87,0,0,0,17,6113,6115),(6115,-1,-1,6113,6113,15,89,0,0,0,17,6114,-1),(6119,-1,-1,6119,6119,6,76,-1,0,0,14,-1,6120),(6120,-1,-1,6119,6119,6,77,-1,0,0,14,6119,6121),(6121,-1,-1,6119,6119,6,78,-1,0,0,14,6120,6122),(6122,-1,-1,6119,6119,6,79,-1,0,0,14,6121,6123),(6123,-1,-1,6119,6119,6,80,-1,0,0,14,6122,7526),(6124,-1,-1,5263,5263,3,71,-1,0,0,12,-1,6125),(6125,-1,-1,5263,5263,6,73,-1,0,0,12,6124,6126),(6126,-1,-1,5263,5263,9,75,-1,0,0,12,6125,6127),(6127,-1,-1,5263,5263,10,76,-1,0,0,14,6126,6128),(6128,-1,-1,5263,5263,11,78,-1,0,0,14,6127,6129),(6129,-1,-1,5263,5263,12,80,-1,0,0,14,6128,12463),(6130,-1,-1,586,586,7,76,-1,0,0,14,588,6131),(6131,-1,-1,586,586,7,76,-1,0,0,14,6130,6132),(6132,-1,-1,586,586,7,76,-1,0,0,14,6131,-1),(6133,1351,1351,1351,1351,8,77,12649,5,30,14,1351,7109),(6134,4849,4849,4849,4849,7,76,12650,7,1800,14,4849,7110),(6135,54006,54006,54006,54006,7,76,12651,18,180,14,-1,7111),(6136,-1,-1,6136,6136,7,76,-1,0,0,10,-1,6137),(6149,921,921,921,921,9,79,12652,8,60,14,5280,7245),(6150,922,922,922,922,9,78,12653,8,60,14,5281,7236),(6151,923,923,923,923,9,77,12654,8,60,14,5282,7235),(6152,1334,1334,1334,1334,9,78,12655,11,4320,14,1336,6153),(6153,1334,1334,1334,1334,10,79,12656,11,4320,14,6152,6154),(6154,1334,1334,1334,1334,12,80,12657,11,4320,14,6153,7239),(6155,4944,-1,4944,4944,7,76,12658,0,1,14,4946,6156),(6156,4944,-1,4944,4944,9,78,12659,0,1,14,6155,6157),(6157,4944,-1,4944,4944,12,80,12660,0,1,14,6156,7229),(6158,1337,1337,1337,1337,8,77,12661,13,4320,14,1339,6159),(6159,1337,1337,1337,1337,9,78,12662,13,4320,14,6158,6160),(6160,1337,1337,1337,1337,10,79,12663,13,4320,14,6159,14338),(6161,1478,-1,1478,1478,9,78,12664,0,1,14,1480,6162),(6162,1478,-1,1478,1478,10,79,12665,0,1,14,6161,6163),(6163,1478,-1,1478,1478,12,80,12666,0,1,14,6162,7242),(6200,6533,6533,6533,6533,10,79,12768,15,600,14,-1,7428),(6201,6534,6534,6534,6534,9,78,12769,16,900,14,-1,7429),(6202,-1,-1,6535,6535,5,70,-1,0,0,14,-1,6203),(6203,-1,-1,6535,6535,5,70,-1,0,0,14,6202,6204),(6204,-1,-1,6535,6535,5,70,-1,0,0,14,6203,-1),(6205,6536,6536,6536,6536,7,76,12712,39,5,14,-1,-1),(6206,6537,6537,6537,6537,7,76,12770,30,900,14,-1,6207),(6207,6537,6537,6537,6537,8,77,12771,30,900,14,6206,6208),(6208,6537,6537,6537,6537,9,78,12772,30,900,14,6207,7606),(6209,-1,-1,6538,6538,7,76,-1,0,0,14,-1,6210),(6210,-1,-1,6538,6538,9,78,-1,0,0,14,6209,6211),(6211,-1,-1,6538,6538,12,80,-1,0,0,14,6210,7478),(6212,6539,6539,6539,6539,6,71,12776,18,1800,14,-1,6213),(6213,6539,6539,6539,6539,6,74,12777,18,1800,14,6212,6214),(6214,6539,6539,6539,6539,6,77,12778,18,1800,14,6213,7609),(6215,-1,-1,6540,6540,8,71,-1,0,0,14,-1,6216),(6216,-1,-1,6540,6540,8,72,-1,0,0,14,6215,6217),(6217,-1,-1,6540,6540,8,73,-1,0,0,14,6216,6300),(6218,6218,6218,6218,6218,7,76,12782,0,1,14,-1,7488),(6219,6542,6542,6542,6542,7,76,12783,18,1800,14,-1,6220),(6220,6542,6542,6542,6542,9,78,12784,18,1800,14,6219,6221),(6221,6542,6542,6542,6542,12,80,12785,18,1800,14,6220,-1),(6222,6543,6543,6543,6543,9,72,13143,18,25,14,-1,-1),(6223,-1,-1,962,962,5,76,-1,0,0,14,966,6224),(6224,-1,-1,962,962,5,77,-1,0,0,14,6223,6225),(6225,-1,-1,962,962,5,78,-1,0,0,14,6224,6226),(6226,-1,-1,962,962,5,79,-1,0,0,14,6225,6227),(6227,-1,-1,962,962,5,80,-1,0,0,14,6226,10361),(6228,-1,-1,6545,6545,2,70,-1,0,0,14,-1,6229),(6229,-1,-1,6545,6545,2,70,-1,0,0,14,6228,6230),(6230,-1,-1,6545,6545,2,70,-1,0,0,14,6229,6231),(6231,-1,-1,6545,6545,2,70,-1,0,0,14,6230,-1),(6232,6232,6232,6232,6232,12,80,14413,18,900,14,-1,7421),(6233,-1,-1,477,477,2,70,-1,0,0,14,479,6234),(6234,-1,-1,477,477,2,71,-1,0,0,14,6233,6235),(6235,-1,-1,477,477,2,72,-1,0,0,14,6234,16094),(6236,-1,-1,6548,6548,6,73,-1,0,0,14,-1,6237),(6237,-1,-1,6548,6548,6,75,-1,0,0,14,6236,6238),(6238,-1,-1,6548,6548,8,77,-1,0,0,14,6237,12929),(6240,-1,-1,767,767,3,65,-1,0,0,14,-1,6241),(6241,-1,-1,767,767,6,65,-1,0,0,14,6240,6242),(6242,-1,-1,767,767,9,65,-1,0,0,14,6241,6243),(6243,-1,-1,767,767,3,67,-1,0,0,14,6242,6244),(6244,-1,-1,767,767,6,68,-1,0,0,14,6243,6245),(6245,-1,-1,767,767,9,69,-1,0,0,14,6244,12426),(6249,6552,6552,6552,6552,5,70,-1,0,0,14,-1,6250),(6250,6552,6552,6552,6552,6,72,-1,0,0,14,6249,6251),(6251,6552,6552,6552,6552,6,74,-1,0,0,14,6250,6252),(6252,6552,6552,6552,6552,7,76,-1,0,0,14,6251,6253),(6253,6552,6552,6552,6552,9,78,-1,0,0,14,6252,7279),(6254,616,616,616,616,6,73,12765,7,900,14,1250,6255),(6255,616,616,616,616,7,76,12766,7,900,14,6254,6256),(6256,616,616,616,616,10,79,12767,7,900,14,6255,7257),(6257,-1,-1,86,86,2,55,-1,0,0,14,-1,6258),(6258,-1,-1,86,86,4,55,-1,0,0,14,6257,6259),(6259,-1,-1,86,86,6,55,-1,0,0,14,6258,8223),(6260,-1,-1,495,495,6,73,-1,0,0,14,497,6261),(6261,-1,-1,495,495,7,76,-1,0,0,14,6260,6262),(6262,-1,-1,495,495,10,79,-1,0,0,14,6261,10666),(6266,-1,-1,6557,6557,6,73,-1,0,0,14,-1,6267),(6267,-1,-1,6557,6557,7,76,-1,0,0,14,6266,6268),(6268,-1,-1,6557,6557,10,79,-1,0,0,14,6267,-1),(6269,-1,-1,6558,6558,6,73,-1,0,0,14,-1,6270),(6270,-1,-1,6558,6558,7,76,-1,0,0,14,6269,6271),(6271,-1,-1,6558,6558,10,79,-1,0,0,14,6270,-1),(6272,-1,-1,6559,6559,6,73,-1,0,0,14,-1,6273),(6273,-1,-1,6559,6559,7,75,-1,0,0,14,6272,6274),(6274,-1,-1,6559,6559,10,77,-1,0,0,14,6273,7137),(6275,-1,-1,6560,6560,6,73,-1,0,0,14,-1,6276),(6276,-1,-1,6560,6560,7,76,-1,0,0,14,6275,6277),(6277,-1,-1,6560,6560,10,79,-1,0,0,14,6276,16266),(6278,6561,6561,6561,6561,7,76,12795,32,30,14,-1,6279),(6279,6561,6561,6561,6561,7,76,12796,32,30,14,6278,6280),(6280,6561,6561,6561,6561,7,76,12797,32,30,14,6279,7422),(6281,6563,6563,6563,6563,9,78,13144,36,8,14,-1,12995),(6282,6562,6562,6562,6562,6,72,12798,39,1,14,-1,-1),(6283,-1,-1,6564,6564,6,73,-1,0,0,14,-1,6284),(6284,-1,-1,6564,6564,7,76,-1,0,0,14,6283,6285),(6285,-1,-1,6564,6564,10,79,-1,0,0,14,6284,7112),(6286,6565,6565,6565,6565,7,76,12802,17,45,14,-1,7115),(6287,-1,-1,6566,6566,6,73,-1,0,0,14,-1,6288),(6288,-1,-1,6566,6566,7,76,-1,0,0,14,6287,6289),(6289,-1,-1,6566,6566,10,79,-1,0,0,14,6288,-1),(6290,6290,6290,6290,6290,6,71,12803,0,1,14,-1,6291),(6291,6290,6290,6290,6290,6,73,12804,0,1,14,6290,6292),(6292,6290,6290,6290,6290,6,75,12805,0,1,14,6291,6293),(6293,6290,6290,6290,6290,7,76,12806,0,1,14,6292,6294),(6294,6290,6290,6290,6290,9,78,12807,0,1,14,6293,6295),(6295,6290,6290,6290,6290,12,80,12808,0,1,14,6294,7223),(6296,619,619,619,619,6,73,12759,6,900,14,722,6297),(6297,619,619,619,619,6,73,12760,6,900,14,6296,6298),(6298,619,619,619,619,6,73,12761,6,900,14,6297,7226),(6299,6299,6299,6299,6299,9,65,12786,18,12,14,-1,-1),(6300,-1,-1,6540,6540,8,74,-1,0,0,14,6217,6301),(6301,-1,-1,6540,6540,8,75,-1,0,0,14,6300,6472),(6302,-1,-1,6302,6302,5,81,0,0,0,16,-1,6303),(6303,-1,-1,6302,6302,5,83,0,0,0,16,6302,6304),(6304,-1,-1,6302,6302,5,85,0,0,0,16,6303,11011),(6307,1358,1358,1358,1358,6,71,13168,3,60,14,1360,6308),(6308,1358,1358,1358,1358,6,73,13169,3,60,14,6307,6309),(6309,1358,1358,1358,1358,6,75,13170,3,60,14,6308,6310),(6310,1358,1358,1358,1358,6,76,13171,3,60,14,6309,6311),(6311,1358,1358,1358,1358,6,78,13172,3,60,14,6310,6312),(6312,1358,1358,1358,1358,6,80,13173,3,60,14,6311,7157),(6313,1352,1352,1352,1352,6,71,13174,3,60,14,1354,6314),(6314,1352,1352,1352,1352,6,73,13175,3,60,14,6313,6315),(6315,1352,1352,1352,1352,6,75,13177,3,60,14,6314,6316),(6316,1352,1352,1352,1352,6,76,13178,3,60,14,6315,6317),(6317,1352,1352,1352,1352,6,78,13179,3,60,14,6316,6318),(6318,1352,1352,1352,1352,6,80,13180,3,60,14,6317,7154),(6319,-1,-1,501,501,6,73,-1,0,0,14,503,6320),(6320,-1,-1,501,501,6,75,-1,0,0,14,6319,6321),(6321,-1,-1,501,501,6,77,-1,0,0,14,6320,6528),(6322,-1,-1,6322,6322,6,73,-1,0,0,14,-1,6323),(6323,-1,-1,6322,6322,6,75,-1,0,0,14,6322,6324),(6324,-1,-1,6322,6322,6,77,-1,0,0,14,6323,-1),(6325,6325,6325,6325,6325,7,73,13213,18,600,14,-1,6326),(6326,6325,6325,6325,6325,7,75,13214,18,600,14,6325,6327),(6327,6325,6325,6325,6325,7,77,13215,18,600,14,6326,6361),(6328,6328,6328,6328,6328,7,74,13204,10,600,14,-1,6329),(6329,6328,6328,6328,6328,7,76,13205,10,600,14,6328,6330),(6330,6328,6328,6328,6328,7,78,13212,10,600,14,6329,7143),(6331,-1,-1,878,878,7,76,-1,0,0,14,4959,6332),(6332,-1,-1,878,878,7,78,-1,0,0,14,6331,7146),(6333,6333,6333,6333,6333,9,59,13167,3,600,14,-1,7266),(6334,-1,-1,6334,6334,6,73,-1,0,0,14,-1,6335),(6335,-1,-1,6334,6334,6,75,-1,0,0,14,6334,6336),(6336,-1,-1,6334,6334,6,77,-1,0,0,14,6335,-1),(6337,-1,-1,6337,6337,6,74,-1,0,0,14,-1,6338),(6338,-1,-1,6337,6337,6,76,-1,0,0,14,6337,6339),(6339,-1,-1,6337,6337,6,78,-1,0,0,14,6338,7448),(6340,-1,-1,6340,6340,6,74,-1,0,0,14,-1,6341),(6341,-1,-1,6340,6340,6,76,-1,0,0,14,6340,6342),(6342,-1,-1,6340,6340,6,78,-1,0,0,14,6341,7451),(6343,-1,-1,6343,6343,6,74,-1,0,0,14,-1,6344),(6344,-1,-1,6343,6343,6,76,-1,0,0,14,6343,6345),(6345,-1,-1,6343,6343,6,78,-1,0,0,14,6344,7166),(6346,-1,-1,6346,6346,6,74,-1,0,0,14,-1,6347),(6347,-1,-1,6346,6346,6,76,-1,0,0,14,6346,6348),(6348,-1,-1,6346,6346,6,78,-1,0,0,14,6347,7615),(6349,-1,-1,6349,6349,6,74,-1,0,0,14,-1,6350),(6350,-1,-1,6349,6349,6,76,-1,0,0,14,6349,6351),(6351,-1,-1,6349,6349,6,78,-1,0,0,14,6350,7618),(6352,4894,4894,4894,4894,6,76,13181,7,2160,14,4896,6353),(6353,4894,4894,4894,4894,6,77,13182,7,2160,14,6352,6354),(6354,4894,4894,4894,4894,6,78,13183,7,2160,14,6353,7288),(6355,-1,-1,6355,6355,6,73,-1,0,0,14,-1,6356),(6356,-1,-1,6355,6355,6,74,-1,0,0,14,6355,6357),(6357,-1,-1,6355,6355,6,75,-1,0,0,14,6356,6358),(6358,-1,-1,6355,6355,6,76,-1,0,0,14,6357,6359),(6359,-1,-1,6355,6355,6,77,-1,0,0,14,6358,6360),(6360,-1,-1,6355,6355,6,80,-1,0,0,16,6359,14101),(6361,6325,6325,6325,6325,7,81,16861,18,600,16,6327,12633),(6362,-1,-1,6362,6362,5,77,0,0,0,16,-1,6363),(6363,-1,-1,6362,6362,5,79,0,0,0,16,6362,6364),(6364,-1,-1,6362,6362,5,81,0,0,0,16,6363,6365),(6365,-1,-1,6362,6362,5,83,0,0,0,16,6364,6366),(6366,-1,-1,6362,6362,5,85,0,0,0,16,6365,16327),(6370,6370,6370,6370,6370,6,76,13188,7,600,14,-1,6371),(6371,6370,6370,6370,6370,6,77,13189,7,600,14,6370,6372),(6372,6370,6370,6370,6370,6,78,13190,7,600,14,6371,7350),(6375,-1,-1,6375,6375,6,76,-1,0,0,14,-1,6376),(6376,-1,-1,6375,6375,6,77,-1,0,0,14,6375,6377),(6377,-1,-1,6375,6375,6,78,-1,0,0,14,6376,7644),(6378,209,209,209,1272,6,76,13501,12,5,14,1272,-1),(6379,6379,6379,6379,6379,6,60,13500,37,5,14,-1,-1),(6380,6380,6380,6380,6380,6,78,13209,39,120,14,-1,6381),(6381,6380,6380,6380,6380,6,79,13210,39,120,14,6380,6382),(6382,6380,6380,6380,6380,6,80,13211,39,120,14,6381,7497),(6383,-1,-1,6383,6383,3,70,-1,0,0,14,-1,6384),(6384,-1,-1,6383,6383,6,70,-1,0,0,14,6383,6385),(6385,-1,-1,6383,6383,9,70,-1,0,0,14,6384,10607),(6386,-1,-1,6386,6386,7,72,-1,0,0,14,-1,6387),(6387,-1,-1,6386,6386,7,74,-1,0,0,14,6386,6388),(6388,-1,-1,6386,6386,7,76,-1,0,0,14,6387,6389),(6389,-1,-1,6386,6386,7,78,-1,0,0,14,6388,13521),(6390,-1,-1,65,661,3,76,-1,0,0,14,4697,6391),(6391,-1,-1,65,661,3,77,-1,0,0,14,6390,6392),(6392,-1,-1,65,661,3,78,-1,0,0,14,6391,6393),(6393,-1,-1,65,661,3,79,-1,0,0,14,6392,6394),(6394,-1,-1,65,661,3,80,-1,0,0,14,6393,7534),(6395,-1,-1,6395,6395,7,76,-1,0,0,14,-1,6396),(6396,-1,-1,6395,6395,7,77,-1,0,0,14,6395,6397),(6397,-1,-1,6395,6395,7,78,-1,0,0,14,6396,7336),(6398,516,516,516,516,6,72,13198,5,480,14,516,7237),(6400,1110,1110,1110,1110,6,73,13192,3,2160,14,1112,6401),(6401,1110,1110,1110,1110,6,75,13193,3,2160,14,6400,6402),(6402,1110,1110,1110,1110,6,76,13194,3,2160,14,6401,7445),(6403,-1,-1,1107,1107,7,76,-1,0,0,14,5288,6404),(6404,-1,-1,1107,1107,9,78,-1,0,0,14,6403,6405),(6405,-1,-1,1107,1107,12,80,-1,0,0,14,6404,12432),(6406,-1,-1,5085,5085,6,76,-1,0,0,14,5087,6407),(6407,-1,-1,5085,5085,6,78,-1,0,0,14,6406,6408),(6408,-1,-1,5085,5085,6,80,-1,0,0,14,6407,7384),(6409,-1,-1,6540,6540,8,71,-1,0,0,14,-1,6410),(6410,-1,-1,6540,6540,8,72,-1,0,0,14,6409,6411),(6411,-1,-1,6540,6540,8,73,-1,0,0,14,6410,6412),(6412,-1,-1,6540,6540,8,74,-1,0,0,14,6411,6413),(6413,-1,-1,6540,6540,8,75,-1,0,0,14,6412,6414),(6414,-1,-1,6540,6540,8,76,-1,0,0,14,6413,6415),(6415,-1,-1,6540,6540,8,77,-1,0,0,14,6414,6416),(6416,-1,-1,6540,6540,8,78,-1,0,0,14,6415,6417),(6417,-1,-1,6540,6540,8,79,-1,0,0,14,6416,6418),(6418,-1,-1,6540,6540,8,80,-1,0,0,14,6417,6474),(6419,-1,-1,6540,6540,8,71,-1,0,0,14,-1,6420),(6420,-1,-1,6540,6540,8,72,-1,0,0,14,6419,6421),(6421,-1,-1,6540,6540,8,73,-1,0,0,14,6420,6476),(6422,-1,-1,6422,6422,3,61,-1,0,0,14,-1,6423),(6423,-1,-1,6422,6422,3,63,-1,0,0,14,6422,6424),(6424,-1,-1,6422,6422,3,65,-1,0,0,14,6423,-1),(6425,5007,5007,5007,5007,9,76,13509,8,2160,14,5009,6426),(6426,5007,5007,5007,5007,9,78,13510,8,2160,14,6425,6427),(6427,5007,5007,5007,5007,9,80,13511,8,2160,14,6426,7341),(6428,-1,-1,1287,1287,3,67,-1,0,0,14,-1,6429),(6429,-1,-1,1287,1287,6,68,-1,0,0,14,6428,6430),(6430,-1,-1,1287,1287,9,69,-1,0,0,14,6429,12472),(6431,-1,-1,1056,1056,5,76,-1,0,0,14,1060,6432),(6432,-1,-1,1056,1056,5,77,-1,0,0,14,6431,6433),(6433,-1,-1,1056,1056,5,78,-1,0,0,14,6432,6434),(6434,-1,-1,1056,1056,5,79,-1,0,0,14,6433,6435),(6435,-1,-1,1056,1056,5,80,-1,0,0,14,6434,7521),(6436,-1,-1,6436,6436,6,73,-1,0,0,14,-1,6437),(6437,-1,-1,6436,6436,6,75,-1,0,0,14,6436,6438),(6438,-1,-1,6436,6436,8,77,-1,0,0,14,6437,7313),(6439,-1,-1,468,468,2,67,-1,0,0,14,470,6440),(6440,-1,-1,468,468,2,69,-1,0,0,14,6439,7316),(6441,-1,-1,1546,1546,5,76,-1,0,0,14,4831,12673),(6442,-1,-1,1471,1471,6,76,-1,0,0,14,1475,6443),(6443,-1,-1,1471,1471,6,77,-1,0,0,14,6442,-1),(6445,-1,-1,6445,6445,2,62,-1,0,0,14,-1,6446),(6446,-1,-1,6445,6445,2,64,-1,0,0,14,6445,6447),(6447,-1,-1,6445,6445,2,66,-1,0,0,14,6446,-1),(6448,5109,5109,5109,5109,9,77,13515,0,1,14,5109,7467),(6449,1520,1520,1520,1520,9,70,13516,11,900,14,1522,6450),(6450,1520,1520,1520,1520,9,70,13517,11,900,14,6449,6451),(6451,1520,1520,1520,1520,9,70,13518,11,900,14,6450,7463),(6452,-1,-1,6452,6452,2,71,-1,0,0,14,-1,6453),(6453,-1,-1,6452,6452,2,72,-1,0,0,14,6452,6454),(6454,-1,-1,6452,6452,2,73,-1,0,0,14,6453,-1),(6455,6455,6455,6455,6455,2,72,14750,36,30,14,-1,6456),(6456,6455,6455,6455,6455,2,74,14751,36,30,14,6455,6457),(6457,6455,6455,6455,6455,2,76,14752,36,30,14,6456,-1),(6458,-1,-1,6458,6458,3,78,-1,0,0,14,-1,6459),(6459,-1,-1,6458,6458,3,78,-1,0,0,14,6458,6460),(6460,-1,-1,6458,6458,3,78,-1,0,0,14,6459,-1),(6461,-1,-1,6461,6461,3,78,-1,0,0,14,-1,6462),(6462,-1,-1,6461,6461,3,78,-1,0,0,14,6461,6463),(6463,-1,-1,6461,6461,3,78,-1,0,0,14,6462,-1),(6464,967,967,967,967,6,76,13897,10,1800,14,969,6465),(6465,967,967,967,967,6,77,13898,10,1800,14,6464,6466),(6466,967,967,967,967,6,78,13899,10,1800,14,6465,7217),(6467,-1,-1,6467,6467,3,61,-1,0,0,15,-1,6468),(6468,-1,-1,6467,6467,3,63,-1,0,0,15,6467,6469),(6469,-1,-1,6467,6467,3,65,-1,0,0,15,6468,-1),(6470,-1,-1,6540,6540,8,76,-1,0,0,15,6061,6471),(6471,-1,-1,6540,6540,8,81,-1,0,0,15,6470,12487),(6472,-1,-1,6540,6540,8,81,-1,0,0,15,6301,6473),(6473,-1,-1,6540,6540,8,83,-1,0,0,15,6472,12481),(6474,-1,-1,6540,6540,8,81,-1,0,0,15,6418,6475),(6475,-1,-1,6540,6540,8,83,-1,0,0,15,6474,12483),(6476,-1,-1,6540,6540,8,81,-1,0,0,15,6421,6477),(6477,-1,-1,6540,6540,8,83,-1,0,0,15,6476,12485),(6478,0,0,6478,6478,3,81,-1,0,0,16,-1,6479),(6479,0,0,6478,6478,5,83,-1,0,0,16,6478,6480),(6480,0,0,6478,6478,7,85,-1,0,0,16,6479,-1),(6481,0,0,6481,6481,5,85,-1,0,0,16,-1,6482),(6482,0,0,6481,6481,7,85,-1,0,0,16,6481,6483),(6483,0,0,6481,6481,9,85,-1,0,0,16,6482,15314),(6484,-1,-1,7940,7940,5,85,-1,0,0,16,10032,6485),(6485,-1,-1,7940,7940,7,85,-1,0,0,16,6484,6486),(6486,-1,-1,7940,7940,9,85,-1,0,0,16,6485,15320),(6487,1383,1383,1383,1383,12,85,21812,6,300,16,10014,14221),(6488,6488,6488,6488,6488,12,85,21806,32,900,16,-1,13383),(6489,-1,-1,6489,6489,5,81,-1,0,0,16,-1,6490),(6490,-1,-1,6489,6489,7,83,-1,0,0,16,6489,6491),(6491,-1,-1,6489,6489,9,85,-1,0,0,16,6490,17239),(6492,6492,6492,6492,6492,7,75,21692,52,720,16,-1,6493),(6493,6492,6492,6492,6492,7,77,21693,52,720,16,6492,6494),(6494,6492,6492,6492,6492,7,79,21694,52,720,16,6493,6495),(6495,6492,6492,6492,6492,7,81,21695,52,720,16,6494,6496),(6496,6492,6492,6492,6492,7,83,21696,52,720,16,6495,6497),(6497,6492,6492,6492,6492,7,85,21697,52,720,16,6496,10679),(6499,6499,6499,6499,6499,3,75,13512,13,60,14,-1,-1),(6500,-1,-1,4761,4761,7,76,-1,0,0,14,4763,6501),(6501,-1,-1,4761,4761,7,78,-1,0,0,14,6500,6502),(6502,-1,-1,4761,4761,7,80,-1,0,0,14,6501,-1),(6503,-1,-1,6503,6503,6,72,-1,0,0,14,-1,6504),(6504,-1,-1,6503,6503,6,72,-1,0,0,14,6503,6505),(6505,-1,-1,6503,6503,6,72,-1,0,0,14,6504,6506),(6506,-1,-1,6503,6503,6,72,-1,0,0,14,6505,-1),(6508,6508,6508,6508,6508,7,74,13195,38,600,14,-1,6509),(6509,6508,6508,6508,6508,7,76,13196,38,600,14,6508,6510),(6510,6508,6508,6508,6508,7,78,13197,38,600,14,6509,7387),(6511,-1,-1,6511,6511,6,73,-1,0,0,14,-1,6512),(6512,-1,-1,6511,6511,6,75,-1,0,0,14,6511,6513),(6513,-1,-1,6511,6511,6,77,-1,0,0,14,6512,-1),(6514,-1,-1,6514,6514,2,72,-1,0,0,14,-1,6515),(6515,-1,-1,6514,6514,2,72,-1,0,0,14,6514,6516),(6516,-1,-1,6514,6514,2,72,-1,0,0,14,6515,-1),(6517,-1,-1,1435,4773,9,76,-1,0,0,14,4773,7621),(6518,-1,-1,678,678,3,65,-1,0,0,14,682,6519),(6519,-1,-1,678,678,3,65,-1,0,0,14,6518,6520),(6520,-1,-1,678,678,3,65,-1,0,0,14,6519,7544),(6521,-1,-1,1021,1021,5,75,-1,0,0,14,1025,6522),(6522,-1,-1,1021,1021,5,80,-1,0,0,14,6521,7539),(6523,-1,-1,1026,1026,5,76,-1,0,0,14,4687,6524),(6524,-1,-1,1026,1026,5,77,-1,0,0,14,6523,6525),(6525,-1,-1,1026,1026,5,78,-1,0,0,14,6524,6526),(6526,-1,-1,1026,1026,5,79,-1,0,0,14,6525,6527),(6527,-1,-1,1026,1026,5,80,-1,0,0,14,6526,7511),(6528,-1,-1,501,501,5,96,-1,0,0,19,6321,6529),(6531,-1,-1,5295,5295,6,76,-1,0,0,14,5297,6532),(6532,-1,-1,5295,5295,6,78,-1,0,0,14,6531,6533),(6533,-1,-1,5295,5295,6,80,-1,0,0,14,6532,7220),(6534,8000,8000,8000,8000,12,90,23607,73,600,17,-1,14216),(6540,-1,-1,4699,4699,5,56,-1,0,0,14,4699,7500),(6545,-1,-1,4698,4698,5,56,-1,0,0,14,4698,-1),(6546,-1,-1,6546,6546,0,55,-1,0,0,3,-1,6547),(6547,-1,-1,6546,6546,0,56,-1,0,0,3,6546,6548),(6548,-1,-1,6546,6546,0,57,-1,0,0,3,6547,6549),(6549,-1,-1,6546,6546,0,58,-1,0,0,3,6548,6550),(6550,-1,-1,6546,6546,0,59,-1,0,0,3,6549,6551),(6551,-1,-1,6546,6546,0,60,-1,0,0,3,6550,6552),(6552,-1,-1,6546,6546,0,61,-1,0,0,3,6551,6553),(6553,-1,-1,6546,6546,0,62,-1,0,0,3,6552,6554),(6554,-1,-1,6546,6546,0,63,-1,0,0,3,6553,6555),(6555,-1,-1,6546,6546,0,64,-1,0,0,3,6554,6556),(6556,-1,-1,6546,6546,0,65,-1,0,0,3,6555,6557),(6557,-1,-1,6546,6546,0,66,-1,0,0,3,6556,6558),(6558,-1,-1,6546,6546,0,67,-1,0,0,3,6557,6559),(6559,-1,-1,6546,6546,0,68,-1,0,0,3,6558,6560),(6560,-1,-1,6546,6546,0,69,-1,0,0,3,6559,6561),(6561,-1,-1,6546,6546,0,70,-1,0,0,3,6560,6562),(6562,-1,-1,6546,6546,0,71,-1,0,0,3,6561,6563),(6563,-1,-1,6546,6546,0,72,-1,0,0,3,6562,6564),(6564,-1,-1,6546,6546,0,73,-1,0,0,3,6563,6565),(6565,-1,-1,6546,6546,0,74,-1,0,0,3,6564,6566),(6566,-1,-1,6546,6546,0,75,-1,0,0,3,6565,6567),(6567,-1,-1,6546,6546,0,76,-1,0,0,3,6566,6568),(6568,-1,-1,6546,6546,0,77,-1,0,0,3,6567,6569),(6569,-1,-1,6546,6546,0,78,-1,0,0,3,6568,6570),(6570,-1,-1,6546,6546,0,79,-1,0,0,3,6569,6571),(6571,-1,-1,6546,6546,0,80,-1,0,0,3,6570,7373),(6601,-1,-1,6601,6601,6,72,-1,0,0,14,-1,6602),(6602,-1,-1,6601,6601,6,73,-1,0,0,14,6601,6603),(6603,-1,-1,6601,6601,6,74,-1,0,0,14,6602,6604),(6604,-1,-1,6601,6601,6,75,-1,0,0,14,6603,6605),(6605,-1,-1,6601,6601,6,76,-1,0,0,14,6604,7318),(6606,1597,1597,1597,1597,9,75,16095,6,10,15,1597,10571),(6607,6607,6607,6607,6607,9,75,16092,61,600,15,-1,6608),(6608,6607,6607,6607,6607,9,80,16093,61,600,15,6607,6609),(6609,6607,6607,6607,6607,9,85,16094,61,600,15,6608,16324),(6610,6610,6610,6610,6610,2,55,16096,41,30,15,-1,10003),(6611,-1,-1,6611,6611,2,60,-1,0,0,15,-1,6612),(6612,-1,-1,6611,6611,4,63,-1,0,0,15,6611,6613),(6613,-1,-1,6611,6611,6,66,-1,0,0,15,6612,6618),(6614,-1,-1,6614,6614,2,60,-1,0,0,15,-1,6615),(6615,-1,-1,6614,6614,4,63,-1,0,0,15,6614,6616),(6616,-1,-1,6614,6614,6,66,-1,0,0,15,6615,10004),(6617,6617,6617,6617,6617,6,83,16097,42,3600,15,-1,10572),(6618,-1,-1,6611,6611,6,69,-1,0,0,15,6613,6619),(6619,-1,-1,6611,6611,6,72,-1,0,0,15,6618,10574),(6630,-1,-1,6630,6630,6,70,-1,0,0,15,-1,6631),(6631,-1,-1,6630,6630,6,70,-1,0,0,15,6630,6632),(6632,-1,-1,6630,6630,6,70,-1,0,0,15,6631,6633),(6633,-1,-1,6630,6630,6,70,-1,0,0,15,6632,6634),(6634,-1,-1,6630,6630,6,70,-1,0,0,15,6633,10070),(6635,6635,6635,6635,6635,7,70,16098,41,600,15,-1,-1),(6636,-1,-1,6636,6636,3,70,-1,0,0,15,-1,6637),(6637,-1,-1,6636,6636,6,70,-1,0,0,15,6636,6638),(6638,-1,-1,6636,6636,9,70,-1,0,0,15,6637,10041),(6639,6639,6639,6639,6639,7,70,16099,42,300,15,-1,15173),(6640,6640,6640,6640,6640,7,81,16100,43,60,15,-1,12585),(6641,-1,-1,6641,6641,7,81,-1,0,0,15,-1,6642),(6642,-1,-1,6641,6641,8,83,-1,0,0,15,6641,6643),(6643,-1,-1,6641,6641,9,85,-1,0,0,15,6642,10075),(6644,6644,6644,6644,6644,2,70,16104,44,20,15,-1,12586),(6645,6645,6645,6645,6645,6,80,16105,45,60,15,-1,13107),(6646,6646,6646,6646,6646,6,70,16106,46,6,15,-1,-1),(6660,-1,-1,1307,1307,5,73,-1,0,0,15,1311,6661),(6661,-1,-1,1307,1307,5,74,-1,0,0,15,6660,6662),(6662,-1,-1,1307,1307,5,75,-1,0,0,15,6661,13210),(6663,6663,6663,6663,6663,7,73,16107,59,600,15,-1,6664),(6664,6663,6663,6663,6663,7,75,16108,59,600,15,6663,6665),(6665,6663,6663,6663,6663,7,77,16109,59,600,15,6664,10162),(6666,-1,-1,6666,6666,8,81,-1,0,0,15,-1,6667),(6667,-1,-1,6666,6666,8,83,-1,0,0,15,6666,-1),(6668,-1,-1,6668,6668,3,76,-1,0,0,15,-1,6669),(6669,-1,-1,6668,6668,3,77,-1,0,0,15,6668,6670),(6670,-1,-1,6668,6668,3,78,-1,0,0,15,6669,-1),(6671,6671,6671,6671,6671,4,65,16148,60,60,15,-1,-1),(6672,6672,6672,6672,6672,4,67,16149,60,60,15,-1,-1),(6673,6673,6673,6673,6673,4,69,16150,60,60,15,-1,-1),(6674,6674,6674,6674,6674,4,71,16151,60,60,15,-1,-1),(6675,6675,6675,6675,6675,4,73,16152,60,60,15,-1,-1),(6676,6676,6676,6676,6676,4,75,16153,60,60,15,-1,-1),(6691,6691,6691,6691,6691,9,81,16114,41,30,15,-1,-1),(6692,6692,6692,6692,6692,7,65,16115,42,600,15,-1,6693),(6693,6692,6692,6692,6692,7,70,16116,42,600,15,6692,6694),(6694,6692,6692,6692,6692,7,75,16117,42,600,15,6693,6695),(6695,6692,6692,6692,6692,7,80,16118,42,600,15,6694,6696),(6696,6692,6692,6692,6692,7,85,16119,42,600,15,6695,5342),(6697,-1,-1,6697,6697,7,65,-1,0,0,15,-1,6698),(6698,-1,-1,6697,6697,7,70,-1,0,0,15,6697,6699),(6699,-1,-1,6697,6697,7,75,-1,0,0,15,6698,6700),(6700,-1,-1,6697,6697,7,80,-1,0,0,15,6699,6701),(6701,-1,-1,6697,6697,7,85,-1,0,0,15,6700,-1),(6702,6702,6702,6702,6702,9,75,16120,43,120,15,-1,-1),(6703,-1,-1,6703,6703,3,65,-1,0,0,15,-1,6704),(6704,-1,-1,6703,6703,3,65,-1,0,0,15,6703,6705),(6705,-1,-1,6703,6703,3,65,-1,0,0,15,6704,10176),(6706,6706,6706,6706,6706,7,75,16121,44,600,15,-1,6707),(6707,6706,6706,6706,6706,7,80,16122,44,600,15,6706,6708),(6708,6706,6706,6706,6706,7,85,16123,44,600,15,6707,10179),(6709,-1,-1,6709,6709,3,60,-1,0,0,15,-1,6710),(6710,-1,-1,6709,6709,3,61,-1,0,0,15,6709,6711),(6711,-1,-1,6709,6709,3,62,-1,0,0,15,6710,-1),(6712,-1,-1,6712,6712,7,65,-1,0,0,15,-1,6713),(6713,-1,-1,6712,6712,7,70,-1,0,0,15,6712,6714),(6714,-1,-1,6712,6712,7,75,-1,0,0,15,6713,6715),(6715,-1,-1,6712,6712,7,80,-1,0,0,15,6714,6716),(6716,-1,-1,6712,6712,7,85,-1,0,0,15,6715,10182),(6750,6750,6750,6750,6750,9,85,16127,60,120,15,-1,13899),(6751,-1,-1,6751,6751,6,75,-1,0,0,15,-1,6752),(6752,-1,-1,6751,6751,6,75,-1,0,0,15,6751,6753),(6753,-1,-1,6751,6751,6,75,-1,0,0,15,6752,6768),(6754,6754,6754,6754,6754,7,70,16130,41,1200,15,-1,10053),(6755,6755,6755,6755,6755,7,81,16131,42,900,15,-1,6756),(6756,6755,6755,6755,6755,9,83,16132,42,900,15,6755,6757),(6757,6755,6755,6755,6755,12,85,16133,42,900,15,6756,13542),(6758,6758,6758,6758,6758,3,81,16134,43,900,15,-1,6759),(6759,6758,6758,6758,6758,6,83,16135,43,900,15,6758,6760),(6760,6758,6758,6758,6758,9,85,16136,43,900,15,6759,10054),(6761,-1,-1,6761,6761,3,65,-1,0,0,15,-1,6762),(6762,-1,-1,6761,6761,6,65,-1,0,0,15,6761,6763),(6763,-1,-1,6761,6761,9,65,-1,0,0,15,6762,6085),(6764,6764,6764,6764,6764,7,75,16137,52,600,15,-1,10057),(6765,-1,-1,6765,6765,3,70,-1,0,0,15,-1,6766),(6766,-1,-1,6765,6765,6,75,-1,0,0,15,6765,6767),(6767,-1,-1,6765,6765,9,80,-1,0,0,15,6766,10058),(6768,-1,-1,6751,6751,6,75,-1,0,0,15,6753,6769),(6769,-1,-1,6751,6751,6,75,-1,0,0,15,6768,10769),(6791,-1,-1,6791,6791,6,75,-1,0,0,15,-1,6792),(6792,-1,-1,6791,6791,6,80,-1,0,0,15,6791,6793),(6793,-1,-1,6791,6791,6,85,-1,0,0,15,6792,10044),(6794,6794,6794,6794,6794,6,75,16142,41,60,15,-1,-1),(6815,6815,6815,6815,6815,8,75,16144,60,600,15,-1,6816),(6816,6815,6815,6815,6815,8,80,16145,60,600,15,6815,6817),(6817,6815,6815,6815,6815,8,85,16146,60,600,15,6816,10200),(6818,6818,6818,6818,6818,6,70,16147,44,20,15,-1,-1),(6819,-1,-1,6819,6819,6,72,-1,0,0,15,-1,6820),(6820,-1,-1,6819,6819,6,74,-1,0,0,15,6819,6821),(6821,-1,-1,6819,6819,6,76,-1,0,0,15,6820,10203),(6822,6822,6822,6822,6822,12,80,16154,42,120,15,-1,13683),(6823,-1,-1,6823,6823,4,65,-1,0,0,15,-1,6824),(6824,-1,-1,6823,6823,4,67,-1,0,0,15,6823,6825),(6825,-1,-1,6823,6823,4,69,-1,0,0,15,6824,6826),(6826,-1,-1,6823,6823,4,71,-1,0,0,15,6825,6827),(6827,-1,-1,6823,6823,4,73,-1,0,0,15,6826,10206),(6828,6828,6828,6828,6828,12,80,16155,43,60,15,-1,10208),(6870,-1,-1,6870,6870,6,75,-1,0,0,15,-1,6871),(6871,-1,-1,6870,6870,6,75,-1,0,0,15,6870,6872),(6872,-1,-1,6870,6870,6,75,-1,0,0,15,6871,10130),(6873,-1,-1,255,255,3,76,-1,0,0,15,-1,6874),(6874,-1,-1,255,255,6,76,-1,0,0,15,6873,6875),(6875,-1,-1,255,255,9,76,-1,0,0,15,6874,10133),(6876,-1,-1,6375,6375,6,76,-1,0,0,15,-1,6877),(6877,-1,-1,6375,6375,6,77,-1,0,0,15,6876,6878),(6878,-1,-1,6375,6375,6,78,-1,0,0,15,6877,10136),(6879,-1,-1,649,649,2,66,-1,0,0,15,-1,6880),(6880,-1,-1,649,649,4,68,-1,0,0,15,6879,6881),(6881,-1,-1,649,649,6,70,-1,0,0,15,6880,-1),(6882,-1,-1,776,776,3,70,-1,0,0,15,-1,6883),(6883,-1,-1,776,776,3,70,-1,0,0,15,6882,6884),(6884,-1,-1,776,776,3,70,-1,0,0,15,6883,-1),(6900,-1,-1,6935,6935,6,81,-1,0,0,16,6937,6901),(6901,-1,-1,6935,6935,6,82,-1,0,0,16,6900,6902),(6902,-1,-1,6935,6935,6,83,-1,0,0,16,6901,6903),(6903,-1,-1,6935,6935,6,84,-1,0,0,16,6902,6904),(6904,-1,-1,6935,6935,6,85,-1,0,0,16,6903,14196),(6905,-1,-1,551,551,5,81,-1,0,0,16,1637,6906),(6906,-1,-1,551,551,5,83,-1,0,0,16,6905,6907),(6907,-1,-1,551,551,5,85,-1,0,0,16,6906,12843),(6908,-1,-1,6908,6908,6,81,-1,0,0,16,-1,6909),(6909,-1,-1,6908,6908,6,83,-1,0,0,16,6908,6910),(6910,-1,-1,6908,6908,6,85,-1,0,0,16,6909,14199),(6911,-1,-1,1143,1143,5,65,-1,0,0,16,1168,6912),(6912,-1,-1,1143,1143,7,65,-1,0,0,16,6911,6913),(6913,-1,-1,1143,1143,9,65,-1,0,0,16,6912,-1),(6930,6930,6930,6930,6930,12,80,16156,13,60,15,-1,-1),(6931,6931,6931,6931,6931,12,85,16157,41,600,15,-1,10319),(6932,6932,6932,6932,6932,7,81,16158,42,1200,15,-1,6933),(6933,6932,6932,6932,6932,7,83,16159,42,1200,15,6932,6934),(6934,6932,6932,6932,6932,7,85,16160,42,1200,15,6933,10320),(6935,-1,-1,6935,6935,6,75,-1,0,0,15,-1,6936),(6936,-1,-1,6935,6935,6,77,-1,0,0,15,6935,6937),(6937,-1,-1,6935,6935,6,79,-1,0,0,15,6936,6900),(6938,-1,-1,6938,6938,7,81,-1,0,0,15,-1,6939),(6939,-1,-1,6938,6938,7,83,-1,0,0,15,6938,6940),(6940,-1,-1,6938,6938,7,85,-1,0,0,15,6939,-1),(6941,-1,-1,6941,6941,6,81,-1,0,0,15,-1,6942),(6942,-1,-1,6941,6941,6,81,-1,0,0,15,6941,6943),(6943,-1,-1,6941,6941,6,81,-1,0,0,15,6942,6944),(6944,-1,-1,6941,6941,6,81,-1,0,0,15,6943,6945),(6945,-1,-1,6941,6941,6,81,-1,0,0,15,6944,-1),(6970,6970,6970,6970,6970,6,70,16167,61,6,15,-1,-1),(6971,6971,6971,6971,6971,7,78,16168,41,600,15,-1,6972),(6972,6971,6971,6971,6971,7,80,16169,41,600,15,6971,6973),(6973,6971,6971,6971,6971,7,82,16170,41,600,15,6972,10288),(6974,-1,-1,6974,6974,5,81,-1,0,0,15,-1,6975),(6975,-1,-1,6974,6974,5,83,-1,0,0,15,6974,6976),(6976,-1,-1,6974,6974,5,85,-1,0,0,15,6975,10291),(6977,-1,-1,6977,6977,5,81,-1,0,0,15,-1,6978),(6978,-1,-1,6977,6977,5,83,-1,0,0,15,6977,6979),(6979,-1,-1,6977,6977,5,85,-1,0,0,15,6978,12840),(6980,-1,-1,6980,6980,5,81,-1,0,0,15,-1,6981),(6981,-1,-1,6980,6980,5,83,-1,0,0,15,6980,6982),(6982,-1,-1,6980,6980,5,85,-1,0,0,15,6981,12834),(6983,6983,6983,6983,6983,7,83,16439,66,720,15,-1,16246),(6984,6984,6984,6984,6984,6,73,16172,60,60,15,-1,10294),(6985,6985,6985,6985,6985,6,73,16173,60,60,15,-1,10295),(6986,6986,6986,6986,6986,6,73,16174,60,60,15,-1,10296),(6987,-1,-1,6987,6987,12,81,-1,0,0,15,-1,-1),(6988,-1,-1,6988,6988,5,83,0,0,0,16,-1,6989),(6989,-1,-1,6988,6988,5,84,0,0,0,16,6988,6990),(6990,-1,-1,6988,6988,5,83,0,0,0,16,6989,14278),(7000,7000,7000,7000,7000,4,65,12748,31,600,3,-1,-1),(7002,7002,7002,7002,7002,4,65,12750,31,600,3,-1,-1),(7003,7003,7003,7003,7003,4,65,12751,31,600,3,-1,-1),(7004,7004,7004,7004,7004,4,65,12752,31,300,3,-1,-1),(7005,-1,-1,7005,7005,2,73,-1,0,0,15,-1,7006),(7006,-1,-1,7005,7005,2,74,-1,0,0,15,7005,7007),(7007,-1,-1,7005,7005,2,75,-1,0,0,15,7006,15632),(7008,-1,-1,1604,1604,9,81,-1,0,0,16,7133,7009),(7009,-1,-1,1604,1604,12,83,-1,0,0,16,7008,12612),(7010,-1,-1,7010,7010,6,81,-1,0,0,16,-1,7011),(7011,-1,-1,7010,7010,6,83,-1,0,0,16,7010,7012),(7012,-1,-1,7010,7010,6,85,-1,0,0,16,7011,7013),(7013,-1,-1,7010,7010,6,85,-1,0,0,16,7012,7014),(7014,-1,-1,7010,7010,6,85,-1,0,0,16,7013,7015),(7015,-1,-1,7010,7010,6,85,-1,0,0,16,7014,13533),(7016,7016,7016,7016,7016,5,85,21658,31,600,3,-1,-1),(7017,7017,7017,7017,7017,5,85,21659,31,600,3,-1,-1),(7018,7018,7018,7018,7018,5,85,21660,31,600,3,-1,-1),(7019,7019,7019,7019,7019,5,85,21661,31,600,3,-1,-1),(7020,7020,7020,7020,7020,0,85,21658,31,600,3,-1,-1),(7021,7021,7021,7021,7021,0,85,21659,31,600,3,-1,-1),(7022,7022,7022,7022,7022,0,85,21660,31,600,3,-1,-1),(7023,7023,7023,7023,7023,0,85,21661,31,600,3,-1,-1),(7024,7024,7024,7024,7024,0,0,9475,31,600,12,-1,-1),(7025,7025,7025,7025,7025,0,0,9477,31,600,12,-1,-1),(7026,7026,7026,7026,7026,0,0,9478,31,600,12,-1,-1),(7027,7027,7027,7027,7027,0,0,9479,31,600,12,-1,-1),(7028,7028,7028,7028,7028,0,0,12748,31,600,3,-1,-1),(7030,7030,7030,7030,7030,0,0,12750,31,600,3,-1,-1),(7031,7031,7031,7031,7031,0,0,12751,31,600,3,-1,-1),(7032,7032,7032,7032,7032,0,0,12752,31,300,3,-1,-1),(7033,-1,-1,7033,7033,6,85,0,0,0,16,-1,7034),(7034,-1,-1,7033,7033,9,85,0,0,0,16,7033,7035),(7035,-1,-1,7033,7033,12,85,0,0,0,16,7034,15746),(7036,-1,-1,7036,7036,7,81,-1,0,0,16,-1,7037),(7037,-1,-1,7036,7036,9,81,-1,0,0,16,7036,7038),(7038,-1,-1,7036,7036,12,81,-1,0,0,16,7037,10579),(7050,-1,-1,446,735,5,67,-1,0,0,8,448,7051),(7051,-1,-1,446,735,5,68,-1,0,0,8,7050,7052),(7052,-1,-1,446,735,5,69,-1,0,0,8,7051,7053),(7053,-1,-1,446,735,7,72,-1,0,0,12,7052,7054),(7054,-1,-1,446,735,7,73,-1,0,0,12,7053,7055),(7055,-1,-1,446,735,7,74,-1,0,0,12,7054,7063),(7056,-1,-1,735,735,5,67,-1,0,0,8,737,7057),(7057,-1,-1,735,735,5,68,-1,0,0,8,7056,7058),(7058,-1,-1,735,735,5,69,-1,0,0,8,7057,7059),(7059,-1,-1,735,735,7,72,-1,0,0,12,7058,7060),(7060,-1,-1,735,735,7,73,-1,0,0,12,7059,7061),(7061,-1,-1,735,735,7,74,-1,0,0,12,7060,7066),(7062,-1,-1,7062,7062,3,51,-1,0,0,0,-1,-1),(7063,-1,-1,446,735,8,76,-1,0,0,14,7055,7064),(7064,-1,-1,446,735,8,77,-1,0,0,14,7063,7065),(7065,-1,-1,446,735,8,78,-1,0,0,14,7064,7622),(7066,-1,-1,735,735,8,76,-1,0,0,14,7061,7067),(7067,-1,-1,735,735,8,77,-1,0,0,14,7066,7068),(7068,-1,-1,735,735,8,78,-1,0,0,14,7067,7625),(7069,7069,7069,7069,7069,3,71,13219,39,7,14,-1,-1),(7100,-1,-1,7100,7100,6,76,-1,0,0,14,-1,7101),(7101,-1,-1,7100,7100,6,77,-1,0,0,14,7100,7102),(7102,-1,-1,7100,7100,6,78,-1,0,0,14,7101,7323),(7103,-1,-1,7103,7103,2,65,-1,0,0,14,-1,7104),(7104,-1,-1,7103,7103,2,65,-1,0,0,14,7103,7105),(7105,-1,-1,7103,7103,2,65,-1,0,0,14,7104,7326),(7106,-1,-1,7106,7106,6,73,-1,0,0,14,-1,7107),(7107,-1,-1,7106,7106,7,76,-1,0,0,14,7106,7108),(7108,-1,-1,7106,7106,10,79,-1,0,0,14,7107,-1),(7109,1351,1351,1351,1351,8,82,13499,5,30,15,6133,13109),(7110,4849,4849,4849,4849,7,81,13593,7,1800,15,6134,13914),(7111,54006,54006,54006,54006,7,81,13594,18,180,15,6135,10006),(7112,-1,-1,6564,6564,6,78,-1,0,0,15,6285,7113),(7113,-1,-1,6564,6564,7,81,-1,0,0,15,7112,7114),(7114,-1,-1,6564,6564,10,84,-1,0,0,15,7113,10007),(7115,6565,6565,6565,6565,7,81,13595,17,45,15,6286,10010),(7116,-1,-1,489,489,3,68,-1,0,0,15,491,7117),(7117,-1,-1,489,489,3,69,-1,0,0,15,7116,7118),(7118,-1,-1,489,489,3,70,-1,0,0,15,7117,-1),(7119,912,912,912,912,3,71,13496,4,3600,15,1332,7120),(7120,912,912,912,912,6,73,13497,4,3600,15,7119,7121),(7121,912,912,912,912,9,75,13498,4,3600,15,7120,10011),(7122,-1,-1,4844,4844,5,76,-1,0,0,15,4848,7123),(7123,-1,-1,4844,4844,5,77,-1,0,0,15,7122,7124),(7124,-1,-1,4844,4844,5,78,-1,0,0,15,7123,7125),(7125,-1,-1,4844,4844,5,79,-1,0,0,15,7124,7126),(7126,-1,-1,4844,4844,5,80,-1,0,0,15,7125,7686),(7127,4860,4860,4860,4860,12,85,13599,13,60,15,5606,-1),(7128,-1,-1,492,492,2,68,-1,0,0,15,494,7129),(7129,-1,-1,492,492,2,69,-1,0,0,15,7128,7130),(7130,-1,-1,492,492,2,70,-1,0,0,15,7129,10576),(7131,-1,-1,1604,1604,7,75,-1,0,0,15,6034,7132),(7132,-1,-1,1604,1604,9,77,-1,0,0,15,7131,7133),(7133,-1,-1,1604,1604,12,79,-1,0,0,15,7132,7008),(7134,-1,-1,1543,1543,7,81,-1,0,0,15,6044,7135),(7135,-1,-1,1543,1543,9,83,-1,0,0,15,7134,7136),(7136,-1,-1,1543,1543,12,85,-1,0,0,15,7135,10165),(7137,-1,-1,6559,6559,6,79,-1,0,0,15,6274,7138),(7138,-1,-1,6559,6559,7,81,-1,0,0,15,7137,7139),(7139,-1,-1,6559,6559,10,83,-1,0,0,15,7138,-1),(7143,6328,6328,6328,6328,7,79,13601,10,600,15,6330,7144),(7144,6328,6328,6328,6328,7,81,13602,10,600,15,7143,7145),(7145,6328,6328,6328,6328,7,83,13603,10,600,15,7144,10168),(7146,-1,-1,878,878,7,81,-1,0,0,15,6332,7147),(7147,-1,-1,878,878,7,83,-1,0,0,15,7146,10171),(7148,-1,-1,1304,1304,7,81,-1,0,0,15,6031,7149),(7149,-1,-1,1304,1304,9,83,-1,0,0,15,7148,7150),(7150,-1,-1,1304,1304,12,85,-1,0,0,15,7149,10865),(7151,-1,-1,846,846,7,81,-1,0,0,15,6037,7152),(7152,-1,-1,846,846,9,83,-1,0,0,15,7151,7153),(7153,-1,-1,846,846,12,85,-1,0,0,15,7152,10173),(7154,1352,1352,1352,1352,6,81,13613,3,60,15,6318,7155),(7155,1352,1352,1352,1352,6,83,13614,3,60,15,7154,7156),(7156,1352,1352,1352,1352,6,85,13615,3,60,15,7155,10113),(7157,1358,1358,1358,1358,6,81,13610,3,60,15,6312,7158),(7158,1358,1358,1358,1358,6,83,13611,3,60,15,7157,7159),(7159,1358,1358,1358,1358,6,85,13612,3,60,15,7158,10116),(7160,-1,-1,4801,4801,6,79,-1,0,0,15,4803,7161),(7161,-1,-1,4801,4801,6,81,-1,0,0,15,7160,7162),(7162,-1,-1,4801,4801,6,83,-1,0,0,15,7161,10122),(7163,-1,-1,820,820,5,81,-1,0,0,15,5919,7164),(7164,-1,-1,820,820,5,83,-1,0,0,15,7163,7165),(7165,-1,-1,820,820,5,85,-1,0,0,15,7164,10660),(7166,-1,-1,6343,6343,6,79,-1,0,0,15,6345,7167),(7167,-1,-1,6343,6343,6,81,-1,0,0,15,7166,7168),(7168,-1,-1,6343,6343,6,83,-1,0,0,15,7167,-1),(7169,-1,-1,6020,6020,2,81,-1,0,0,15,6059,7170),(7170,-1,-1,6020,6020,2,83,-1,0,0,15,7169,7171),(7171,-1,-1,6020,6020,2,85,-1,0,0,15,7170,10663),(7172,1355,1355,1355,1355,6,81,13607,3,60,15,5916,7173),(7173,1355,1355,1355,1355,6,83,13608,3,60,15,7172,7174),(7174,1355,1355,1355,1355,6,85,13609,3,60,15,7173,10119),(7175,-1,-1,611,611,2,68,-1,0,0,15,615,7176),(7176,-1,-1,611,611,2,69,-1,0,0,15,7175,7177),(7177,-1,-1,611,611,2,70,-1,0,0,15,7176,10124),(7178,4854,4854,4854,4854,7,81,13616,8,600,15,5766,7179),(7179,4854,4854,4854,4854,9,83,13617,8,600,15,7178,7180),(7180,4854,4854,4854,4854,12,85,13618,8,600,15,7179,10323),(7184,1348,1348,1348,1348,12,91,13622,0,3600,18,5772,7185),(7187,1178,1178,1178,1178,7,81,13625,4,900,15,5781,7188),(7188,1178,1178,1178,1178,8,82,13626,4,900,15,7187,7189),(7189,1178,1178,1178,1178,9,83,13627,4,900,15,7188,10326),(7196,-1,-1,5776,5776,7,81,-1,0,0,16,5778,7197),(7197,-1,-1,5776,5776,9,83,-1,0,0,16,7196,7198),(7198,-1,-1,5776,5776,12,85,-1,0,0,16,7197,13043),(7199,1274,1274,1274,1274,9,83,13657,9,540,15,5949,7200),(7200,1274,1274,1274,1274,10,84,13658,9,540,15,7199,7201),(7201,1274,1274,1274,1274,12,85,13659,9,540,15,7200,10209),(7202,1510,-1,1510,1510,12,75,13664,13,2160,15,1510,10212),(7203,184,184,184,184,10,84,13660,5,4320,15,5953,-1),(7204,-1,-1,5264,5264,7,81,-1,0,0,15,5943,7205),(7205,-1,-1,5264,5264,8,82,-1,0,0,15,7204,7206),(7206,-1,-1,5264,5264,9,83,-1,0,0,15,7205,7207),(7207,-1,-1,5264,5264,10,84,-1,0,0,15,7206,7208),(7208,-1,-1,5264,5264,12,85,-1,0,0,15,7207,10213),(7209,4927,4927,4927,4927,9,76,13656,14,600,15,4927,10218),(7210,-1,-1,839,839,6,75,-1,0,0,15,5329,7211),(7211,-1,-1,839,839,6,75,-1,0,0,15,7210,7212),(7212,-1,-1,839,839,6,75,-1,0,0,15,7211,7213),(7213,-1,-1,839,839,6,75,-1,0,0,15,7212,7214),(7214,-1,-1,839,839,6,75,-1,0,0,15,7213,10219),(7215,-1,-1,4861,4861,9,83,-1,0,0,15,5956,7216),(7216,-1,-1,4861,4861,12,85,-1,0,0,15,7215,7682),(7217,967,967,967,967,6,81,13661,10,1800,15,6466,7218),(7218,967,967,967,967,6,82,13662,10,1800,15,7217,7219),(7219,967,967,967,967,6,83,13663,10,1800,15,7218,10224),(7220,-1,-1,5295,5295,6,81,-1,0,0,15,6533,7221),(7221,-1,-1,5295,5295,6,83,-1,0,0,15,7220,7222),(7222,-1,-1,5295,5295,6,85,-1,0,0,15,7221,10227),(7223,6290,6290,6290,6290,7,81,13689,0,1,15,6295,7224),(7224,6290,6290,6290,6290,9,83,13690,0,1,15,7223,7225),(7225,6290,6290,6290,6290,12,85,13691,0,1,15,7224,11064),(7226,619,619,619,619,6,78,13686,6,900,15,6298,7227),(7227,619,619,619,619,6,78,13687,6,900,15,7226,7228),(7228,619,619,619,619,6,78,13688,6,900,15,7227,10230),(7229,4944,-1,4944,4944,7,81,13677,0,1,15,6157,7230),(7230,4944,-1,4944,4944,9,83,13678,0,1,15,7229,7231),(7231,4944,-1,4944,4944,12,85,13679,0,1,15,7230,11067),(7232,-1,-1,1210,1210,7,81,-1,0,0,15,5576,7233),(7233,-1,-1,1210,1210,9,83,-1,0,0,15,7232,7234),(7234,-1,-1,1210,1210,12,85,-1,0,0,15,7233,12523),(7235,923,923,923,923,9,82,13673,8,60,15,6151,-1),(7236,922,922,922,922,9,83,13672,8,60,15,6150,-1),(7237,516,516,516,516,6,77,13692,5,480,15,6398,10233),(7238,155,155,155,155,12,82,13693,8,60,15,5289,14324),(7239,1334,1334,1334,1334,9,83,13674,11,4320,15,6154,7240),(7240,1334,1334,1334,1334,10,84,13675,11,4320,15,7239,7241),(7241,1334,1334,1334,1334,12,85,13676,11,4320,15,7240,10234),(7242,1478,-1,1478,1478,9,83,13680,0,1,15,6163,7243),(7243,1478,-1,1478,1478,10,84,13681,0,1,15,7242,7244),(7244,1478,-1,1478,1478,12,85,13682,0,1,15,7243,11070),(7245,921,921,921,921,9,84,13671,8,60,15,6149,-1),(7246,4915,4915,4915,4915,7,81,13683,7,4320,15,5609,7247),(7247,4915,4915,4915,4915,9,83,13684,7,4320,15,7246,7248),(7248,4915,4915,4915,4915,12,85,13685,7,4320,15,7247,-1),(7249,167,167,167,167,10,84,13703,14,900,15,5879,8343),(7250,520,520,520,520,12,81,13704,6,540,15,5885,7251),(7251,520,520,520,520,12,83,13705,6,540,15,7250,7252),(7252,520,520,520,520,12,85,13706,6,540,15,7251,10252),(7253,4903,4903,4903,4903,9,81,13707,9,1320,15,5892,10255),(7254,4906,4906,4906,4906,9,81,13708,9,1320,15,5893,10256),(7255,4909,4909,4909,4909,9,81,13709,16,1320,15,5894,10257),(7256,4912,4912,4912,4912,9,81,13710,16,1320,15,5895,10258),(7257,616,616,616,616,6,78,13711,7,900,15,6256,7258),(7258,616,616,616,616,7,81,13712,7,900,15,7257,7259),(7259,616,616,616,616,10,84,13713,7,900,15,7258,10259),(7260,-1,-1,1504,1504,5,81,-1,0,0,15,5882,7261),(7261,-1,-1,1504,1504,5,83,-1,0,0,15,7260,7262),(7262,-1,-1,1504,1504,5,85,-1,0,0,15,7261,-1),(7263,-1,-1,1577,1577,7,81,-1,0,0,15,5888,7264),(7264,-1,-1,1577,1577,9,83,-1,0,0,15,7263,7265),(7265,-1,-1,1577,1577,12,85,-1,0,0,15,7264,10262),(7266,6333,6333,6333,6333,6,64,13714,3,600,15,6333,13920),(7267,-1,-1,795,795,7,81,-1,0,0,15,5891,7268),(7268,-1,-1,795,795,9,83,-1,0,0,15,7267,7269),(7269,-1,-1,795,795,12,85,-1,0,0,15,7268,10265),(7270,-1,-1,790,790,6,81,-1,0,0,15,5324,7271),(7271,-1,-1,790,790,6,82,-1,0,0,15,7270,7272),(7272,-1,-1,790,790,6,83,-1,0,0,15,7271,7273),(7273,-1,-1,790,790,6,84,-1,0,0,15,7272,7274),(7274,-1,-1,790,790,6,85,-1,0,0,15,7273,12950),(7275,1239,1239,1239,1239,12,85,13735,6,600,15,5868,13251),(7276,773,-1,773,773,7,81,13726,5,1800,15,5856,7277),(7277,773,-1,773,773,9,83,13727,5,1800,15,7276,7278),(7278,773,-1,773,773,12,85,13728,5,1800,15,7277,10564),(7279,6552,6552,6552,6552,5,75,-1,0,0,15,6253,7280),(7280,6552,6552,6552,6552,6,77,-1,0,0,15,7279,7281),(7281,6552,6552,6552,6552,6,79,-1,0,0,15,7280,7282),(7282,6552,6552,6552,6552,7,81,-1,0,0,15,7281,7283),(7283,6552,6552,6552,6552,9,83,-1,0,0,15,7282,-1),(7284,-1,-1,781,781,8,82,-1,0,0,15,5850,13763),(7285,1242,1242,1242,1242,7,81,13723,9,1320,15,5859,7286),(7286,1242,1242,1242,1242,9,83,13724,9,1320,15,7285,7287),(7287,1242,1242,1242,1242,12,85,13725,9,1320,15,7286,10271),(7288,4894,4894,4894,4894,6,81,13732,7,2160,15,6354,7289),(7289,4894,4894,4894,4894,6,82,13733,7,2160,15,7288,7290),(7290,4894,4894,4894,4894,6,83,13734,7,2160,15,7289,13247),(7291,4931,4931,4931,4931,7,81,13729,4,600,15,6056,7292),(7292,4931,4931,4931,4931,7,83,13730,4,600,15,7291,7293),(7293,4931,4931,4931,4931,7,85,13731,4,600,15,7292,10274),(7294,4935,4935,4935,4935,7,76,13722,14,300,15,4935,10277),(7295,4934,4934,4934,4934,7,76,13721,13,300,15,4934,10278),(7296,517,517,517,517,5,73,13718,12,600,15,1444,7297),(7297,517,517,517,517,5,74,13719,12,600,15,7296,7298),(7298,517,517,517,517,5,75,13720,12,600,15,7297,10279),(7299,1383,1383,1383,1383,12,85,16000,6,300,15,5789,10014),(7300,1195,1195,1195,1195,9,85,16001,13,2160,15,5790,10015),(7301,131,131,131,131,8,82,16002,4,900,15,5793,7302),(7302,131,131,131,131,9,83,16003,4,900,15,7301,7303),(7303,131,131,131,131,10,84,16004,4,900,15,7302,10016),(7304,1192,1192,1192,1192,8,82,16005,12,1320,15,5796,7305),(7305,1192,1192,1192,1192,9,83,16006,12,1320,15,7304,7306),(7306,1192,1192,1192,1192,10,84,16007,12,1320,15,7305,10019),(7307,746,746,746,746,9,83,16008,10,2160,15,5802,7308),(7308,746,746,746,746,10,84,16009,10,2160,15,7307,7309),(7309,746,746,746,746,12,85,16010,10,2160,15,7308,10022),(7310,1459,1459,1459,1459,7,81,16011,11,1800,15,5805,7311),(7311,1459,1459,1459,1459,9,83,16012,11,1800,15,7310,7312),(7312,1459,1459,1459,1459,12,85,16013,11,1800,15,7311,-1),(7313,-1,-1,6436,6436,6,78,-1,0,0,15,6438,7314),(7314,-1,-1,6436,6436,6,80,-1,0,0,15,7313,7315),(7315,-1,-1,6436,6436,8,82,-1,0,0,15,7314,-1),(7316,-1,-1,468,468,2,72,-1,0,0,15,6440,7317),(7317,-1,-1,468,468,2,74,-1,0,0,15,7316,17288),(7318,-1,-1,6601,6601,6,77,-1,0,0,15,6605,7319),(7319,-1,-1,6601,6601,6,78,-1,0,0,15,7318,7320),(7320,-1,-1,6601,6601,6,79,-1,0,0,15,7319,7321),(7321,-1,-1,6601,6601,6,80,-1,0,0,15,7320,7322),(7322,-1,-1,6601,6601,6,81,-1,0,0,15,7321,10025),(7323,-1,-1,7100,7100,6,81,-1,0,0,15,7102,7324),(7324,-1,-1,7100,7100,6,82,-1,0,0,15,7323,7325),(7325,-1,-1,7100,7100,6,83,-1,0,0,15,7324,8427),(7326,-1,-1,7103,7103,2,70,-1,0,0,15,7105,7327),(7327,-1,-1,7103,7103,2,70,-1,0,0,15,7326,7328),(7328,-1,-1,7103,7103,2,70,-1,0,0,15,7327,10750),(7329,534,534,534,534,7,81,16021,4,2160,15,5971,7330),(7330,534,534,534,534,9,83,16022,4,2160,15,7329,7331),(7331,534,534,534,534,12,85,16023,4,2160,15,7330,10047),(7332,5095,5095,5095,5095,7,81,16024,10,900,15,5977,7333),(7333,5095,5095,5095,5095,9,83,16025,10,900,15,7332,7334),(7334,5095,5095,5095,5095,12,85,16026,10,900,15,7333,10640),(7335,5984,5984,5984,5984,12,85,16027,2,30,15,5984,7710),(7336,-1,-1,6395,6395,7,81,-1,0,0,15,6397,7337),(7337,-1,-1,6395,6395,7,82,-1,0,0,15,7336,7338),(7338,-1,-1,6395,6395,7,83,-1,0,0,15,7337,10050),(7339,188,188,188,188,9,78,16020,2,30,14,5044,7662),(7340,7850,7850,7850,7850,8,81,16028,39,4320,0,7865,10618),(7341,5007,5007,5007,5007,9,81,16047,8,2160,15,6427,7342),(7342,5007,5007,5007,5007,9,83,16048,8,2160,15,7341,7343),(7343,5007,5007,5007,5007,9,85,16049,8,2160,15,7342,10061),(7344,545,545,545,545,7,81,16038,3,900,15,6002,7345),(7345,545,545,545,545,9,83,16039,3,900,15,7344,7346),(7346,545,545,545,545,12,85,16040,3,900,15,7345,10758),(7347,1345,1345,1345,1345,8,82,16041,6,900,15,6010,7348),(7348,1345,1345,1345,1345,9,83,16042,6,900,15,7347,7349),(7349,1345,1345,1345,1345,10,84,16043,6,900,15,7348,10740),(7350,6370,6370,6370,6370,6,81,16044,7,600,15,6372,7351),(7351,6370,6370,6370,6370,6,82,16045,7,600,15,7350,7352),(7352,6370,6370,6370,6370,6,83,16046,7,600,15,7351,14112),(7353,-1,-1,864,864,6,85,-1,0,0,15,6013,7354),(7354,-1,-1,864,864,6,85,-1,0,0,15,7353,7355),(7355,-1,-1,864,864,6,85,-1,0,0,15,7354,-1),(7356,-1,-1,5248,5248,7,81,-1,0,0,15,6016,7357),(7357,-1,-1,5248,5248,9,83,-1,0,0,15,7356,7358),(7358,-1,-1,5248,5248,12,85,-1,0,0,15,7357,16170),(7359,-1,-1,644,644,7,79,-1,0,0,15,6019,7360),(7360,-1,-1,644,644,9,81,-1,0,0,15,7359,7361),(7361,-1,-1,644,644,12,83,-1,0,0,15,7360,13092),(7362,-1,-1,867,867,5,70,-1,0,0,15,871,7363),(7363,-1,-1,867,867,5,70,-1,0,0,15,7362,7364),(7364,-1,-1,867,867,5,70,-1,0,0,15,7363,7365),(7365,-1,-1,867,867,5,70,-1,0,0,15,7364,7366),(7366,-1,-1,867,867,5,70,-1,0,0,15,7365,10748),(7367,872,872,872,872,3,70,16032,5,180,15,874,7368),(7368,872,872,872,872,6,70,16033,5,180,15,7367,7369),(7369,872,872,872,872,9,70,16034,5,180,15,7368,10772),(7370,875,875,875,875,3,70,16035,5,180,15,877,7371),(7371,875,875,875,875,6,73,16036,5,180,15,7370,7372),(7372,875,875,875,875,9,75,16037,5,180,15,7371,10775),(7373,-1,-1,6546,6546,0,81,-1,0,0,15,6571,7374),(7374,-1,-1,6546,6546,0,82,-1,0,0,15,7373,7375),(7375,-1,-1,6546,6546,0,83,-1,0,0,15,7374,7376),(7376,-1,-1,6546,6546,0,84,-1,0,0,15,7375,7377),(7377,-1,-1,6546,6546,0,85,-1,0,0,15,7376,13122),(7378,-1,-1,1608,1608,3,71,-1,0,0,15,4991,7379),(7379,-1,-1,1608,1608,6,73,-1,0,0,15,7378,7380),(7380,-1,-1,1608,1608,9,75,-1,0,0,15,7379,7381),(7381,-1,-1,1608,1608,6,76,-1,0,0,15,7380,7382),(7382,-1,-1,1608,1608,6,78,-1,0,0,15,7381,7383),(7383,-1,-1,1608,1608,6,80,-1,0,0,15,7382,10064),(7384,-1,-1,5085,5085,6,81,-1,0,0,15,6408,7385),(7385,-1,-1,5085,5085,6,83,-1,0,0,15,7384,7386),(7386,-1,-1,5085,5085,6,85,-1,0,0,15,7385,10383),(7387,6508,6508,6508,6508,7,79,16059,38,600,15,6510,7388),(7388,6508,6508,6508,6508,7,81,16060,38,600,15,7387,7389),(7389,6508,6508,6508,6508,7,83,16061,38,600,15,7388,10078),(7390,-1,-1,589,589,7,81,-1,0,0,15,6065,7391),(7391,-1,-1,589,589,7,83,-1,0,0,15,7390,7392),(7392,-1,-1,589,589,7,85,-1,0,0,15,7391,7707),(7393,-1,-1,1313,1313,7,81,-1,0,0,15,6071,7394),(7394,-1,-1,1313,1313,7,81,-1,0,0,15,7393,7395),(7395,-1,-1,1313,1313,8,82,-1,0,0,15,7394,7396),(7396,-1,-1,1313,1313,9,83,-1,0,0,15,7395,7397),(7397,-1,-1,1313,1313,10,84,-1,0,0,15,7396,7398),(7398,-1,-1,1313,1313,12,85,-1,0,0,15,7397,10081),(7399,-1,-1,210,210,8,82,-1,0,0,15,6074,7400),(7400,-1,-1,210,210,9,83,-1,0,0,15,7399,7401),(7401,-1,-1,210,210,10,84,-1,0,0,15,7400,15172),(7402,-1,-1,895,895,7,81,-1,0,0,15,6079,7403),(7403,-1,-1,895,895,8,82,-1,0,0,15,7402,7404),(7404,-1,-1,895,895,9,83,-1,0,0,15,7403,7405),(7405,-1,-1,895,895,10,84,-1,0,0,15,7404,7406),(7406,-1,-1,895,895,12,85,-1,0,0,15,7405,10906),(7407,-1,-1,7407,7407,12,85,0,0,0,16,-1,-1),(7408,1498,1498,1498,1498,7,81,16075,12,1320,15,5821,7409),(7409,1498,1498,1498,1498,9,83,16076,12,1320,15,7408,7410),(7410,1498,1498,1498,1498,12,85,16077,12,1320,15,7409,10090),(7411,757,-1,757,757,7,81,16078,6,1800,15,5824,7412),(7412,757,-1,757,757,9,83,16079,6,1800,15,7411,7413),(7413,757,-1,757,757,12,85,16080,6,1800,15,7412,12658),(7414,1495,1495,1495,1495,7,81,16081,30,900,15,5828,7415),(7415,1495,1495,1495,1495,9,83,16082,30,900,15,7414,7416),(7416,1495,1495,1495,1495,12,85,16083,30,900,15,7415,10093),(7417,548,548,548,548,8,82,16084,5,900,15,5831,7418),(7418,548,548,548,548,9,83,16085,5,900,15,7417,7419),(7419,548,548,548,548,10,84,16086,5,900,15,7418,10096),(7420,5105,5105,5105,5105,12,85,16087,11,600,15,5832,10509),(7421,6232,6232,6232,6232,12,85,16091,18,900,15,6232,-1),(7422,6561,6561,6561,6561,7,81,16088,32,30,15,6280,7423),(7423,6561,6561,6561,6561,7,81,16089,32,30,15,7422,7424),(7424,6561,6561,6561,6561,7,81,16090,32,30,15,7423,10099),(7425,510,510,510,510,3,66,16072,37,240,15,512,7426),(7426,510,510,510,510,3,68,16073,37,240,15,7425,7427),(7427,510,510,510,510,3,70,16074,37,240,15,7426,10102),(7428,6533,6533,6533,6533,10,84,13785,15,600,15,6200,10139),(7429,6534,6534,6534,6534,9,83,13777,16,900,15,6201,13524),(7430,1116,1116,1116,1116,7,81,13762,4,2160,15,5701,7431),(7431,1116,1116,1116,1116,9,83,13763,4,2160,15,7430,7432),(7432,1116,1116,1116,1116,12,85,13764,4,2160,15,7431,10140),(7433,592,592,592,592,5,81,13765,2,18,15,5706,7434),(7434,592,592,592,592,5,82,13766,2,18,15,7433,7435),(7435,592,592,592,592,5,83,13767,2,18,15,7434,7436),(7436,592,592,592,592,5,84,13768,2,18,15,7435,7437),(7437,592,592,592,592,5,85,13769,2,18,15,7436,12749),(7438,5298,5298,5298,5298,9,83,13770,32,1800,15,5709,7439),(7439,5298,5298,5298,5298,10,84,13771,32,1800,15,7438,7440),(7440,5298,5298,5298,5298,12,85,13772,32,1800,15,7439,10143),(7441,1598,-1,1598,1598,7,81,13773,6,900,15,5712,7442),(7442,1598,-1,1598,1598,9,83,13774,6,900,15,7441,7443),(7443,1598,-1,1598,1598,12,85,13775,6,900,15,7442,10146),(7444,5020,5020,5020,5020,9,82,13776,9,300,15,5716,10149),(7445,1110,1110,1110,1110,6,78,13778,3,2160,15,6402,7446),(7446,1110,1110,1110,1110,6,80,13779,3,2160,15,7445,7447),(7447,1110,1110,1110,1110,6,81,13780,3,2160,15,7446,10150),(7448,-1,-1,6337,6337,6,79,-1,0,0,15,6339,7449),(7449,-1,-1,6337,6337,6,81,-1,0,0,15,7448,7450),(7450,-1,-1,6337,6337,6,83,-1,0,0,15,7449,10153),(7451,-1,-1,6340,6340,6,79,-1,0,0,15,6342,7452),(7452,-1,-1,6340,6340,6,81,-1,0,0,15,7451,7453),(7453,-1,-1,6340,6340,6,83,-1,0,0,15,7452,16306),(7454,5017,5017,5017,5017,3,76,13759,8,600,15,5019,7455),(7455,5017,5017,5017,5017,6,78,13760,8,600,15,7454,7456),(7456,5017,5017,5017,5017,9,80,13761,8,600,15,7455,10156),(7457,1569,1569,1569,1569,7,82,13756,5,1800,15,5715,7458),(7458,1569,1569,1569,1569,7,83,13757,5,1800,15,7457,7459),(7459,1569,1569,1569,1569,7,85,13758,5,1800,15,7458,10159),(7460,1327,1327,1327,1327,7,81,13792,10,900,15,6100,7461),(7461,1327,1327,1327,1327,9,83,13793,10,900,15,7460,7462),(7462,1327,1327,1327,1327,12,85,13794,10,900,15,7461,10187),(7463,1520,1520,1520,1520,9,75,13801,11,900,15,6451,7464),(7464,1520,1520,1520,1520,9,75,13802,11,900,15,7463,7465),(7465,1520,1520,1520,1520,9,75,13803,11,900,15,7464,10190),(7466,146,146,146,146,8,82,13796,2,180,15,6102,7691),(7467,5109,5109,5109,5109,9,82,13800,0,1,15,6448,13016),(7468,153,153,153,153,12,85,13795,3,2160,15,6101,10193),(7469,528,528,528,528,7,81,13797,5,720,15,6105,7470),(7470,528,528,528,528,9,83,13798,5,720,15,7469,7471),(7471,528,528,528,528,12,85,13799,5,720,15,7470,10194),(7472,5251,5251,5251,5251,7,81,13786,13,900,15,6094,7473),(7473,5251,5251,5251,5251,9,83,13787,13,900,15,7472,7474),(7474,5251,5251,5251,5251,12,85,13788,13,900,15,7473,10197),(7475,513,513,513,513,7,81,13789,4,120,15,6097,7476),(7476,513,513,513,513,9,83,13790,4,120,15,7475,7477),(7477,513,513,513,513,12,85,13791,4,120,15,7476,-1),(7478,-1,-1,6538,6538,12,85,-1,0,0,15,6211,15421),(7479,1119,1119,1119,1119,7,83,13805,8,900,15,5736,7480),(7480,1119,1119,1119,1119,8,84,13806,8,900,15,7479,7481),(7481,1119,1119,1119,1119,9,85,13807,8,900,15,7480,10297),(7482,723,723,723,723,7,81,13808,6,30,15,5737,10300),(7483,5015,5015,5015,5015,12,85,13809,9,900,15,5741,10301),(7484,289,289,289,289,12,85,13810,3,300,15,5742,-1),(7485,291,291,291,291,9,83,13811,5,900,15,5745,7486),(7486,291,291,291,291,10,84,13812,5,900,15,7485,7487),(7487,291,291,291,291,12,85,13813,5,900,15,7486,10302),(7488,6218,6218,6218,6218,7,81,13814,0,1,15,6218,14272),(7489,-1,-1,724,724,7,81,-1,0,0,15,5733,7490),(7490,-1,-1,724,724,8,82,-1,0,0,15,7489,7491),(7491,-1,-1,724,724,9,83,-1,0,0,15,7490,7492),(7492,-1,-1,724,724,10,84,-1,0,0,15,7491,7493),(7493,-1,-1,724,724,12,85,-1,0,0,15,7492,16890),(7494,-1,-1,729,729,7,81,-1,0,0,15,5740,7495),(7495,-1,-1,729,729,8,82,-1,0,0,15,7494,7496),(7496,-1,-1,729,729,9,83,-1,0,0,15,7495,10305),(7497,6380,6380,6380,6380,6,83,13815,39,120,15,6382,7498),(7498,6380,6380,6380,6380,6,84,13816,39,120,15,7497,7499),(7499,6380,6380,6380,6380,6,85,13817,39,120,15,7498,10308),(7500,-1,-1,4699,4699,5,61,-1,0,0,15,6540,10788),(7501,-1,-1,125,125,6,81,-1,0,0,15,5523,7502),(7502,-1,-1,125,125,7,82,-1,0,0,15,7501,7503),(7503,-1,-1,125,125,8,83,-1,0,0,15,7502,7504),(7504,-1,-1,125,125,9,84,-1,0,0,15,7503,7505),(7505,-1,-1,125,125,10,85,-1,0,0,15,7504,12396),(7506,-1,-1,122,122,6,81,-1,0,0,15,5528,7507),(7507,-1,-1,122,122,7,82,-1,0,0,15,7506,7508),(7508,-1,-1,122,122,8,83,-1,0,0,15,7507,7509),(7509,-1,-1,122,122,9,84,-1,0,0,15,7508,7510),(7510,-1,-1,122,122,10,85,-1,0,0,15,7509,12401),(7511,-1,-1,1026,1026,5,81,-1,0,0,15,6527,7512),(7512,-1,-1,1026,1026,5,82,-1,0,0,15,7511,7513),(7513,-1,-1,1026,1026,5,83,-1,0,0,15,7512,7514),(7514,-1,-1,1026,1026,5,84,-1,0,0,15,7513,7515),(7515,-1,-1,1026,1026,5,85,-1,0,0,15,7514,7886),(7516,-1,-1,1006,1006,5,71,-1,0,0,15,1010,7517),(7517,-1,-1,1006,1006,5,72,-1,0,0,15,7516,7518),(7518,-1,-1,1006,1006,5,73,-1,0,0,15,7517,7519),(7519,-1,-1,1006,1006,5,74,-1,0,0,15,7518,7520),(7520,-1,-1,1006,1006,5,75,-1,0,0,15,7519,7837),(7521,-1,-1,1056,1056,5,81,-1,0,0,15,6435,7522),(7522,-1,-1,1056,1056,5,82,-1,0,0,15,7521,7523),(7523,-1,-1,1056,1056,5,83,-1,0,0,15,7522,7524),(7524,-1,-1,1056,1056,5,84,-1,0,0,15,7523,7525),(7525,-1,-1,1056,1056,5,85,-1,0,0,15,7524,16414),(7526,-1,-1,6119,6119,6,81,-1,0,0,15,6123,7527),(7527,-1,-1,6119,6119,6,82,-1,0,0,15,7526,7528),(7528,-1,-1,6119,6119,6,83,-1,0,0,15,7527,7529),(7529,-1,-1,6119,6119,6,84,-1,0,0,15,7528,7530),(7530,-1,-1,6119,6119,6,85,-1,0,0,15,7529,12406),(7534,-1,-1,65,661,3,81,-1,0,0,15,6394,7535),(7535,-1,-1,65,661,3,82,-1,0,0,15,7534,7536),(7536,-1,-1,65,661,3,83,-1,0,0,15,7535,7537),(7537,-1,-1,65,661,3,84,-1,0,0,15,7536,7538),(7538,-1,-1,65,661,3,85,-1,0,0,15,7537,7904),(7539,-1,-1,1021,1021,5,80,-1,0,0,16,6522,7540),(7540,-1,-1,1021,1021,5,85,-1,0,0,16,7539,7683),(7541,-1,-1,107,107,2,60,-1,0,0,15,109,7542),(7542,-1,-1,107,107,4,60,-1,0,0,15,7541,7543),(7543,-1,-1,107,107,6,60,-1,0,0,15,7542,-1),(7544,-1,-1,678,678,3,70,-1,0,0,15,6520,7545),(7545,-1,-1,678,678,3,70,-1,0,0,15,7544,7546),(7546,-1,-1,678,678,3,70,-1,0,0,15,7545,-1),(7547,-1,-1,418,418,5,76,-1,0,0,15,4682,7548),(7548,-1,-1,418,418,5,77,-1,0,0,15,7547,7549),(7549,-1,-1,418,418,5,78,-1,0,0,15,7548,7550),(7550,-1,-1,418,418,5,79,-1,0,0,15,7549,7551),(7551,-1,-1,418,418,5,80,-1,0,0,15,7550,-1),(7553,-1,-1,1071,1071,6,80,-1,0,0,16,4764,7681),(7554,-1,-1,1486,1486,7,81,-1,0,0,15,5533,7555),(7555,-1,-1,1486,1486,8,82,-1,0,0,15,7554,7556),(7556,-1,-1,1486,1486,9,83,-1,0,0,15,7555,7557),(7557,-1,-1,1486,1486,10,84,-1,0,0,15,7556,7558),(7558,-1,-1,1486,1486,12,85,-1,0,0,15,7557,7722),(7559,-1,-1,599,599,9,83,-1,0,0,15,5536,7560),(7560,-1,-1,599,599,10,84,-1,0,0,15,7559,7561),(7561,-1,-1,599,599,12,85,-1,0,0,15,7560,13026),(7562,-1,-1,1041,1041,7,81,-1,0,0,15,5544,7563),(7563,-1,-1,1041,1041,9,83,-1,0,0,15,7562,7564),(7564,-1,-1,1041,1041,12,85,-1,0,0,15,7563,12697),(7565,-1,-1,119,119,7,81,-1,0,0,15,5556,7566),(7566,-1,-1,119,119,9,83,-1,0,0,15,7565,7567),(7567,-1,-1,119,119,12,85,-1,0,0,15,7566,6023),(7568,-1,-1,1592,1592,7,81,-1,0,0,15,5561,7569),(7569,-1,-1,1592,1592,8,82,-1,0,0,15,7568,7570),(7570,-1,-1,1592,1592,9,83,-1,0,0,15,7569,7571),(7571,-1,-1,1592,1592,10,84,-1,0,0,15,7570,7572),(7572,-1,-1,1592,1592,12,85,-1,0,0,15,7571,12439),(7573,-1,-1,4739,4739,7,81,-1,0,0,15,5564,7574),(7574,-1,-1,4739,4739,9,83,-1,0,0,15,7573,7575),(7575,-1,-1,4739,4739,12,85,-1,0,0,15,7574,-1),(7576,-1,-1,1072,1072,7,81,-1,0,0,15,5570,7577),(7577,-1,-1,1072,1072,8,82,-1,0,0,15,7576,7578),(7578,-1,-1,1072,1072,9,83,-1,0,0,15,7577,7579),(7579,-1,-1,1072,1072,10,84,-1,0,0,15,7578,7580),(7580,-1,-1,1072,1072,12,85,-1,0,0,15,7579,12444),(7581,-1,-1,1210,1213,7,81,-1,0,0,15,5579,7582),(7582,-1,-1,1210,1213,9,83,-1,0,0,15,7581,7583),(7583,-1,-1,1210,1213,12,85,-1,0,0,15,7582,8344),(7584,-1,-1,98,98,7,81,-1,0,0,15,5588,7585),(7585,-1,-1,98,98,9,83,-1,0,0,15,7584,7586),(7586,-1,-1,98,98,12,85,-1,0,0,15,7585,11061),(7587,-1,-1,1186,1186,7,81,-1,0,0,15,5591,7588),(7588,-1,-1,1186,1186,9,83,-1,0,0,15,7587,7589),(7589,-1,-1,1186,1186,12,85,-1,0,0,15,7588,7692),(7590,-1,-1,80,80,7,81,-1,0,0,15,5594,7591),(7591,-1,-1,80,80,9,83,-1,0,0,15,7590,7592),(7592,-1,-1,80,80,12,85,-1,0,0,15,7591,12452),(7593,-1,-1,658,658,5,81,-1,0,0,15,5627,7594),(7594,-1,-1,658,658,5,82,-1,0,0,15,7593,7595),(7595,-1,-1,658,658,5,83,-1,0,0,15,7594,7596),(7596,-1,-1,658,658,5,84,-1,0,0,15,7595,7597),(7597,-1,-1,658,658,5,85,-1,0,0,15,7596,12455),(7598,-1,-1,98,738,7,81,-1,0,0,15,5630,7599),(7599,-1,-1,98,738,9,83,-1,0,0,15,7598,7600),(7600,-1,-1,98,738,12,85,-1,0,0,15,7599,13924),(7601,-1,-1,6051,6051,3,81,-1,0,0,15,6053,7602),(7602,-1,-1,6051,6051,3,83,-1,0,0,15,7601,7603),(7603,-1,-1,6051,6051,3,85,-1,0,0,15,7602,10604),(7604,-1,-1,683,683,5,80,-1,0,0,15,6081,7605),(7605,-1,-1,683,683,5,80,-1,0,0,15,7604,12694),(7606,6537,6537,6537,6537,7,81,13821,30,900,15,6208,7607),(7607,6537,6537,6537,6537,8,82,13822,30,900,15,7606,7608),(7608,6537,6537,6537,6537,9,83,13823,30,900,15,7607,12460),(7609,6539,6539,6539,6539,6,76,13824,18,1800,15,6214,7610),(7610,6539,6539,6539,6539,6,79,13825,18,1800,15,7609,7611),(7611,6539,6539,6539,6539,6,82,13826,18,1800,15,7610,12942),(7612,-1,-1,270,665,2,66,-1,0,0,15,670,7613),(7613,-1,-1,270,665,2,67,-1,0,0,15,7612,7614),(7614,-1,-1,270,665,2,68,-1,0,0,15,7613,-1),(7615,-1,-1,6346,6346,6,79,-1,0,0,15,6348,7616),(7616,-1,-1,6346,6346,6,81,-1,0,0,15,7615,7617),(7617,-1,-1,6346,6346,6,83,-1,0,0,15,7616,15397),(7618,-1,-1,6349,6349,6,79,-1,0,0,15,6351,7619),(7619,-1,-1,6349,6349,6,81,-1,0,0,15,7618,7620),(7620,-1,-1,6349,6349,6,83,-1,0,0,15,7619,11053),(7621,-1,-1,1435,4773,9,81,-1,0,0,15,6517,13090),(7622,-1,-1,446,735,8,81,-1,0,0,15,7065,7623),(7623,-1,-1,446,735,8,82,-1,0,0,15,7622,7624),(7624,-1,-1,446,735,8,83,-1,0,0,15,7623,10473),(7625,-1,-1,735,735,8,81,-1,0,0,15,7068,7626),(7626,-1,-1,735,735,8,82,-1,0,0,15,7625,7627),(7627,-1,-1,735,735,8,83,-1,0,0,15,7626,10632),(7628,-1,-1,807,807,5,81,-1,0,0,15,5924,7629),(7629,-1,-1,807,807,5,83,-1,0,0,15,7628,7630),(7630,-1,-1,807,807,5,85,-1,0,0,15,7629,12685),(7631,-1,-1,255,255,7,81,-1,0,0,15,5597,7632),(7632,-1,-1,255,255,9,83,-1,0,0,15,7631,7633),(7633,-1,-1,255,255,12,85,-1,0,0,15,7632,17441),(7634,-1,-1,815,815,9,83,-1,0,0,15,5913,7635),(7635,-1,-1,815,815,10,84,-1,0,0,15,7634,7636),(7636,-1,-1,815,815,12,85,-1,0,0,15,7635,15441),(7637,-1,-1,1616,1616,5,83,-1,0,0,15,6007,7638),(7638,-1,-1,1616,1616,5,84,-1,0,0,15,7637,7639),(7639,-1,-1,1616,1616,5,85,-1,0,0,15,7638,-1),(7640,-1,-1,686,686,5,60,-1,0,0,15,690,12438),(7641,-1,-1,625,625,3,76,-1,0,0,15,4735,7642),(7642,-1,-1,625,625,3,78,-1,0,0,15,7641,7643),(7643,-1,-1,625,625,3,80,-1,0,0,15,7642,-1),(7644,-1,-1,6375,6375,6,81,-1,0,0,15,6377,7645),(7645,-1,-1,6375,6375,6,82,-1,0,0,15,7644,7646),(7646,-1,-1,6375,6375,6,83,-1,0,0,15,7645,7663),(7647,-1,-1,692,692,6,60,-1,0,0,15,694,7648),(7648,-1,-1,692,692,6,60,-1,0,0,15,7647,7649),(7649,-1,-1,692,692,6,60,-1,0,0,15,7648,7670),(7650,-1,-1,1044,1044,7,81,-1,0,0,15,5547,7651),(7651,-1,-1,1044,1044,9,83,-1,0,0,15,7650,7652),(7652,-1,-1,1044,1044,12,85,-1,0,0,15,7651,13074),(7653,-1,-1,1047,1047,7,81,-1,0,0,15,5550,7654),(7654,-1,-1,1047,1047,9,83,-1,0,0,15,7653,7655),(7655,-1,-1,1047,1047,12,85,-1,0,0,15,7654,13077),(7656,-1,-1,1050,1050,7,81,-1,0,0,15,5553,7657),(7657,-1,-1,1050,1050,9,83,-1,0,0,15,7656,7658),(7658,-1,-1,1050,1050,12,85,-1,0,0,15,7657,13023),(7659,-1,-1,754,754,3,70,-1,0,0,15,756,7660),(7660,-1,-1,754,754,6,70,-1,0,0,15,7659,7661),(7661,-1,-1,754,754,9,70,-1,0,0,15,7660,-1),(7662,188,188,188,188,9,83,16431,2,30,15,7339,10647),(7663,-1,-1,6375,6375,6,83,-1,0,0,15,7646,10084),(7664,-1,-1,7664,7664,2,73,-1,0,0,15,-1,7665),(7665,-1,-1,7664,7664,2,74,-1,0,0,15,7664,7666),(7666,-1,-1,7664,7664,2,75,-1,0,0,15,7665,7667),(7667,-1,-1,7664,7664,2,76,-1,0,0,15,7666,7668),(7668,-1,-1,7664,7664,2,77,-1,0,0,15,7667,10105),(7669,7669,7669,7669,7669,3,81,13838,35,5,15,-1,-1),(7670,-1,-1,692,692,7,75,-1,0,0,16,7649,7671),(7671,-1,-1,692,692,9,80,-1,0,0,16,7670,7672),(7672,-1,-1,692,692,12,85,-1,0,0,16,7671,12767),(7673,-1,-1,855,855,5,75,-1,0,0,16,859,7674),(7674,-1,-1,855,855,5,75,-1,0,0,16,7673,7675),(7675,-1,-1,855,855,5,75,-1,0,0,16,7674,7676),(7676,-1,-1,855,855,5,75,-1,0,0,16,7675,7677),(7677,-1,-1,855,855,5,75,-1,0,0,16,7676,10688),(7678,-1,-1,852,852,9,81,-1,0,0,16,5502,7679),(7679,-1,-1,852,852,10,83,-1,0,0,16,7678,7680),(7680,-1,-1,852,852,12,85,-1,0,0,16,7679,12576),(7681,-1,-1,1071,1071,6,80,-1,0,0,16,7553,-1),(7682,-1,-1,4861,4861,12,85,-1,0,0,16,7216,12757),(7683,-1,-1,1021,1021,5,85,-1,0,0,16,7540,7684),(7684,-1,-1,1021,1021,5,85,-1,0,0,16,7683,7685),(7685,-1,-1,1021,1021,5,85,-1,0,0,16,7684,13894),(7686,-1,-1,4844,4844,5,81,-1,0,0,16,7126,7687),(7687,-1,-1,4844,4844,5,83,-1,0,0,16,7686,7688),(7688,-1,-1,4844,4844,5,85,-1,0,0,16,7687,-1),(7689,7689,7689,7689,7689,12,85,21820,94,180,16,-1,-1),(7690,-1,-1,7690,7690,12,85,-1,0,0,16,-1,-1),(7691,146,146,146,146,8,85,16862,2,180,16,7466,13256),(7692,-1,-1,1186,1186,12,85,-1,0,0,16,7589,7693),(7693,-1,-1,1186,1186,12,85,-1,0,0,16,7692,7694),(7694,-1,-1,1186,1186,12,85,-1,0,0,16,7693,12564),(7695,-1,-1,7695,7695,6,85,-1,0,0,16,-1,7696),(7696,-1,-1,7695,7695,6,85,-1,0,0,16,7695,7697),(7697,-1,-1,7695,7695,6,85,-1,0,0,16,7696,-1),(7698,7698,7698,7698,7698,6,85,21763,17,6,16,-1,-1),(7699,-1,-1,7699,7699,12,85,0,0,0,16,-1,-1),(7700,-1,-1,255,255,7,81,-1,0,0,16,-1,7701),(7701,-1,-1,255,255,9,83,-1,0,0,16,7700,7702),(7702,-1,-1,255,255,12,85,-1,0,0,16,7701,12610),(7703,7703,7703,7703,7703,12,85,21754,16,600,16,-1,-1),(7704,-1,-1,8195,8195,5,81,-1,0,0,16,8197,7705),(7705,-1,-1,8195,8195,5,83,-1,0,0,16,7704,7706),(7706,-1,-1,8195,8195,5,85,-1,0,0,16,7705,-1),(7707,-1,-1,589,589,7,85,-1,0,0,16,7392,7708),(7708,-1,-1,589,589,7,85,-1,0,0,16,7707,7709),(7709,-1,-1,589,589,7,85,-1,0,0,16,7708,13104),(7710,5984,5984,5984,5984,12,85,21679,2,30,16,7335,7711),(7711,5984,5984,5984,5984,12,85,21680,2,30,16,7710,10626),(7712,7712,7712,7712,7712,12,85,21682,2,30,16,-1,10646),(7713,-1,-1,634,634,12,81,-1,0,0,16,5613,7714),(7714,-1,-1,634,634,12,83,-1,0,0,16,7713,10778),(7715,-1,-1,7715,7715,5,77,0,0,0,16,-1,7716),(7716,-1,-1,7715,7715,5,79,0,0,0,16,7715,7717),(7717,-1,-1,7715,7715,5,81,0,0,0,16,7716,14314),(7718,-1,-1,574,574,3,81,-1,0,0,16,576,-1),(7722,-1,-1,1486,1486,7,86,-1,0,0,17,7558,7723),(7723,-1,-1,1486,1486,8,87,-1,0,0,17,7722,7724),(7724,-1,-1,1486,1486,9,88,-1,0,0,17,7723,7725),(7725,-1,-1,1486,1486,10,89,-1,0,0,17,7724,7726),(7726,-1,-1,1486,1486,12,90,-1,0,0,17,7725,7842),(7732,7732,7732,7732,7732,0,60,7732,34,3600,14,-1,-1),(7733,-1,-1,288,288,6,65,-1,0,0,14,-1,-1),(7734,7734,7734,7734,7734,0,61,7734,34,28800,14,-1,-1),(7735,7735,7735,7735,7735,0,51,7731,32,3600,9,-1,-1),(7736,7736,7736,7736,7736,0,52,7865,32,10800,9,-1,-1),(7737,7737,7737,7737,7737,0,53,7733,32,10800,9,-1,-1),(7738,7738,7738,7738,7738,0,54,7990,32,21600,9,-1,-1),(7739,7739,7739,7739,7739,0,65,13064,36,3600,0,-1,-1),(7740,7740,7740,7740,7740,0,66,13065,36,28800,0,-1,-1),(7741,7741,7741,7741,7741,0,70,21854,50,3600,0,-1,-1),(7742,7742,7742,7742,7742,0,71,21855,50,28800,0,-1,-1),(7743,-1,-1,7743,7743,5,61,-1,0,0,16,-1,7744),(7744,-1,-1,7743,7743,7,61,-1,0,0,16,7743,7745),(7745,-1,-1,7743,7743,9,61,-1,0,0,16,7744,10717),(7746,-1,-1,7746,7746,5,85,-1,0,0,16,-1,7763),(7747,7747,7747,7747,7747,9,85,21790,32,180,16,-1,-1),(7748,-1,-1,7748,7748,3,81,-1,0,0,16,-1,7749),(7749,-1,-1,7748,7748,6,83,-1,0,0,16,7748,7750),(7750,-1,-1,7748,7748,9,85,-1,0,0,16,7749,-1),(7751,-1,-1,7751,7751,5,85,-1,0,0,16,-1,7752),(7752,-1,-1,7751,7751,5,85,-1,0,0,16,7751,7753),(7753,-1,-1,7751,7751,5,85,-1,0,0,16,7752,14132),(7754,7754,7754,7754,7754,9,85,21803,0,1,16,-1,-1),(7755,7755,7755,7755,7755,9,81,21804,53,900,16,-1,15782),(7756,7756,7756,7756,7756,12,85,21805,54,120,16,-1,-1),(7757,-1,-1,7757,7757,5,85,-1,0,0,16,-1,7758),(7758,-1,-1,7757,7757,7,85,-1,0,0,16,7757,7759),(7759,-1,-1,7757,7757,9,85,-1,0,0,16,7758,12587),(7760,-1,-1,7760,7760,5,85,-1,0,0,16,-1,7761),(7761,-1,-1,7760,7760,7,85,-1,0,0,16,7760,7762),(7762,-1,-1,7760,7760,9,85,-1,0,0,16,7761,-1),(7763,-1,-1,7746,7746,5,85,-1,0,0,16,7746,7764),(7764,-1,-1,7746,7746,5,85,-1,0,0,16,7763,-1),(7765,-1,-1,7765,7765,5,86,0,0,0,17,-1,7766),(7766,-1,-1,7765,7765,7,87,0,0,0,17,7765,7767),(7767,-1,-1,7765,7765,9,88,0,0,0,17,7766,7768),(7768,-1,-1,7765,7765,12,89,0,0,0,17,7767,7769),(7770,131,131,131,131,9,86,27655,4,900,17,10018,7771),(7771,131,131,131,131,12,88,27656,4,900,17,7770,7772),(7772,131,131,131,131,15,90,27657,4,900,17,7771,13374),(7773,7951,7951,7951,7951,9,86,27658,61,900,17,10040,7774),(7774,7951,7951,7951,7951,9,88,27659,61,900,17,7773,7775),(7775,7951,7951,7951,7951,9,90,27660,61,900,17,7774,13377),(7800,7800,7800,7800,7800,0,1,13531,39,4320,0,-1,7801),(7801,7800,7800,7800,7800,0,6,13532,39,4320,0,7800,7802),(7802,7800,7800,7800,7800,0,11,13533,39,4320,0,7801,7803),(7803,7800,7800,7800,7800,0,16,13534,39,4320,0,7802,7804),(7804,7800,7800,7800,7800,0,21,13535,39,4320,0,7803,7805),(7805,7800,7800,7800,7800,0,26,13536,39,4320,0,7804,7806),(7806,7800,7800,7800,7800,0,31,13537,39,4320,0,7805,7807),(7807,7800,7800,7800,7800,0,36,13538,39,4320,0,7806,7808),(7808,7800,7800,7800,7800,0,41,13539,39,4320,0,7807,7809),(7809,7800,7800,7800,7800,0,46,13540,39,4320,0,7808,7810),(7810,7800,7800,7800,7800,3,51,13541,39,4320,0,7809,7811),(7811,7800,7800,7800,7800,4,56,13542,39,4320,0,7810,7812),(7812,7800,7800,7800,7800,5,61,13543,39,4320,0,7811,7813),(7813,7800,7800,7800,7800,6,66,13544,39,4320,0,7812,7814),(7814,7800,7800,7800,7800,7,71,13545,39,4320,0,7813,7815),(7815,7800,7800,7800,7800,8,76,13562,39,4320,0,7814,7816),(7816,7800,7800,7800,7800,8,81,16062,39,4320,0,7815,7817),(7817,7800,7800,7800,7800,9,83,16855,39,4320,0,7816,10786),(7818,-1,-1,7818,7818,12,85,21750,0,0,16,-1,13029),(7819,-1,-1,9512,9512,7,85,-1,0,0,16,9514,7820),(7820,-1,-1,9512,9512,7,85,-1,0,0,16,7819,7821),(7821,-1,-1,9512,9512,7,85,-1,0,0,16,7820,7881),(7822,-1,-1,7822,7822,5,77,0,0,0,16,-1,7823),(7823,-1,-1,7822,7822,5,79,0,0,0,16,7822,7824),(7824,-1,-1,7822,7822,5,81,0,0,0,16,7823,7825),(7825,-1,-1,7822,7822,5,83,0,0,0,16,7824,7826),(7826,-1,-1,7822,7822,5,85,0,0,0,16,7825,14328),(7827,-1,-1,7827,7827,5,81,0,0,0,16,-1,-1),(7828,-1,-1,7828,7828,5,79,0,0,0,16,-1,7829),(7829,-1,-1,7828,7828,5,81,0,0,0,16,7828,7830),(7830,-1,-1,7828,7828,5,83,0,0,0,16,7829,-1),(7832,-1,-1,7832,7832,5,85,0,0,0,16,-1,7833),(7833,-1,-1,7832,7832,5,85,0,0,0,16,7832,7834),(7834,-1,-1,7832,7832,5,85,0,0,0,16,7833,7835),(7835,-1,-1,7832,7832,5,85,0,0,0,16,7834,7836),(7836,-1,-1,7832,7832,5,85,0,0,0,16,7835,-1),(7837,-1,-1,1006,1006,5,76,-1,0,0,17,7520,7838),(7838,-1,-1,1006,1006,5,77,-1,0,0,17,7837,7839),(7839,-1,-1,1006,1006,5,78,-1,0,0,17,7838,7840),(7840,-1,-1,1006,1006,5,79,-1,0,0,17,7839,7841),(7841,-1,-1,1006,1006,5,80,-1,0,0,17,7840,8470),(7842,-1,-1,1486,1486,12,91,-1,0,0,18,7726,7843),(7843,-1,-1,1486,1486,12,92,-1,0,0,18,7842,7844),(7844,-1,-1,1486,1486,12,93,-1,0,0,18,7843,7845),(7850,7850,7850,7850,7850,0,1,13546,39,4320,0,-1,7851),(7851,7850,7850,7850,7850,0,6,13547,39,4320,0,7850,7852),(7852,7850,7850,7850,7850,0,11,13548,39,4320,0,7851,7853),(7853,7850,7850,7850,7850,0,16,13549,39,4320,0,7852,7854),(7854,7850,7850,7850,7850,0,21,13550,39,4320,0,7853,7855),(7855,7850,7850,7850,7850,0,26,13551,39,4320,0,7854,7856),(7856,7850,7850,7850,7850,0,31,13552,39,4320,0,7855,7857),(7857,7850,7850,7850,7850,0,36,13553,39,4320,0,7856,7858),(7858,7850,7850,7850,7850,0,41,13554,39,4320,0,7857,7859),(7859,7850,7850,7850,7850,0,46,13555,39,4320,0,7858,7860),(7860,7850,7850,7850,7850,3,51,13556,39,4320,0,7859,7861),(7861,7850,7850,7850,7850,4,56,13557,39,4320,0,7860,7862),(7862,7850,7850,7850,7850,5,61,13558,39,4320,0,7861,7863),(7863,7850,7850,7850,7850,6,66,13559,39,4320,0,7862,7864),(7864,7850,7850,7850,7850,7,71,13560,39,4320,0,7863,7865),(7865,7850,7850,7850,7850,8,76,13561,39,4320,0,7864,7340),(7869,7869,7869,7869,7869,6,73,16175,60,30,15,-1,7870),(7870,7869,7869,7869,7869,6,77,16176,60,30,15,7869,7871),(7871,7869,7869,7869,7869,6,81,16177,60,30,15,7870,-1),(7872,7872,7872,7872,7872,6,76,16178,41,600,15,-1,7873),(7873,7872,7872,7872,7872,6,81,16179,41,600,15,7872,7874),(7874,7872,7872,7872,7872,6,85,16180,41,600,15,7873,10127),(7875,7875,7875,7875,7875,6,76,16181,42,600,15,-1,7876),(7876,7875,7875,7875,7875,6,81,16182,42,600,15,7875,7877),(7877,7875,7875,7875,7875,6,85,16183,42,600,15,7876,7878),(7878,7875,7875,7875,7875,6,85,16859,42,600,16,7877,7879),(7879,7875,7875,7875,7875,6,85,21823,42,600,16,7878,7880),(7880,7875,7875,7875,7875,6,85,21824,42,600,16,7879,13816),(7881,-1,-1,9512,9512,7,85,-1,0,0,16,7821,7882),(7882,-1,-1,9512,9512,7,85,-1,0,0,16,7881,7883),(7883,-1,-1,9512,9512,7,85,-1,0,0,16,7882,13187),(7884,-1,-1,7884,7884,9,85,-1,0,0,16,-1,12689),(7885,-1,-1,7885,7885,9,85,-1,0,0,16,-1,12690),(7886,-1,-1,1026,1026,5,85,-1,0,0,17,7515,7887),(7887,-1,-1,1026,1026,5,86,-1,0,0,17,7886,7888),(7888,-1,-1,1026,1026,5,87,-1,0,0,17,7887,7889),(7889,-1,-1,1026,1026,5,88,-1,0,0,17,7888,7890),(7890,-1,-1,1026,1026,5,89,-1,0,0,17,7889,8430),(7900,-1,-1,7900,7900,4,60,-1,0,0,15,-1,7901),(7901,-1,-1,7900,7900,4,65,-1,0,0,15,7900,7902),(7902,-1,-1,7900,7900,4,70,-1,0,0,15,7901,10268),(7903,7903,7903,7903,7903,6,75,16188,60,30,15,-1,12976),(7904,-1,-1,65,661,3,85,-1,0,0,17,7538,7905),(7905,-1,-1,65,661,3,86,-1,0,0,17,7904,7906),(7906,-1,-1,65,661,3,87,-1,0,0,17,7905,7907),(7907,-1,-1,65,661,3,88,-1,0,0,17,7906,7908),(7908,-1,-1,65,661,3,89,-1,0,0,17,7907,8435),(7940,-1,-1,7940,7940,6,60,-1,0,0,15,-1,7941),(7941,-1,-1,7940,7940,6,65,-1,0,0,15,7940,7942),(7942,-1,-1,7940,7940,6,70,-1,0,0,15,7941,10030),(7943,7943,7943,7943,7943,6,79,16192,60,8640,15,-1,7993),(7944,7944,7944,7944,7944,7,79,16193,34,1800,15,-1,-1),(7945,-1,-1,7945,7945,6,81,-1,0,0,15,-1,7946),(7946,-1,-1,7945,7945,6,82,-1,0,0,15,7945,7947),(7947,-1,-1,7945,7945,6,83,-1,0,0,15,7946,10033),(7948,-1,-1,7948,7948,6,75,-1,0,0,15,-1,7949),(7949,-1,-1,7948,7948,6,80,-1,0,0,15,7948,7950),(7950,-1,-1,7948,7948,6,85,-1,0,0,15,7949,10035),(7951,7951,7951,7951,7951,6,82,16200,61,900,15,-1,7952),(7952,7951,7951,7951,7951,6,83,16201,61,900,15,7951,7953),(7953,7951,7951,7951,7951,6,84,16202,61,900,15,7952,10038),(7980,-1,-1,7980,7980,6,70,-1,0,0,15,-1,7981),(7981,-1,-1,7980,7980,6,73,-1,0,0,15,7980,7982),(7982,-1,-1,7980,7980,6,76,-1,0,0,15,7981,-1),(7983,-1,-1,7983,7983,6,70,-1,0,0,15,-1,7984),(7984,-1,-1,7983,7983,6,73,-1,0,0,15,7983,7985),(7985,-1,-1,7983,7983,6,76,-1,0,0,15,7984,10110),(7986,7986,7986,7986,7986,9,75,16203,11,600,15,-1,7987),(7987,7986,7986,7986,7986,12,80,16204,11,600,15,7986,7988),(7988,7986,7986,7986,7986,12,85,16205,11,600,15,7987,10510),(7989,-1,-1,7989,7989,6,75,-1,0,0,15,-1,7990),(7990,-1,-1,7989,7989,6,80,-1,0,0,15,7989,7991),(7991,-1,-1,7989,7989,6,85,-1,0,0,15,7990,7992),(7992,-1,-1,7989,7989,6,85,-1,0,0,15,7991,13415),(7993,7943,7943,7943,7943,6,85,23601,60,8640,17,7943,-1),(7994,-1,-1,462,462,2,81,-1,0,0,17,464,7995),(7995,-1,-1,462,462,2,85,-1,0,0,17,7994,-1),(8000,-1,-1,8001,8001,0,50,-1,0,0,8,-1,-1),(8030,8030,8030,8030,8030,6,70,16206,60,900,15,-1,-1),(8031,-1,-1,8031,8031,6,75,-1,0,0,15,-1,8032),(8032,-1,-1,8031,8031,6,77,-1,0,0,15,8031,8033),(8033,-1,-1,8031,8031,6,79,-1,0,0,15,8032,10282),(8034,8034,8034,8034,8034,6,81,16207,59,600,15,-1,-1),(8035,-1,-1,8035,8035,6,73,-1,0,0,15,-1,8036),(8036,-1,-1,8035,8035,6,75,-1,0,0,15,8035,8037),(8037,-1,-1,8035,8035,6,77,-1,0,0,15,8036,10285),(8038,8038,8038,8038,8038,6,81,16210,56,12,15,-1,17541),(8039,8039,8039,8039,8039,6,83,16211,58,7,15,-1,15462),(8040,-1,-1,8040,8040,4,65,-1,0,0,15,-1,8041),(8041,-1,-1,8040,8040,4,70,-1,0,0,15,8040,8042),(8042,-1,-1,8040,8040,4,75,-1,0,0,15,8041,8043),(8043,-1,-1,8040,8040,4,78,-1,0,0,15,8042,8313),(8059,-1,-1,8232,8232,4,78,-1,0,0,15,8234,8261),(8060,8060,8060,8060,8060,7,75,16238,41,1800,15,-1,8061),(8061,8060,8060,8060,8060,7,78,16239,41,1800,15,8060,8062),(8062,8060,8060,8060,8060,7,81,16240,41,1800,15,8061,10237),(8063,8063,8063,8063,8063,7,75,16241,41,1800,15,-1,8064),(8064,8063,8063,8063,8063,7,78,16242,41,1800,15,8063,8065),(8065,8063,8063,8063,8063,7,81,16243,41,1800,15,8064,10240),(8066,8066,8066,8066,8066,7,75,16244,41,1800,15,-1,8067),(8067,8066,8066,8066,8066,7,78,16245,41,1800,15,8066,8068),(8068,8066,8066,8066,8066,7,81,16246,41,1800,15,8067,10243),(8069,-1,-1,8069,8069,5,71,-1,0,0,15,-1,8070),(8070,-1,-1,8069,8069,5,72,-1,0,0,15,8069,8071),(8071,-1,-1,8069,8069,5,73,-1,0,0,15,8070,15606),(8072,8072,8072,8072,8072,7,75,16221,37,20,15,-1,8073),(8073,8072,8072,8072,8072,7,75,16222,37,20,15,8072,8074),(8074,8072,8072,8072,8072,7,75,16223,37,20,15,8073,10246),(8075,8075,8075,8075,8075,7,81,16224,42,6,15,-1,-1),(8076,-1,-1,8076,8076,5,77,-1,0,0,15,-1,8077),(8077,-1,-1,8076,8076,5,78,-1,0,0,15,8076,8078),(8078,-1,-1,8076,8076,5,79,-1,0,0,15,8077,8079),(8079,-1,-1,8076,8076,5,80,-1,0,0,15,8078,8080),(8080,-1,-1,8076,8076,5,81,-1,0,0,15,8079,8081),(8081,-1,-1,8076,8076,5,82,-1,0,0,15,8080,-1),(8082,-1,-1,8082,8082,3,65,-1,0,0,15,-1,8083),(8083,-1,-1,8082,8082,3,67,-1,0,0,15,8082,8084),(8084,-1,-1,8082,8082,3,69,-1,0,0,15,8083,10249),(8190,-1,-1,8190,8190,7,75,-1,0,0,15,-1,8191),(8191,-1,-1,8190,8190,7,75,-1,0,0,15,8190,8192),(8192,-1,-1,8190,8190,7,75,-1,0,0,15,8191,-1),(8193,-1,-1,8193,8193,7,75,-1,0,0,15,-1,-1),(8194,8194,8194,8194,8194,7,75,16226,47,12,15,-1,-1),(8195,-1,-1,8195,8195,4,75,-1,0,0,15,-1,8196),(8196,-1,-1,8195,8195,4,75,-1,0,0,15,8195,8197),(8197,-1,-1,8195,8195,4,75,-1,0,0,15,8196,7704),(8198,-1,-1,8198,8198,4,65,-1,0,0,15,-1,8199),(8199,-1,-1,8198,8198,4,65,-1,0,0,15,8198,8200),(8200,-1,-1,8198,8198,4,65,-1,0,0,15,8199,-1),(8201,-1,-1,8201,8201,7,81,-1,0,0,15,-1,8202),(8202,-1,-1,8201,8201,7,81,-1,0,0,15,8201,8203),(8203,-1,-1,8201,8201,7,81,-1,0,0,15,8202,16475),(8204,-1,-1,8204,8204,4,75,-1,0,0,15,-1,8205),(8205,-1,-1,8204,8204,4,75,-1,0,0,15,8204,8206),(8206,-1,-1,8204,8204,4,75,-1,0,0,15,8205,1656),(8207,-1,-1,8207,8207,4,75,-1,0,0,15,-1,8208),(8208,-1,-1,8207,8207,4,75,-1,0,0,15,8207,8209),(8209,-1,-1,8207,8207,4,75,-1,0,0,15,8208,1659),(8210,-1,-1,8210,8210,5,65,-1,0,0,15,-1,8211),(8211,-1,-1,8210,8210,5,70,-1,0,0,15,8210,8212),(8212,-1,-1,8210,8210,5,75,-1,0,0,15,8211,8213),(8213,-1,-1,8210,8210,5,80,-1,0,0,15,8212,8214),(8214,-1,-1,8210,8210,5,85,-1,0,0,15,8213,1651),(8215,-1,-1,8215,8215,5,65,-1,0,0,15,-1,8216),(8216,-1,-1,8215,8215,5,70,-1,0,0,15,8215,8217),(8217,-1,-1,8215,8215,5,75,-1,0,0,15,8216,8218),(8218,-1,-1,8215,8215,5,80,-1,0,0,15,8217,8219),(8219,-1,-1,8215,8215,5,85,-1,0,0,15,8218,12559),(8220,8220,8220,8220,8220,5,76,16227,39,15,15,-1,-1),(8221,8221,8221,8221,8221,9,81,16228,45,600,15,-1,-1),(8222,8222,8222,8222,8222,7,75,16229,70,10,15,-1,-1),(8223,-1,-1,86,86,8,59,-1,0,0,15,6259,8262),(8224,-1,-1,8224,8224,5,75,-1,0,0,15,-1,8225),(8225,-1,-1,8224,8224,5,80,-1,0,0,15,8224,8226),(8226,-1,-1,8224,8224,5,85,-1,0,0,15,8225,8421),(8227,8227,8227,8227,8227,3,55,16233,71,10,15,-1,12810),(8228,-1,-1,8228,8228,5,75,-1,0,0,15,-1,8229),(8229,-1,-1,8228,8228,5,80,-1,0,0,15,8228,8230),(8230,-1,-1,8228,8228,5,85,-1,0,0,15,8229,-1),(8231,8231,-1,8231,8231,3,55,16234,38,60,15,-1,-1),(8232,-1,-1,8232,8232,4,65,-1,0,0,15,-1,8233),(8233,-1,-1,8232,8232,4,70,-1,0,0,15,8232,8234),(8234,-1,-1,8232,8232,4,75,-1,0,0,15,8233,8059),(8235,-1,-1,8235,8235,6,81,-1,0,0,15,-1,8236),(8236,-1,-1,8235,8235,6,81,-1,0,0,15,8235,8237),(8237,-1,-1,8235,8235,6,81,-1,0,0,15,8236,8238),(8238,-1,-1,8235,8235,6,81,-1,0,0,15,8237,8239),(8239,-1,-1,8235,8235,6,81,-1,0,0,15,8238,8304),(8240,-1,-1,8240,8240,6,81,-1,0,0,15,-1,8241),(8241,-1,-1,8240,8240,6,81,-1,0,0,15,8240,8242),(8242,-1,-1,8240,8240,6,81,-1,0,0,15,8241,8243),(8243,-1,-1,8240,8240,6,81,-1,0,0,15,8242,8244),(8244,-1,-1,8240,8240,6,81,-1,0,0,15,8243,10781),(8245,-1,-1,8245,8245,6,81,-1,0,0,15,-1,8246),(8246,-1,-1,8245,8245,6,81,-1,0,0,15,8245,8247),(8247,-1,-1,8245,8245,6,81,-1,0,0,15,8246,8248),(8248,-1,-1,8245,8245,6,81,-1,0,0,15,8247,8249),(8249,-1,-1,8245,8245,6,81,-1,0,0,15,8248,8422),(8250,-1,-1,8250,8250,6,81,-1,0,0,15,-1,8251),(8251,-1,-1,8250,8250,6,81,-1,0,0,15,8250,8252),(8252,-1,-1,8250,8250,6,81,-1,0,0,15,8251,8253),(8253,-1,-1,8250,8250,6,81,-1,0,0,15,8252,8254),(8254,-1,-1,8250,8250,6,81,-1,0,0,15,8253,13046),(8255,-1,-1,8255,8255,6,81,-1,0,0,15,-1,8256),(8256,-1,-1,8255,8255,6,81,-1,0,0,15,8255,8257),(8257,-1,-1,8255,8255,6,81,-1,0,0,15,8256,8258),(8258,-1,-1,8255,8255,6,81,-1,0,0,15,8257,8259),(8259,-1,-1,8255,8255,6,81,-1,0,0,15,8258,12411),(8260,8005,8005,8005,8005,9,85,20185,45,600,16,-1,-1),(8261,-1,-1,8232,8232,4,80,-1,0,0,16,8059,15772),(8262,-1,-1,86,86,8,65,-1,0,0,16,8223,-1),(8263,-1,-1,8263,8263,5,81,-1,0,0,16,-1,8264),(8264,-1,-1,8263,8263,5,82,-1,0,0,16,8263,8265),(8265,-1,-1,8263,8263,5,83,-1,0,0,16,8264,8266),(8266,-1,-1,8263,8263,5,84,-1,0,0,16,8265,8267),(8267,-1,-1,8263,8263,5,85,-1,0,0,16,8266,8351),(8268,-1,-1,8268,8268,5,81,-1,0,0,16,-1,8269),(8269,-1,-1,8268,8268,5,82,-1,0,0,16,8268,8270),(8270,-1,-1,8268,8268,5,83,-1,0,0,16,8269,8271),(8271,-1,-1,8268,8268,5,84,-1,0,0,16,8270,8272),(8272,-1,-1,8268,8268,5,85,-1,0,0,16,8271,8361),(8273,-1,-1,8273,8273,5,81,-1,0,0,16,-1,8274),(8274,-1,-1,8273,8273,5,82,-1,0,0,16,8273,8275),(8275,-1,-1,8273,8273,5,83,-1,0,0,16,8274,8276),(8276,-1,-1,8273,8273,5,84,-1,0,0,16,8275,8277),(8277,-1,-1,8273,8273,5,85,-1,0,0,16,8276,8371),(8278,-1,-1,8278,8278,5,81,-1,0,0,16,-1,8279),(8279,-1,-1,8278,8278,5,82,-1,0,0,16,8278,8280),(8280,-1,-1,8278,8278,5,83,-1,0,0,16,8279,8281),(8281,-1,-1,8278,8278,5,84,-1,0,0,16,8280,8282),(8282,-1,-1,8278,8278,5,85,-1,0,0,16,8281,8381),(8283,-1,-1,8283,8283,5,81,-1,0,0,16,-1,8284),(8284,-1,-1,8283,8283,5,82,-1,0,0,16,8283,8285),(8285,-1,-1,8283,8283,5,83,-1,0,0,16,8284,8286),(8286,-1,-1,8283,8283,5,84,-1,0,0,16,8285,8287),(8287,-1,-1,8283,8283,5,85,-1,0,0,16,8286,8391),(8288,-1,-1,8288,8288,5,81,-1,0,0,16,-1,8289),(8289,-1,-1,8288,8288,5,82,-1,0,0,16,8288,8290),(8290,-1,-1,8288,8288,5,83,-1,0,0,16,8289,8291),(8291,-1,-1,8288,8288,5,84,-1,0,0,16,8290,8292),(8292,-1,-1,8288,8288,5,85,-1,0,0,16,8291,8401),(8293,-1,-1,8293,8293,5,81,-1,0,0,16,-1,8294),(8294,-1,-1,8293,8293,5,82,-1,0,0,16,8293,8295),(8295,-1,-1,8293,8293,5,83,-1,0,0,16,8294,8296),(8296,-1,-1,8293,8293,5,84,-1,0,0,16,8295,8297),(8297,-1,-1,8293,8293,5,85,-1,0,0,16,8296,8411),(8300,8300,8300,8300,8300,5,81,21778,8,900,16,-1,8301),(8301,8300,8300,8300,8300,7,83,21779,8,900,16,8300,8302),(8302,8300,8300,8300,8300,9,85,21780,8,900,16,8301,15111),(8303,8303,8303,8303,8303,12,85,21773,9,1800,16,-1,-1),(8304,-1,-1,8235,8235,6,85,-1,0,0,16,8239,8305),(8305,-1,-1,8235,8235,6,85,-1,0,0,16,8304,8306),(8306,-1,-1,8235,8235,6,85,-1,0,0,16,8305,8307),(8307,-1,-1,8235,8235,6,85,-1,0,0,16,8306,8308),(8308,-1,-1,8235,8235,6,85,-1,0,0,16,8307,13353),(8309,260,-1,260,260,5,81,21687,3,2160,16,262,8310),(8310,260,-1,260,260,7,83,21688,3,2160,16,8309,8311),(8311,260,-1,260,260,9,85,21689,3,2160,16,8310,-1),(8312,8312,8312,8312,8312,12,85,21690,2,900,16,-1,-1),(8313,-1,-1,8040,8040,4,80,-1,0,0,16,8043,15773),(8314,-1,-1,8314,8314,7,85,-1,0,0,16,-1,8315),(8315,-1,-1,8314,8314,9,85,-1,0,0,16,8314,8316),(8316,-1,-1,8314,8314,12,85,-1,0,0,16,8315,13508),(8317,-1,-1,8317,8317,5,85,-1,0,0,16,-1,8318),(8318,-1,-1,8317,8317,5,85,-1,0,0,16,8317,-1),(8319,-1,-1,8319,8319,5,85,-1,0,0,16,-1,8320),(8320,-1,-1,8319,8319,5,85,-1,0,0,16,8319,8321),(8321,-1,-1,8319,8319,5,85,-1,0,0,16,8320,-1),(8322,-1,-1,8322,8322,5,81,0,0,0,16,-1,8323),(8323,-1,-1,8322,8322,7,83,0,0,0,16,8322,8324),(8324,-1,-1,8322,8322,9,85,0,0,0,16,8323,13199),(8325,-1,-1,8325,8325,7,81,0,0,0,16,-1,8326),(8326,-1,-1,8325,8325,9,81,0,0,0,16,8325,8327),(8327,-1,-1,8325,8325,11,81,0,0,0,16,8326,13219),(8328,-1,-1,244,244,12,59,-1,0,0,3,246,-1),(8329,-1,-1,622,622,3,71,-1,0,0,16,624,-1),(8331,-1,-1,8331,8331,9,85,0,0,0,16,-1,-1),(8332,-1,-1,8332,8332,7,85,0,0,0,16,-1,8333),(8333,-1,-1,8332,8332,7,85,0,0,0,16,8332,8334),(8334,-1,-1,8332,8332,7,85,0,0,0,16,8333,-1),(8335,-1,-1,8335,8335,5,81,0,0,0,16,-1,8336),(8336,-1,-1,8335,8335,5,82,0,0,0,16,8335,8337),(8337,-1,-1,8335,8335,5,83,0,0,0,16,8336,8338),(8338,-1,-1,8335,8335,5,84,0,0,0,16,8337,8339),(8339,-1,-1,8335,8335,5,85,0,0,0,16,8338,-1),(8341,8341,8341,8341,8341,12,85,21829,53,450,16,-1,-1),(8342,8342,8342,8342,8342,12,85,21843,54,240,16,-1,14729),(8343,167,167,167,167,10,85,21837,14,900,16,7249,12955),(8344,-1,-1,1210,1213,12,85,-1,0,0,16,7583,8345),(8345,-1,-1,1210,1213,12,85,-1,0,0,16,8344,8346),(8346,-1,-1,1210,1213,12,85,-1,0,0,16,8345,12526),(8347,-1,-1,8347,8347,7,81,0,0,0,16,-1,8348),(8348,-1,-1,8347,8347,9,83,0,0,0,16,8347,8349),(8349,-1,-1,8347,8347,11,85,0,0,0,16,8348,-1),(8350,-1,-1,8350,8350,12,85,0,0,0,16,-1,-1),(8351,-1,-1,8263,8263,3,85,-1,0,0,17,8267,8352),(8352,-1,-1,8263,8263,3,85,-1,0,0,17,8351,8353),(8353,-1,-1,8263,8263,3,85,-1,0,0,17,8352,8354),(8354,-1,-1,8263,8263,3,85,-1,0,0,17,8353,8355),(8355,-1,-1,8263,8263,3,85,-1,0,0,17,8354,8356),(8356,-1,-1,8263,8263,3,85,-1,0,0,17,8355,8357),(8357,-1,-1,8263,8263,3,85,-1,0,0,17,8356,8358),(8358,-1,-1,8263,8263,3,85,-1,0,0,17,8357,8359),(8359,-1,-1,8263,8263,3,85,-1,0,0,17,8358,8360),(8360,-1,-1,8263,8263,3,85,-1,0,0,17,8359,13933),(8361,-1,-1,8268,8268,3,85,-1,0,0,17,8272,8362),(8362,-1,-1,8268,8268,3,85,-1,0,0,17,8361,8363),(8363,-1,-1,8268,8268,3,85,-1,0,0,17,8362,8364),(8364,-1,-1,8268,8268,3,85,-1,0,0,17,8363,8365),(8365,-1,-1,8268,8268,3,85,-1,0,0,17,8364,8366),(8366,-1,-1,8268,8268,3,85,-1,0,0,17,8365,8367),(8367,-1,-1,8268,8268,3,85,-1,0,0,17,8366,8368),(8368,-1,-1,8268,8268,3,85,-1,0,0,17,8367,8369),(8369,-1,-1,8268,8268,3,85,-1,0,0,17,8368,8370),(8370,-1,-1,8268,8268,3,85,-1,0,0,17,8369,13943),(8371,-1,-1,8273,8273,3,85,-1,0,0,17,8277,8372),(8372,-1,-1,8273,8273,3,85,-1,0,0,17,8371,8373),(8373,-1,-1,8273,8273,3,85,-1,0,0,17,8372,8374),(8374,-1,-1,8273,8273,3,85,-1,0,0,17,8373,8375),(8375,-1,-1,8273,8273,3,85,-1,0,0,17,8374,8376),(8376,-1,-1,8273,8273,3,85,-1,0,0,17,8375,8377),(8377,-1,-1,8273,8273,3,85,-1,0,0,17,8376,8378),(8378,-1,-1,8273,8273,3,85,-1,0,0,17,8377,8379),(8379,-1,-1,8273,8273,3,85,-1,0,0,17,8378,8380),(8380,-1,-1,8273,8273,3,85,-1,0,0,17,8379,13953),(8381,-1,-1,8278,8278,3,85,-1,0,0,17,8282,8382),(8382,-1,-1,8278,8278,3,85,-1,0,0,17,8381,8383),(8383,-1,-1,8278,8278,3,85,-1,0,0,17,8382,8384),(8384,-1,-1,8278,8278,3,85,-1,0,0,17,8383,8385),(8385,-1,-1,8278,8278,3,85,-1,0,0,17,8384,8386),(8386,-1,-1,8278,8278,3,85,-1,0,0,17,8385,8387),(8387,-1,-1,8278,8278,3,85,-1,0,0,17,8386,8388),(8388,-1,-1,8278,8278,3,85,-1,0,0,17,8387,8389),(8389,-1,-1,8278,8278,3,85,-1,0,0,17,8388,8390),(8390,-1,-1,8278,8278,3,85,-1,0,0,17,8389,13963),(8391,-1,-1,8283,8283,3,85,-1,0,0,17,8287,8392),(8392,-1,-1,8283,8283,3,85,-1,0,0,17,8391,8393),(8393,-1,-1,8283,8283,3,85,-1,0,0,17,8392,8394),(8394,-1,-1,8283,8283,3,85,-1,0,0,17,8393,8395),(8395,-1,-1,8283,8283,3,85,-1,0,0,17,8394,8396),(8396,-1,-1,8283,8283,3,85,-1,0,0,17,8395,8397),(8397,-1,-1,8283,8283,3,85,-1,0,0,17,8396,8398),(8398,-1,-1,8283,8283,3,85,-1,0,0,17,8397,8399),(8399,-1,-1,8283,8283,3,85,-1,0,0,17,8398,8400),(8400,-1,-1,8283,8283,3,85,-1,0,0,17,8399,13973),(8401,-1,-1,8288,8288,3,85,-1,0,0,17,8292,8402),(8402,-1,-1,8288,8288,3,85,-1,0,0,17,8401,8403),(8403,-1,-1,8288,8288,3,85,-1,0,0,17,8402,8404),(8404,-1,-1,8288,8288,3,85,-1,0,0,17,8403,8405),(8405,-1,-1,8288,8288,3,85,-1,0,0,17,8404,8406),(8406,-1,-1,8288,8288,3,85,-1,0,0,17,8405,8407),(8407,-1,-1,8288,8288,3,85,-1,0,0,17,8406,8408),(8408,-1,-1,8288,8288,3,85,-1,0,0,17,8407,8409),(8409,-1,-1,8288,8288,3,85,-1,0,0,17,8408,8410),(8410,-1,-1,8288,8288,3,85,-1,0,0,17,8409,13983),(8411,-1,-1,8293,8293,3,85,-1,0,0,17,8297,8412),(8412,-1,-1,8293,8293,3,85,-1,0,0,17,8411,8413),(8413,-1,-1,8293,8293,3,85,-1,0,0,17,8412,8414),(8414,-1,-1,8293,8293,3,85,-1,0,0,17,8413,8415),(8415,-1,-1,8293,8293,3,85,-1,0,0,17,8414,8416),(8416,-1,-1,8293,8293,3,85,-1,0,0,17,8415,8417),(8417,-1,-1,8293,8293,3,85,-1,0,0,17,8416,8418),(8418,-1,-1,8293,8293,3,85,-1,0,0,17,8417,8419),(8419,-1,-1,8293,8293,3,85,-1,0,0,17,8418,8420),(8420,-1,-1,8293,8293,3,85,-1,0,0,17,8419,13993),(8421,-1,-1,8224,8224,5,90,-1,0,0,17,8226,-1),(8422,-1,-1,8245,8245,6,86,-1,0,0,17,8249,8423),(8423,-1,-1,8245,8245,6,87,-1,0,0,17,8422,8424),(8424,-1,-1,8245,8245,6,88,-1,0,0,17,8423,8425),(8425,-1,-1,8245,8245,6,89,-1,0,0,17,8424,8426),(8426,-1,-1,8245,8245,6,90,-1,0,0,17,8425,13338),(8427,-1,-1,7100,7100,6,85,-1,0,0,17,7325,8428),(8428,-1,-1,7100,7100,6,87,-1,0,0,17,8427,8429),(8429,-1,-1,7100,7100,6,89,-1,0,0,17,8428,-1),(8430,-1,-1,1026,1026,10,91,-1,0,0,18,7890,8431),(8435,-1,-1,65,661,8,91,-1,0,0,18,7908,8436),(8440,-1,-1,122,122,13,91,-1,0,0,18,13089,8441),(8445,-1,-1,12636,12636,0,1,-1,0,0,16,12637,8446),(8446,-1,-1,12636,12636,0,1,-1,0,0,16,8445,8447),(8447,-1,-1,12636,12636,0,1,-1,0,0,16,8446,16419),(8448,-1,-1,6119,6119,8,91,-1,0,0,18,12496,8449),(8463,-1,-1,125,125,10,91,-1,0,0,18,13084,8464),(8464,-1,-1,125,125,11,91,-1,0,0,18,8463,8465),(8470,-1,-1,1006,1006,10,91,-1,0,0,18,7841,8471),(9000,9000,9000,9000,9000,0,1,16995,49,72000,0,-1,-1),(9001,-1,-1,9101,9101,2,51,-1,0,0,15,-1,9002),(9002,-1,-1,9101,9101,2,51,-1,0,0,15,9001,9003),(9003,-1,-1,9101,9101,2,51,-1,0,0,15,9002,9004),(9004,-1,-1,9101,9101,2,51,-1,0,0,15,9003,9005),(9005,-1,-1,9101,9101,2,51,-1,0,0,15,9004,9006),(9006,-1,-1,9101,9101,2,51,-1,0,0,15,9005,9007),(9007,-1,-1,9101,9101,2,51,-1,0,0,15,9006,9008),(9008,-1,-1,9101,9101,2,51,-1,0,0,15,9007,9009),(9009,-1,-1,9101,9101,2,51,-1,0,0,15,9008,9010),(9010,-1,-1,9101,9101,2,51,-1,0,0,15,9009,-1),(9011,-1,-1,9111,9111,4,51,-1,0,0,15,-1,9012),(9012,-1,-1,9111,9111,4,51,-1,0,0,15,9011,9013),(9013,-1,-1,9111,9111,4,51,-1,0,0,15,9012,9014),(9014,-1,-1,9111,9111,4,51,-1,0,0,15,9013,9015),(9015,-1,-1,9111,9111,4,51,-1,0,0,15,9014,9016),(9016,-1,-1,9111,9111,4,51,-1,0,0,15,9015,9017),(9017,-1,-1,9111,9111,4,51,-1,0,0,15,9016,9018),(9018,-1,-1,9111,9111,4,51,-1,0,0,15,9017,9019),(9019,-1,-1,9111,9111,4,51,-1,0,0,15,9018,9020),(9020,-1,-1,9111,9111,4,51,-1,0,0,15,9019,-1),(9021,-1,-1,9121,9121,3,51,-1,0,0,15,-1,9022),(9022,-1,-1,9121,9121,3,51,-1,0,0,15,9021,9023),(9023,-1,-1,9121,9121,3,51,-1,0,0,15,9022,9024),(9024,-1,-1,9121,9121,3,51,-1,0,0,15,9023,9025),(9025,-1,-1,9121,9121,3,51,-1,0,0,15,9024,9026),(9026,-1,-1,9121,9121,3,51,-1,0,0,15,9025,9027),(9027,-1,-1,9121,9121,3,51,-1,0,0,15,9026,9028),(9028,-1,-1,9121,9121,3,51,-1,0,0,15,9027,9029),(9029,-1,-1,9121,9121,3,51,-1,0,0,15,9028,9030),(9030,-1,-1,9121,9121,3,51,-1,0,0,15,9029,-1),(9031,9031,9031,9031,9031,0,1,16601,65,72000,0,-1,-1),(9032,9032,9032,9032,9032,0,0,21815,51,72000,0,-1,-1),(9033,-1,-1,9033,9033,0,1,-1,0,0,0,-1,-1),(9100,-1,-1,9100,9100,1,85,-1,0,0,15,-1,9101),(9101,-1,-1,9100,9100,1,85,-1,0,0,15,9100,9102),(9102,-1,-1,9100,9100,1,85,-1,0,0,15,9101,9103),(9103,-1,-1,9100,9100,1,85,-1,0,0,15,9102,9104),(9104,-1,-1,9100,9100,1,85,-1,0,0,15,9103,9105),(9105,-1,-1,9100,9100,1,85,-1,0,0,15,9104,9106),(9106,-1,-1,9100,9100,1,85,-1,0,0,15,9105,9107),(9107,-1,-1,9100,9100,1,85,-1,0,0,15,9106,9108),(9108,-1,-1,9100,9100,1,85,-1,0,0,15,9107,-1),(9109,-1,-1,9109,9109,1,85,-1,0,0,15,-1,9110),(9110,-1,-1,9109,9109,1,85,-1,0,0,15,9109,9111),(9111,-1,-1,9109,9109,1,85,-1,0,0,15,9110,9112),(9112,-1,-1,9109,9109,1,85,-1,0,0,15,9111,9113),(9113,-1,-1,9109,9109,1,85,-1,0,0,15,9112,9114),(9114,-1,-1,9109,9109,1,85,-1,0,0,15,9113,9115),(9115,-1,-1,9109,9109,1,85,-1,0,0,15,9114,9116),(9116,-1,-1,9109,9109,1,85,-1,0,0,15,9115,9117),(9117,-1,-1,9109,9109,1,85,-1,0,0,15,9116,-1),(9118,-1,-1,9118,9118,1,85,-1,0,0,15,-1,9119),(9119,-1,-1,9118,9118,1,85,-1,0,0,15,9118,9120),(9120,-1,-1,9118,9118,1,85,-1,0,0,15,9119,9121),(9121,-1,-1,9118,9118,1,85,-1,0,0,15,9120,9122),(9122,-1,-1,9118,9118,1,85,-1,0,0,15,9121,9123),(9123,-1,-1,9118,9118,1,85,-1,0,0,15,9122,9124),(9124,-1,-1,9118,9118,1,85,-1,0,0,15,9123,9125),(9125,-1,-1,9118,9118,1,85,-1,0,0,15,9124,9126),(9126,-1,-1,9118,9118,1,85,-1,0,0,15,9125,-1),(9127,-1,-1,9127,9127,1,85,-1,0,0,15,-1,9128),(9128,-1,-1,9127,9127,1,85,-1,0,0,15,9127,9129),(9129,-1,-1,9127,9127,1,85,-1,0,0,15,9128,9130),(9130,-1,-1,9127,9127,1,85,-1,0,0,15,9129,9131),(9131,-1,-1,9127,9127,1,85,-1,0,0,15,9130,9132),(9132,-1,-1,9127,9127,1,85,-1,0,0,15,9131,9133),(9133,-1,-1,9127,9127,1,85,-1,0,0,15,9132,9134),(9134,-1,-1,9127,9127,1,85,-1,0,0,15,9133,9135),(9135,-1,-1,9127,9127,1,85,-1,0,0,15,9134,-1),(9136,-1,-1,9136,9136,1,85,-1,0,0,15,-1,9137),(9137,-1,-1,9136,9136,1,85,-1,0,0,15,9136,9138),(9138,-1,-1,9136,9136,1,85,-1,0,0,15,9137,9139),(9139,-1,-1,9136,9136,1,85,-1,0,0,15,9138,9140),(9140,-1,-1,9136,9136,1,85,-1,0,0,15,9139,9141),(9141,-1,-1,9136,9136,1,85,-1,0,0,15,9140,9142),(9142,-1,-1,9136,9136,1,85,-1,0,0,15,9141,9143),(9143,-1,-1,9136,9136,1,85,-1,0,0,15,9142,9144),(9144,-1,-1,9136,9136,1,85,-1,0,0,15,9143,-1),(9145,-1,-1,9145,9145,1,85,-1,0,0,15,-1,9146),(9146,-1,-1,9145,9145,1,85,-1,0,0,15,9145,9147),(9147,-1,-1,9145,9145,1,85,-1,0,0,15,9146,9148),(9148,-1,-1,9145,9145,1,85,-1,0,0,15,9147,9149),(9149,-1,-1,9145,9145,1,85,-1,0,0,15,9148,9150),(9150,-1,-1,9145,9145,1,85,-1,0,0,15,9149,9151),(9151,-1,-1,9145,9145,1,85,-1,0,0,15,9150,9152),(9152,-1,-1,9145,9145,1,85,-1,0,0,15,9151,9153),(9153,-1,-1,9145,9145,1,85,-1,0,0,15,9152,-1),(9154,-1,-1,9154,9154,1,85,-1,0,0,15,-1,9155),(9155,-1,-1,9154,9154,1,85,-1,0,0,15,9154,9156),(9156,-1,-1,9154,9154,1,85,-1,0,0,15,9155,9157),(9157,-1,-1,9154,9154,1,85,-1,0,0,15,9156,9158),(9158,-1,-1,9154,9154,1,85,-1,0,0,15,9157,9159),(9159,-1,-1,9154,9154,1,85,-1,0,0,15,9158,9160),(9160,-1,-1,9154,9154,1,85,-1,0,0,15,9159,9161),(9161,-1,-1,9154,9154,1,85,-1,0,0,15,9160,9162),(9162,-1,-1,9154,9154,1,85,-1,0,0,15,9161,-1),(9163,-1,-1,9163,9163,1,85,-1,0,0,15,-1,9164),(9164,-1,-1,9163,9163,1,85,-1,0,0,15,9163,9165),(9165,-1,-1,9163,9163,1,85,-1,0,0,15,9164,9166),(9166,-1,-1,9163,9163,1,85,-1,0,0,15,9165,9167),(9167,-1,-1,9163,9163,1,85,-1,0,0,15,9166,9168),(9168,-1,-1,9163,9163,1,85,-1,0,0,15,9167,9169),(9169,-1,-1,9163,9163,1,85,-1,0,0,15,9168,9170),(9170,-1,-1,9163,9163,1,85,-1,0,0,15,9169,9171),(9171,-1,-1,9163,9163,1,85,-1,0,0,15,9170,-1),(9172,-1,-1,9172,9172,1,85,-1,0,0,15,-1,9173),(9173,-1,-1,9172,9172,1,85,-1,0,0,15,9172,9174),(9174,-1,-1,9172,9172,1,85,-1,0,0,15,9173,9175),(9175,-1,-1,9172,9172,1,85,-1,0,0,15,9174,9176),(9176,-1,-1,9172,9172,1,85,-1,0,0,15,9175,9177),(9177,-1,-1,9172,9172,1,85,-1,0,0,15,9176,9178),(9178,-1,-1,9172,9172,1,85,-1,0,0,15,9177,9179),(9179,-1,-1,9172,9172,1,85,-1,0,0,15,9178,9180),(9180,-1,-1,9172,9172,1,85,-1,0,0,15,9179,-1),(9181,-1,-1,9181,9181,1,85,-1,0,0,15,-1,9182),(9182,-1,-1,9181,9181,1,85,-1,0,0,15,9181,9183),(9183,-1,-1,9181,9181,1,85,-1,0,0,15,9182,9184),(9184,-1,-1,9181,9181,1,85,-1,0,0,15,9183,9185),(9185,-1,-1,9181,9181,1,85,-1,0,0,15,9184,9186),(9186,-1,-1,9181,9181,1,85,-1,0,0,15,9185,9187),(9187,-1,-1,9181,9181,1,85,-1,0,0,15,9186,9188),(9188,-1,-1,9181,9181,1,85,-1,0,0,15,9187,9189),(9189,-1,-1,9181,9181,1,85,-1,0,0,15,9188,-1),(9190,-1,-1,9190,9190,1,85,-1,0,0,15,-1,9191),(9191,-1,-1,9190,9190,1,85,-1,0,0,15,9190,9192),(9192,-1,-1,9190,9190,1,85,-1,0,0,15,9191,9193),(9193,-1,-1,9190,9190,1,85,-1,0,0,15,9192,9194),(9194,-1,-1,9190,9190,1,85,-1,0,0,15,9193,9195),(9195,-1,-1,9190,9190,1,85,-1,0,0,15,9194,9196),(9196,-1,-1,9190,9190,1,85,-1,0,0,15,9195,9197),(9197,-1,-1,9190,9190,1,85,-1,0,0,15,9196,9198),(9198,-1,-1,9190,9190,1,85,-1,0,0,15,9197,-1),(9199,-1,-1,9199,9199,1,85,-1,0,0,15,-1,9200),(9200,-1,-1,9199,9199,1,85,-1,0,0,15,9199,9201),(9201,-1,-1,9199,9199,1,85,-1,0,0,15,9200,9202),(9202,-1,-1,9199,9199,1,85,-1,0,0,15,9201,9203),(9203,-1,-1,9199,9199,1,85,-1,0,0,15,9202,9204),(9204,-1,-1,9199,9199,1,85,-1,0,0,15,9203,9205),(9205,-1,-1,9199,9199,1,85,-1,0,0,15,9204,9206),(9206,-1,-1,9199,9199,1,85,-1,0,0,15,9205,9207),(9207,-1,-1,9199,9199,1,85,-1,0,0,15,9206,-1),(9208,-1,-1,9208,9208,1,85,-1,0,0,15,-1,9209),(9209,-1,-1,9208,9208,1,85,-1,0,0,15,9208,9210),(9210,-1,-1,9208,9208,1,85,-1,0,0,15,9209,9211),(9211,-1,-1,9208,9208,1,85,-1,0,0,15,9210,9212),(9212,-1,-1,9208,9208,1,85,-1,0,0,15,9211,9213),(9213,-1,-1,9208,9208,1,85,-1,0,0,15,9212,9214),(9214,-1,-1,9208,9208,1,85,-1,0,0,15,9213,9215),(9215,-1,-1,9208,9208,1,85,-1,0,0,15,9214,9216),(9216,-1,-1,9208,9208,1,85,-1,0,0,15,9215,-1),(9217,-1,-1,9217,9217,1,85,-1,0,0,15,-1,9218),(9218,-1,-1,9217,9217,1,85,-1,0,0,15,9217,9219),(9219,-1,-1,9217,9217,1,85,-1,0,0,15,9218,9220),(9220,-1,-1,9217,9217,1,85,-1,0,0,15,9219,9221),(9221,-1,-1,9217,9217,1,85,-1,0,0,15,9220,9222),(9222,-1,-1,9217,9217,1,85,-1,0,0,15,9221,9223),(9223,-1,-1,9217,9217,1,85,-1,0,0,15,9222,9224),(9224,-1,-1,9217,9217,1,85,-1,0,0,15,9223,9225),(9225,-1,-1,9217,9217,1,85,-1,0,0,15,9224,-1),(9226,-1,-1,9226,9226,1,85,-1,0,0,15,-1,9227),(9227,-1,-1,9226,9226,1,85,-1,0,0,15,9226,9228),(9228,-1,-1,9226,9226,1,85,-1,0,0,15,9227,9229),(9229,-1,-1,9226,9226,1,85,-1,0,0,15,9228,9230),(9230,-1,-1,9226,9226,1,85,-1,0,0,15,9229,9231),(9231,-1,-1,9226,9226,1,85,-1,0,0,15,9230,9232),(9232,-1,-1,9226,9226,1,85,-1,0,0,15,9231,9233),(9233,-1,-1,9226,9226,1,85,-1,0,0,15,9232,9234),(9234,-1,-1,9226,9226,1,85,-1,0,0,15,9233,-1),(9235,-1,-1,9235,9235,1,85,-1,0,0,15,-1,9236),(9236,-1,-1,9235,9235,1,85,-1,0,0,15,9235,9237),(9237,-1,-1,9235,9235,1,85,-1,0,0,15,9236,9238),(9238,-1,-1,9235,9235,1,85,-1,0,0,15,9237,9239),(9239,-1,-1,9235,9235,1,85,-1,0,0,15,9238,9240),(9240,-1,-1,9235,9235,1,85,-1,0,0,15,9239,9241),(9241,-1,-1,9235,9235,1,85,-1,0,0,15,9240,9242),(9242,-1,-1,9235,9235,1,85,-1,0,0,15,9241,9243),(9243,-1,-1,9235,9235,1,85,-1,0,0,15,9242,-1),(9300,9300,9300,9300,9300,5,85,16212,40,600,15,-1,9301),(9301,9300,9300,9300,9300,5,85,16213,40,600,15,9300,9302),(9302,9300,9300,9300,9300,5,85,16214,40,600,15,9301,-1),(9303,9303,9303,9303,9303,5,85,16215,40,600,15,-1,9304),(9304,9303,9303,9303,9303,5,85,16216,40,600,15,9303,9305),(9305,9303,9303,9303,9303,5,85,16217,40,600,15,9304,-1),(9306,9306,9306,9306,9306,5,85,16218,40,600,15,-1,9307),(9307,9306,9306,9306,9306,5,85,16219,40,600,15,9306,9308),(9308,9306,9306,9306,9306,5,85,16220,40,600,15,9307,-1),(9309,9309,9309,9309,9309,5,85,16249,40,600,15,-1,9310),(9310,9309,9309,9309,9309,5,85,16250,40,600,15,9309,9311),(9311,9309,9309,9309,9309,5,85,16251,40,600,15,9310,-1),(9312,9312,9312,9312,9312,5,85,16252,40,600,15,-1,9313),(9313,9312,9312,9312,9312,5,85,16253,40,600,15,9312,9314),(9314,9312,9312,9312,9312,5,85,16254,40,600,15,9313,-1),(9315,9315,9315,9315,9315,5,85,16255,40,600,15,-1,9316),(9316,9315,9315,9315,9315,5,85,16256,40,600,15,9315,9317),(9317,9315,9315,9315,9315,5,85,16257,40,600,15,9316,-1),(9318,9318,9318,9318,9318,5,85,16261,40,600,15,-1,9319),(9319,9318,9318,9318,9318,5,85,16262,40,600,15,9318,9320),(9320,9318,9318,9318,9318,5,85,16263,40,600,15,9319,-1),(9321,9321,9321,9321,9321,5,85,16264,40,600,15,-1,9322),(9322,9321,9321,9321,9321,5,85,16265,40,600,15,9321,9323),(9323,9321,9321,9321,9321,5,85,16266,40,600,15,9322,-1),(9324,9324,9324,9324,9324,5,85,16267,40,600,15,-1,9325),(9325,9324,9324,9324,9324,5,85,16268,40,600,15,9324,9326),(9326,9324,9324,9324,9324,5,85,16269,40,600,15,9325,-1),(9327,9327,9327,9327,9327,5,85,16270,40,600,15,-1,9328),(9328,9327,9327,9327,9327,5,85,16271,40,600,15,9327,9329),(9329,9327,9327,9327,9327,5,85,16272,40,600,15,9328,-1),(9330,9330,9330,9330,9330,5,85,16273,40,600,15,-1,9331),(9331,9330,9330,9330,9330,5,85,16274,40,600,15,9330,9332),(9332,9330,9330,9330,9330,5,85,16275,40,600,15,9331,-1),(9333,9333,9333,9333,9333,5,85,16276,40,600,15,-1,9334),(9334,9333,9333,9333,9333,5,85,16277,40,600,15,9333,9335),(9335,9333,9333,9333,9333,5,85,16278,40,600,15,9334,-1),(9336,9336,9336,9336,9336,5,85,16284,40,600,15,-1,9337),(9337,9336,9336,9336,9336,5,85,16285,40,600,15,9336,9338),(9338,9336,9336,9336,9336,5,85,16286,40,600,15,9337,-1),(9339,9339,9339,9339,9339,5,85,16287,40,600,15,-1,9340),(9340,9339,9339,9339,9339,5,85,16288,40,600,15,9339,9341),(9341,9339,9339,9339,9339,5,85,16289,40,600,15,9340,-1),(9342,9342,9342,9342,9342,5,85,16290,40,600,15,-1,9343),(9343,9342,9342,9342,9342,5,85,16291,40,600,15,9342,9344),(9344,9342,9342,9342,9342,5,85,16292,40,600,15,9343,-1),(9345,9345,9345,9345,9345,5,85,16293,40,600,15,-1,9346),(9346,9345,9345,9345,9345,5,85,16294,40,600,15,9345,9347),(9347,9345,9345,9345,9345,5,85,16295,40,600,15,9346,-1),(9348,9348,9348,9348,9348,5,85,16296,40,600,15,-1,9349),(9349,9348,9348,9348,9348,5,85,16297,40,600,15,9348,9350),(9350,9348,9348,9348,9348,5,85,16298,40,600,15,9349,-1),(9351,9351,9351,9351,9351,5,85,16299,40,600,15,-1,9352),(9352,9351,9351,9351,9351,5,85,16300,40,600,15,9351,9353),(9353,9351,9351,9351,9351,5,85,16301,40,600,15,9352,-1),(9354,9354,9354,9354,9354,5,85,16305,40,600,15,-1,9355),(9355,9354,9354,9354,9354,5,85,16306,40,600,15,9354,9356),(9356,9354,9354,9354,9354,5,85,16307,40,600,15,9355,12626),(9357,9357,9357,9357,9357,5,85,16308,40,600,15,-1,9358),(9358,9357,9357,9357,9357,5,85,16309,40,600,15,9357,9359),(9359,9357,9357,9357,9357,5,85,16310,40,600,15,9358,12629),(9360,9360,9360,9360,9360,5,85,16311,40,600,15,-1,9361),(9361,9360,9360,9360,9360,5,85,16312,40,600,15,9360,9362),(9362,9360,9360,9360,9360,5,85,16313,40,600,15,9361,12632),(9363,9363,9363,9363,9363,5,85,16317,40,600,15,-1,9364),(9364,9363,9363,9363,9363,5,85,16318,40,600,15,9363,9365),(9365,9363,9363,9363,9363,5,85,16319,40,600,15,9364,-1),(9366,9366,9366,9366,9366,5,85,16320,40,600,15,-1,9367),(9367,9366,9366,9366,9366,5,85,16321,40,600,15,9366,9368),(9368,9366,9366,9366,9366,5,85,16322,40,600,15,9367,-1),(9369,9369,9369,9369,9369,5,85,16323,40,600,15,-1,9370),(9370,9369,9369,9369,9369,5,85,16324,40,600,15,9369,9371),(9371,9369,9369,9369,9369,5,85,16325,40,600,15,9370,-1),(9372,9372,9372,9372,9372,5,85,16326,40,600,15,-1,9373),(9373,9372,9372,9372,9372,5,85,16327,40,600,15,9372,9374),(9374,9372,9372,9372,9372,5,85,16328,40,600,15,9373,-1),(9375,9375,9375,9375,9375,5,85,16329,40,600,15,-1,9376),(9376,9375,9375,9375,9375,5,85,16330,40,600,15,9375,9377),(9377,9375,9375,9375,9375,5,85,16331,40,600,15,9376,-1),(9378,9378,9378,9378,9378,5,85,16332,40,600,15,-1,9379),(9379,9378,9378,9378,9378,5,85,16333,40,600,15,9378,9380),(9380,9378,9378,9378,9378,5,85,16334,40,600,15,9379,-1),(9381,9381,9381,9381,9381,5,85,16335,40,600,15,-1,9382),(9382,9381,9381,9381,9381,5,85,16336,40,600,15,9381,9383),(9383,9381,9381,9381,9381,5,85,16337,40,600,15,9382,-1),(9384,9384,9384,9384,9384,5,85,16338,40,600,15,-1,9385),(9385,9384,9384,9384,9384,5,85,16339,40,600,15,9384,9386),(9386,9384,9384,9384,9384,5,85,16340,40,600,15,9385,-1),(9387,9387,9387,9387,9387,5,85,16341,40,600,15,-1,9388),(9388,9387,9387,9387,9387,5,85,16342,40,600,15,9387,9389),(9389,9387,9387,9387,9387,5,85,16343,40,600,15,9388,-1),(9390,9390,9390,9390,9390,5,85,16344,40,600,15,-1,9391),(9391,9390,9390,9390,9390,5,85,16345,40,600,15,9390,9392),(9392,9390,9390,9390,9390,5,85,16346,40,600,15,9391,-1),(9393,9393,9393,9393,9393,5,85,16347,40,600,15,-1,9394),(9394,9393,9393,9393,9393,5,85,16348,40,600,15,9393,9395),(9395,9393,9393,9393,9393,5,85,16349,40,600,15,9394,-1),(9396,9396,9396,9396,9396,5,85,16350,40,600,15,-1,9397),(9397,9396,9396,9396,9396,5,85,16351,40,600,15,9396,9398),(9398,9396,9396,9396,9396,5,85,16352,40,600,15,9397,-1),(9399,9399,9399,9399,9399,5,85,16359,40,600,15,-1,9400),(9400,9399,9399,9399,9399,5,85,16360,40,600,15,9399,9401),(9401,9399,9399,9399,9399,5,85,16361,40,600,15,9400,-1),(9402,9402,9402,9402,9402,5,85,16362,40,600,15,-1,9403),(9403,9402,9402,9402,9402,5,85,16363,40,600,15,9402,9404),(9404,9402,9402,9402,9402,5,85,16364,40,600,15,9403,-1),(9405,9405,9405,9405,9405,5,85,16365,40,600,15,-1,9406),(9406,9405,9405,9405,9405,5,85,16366,40,600,15,9405,9407),(9407,9405,9405,9405,9405,5,85,16367,40,600,15,9406,-1),(9408,9408,9408,9408,9408,5,85,16368,40,600,15,-1,9409),(9409,9408,9408,9408,9408,5,85,16369,40,600,15,9408,9410),(9410,9408,9408,9408,9408,5,85,16370,40,600,15,9409,-1),(9411,9411,9411,9411,9411,5,85,16371,40,600,15,-1,9412),(9412,9411,9411,9411,9411,5,85,16372,40,600,15,9411,9413),(9413,9411,9411,9411,9411,5,85,16373,40,600,15,9412,-1),(9414,9414,9414,9414,9414,5,85,16374,40,600,15,-1,9415),(9415,9414,9414,9414,9414,5,85,16375,40,600,15,9414,9416),(9416,9414,9414,9414,9414,5,85,16376,40,600,15,9415,-1),(9417,9417,9417,9417,9417,5,85,16377,40,600,15,-1,9418),(9418,9417,9417,9417,9417,5,85,16378,40,600,15,9417,9419),(9419,9417,9417,9417,9417,5,85,16379,40,600,15,9418,-1),(9420,9420,9420,9420,9420,5,85,16380,40,600,15,-1,9421),(9421,9420,9420,9420,9420,5,85,16381,40,600,15,9420,9422),(9422,9420,9420,9420,9420,5,85,16382,40,600,15,9421,-1),(9423,9423,9423,9423,9423,5,85,16386,40,600,15,-1,9424),(9424,9423,9423,9423,9423,5,85,16387,40,600,15,9423,9425),(9425,9423,9423,9423,9423,5,85,16388,40,600,15,9424,-1),(9426,9426,9426,9426,9426,5,85,16389,40,600,15,-1,9427),(9427,9426,9426,9426,9426,5,85,16390,40,600,15,9426,9428),(9428,9426,9426,9426,9426,5,85,16391,40,600,15,9427,-1),(9429,9429,9429,9429,9429,5,85,16392,40,600,15,-1,9430),(9430,9429,9429,9429,9429,5,85,16393,40,600,15,9429,9431),(9431,9429,9429,9429,9429,5,85,16394,40,600,15,9430,-1),(9432,9432,9432,9432,9432,5,85,16395,40,600,15,-1,9433),(9433,9432,9432,9432,9432,5,85,16396,40,600,15,9432,9434),(9434,9432,9432,9432,9432,5,85,16397,40,600,15,9433,-1),(9435,9435,9435,9435,9435,5,85,16398,40,600,15,-1,9436),(9436,9435,9435,9435,9435,5,85,16399,40,600,15,9435,9437),(9437,9435,9435,9435,9435,5,85,16400,40,600,15,9436,-1),(9438,9438,9438,9438,9438,5,85,16401,40,600,15,-1,9439),(9439,9438,9438,9438,9438,5,85,16402,40,600,15,9438,9440),(9440,9438,9438,9438,9438,5,85,16403,40,600,15,9439,-1),(9441,9441,9441,9441,9441,5,85,16404,40,600,15,-1,9442),(9442,9441,9441,9441,9441,5,85,16405,40,600,15,9441,9443),(9443,9441,9441,9441,9441,5,85,16406,40,600,15,9442,-1),(9500,9500,9500,9500,9500,3,76,16247,47,60,15,-1,-1),(9501,9501,9501,9501,9501,9,85,16247,47,600,15,-1,-1),(9502,9502,9502,9502,9502,7,81,16248,48,3600,15,-1,-1),(9503,-1,-1,9503,9503,7,83,-1,0,0,15,-1,9504),(9504,-1,-1,9503,9503,7,84,-1,0,0,15,9503,9505),(9505,-1,-1,9503,9503,7,85,-1,0,0,15,9504,10087),(9506,-1,-1,9506,9506,7,81,-1,0,0,15,-1,9507),(9507,-1,-1,9506,9506,7,83,-1,0,0,15,9506,9508),(9508,-1,-1,9506,9506,7,85,-1,0,0,15,9507,13630),(9509,-1,-1,9509,9509,7,81,-1,0,0,15,-1,9510),(9510,-1,-1,9509,9509,7,82,-1,0,0,15,9509,9511),(9511,-1,-1,9509,9509,7,83,-1,0,0,15,9510,9515),(9512,-1,-1,9512,9512,7,81,-1,0,0,15,-1,9513),(9513,-1,-1,9512,9512,7,82,-1,0,0,15,9512,9514),(9514,-1,-1,9512,9512,7,83,-1,0,0,15,9513,7819),(9515,-1,-1,9509,9509,7,86,-1,0,0,17,9511,16361),(10003,6610,6610,6610,6610,5,60,16494,41,30,16,6610,10573),(10004,-1,-1,6614,6614,6,70,-1,0,0,16,6616,10005),(10005,-1,-1,6614,6614,9,70,-1,0,0,16,10004,10575),(10006,54006,54006,54006,54006,7,85,16495,18,180,16,7111,13425),(10007,-1,-1,6564,6564,10,85,-1,0,0,16,7114,10008),(10008,-1,-1,6564,6564,10,85,-1,0,0,16,10007,10009),(10009,-1,-1,6564,6564,10,85,-1,0,0,16,10008,10568),(10010,6565,6565,6565,6565,7,85,16496,17,45,16,7115,10517),(10011,912,912,912,912,9,80,16497,4,3600,16,7121,10012),(10012,912,912,912,912,9,80,16498,4,3600,16,10011,10013),(10013,912,912,912,912,9,80,16499,4,3600,16,10012,10585),(10014,1383,1383,1383,1383,12,85,21766,6,300,16,7299,6487),(10015,1195,1195,1195,1195,9,85,16504,13,2160,16,7300,13259),(10016,131,131,131,131,10,85,16505,4,900,16,7303,10017),(10017,131,131,131,131,10,85,16506,4,900,16,10016,10018),(10018,131,131,131,131,10,85,16507,4,900,16,10017,7770),(10019,1192,1192,1192,1192,10,85,20177,12,1320,16,7306,10020),(10020,1192,1192,1192,1192,10,85,21652,12,1320,16,10019,10021),(10021,1192,1192,1192,1192,10,85,21704,12,1320,16,10020,13363),(10022,746,746,746,746,12,85,16511,10,2160,16,7309,10023),(10023,746,746,746,746,12,85,16512,10,2160,16,10022,10024),(10024,746,746,746,746,12,85,16513,10,2160,16,10023,15321),(10025,-1,-1,6601,6601,6,85,-1,0,0,16,7322,10026),(10026,-1,-1,6601,6601,6,85,-1,0,0,16,10025,10027),(10027,-1,-1,6601,6601,6,85,-1,0,0,16,10026,10028),(10028,-1,-1,6601,6601,6,85,-1,0,0,16,10027,10029),(10029,-1,-1,6601,6601,6,85,-1,0,0,16,10028,10437),(10030,-1,-1,7940,7940,5,75,-1,0,0,16,7942,10031),(10031,-1,-1,7940,7940,7,75,-1,0,0,16,10030,10032),(10032,-1,-1,7940,7940,9,75,-1,0,0,16,10031,6484),(10033,-1,-1,7945,7945,6,85,-1,0,0,16,7947,10034),(10034,-1,-1,7945,7945,6,85,-1,0,0,16,10033,10347),(10035,-1,-1,7948,7948,6,85,-1,0,0,16,7950,10036),(10036,-1,-1,7948,7948,6,85,-1,0,0,16,10035,10037),(10037,-1,-1,7948,7948,6,85,-1,0,0,16,10036,15328),(10038,7951,7951,7951,7951,6,85,16514,61,900,16,7953,10039),(10039,7951,7951,7951,7951,6,85,16515,61,900,16,10038,10040),(10040,7951,7951,7951,7951,6,85,16516,61,900,16,10039,7773),(10041,-1,-1,6636,6636,9,75,-1,0,0,16,6638,10042),(10042,-1,-1,6636,6636,10,75,-1,0,0,16,10041,10043),(10043,-1,-1,6636,6636,11,75,-1,0,0,16,10042,12529),(10044,-1,-1,6791,6791,6,85,-1,0,0,16,6793,10045),(10045,-1,-1,6791,6791,6,85,-1,0,0,16,10044,10046),(10046,-1,-1,6791,6791,6,85,-1,0,0,16,10045,10676),(10047,534,534,534,534,12,85,16561,4,2160,16,7331,10048),(10048,534,534,534,534,12,85,16562,4,2160,16,10047,10049),(10049,534,534,534,534,12,85,16563,4,2160,16,10048,10708),(10050,-1,-1,6395,6395,7,85,-1,0,0,16,7338,10051),(10051,-1,-1,6395,6395,7,85,-1,0,0,16,10050,10052),(10052,-1,-1,6395,6395,7,85,-1,0,0,16,10051,10705),(10053,6754,6754,6754,6754,9,75,16570,41,1200,16,6754,14111),(10054,6758,6758,6758,6758,10,85,16571,43,900,16,6760,10055),(10055,6758,6758,6758,6758,11,85,16572,43,900,16,10054,10056),(10056,6758,6758,6758,6758,12,85,16573,43,900,16,10055,13546),(10057,6764,6764,6764,6764,9,80,16574,52,600,16,6764,16716),(10058,-1,-1,6765,6765,9,85,-1,0,0,16,6767,10059),(10059,-1,-1,6765,6765,9,85,-1,0,0,16,10058,10060),(10060,-1,-1,6765,6765,9,85,-1,0,0,16,10059,10766),(10061,5007,5007,5007,5007,9,85,16575,8,2160,16,7343,10062),(10062,5007,5007,5007,5007,9,85,16576,8,2160,16,10061,10063),(10063,5007,5007,5007,5007,9,85,16577,8,2160,16,10062,13119),(10064,-1,-1,1608,1608,6,85,-1,0,0,16,7383,10065),(10065,-1,-1,1608,1608,7,85,-1,0,0,16,10064,10066),(10066,-1,-1,1608,1608,8,85,-1,0,0,16,10065,10067),(10067,-1,-1,1608,1608,9,85,-1,0,0,16,10066,10068),(10068,-1,-1,1608,1608,10,85,-1,0,0,16,10067,10069),(10069,-1,-1,1608,1608,11,85,-1,0,0,16,10068,16730),(10070,-1,-1,6630,6630,6,75,-1,0,0,16,6634,10071),(10071,-1,-1,6630,6630,6,75,-1,0,0,16,10070,10072),(10072,-1,-1,6630,6630,6,75,-1,0,0,16,10071,10073),(10073,-1,-1,6630,6630,6,75,-1,0,0,16,10072,10074),(10074,-1,-1,6630,6630,6,75,-1,0,0,16,10073,13621),(10075,-1,-1,6641,6641,9,85,-1,0,0,16,6643,10076),(10076,-1,-1,6641,6641,9,85,-1,0,0,16,10075,10077),(10077,-1,-1,6641,6641,9,85,-1,0,0,16,10076,16192),(10078,6508,6508,6508,6508,7,85,16578,38,600,16,7389,10079),(10079,6508,6508,6508,6508,7,85,16579,38,600,16,10078,10080),(10080,6508,6508,6508,6508,7,85,16580,38,600,16,10079,15775),(10081,-1,-1,1313,1313,12,85,-1,0,0,16,7398,10082),(10082,-1,-1,1313,1313,12,85,-1,0,0,16,10081,10083),(10083,-1,-1,1313,1313,12,85,-1,0,0,16,10082,12579),(10084,-1,-1,6375,6375,6,85,-1,0,0,16,7663,10085),(10085,-1,-1,6375,6375,6,85,-1,0,0,16,10084,10086),(10086,-1,-1,6375,6375,6,85,-1,0,0,16,10085,5347),(10087,-1,-1,9503,9503,7,85,-1,0,0,16,9505,10088),(10088,-1,-1,9503,9503,7,85,-1,0,0,16,10087,10089),(10089,-1,-1,9503,9503,7,85,-1,0,0,16,10088,12792),(10090,1498,1498,1498,1498,12,85,16590,12,1320,16,7410,10091),(10091,1498,1498,1498,1498,12,85,16591,12,1320,16,10090,10092),(10092,1498,1498,1498,1498,12,85,16602,12,1320,16,10091,13401),(10093,1495,1495,1495,1495,9,86,16603,30,900,17,7416,10094),(10096,548,548,548,548,10,85,16606,5,900,16,7419,10097),(10097,548,548,548,548,10,85,16607,5,900,16,10096,10098),(10098,548,548,548,548,10,85,16608,5,900,16,10097,13158),(10099,6561,6561,6561,6561,7,85,16609,32,30,16,7424,10100),(10100,6561,6561,6561,6561,7,85,16610,32,30,16,10099,10101),(10101,6561,6561,6561,6561,7,85,16611,32,30,16,10100,10418),(10102,510,510,510,510,3,75,16587,37,240,16,7427,10103),(10103,510,510,510,510,3,75,16588,37,240,16,10102,10104),(10104,510,510,510,510,3,75,16589,37,240,16,10103,10824),(10105,-1,-1,7664,7664,2,82,-1,0,0,16,7668,10106),(10106,-1,-1,7664,7664,2,82,-1,0,0,16,10105,10107),(10107,-1,-1,7664,7664,2,82,-1,0,0,16,10106,10108),(10108,-1,-1,7664,7664,2,82,-1,0,0,16,10107,10109),(10109,-1,-1,7664,7664,2,82,-1,0,0,16,10108,17350),(10110,-1,-1,7983,7983,6,81,-1,0,0,16,7985,10111),(10111,-1,-1,7983,7983,6,81,-1,0,0,16,10110,10112),(10112,-1,-1,7983,7983,6,81,-1,0,0,16,10111,-1),(10113,1352,1352,1352,1352,6,85,16618,3,60,16,7156,10114),(10114,1352,1352,1352,1352,6,85,16619,3,60,16,10113,10115),(10115,1352,1352,1352,1352,6,85,16620,3,60,16,10114,13807),(10116,1358,1358,1358,1358,6,85,16615,3,60,16,7159,10117),(10117,1358,1358,1358,1358,6,85,16616,3,60,16,10116,10118),(10118,1358,1358,1358,1358,6,85,16617,3,60,16,10117,13810),(10119,1355,1355,1355,1355,6,85,16612,3,60,16,7174,10120),(10120,1355,1355,1355,1355,6,85,16613,3,60,16,10119,10121),(10121,1355,1355,1355,1355,6,85,16614,3,60,16,10120,12700),(10122,-1,-1,4801,4801,6,85,-1,0,0,16,7162,10123),(10123,-1,-1,4801,4801,6,85,-1,0,0,16,10122,12674),(10124,-1,-1,611,611,2,75,-1,0,0,16,7177,10125),(10125,-1,-1,611,611,2,75,-1,0,0,16,10124,10126),(10126,-1,-1,611,611,2,75,-1,0,0,16,10125,12703),(10127,7872,7872,7872,7872,6,85,16621,41,600,16,7874,10128),(10128,7872,7872,7872,7872,6,85,16622,41,600,16,10127,10129),(10129,7872,7872,7872,7872,6,85,16623,41,600,16,10128,12682),(10130,-1,-1,6870,6870,6,80,-1,0,0,16,6872,10131),(10131,-1,-1,6870,6870,6,80,-1,0,0,16,10130,10132),(10132,-1,-1,6870,6870,6,80,-1,0,0,16,10131,-1),(10133,-1,-1,255,255,9,80,-1,0,0,16,6875,10134),(10134,-1,-1,255,255,9,80,-1,0,0,16,10133,10135),(10135,-1,-1,255,255,9,80,-1,0,0,16,10134,13196),(10136,-1,-1,6375,6375,6,83,-1,0,0,16,6878,10137),(10137,-1,-1,6375,6375,6,83,-1,0,0,16,10136,10138),(10138,-1,-1,6375,6375,6,83,-1,0,0,16,10137,12734),(10139,6533,6533,6533,6533,10,85,16631,15,600,16,7428,12740),(10140,1116,1116,1116,1116,12,85,16647,4,2160,16,7432,10141),(10141,1116,1116,1116,1116,12,85,16648,4,2160,16,10140,10142),(10142,1116,1116,1116,1116,12,85,16649,4,2160,16,10141,12743),(10143,5298,5298,5298,5298,12,85,16632,32,1800,16,7440,10144),(10144,5298,5298,5298,5298,12,85,16633,32,1800,16,10143,10145),(10145,5298,5298,5298,5298,12,85,16634,32,1800,16,10144,12746),(10146,1598,-1,1598,1598,12,85,16638,6,900,16,7443,10147),(10147,1598,-1,1598,1598,12,85,16639,6,900,16,10146,10148),(10148,1598,-1,1598,1598,12,85,16640,6,900,16,10147,13193),(10149,5020,5020,5020,5020,9,85,16630,9,300,16,7444,13490),(10150,1110,1110,1110,1110,6,85,16641,3,2160,16,7447,10151),(10151,1110,1110,1110,1110,6,85,16642,3,2160,16,10150,10152),(10152,1110,1110,1110,1110,6,85,16643,3,2160,16,10151,13190),(10153,-1,-1,6337,6337,6,85,-1,0,0,16,7450,10154),(10154,-1,-1,6337,6337,6,85,-1,0,0,16,10153,10155),(10155,-1,-1,6337,6337,6,85,-1,0,0,16,10154,16297),(10156,5017,5017,5017,5017,9,85,16627,8,600,16,7456,10157),(10157,5017,5017,5017,5017,9,85,16628,8,600,16,10156,10158),(10158,5017,5017,5017,5017,9,85,16629,8,600,16,10157,14189),(10159,1569,1569,1569,1569,7,85,16624,5,1800,16,7459,10160),(10160,1569,1569,1569,1569,7,85,16625,5,1800,16,10159,10161),(10161,1569,1569,1569,1569,7,85,16626,5,1800,16,10160,17276),(10162,6663,6663,6663,6663,7,82,16653,59,600,16,6665,10163),(10163,6663,6663,6663,6663,7,82,16654,59,600,16,10162,10164),(10164,6663,6663,6663,6663,7,82,16655,59,600,16,10163,-1),(10165,-1,-1,1543,1543,12,85,-1,0,0,16,7136,10166),(10166,-1,-1,1543,1543,12,85,-1,0,0,16,10165,10167),(10167,-1,-1,1543,1543,12,85,-1,0,0,16,10166,13213),(10168,6328,6328,6328,6328,7,85,16650,10,600,16,7145,10169),(10169,6328,6328,6328,6328,7,85,16651,10,600,16,10168,10170),(10170,6328,6328,6328,6328,7,85,16652,10,600,16,10169,13770),(10171,-1,-1,878,878,7,85,-1,0,0,16,7147,10172),(10172,-1,-1,878,878,7,85,-1,0,0,16,10171,-1),(10173,-1,-1,846,846,12,85,-1,0,0,16,7153,10174),(10174,-1,-1,846,846,12,85,-1,0,0,16,10173,10175),(10175,-1,-1,846,846,12,85,-1,0,0,16,10174,13795),(10176,-1,-1,6703,6703,3,70,-1,0,0,16,6705,10177),(10177,-1,-1,6703,6703,3,70,-1,0,0,16,10176,10178),(10178,-1,-1,6703,6703,3,70,-1,0,0,16,10177,13005),(10179,6706,6706,6706,6706,7,85,16675,44,600,16,6708,10180),(10180,6706,6706,6706,6706,7,85,16676,44,600,16,10179,10181),(10181,6706,6706,6706,6706,7,85,16677,44,600,16,10180,5353),(10182,-1,-1,6712,6712,7,85,-1,0,0,16,6716,10183),(10183,-1,-1,6712,6712,7,85,-1,0,0,16,10182,10184),(10184,-1,-1,6712,6712,7,85,-1,0,0,16,10183,10185),(10185,-1,-1,6712,6712,7,85,-1,0,0,16,10184,10186),(10186,-1,-1,6712,6712,7,85,-1,0,0,16,10185,-1),(10187,1327,1327,1327,1327,12,85,16665,10,900,16,7462,10188),(10188,1327,1327,1327,1327,12,85,16666,10,900,16,10187,10189),(10189,1327,1327,1327,1327,12,85,16667,10,900,16,10188,5330),(10190,1520,1520,1520,1520,9,80,16672,11,900,16,7465,10191),(10191,1520,1520,1520,1520,9,80,16673,11,900,16,10190,10192),(10192,1520,1520,1520,1520,9,80,16674,11,900,16,10191,12997),(10193,153,153,153,153,12,85,16668,3,2160,16,7468,11081),(10194,528,528,528,528,12,85,16669,5,720,16,7471,10195),(10195,528,528,528,528,12,85,16670,5,720,16,10194,10196),(10196,528,528,528,528,12,85,16671,5,720,16,10195,13161),(10197,5251,5251,5251,5251,12,85,16662,13,900,16,7474,10198),(10198,5251,5251,5251,5251,12,85,16663,13,900,16,10197,10199),(10199,5251,5251,5251,5251,12,85,16664,13,900,16,10198,5363),(10200,6815,6815,6815,6815,8,85,16691,60,600,16,6817,10201),(10201,6815,6815,6815,6815,8,85,16692,60,600,16,10200,10202),(10202,6815,6815,6815,6815,8,85,16693,60,600,16,10201,12786),(10203,-1,-1,6819,6819,6,77,-1,0,0,16,6821,10204),(10204,-1,-1,6819,6819,6,77,-1,0,0,16,10203,10205),(10205,-1,-1,6819,6819,6,77,-1,0,0,16,10204,-1),(10206,-1,-1,6823,6823,4,75,-1,0,0,16,6827,10207),(10207,-1,-1,6823,6823,4,77,-1,0,0,16,10206,-1),(10208,6828,6828,6828,6828,12,85,16686,43,60,16,6828,17534),(10209,1274,1274,1274,1274,12,85,16683,9,540,16,7201,10210),(10210,1274,1274,1274,1274,12,85,16684,9,540,16,10209,10211),(10211,1274,1274,1274,1274,12,85,16685,9,540,16,10210,12760),(10212,1510,-1,1510,1510,12,80,16690,13,2160,16,7202,-1),(10213,-1,-1,5264,5264,12,85,-1,0,0,16,7208,10214),(10214,-1,-1,5264,5264,12,85,-1,0,0,16,10213,10215),(10215,-1,-1,5264,5264,12,85,-1,0,0,16,10214,10216),(10216,-1,-1,5264,5264,12,85,-1,0,0,16,10215,10217),(10217,-1,-1,5264,5264,12,85,-1,0,0,16,10216,12798),(10218,4927,4927,4927,4927,9,85,16682,14,600,16,7209,-1),(10219,-1,-1,839,839,6,80,-1,0,0,16,7214,10220),(10220,-1,-1,839,839,6,80,-1,0,0,16,10219,10221),(10221,-1,-1,839,839,6,80,-1,0,0,16,10220,10222),(10222,-1,-1,839,839,6,80,-1,0,0,16,10221,10223),(10223,-1,-1,839,839,6,80,-1,0,0,16,10222,-1),(10224,967,967,967,967,6,85,16687,10,1800,16,7219,10225),(10225,967,967,967,967,6,85,16688,10,1800,16,10224,10226),(10226,967,967,967,967,6,85,16689,10,1800,16,10225,12789),(10227,-1,-1,5295,5295,6,85,-1,0,0,16,7222,10228),(10228,-1,-1,5295,5295,6,85,-1,0,0,16,10227,10229),(10229,-1,-1,5295,5295,6,85,-1,0,0,16,10228,13226),(10230,619,619,619,619,6,83,16704,6,900,16,7228,10231),(10231,619,619,619,619,6,83,16705,6,900,16,10230,10232),(10232,619,619,619,619,6,83,16706,6,900,16,10231,-1),(10233,516,516,516,516,6,82,16707,5,480,16,7237,12879),(10234,1334,1334,1334,1334,12,85,16701,11,4320,16,7241,10235),(10235,1334,1334,1334,1334,12,85,16702,11,4320,16,10234,10236),(10236,1334,1334,1334,1334,12,85,16703,11,4320,16,10235,12868),(10237,8060,8060,8060,8060,7,85,16711,41,1800,16,8062,10238),(10238,8060,8060,8060,8060,7,85,16712,41,1800,16,10237,10239),(10239,8060,8060,8060,8060,7,85,16713,41,1800,16,10238,13650),(10240,8063,8063,8063,8063,7,85,16714,41,1800,16,8065,10241),(10241,8063,8063,8063,8063,7,85,16715,41,1800,16,10240,10242),(10242,8063,8063,8063,8063,7,85,16716,41,1800,16,10241,13653),(10243,8066,8066,8066,8066,7,85,16717,41,1800,16,8068,10244),(10244,8066,8066,8066,8066,7,85,16718,41,1800,16,10243,10245),(10245,8066,8066,8066,8066,7,85,16719,41,1800,16,10244,13656),(10246,8072,8072,8072,8072,7,80,16708,37,20,16,8074,10247),(10247,8072,8072,8072,8072,7,80,16709,37,20,16,10246,10248),(10248,8072,8072,8072,8072,7,80,16710,37,20,16,10247,12857),(10249,-1,-1,8082,8082,3,74,-1,0,0,16,8084,10250),(10250,-1,-1,8082,8082,3,74,-1,0,0,16,10249,10251),(10251,-1,-1,8082,8082,3,74,-1,0,0,16,10250,-1),(10252,520,520,520,520,12,85,16723,6,540,16,7252,10253),(10253,520,520,520,520,12,85,16724,6,540,16,10252,10254),(10254,520,520,520,520,12,85,16725,6,540,16,10253,12985),(10255,4903,4903,4903,4903,9,81,16726,9,1320,16,7253,12956),(10256,4906,4906,4906,4906,9,81,16727,9,1320,16,7254,12959),(10257,4909,4909,4909,4909,9,81,16728,16,1320,16,7255,12957),(10258,4912,4912,4912,4912,9,81,16729,16,1320,16,7256,12958),(10259,616,616,616,616,10,85,16733,7,900,16,7259,10260),(10260,616,616,616,616,10,85,16734,7,900,16,10259,10261),(10261,616,616,616,616,10,85,16735,7,900,16,10260,14730),(10262,-1,-1,1577,1577,12,85,-1,0,0,16,7265,10263),(10263,-1,-1,1577,1577,12,85,-1,0,0,16,10262,10264),(10264,-1,-1,1577,1577,12,85,-1,0,0,16,10263,13707),(10265,-1,-1,795,795,12,85,-1,0,0,16,7269,10266),(10266,-1,-1,795,795,12,85,-1,0,0,16,10265,10267),(10267,-1,-1,795,795,12,85,-1,0,0,16,10266,12945),(10268,-1,-1,7900,7900,4,70,-1,0,0,16,7902,10269),(10269,-1,-1,7900,7900,4,70,-1,0,0,16,10268,10270),(10270,-1,-1,7900,7900,4,70,-1,0,0,16,10269,-1),(10271,1242,1242,1242,1242,12,85,16744,9,1320,16,7287,10272),(10272,1242,1242,1242,1242,12,85,16745,9,1320,16,10271,10273),(10273,1242,1242,1242,1242,12,85,16746,9,1320,16,10272,12934),(10274,4931,4931,4931,4931,7,85,16747,4,600,16,7293,10275),(10275,4931,4931,4931,4931,7,85,16748,4,600,16,10274,10276),(10276,4931,4931,4931,4931,7,85,16749,4,600,16,10275,10428),(10277,4935,4935,4935,4935,7,81,16743,14,300,16,7294,17540),(10278,4934,4934,4934,4934,7,81,16742,13,300,16,7295,17539),(10279,517,517,517,517,5,80,16739,12,600,16,7298,10280),(10280,517,517,517,517,5,80,16740,12,600,16,10279,10281),(10281,517,517,517,517,5,80,16741,12,600,16,10280,12917),(10282,-1,-1,8031,8031,6,84,-1,0,0,16,8033,10283),(10283,-1,-1,8031,8031,6,84,-1,0,0,16,10282,10284),(10284,-1,-1,8031,8031,6,84,-1,0,0,16,10283,10431),(10285,-1,-1,8035,8035,6,82,-1,0,0,16,8037,10286),(10286,-1,-1,8035,8035,6,82,-1,0,0,16,10285,10287),(10287,-1,-1,8035,8035,6,82,-1,0,0,16,10286,15472),(10288,6971,6971,6971,6971,7,85,16761,41,600,16,6973,10289),(10289,6971,6971,6971,6971,7,85,16762,41,600,16,10288,10290),(10290,6971,6971,6971,6971,7,85,16763,41,600,16,10289,14274),(10291,-1,-1,6974,6974,5,85,-1,0,0,16,6976,10292),(10292,-1,-1,6974,6974,5,85,-1,0,0,16,10291,10293),(10293,-1,-1,6974,6974,5,85,-1,0,0,16,10292,-1),(10294,6984,6984,6984,6984,6,78,16765,60,60,16,6984,13177),(10295,6985,6985,6985,6985,6,78,16766,60,60,16,6985,13179),(10296,6986,6986,6986,6986,6,78,16767,60,60,16,6986,13178),(10297,1119,1119,1119,1119,9,85,16750,8,900,16,7481,10298),(10298,1119,1119,1119,1119,9,85,16751,8,900,16,10297,10299),(10299,1119,1119,1119,1119,9,85,16752,8,900,16,10298,16883),(10300,723,723,723,723,7,85,16753,6,30,16,7482,14273),(10301,5015,5015,5015,5015,12,85,16754,9,900,16,7483,17382),(10302,291,291,291,291,12,85,16755,5,900,16,7487,10303),(10303,291,291,291,291,12,85,16756,5,900,16,10302,10304),(10304,291,291,291,291,12,85,16757,5,900,16,10303,12828),(10305,-1,-1,729,729,9,85,-1,0,0,16,7496,10306),(10306,-1,-1,729,729,9,85,-1,0,0,16,10305,10307),(10307,-1,-1,729,729,9,85,-1,0,0,16,10306,16887),(10308,6380,6380,6380,6380,6,85,16758,39,120,16,7499,10309),(10309,6380,6380,6380,6380,6,85,16759,39,120,16,10308,10310),(10310,6380,6380,6380,6380,6,85,16760,39,120,16,10309,13170),(10311,-1,-1,1134,1134,3,85,-1,0,0,16,4808,10312),(10312,-1,-1,1134,1134,3,85,-1,0,0,16,10311,10313),(10313,-1,-1,1134,1134,3,85,-1,0,0,16,10312,10314),(10314,-1,-1,1134,1134,3,85,-1,0,0,16,10313,10315),(10315,-1,-1,1134,1134,3,85,-1,0,0,16,10314,13035),(10316,-1,-1,4809,4809,5,85,-1,0,0,16,4811,10317),(10317,-1,-1,4809,4809,5,85,-1,0,0,16,10316,10318),(10318,-1,-1,4809,4809,5,85,-1,0,0,16,10317,13040),(10319,6931,6931,6931,6931,12,85,16774,41,600,16,6931,13058),(10320,6932,6932,6932,6932,7,85,16775,42,1200,16,6934,10321),(10321,6932,6932,6932,6932,7,85,16776,42,1200,16,10320,10322),(10322,6932,6932,6932,6932,7,85,16777,42,1200,16,10321,13062),(10323,4854,4854,4854,4854,12,85,16768,8,600,16,7180,10324),(10324,4854,4854,4854,4854,12,85,16769,8,600,16,10323,10325),(10325,4854,4854,4854,4854,12,85,16770,8,600,16,10324,13059),(10326,1178,1178,1178,1178,9,85,16771,4,900,16,7189,10327),(10327,1178,1178,1178,1178,9,85,16772,4,900,16,10326,10328),(10328,1178,1178,1178,1178,9,85,16773,4,900,16,10327,13845),(10329,-1,-1,10329,10329,5,85,0,0,0,16,-1,10398),(10330,10330,10330,10330,10330,7,85,16785,35,30,16,-1,13203),(10331,10331,10331,10331,10331,6,85,16787,44,20,16,-1,-1),(10332,-1,-1,10332,10332,3,85,-1,0,0,16,-1,12733),(10333,10333,10333,10333,10333,5,85,16788,55,120,16,-1,10334),(10334,10333,10333,10333,10333,7,85,16789,55,120,16,10333,10335),(10335,10333,10333,10333,10333,9,85,16790,55,120,16,10334,12724),(10336,10336,10336,10336,10336,5,85,16791,58,8,16,-1,10337),(10337,10336,10336,10336,10336,7,85,16792,58,8,16,10336,10338),(10338,10336,10336,10336,10336,9,85,16793,58,8,16,10337,12730),(10339,10339,10339,10339,10339,12,85,16786,48,1800,16,-1,-1),(10340,-1,-1,10340,10340,3,80,-1,0,0,16,-1,10341),(10341,-1,-1,10340,10340,6,83,-1,0,0,16,10340,10342),(10342,-1,-1,10340,10340,9,85,-1,0,0,16,10341,13184),(10343,-1,-1,10343,10343,5,85,0,0,0,16,-1,10344),(10344,-1,-1,10343,10343,7,85,0,0,0,16,10343,10345),(10345,-1,-1,10343,10343,9,85,0,0,0,16,10344,13841),(10346,10346,10346,10346,10346,9,85,21783,46,600,16,-1,13183),(10347,-1,-1,7945,7945,6,85,-1,0,0,16,10034,17310),(10348,0,0,10348,10348,5,80,-1,0,0,16,-1,10349),(10349,0,0,10348,10348,7,83,-1,0,0,16,10348,10350),(10350,0,0,10348,10348,9,85,-1,0,0,16,10349,13578),(10351,10351,10351,10351,10351,12,85,21785,34,600,16,-1,10682),(10352,10352,10352,10352,10352,12,85,21786,34,600,16,-1,10683),(10353,10353,10353,10353,10353,12,85,21787,34,600,16,-1,10684),(10354,10354,10354,10354,10354,8,85,21653,39,4320,16,-1,14016),(10355,-1,-1,10355,10355,6,83,-1,0,0,16,-1,10356),(10356,-1,-1,10355,10355,8,84,-1,0,0,16,10355,10357),(10357,-1,-1,10355,10355,10,85,-1,0,0,16,10356,10643),(10358,-1,-1,10358,10358,7,80,-1,0,0,16,-1,10359),(10359,-1,-1,10358,10358,9,83,-1,0,0,16,10358,10360),(10360,-1,-1,10358,10358,12,85,-1,0,0,16,10359,14210),(10361,-1,-1,962,962,5,83,-1,0,0,16,6227,10362),(10362,-1,-1,962,962,5,84,-1,0,0,16,10361,10363),(10363,-1,-1,962,962,5,85,-1,0,0,16,10362,14218),(10364,-1,-1,10364,10364,5,85,-1,0,0,16,-1,10365),(10365,-1,-1,10364,10364,7,85,-1,0,0,16,10364,10366),(10366,-1,-1,10364,10364,9,85,-1,0,0,16,10365,10442),(10367,10367,10367,10367,10367,12,85,21751,30,360,16,-1,10630),(10368,10368,10368,10368,10368,6,85,21654,46,900,16,-1,10369),(10369,10368,10368,10368,10368,9,85,21655,46,900,16,10368,10386),(10370,-1,-1,10370,10370,3,60,-1,0,0,16,-1,10371),(10371,-1,-1,10370,10370,3,60,-1,0,0,16,10370,10372),(10372,-1,-1,10370,10370,3,60,-1,0,0,16,10371,13927),(10373,10373,10373,10373,10373,6,75,16806,62,6,16,-1,-1),(10374,10374,10374,10374,10374,6,85,16800,63,900,16,-1,10375),(10375,10374,10374,10374,10374,6,85,16801,63,900,16,10374,10376),(10376,10374,10374,10374,10374,6,85,16802,63,900,16,10375,13174),(10377,10377,10377,10377,10377,6,85,16794,64,60,16,-1,10378),(10378,10377,10377,10377,10377,6,85,16795,64,60,16,10377,10379),(10379,10377,10377,10377,10377,6,85,16796,64,60,16,10378,13180),(10380,-1,-1,10380,10380,6,85,-1,0,0,16,-1,10381),(10381,-1,-1,10380,10380,6,85,-1,0,0,16,10380,10382),(10382,-1,-1,10380,10380,6,85,-1,0,0,16,10381,13477),(10383,-1,-1,5085,5085,6,85,-1,0,0,16,7386,10384),(10384,-1,-1,5085,5085,6,85,-1,0,0,16,10383,10385),(10385,-1,-1,5085,5085,6,85,-1,0,0,16,10384,-1),(10386,10368,10368,10368,10368,12,85,21656,46,900,16,10369,-1),(10387,10387,10387,10387,10387,9,85,21835,45,1200,16,-1,-1),(10388,-1,-1,10388,10388,12,85,-1,0,0,16,-1,13545),(10389,-1,-1,10389,10389,9,83,0,0,0,16,-1,10390),(10390,-1,-1,10389,10389,11,84,0,0,0,16,10389,10391),(10391,-1,-1,10389,10389,12,85,0,0,0,16,10390,-1),(10392,10392,10392,10392,10392,12,85,21751,11,480,16,-1,10631),(10393,10393,10393,10393,10393,9,81,3246,42,2,16,-1,-1),(10394,10394,10394,10394,10394,12,85,21821,30,600,16,-1,10704),(10395,10395,10395,10395,10395,3,80,21748,62,5,16,-1,12590),(10396,10396,10396,10396,10396,12,85,16857,14,600,16,-1,10790),(10397,10397,10397,10397,10397,12,85,16858,14,600,16,-1,10791),(10398,-1,-1,10329,10329,7,85,0,0,0,16,10329,10399),(10399,-1,-1,10329,10329,9,85,0,0,0,16,10398,-1),(10400,10400,10400,10400,10400,6,85,16807,62,900,16,-1,15558),(10401,-1,-1,10401,10401,6,85,-1,0,0,16,-1,10402),(10402,-1,-1,10401,10401,6,85,-1,0,0,16,10401,10403),(10403,-1,-1,10401,10401,6,85,-1,0,0,16,10402,13052),(10404,-1,-1,10404,10404,6,85,-1,0,0,16,-1,13051),(10405,-1,-1,10405,10405,7,81,0,0,0,16,-1,10406),(10406,-1,-1,10405,10405,7,82,0,0,0,16,10405,10407),(10407,-1,-1,10405,10405,7,83,0,0,0,16,10406,10408),(10408,-1,-1,10405,10405,7,84,0,0,0,16,10407,10409),(10409,-1,-1,10405,10405,7,85,0,0,0,16,10408,10671),(10410,-1,-1,10410,10410,8,85,-1,0,0,16,-1,10411),(10413,-1,-1,10413,10413,5,81,0,0,0,16,-1,10414),(10414,-1,-1,10413,10413,5,81,0,0,0,16,10413,10415),(10415,-1,-1,10413,10413,5,81,0,0,0,16,10414,10416),(10416,-1,-1,10413,10413,5,81,0,0,0,16,10415,10417),(10417,-1,-1,10413,10413,5,81,0,0,0,16,10416,-1),(10418,6561,6561,6561,6561,7,85,21808,32,30,16,10101,10419),(10419,6561,6561,6561,6561,7,85,21810,32,30,16,10418,10420),(10420,6561,6561,6561,6561,7,85,21811,32,30,16,10419,14256),(10421,10506,10506,10506,10506,9,85,23521,66,120,16,10508,-1),(10424,10424,10424,10424,10424,7,81,21813,41,6,16,-1,-1),(10425,10425,10425,10425,10425,7,81,21814,39,6,16,-1,-1),(10426,10426,10426,10426,10426,10,85,21816,5,900,16,-1,-1),(10427,10427,10427,10427,10427,12,85,21818,30,900,16,-1,-1),(10428,4931,4931,4931,4931,7,85,21838,4,600,16,10276,10429),(10429,4931,4931,4931,4931,7,85,21839,4,600,16,10428,10430),(10430,4931,4931,4931,4931,7,85,21844,4,600,16,10429,13241),(10431,-1,-1,8031,8031,6,85,-1,0,0,16,10284,10432),(10432,-1,-1,8031,8031,6,85,-1,0,0,16,10431,10433),(10433,-1,-1,8031,8031,6,85,-1,0,0,16,10432,-1),(10434,-1,-1,10434,10434,7,85,0,0,0,16,-1,10435),(10435,-1,-1,10434,10434,9,85,0,0,0,16,10434,10436),(10436,-1,-1,10434,10434,12,85,0,0,0,16,10435,-1),(10437,-1,-1,6601,6601,6,86,-1,0,0,17,10029,10438),(10438,-1,-1,6601,6601,6,87,-1,0,0,17,10437,10439),(10439,-1,-1,6601,6601,6,88,-1,0,0,17,10438,10440),(10440,-1,-1,6601,6601,6,89,-1,0,0,17,10439,10441),(10442,-1,-1,10364,10364,9,86,-1,0,0,17,10366,10443),(10443,-1,-1,10364,10364,9,88,-1,0,0,17,10442,-1),(10450,10450,10450,10450,10450,7,85,16808,63,900,16,-1,10451),(10451,10450,10450,10450,10450,7,85,16809,63,900,16,10450,10452),(10452,10450,10450,10450,10450,7,85,16810,63,900,16,10451,10468),(10453,-1,-1,10453,10453,5,85,-1,0,0,16,-1,10454),(10454,-1,-1,10453,10453,7,85,-1,0,0,16,10453,10455),(10455,-1,-1,10453,10453,9,85,-1,0,0,16,10454,13607),(10456,-1,-1,10456,10456,5,85,-1,0,0,16,-1,10457),(10457,-1,-1,10456,10456,7,85,-1,0,0,16,10456,10458),(10458,-1,-1,10456,10456,9,85,-1,0,0,16,10457,-1),(10459,-1,-1,10459,10459,5,65,-1,0,0,16,-1,10460),(10460,-1,-1,10459,10459,7,65,-1,0,0,16,10459,10461),(10461,-1,-1,10459,10459,9,65,-1,0,0,16,10460,-1),(10462,10462,10462,10462,10462,12,85,16811,14,4320,16,-1,-1),(10463,10463,10463,10463,10463,12,85,16812,16,4320,16,-1,-1),(10464,-1,-1,10464,10464,5,80,-1,0,0,16,-1,10465),(10465,-1,-1,10464,10464,7,80,-1,0,0,16,10464,10466),(10466,-1,-1,10464,10464,9,80,-1,0,0,16,10465,13140),(10467,-1,-1,86,86,8,85,-1,0,0,17,266,-1),(10468,10450,10450,10450,10450,7,85,23603,63,900,17,10452,10469),(10469,10450,10450,10450,10450,7,85,23604,63,900,17,10468,10670),(10470,-1,-1,10470,10470,9,86,-1,0,0,17,-1,10471),(10471,-1,-1,10470,10470,12,88,-1,0,0,17,10470,10472),(10472,-1,-1,10470,10470,15,90,-1,0,0,17,10471,15828),(10473,-1,-1,446,735,10,86,-1,0,0,17,7624,10474),(10474,-1,-1,446,735,10,87,-1,0,0,17,10473,10475),(10475,-1,-1,446,735,10,88,-1,0,0,17,10474,10476),(10476,-1,-1,446,735,10,89,-1,0,0,17,10475,10477),(10477,-1,-1,446,735,10,90,-1,0,0,17,10476,13308),(10478,-1,-1,10478,10478,15,101,-1,0,0,21,-1,10479),(10481,10481,10481,10481,10481,21,105,46249,90,600,21,-1,-1),(10500,10500,10500,10500,10500,7,85,16813,62,12,16,-1,-1),(10501,10501,10501,10501,10501,7,85,16814,63,1,16,-1,-1),(10502,10502,-1,10502,10502,7,85,1566,64,120,16,-1,12647),(10503,10503,10503,10503,10503,9,85,16816,13,600,16,-1,10504),(10504,10503,10503,10503,10503,9,85,16817,13,600,16,10503,10505),(10505,10503,10503,10503,10503,9,85,16818,13,600,16,10504,12648),(10506,10506,10506,10506,10506,9,85,16819,66,120,16,-1,10507),(10507,10506,10506,10506,10506,9,85,16820,66,120,16,10506,10508),(10508,10506,10506,10506,10506,9,85,16821,66,120,16,10507,10421),(10509,5105,5105,5105,5105,12,85,16822,11,600,16,7420,13154),(10510,7986,7986,7986,7986,12,85,16823,11,600,16,7988,13155),(10511,-1,-1,10511,10511,6,85,-1,0,0,16,-1,10512),(10512,-1,-1,10511,10511,6,85,-1,0,0,16,10511,10513),(10513,-1,-1,10511,10511,6,85,-1,0,0,16,10512,12642),(10514,-1,-1,10514,10514,6,85,-1,0,0,16,-1,10516),(10515,-1,-1,10514,10514,6,85,-1,0,0,16,10516,12639),(10516,-1,-1,10514,10514,6,85,-1,0,0,16,10514,10515),(10517,6565,6565,6565,6565,9,88,23608,17,45,17,10010,10518),(10519,-1,-1,10519,10519,9,86,0,0,0,17,-1,10520),(10522,-1,-1,10522,10522,7,86,0,0,0,17,-1,10523),(10527,-1,-1,10527,10527,5,86,0,0,0,17,-1,10528),(10532,-1,-1,10532,10532,5,86,0,0,0,17,-1,10533),(10537,-1,-1,10537,10537,5,86,0,0,0,17,-1,10538),(10545,10545,10545,10545,10545,12,85,23531,73,600,17,-1,-1),(10546,10546,10546,10546,10546,12,85,23528,74,600,17,-1,-1),(10548,-1,-1,10548,10548,9,86,-1,0,0,17,-1,10549),(10550,10550,10550,10550,10550,7,85,16824,61,120,16,-1,13250),(10551,-1,-1,10551,10551,6,85,-1,0,0,16,-1,10552),(10552,-1,-1,10551,10551,6,85,-1,0,0,16,10551,10553),(10553,-1,-1,10551,10551,6,85,-1,0,0,16,10552,14764),(10554,-1,-1,1572,1572,5,80,-1,0,0,16,1576,10555),(10555,-1,-1,1572,1572,5,80,-1,0,0,16,10554,10556),(10556,-1,-1,1572,1572,5,80,-1,0,0,16,10555,16062),(10557,12395,12395,12395,12395,9,75,16828,11,900,16,-1,-1),(10558,-1,-1,10558,10558,6,80,-1,0,0,16,-1,10559),(10559,-1,-1,10558,10558,6,83,-1,0,0,16,10558,10560),(10560,-1,-1,10558,10558,6,85,-1,0,0,16,10559,15469),(10561,-1,-1,10561,10561,6,85,-1,0,0,16,-1,10562),(10562,-1,-1,10561,10561,6,85,-1,0,0,16,10561,10563),(10563,-1,-1,10561,10561,6,85,-1,0,0,16,10562,15466),(10564,773,-1,773,773,12,85,16829,5,1800,16,7278,10565),(10565,773,-1,773,773,12,85,16830,5,1800,16,10564,10566),(10566,773,-1,773,773,12,85,16831,5,1800,16,10565,13734),(10568,-1,-1,6564,6564,10,86,-1,0,0,17,10009,10569),(10571,1597,1597,1597,1597,9,85,23611,6,10,17,6606,-1),(10572,6617,6617,6617,6617,12,86,23612,42,3600,17,6617,14036),(10573,6610,6610,6610,6610,9,86,23613,41,30,17,10003,13422),(10574,-1,-1,6611,6611,6,85,-1,0,0,17,6619,16121),(10575,-1,-1,6614,6614,9,85,-1,0,0,17,10005,-1),(10576,-1,-1,492,492,2,87,-1,0,0,17,7130,-1),(10578,258,-1,258,258,9,86,27520,1,600,17,258,16003),(10579,-1,-1,7036,10579,9,85,0,0,0,17,7038,10580),(10580,-1,-1,7036,10579,12,87,0,0,0,17,10579,10581),(10585,912,912,912,912,9,86,23617,4,3600,17,10013,10586),(10588,-1,-1,10588,10588,5,86,0,0,0,17,-1,10589),(10589,-1,-1,10588,10588,5,87,0,0,0,17,10588,10590),(10590,-1,-1,10588,10588,5,88,0,0,0,17,10589,10591),(10591,-1,-1,10588,10588,5,89,0,0,0,17,10590,10592),(10592,-1,-1,10588,10588,5,90,0,0,0,17,10591,17206),(10600,10600,10600,10600,10600,7,85,16832,73,20,16,-1,10601),(10601,10600,10600,10600,10600,7,85,16833,73,20,16,10600,10602),(10602,10600,10600,10600,10600,7,85,16834,73,20,16,10601,12982),(10603,10601,10601,10601,10601,3,85,16835,62,6,16,-1,-1),(10604,-1,-1,6051,6051,3,85,-1,0,0,16,7603,10605),(10605,-1,-1,6051,6051,3,85,-1,0,0,16,10604,10606),(10606,-1,-1,6051,6051,3,85,-1,0,0,16,10605,12795),(10607,-1,-1,6383,6383,9,80,-1,0,0,16,6385,10608),(10608,-1,-1,6383,6383,9,80,-1,0,0,16,10607,10609),(10609,-1,-1,6383,6383,9,80,-1,0,0,16,10608,12801),(10610,-1,-1,10610,10610,3,70,-1,0,0,16,-1,10611),(10611,-1,-1,10610,10610,3,70,-1,0,0,16,10610,10612),(10612,-1,-1,10610,10610,3,70,-1,0,0,16,10611,-1),(10618,7850,7850,7850,7850,9,86,23532,39,4320,17,7340,10619),(10619,7850,7850,7850,7850,12,88,23533,39,4320,17,10618,10620),(10620,7850,7850,7850,7850,15,90,23534,39,4320,17,10619,13604),(10621,-1,-1,849,849,9,85,-1,0,0,17,851,10622),(10622,-1,-1,849,849,9,87,-1,0,0,17,10621,16604),(10623,-1,-1,255,255,9,85,-1,0,0,17,5808,10624),(10624,-1,-1,255,255,12,87,-1,0,0,17,10623,10625),(10625,-1,-1,255,255,15,89,-1,0,0,17,10624,13589),(10626,5984,5984,5984,5984,12,90,23535,2,30,17,7711,13592),(10627,-1,-1,10627,10627,3,59,0,0,0,3,-1,10628),(10628,-1,-1,10627,10627,3,59,0,0,0,3,10627,10629),(10629,-1,-1,10627,10627,3,59,0,0,0,3,10628,-1),(10630,10367,10367,10367,10367,12,90,27642,30,360,17,10367,13434),(10631,10392,10392,10392,10392,12,90,27642,11,480,17,10392,-1),(10632,-1,-1,735,735,10,86,-1,0,0,17,7627,10633),(10633,-1,-1,735,735,10,87,-1,0,0,17,10632,10634),(10634,-1,-1,735,735,10,88,-1,0,0,17,10633,10635),(10635,-1,-1,735,735,10,89,-1,0,0,17,10634,10636),(10636,-1,-1,735,735,10,90,-1,0,0,17,10635,13884),(10637,-1,-1,1287,1287,9,86,-1,0,0,17,12471,10638),(10638,-1,-1,1287,1287,12,88,-1,0,0,17,10637,10639),(10639,-1,-1,1287,1287,15,90,-1,0,0,17,10638,13323),(10640,5095,5095,5095,5095,9,85,23620,10,900,17,7334,10641),(10641,5095,5095,5095,5095,12,87,23621,10,900,17,10640,10642),(10642,5095,5095,5095,5095,15,89,23622,10,900,17,10641,13575),(10643,-1,-1,10355,10355,10,86,-1,0,0,17,10357,10644),(10644,-1,-1,10355,10355,10,88,-1,0,0,17,10643,10645),(10645,-1,-1,10355,10355,10,90,-1,0,0,17,10644,14094),(10646,7712,7712,7712,7712,15,90,23536,2,30,17,7712,13585),(10647,188,188,188,188,9,88,23537,2,30,17,7662,13586),(10650,-1,-1,10650,10650,7,85,-1,0,0,16,-1,10651),(10651,-1,-1,10650,10650,9,85,-1,0,0,16,10650,10652),(10652,-1,-1,10650,10650,12,85,-1,0,0,16,10651,13804),(10653,-1,-1,10653,10653,7,85,-1,0,0,16,-1,10654),(10654,-1,-1,10653,10653,7,85,-1,0,0,16,10653,10655),(10655,-1,-1,10653,10653,7,85,-1,0,0,16,10654,17406),(10656,-1,-1,10656,10656,7,85,-1,0,0,16,-1,12678),(10657,-1,-1,10657,10657,7,85,-1,0,0,16,-1,10658),(10658,-1,-1,10657,10657,7,85,-1,0,0,16,10657,10659),(10659,-1,-1,10657,10657,7,85,-1,0,0,16,10658,12679),(10660,-1,-1,820,820,5,85,-1,0,0,16,7165,10661),(10661,-1,-1,820,820,5,85,-1,0,0,16,10660,10662),(10662,-1,-1,820,820,5,85,-1,0,0,16,10661,12667),(10663,-1,-1,6020,6020,2,85,-1,0,0,16,7171,10664),(10664,-1,-1,6020,6020,2,85,-1,0,0,16,10663,10665),(10665,-1,-1,6020,6020,2,85,-1,0,0,16,10664,12670),(10666,-1,-1,495,495,6,85,-1,0,0,16,6262,10667),(10667,-1,-1,495,495,5,85,-1,0,0,16,10666,10668),(10668,-1,-1,495,495,7,85,-1,0,0,16,10667,17391),(10670,10450,10450,10450,10450,7,85,23605,63,900,17,10469,15839),(10671,-1,-1,10405,10405,9,86,0,0,0,17,10409,10672),(10672,-1,-1,10405,10405,9,87,0,0,0,17,10671,10673),(10673,-1,-1,10405,10405,9,88,0,0,0,17,10672,10674),(10674,-1,-1,10405,10405,9,89,0,0,0,17,10673,10675),(10675,-1,-1,10405,10405,9,90,0,0,0,17,10674,-1),(10676,-1,-1,6791,6791,6,86,-1,0,0,17,10046,10677),(10677,-1,-1,6791,6791,6,88,-1,0,0,17,10676,10678),(10678,-1,-1,6791,6791,6,90,-1,0,0,17,10677,13598),(10679,6492,6492,6492,6492,9,85,23626,52,720,17,6497,10680),(10680,6492,6492,6492,6492,9,87,23627,52,720,17,10679,10681),(10681,6492,6492,6492,6492,9,89,23628,52,720,17,10680,14003),(10682,10351,10351,10351,10351,15,90,23538,34,600,17,10351,-1),(10683,10352,10352,10352,10352,15,90,23539,34,600,17,10352,-1),(10684,10353,10353,10353,10353,15,90,23540,34,600,17,10353,-1),(10685,-1,-1,602,602,9,86,-1,0,0,17,5582,10686),(10686,-1,-1,602,602,12,88,-1,0,0,17,10685,10687),(10687,-1,-1,602,602,15,90,-1,0,0,17,10686,13610),(10688,-1,-1,855,855,7,86,-1,0,0,17,7677,10689),(10689,-1,-1,855,855,7,87,-1,0,0,17,10688,10690),(10690,-1,-1,855,855,7,88,-1,0,0,17,10689,10691),(10691,-1,-1,855,855,7,89,-1,0,0,17,10690,10692),(10692,-1,-1,855,855,7,90,-1,0,0,17,10691,13613),(10700,10700,10700,10700,10700,7,85,16839,61,10,16,-1,-1),(10701,10701,10701,10701,10701,7,85,21662,32,360,16,-1,10702),(10702,10701,10701,10701,10701,9,85,21663,32,360,16,10701,10703),(10703,10701,10701,10701,10701,12,85,21664,32,360,16,10702,12754),(10704,10394,10394,10394,10394,12,85,23541,30,300,17,10394,13584),(10705,-1,-1,6395,6395,9,86,-1,0,0,17,10052,10706),(10706,-1,-1,6395,6395,9,88,-1,0,0,17,10705,10707),(10707,-1,-1,6395,6395,9,90,-1,0,0,17,10706,14097),(10708,534,534,534,534,12,86,23545,4,2160,17,10049,10709),(10709,534,534,534,534,12,88,23546,4,2160,17,10708,10710),(10710,534,534,534,534,12,90,23547,4,2160,17,10709,13595),(10711,10711,10711,10711,10711,9,86,23548,75,1200,17,-1,10712),(10712,10711,10711,10711,10711,12,88,23549,75,1200,17,10711,10713),(10713,10711,10711,10711,10711,15,90,23550,75,1200,17,10712,14006),(10714,-1,-1,10714,10714,9,86,0,0,0,17,-1,10715),(10715,-1,-1,10714,10714,12,88,0,0,0,17,10714,10716),(10717,-1,-1,7743,7743,9,61,-1,0,0,17,7745,10718),(10718,-1,-1,7743,7743,9,61,-1,0,0,17,10717,15258),(10719,-1,-1,10719,10719,9,75,0,0,0,17,-1,10720),(10720,-1,-1,10719,10719,12,75,0,0,0,17,10719,10721),(10721,-1,-1,10719,10719,15,75,0,0,0,17,10720,13562),(10722,-1,-1,10722,10722,5,81,0,0,0,17,-1,10723),(10723,-1,-1,10722,10722,5,82,0,0,0,17,10722,10724),(10724,-1,-1,10722,10722,7,83,0,0,0,17,10723,10725),(10725,-1,-1,10722,10722,9,84,0,0,0,17,10724,10726),(10726,-1,-1,10722,10722,12,85,0,0,0,17,10725,15280),(10727,-1,-1,10727,10727,7,86,0,0,0,17,-1,10728),(10728,-1,-1,10727,10727,9,88,0,0,0,17,10727,10729),(10730,-1,-1,10730,10730,7,86,0,0,0,17,-1,10731),(10731,-1,-1,10730,10730,9,88,0,0,0,17,10730,10732),(10733,-1,-1,10733,10733,7,81,0,0,0,17,-1,10734),(10734,-1,-1,10733,10733,9,83,0,0,0,17,10733,10735),(10735,-1,-1,10733,10733,12,85,0,0,0,17,10734,-1),(10736,10736,10736,10736,10736,7,86,23632,5,180,17,-1,10737),(10737,10736,10736,10736,10736,9,88,23633,5,180,17,10736,10738),(10739,645,-1,645,645,12,86,23551,4,5,17,5999,13410),(10740,1345,1345,1345,1345,9,86,23552,6,900,17,7349,10741),(10741,1345,1345,1345,1345,12,88,23553,6,900,17,10740,10742),(10743,-1,-1,1196,1196,5,86,-1,0,0,17,1200,10744),(10744,-1,-1,1196,1196,5,87,-1,0,0,17,10743,10745),(10745,-1,-1,1196,1196,5,88,-1,0,0,17,10744,10746),(10748,-1,-1,867,867,7,86,-1,0,0,17,7366,10749),(10749,-1,-1,867,867,7,87,-1,0,0,17,10748,10755),(10750,-1,-1,7103,7103,2,70,-1,0,0,16,7328,10751),(10751,-1,-1,7103,7103,2,70,-1,0,0,16,10750,-1),(10752,10752,10752,10752,10752,6,85,16843,72,600,16,-1,-1),(10753,10753,10753,10753,10753,12,80,16844,6,4320,16,-1,-1),(10754,10754,10754,10754,10754,2,70,16845,62,5,16,-1,-1),(10755,-1,-1,867,867,7,88,-1,0,0,17,10749,10756),(10758,545,545,545,545,12,86,23638,3,900,17,7346,10759),(10759,545,545,545,545,12,87,23639,3,900,17,10758,10760),(10760,545,545,545,545,12,88,23640,3,900,17,10759,10761),(10763,-1,-1,6761,6761,12,86,-1,0,0,17,6087,10764),(10764,-1,-1,6761,6761,12,88,-1,0,0,17,10763,10765),(10766,-1,-1,6765,6765,9,85,-1,0,0,17,10060,10767),(10767,-1,-1,6765,6765,9,87,-1,0,0,17,10766,10768),(10768,-1,-1,6765,6765,9,89,-1,0,0,17,10767,13553),(10769,-1,-1,6751,6751,9,86,-1,0,0,17,6769,10770),(10770,-1,-1,6751,6751,9,88,-1,0,0,17,10769,10771),(10772,872,872,872,872,9,85,23555,5,180,17,7369,10773),(10773,872,872,872,872,9,87,23556,5,180,17,10772,10774),(10774,872,872,872,872,9,89,23557,5,180,17,10773,-1),(10775,875,875,875,875,9,85,23561,5,180,17,7372,10776),(10776,875,875,875,875,9,87,23562,5,180,17,10775,10777),(10777,875,875,875,875,9,89,23563,5,180,17,10776,13536),(10778,-1,-1,634,634,12,85,-1,0,0,17,7714,10779),(10779,-1,-1,634,634,12,87,-1,0,0,17,10778,10780),(10780,-1,-1,634,634,12,89,-1,0,0,17,10779,15585),(10781,-1,-1,8240,8240,9,85,-1,0,0,17,8244,10782),(10782,-1,-1,8240,8240,9,86,-1,0,0,17,10781,10783),(10783,-1,-1,8240,8240,9,87,-1,0,0,17,10782,10784),(10784,-1,-1,8240,8240,9,88,-1,0,0,17,10783,10785),(10785,-1,-1,8240,8240,9,89,-1,0,0,17,10784,13343),(10786,7800,7800,7800,7800,12,85,23567,39,4320,17,7817,10787),(10787,7800,7800,7800,7800,12,87,23568,39,4320,17,10786,13619),(10788,-1,-1,4699,4699,7,65,-1,0,0,17,7500,-1),(10789,10789,10789,10789,10789,15,90,23575,41,6,17,-1,14261),(10790,10396,10396,10396,10396,15,90,23576,14,600,17,10396,14024),(10791,10397,10397,10397,10397,15,90,23577,14,600,17,10397,14025),(10792,-1,-1,10792,10792,5,86,0,0,0,17,-1,10793),(10793,-1,-1,10792,10792,7,87,0,0,0,17,10792,10794),(10794,-1,-1,10792,10792,9,88,0,0,0,17,10793,10795),(10795,-1,-1,10792,10792,11,89,0,0,0,17,10794,10796),(10796,-1,-1,10792,10792,13,90,0,0,0,17,10795,17365),(10800,-1,-1,10800,10800,6,70,-1,0,0,16,-1,10801),(10801,-1,-1,10800,10800,9,70,-1,0,0,16,10800,10802),(10802,-1,-1,10800,10800,12,70,-1,0,0,16,10801,17476),(10803,-1,-1,10803,10803,6,76,-1,0,0,16,-1,10804),(10804,-1,-1,10803,10803,6,78,-1,0,0,16,10803,10805),(10805,-1,-1,10803,10803,6,80,-1,0,0,16,10804,-1),(10806,10806,10806,10806,10806,10,80,16846,71,540,16,-1,10807),(10807,10806,10806,10806,10806,11,80,16847,71,540,16,10806,10808),(10808,10806,10806,10806,10806,12,80,16848,71,540,16,10807,15298),(10809,10809,10809,10809,10809,10,80,16849,71,540,16,-1,10810),(10810,10809,10809,10809,10809,11,80,16850,71,540,16,10809,10811),(10811,10809,10809,10809,10809,12,80,16851,71,540,16,10810,15301),(10815,10815,10815,10815,10815,6,80,-1,0,0,16,-1,10816),(10816,10815,10815,10815,10815,9,80,-1,0,0,16,10815,10817),(10817,10815,10815,10815,10815,12,80,-1,0,0,16,10816,13110),(10818,10818,10818,10818,10818,6,80,-1,0,0,16,-1,10819),(10819,10818,10818,10818,10818,9,80,-1,0,0,16,10818,10820),(10820,10818,10818,10818,10818,12,80,-1,0,0,16,10819,13113),(10821,10821,10821,10821,10821,6,80,-1,0,0,16,-1,10822),(10822,10821,10821,10821,10821,9,80,-1,0,0,16,10821,10823),(10823,10821,10821,10821,10821,12,80,-1,0,0,16,10822,13116),(10824,510,510,510,510,6,86,23578,37,240,17,10104,10825),(10850,-1,-1,10850,10850,6,85,16864,0,0,16,-1,10851),(10851,-1,-1,10850,10850,6,85,16865,0,0,16,10850,10852),(10852,-1,-1,10850,10850,6,85,16866,0,0,16,10851,13207),(10853,-1,-1,10853,10853,3,65,-1,0,0,16,-1,10854),(10854,-1,-1,10853,10853,6,65,-1,0,0,16,10853,10855),(10855,-1,-1,10853,10853,9,65,-1,0,0,16,10854,10856),(10856,-1,-1,10853,10853,5,66,-1,0,0,16,10855,10857),(10857,-1,-1,10853,10853,5,68,-1,0,0,16,10856,10858),(10858,-1,-1,10853,10853,5,70,-1,0,0,16,10857,10859),(10859,-1,-1,10853,10853,5,76,-1,0,0,16,10858,10860),(10860,-1,-1,10853,10853,5,78,-1,0,0,16,10859,10861),(10861,-1,-1,10853,10853,5,80,-1,0,0,16,10860,10862),(10862,-1,-1,10853,10853,5,81,-1,0,0,16,10861,10863),(10863,-1,-1,10853,10853,5,83,-1,0,0,16,10862,10864),(10864,-1,-1,10853,10853,5,85,-1,0,0,16,10863,15954),(10865,-1,-1,1304,1304,12,85,-1,0,0,16,7150,10866),(10866,-1,-1,1304,1304,12,85,-1,0,0,16,10865,10867),(10867,-1,-1,1304,1304,12,85,-1,0,0,16,10866,13218),(10868,5021,5021,5021,5021,9,76,16867,7,60,16,5021,10869),(10869,5021,5021,5021,5021,9,81,16868,7,60,16,10868,10870),(10870,5021,5021,5021,5021,9,85,16869,7,60,16,10869,12618),(10900,10900,10900,10900,10900,9,85,16870,55,120,16,-1,10901),(10901,10900,10900,10900,10900,9,85,16871,55,120,16,10900,10902),(10902,10900,10900,10900,10900,9,85,16872,55,120,16,10901,13624),(10903,-1,-1,10903,10903,6,81,-1,0,0,16,-1,10904),(10904,-1,-1,10903,10903,6,83,-1,0,0,16,10903,10905),(10905,-1,-1,10903,10903,6,85,-1,0,0,16,10904,-1),(10906,-1,-1,895,895,12,85,-1,0,0,16,7406,10907),(10907,-1,-1,895,895,12,85,-1,0,0,16,10906,10908),(10908,-1,-1,895,895,12,85,-1,0,0,16,10907,13627),(10909,-1,-1,10909,10909,6,85,-1,0,0,16,-1,10910),(10910,-1,-1,10909,10909,6,85,-1,0,0,16,10909,10911),(10911,-1,-1,10909,10909,6,85,-1,0,0,16,10910,-1),(10912,10912,10912,10912,10912,6,85,16873,69,1800,16,-1,10913),(10913,10912,10912,10912,10912,6,85,16874,69,1800,16,10912,10914),(10914,10912,10912,10912,10912,6,85,16875,69,1800,16,10913,14053),(10915,-1,-1,10915,10915,9,85,-1,0,0,16,-1,10916),(10916,-1,-1,10915,10915,9,85,-1,0,0,16,10915,10917),(10917,-1,-1,10915,10915,9,85,-1,0,0,16,10916,16189),(10950,-1,-1,10950,10950,6,85,-1,0,0,16,-1,-1),(10951,-1,-1,10951,10951,12,85,-1,0,0,16,-1,10952),(10952,-1,-1,10951,10951,12,85,-1,0,0,16,10951,10953),(10953,-1,-1,10951,10951,12,85,-1,0,0,16,10952,15363),(10954,-1,-1,10954,10954,12,85,-1,0,0,16,-1,10955),(10955,-1,-1,10954,10954,12,85,-1,0,0,16,10954,10956),(10956,-1,-1,10954,10954,12,85,-1,0,0,16,10955,-1),(10957,10957,10957,10957,10957,6,85,16879,61,5,16,-1,-1),(10958,10958,10958,10958,10958,12,85,16880,62,900,16,-1,13000),(10959,10959,10959,10959,10959,12,85,16881,63,600,16,-1,10961),(10961,10959,10959,10959,10959,12,85,21717,63,600,16,10959,10962),(10962,10959,10959,10959,10959,12,85,21718,63,600,16,10961,12988),(11000,-1,-1,11000,11000,6,85,-1,0,0,16,-1,11001),(11001,-1,-1,11000,11000,9,85,-1,0,0,16,11000,11002),(11002,-1,-1,11000,11000,12,85,-1,0,0,16,11001,-1),(11003,-1,-1,11003,11003,6,85,-1,0,0,16,-1,-1),(11004,-1,-1,11004,11004,6,85,-1,0,0,16,-1,11005),(11005,-1,-1,11004,11004,6,85,-1,0,0,16,11004,11006),(11006,-1,-1,11004,11004,6,85,-1,0,0,16,11005,-1),(11011,-1,-1,6302,6302,5,85,0,0,0,16,6304,11012),(11012,-1,-1,6302,6302,5,85,0,0,0,16,11011,11013),(11013,-1,-1,6302,6302,5,85,0,0,0,16,11012,15552),(11014,-1,-1,11007,11007,5,80,-1,0,0,16,-1,11015),(11015,-1,-1,11007,11007,7,82,-1,0,0,16,11014,11016),(11016,-1,-1,11007,11007,9,85,-1,0,0,16,11015,11020),(11020,-1,-1,11007,11007,12,86,-1,0,0,17,11016,-1),(11050,-1,-1,11050,11050,6,85,-1,0,0,16,-1,11051),(11051,-1,-1,11050,11050,6,85,-1,0,0,16,11050,11052),(11052,-1,-1,11050,11050,6,85,-1,0,0,16,11051,11059),(11053,-1,-1,6349,6349,6,83,-1,0,0,16,7620,11054),(11054,-1,-1,6349,6349,6,83,-1,0,0,16,11053,-1),(11055,11055,11055,11055,11055,3,85,16884,63,20,16,-1,-1),(11056,11056,11056,11056,11056,6,85,16885,64,180,16,-1,-1),(11057,11057,11057,11057,11057,2,85,1422,65,10,16,-1,-1),(11058,11058,11058,11058,11058,2,85,3243,66,10,16,-1,-1),(11059,-1,-1,11050,11050,6,85,-1,0,0,16,11052,11060),(11060,-1,-1,11050,11050,6,85,-1,0,0,16,11059,12871),(11061,-1,-1,98,98,12,85,-1,0,0,16,7586,11062),(11062,-1,-1,98,98,12,85,-1,0,0,16,11061,11063),(11063,-1,-1,98,98,12,85,-1,0,0,16,11062,13921),(11064,6290,6290,6290,6290,7,85,23500,0,1,16,7225,11065),(11065,6290,6290,6290,6290,9,85,23501,0,1,16,11064,11066),(11066,6290,6290,6290,6290,12,85,23502,0,1,16,11065,13229),(11067,4944,-1,4944,4944,7,85,23506,0,1,16,7231,11068),(11068,4944,-1,4944,4944,9,85,23507,0,1,16,11067,11069),(11069,4944,-1,4944,4944,12,85,23508,0,1,16,11068,13232),(11070,1478,-1,1478,1478,9,85,23512,0,1,16,7244,11071),(11071,1478,-1,1478,1478,10,85,23513,0,1,16,11070,11072),(11072,1478,-1,1478,1478,12,85,23514,0,1,16,11071,13235),(11073,11073,11073,11073,11073,12,85,23518,53,30,16,-1,13447),(11074,-1,-1,11074,11074,5,81,0,0,0,16,-1,11075),(11075,-1,-1,11074,11074,7,83,0,0,0,16,11074,11076),(11076,-1,-1,11074,11074,9,85,0,0,0,16,11075,-1),(11077,-1,-1,11077,11077,5,81,0,0,0,16,-1,15895),(11078,-1,-1,11078,11078,5,81,0,0,0,16,-1,15891),(11079,-1,-1,11079,11079,5,81,0,0,0,16,-1,15893),(11080,11080,11080,11080,11080,7,85,23519,10,20,16,-1,13472),(11081,153,153,153,153,12,85,23599,3,2160,16,10193,12996),(11082,-1,-1,1131,1131,6,81,-1,0,0,16,1133,11083),(11083,-1,-1,1131,1131,9,83,-1,0,0,16,11082,11084),(11084,-1,-1,1131,1131,12,85,-1,0,0,16,11083,13032),(11085,-1,-1,11085,11085,7,85,0,0,0,16,-1,11086),(11086,-1,-1,11085,11085,9,85,0,0,0,16,11085,11087),(11087,-1,-1,11085,11085,12,85,0,0,0,16,11086,13021),(11088,-1,-1,11088,11088,6,75,0,0,0,16,-1,11089),(11089,-1,-1,11088,11088,6,75,0,0,0,16,11088,11090),(11090,-1,-1,11088,11088,6,75,0,0,0,16,11089,11091),(11091,-1,-1,11088,11088,6,75,0,0,0,16,11090,-1),(12396,-1,-1,125,125,8,85,-1,0,0,16,7505,12397),(12397,-1,-1,125,125,9,85,-1,0,0,16,12396,12398),(12398,-1,-1,125,125,10,85,-1,0,0,16,12397,12399),(12399,-1,-1,125,125,11,85,-1,0,0,16,12398,12400),(12400,-1,-1,125,125,12,85,-1,0,0,16,12399,13080),(12401,-1,-1,122,122,8,85,-1,0,0,16,7510,12402),(12402,-1,-1,122,122,9,85,-1,0,0,16,12401,12403),(12403,-1,-1,122,122,10,85,-1,0,0,16,12402,12404),(12404,-1,-1,122,122,11,85,-1,0,0,16,12403,12405),(12405,-1,-1,122,122,12,85,-1,0,0,16,12404,13085),(12406,-1,-1,6119,6119,6,85,-1,0,0,16,7530,12407),(12407,-1,-1,6119,6119,6,85,-1,0,0,16,12406,12408),(12408,-1,-1,6119,6119,6,85,-1,0,0,16,12407,12409),(12409,-1,-1,6119,6119,6,85,-1,0,0,16,12408,12410),(12410,-1,-1,6119,6119,6,85,-1,0,0,16,12409,12492),(12411,-1,-1,8255,8255,6,85,-1,0,0,16,8259,12412),(12412,-1,-1,8255,8255,6,85,-1,0,0,16,12411,12413),(12413,-1,-1,8255,8255,6,85,-1,0,0,16,12412,12414),(12414,-1,-1,8255,8255,6,85,-1,0,0,16,12413,12415),(12415,-1,-1,8255,8255,6,85,-1,0,0,16,12414,13358),(12416,-1,-1,12416,12416,7,83,-1,0,0,16,-1,12417),(12417,-1,-1,12416,12416,9,84,-1,0,0,16,12416,12418),(12418,-1,-1,12416,12416,12,85,-1,0,0,16,12417,13413),(12419,-1,-1,12419,12419,5,83,-1,0,0,16,-1,12420),(12420,-1,-1,12419,12419,5,84,-1,0,0,16,12419,12421),(12421,-1,-1,12419,12419,5,85,-1,0,0,16,12420,12575),(12422,12422,12422,12422,12422,12,85,13994,47,12,16,-1,-1),(12423,-1,-1,767,767,9,81,-1,0,0,16,1101,12424),(12424,-1,-1,767,767,10,83,-1,0,0,16,12423,12425),(12425,-1,-1,767,767,12,85,-1,0,0,16,12424,-1),(12426,-1,-1,767,767,3,81,-1,0,0,16,6245,12427),(12427,-1,-1,767,767,6,83,-1,0,0,16,12426,12428),(12428,-1,-1,767,767,9,85,-1,0,0,16,12427,-1),(12432,-1,-1,1107,1107,10,81,-1,0,0,16,6405,12433),(12433,-1,-1,1107,1107,11,83,-1,0,0,16,12432,12434),(12434,-1,-1,1107,1107,12,85,-1,0,0,16,12433,12556),(12435,-1,-1,637,637,8,81,-1,0,0,16,5573,12436),(12436,-1,-1,637,637,10,83,-1,0,0,16,12435,12437),(12437,-1,-1,637,637,12,85,-1,0,0,16,12436,12553),(12438,-1,-1,686,686,5,85,-1,0,0,16,7640,-1),(12439,-1,-1,1592,1592,9,85,-1,0,0,16,7572,12440),(12440,-1,-1,1592,1592,10,85,-1,0,0,16,12439,12441),(12441,-1,-1,1592,1592,11,85,-1,0,0,16,12440,12442),(12442,-1,-1,1592,1592,12,85,-1,0,0,16,12441,12443),(12443,-1,-1,1592,1592,12,85,-1,0,0,16,12442,12532),(12444,-1,-1,1072,1072,8,85,-1,0,0,16,7580,12445),(12445,-1,-1,1072,1072,9,85,-1,0,0,16,12444,12446),(12446,-1,-1,1072,1072,10,85,-1,0,0,16,12445,12447),(12447,-1,-1,1072,1072,11,85,-1,0,0,16,12446,12448),(12448,-1,-1,1072,1072,12,85,-1,0,0,16,12447,12537),(12449,-1,-1,77,77,10,81,-1,0,0,16,1085,12450),(12450,-1,-1,77,77,11,83,-1,0,0,16,12449,12451),(12451,-1,-1,77,77,12,85,-1,0,0,16,12450,12497),(12452,-1,-1,80,80,12,85,-1,0,0,16,7592,12453),(12453,-1,-1,80,80,12,85,-1,0,0,16,12452,12454),(12454,-1,-1,80,80,12,85,-1,0,0,16,12453,12567),(12455,-1,-1,658,658,5,85,-1,0,0,16,7597,12456),(12456,-1,-1,658,658,5,85,-1,0,0,16,12455,12457),(12457,-1,-1,658,658,5,85,-1,0,0,16,12456,12458),(12458,-1,-1,658,658,5,85,-1,0,0,16,12457,12459),(12459,-1,-1,658,658,5,85,-1,0,0,16,12458,12570),(12460,6537,6537,6537,6537,7,83,20172,30,900,16,7608,12461),(12461,6537,6537,6537,6537,8,83,20173,30,900,16,12460,12462),(12462,6537,6537,6537,6537,9,83,20174,30,900,16,12461,12520),(12463,-1,-1,5263,5263,7,81,-1,0,0,16,6129,12464),(12464,-1,-1,5263,5263,8,81,-1,0,0,16,12463,12465),(12465,-1,-1,5263,5263,9,81,-1,0,0,16,12464,16173),(12466,-1,-1,5263,5263,7,81,-1,0,0,16,5622,12467),(12467,-1,-1,5263,5263,9,81,-1,0,0,16,12466,12468),(12468,-1,-1,5263,5263,12,81,-1,0,0,16,12467,15714),(12469,-1,-1,1287,1287,7,81,-1,0,0,16,5518,12470),(12470,-1,-1,1287,1287,9,81,-1,0,0,16,12469,12471),(12471,-1,-1,1287,1287,12,81,-1,0,0,16,12470,10637),(12472,-1,-1,1287,1287,8,81,-1,0,0,16,6430,12473),(12473,-1,-1,1287,1287,9,81,-1,0,0,16,12472,12474),(12474,-1,-1,1287,1287,10,81,-1,0,0,16,12473,13238),(12475,-1,-1,12430,12430,5,85,0,0,0,16,-1,12476),(12476,-1,-1,12430,12430,7,85,0,0,0,16,12475,12477),(12477,-1,-1,12430,12430,9,85,0,0,0,16,12476,12876),(12478,-1,-1,12478,12478,5,85,0,0,0,16,-1,12479),(12479,-1,-1,12478,12478,7,85,0,0,0,16,12478,12480),(12480,-1,-1,12478,12478,9,85,0,0,0,16,12479,-1),(12481,-1,-1,6540,6540,8,85,-1,0,0,16,6473,12482),(12482,-1,-1,6540,6540,8,85,-1,0,0,16,12481,12508),(12483,-1,-1,6540,6540,8,85,-1,0,0,16,6475,12484),(12484,-1,-1,6540,6540,8,85,-1,0,0,16,12483,12511),(12485,-1,-1,6540,6540,8,85,-1,0,0,16,6477,12486),(12486,-1,-1,6540,6540,8,85,-1,0,0,16,12485,12514),(12487,-1,-1,6540,6540,8,83,-1,0,0,16,6471,12488),(12488,-1,-1,6540,6540,8,85,-1,0,0,16,12487,12517),(12492,-1,-1,6119,6119,6,85,-1,0,0,17,12410,12493),(12493,-1,-1,6119,6119,6,86,-1,0,0,17,12492,12494),(12494,-1,-1,6119,6119,6,87,-1,0,0,17,12493,12495),(12495,-1,-1,6119,6119,6,88,-1,0,0,17,12494,12496),(12496,-1,-1,6119,6119,6,89,-1,0,0,17,12495,8448),(12497,-1,-1,77,77,12,86,-1,0,0,17,12451,12498),(12498,-1,-1,77,77,12,88,-1,0,0,17,12497,12499),(12499,-1,-1,77,77,12,90,-1,0,0,17,12498,13296),(12500,-1,-1,12500,12500,5,81,-1,0,0,16,-1,12501),(12501,-1,-1,12500,12500,7,81,-1,0,0,16,12500,12502),(12502,-1,-1,12500,12500,9,81,-1,0,0,16,12501,12505),(12505,-1,-1,12500,12500,11,83,-1,0,0,16,12502,12506),(12506,-1,-1,12500,12500,12,85,-1,0,0,16,12505,-1),(12507,-1,-1,199,199,12,81,-1,0,0,16,201,-1),(12508,-1,-1,6540,6540,8,86,-1,0,0,17,12482,12509),(12509,-1,-1,6540,6540,8,88,-1,0,0,17,12508,12510),(12510,-1,-1,6540,6540,8,90,-1,0,0,17,12509,16440),(12511,-1,-1,6540,6540,8,86,-1,0,0,17,12484,12512),(12512,-1,-1,6540,6540,8,88,-1,0,0,17,12511,12513),(12513,-1,-1,6540,6540,8,90,-1,0,0,17,12512,12591),(12514,-1,-1,6540,6540,8,86,-1,0,0,17,12486,12515),(12515,-1,-1,6540,6540,8,88,-1,0,0,17,12514,12516),(12516,-1,-1,6540,6540,8,90,-1,0,0,17,12515,12594),(12517,-1,-1,6540,6540,8,86,-1,0,0,17,12488,12518),(12518,-1,-1,6540,6540,8,88,-1,0,0,17,12517,12519),(12519,-1,-1,6540,6540,8,90,-1,0,0,17,12518,12597),(12520,6537,6537,6537,6537,7,86,23974,30,900,17,12462,12521),(12521,6537,6537,6537,6537,8,88,23975,30,900,17,12520,12522),(12522,6537,6537,6537,6537,9,90,23976,30,900,17,12521,13275),(12523,-1,-1,1210,1210,7,86,-1,0,0,17,7234,12524),(12526,-1,-1,1210,1213,12,86,-1,0,0,17,8346,12527),(12527,-1,-1,1210,1213,12,88,-1,0,0,17,12526,12528),(12528,-1,-1,1210,1213,12,90,-1,0,0,17,12527,14349),(12529,-1,-1,6636,6636,9,86,-1,0,0,17,10043,12530),(12530,-1,-1,6636,6636,10,88,-1,0,0,17,12529,12531),(12531,-1,-1,6636,6636,11,90,-1,0,0,17,12530,16164),(12532,-1,-1,1592,1592,9,86,-1,0,0,17,12443,12533),(12533,-1,-1,1592,1592,10,87,-1,0,0,17,12532,12534),(12534,-1,-1,1592,1592,11,88,-1,0,0,17,12533,12535),(12535,-1,-1,1592,1592,12,89,-1,0,0,17,12534,12536),(12536,-1,-1,1592,1592,12,90,-1,0,0,17,12535,13930),(12537,-1,-1,1072,1072,8,86,-1,0,0,17,12448,12538),(12538,-1,-1,1072,1072,9,87,-1,0,0,17,12537,12539),(12539,-1,-1,1072,1072,10,88,-1,0,0,17,12538,12540),(12540,-1,-1,1072,1072,11,89,-1,0,0,17,12539,12541),(12541,-1,-1,1072,1072,12,90,-1,0,0,17,12540,13281),(12548,-1,-1,119,119,12,86,-1,0,0,17,6025,12549),(12549,-1,-1,119,119,12,87,-1,0,0,17,12548,12550),(12550,-1,-1,119,119,12,88,-1,0,0,17,12549,12551),(12551,-1,-1,119,119,12,89,-1,0,0,17,12550,12552),(12552,-1,-1,119,119,12,90,-1,0,0,17,12551,13286),(12553,-1,-1,637,637,8,86,-1,0,0,17,12437,12554),(12554,-1,-1,637,637,10,88,-1,0,0,17,12553,12555),(12555,-1,-1,637,637,12,90,-1,0,0,17,12554,14361),(12556,-1,-1,1107,1107,10,86,-1,0,0,17,12434,12557),(12557,-1,-1,1107,1107,11,88,-1,0,0,17,12556,12558),(12558,-1,-1,1107,1107,12,90,-1,0,0,17,12557,16489),(12559,-1,-1,8215,8215,5,86,-1,0,0,17,8219,12560),(12560,-1,-1,8215,8215,5,87,-1,0,0,17,12559,12561),(12561,-1,-1,8215,8215,5,88,-1,0,0,17,12560,12562),(12562,-1,-1,8215,8215,5,89,-1,0,0,17,12561,12563),(12563,-1,-1,8215,8215,5,90,-1,0,0,17,12562,15694),(12564,-1,-1,1186,1186,12,86,-1,0,0,17,7694,12565),(12565,-1,-1,1186,1186,12,88,-1,0,0,17,12564,12566),(12566,-1,-1,1186,1186,12,90,-1,0,0,17,12565,13299),(12567,-1,-1,80,80,12,86,-1,0,0,17,12454,12568),(12568,-1,-1,80,80,12,88,-1,0,0,17,12567,12569),(12569,-1,-1,80,80,12,90,-1,0,0,17,12568,13302),(12570,-1,-1,658,658,5,86,-1,0,0,17,12459,12571),(12571,-1,-1,658,658,5,87,-1,0,0,17,12570,12572),(12572,-1,-1,658,658,5,88,-1,0,0,17,12571,12573),(12573,-1,-1,658,658,5,89,-1,0,0,17,12572,12574),(12574,-1,-1,658,658,5,90,-1,0,0,17,12573,13313),(12575,-1,-1,12419,12419,9,90,-1,0,0,17,12421,13520),(12576,-1,-1,852,852,12,86,-1,0,0,17,7680,12577),(12577,-1,-1,852,852,12,88,-1,0,0,17,12576,12578),(12578,-1,-1,852,852,12,90,-1,0,0,17,12577,13601),(12579,-1,-1,1313,1313,12,86,-1,0,0,17,10083,12580),(12580,-1,-1,1313,1313,12,88,-1,0,0,17,12579,12581),(12581,-1,-1,1313,1313,12,90,-1,0,0,17,12580,14043),(12582,-1,-1,12582,12582,7,85,0,0,0,17,-1,12583),(12583,-1,-1,12582,12582,9,87,0,0,0,17,12582,12584),(12584,-1,-1,12582,12582,12,89,0,0,0,17,12583,15174),(12585,6640,6640,6640,6640,9,86,23572,43,60,17,6640,-1),(12586,6644,6644,6644,6644,2,86,23573,44,20,17,6644,-1),(12587,-1,-1,7757,7757,9,86,-1,0,0,17,7759,12588),(12588,-1,-1,7757,7757,9,88,-1,0,0,17,12587,12589),(12589,-1,-1,7757,7757,9,90,-1,0,0,17,12588,15182),(12590,10395,10395,10395,10395,5,85,23574,62,5,17,10395,-1),(12591,-1,-1,6540,6540,15,91,-1,0,0,18,12513,12592),(12594,-1,-1,6540,6540,11,91,-1,0,0,18,12516,12595),(12597,-1,-1,6540,6540,9,91,-1,0,0,18,12519,12598),(12598,-1,-1,6540,6540,11,93,-1,0,0,18,12597,12599),(12600,-1,-1,12600,12600,7,85,0,0,0,17,-1,13072),(12603,-1,-1,12603,12603,10,70,0,0,0,17,-1,-1),(12606,-1,-1,12606,12606,6,85,0,0,0,17,-1,-1),(12607,-1,-1,12607,12607,6,74,0,0,0,17,-1,14140),(12610,-1,-1,255,255,9,87,-1,0,0,17,7702,13773),(12612,-1,-1,1604,1604,10,85,-1,0,0,17,7009,12613),(12613,-1,-1,1604,1604,12,87,-1,0,0,17,12612,13095),(12615,-1,-1,12615,12615,10,85,0,0,0,17,-1,12616),(12616,-1,-1,12615,12615,12,87,0,0,0,17,12615,12617),(12617,-1,-1,12615,12615,14,89,0,0,0,17,12616,14138),(12618,5021,5021,5021,5021,9,86,24009,7,60,17,10870,12619),(12619,5021,5021,5021,5021,9,87,24010,7,60,17,12618,12620),(12620,5021,5021,5021,5021,9,88,24011,7,60,17,12619,12621),(12621,5021,5021,5021,5021,9,89,24012,7,60,17,12620,13785),(12626,9354,9354,9354,9354,5,86,23996,40,600,17,9356,-1),(12629,9357,9357,9357,9357,5,86,24002,40,600,17,9359,-1),(12632,9360,9360,9360,9360,5,86,24005,40,600,17,9362,-1),(12633,6325,6325,6325,6325,7,85,24008,18,600,17,6361,13792),(12635,12635,12635,12635,12635,12,90,23643,12,5,17,-1,-1),(12636,-1,-1,12636,12636,0,1,-1,0,0,16,-1,12637),(12637,-1,-1,12636,12636,0,1,-1,0,0,16,12636,8445),(12638,12638,12638,12638,12638,9,85,23581,68,10,17,-1,-1),(12639,-1,-1,10514,10514,6,86,-1,0,0,17,10515,12640),(12642,-1,-1,10511,10511,6,86,-1,0,0,17,10513,12643),(12645,-1,-1,12645,12645,9,90,0,0,0,17,-1,15386),(12646,-1,-1,12646,12646,9,90,0,0,0,17,-1,15388),(12647,10502,-1,10502,10502,7,90,16815,64,120,17,10502,-1),(12648,10503,10503,10503,10503,9,86,23582,13,600,17,10505,12649),(12651,12651,12651,12651,12651,15,90,23585,69,600,17,-1,17352),(12652,-1,-1,12652,12652,9,86,0,0,0,17,-1,12653),(12653,-1,-1,12652,12652,12,88,0,0,0,17,12652,12654),(12654,-1,-1,12652,12652,15,90,0,0,0,17,12653,13411),(12655,12655,12655,12655,12655,9,86,23586,70,1800,17,-1,12656),(12658,757,-1,757,757,12,86,23589,6,1800,17,7413,12659),(12661,12661,12661,12661,12661,9,86,23592,73,2700,17,-1,12662),(12664,-1,-1,12664,12664,7,86,0,0,0,17,-1,12665),(12667,-1,-1,820,820,5,86,-1,0,0,17,10662,12668),(12668,-1,-1,820,820,5,88,-1,0,0,17,12667,12669),(12669,-1,-1,820,820,5,90,-1,0,0,17,12668,13820),(12670,-1,-1,6020,6020,2,86,-1,0,0,17,10665,12671),(12671,-1,-1,6020,6020,2,87,-1,0,0,17,12670,12672),(12672,-1,-1,6020,6020,2,88,-1,0,0,17,12671,12692),(12673,-1,-1,1546,1546,5,80,-1,0,0,17,6441,-1),(12674,-1,-1,4801,4801,6,86,-1,0,0,17,10123,12675),(12675,-1,-1,4801,4801,6,88,-1,0,0,17,12674,12676),(12676,-1,-1,4801,4801,6,90,-1,0,0,17,12675,-1),(12677,-1,-1,230,230,6,90,-1,0,0,17,541,16249),(12678,-1,-1,10656,10656,12,90,0,0,0,17,10656,-1),(12679,-1,-1,10657,10657,7,86,0,0,0,17,10659,12680),(12680,-1,-1,10657,10657,9,88,0,0,0,17,12679,12681),(12681,-1,-1,10657,10657,12,90,0,0,0,17,12680,14154),(12682,7872,7872,7872,7872,6,86,23595,41,600,17,10129,12683),(12683,7872,7872,7872,7872,6,88,23596,41,600,17,12682,12684),(12684,7872,7872,7872,7872,6,90,23597,41,600,17,12683,13838),(12685,-1,-1,807,807,5,86,-1,0,0,17,7630,12686),(12686,-1,-1,807,807,5,88,-1,0,0,17,12685,12687),(12687,-1,-1,807,807,5,90,-1,0,0,17,12686,-1),(12688,-1,-1,12688,12688,12,90,0,0,0,17,-1,-1),(12689,-1,-1,7884,7884,12,87,-1,0,0,17,7884,-1),(12690,-1,-1,7885,7885,12,86,-1,0,0,17,7885,-1),(12691,-1,-1,12691,12691,12,88,0,0,0,17,-1,-1),(12692,-1,-1,6020,6020,2,89,-1,0,0,17,12672,12693),(12693,-1,-1,6020,6020,2,90,-1,0,0,17,12692,13823),(12694,-1,-1,683,683,5,86,-1,0,0,17,7605,12695),(12695,-1,-1,683,683,5,88,-1,0,0,17,12694,12696),(12696,-1,-1,683,683,5,90,-1,0,0,17,12695,13305),(12697,-1,-1,1041,1041,12,86,-1,0,0,17,7564,12698),(12698,-1,-1,1041,1041,12,88,-1,0,0,17,12697,12699),(12699,-1,-1,1041,1041,12,90,-1,0,0,17,12698,13332),(12700,1355,1355,1355,1355,9,86,23644,3,60,17,10121,12701),(12701,1355,1355,1355,1355,9,88,23645,3,60,17,12700,12702),(12702,1355,1355,1355,1355,9,90,23646,3,60,17,12701,13832),(12703,-1,-1,611,611,4,86,-1,0,0,17,10126,12704),(12704,-1,-1,611,611,4,88,-1,0,0,17,12703,12705),(12705,-1,-1,611,611,4,90,-1,0,0,17,12704,13835),(12706,-1,-1,12706,12706,7,86,0,0,0,17,-1,12707),(12707,-1,-1,12706,12706,9,88,0,0,0,17,12706,12708),(12708,-1,-1,12706,12706,12,90,0,0,0,17,12707,13813),(12709,-1,-1,12709,12709,9,86,-1,0,0,17,-1,-1),(12710,-1,-1,12710,12710,9,86,0,0,0,17,-1,12711),(12711,-1,-1,12710,12710,12,88,0,0,0,17,12710,12712),(12712,-1,-1,12710,12710,15,90,0,0,0,17,12711,14173),(12713,-1,-1,12713,12713,7,86,0,0,0,17,-1,12714),(12714,-1,-1,12713,12713,7,88,0,0,0,17,12713,12715),(12715,-1,-1,12713,12713,7,90,0,0,0,17,12714,-1),(12716,-1,-1,12716,12716,7,86,0,0,0,17,-1,12717),(12717,-1,-1,12716,12716,7,88,0,0,0,17,12716,12718),(12718,-1,-1,12716,12716,7,90,0,0,0,17,12717,15526),(12719,-1,-1,12719,12719,9,90,0,0,0,17,-1,-1),(12720,-1,-1,12720,12720,9,86,0,0,0,17,-1,-1),(12721,-1,-1,12721,12721,7,86,0,0,0,17,-1,12722),(12722,-1,-1,12721,12721,9,88,0,0,0,17,12721,12723),(12723,-1,-1,12721,12721,12,90,0,0,0,17,12722,16303),(12724,10333,10333,10333,10333,9,86,23647,55,120,17,10335,12725),(12725,10333,10333,10333,10333,9,86,23648,55,120,17,12724,12726),(12726,10333,10333,10333,10333,9,86,23649,55,120,17,12725,15988),(12727,-1,-1,1555,1555,7,86,0,0,0,17,1557,12728),(12728,-1,-1,1555,1555,7,88,0,0,0,17,12727,12729),(12729,-1,-1,1555,1555,7,90,0,0,0,17,12728,-1),(12730,10336,10336,10336,10336,9,86,23650,58,8,17,10338,12731),(12731,10336,10336,10336,10336,12,88,23651,58,8,17,12730,12732),(12732,10336,10336,10336,10336,15,90,23652,58,8,17,12731,13517),(12733,-1,-1,10332,10332,7,90,-1,0,0,17,10332,-1),(12734,-1,-1,6375,6375,9,86,-1,0,0,17,10138,12735),(12735,-1,-1,6375,6375,9,88,-1,0,0,17,12734,12736),(12736,-1,-1,6375,6375,9,90,-1,0,0,17,12735,13502),(12737,-1,-1,12737,12737,9,86,0,0,0,17,-1,12738),(12738,-1,-1,12737,12737,9,88,0,0,0,17,12737,12739),(12739,-1,-1,12737,12737,9,90,0,0,0,17,12738,15961),(12740,6533,6533,6533,6533,10,86,23653,15,600,17,10139,12741),(12741,6533,6533,6533,6533,10,88,23654,15,600,17,12740,12742),(12742,6533,6533,6533,6533,10,90,23655,15,600,17,12741,13505),(12743,1116,1116,1116,1116,12,86,23656,4,2160,17,10142,12744),(12744,1116,1116,1116,1116,12,88,23657,4,2160,17,12743,12745),(12745,1116,1116,1116,1116,12,90,23658,4,2160,17,12744,13530),(12746,5298,5298,5298,5298,12,86,23659,32,1800,17,10145,12747),(12747,5298,5298,5298,5298,12,88,23660,32,1800,17,12746,12748),(12748,5298,5298,5298,5298,12,90,23661,32,1800,17,12747,13514),(12749,592,592,592,592,5,86,23665,2,18,17,7437,12750),(12750,592,592,592,592,5,88,23666,2,18,17,12749,12751),(12751,592,592,592,592,5,90,23667,2,18,17,12750,13499),(12754,10701,10701,10701,10701,12,86,23668,32,360,17,10703,12755),(12755,10701,10701,10701,10701,12,88,23669,32,360,17,12754,12756),(12756,10701,10701,10701,10701,12,90,23670,32,360,17,12755,15588),(12757,-1,-1,4861,4861,12,86,-1,0,0,17,7682,12758),(12758,-1,-1,4861,4861,12,88,-1,0,0,17,12757,12759),(12759,-1,-1,4861,4861,12,90,-1,0,0,17,12758,-1),(12760,1274,1274,1274,1274,12,86,23674,9,540,17,10211,12761),(12761,1274,1274,1274,1274,12,88,23675,9,540,17,12760,12762),(12762,1274,1274,1274,1274,12,90,23676,9,540,17,12761,14352),(12766,12766,12766,12766,12766,15,90,23677,69,3600,17,-1,13682),(12767,-1,-1,692,692,12,86,-1,0,0,17,7672,12768),(12768,-1,-1,692,692,12,88,-1,0,0,17,12767,12769),(12769,-1,-1,692,692,12,90,-1,0,0,17,12768,17295),(12770,12770,12770,12770,12770,9,85,23678,52,120,17,-1,12771),(12771,12770,12770,12770,12770,12,87,23679,52,120,17,12770,12772),(12772,12770,12770,12770,12770,15,89,23680,52,120,17,12771,-1),(12773,-1,-1,12773,12773,7,86,0,0,0,17,-1,12774),(12774,-1,-1,12773,12773,7,87,0,0,0,17,12773,12775),(12775,-1,-1,12773,12773,7,88,0,0,0,17,12774,12776),(12776,-1,-1,12773,12773,7,89,0,0,0,17,12775,12777),(12777,-1,-1,12773,12773,7,90,0,0,0,17,12776,-1),(12778,12778,12778,12778,12778,12,90,23681,74,1200,17,-1,13678),(12779,-1,-1,12779,12779,7,85,0,0,0,17,-1,12780),(12780,-1,-1,12779,12779,9,87,0,0,0,17,12779,12781),(12781,-1,-1,12779,12779,12,89,0,0,0,17,12780,-1),(12782,-1,-1,12782,12782,7,86,0,0,0,17,-1,12783),(12783,-1,-1,12782,12782,9,88,0,0,0,17,12782,12784),(12784,-1,-1,12782,12782,12,90,0,0,0,17,12783,-1),(12785,12785,12785,12785,12785,12,90,23683,80,30,17,-1,17131),(12786,6815,6815,6815,6815,8,86,23684,60,600,17,10202,12787),(12787,6815,6815,6815,6815,8,88,23685,60,600,17,12786,12788),(12788,6815,6815,6815,6815,8,90,23686,60,600,17,12787,14355),(12789,967,967,967,967,7,85,23687,10,1800,17,10226,12790),(12790,967,967,967,967,7,87,23688,10,1800,17,12789,12791),(12791,967,967,967,967,7,89,23689,10,1800,17,12790,17535),(12792,-1,-1,9503,9503,7,86,-1,0,0,17,10089,12793),(12793,-1,-1,9503,9503,7,88,-1,0,0,17,12792,12794),(12794,-1,-1,9503,9503,7,90,-1,0,0,17,12793,5360),(12795,-1,-1,6051,6051,5,85,-1,0,0,17,10606,12796),(12796,-1,-1,6051,6051,5,87,-1,0,0,17,12795,12797),(12797,-1,-1,6051,6051,5,89,-1,0,0,17,12796,13278),(12798,-1,-1,5264,5264,12,86,-1,0,0,17,10217,12799),(12799,-1,-1,5264,5264,12,88,-1,0,0,17,12798,12800),(12800,-1,-1,5264,5264,12,90,-1,0,0,17,12799,13675),(12801,-1,-1,6383,6383,9,85,-1,0,0,17,10609,12802),(12802,-1,-1,6383,6383,9,87,-1,0,0,17,12801,12803),(12803,-1,-1,6383,6383,9,89,-1,0,0,17,12802,5339),(12804,12804,12804,12804,12804,7,86,23693,75,900,17,-1,12805),(12807,12807,12807,12807,12807,7,86,23699,73,1200,17,-1,12808),(12810,8227,8227,8227,12810,5,85,27402,71,10,17,8227,12811),(12811,8227,8227,8227,12810,7,87,27403,71,10,17,12810,12812),(12812,8227,8227,8227,12810,9,89,27404,71,10,17,12811,-1),(12813,-1,-1,1287,1287,5,75,-1,0,0,17,-1,12814),(12814,-1,-1,1287,1287,5,77,-1,0,0,17,12813,12815),(12815,-1,-1,1287,1287,5,79,-1,0,0,17,12814,14279),(12816,-1,-1,12816,12816,7,86,0,0,0,17,-1,12817),(12819,-1,-1,12819,12819,9,85,0,0,0,17,-1,12820),(12820,-1,-1,12819,12819,12,87,0,0,0,17,12819,12821),(12822,-1,-1,12822,12822,9,86,0,0,0,17,-1,12823),(12828,291,291,291,12828,12,86,27409,5,900,17,10304,12829),(12831,-1,-1,12831,12831,7,86,0,0,0,17,-1,12832),(12834,-1,-1,6980,6980,5,85,-1,0,0,17,6982,12835),(12835,-1,-1,6980,6980,5,87,-1,0,0,17,12834,12836),(12837,12837,12837,12837,12837,7,86,27412,74,420,17,-1,12838),(12840,-1,-1,6977,6977,5,85,-1,0,0,17,6979,12841),(12841,-1,-1,6977,6977,5,87,-1,0,0,17,12840,12842),(12843,-1,-1,551,551,5,86,-1,0,0,17,6907,12844),(12846,-1,-1,12846,12846,7,86,6499,0,0,17,-1,12847),(12849,-1,-1,12849,12849,7,86,0,0,0,17,-1,12850),(12857,8072,8072,8072,8072,7,86,27419,37,20,17,10248,12858),(12860,-1,-1,267,267,12,86,-1,0,0,17,5619,12861),(12863,-1,-1,141,12863,12,59,-1,0,0,17,143,15396),(12864,12864,-1,12864,12864,5,59,27422,73,10,17,-1,17486),(12865,12865,12865,12865,12865,12,90,27423,42,6,17,-1,-1),(12866,12866,12866,12866,12866,12,86,27424,74,1800,17,-1,15605),(12867,12867,12867,12867,12867,12,86,27426,13,4320,17,-1,-1),(12868,1334,1334,1334,1334,12,86,27427,11,4320,17,10236,12869),(12871,-1,-1,11050,11050,9,85,-1,0,0,17,11060,12872),(12872,-1,-1,11050,11050,12,87,-1,0,0,17,12871,12873),(12874,-1,-1,1414,1414,5,86,-1,0,0,17,1418,17490),(12875,4938,4938,4938,4938,12,90,27430,35,1800,17,5614,13727),(12876,-1,-1,12430,12430,7,86,0,0,0,17,12477,12877),(12877,-1,-1,12430,12430,9,88,0,0,0,17,12876,12878),(12878,-1,-1,12430,12430,12,90,0,0,0,17,12877,15270),(12879,516,516,516,516,6,86,27431,5,480,17,10233,13659),(12880,1404,1404,1404,1404,7,85,27432,15,2160,17,1408,-1),(12881,-1,-1,12881,12881,9,86,0,0,0,17,-1,12882),(12885,12885,12885,12885,12885,12,86,27435,75,90,17,-1,17491),(12886,-1,-1,12886,12886,2,85,-1,0,0,17,-1,-1),(12887,-1,-1,12887,12887,2,87,-1,0,0,17,-1,-1),(12888,-1,-1,12888,12888,2,89,-1,0,0,17,-1,-1),(12889,-1,-1,12889,12889,2,85,-1,0,0,17,-1,12890),(12890,-1,-1,12889,12889,2,87,-1,0,0,17,12889,12891),(12892,12892,12892,12892,12892,3,90,27434,8,60,17,-1,13666),(12893,12893,12893,12893,12893,12,90,27436,76,1800,17,-1,13663),(12894,-1,-1,12894,12894,5,86,0,0,0,17,-1,12895),(12899,-1,-1,471,471,2,85,-1,0,0,17,473,12900),(12900,-1,-1,471,471,2,87,-1,0,0,17,12899,12901),(12902,-1,-1,12902,12902,5,85,0,0,0,17,-1,12903),(12903,-1,-1,12902,12902,5,86,0,0,0,17,12902,12904),(12907,-1,-1,12907,12907,5,85,0,0,0,17,-1,12908),(12908,-1,-1,12907,12907,5,86,0,0,0,17,12907,12909),(12912,-1,-1,12912,12912,5,85,0,0,0,17,-1,12913),(12913,-1,-1,12912,12912,5,86,0,0,0,17,12912,12914),(12917,517,517,517,517,5,85,27437,12,600,17,10281,12918),(12918,517,517,517,517,5,87,27438,12,600,17,12917,12919),(12920,-1,-1,12920,12920,5,86,0,0,0,17,-1,12921),(12923,54009,54009,54009,12923,3,85,27440,22,12,17,5849,12924),(12924,54009,54009,54009,12923,3,87,27441,22,12,17,12923,12925),(12929,-1,-1,6548,6548,8,85,-1,0,0,17,6238,12930),(12930,-1,-1,6548,6548,8,90,-1,0,0,17,12929,15463),(12931,12931,12931,12931,12931,7,86,27443,73,3600,17,-1,12932),(12934,1242,1242,1242,1242,12,86,27446,9,1320,17,10273,12935),(12937,12937,12937,12937,12937,12,86,27449,16,420,17,-1,13733),(12938,12938,12938,12938,12938,15,88,27450,75,2700,17,-1,13743),(12939,12939,12939,12939,12939,12,90,27451,77,1800,17,-1,14756),(12941,12941,12941,12941,12941,5,85,27453,77,1,17,-1,-1),(12942,6539,6539,6539,6539,6,86,27454,18,1800,17,7611,12943),(12943,6539,6539,6539,6539,6,88,27455,18,1800,17,12942,12944),(12944,6539,6539,6539,6539,6,90,27456,18,1800,17,12943,13291),(12945,-1,-1,795,795,12,85,-1,0,0,17,10267,12946),(12946,-1,-1,795,795,12,86,-1,0,0,17,12945,12947),(12947,-1,-1,795,795,12,87,-1,0,0,17,12946,12948),(12948,-1,-1,795,795,12,88,-1,0,0,17,12947,12949),(12949,-1,-1,795,795,12,89,-1,0,0,17,12948,13710),(12950,-1,-1,790,790,6,86,-1,0,0,17,7274,12951),(12951,-1,-1,790,790,6,87,-1,0,0,17,12950,12952),(12952,-1,-1,790,790,6,88,-1,0,0,17,12951,12953),(12953,-1,-1,790,790,6,89,-1,0,0,17,12952,12954),(12954,-1,-1,790,790,6,90,-1,0,0,17,12953,13713),(12955,167,167,167,167,10,86,27457,14,900,17,8343,13718),(12956,4903,4903,4903,4903,9,85,27460,9,1320,17,10255,13698),(12957,4909,4909,4909,4909,9,85,27461,16,1320,17,10257,14733),(12958,4912,4912,4912,4912,9,85,27459,16,1320,17,10258,13704),(12959,4906,4906,4906,4906,9,85,27458,9,1320,17,10256,13701),(12963,12963,12963,12963,12963,7,86,27465,81,5,17,-1,-1),(12964,12964,12964,12964,12964,7,88,27466,81,5,17,-1,-1),(12965,12965,12965,12965,12965,7,90,27467,81,5,17,-1,-1),(12966,-1,-1,6112,6112,5,87,-1,0,0,17,6112,12967),(12967,-1,-1,6112,6112,5,89,-1,0,0,17,12966,16402),(12968,-1,-1,12968,12968,7,85,0,0,0,17,-1,12969),(12969,-1,-1,12968,12968,7,87,0,0,0,17,12968,12970),(12970,-1,-1,12968,12968,7,89,0,0,0,17,12969,14238),(12971,12971,12971,12971,12971,5,86,27471,79,2160,17,-1,12972),(12972,12971,12971,12971,12971,7,87,27472,79,2160,17,12971,12973),(12973,12971,12971,12971,12971,9,88,27473,79,2160,17,12972,12974),(12974,12971,12971,12971,12971,12,89,27474,79,2160,17,12973,12975),(12975,12971,12971,12971,12971,15,90,27475,79,2160,17,12974,-1),(12976,7903,7903,7903,7903,6,85,27476,60,30,17,7903,14734),(12977,-1,-1,12977,12977,5,85,0,0,0,17,-1,12978),(12978,-1,-1,12977,12977,5,86,0,0,0,17,12977,12979),(12979,-1,-1,12977,12977,5,87,0,0,0,17,12978,12980),(12980,-1,-1,12977,12977,5,88,0,0,0,17,12979,12981),(12981,-1,-1,12977,12977,5,89,0,0,0,17,12980,17334),(12982,10600,10600,10600,10600,7,86,27477,73,20,17,10602,12983),(12983,10600,10600,10600,10600,7,88,27478,73,20,17,12982,12984),(12984,10600,10600,10600,10600,7,90,27479,73,20,17,12983,13720),(12985,520,520,520,520,12,86,27480,6,540,17,10254,12986),(12986,520,520,520,520,12,88,27481,6,540,17,12985,12987),(12987,520,520,520,520,12,90,27482,6,540,17,12986,-1),(12988,-1,-1,10959,12988,12,90,-1,0,0,17,10962,-1),(12989,12989,12989,12989,12989,7,86,27486,73,1800,17,-1,12990),(12990,12989,12989,12989,12989,9,88,27487,73,1800,17,12989,12991),(12991,12989,12989,12989,12989,12,90,27488,73,1800,17,12990,5336),(12992,12992,12992,12992,12992,9,86,27489,0,1,17,-1,12993),(12993,12992,12992,12992,12992,12,88,27490,0,1,17,12992,12994),(12994,12992,12992,12992,12992,15,90,27491,0,1,17,12993,5350),(12995,6563,6563,6563,6563,12,86,27492,36,8,17,6281,-1),(12996,153,153,153,153,12,90,27493,3,2160,17,11081,17333),(12997,1520,1520,1520,1520,9,85,27494,11,900,17,10192,12998),(12998,1520,1520,1520,1520,9,87,27495,11,900,17,12997,12999),(12999,1520,1520,1520,1520,9,89,27496,11,900,17,12998,5333),(13000,10958,10958,10958,10958,15,90,27497,62,900,17,10958,16214),(13001,-1,-1,13001,13001,7,86,-1,0,0,17,-1,13002),(13002,-1,-1,13001,13001,7,88,-1,0,0,17,13001,13003),(13003,-1,-1,13001,13001,7,90,-1,0,0,17,13002,15348),(13004,13004,13004,13004,13004,9,86,27499,78,300,17,-1,15855),(13005,-1,-1,6703,6703,3,86,-1,0,0,17,10178,13006),(13006,-1,-1,6703,6703,3,88,-1,0,0,17,13005,13007),(13007,-1,-1,6703,6703,3,90,-1,0,0,17,13006,-1),(13008,13008,13008,13008,13008,9,90,27500,86,300,17,-1,-1),(13009,13009,13009,13009,13009,6,86,27501,39,1,17,-1,-1),(13010,-1,-1,13010,13010,6,85,0,0,0,17,-1,13011),(13011,-1,-1,13010,13010,6,87,0,0,0,17,13010,13012),(13012,-1,-1,13010,13010,6,89,0,0,0,17,13011,14223),(13013,-1,-1,13013,13013,6,86,0,0,0,17,-1,13014),(13014,-1,-1,13013,13013,6,88,0,0,0,17,13013,13015),(13015,-1,-1,13013,13013,6,90,0,0,0,17,13014,-1),(13016,5109,5109,5109,5109,9,86,27502,0,1,17,7467,5356),(13017,-1,-1,13017,13017,9,86,-1,0,0,17,-1,13018),(13018,-1,-1,13017,13017,12,88,-1,0,0,17,13017,13019),(13019,-1,-1,13017,13017,15,90,-1,0,0,17,13018,13396),(13020,13020,13020,13020,13020,12,86,27503,76,420,17,-1,-1),(13021,-1,-1,11085,11085,12,86,0,0,0,17,11087,13022),(13023,-1,-1,1050,1050,12,86,-1,0,0,17,7658,13024),(13026,-1,-1,599,599,12,86,-1,0,0,17,7561,13027),(13027,-1,-1,599,599,12,88,-1,0,0,17,13026,13028),(13028,-1,-1,599,599,12,90,-1,0,0,17,13027,13438),(13029,-1,-1,7818,7818,9,86,31681,0,0,17,7818,13030),(13032,-1,-1,1131,1131,9,85,-1,0,0,17,11084,13033),(13033,-1,-1,1131,1131,12,87,-1,0,0,17,13032,13034),(13035,-1,-1,1134,1134,3,86,-1,0,0,17,10315,13036),(13040,-1,-1,4809,4809,5,86,-1,0,0,17,10318,13041),(13043,-1,-1,5776,5776,9,86,-1,0,0,17,7198,13044),(13046,-1,-1,8250,8250,6,85,-1,0,0,17,8254,13047),(13047,-1,-1,8250,8250,6,86,-1,0,0,17,13046,13048),(13048,-1,-1,8250,8250,6,87,-1,0,0,17,13047,13049),(13049,-1,-1,8250,8250,6,88,-1,0,0,17,13048,13050),(13050,-1,-1,8250,8250,6,89,-1,0,0,17,13049,13348),(13051,-1,-1,10404,10404,6,90,-1,0,0,17,10404,-1),(13052,-1,-1,10401,10401,6,86,-1,0,0,17,10403,13053),(13055,-1,-1,13055,13055,6,86,0,0,0,17,-1,13056),(13058,6931,6931,6931,6931,12,90,27504,41,600,17,10319,13857),(13059,4854,4854,4854,4854,9,86,27505,8,600,17,10325,13060),(13062,6932,6932,6932,6932,7,86,27508,42,1200,17,10322,13063),(13065,13065,13065,13065,13065,12,86,27514,70,90,17,-1,-1),(13066,13066,13066,13066,13066,9,85,27516,71,1800,17,-1,-1),(13067,-1,-1,13067,13067,6,86,0,0,0,17,-1,13068),(13072,-1,-1,12600,12600,7,87,0,0,0,17,12600,13073),(13073,-1,-1,12600,12600,7,89,0,0,0,17,13072,13222),(13074,-1,-1,1044,1044,9,86,-1,0,0,17,7652,13075),(13075,-1,-1,1044,1044,12,88,-1,0,0,17,13074,13076),(13076,-1,-1,1044,1044,15,90,-1,0,0,17,13075,13326),(13077,-1,-1,1047,1047,9,86,-1,0,0,17,7655,13078),(13078,-1,-1,1047,1047,12,88,-1,0,0,17,13077,13079),(13080,-1,-1,125,125,9,86,-1,0,0,17,12400,13081),(13081,-1,-1,125,125,10,87,-1,0,0,17,13080,13082),(13082,-1,-1,125,125,11,88,-1,0,0,17,13081,13083),(13083,-1,-1,125,125,12,89,-1,0,0,17,13082,13084),(13084,-1,-1,125,125,13,90,-1,0,0,17,13083,8463),(13085,-1,-1,122,122,9,86,-1,0,0,17,12405,13086),(13086,-1,-1,122,122,10,87,-1,0,0,17,13085,13087),(13087,-1,-1,122,122,11,88,-1,0,0,17,13086,13088),(13088,-1,-1,122,122,12,89,-1,0,0,17,13087,13089),(13089,-1,-1,122,122,13,90,-1,0,0,17,13088,8440),(13090,-1,-1,1435,4773,9,86,-1,0,0,17,7621,13295),(13091,-1,-1,1435,4773,9,86,-1,0,0,17,1650,13294),(13092,-1,-1,644,644,9,85,-1,0,0,17,7361,13093),(13093,-1,-1,644,644,12,87,-1,0,0,17,13092,13094),(13094,-1,-1,644,644,15,89,-1,0,0,17,13093,13265),(13095,-1,-1,1604,1604,15,89,-1,0,0,17,12613,13767),(13096,-1,-1,13096,13096,12,86,-1,0,0,17,-1,13097),(13097,-1,-1,13096,13096,12,88,-1,0,0,17,13096,13098),(13098,-1,-1,13096,13096,12,90,-1,0,0,17,13097,13127),(13099,-1,-1,83,83,9,55,-1,0,0,17,85,-1),(13100,13100,13100,13100,13100,9,86,27534,86,300,17,-1,15140),(13101,-1,-1,13101,13101,7,86,0,0,0,17,-1,13102),(13102,-1,-1,13101,13101,9,88,0,0,0,17,13101,13103),(13103,-1,-1,13101,13101,12,90,0,0,0,17,13102,14082),(13104,-1,-1,589,589,9,86,-1,0,0,17,7709,13105),(13105,-1,-1,589,589,9,88,-1,0,0,17,13104,13106),(13106,-1,-1,589,589,9,90,-1,0,0,17,13105,15778),(13107,6645,6645,6645,6645,9,90,27541,45,60,17,6645,13633),(13108,13108,13108,13108,13108,5,90,27542,89,30,17,-1,-1),(13109,1351,1351,1351,1351,8,90,27543,5,30,17,7109,-1),(13110,10815,10815,10815,10815,9,86,-1,0,0,17,10817,13111),(13111,10815,10815,10815,10815,11,88,-1,0,0,17,13110,13112),(13113,10818,10818,10818,10818,9,86,-1,0,0,17,10820,13114),(13114,10818,10818,10818,10818,11,88,-1,0,0,17,13113,13115),(13116,10821,10821,10821,10821,9,86,-1,0,0,17,10823,13117),(13117,10821,10821,10821,10821,11,88,-1,0,0,17,13116,13118),(13119,5007,5007,5007,5007,9,86,27544,8,2160,17,10063,13120),(13120,5007,5007,5007,5007,9,88,27545,8,2160,17,13119,13121),(13122,-1,-1,6546,6546,0,86,-1,0,0,17,7377,13123),(13123,-1,-1,6546,6546,0,87,-1,0,0,17,13122,13124),(13124,-1,-1,6546,6546,0,88,-1,0,0,17,13123,13125),(13127,-1,-1,13096,13096,12,91,-1,0,0,18,13098,13128),(13130,13130,13130,13130,13130,15,95,32440,48,30,18,-1,-1),(13133,7756,7756,7756,7756,12,85,21805,85,120,17,-1,-1),(13134,13134,13134,13134,13134,7,86,27547,74,900,17,-1,13135),(13135,13134,13134,13134,13134,7,88,27548,74,900,17,13134,13136),(13136,13134,13134,13134,13134,7,90,27549,74,900,17,13135,13380),(13140,-1,-1,10464,10464,7,86,-1,0,0,17,10466,13141),(13141,-1,-1,10464,10464,9,88,-1,0,0,17,13140,13142),(13142,-1,-1,10464,10464,11,90,-1,0,0,17,13141,-1),(13143,-1,-1,13143,13143,5,86,0,0,0,17,-1,13144),(13144,-1,-1,13143,13143,5,88,0,0,0,17,13143,13145),(13145,-1,-1,13143,13143,5,90,0,0,0,17,13144,-1),(13146,-1,-1,13146,13146,5,86,0,0,0,17,-1,13147),(13147,-1,-1,13146,13146,5,88,0,0,0,17,13146,13148),(13148,-1,-1,13146,13146,5,90,0,0,0,17,13147,-1),(13149,-1,-1,8210,8210,5,86,-1,0,0,17,1655,13150),(13150,-1,-1,8210,8210,5,87,-1,0,0,17,13149,13151),(13151,-1,-1,8210,8210,5,88,-1,0,0,17,13150,13152),(13152,-1,-1,8210,8210,5,89,-1,0,0,17,13151,13153),(13153,-1,-1,8210,8210,5,90,-1,0,0,17,13152,13318),(13154,5105,5105,5105,5105,12,90,27550,11,600,17,10509,14023),(13155,7986,7986,7986,7986,12,90,27551,11,600,17,10510,14022),(13158,548,548,548,548,10,86,27552,5,900,17,10098,13159),(13161,528,528,528,528,12,86,27555,5,720,17,10196,13162),(13162,528,528,528,528,12,88,27556,5,720,17,13161,13163),(13163,528,528,528,528,12,90,27557,5,720,17,13162,5357),(13164,13164,13164,13164,13164,9,86,27540,99,180,17,-1,-1),(13165,13165,13165,13165,13165,9,86,27559,56,60,17,-1,-1),(13166,-1,-1,13166,13166,7,86,0,0,0,17,-1,13167),(13167,-1,-1,13166,13166,7,88,0,0,0,17,13166,13168),(13168,-1,-1,13166,13166,7,90,0,0,0,17,13167,-1),(13169,13169,13169,13169,13169,9,90,27560,99,180,17,-1,17221),(13170,6380,6380,6380,6380,6,86,27561,39,120,17,10310,13171),(13173,290,290,290,290,8,86,27564,4,720,17,290,13448),(13174,10374,10374,10374,10374,6,85,27565,63,900,17,10376,13175),(13175,10374,10374,10374,10374,8,87,27566,63,900,17,13174,13176),(13177,6984,6984,6984,6984,6,83,27568,60,60,17,10294,13466),(13178,6986,6986,6986,6986,6,83,27570,60,60,17,10296,13468),(13179,6985,6985,6985,6985,6,83,27569,60,60,17,10295,13467),(13180,10377,10377,10377,10377,6,86,16796,64,60,17,10379,13181),(13183,10346,10346,10346,10346,9,90,27574,46,600,17,10346,13819),(13184,-1,-1,10340,10340,9,86,-1,0,0,17,10342,13185),(13185,-1,-1,10340,10340,9,88,-1,0,0,17,13184,13186),(13186,-1,-1,10340,10340,9,90,-1,0,0,17,13185,13829),(13187,-1,-1,9512,9512,7,86,-1,0,0,17,7883,13188),(13188,-1,-1,9512,9512,7,88,-1,0,0,17,13187,13189),(13189,-1,-1,9512,9512,7,90,-1,0,0,17,13188,13826),(13190,1110,1110,1110,1110,6,86,27576,3,2160,17,10152,13191),(13191,1110,1110,1110,1110,6,88,27577,3,2160,17,13190,13192),(13192,1110,1110,1110,1110,6,90,27578,3,2160,17,13191,13496),(13193,1598,-1,1598,1598,9,86,27582,6,900,17,10148,13194),(13194,1598,-1,1598,1598,11,88,27583,6,900,17,13193,13195),(13195,1598,-1,1598,1598,13,90,27584,6,900,17,13194,13493),(13196,-1,-1,255,255,9,86,-1,0,0,17,10135,13197),(13197,-1,-1,255,255,9,88,-1,0,0,17,13196,13198),(13198,-1,-1,255,255,9,90,-1,0,0,17,13197,13511),(13199,-1,-1,8322,8322,9,86,0,0,0,17,8324,13200),(13200,-1,-1,8322,8322,9,88,0,0,0,17,13199,13201),(13201,-1,-1,8322,8322,9,90,0,0,0,17,13200,-1),(13202,13202,13202,13202,13202,2,81,27585,98,20,17,-1,14009),(13203,10330,10330,10330,10330,7,90,27586,35,30,17,10330,13492),(13204,-1,-1,13204,13204,7,86,-1,0,0,17,-1,13205),(13205,-1,-1,13204,13204,7,88,-1,0,0,17,13204,13206),(13206,-1,-1,13204,13204,7,90,-1,0,0,17,13205,14176),(13207,-1,-1,10850,10850,9,86,27587,0,0,17,10852,13208),(13208,-1,-1,10850,10850,9,88,27588,0,0,17,13207,13209),(13209,-1,-1,10850,10850,9,90,27589,0,0,17,13208,13779),(13210,-1,-1,1307,1307,5,81,-1,0,0,17,6662,13211),(13211,-1,-1,1307,1307,5,83,-1,0,0,17,13210,13212),(13212,-1,-1,1307,1307,5,85,-1,0,0,17,13211,-1),(13213,-1,-1,1543,1543,7,86,-1,0,0,17,10167,13214),(13214,-1,-1,1543,1543,7,87,-1,0,0,17,13213,13215),(13215,-1,-1,1543,1543,7,88,-1,0,0,17,13214,13216),(13216,-1,-1,1543,1543,7,89,-1,0,0,17,13215,13217),(13217,-1,-1,1543,1543,7,90,-1,0,0,17,13216,13782),(13218,-1,-1,1304,1304,12,90,-1,0,0,17,10867,13789),(13219,-1,-1,8325,8325,7,85,0,0,0,17,8327,13220),(13220,-1,-1,8325,8325,9,87,0,0,0,17,13219,13221),(13221,-1,-1,8325,8325,11,89,0,0,0,17,13220,13798),(13222,-1,-1,12600,12600,7,89,0,0,0,17,13073,13223),(13223,-1,-1,12600,12600,7,89,0,0,0,17,13222,-1),(13224,13224,-1,13224,13224,3,86,27590,98,1,17,-1,15559),(13225,13225,13225,13225,13225,6,86,27592,0,4,17,-1,13688),(13226,-1,-1,5295,5295,6,86,-1,0,0,17,10229,13227),(13229,6290,6290,6290,6290,9,86,27596,0,1,17,11066,13230),(13232,4944,-1,4944,4944,9,86,27602,0,1,17,11069,13233),(13235,1478,-1,1478,1478,9,86,27608,0,1,17,11072,13236),(13238,-1,-1,1287,1287,9,86,-1,0,0,17,12474,13239),(13239,-1,-1,1287,1287,10,88,-1,0,0,17,13238,13240),(13240,-1,-1,1287,1287,11,90,-1,0,0,17,13239,15719),(13241,4931,4931,4931,4931,7,86,27614,4,600,17,10430,13242),(13244,1501,1501,1501,1501,6,86,27617,10,4320,17,1560,13245),(13247,4894,4894,4894,4894,6,86,27620,7,2160,17,7290,13248),(13250,10550,10550,10550,10550,7,90,27626,61,120,17,10550,13728),(13251,1239,1239,1239,1239,9,90,27627,6,600,17,7275,13732),(13252,13252,13252,13252,13252,9,86,27629,95,4,17,-1,16065),(13253,1126,1126,1126,1126,7,85,27630,2,2160,17,5515,13254),(13254,1126,1126,1126,1126,7,87,27631,2,2160,17,13253,13255),(13255,1126,1126,1126,1126,7,89,27632,2,2160,17,13254,13723),(13256,146,146,146,146,8,86,27633,2,180,17,7691,13257),(13257,146,146,146,146,8,88,27634,2,180,17,13256,13258),(13258,146,146,146,146,8,90,27635,2,180,17,13257,14222),(13259,1195,1195,1195,1195,9,90,27661,13,2160,17,10015,15334),(13260,13260,13260,13260,13260,0,80,27664,98,3600,17,-1,-1),(13261,13261,13261,13261,13261,0,81,27665,98,28800,17,-1,-1),(13262,-1,-1,498,498,5,70,-1,0,0,16,975,13263),(13263,-1,-1,498,498,5,75,-1,0,0,16,13262,13264),(13264,-1,-1,498,498,5,80,-1,0,0,16,13263,-1),(13271,13271,13271,13271,13271,0,80,27691,97,3600,18,-1,-1),(13272,13272,13272,13272,13272,0,81,27692,97,28800,18,-1,-1),(13275,6537,6537,6537,6537,10,91,30638,30,900,18,12522,13276),(13278,-1,-1,6051,6051,10,91,-1,0,0,18,12797,13279),(13281,-1,-1,1072,1072,12,91,-1,0,0,18,12541,13282),(13286,-1,-1,119,119,12,91,-1,0,0,18,12552,13287),(13291,6539,6539,6539,6539,9,91,30641,18,1800,18,12944,13292),(13294,-1,-1,1435,4773,12,91,-1,0,0,18,13091,14490),(13295,-1,-1,1435,4773,12,91,-1,0,0,18,13090,14491),(13296,-1,-1,77,77,12,91,-1,0,0,18,12499,13297),(13297,-1,-1,77,77,12,93,-1,0,0,18,13296,13298),(13299,-1,-1,1186,1186,12,91,-1,0,0,18,12566,13300),(13302,-1,-1,80,80,12,91,-1,0,0,18,12569,13303),(13305,-1,-1,683,683,10,91,-1,0,0,18,12696,13306),(13308,-1,-1,446,735,10,91,-1,0,0,18,10477,13309),(13313,-1,-1,658,658,8,91,-1,0,0,18,12574,13314),(13318,-1,-1,8210,8210,10,91,-1,0,0,18,13153,13319),(13323,-1,-1,1287,1287,12,91,-1,0,0,18,10639,13324),(13326,-1,-1,1044,1044,10,91,-1,0,0,18,13076,13327),(13332,-1,-1,1041,1041,11,91,-1,0,0,18,12699,13333),(13338,-1,-1,8245,8245,11,91,-1,0,0,18,8426,13339),(13343,-1,-1,8240,8240,11,91,-1,0,0,18,10785,13344),(13348,-1,-1,8250,8250,11,91,-1,0,0,18,13050,13349),(13353,-1,-1,8235,8235,11,91,-1,0,0,18,8308,13354),(13358,-1,-1,8255,8255,11,91,-1,0,0,18,12415,13359),(13363,1192,1192,1192,1192,9,91,30645,12,1320,18,10021,13364),(13383,6488,6488,6488,6488,15,91,30657,32,900,18,6488,13384),(13385,13385,13385,13385,13385,12,91,30659,75,600,18,-1,13386),(13388,13388,13388,13388,13388,12,91,30665,79,180,18,-1,-1),(13389,13389,-1,13389,13389,5,91,30666,77,12,18,-1,15832),(13396,-1,-1,13017,13017,15,91,-1,0,0,18,13019,13397),(13401,1498,1498,1498,1498,15,91,30679,12,1320,18,10092,13402),(13404,-1,-1,1514,1514,11,91,-1,0,0,18,1516,13405),(13410,645,-1,645,645,15,95,30682,4,5,18,10739,-1),(13411,-1,-1,12652,12652,15,92,0,0,0,18,12654,13412),(13413,-1,-1,12416,12416,15,91,-1,0,0,18,12418,13414),(13415,-1,-1,7989,7989,9,95,-1,0,0,18,7992,-1),(13416,-1,-1,13416,13416,9,91,0,0,0,18,-1,13417),(13419,13419,13419,13419,13419,12,91,30683,99,600,18,-1,13420),(13425,54006,54006,54006,54006,9,91,30692,18,180,18,10006,13426),(13438,-1,-1,599,599,13,91,-1,0,0,18,13028,13439),(13444,13444,13444,13444,13444,9,91,30699,75,600,18,-1,13445),(13447,11073,11073,11073,11073,12,95,30705,53,30,18,11073,15412),(13449,-1,-1,13449,13449,5,91,-1,0,0,18,-1,13450),(13454,718,718,718,718,12,91,30711,7,4320,18,1019,14855),(13463,-1,-1,13463,13463,7,91,-1,0,0,18,-1,13464),(13466,6984,6984,6984,6984,9,91,30721,60,60,18,13177,13469),(13467,6985,6985,6985,6985,9,91,30723,60,60,18,13179,13470),(13468,6986,6986,6986,6986,12,92,30725,60,60,18,13178,13471),(13472,11080,11080,11080,11080,11,91,30727,10,20,18,11080,13473),(13474,-1,-1,13474,13474,9,91,-1,0,0,18,-1,13475),(13477,-1,-1,10380,10380,11,91,-1,0,0,18,10382,13478),(13483,13483,13483,13483,13483,5,91,30735,68,20,18,-1,-1),(13484,13484,-1,13484,13484,12,95,30736,76,720,18,-1,15879),(13485,-1,-1,13485,13485,7,91,-1,0,0,18,-1,13486),(13490,5020,5020,5020,5020,9,91,30742,9,300,18,10149,13491),(13492,10330,10330,10330,10330,12,95,30744,35,30,18,13203,14797),(13493,1598,-1,1598,1598,11,91,30745,6,900,18,13195,13494),(13496,1110,1110,1110,1110,9,91,30748,3,2160,18,13192,13497),(13499,592,592,592,592,9,91,30754,2,18,18,12751,13500),(13502,-1,-1,6375,6375,9,91,-1,0,0,18,12736,13503),(13505,6533,6533,6533,6533,11,91,30757,15,600,18,12742,13506),(13508,-1,-1,8314,8314,9,91,-1,0,0,18,8316,13509),(13511,-1,-1,255,255,9,91,-1,0,0,18,13198,13512),(13514,5298,5298,5298,5298,12,91,30760,32,1800,18,12748,13515),(13517,10336,10336,10336,10336,11,91,30766,58,8,18,12732,13518),(13520,-1,-1,12419,12419,15,95,-1,0,0,18,12575,16886),(13521,-1,-1,6386,6386,9,91,-1,0,0,18,6389,13522),(13524,6534,6534,6534,6534,11,91,30769,16,900,18,7429,13525),(13527,13527,13527,13527,13527,9,91,30772,18,9,18,-1,15964),(13528,13528,13528,13528,13528,10,91,30773,42,60,18,-1,-1),(13529,13529,13529,13529,13529,15,95,30774,41,120,18,-1,-1),(13530,1116,1116,1116,1116,12,91,30775,4,2160,18,12745,13531),(13533,-1,-1,7010,7010,9,91,-1,0,0,18,7015,13534),(13542,6755,6755,6755,6755,12,91,30784,42,900,18,6757,13543),(13545,-1,-1,10388,10388,12,95,-1,0,0,18,10388,15293),(13546,6758,6758,6758,6758,11,91,32360,43,900,18,10056,13547),(13549,13549,13549,13549,13549,15,95,30788,64,180,18,-1,-1),(13556,13556,13556,13556,13556,9,91,30792,44,600,18,-1,13557),(13562,-1,-1,10719,10719,15,91,0,0,0,18,10721,13563),(13565,-1,-1,13565,13565,11,91,0,0,0,18,-1,13566),(13568,-1,-1,13568,13568,11,91,0,0,0,18,-1,13569),(13571,13571,13571,13571,13571,12,91,30795,50,60,18,-1,-1),(13575,5095,5095,5095,5095,11,91,30796,10,900,18,10642,13576),(13578,0,0,10348,10348,9,91,-1,0,0,18,10350,13579),(13584,10394,10394,10394,10394,15,91,30799,30,300,18,10704,14981),(13585,7712,7712,7712,7712,15,95,30800,2,30,18,10646,15095),(13586,188,188,188,188,12,91,30801,2,30,18,10647,13587),(13589,-1,-1,255,255,13,91,-1,0,0,18,10625,13590),(13590,-1,-1,255,255,15,93,-1,0,0,18,13589,13591),(13592,5984,5984,5984,5984,12,91,30803,2,30,18,10626,13593),(13595,534,534,534,534,12,91,30806,4,2160,18,10710,13596),(13598,-1,-1,6791,6791,11,91,-1,0,0,18,10678,13599),(13601,-1,-1,852,852,11,91,-1,0,0,18,12578,13602),(13604,7850,7850,7850,7850,15,91,30812,39,4320,18,10620,13605),(13607,-1,-1,10453,10453,11,91,-1,0,0,18,10455,13608),(13610,-1,-1,602,602,12,91,-1,0,0,18,10687,13611),(13613,-1,-1,855,855,11,91,-1,0,0,18,10692,13614),(13616,-1,-1,13616,13616,7,91,-1,0,0,18,-1,13617),(13617,-1,-1,13616,13616,9,93,-1,0,0,18,13616,13618),(13618,-1,-1,13616,13616,12,95,-1,0,0,18,13617,14786),(13619,7800,7800,7800,7800,15,91,30815,39,4320,18,10787,13620),(13621,-1,-1,6630,6630,9,91,-1,0,0,18,10074,13622),(13624,10900,10900,10900,10900,9,91,30817,55,120,18,10902,13625),(13627,-1,-1,895,895,9,91,-1,0,0,18,10908,13628),(13628,-1,-1,895,895,12,93,-1,0,0,18,13627,13629),(13630,-1,-1,9506,9506,11,91,-1,0,0,18,9508,13631),(13633,6645,6645,6645,6645,15,95,30820,45,60,18,13107,15178),(13646,13646,13646,13646,13646,15,91,30837,45,600,18,-1,-1),(13650,8060,8060,8060,8060,9,91,31524,41,1800,18,10239,13651),(13653,8063,8063,8063,8063,9,91,31527,41,1800,18,10242,13654),(13656,8066,8066,8066,8066,11,91,31530,41,1800,18,10245,13657),(13663,12893,12893,12893,12893,15,91,31534,76,1800,18,12893,13664),(13667,-1,-1,13667,13667,11,91,-1,0,0,18,-1,13668),(13670,13670,13670,13670,13670,12,91,31538,43,1800,18,-1,13671),(13673,13673,13673,13673,13673,18,95,32050,0,1,18,-1,-1),(13674,13674,13674,13674,13674,18,95,32058,0,1,18,-1,-1),(13675,-1,-1,5264,5264,12,91,-1,0,0,18,12800,13676),(13678,13678,13678,13678,13678,15,95,31543,74,1200,18,12778,-1),(13682,12766,12766,12766,12766,18,95,31545,69,3600,18,12766,-1),(13683,6822,6822,6822,6822,15,91,31546,42,120,18,6822,14780),(13684,-1,-1,13684,13684,9,91,-1,0,0,18,-1,13685),(13685,-1,-1,13684,13684,12,93,-1,0,0,18,13684,13686),(13686,-1,-1,13684,13684,15,95,-1,0,0,18,13685,16653),(13687,13687,13687,13687,13687,15,91,31547,75,300,18,-1,17521),(13688,13225,13225,13225,13225,12,91,31548,0,4,18,13225,15620),(13689,-1,-1,13689,13689,9,91,-1,0,0,18,-1,13690),(13692,12208,12208,12208,12208,6,91,31549,17,12,18,-1,-1),(13693,13693,13693,13693,13693,18,95,31550,76,500,18,-1,17531),(13695,13695,13695,13695,13695,12,91,31577,91,1320,18,-1,13696),(13698,4903,4903,4903,4903,12,91,31580,9,1320,18,12956,13699),(13701,4906,4906,4906,4906,12,91,31583,9,1320,18,12959,13702),(13704,4912,4912,4912,4912,12,91,31586,16,1320,18,12958,13705),(13707,-1,-1,1577,1577,12,91,-1,0,0,18,10264,13708),(13710,-1,-1,795,795,9,91,-1,0,0,18,12949,13711),(13713,-1,-1,790,790,6,91,-1,0,0,18,12954,13714),(13718,167,167,167,167,12,91,31589,14,900,18,12955,13719),(13720,10600,10600,10600,10600,11,91,31591,73,20,18,12984,13721),(13723,1126,1126,1126,1126,11,91,31594,2,2160,18,13255,13724),(13726,1017,1017,1017,1017,12,91,31597,75,15,18,1017,-1),(13727,4938,4938,4938,4938,12,95,31598,35,1800,18,12875,16031),(13734,773,-1,773,773,9,91,31606,5,1800,18,10566,13735),(13753,-1,-1,13753,13753,5,91,-1,0,0,18,-1,13754),(13758,-1,-1,13758,13758,5,91,-1,0,0,18,-1,13759),(13763,-1,-1,781,781,12,95,-1,0,0,18,7284,-1),(13764,-1,-1,13764,13764,9,91,-1,0,0,18,-1,13765),(13767,-1,-1,1604,1604,12,91,-1,0,0,18,13095,13768),(13770,6328,6328,6328,6328,9,91,31628,10,600,18,10170,13771),(13771,6328,6328,6328,6328,12,93,31629,10,600,18,13770,13772),(13773,-1,-1,255,255,11,91,-1,0,0,18,12610,13774),(13774,-1,-1,255,255,13,92,-1,0,0,18,13773,13775),(13775,-1,-1,255,255,15,93,-1,0,0,18,13774,14126),(13779,-1,-1,10850,10850,12,91,31637,0,0,18,13209,13780),(13782,-1,-1,1543,1543,9,91,-1,0,0,18,13217,13783),(13785,5021,5021,5021,5021,11,91,31640,7,60,18,12621,13786),(13788,13788,13788,13788,13788,25,51,31643,31,2,3,-1,-1),(13789,-1,-1,1304,1304,11,91,-1,0,0,18,13218,13790),(13790,-1,-1,1304,1304,13,93,-1,0,0,18,13789,13791),(13792,13792,13792,13792,13792,9,91,31644,18,600,18,12633,13793),(13795,-1,-1,846,846,12,91,-1,0,0,18,10175,13796),(13798,-1,-1,8325,8325,9,91,-1,0,0,18,13221,13799),(13804,-1,-1,10650,10650,9,91,-1,0,0,18,10652,13805),(13807,1352,1352,1352,1352,9,91,31647,3,60,18,10115,13808),(13810,1358,1358,1358,1358,9,91,31650,3,60,18,10118,13811),(13813,-1,-1,12706,12706,12,91,0,0,0,18,12708,13814),(13816,7875,7875,7875,7875,9,91,31653,42,600,18,7880,13817),(13819,10346,10346,10346,10346,12,95,31659,46,600,18,13183,16924),(13820,-1,-1,820,820,9,91,-1,0,0,18,12669,13821),(13823,-1,-1,6020,6020,9,91,-1,0,0,18,12693,13824),(13826,-1,-1,9512,9512,9,91,-1,0,0,18,13189,13827),(13829,-1,-1,10340,10340,12,91,-1,0,0,18,13186,13830),(13832,1355,1355,1355,1355,11,91,31661,3,60,18,12702,13833),(13835,-1,-1,611,611,9,91,-1,0,0,18,12705,13836),(13838,7872,7872,7872,7872,9,91,31664,41,600,18,12684,13839),(13841,-1,-1,10343,10343,9,91,0,0,0,18,10345,13842),(13845,1178,1178,1178,1178,9,91,31669,4,900,18,10328,13846),(13872,13872,13872,13872,13872,15,95,31694,63,60,18,-1,16002),(13873,-1,-1,13873,13873,7,91,0,0,0,18,-1,13874),(13878,-1,-1,13878,13878,9,91,0,0,0,18,-1,13879),(13881,-1,-1,13881,13881,9,91,0,0,0,18,-1,13882),(13884,-1,-1,735,735,10,91,-1,0,0,18,10636,13885),(13889,-1,-1,13889,13889,5,91,0,0,0,18,-1,13890),(13894,-1,-1,1021,1021,6,91,-1,0,0,18,7685,13895),(13899,6750,6750,6750,6750,15,95,32100,60,120,18,6750,15294),(13905,-1,-1,13905,13905,10,91,-1,0,0,18,-1,13906),(13908,-1,-1,13908,13908,10,91,-1,0,0,18,-1,13909),(13911,-1,-1,13911,13911,12,91,-1,0,0,18,-1,13912),(13914,4849,4849,4849,4849,12,91,32103,7,1800,18,7110,13915),(13917,-1,-1,13917,13917,9,91,-1,0,0,18,-1,13918),(13920,6333,6333,6333,6333,15,91,32140,3,600,18,7266,16032),(13921,-1,-1,98,98,12,91,-1,0,0,18,11063,13922),(13924,-1,-1,98,738,12,91,-1,0,0,18,7600,13925),(13927,-1,-1,10370,10370,10,91,-1,0,0,18,10372,13928),(13930,-1,-1,1592,1592,12,91,-1,0,0,18,12536,13931),(13933,-1,-1,8263,8263,5,91,-1,0,0,18,8360,13934),(13943,-1,-1,8268,8268,5,91,-1,0,0,18,8370,13944),(13953,-1,-1,8273,8273,5,91,-1,0,0,18,8380,13954),(13963,-1,-1,8278,8278,5,91,-1,0,0,18,8390,13964),(13973,-1,-1,8283,8283,5,91,-1,0,0,18,8400,13974),(13983,-1,-1,8288,8288,5,91,-1,0,0,18,8410,13984),(13993,-1,-1,8293,8293,5,91,-1,0,0,18,8420,13994),(14003,6492,6492,6492,6492,12,91,32151,52,720,18,10681,14004),(14006,10711,10711,10711,10711,15,91,32157,75,1200,18,10713,14007),(14009,13202,13202,13202,13202,6,91,32160,98,20,18,13202,-1),(14010,14010,14010,14010,14010,15,95,32161,97,20,18,-1,-1),(14011,-1,-1,14011,14011,5,91,-1,0,0,18,-1,14012),(14016,10354,10354,10354,10354,15,95,32162,39,4320,18,10354,14647),(14017,-1,-1,14017,14017,0,90,-1,0,0,18,-1,-1),(14018,-1,-1,14018,14018,0,91,-1,0,0,18,-1,-1),(14019,14019,14019,14019,14019,12,91,32177,14,900,18,-1,14020),(14026,-1,-1,14026,14026,12,91,-1,0,0,18,-1,14027),(14029,-1,-1,14029,14029,12,91,-1,0,0,18,-1,14030),(14032,-1,-1,14032,14032,15,95,-1,0,0,18,-1,-1),(14037,-1,-1,14037,14037,9,91,0,0,0,18,-1,14038),(14040,-1,-1,14040,14040,9,91,0,0,0,18,-1,14041),(14043,-1,-1,1313,1313,12,91,-1,0,0,18,12581,14044),(14046,-1,-1,14046,14046,5,91,-1,0,0,18,-1,14047),(14051,14051,14051,14051,14051,12,95,32300,62,8,18,-1,15774),(14052,14052,14052,14052,14052,21,95,32301,13,1440,18,-1,14793),(14053,10912,10912,10912,10912,9,91,32303,69,1800,18,10914,14054),(14054,10912,10912,10912,10912,12,93,32304,69,1800,18,14053,14055),(14055,10912,10912,10912,10912,15,95,32305,69,1800,18,14054,-1),(14056,-1,-1,14056,14056,9,91,-1,0,0,18,-1,14057),(14059,-1,-1,14059,14059,9,91,-1,0,0,18,-1,14060),(14062,-1,-1,14062,14062,9,91,-1,0,0,18,-1,14063),(14065,-1,-1,14065,14065,9,91,0,0,0,18,-1,14066),(14068,-1,-1,14068,14068,9,91,0,0,0,18,-1,14069),(14071,14071,14071,14071,14071,9,91,32307,12,600,18,-1,14072),(14076,-1,-1,14076,14076,9,91,-1,0,0,18,-1,14077),(14080,14080,14080,14080,14080,9,95,32312,13,900,18,-1,-1),(14081,14081,14081,14081,14081,9,95,32313,14,120,18,-1,17240),(14082,-1,-1,13101,13101,9,91,0,0,0,18,13103,14083),(14085,-1,-1,14085,14085,9,91,-1,0,0,18,-1,14086),(14088,-1,-1,14088,14088,9,91,-1,0,0,18,-1,14089),(14091,-1,-1,14091,14091,9,91,-1,0,0,18,-1,14092),(14094,-1,-1,10355,10355,9,91,-1,0,0,18,10645,14095),(14097,-1,-1,6395,6395,12,91,-1,0,0,18,10707,14098),(14100,-1,-1,14100,14100,15,95,-1,0,0,18,-1,-1),(14101,-1,-1,6355,6355,9,91,-1,0,0,18,6360,14263),(14111,6754,6754,6754,6754,12,95,32326,41,1200,18,10053,14839),(14112,6370,6370,6370,6370,9,91,32329,7,600,18,7352,14113),(14115,-1,-1,14115,14115,12,91,-1,0,0,18,-1,14116),(14129,-1,-1,14129,14129,12,91,-1,0,0,18,-1,14130),(14130,-1,-1,14129,14129,15,93,-1,0,0,18,14129,14131),(14132,-1,-1,7751,7751,7,91,-1,0,0,18,7753,14133),(14135,-1,-1,14135,14135,12,91,-1,0,0,18,-1,14136),(14138,-1,-1,12615,12615,18,95,-1,0,0,18,12617,15499),(14139,14139,14139,14139,14139,15,95,32328,60,60,18,-1,-1),(14140,-1,-1,12607,12607,15,95,0,0,0,18,12607,15631),(14141,-1,-1,14141,14141,9,91,-1,0,0,18,-1,14142),(14144,-1,-1,14144,14144,7,91,-1,0,0,18,-1,14145),(14148,-1,-1,14148,14148,9,91,0,0,0,18,-1,14149),(14151,-1,-1,14151,14151,9,91,0,0,0,18,-1,14152),(14154,-1,-1,10657,10657,12,91,0,0,0,18,12681,14155),(14157,-1,-1,14157,14157,9,91,0,0,0,18,-1,14158),(14160,-1,-1,14160,14160,9,91,0,0,0,18,-1,14161),(14163,-1,-1,14163,14163,9,91,0,0,0,18,-1,14164),(14166,-1,-1,14166,14166,9,91,0,0,0,18,-1,14167),(14169,-1,-1,14169,14169,7,91,-1,0,0,18,-1,14170),(14173,-1,-1,12710,12710,9,91,-1,0,0,18,12712,14174),(14176,-1,-1,13204,13204,9,91,-1,0,0,18,13206,14177),(14179,-1,-1,14179,14179,9,95,-1,0,0,18,-1,-1),(14180,-1,-1,14180,14180,9,95,-1,0,0,18,-1,-1),(14181,-1,-1,14181,14181,9,91,-1,0,0,18,-1,14182),(14186,-1,-1,14186,14186,9,91,-1,0,0,18,-1,14187),(14189,5017,5017,5017,5017,9,91,32332,8,600,18,10158,14190),(14192,14192,14192,14192,14192,15,95,32335,36,12,18,-1,15525),(14196,-1,-1,6935,6935,9,91,-1,0,0,18,6904,14197),(14199,-1,-1,6908,6908,12,95,-1,0,0,18,6910,15560),(14200,-1,-1,14200,14200,9,91,32336,0,0,18,-1,14201),(14203,-1,-1,14203,14203,12,91,-1,0,0,18,-1,14204),(14206,14206,14206,14206,14206,12,95,32339,41,600,18,-1,15324),(14207,14207,14207,14207,14207,12,95,32340,39,180,18,-1,-1),(14208,14208,14208,14208,14208,12,95,32341,17,180,18,-1,14568),(14209,14209,14209,14209,14209,12,95,32342,22,3,18,-1,-1),(14210,-1,-1,10358,10358,12,91,-1,0,0,18,10360,14211),(14213,-1,-1,14213,14213,11,91,-1,0,0,18,-1,14214),(14218,-1,-1,962,962,9,91,-1,0,0,18,10363,14219),(14221,1383,1383,1383,1383,18,95,32345,6,300,18,6487,14581),(14222,146,146,146,146,15,95,32346,2,180,18,13258,14977),(14223,-1,-1,13010,13010,12,95,0,0,0,18,13012,16205),(14224,14224,-1,14224,14224,9,91,345,61,5,18,-1,15860),(14225,-1,-1,14225,14225,9,91,-1,0,0,18,-1,14226),(14229,14229,14229,14229,14229,12,100,37168,42,600,19,-1,-1),(14231,14231,14231,14231,14231,12,95,32347,91,6,18,-1,16207),(14232,14232,-1,14232,14232,12,95,32348,92,6,18,-1,14674),(14233,14233,14233,14233,14233,15,95,32349,93,30,18,-1,15621),(14234,14234,14234,14234,14234,9,91,32350,94,1800,18,-1,14235),(14237,12638,12638,12638,12638,9,91,23581,68,10,18,-1,-1),(14238,-1,-1,12968,12968,9,91,0,0,0,18,12970,14239),(14241,-1,-1,14241,14241,9,91,-1,0,0,18,-1,14242),(14244,-1,-1,14244,14244,9,91,-1,0,0,18,-1,14245),(14249,-1,-1,14249,14249,9,91,-1,0,0,18,-1,14250),(14254,-1,-1,14254,14254,11,91,-1,0,0,18,-1,14255),(14256,6561,6561,6561,6561,9,91,32353,32,30,18,10420,14257),(14259,-1,-1,14259,14259,11,91,-1,0,0,18,-1,14260),(14262,14262,14262,14262,14262,15,95,32357,95,180,18,-1,-1),(14264,14264,14264,14264,14264,12,95,32358,97,120,18,-1,14600),(14265,14265,14265,14265,14265,15,95,32359,68,30,18,-1,-1),(14272,6218,6218,6218,14272,12,95,32369,0,1,18,7488,17381),(14273,723,723,723,723,12,95,32370,6,30,18,10300,14869),(14274,6971,6971,6971,6971,9,91,32371,41,600,18,10290,17383),(14275,-1,-1,14275,14275,7,91,-1,0,0,18,-1,14276),(14278,-1,-1,14278,14278,12,95,0,0,0,18,6990,16248),(14279,-1,-1,1287,1287,11,95,-1,0,0,18,12815,16529),(14280,4890,-1,4890,4890,12,95,32373,3,8640,18,5872,14776),(14281,14281,14281,14281,14281,12,95,32375,39,15,18,-1,-1),(14282,14282,14282,14282,14282,9,91,32374,39,7,18,-1,-1),(14283,-1,-1,14283,14283,7,91,-1,0,0,18,-1,14284),(14286,-1,-1,14286,14286,9,91,-1,0,0,18,-1,14287),(14289,-1,-1,14289,14289,9,91,-1,0,0,18,-1,14290),(14292,-1,-1,14292,14292,9,91,-1,0,0,18,-1,14293),(14295,-1,-1,14295,14295,9,95,-1,0,0,18,-1,14296),(14301,-1,-1,14301,14301,9,91,-1,0,0,18,-1,14302),(14304,-1,-1,14304,14304,9,91,-1,0,0,18,-1,14305),(14307,14307,14307,14307,14307,12,95,32376,92,1200,18,-1,14743),(14308,-1,-1,14308,14308,9,91,-1,0,0,18,-1,14309),(14311,-1,-1,14311,14311,9,91,-1,0,0,18,-1,14312),(14314,-1,-1,7715,7715,7,91,-1,0,0,18,7717,14315),(14318,-1,-1,14318,14318,9,91,-1,0,0,18,-1,14319),(14321,14321,14321,14321,14321,12,95,32378,92,8,18,-1,14781),(14322,14322,14322,14322,14322,12,95,32379,94,2160,18,-1,14782),(14323,14323,14323,14323,14323,12,95,32380,92,150,18,-1,-1),(14324,155,155,155,155,15,95,32381,8,60,18,7238,15610),(14328,-1,-1,7822,7822,7,91,-1,0,0,18,7826,14329),(14331,-1,-1,14331,14331,9,91,-1,0,0,18,-1,14332),(14338,1337,1337,1337,1337,12,91,32382,13,4320,18,6160,14339),(14341,-1,-1,14341,14341,5,91,-1,0,0,18,-1,14342),(14346,14346,14346,14346,14346,9,91,32385,94,12,18,-1,14347),(14349,-1,-1,1210,1213,12,91,-1,0,0,18,12528,14350),(14352,1274,1274,1274,1274,12,91,32391,9,540,18,12762,14353),(14355,6815,6815,6815,6815,9,91,32394,60,600,18,12788,14356),(14358,14358,-1,14358,14358,15,95,32397,98,300,18,-1,-1),(14359,14359,14359,14359,14359,15,95,32399,93,1200,18,-1,-1),(14360,14360,14360,14360,14360,15,95,32400,95,1800,18,-1,16334),(14361,-1,-1,637,637,12,91,-1,0,0,18,12555,14362),(14364,-1,-1,14364,14364,9,91,-1,0,0,18,-1,14365),(14367,-1,-1,14367,14367,0,1,-1,0,0,0,-1,14368),(14371,14371,14371,14371,14371,0,1,32910,0,10,0,-1,-1),(14372,13844,13844,13844,13844,6,95,31667,47,6,18,-1,-1),(14373,14373,14373,14373,14373,0,85,33106,87,3600,19,-1,-1),(14374,14374,14374,14374,14374,0,86,33107,88,28800,19,-1,-1),(14690,14690,14690,14690,14690,15,96,37014,45,600,19,-1,17479),(14729,8342,8342,8342,8342,15,100,33909,54,240,19,8342,17501),(14730,616,616,616,616,12,96,33910,7,900,19,10261,14731),(14733,4909,4909,4909,4909,18,100,33913,16,1320,19,12957,17147),(14734,7903,7903,7903,7903,12,100,33914,60,30,19,12976,15853),(14739,1462,1462,1462,1462,18,99,33919,5,300,19,4902,16054),(14764,-1,-1,10551,10551,12,96,-1,0,0,19,10553,14765),(14991,926,926,926,926,5,85,11071,12,1800,17,930,14992),(14992,926,926,926,926,5,86,11072,12,1800,17,14991,14993),(15073,15073,-1,15073,15073,0,1,37668,90,60,19,-1,-1),(15074,-1,-1,15074,15074,0,1,-1,0,0,19,-1,15075),(15096,15096,15096,15096,15096,5,96,38151,35,30,19,-1,15097),(15099,15099,15099,15099,15099,12,100,37187,15,45,19,-1,16566),(15100,-1,-1,15100,15100,5,96,-1,0,0,19,-1,15101),(15105,-1,-1,15105,15105,11,96,-1,0,0,19,-1,15106),(15108,-1,-1,15108,15108,9,98,-1,0,0,19,-1,15109),(15111,8300,8300,8300,8300,11,97,37189,8,900,19,8302,15112),(15113,-1,-1,15113,15113,11,96,-1,0,0,19,-1,15114),(15119,15119,15119,15119,15119,12,100,37194,16,1200,19,-1,15749),(15120,-1,-1,15120,15120,9,96,-1,0,0,19,-1,15121),(15123,-1,-1,15123,15123,9,96,-1,0,0,19,-1,15124),(15126,-1,-1,15126,15126,9,96,-1,0,0,19,-1,15127),(15129,15129,15129,15129,15129,12,100,37196,32,180,19,-1,15736),(15130,15130,15130,15130,15130,12,100,37197,32,180,19,-1,15737),(15131,15131,15131,15131,15131,12,100,37198,32,180,19,-1,15738),(15132,-1,-1,15132,15132,9,96,-1,0,0,19,-1,15133),(15135,-1,-1,15135,15135,9,100,-1,0,0,19,-1,-1),(15136,15136,15136,15136,15136,9,96,38001,5,120,19,-1,17241),(15140,13100,13100,13100,13100,11,100,38002,86,300,19,13100,-1),(15141,-1,-1,190,190,9,96,-1,0,0,19,5040,15142),(15146,15146,15146,15146,15146,13,100,38006,95,9,19,-1,15758),(15147,15147,15147,15147,15147,11,96,38007,8,1200,19,-1,15148),(15150,-1,-1,15150,15150,7,96,-1,0,0,19,-1,15151),(15153,-1,-1,15153,15153,11,100,-1,0,0,19,-1,-1),(15154,-1,-1,15154,15154,9,96,-1,0,0,19,-1,-1),(15155,-1,-1,15155,15155,5,96,-1,0,0,19,-1,15156),(15158,-1,-1,15158,15158,13,100,-1,0,0,19,-1,-1),(15159,-1,-1,15159,15159,7,96,-1,0,0,19,-1,15160),(15162,-1,-1,15162,15162,7,96,-1,0,0,19,-1,15163),(15168,-1,-1,15168,15168,9,96,-1,0,0,19,-1,15169),(15172,-1,-1,210,210,12,100,-1,0,0,19,7401,16658),(15173,6639,6639,6639,6639,9,100,38012,42,300,19,6639,15788),(15174,-1,-1,12582,12582,9,96,-1,0,0,19,12584,15175),(15177,15177,15177,15177,15177,9,100,38013,94,180,19,-1,-1),(15179,-1,-1,15179,15179,7,96,-1,0,0,19,-1,15180),(15182,-1,-1,7757,7757,5,96,-1,0,0,19,12589,15183),(15188,-1,-1,1528,4819,5,96,-1,0,0,19,4823,15189),(15193,15193,15193,15193,15193,15,100,38016,92,600,19,-1,-1),(15194,-1,-1,15194,15194,9,100,-1,0,0,19,-1,-1),(15200,15200,15200,15200,15200,9,96,38304,32,1080,19,-1,15201),(15203,15203,15203,15203,15203,15,100,38307,34,480,19,-1,-1),(15204,-1,-1,15204,15204,9,96,-1,0,0,19,-1,15205),(15207,-1,-1,15207,15207,9,96,-1,0,0,19,-1,15208),(15210,15210,15210,15210,15210,9,96,38308,12,120,19,-1,15211),(15213,15213,15213,15213,15213,15,100,38312,42,1080,19,-1,17509),(15214,15214,15214,15214,15214,9,96,38313,43,1800,19,-1,15215),(15217,-1,-1,15217,15217,11,96,-1,0,0,19,-1,15218),(15220,-1,-1,15220,15220,9,100,-1,0,0,19,-1,15221),(15223,-1,-1,15223,15223,9,100,-1,0,0,19,-1,15224),(15226,-1,-1,15226,15226,9,100,-1,0,0,19,-1,15227),(15229,-1,-1,15229,15229,9,100,-1,0,0,19,-1,15230),(15232,-1,-1,15232,15232,9,96,-1,0,0,19,-1,15233),(15235,785,785,785,785,9,96,38325,8,900,19,789,15236),(15238,-1,-1,5276,5276,11,96,-1,0,0,19,5278,15239),(15241,168,168,168,168,11,96,38329,4,10,19,170,15242),(15244,171,171,171,171,11,96,38333,4,10,19,173,15245),(15247,174,174,174,174,11,96,38336,4,10,19,176,15248),(15250,177,177,177,177,11,96,38340,4,10,19,179,15251),(15253,-1,-1,15253,15253,4,96,-1,0,0,19,-1,15254),(15258,-1,-1,7743,7743,11,100,-1,0,0,19,10718,-1),(15270,-1,-1,12430,12430,15,100,-1,0,0,19,12878,-1),(15280,-1,-1,10722,10722,9,96,-1,0,0,19,10726,15281),(15283,-1,-1,15283,15283,5,96,-1,0,0,19,-1,15284),(15288,-1,-1,15288,15288,7,96,-1,0,0,19,-1,15289),(15295,-1,-1,15295,15295,7,96,-1,0,0,19,-1,15296),(15298,10806,10806,10806,10806,9,96,38025,71,540,19,10808,15299),(15301,10809,10809,10809,10809,9,96,38028,71,540,19,10811,15302),(15304,15304,15304,15304,15304,12,100,38031,91,360,19,-1,-1),(15314,0,0,6481,6481,11,96,-1,0,0,19,6483,15315),(15317,-1,-1,15317,15317,9,96,-1,0,0,19,5012,15318),(15320,-1,-1,7940,7940,11,100,-1,0,0,19,6486,-1),(15321,746,746,746,746,9,96,38033,10,2160,19,10024,15322),(15328,-1,-1,7948,7948,9,96,-1,0,0,19,10037,15329),(15338,15338,15338,15338,15338,9,96,38054,30,600,19,-1,15339),(15341,136,-1,136,136,7,100,38057,7,1800,19,136,-1),(15342,-1,-1,15341,15341,7,100,-1,0,0,19,-1,-1),(15343,15343,15343,15343,15343,12,100,38058,21,300,19,-1,-1),(15344,-1,-1,2400,2400,12,97,-1,0,0,19,2402,15345),(15348,-1,-1,13001,13001,7,96,-1,0,0,19,13003,15349),(15356,-1,-1,15356,15356,15,100,-1,0,0,19,-1,15851),(15357,15357,15357,15357,15357,9,96,38062,95,2,19,-1,-1),(15358,-1,-1,15358,15358,12,100,-1,0,0,19,-1,-1),(15359,-1,-1,474,474,5,96,-1,0,0,19,476,15360),(15362,15362,15362,15362,15362,15,100,38063,89,20,19,-1,-1),(15363,-1,-1,10951,10951,12,97,-1,0,0,19,10953,15364),(15371,-1,-1,15371,15371,7,96,-1,0,0,19,-1,15372),(15374,-1,-1,15374,15374,9,96,-1,0,0,19,-1,15375),(15377,15377,15377,15377,15377,15,100,38070,75,420,19,-1,15852),(15383,-1,-1,15383,15383,9,96,-1,0,0,19,-1,15384),(15389,-1,-1,15389,15389,9,96,-1,0,0,19,-1,15390),(15396,-1,-1,141,12863,12,100,-1,0,0,19,12863,-1),(15397,-1,-1,6346,6346,9,96,-1,0,0,19,7617,15398),(15403,-1,-1,15403,15403,7,96,-1,0,0,19,-1,15404),(15406,-1,-1,15406,15406,7,96,-1,0,0,19,-1,15407),(15414,-1,-1,15414,15414,9,100,-1,0,0,19,-1,-1),(15421,-1,-1,6538,6538,12,100,-1,0,0,19,7478,-1),(15422,-1,-1,83,83,12,100,-1,0,0,19,1218,-1),(15423,15423,15423,15423,15423,15,100,38078,52,180,19,-1,15884),(15424,15424,15424,15424,15424,12,100,38079,78,1200,19,-1,-1),(15425,15425,15425,15425,15425,15,100,38077,79,6,19,-1,15903),(15426,-1,-1,810,810,5,96,-1,0,0,19,4828,15427),(15429,-1,-1,15429,15429,7,96,-1,0,0,19,-1,15430),(15432,-1,-1,15432,15432,7,96,-1,0,0,19,-1,15433),(15438,-1,-1,15438,15438,9,96,-1,0,0,19,-1,15439),(15441,-1,-1,815,815,10,96,-1,0,0,19,7636,15442),(15444,-1,-1,15444,15444,9,96,38080,0,0,19,-1,15445),(15447,15447,15447,15447,15447,9,96,38083,78,180,19,-1,15448),(15450,-1,-1,15450,15450,9,96,-1,0,0,19,-1,15451),(15453,-1,-1,15453,15453,9,96,-1,0,0,19,-1,15454),(15456,-1,-1,15456,15456,9,96,-1,0,0,19,-1,15457),(15459,1245,1245,1245,1245,9,96,38404,8,2160,19,1247,15460),(15462,8039,8039,8039,38407,15,100,38407,58,7,19,8039,17167),(15466,-1,-1,10561,10561,9,96,-1,0,0,19,10563,15467),(15469,-1,-1,10558,10558,9,96,-1,0,0,19,10560,15470),(15472,-1,-1,8035,8035,9,96,-1,0,0,19,10287,15473),(15475,15475,15475,15475,15475,11,96,38408,41,600,20,-1,15476),(15478,-1,-1,15478,15478,9,96,-1,0,0,19,-1,15479),(15481,15481,15481,15481,15481,18,100,38603,53,1080,19,-1,-1),(15482,15482,15482,15482,15482,11,96,38414,42,1800,19,-1,15483),(15485,-1,-1,15485,15485,18,100,-1,0,0,19,-1,-1),(15486,15486,15486,15486,15486,12,96,38418,43,600,19,-1,15487),(15489,15489,15489,15489,15489,18,100,38421,52,10,19,-1,-1),(15490,15490,15490,15490,15490,11,96,38422,44,10,19,-1,15491),(15493,-1,-1,15493,15493,9,96,-1,0,0,19,-1,15494),(15496,15496,15496,15496,15496,11,96,38425,46,1800,19,-1,15497),(15502,-1,-1,15502,15502,9,96,-1,0,0,19,-1,15503),(15509,-1,-1,15509,15509,9,96,-1,0,0,19,-1,15510),(15512,-1,-1,15512,15512,9,96,38086,0,0,19,-1,15513),(15515,15515,15515,15515,15515,12,100,38089,11,90,19,-1,17417),(15516,-1,-1,15516,15516,9,100,-1,0,0,19,-1,15960),(15517,-1,-1,15517,15517,7,96,-1,0,0,19,-1,15518),(15521,15521,15521,15521,15521,12,96,38090,42,60,19,-1,-1),(15526,-1,-1,12716,12716,7,96,-1,0,0,19,12718,15527),(15529,-1,-1,695,695,4,96,-1,0,0,19,699,15530),(15540,-1,-1,15540,15540,7,96,-1,0,0,19,-1,15541),(15543,-1,-1,15543,15543,7,96,-1,0,0,19,-1,15544),(15546,-1,-1,15546,15546,7,96,-1,0,0,19,-1,15547),(15549,-1,-1,15549,15549,7,96,-1,0,0,19,-1,15550),(15552,-1,-1,6302,6302,5,96,-1,0,0,19,11013,15553),(15555,-1,-1,15555,15555,11,96,-1,0,0,19,-1,15556),(15558,10400,10400,10400,10400,9,100,38104,62,900,19,10400,-1),(15564,-1,-1,15564,15564,9,96,-1,0,0,19,-1,15565),(15567,15567,15567,15567,15567,12,96,38106,11,1200,19,-1,15568),(15569,15569,15569,15569,15569,12,96,38108,13,60,19,-1,15991),(15570,15570,15570,15570,15570,15,100,38109,64,600,19,-1,15992),(15571,-1,-1,15571,15571,7,96,-1,0,0,19,-1,15572),(15574,15574,15574,15574,15574,9,80,38110,73,4,15,-1,15575),(15575,15574,15574,15574,15574,9,85,38111,73,4,16,15574,15576),(15576,15574,15574,15574,15574,9,90,38112,73,4,17,15575,15577),(15577,15574,15574,15574,15574,9,95,38113,73,4,18,15576,15578),(15579,-1,-1,15579,15579,7,96,-1,0,0,19,-1,15580),(15582,15582,15582,15582,15582,9,96,38115,34,600,19,-1,15583),(15585,-1,-1,634,634,11,96,-1,0,0,19,10780,15586),(15588,10701,10701,10701,10701,12,96,38121,32,360,19,12756,15589),(15591,-1,-1,15591,15591,5,96,-1,0,0,19,-1,15592),(15594,15594,15594,15594,15594,9,96,38197,39,30,19,-1,15595),(15598,-1,-1,15598,15598,12,96,-1,0,0,19,-1,15599),(15601,15601,15601,15601,15601,12,96,38131,34,6,19,-1,16077),(15602,-1,-1,15602,15602,9,96,-1,0,0,19,-1,15603),(15605,12866,12866,12866,12866,15,96,38132,74,1800,19,12866,-1),(15606,-1,-1,8069,8069,5,96,-1,0,0,19,8071,15607),(15609,-1,-1,15609,15609,15,100,-1,0,0,19,-1,-1),(15611,15611,15611,15611,15611,18,100,38136,32,900,19,-1,16078),(15612,15612,15612,15612,15612,12,96,38137,36,20,19,-1,15613),(15615,15615,15615,15615,15615,12,96,38140,44,20,19,-1,15616),(15619,15619,15619,15619,15619,15,100,37188,32,600,19,-1,-1),(15622,-1,-1,15622,15622,7,96,-1,0,0,19,-1,15623),(15625,-1,-1,15625,15625,9,96,-1,0,0,19,-1,15626),(15628,5022,5022,5022,5022,9,96,38176,5,600,19,6040,15629),(15632,-1,-1,7005,7005,5,96,-1,0,0,19,7007,15633),(15634,-1,-1,15634,15634,3,80,-1,0,0,19,-1,15635),(15635,-1,-1,15634,15634,5,85,-1,0,0,19,15634,15636),(15639,15639,15639,15639,15639,12,96,38183,56,60,19,-1,-1),(15640,15640,15640,15640,15640,12,100,38184,43,60,19,-1,-1),(15642,15642,15642,15642,15642,18,100,38187,13,1440,19,-1,-1),(15643,15643,15643,15643,15643,9,96,38188,75,600,19,-1,15644),(15646,15646,15646,15646,15646,15,100,38194,74,60,19,-1,17255),(15648,-1,-1,15648,15648,9,96,-1,0,0,19,-1,15649),(15694,-1,-1,8215,8215,5,96,-1,0,0,20,12563,15695),(15714,-1,-1,5263,5263,12,96,-1,0,0,20,12468,15715),(15719,-1,-1,1287,1287,11,96,-1,0,0,20,13240,15720),(15746,-1,-1,7033,7033,12,96,0,0,0,20,7035,15747),(15768,-1,-1,15768,15768,7,96,-1,0,0,20,-1,15769),(15771,15771,-1,15771,15771,1,55,38274,0,3,20,-1,-1),(15772,-1,-1,8232,8232,8,100,-1,0,0,20,8261,-1),(15773,-1,-1,8040,8040,8,100,-1,0,0,20,8313,-1),(15775,6508,6508,6508,6508,9,96,38276,38,600,20,10080,15776),(15778,-1,-1,589,589,12,96,-1,0,0,20,13106,15779),(15782,7755,7755,7755,7755,12,96,38280,53,900,20,7755,16187),(15798,15798,15798,15798,15798,9,100,38297,34,18,20,-1,15799),(15819,15819,15819,15819,15819,18,100,40807,18,900,20,-1,-1),(15833,-1,-1,15833,15833,9,96,0,0,0,20,-1,15834),(15836,-1,-1,15836,15836,9,100,0,0,0,20,-1,15837),(15839,10450,10450,10450,10450,7,96,40817,63,900,20,10670,15840),(15855,13004,13004,13004,13004,9,96,40832,78,300,20,13004,-1),(15891,-1,-1,11078,11078,9,96,0,0,0,20,11078,15892),(15893,-1,-1,11079,11079,9,96,0,0,0,20,11079,15894),(15895,-1,-1,11077,11077,9,96,0,0,0,20,11077,15896),(15904,15904,15904,15904,15904,7,66,40874,54,600,20,-1,-1),(15908,-1,-1,15908,15908,3,80,-1,0,0,20,-1,15909),(15909,-1,-1,15908,15908,5,85,-1,0,0,20,15908,15910),(15910,-1,-1,15908,15908,7,90,-1,0,0,20,15909,15911),(15954,-1,-1,10853,10853,5,90,-1,0,0,20,10864,15955),(15961,-1,-1,12737,12737,9,96,0,0,0,20,12739,15962),(15988,10333,10333,10333,10333,9,96,40894,55,120,20,12726,15989),(16016,16016,16016,16016,16016,12,100,40919,17,12,20,-1,-1),(16062,-1,-1,1572,1572,5,96,-1,0,0,20,10556,16063),(16071,16071,16071,16071,16071,15,100,40953,46,1800,20,-1,16072),(16081,16081,16081,16081,16081,15,100,40969,55,6,20,-1,-1),(16082,16082,16082,16082,16082,3,100,40970,53,6,20,-1,-1),(16083,16083,16083,16083,16083,3,55,40971,46,6,20,-1,-1),(16084,-1,-1,16084,16084,9,100,0,0,0,20,-1,16085),(16087,-1,-1,16087,16087,5,100,0,0,6,20,-1,16088),(16094,-1,-1,477,477,2,100,-1,0,0,20,6235,16095),(16096,16096,16096,16096,16096,12,100,40972,36,6,20,-1,-1),(16097,16097,16097,16097,16097,12,100,40973,38,600,20,-1,16098),(16103,16103,16103,16103,16103,0,85,41071,35,180,16,-1,-1),(16104,-1,-1,16104,16104,5,85,0,0,0,20,-1,-1),(16105,16105,16105,16105,16105,0,85,41086,76,30,20,-1,-1),(16106,16106,16106,16106,16106,0,85,41087,76,30,20,-1,-1),(16107,16107,16107,16107,16107,0,85,41088,76,30,20,-1,-1),(16108,16108,16108,16108,16108,12,100,41090,77,120,20,-1,-1),(16109,-1,-1,16109,16109,11,96,-1,0,0,20,-1,16110),(16113,16113,16113,16113,16113,15,100,41096,78,60,20,-1,-1),(16114,-1,-1,16114,16114,5,96,-1,0,0,20,-1,16115),(16117,-1,-1,16117,16117,11,96,-1,0,0,20,-1,16118),(16120,-1,-1,16120,16120,9,105,-1,0,0,21,-1,-1),(16121,-1,-1,6611,6611,6,100,-1,0,0,20,10574,16122),(16124,-1,-1,16124,16124,5,96,-1,0,0,20,-1,16125),(16128,-1,-1,16128,16128,6,96,-1,0,0,20,-1,16129),(16131,-1,-1,16131,16131,5,96,-1,0,0,20,-1,16132),(16137,-1,-1,16137,16137,9,100,-1,0,0,20,-1,16138),(16140,-1,-1,16140,16140,9,100,-1,0,0,20,-1,-1),(16146,-1,-1,16146,16146,11,100,-1,0,0,20,-1,16147),(16149,-1,-1,16149,16149,9,100,-1,0,0,20,-1,16150),(16152,-1,-1,16152,16152,11,100,-1,0,0,20,-1,16153),(16156,-1,-1,16156,16156,12,100,-1,0,0,20,-1,16157),(16159,-1,-1,16159,16159,15,100,-1,0,0,20,-1,-1),(16160,16160,16160,16160,16160,18,100,41110,81,900,20,-1,-1),(16162,16162,16162,16162,16162,12,100,41112,80,180,20,-1,-1),(16163,16163,16163,16163,16163,18,100,41113,63,180,20,-1,16695),(16164,-1,-1,6636,6636,9,96,-1,0,0,20,12531,16165),(16170,-1,-1,5248,5248,12,96,-1,0,0,20,7358,16171),(16173,-1,-1,5263,5263,9,101,-1,0,0,21,12465,16174),(16176,-1,-1,16176,16176,7,100,-1,0,0,20,-1,16177),(16179,-1,-1,16179,16179,18,100,41122,0,0,20,-1,-1),(16180,-1,-1,16180,16180,7,96,-1,0,0,20,-1,16181),(16185,16185,16185,16185,16185,18,100,41124,68,600,20,-1,16729),(16186,-1,-1,16186,16186,12,100,41125,0,0,20,-1,-1),(16188,16188,16188,16188,16188,12,100,41126,58,180,20,-1,-1),(16189,-1,-1,10915,10915,9,96,-1,0,0,20,10917,16190),(16192,-1,-1,6641,6641,9,96,-1,0,0,20,10077,16193),(16195,16195,16195,16195,16195,15,100,41133,59,60,20,-1,-1),(16196,16196,16196,16196,16196,15,100,41134,60,900,20,-1,16665),(16197,16197,16197,16197,16197,12,96,41136,61,900,20,-1,16198),(16200,16200,16200,16200,16200,9,96,41139,63,900,20,-1,16201),(16203,16203,16203,16203,16203,12,96,41143,98,120,20,-1,16204),(16208,-1,-1,16208,16208,5,96,-1,0,0,20,-1,16209),(16211,-1,-1,16211,16211,7,100,-1,0,0,20,-1,16212),(16214,10958,10958,10958,16214,18,100,41148,62,900,20,13000,-1),(16215,16215,16215,16215,16215,9,96,41150,92,300,20,-1,16216),(16218,-1,-1,16218,16218,7,96,-1,0,0,20,-1,16219),(16221,-1,-1,16221,16221,9,100,-1,0,0,20,-1,16223),(16222,16222,-1,16222,16222,9,100,41153,88,30,20,-1,-1),(16225,-1,-1,16225,16225,5,96,-1,0,0,20,-1,16226),(16230,-1,-1,16230,16230,5,96,-1,0,0,20,-1,16231),(16235,-1,-1,16235,16235,7,96,-1,0,0,20,-1,16236),(16238,-1,-1,16238,16238,7,96,-1,0,0,20,-1,16239),(16246,6983,6983,6983,6983,9,96,41157,66,720,20,6983,16247),(16249,-1,-1,230,230,9,100,-1,0,0,20,12677,-1),(16250,828,828,828,828,9,96,41159,2,3600,20,830,-1),(16257,-1,-1,16257,16257,11,100,0,0,0,20,-1,16258),(16260,-1,-1,16260,16260,11,100,-1,0,0,20,-1,16261),(16263,16263,16263,16263,16263,11,96,41161,95,600,20,-1,16264),(16266,-1,-1,6560,6560,9,96,-1,0,0,20,6277,-1),(16267,-1,-1,888,888,3,96,-1,0,0,20,892,16268),(16272,-1,-1,16272,16272,9,96,-1,0,0,20,-1,16273),(16276,-1,-1,16276,16276,5,96,-1,0,0,20,-1,16277),(16287,-1,-1,16287,16287,7,96,-1,0,0,20,-1,16288),(16296,16296,16296,16296,16296,13,100,41168,60,30,20,-1,-1),(16297,-1,-1,6337,6337,6,96,-1,0,0,20,10155,16298),(16300,-1,-1,16300,16300,9,100,-1,0,0,20,-1,16301),(16303,-1,-1,12721,12721,9,96,0,0,0,20,12723,16304),(16306,-1,-1,6340,6340,6,96,-1,0,0,20,7453,-1),(16310,16310,16310,16310,16310,12,100,41169,97,600,20,-1,-1),(16317,-1,-1,16317,16317,5,100,-1,0,0,20,-1,16318),(16324,6607,6607,6607,16324,9,96,16491,61,600,20,6609,16325),(16327,-1,-1,6362,6362,7,96,0,0,0,20,6366,16328),(16330,-1,-1,16330,16330,9,96,-1,0,0,20,-1,16331),(16336,-1,-1,16336,16336,7,96,-1,0,0,20,-1,16337),(16339,-1,-1,16339,16339,7,96,-1,0,0,20,-1,16340),(16342,-1,-1,16342,16342,7,96,-1,0,0,20,-1,16343),(16360,16360,16360,16360,16360,9,100,41188,91,6,20,-1,-1),(16361,-1,-1,9509,9509,7,96,-1,0,0,20,9515,-1),(16363,16363,16363,16363,16363,12,96,41193,89,1800,20,-1,16364),(16366,-1,-1,16366,16366,12,96,-1,0,0,20,-1,16367),(16369,16369,16369,16369,16369,15,100,41196,98,12,20,-1,-1),(16370,16370,-1,16370,16370,5,100,41197,98,12,20,-1,-1),(16371,-1,-1,16371,16371,3,96,-1,0,0,20,-1,16372),(16380,-1,-1,16380,16380,5,96,-1,0,0,20,-1,16381),(16386,-1,-1,16386,16386,7,96,-1,0,0,20,-1,16387),(16392,-1,-1,16392,16392,5,96,-1,0,0,20,-1,16393),(16395,16395,16395,16395,16395,7,100,41305,93,10,20,-1,-1),(16396,-1,-1,16396,16396,7,96,-1,0,0,20,-1,16397),(16402,-1,-1,6112,6112,5,96,-1,0,0,20,12967,16403),(16414,-1,-1,1056,1056,5,101,-1,0,0,21,7525,16415),(16419,-1,-1,12636,12636,0,1,-1,0,0,16,8447,16420),(16420,-1,-1,12636,12636,0,1,-1,0,0,16,16419,16421),(16421,-1,-1,12636,12636,0,1,-1,0,0,16,16420,-1),(16440,-1,-1,6540,6540,10,101,-1,0,0,21,12510,16441),(16475,-1,-1,8201,8201,9,101,-1,0,0,21,8203,16476),(16489,-1,-1,1107,1107,9,101,-1,0,0,21,12558,16490),(16536,-1,-1,16536,16536,5,101,-1,0,0,21,-1,16537),(16604,-1,-1,849,849,11,105,-1,0,0,21,10622,-1),(16644,-1,-1,16644,16644,11,101,-1,0,0,21,-1,16645),(16666,-1,-1,16666,16666,9,101,-1,0,0,21,-1,16667),(16716,6764,6764,6764,6764,12,105,41308,52,600,21,10057,-1),(16730,-1,-1,1608,1608,13,101,-1,0,0,21,10069,16731),(16745,-1,-1,16745,16745,9,101,-1,0,0,21,-1,16746),(16883,1119,1119,1119,1119,12,101,41594,8,900,21,10299,16884),(16887,-1,-1,729,729,11,101,-1,0,0,21,10307,16888),(16890,-1,-1,724,724,15,101,-1,0,0,21,7493,16891),(17004,-1,-1,556,556,7,101,-1,0,0,21,1567,17005),(17030,4857,4857,4857,4857,15,101,41660,7,600,21,5769,17031),(17131,12785,12785,12785,12785,15,105,41736,80,30,21,12785,-1),(17199,17199,17199,17199,17199,100,51,41819,31,2,21,-1,-1),(17206,-1,-1,10588,10588,7,101,0,0,0,21,10592,17207),(17209,-1,-1,17209,17209,9,101,-1,0,0,21,-1,17210),(17212,-1,-1,17212,17212,12,101,-1,0,0,21,-1,17213),(17215,-1,-1,17215,17215,12,101,-1,0,0,21,-1,17216),(17218,-1,-1,17218,17218,9,101,-1,0,0,21,-1,17219),(17229,-1,-1,17229,17229,9,101,-1,0,0,21,-1,17230),(17235,-1,-1,17235,17235,15,101,-1,0,0,21,-1,17236),(17238,17238,17238,17238,17238,24,105,41808,10,900,21,-1,-1),(17239,-1,-1,6489,6489,12,101,-1,0,0,21,6491,-1),(17242,-1,-1,17242,17242,12,101,-1,0,0,21,-1,17243),(17245,-1,-1,17245,17245,12,101,-1,0,0,21,-1,17246),(17248,17248,17248,17248,17248,24,105,41811,93,1080,21,-1,-1),(17249,-1,-1,17249,17249,12,101,-1,0,0,21,-1,17250),(17252,-1,-1,17252,17252,9,101,-1,0,0,21,-1,17253),(17256,17256,17256,17256,17256,21,105,41815,93,360,21,-1,-1),(17257,17257,17257,17257,17257,21,105,41816,98,300,21,-1,-1),(17258,-1,-1,17258,17258,15,101,0,0,0,21,-1,17259),(17267,-1,-1,17267,17267,9,101,-1,0,0,21,-1,17268),(17273,17273,17273,17273,17273,15,101,41830,98,720,21,-1,-1),(17276,1569,1569,1569,1569,9,101,41831,5,1800,21,10161,17277),(17280,17280,17280,17280,17280,21,105,41834,97,720,21,-1,-1),(17281,-1,-1,17281,17281,15,105,-1,0,0,21,-1,-1),(17288,-1,-1,17288,17288,9,105,-1,0,0,21,7317,-1),(17289,-1,-1,17289,17289,7,101,-1,0,0,21,-1,17290),(17295,-1,-1,692,692,12,101,-1,0,0,21,12769,17296),(17298,749,749,749,749,15,105,41837,11,1800,21,1208,-1),(17307,-1,-1,17307,17307,9,101,-1,0,0,21,-1,17308),(17310,-1,-1,7945,7945,9,105,-1,0,0,21,10347,-1),(17311,970,970,970,970,9,101,41845,6,1800,21,1326,17312),(17317,-1,-1,17317,17317,9,101,-1,0,0,21,-1,17318),(17328,17328,17328,17328,17328,21,105,41854,87,600,21,-1,-1),(17329,17329,17329,17329,17329,12,101,41855,88,20,21,-1,-1),(17333,153,153,153,153,18,105,41856,3,2160,21,12996,-1),(17334,-1,-1,12977,12977,12,102,0,0,0,21,12981,17335),(17336,-1,-1,17336,17336,9,101,-1,0,0,21,-1,17337),(17339,-1,-1,17339,17339,9,101,-1,0,0,21,-1,17340),(17342,17342,17342,17342,17342,15,105,41857,85,60,21,-1,-1),(17344,17344,17344,17344,17344,15,101,41858,94,780,21,-1,17345),(17347,17347,17347,17347,17347,12,101,41861,32,30,21,-1,17348),(17350,-1,-1,7664,7664,5,102,-1,0,0,21,10109,17351),(17357,-1,-1,17357,17357,9,96,-1,0,0,19,-1,17358),(17361,-1,-1,17361,17361,5,100,-1,0,0,21,-1,17362),(17364,17364,17364,17364,17364,15,105,46160,87,120,21,-1,-1),(17365,-1,-1,10792,10792,15,101,0,0,0,21,10796,17366),(17370,-1,-1,17370,17370,15,102,0,0,0,21,-1,17371),(17372,17372,17372,17372,17372,18,104,46161,85,300,21,-1,-1),(17373,17373,-1,17373,17373,15,105,46162,98,900,21,-1,-1),(17375,-1,-1,17375,17375,12,101,-1,0,0,21,-1,17376),(17378,17378,17378,17378,17378,10,101,46164,97,3,21,-1,-1),(17379,17378,17378,17378,17378,10,101,46165,86,3,21,-1,-1),(17380,17378,17378,17378,17378,10,101,46166,97,3,21,-1,-1),(17382,5015,5015,5015,5015,15,103,46168,9,900,21,10301,-1),(17384,17384,17384,17384,17384,18,101,46171,10,20,21,-1,-1),(17391,-1,-1,495,495,12,105,-1,0,0,21,10668,-1),(17406,-1,-1,10653,10653,12,103,-1,0,0,21,10655,-1),(17409,-1,-1,17409,17409,15,105,-1,0,0,21,-1,-1),(17414,-1,-1,17414,17414,9,101,-1,0,0,21,-1,17415),(17418,-1,-1,17418,17418,7,101,-1,0,0,21,-1,17419),(17428,17428,17428,17428,17428,15,101,46178,0,0,21,-1,17429),(17436,-1,-1,17436,17436,7,101,-1,0,0,21,-1,17437),(17439,-1,-1,17439,17439,9,102,-1,0,0,21,-1,17440),(17441,-1,-1,255,255,15,102,-1,0,0,21,7633,-1),(17445,-1,-1,17445,17445,15,101,0,0,0,21,-1,17446),(17448,-1,-1,17448,17448,15,102,0,0,0,21,-1,17449),(17476,-1,-1,10800,10800,15,101,-1,0,0,21,10802,17477),(17486,12864,-1,12864,12864,12,105,46195,73,10,21,12864,-1),(17492,-1,-1,17492,17492,9,101,-1,0,0,21,-1,17493),(17495,-1,-1,17495,17495,9,101,-1,0,0,21,-1,17496),(17515,-1,-1,17515,17515,7,102,-1,0,0,21,-1,17516),(17517,-1,-1,17517,17517,9,101,-1,0,0,21,-1,17518),(17522,-1,-1,17522,17522,9,101,-1,0,0,21,-1,17523),(17533,-1,-1,17533,17533,15,105,-1,0,0,21,-1,-1),(17534,6828,6828,6828,6828,15,105,46207,43,60,21,10208,-1),(17535,967,967,967,967,9,101,46208,10,1800,21,12791,17536),(17538,17538,17538,17538,17538,21,105,46212,91,1800,21,-1,-1),(17539,4934,4934,4934,4934,12,105,46214,13,300,21,10278,-1),(17540,4935,4935,4935,4935,12,105,46215,14,300,21,10277,-1),(17541,8038,8038,8038,8038,12,105,46217,56,12,21,8038,-1),(17547,-1,-1,17547,17547,12,102,-1,0,0,21,-1,17548),(17549,-1,-1,17549,17549,9,101,-1,0,0,21,-1,17550),(17553,-1,-1,17553,17553,18,105,-1,0,0,21,-1,-1),(17554,-1,-1,17554,17554,15,105,-1,0,0,21,-1,-1),(17555,-1,-1,17555,17555,5,101,-1,0,0,21,-1,17556),(17558,-1,-1,17558,17558,5,101,-1,0,0,21,-1,17559),(17561,-1,-1,17561,17561,5,101,-1,0,0,21,-1,17562),(17564,-1,-1,17564,17564,5,101,-1,0,0,21,-1,17565),(17567,-1,-1,17567,17567,5,101,-1,0,0,21,-1,17568),(17570,-1,-1,17570,17570,5,101,-1,0,0,21,-1,17571),(17573,-1,-1,17573,17573,5,101,-1,0,0,21,-1,17574),(17576,-1,-1,17576,17576,5,101,-1,0,0,21,-1,17577),(17579,-1,-1,17579,17579,5,101,-1,0,0,21,-1,17580),(17582,-1,-1,17582,17582,5,101,-1,0,0,21,-1,17583),(17585,-1,-1,17585,17585,5,101,-1,0,0,21,-1,17586),(17588,-1,-1,17588,17588,5,101,-1,0,0,21,-1,17589),(17591,-1,-1,17591,17591,5,101,-1,0,0,21,-1,17592),(17594,-1,-1,17594,17594,5,101,-1,0,0,21,-1,17595),(17597,-1,-1,17597,17597,5,101,-1,0,0,21,-1,17598),(17600,-1,-1,17600,17600,5,101,-1,0,0,21,-1,17601),(17603,-1,-1,17603,17603,5,101,-1,0,0,21,-1,17604),(17606,-1,-1,17606,17606,5,101,-1,0,0,21,-1,17607),(17609,-1,-1,17609,17609,5,101,-1,0,0,21,-1,17610),(17612,-1,-1,17612,17612,5,101,-1,0,0,21,-1,17613),(17615,-1,-1,17615,17615,5,101,-1,0,0,21,-1,17616),(17618,-1,-1,17618,17618,5,101,-1,0,0,21,-1,17619),(17621,-1,-1,17621,17621,5,101,-1,0,0,21,-1,17622),(17624,-1,-1,17624,17624,5,101,-1,0,0,21,-1,17625),(17627,-1,-1,17627,17627,5,101,-1,0,0,21,-1,17628),(17630,-1,-1,17630,17630,5,101,-1,0,0,21,-1,17631),(17633,-1,-1,17633,17633,5,101,-1,0,0,21,-1,17634),(17639,-1,-1,17639,17639,9,91,0,0,0,18,-1,17640),(18972,-1,-1,279,279,15,105,-1,0,0,21,279,-1),(30050,-1,-1,30050,30050,0,1,-1,0,0,0,-1,30051),(30100,-1,-1,30100,30100,0,1,-1,0,0,0,-1,30101),(30150,-1,-1,30150,30150,0,1,-1,0,0,0,-1,30151),(30175,-1,-1,30175,30175,0,1,-1,0,0,0,-1,30176),(30180,-1,-1,30180,30180,0,1,-1,0,0,0,-1,30181),(30185,-1,-1,30185,30185,0,1,-1,0,0,0,-1,30186),(30190,-1,-1,30190,30190,0,1,-1,0,0,0,-1,30191),(30195,-1,-1,30195,30195,0,1,-1,0,0,0,-1,30196),(49999,-1,-1,-1,-1,0,71,0,0,0,0,-1,1); +/*!40000 ALTER TABLE `aa_ranks` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `aa_rank_effects` +-- --- Dumping structure for table eqdb.aa_rank_effects DROP TABLE IF EXISTS `aa_rank_effects`; -CREATE TABLE IF NOT EXISTS `aa_rank_effects` ( +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `aa_rank_effects` ( `rank_id` int(10) unsigned NOT NULL, - `slot` int(10) unsigned NOT NULL DEFAULT '1', - `effect_id` int(10) NOT NULL DEFAULT '0', - `base1` int(10) NOT NULL DEFAULT '0', - `base2` int(10) NOT NULL DEFAULT '0', + `slot` int(10) unsigned NOT NULL DEFAULT 1, + `effect_id` int(10) NOT NULL DEFAULT 0, + `base1` int(10) NOT NULL DEFAULT 0, + `base2` int(10) NOT NULL DEFAULT 0, PRIMARY KEY (`rank_id`,`slot`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; -INSERT INTO `aa_rank_effects` (`rank_id`, `slot`, `effect_id`, `base1`, `base2`) VALUES - (2, 1, 4, 2, 0), - (3, 1, 4, 4, 0), - (4, 1, 4, 6, 0), - (5, 1, 4, 8, 0), - (6, 1, 4, 10, 0), - (7, 1, 7, 2, 0), - (8, 1, 7, 4, 0), - (9, 1, 7, 6, 0), - (10, 1, 7, 8, 0), - (11, 1, 7, 10, 0), - (12, 1, 6, 2, 0), - (13, 1, 6, 4, 0), - (14, 1, 6, 6, 0), - (15, 1, 6, 8, 0), - (16, 1, 6, 10, 0), - (17, 1, 5, 2, 0), - (18, 1, 5, 4, 0), - (19, 1, 5, 6, 0), - (20, 1, 5, 8, 0), - (21, 1, 5, 10, 0), - (22, 1, 8, 2, 0), - (23, 1, 8, 4, 0), - (24, 1, 8, 6, 0), - (25, 1, 8, 8, 0), - (26, 1, 8, 10, 0), - (27, 1, 9, 2, 0), - (28, 1, 9, 4, 0), - (29, 1, 9, 6, 0), - (30, 1, 9, 8, 0), - (31, 1, 9, 10, 0), - (32, 1, 10, 2, 0), - (33, 1, 10, 4, 0), - (34, 1, 10, 6, 0), - (35, 1, 10, 8, 0), - (36, 1, 10, 10, 0), - (37, 1, 46, 2, 0), - (38, 1, 46, 4, 0), - (39, 1, 46, 6, 0), - (40, 1, 46, 8, 0), - (41, 1, 46, 10, 0), - (42, 1, 47, 2, 0), - (43, 1, 47, 4, 0), - (44, 1, 47, 6, 0), - (45, 1, 47, 8, 0), - (46, 1, 47, 10, 0), - (47, 1, 50, 2, 0), - (48, 1, 50, 4, 0), - (49, 1, 50, 6, 0), - (50, 1, 50, 8, 0), - (51, 1, 50, 10, 0), - (52, 1, 48, 2, 0), - (53, 1, 48, 4, 0), - (54, 1, 48, 6, 0), - (55, 1, 48, 8, 0), - (56, 1, 48, 10, 0), - (57, 1, 49, 2, 0), - (58, 1, 49, 4, 0), - (59, 1, 49, 6, 0), - (60, 1, 49, 8, 0), - (61, 1, 49, 10, 0), - (62, 1, 271, 8, 0), - (63, 1, 271, 14, 0), - (64, 1, 271, 21, 0), - (68, 1, 233, 110, 0), - (69, 1, 233, 125, 0), - (70, 1, 233, 150, 0), - (71, 1, 246, 110, 0), - (72, 1, 246, 125, 0), - (73, 1, 246, 150, 0), - (74, 1, 269, 10, 0), - (75, 1, 269, 20, 0), - (76, 1, 269, 30, 0), - (77, 1, 125, 2, 2), - (77, 2, 137, 0, 0), - (77, 3, 141, 1, 0), - (77, 4, 139, -6233, 0), - (77, 5, 139, -6265, 0), - (77, 6, 125, 2, 2), - (77, 7, 137, 147, 0), - (77, 8, 141, 1, 0), - (78, 1, 125, 5, 5), - (78, 2, 137, 0, 0), - (78, 3, 141, 1, 0), - (78, 4, 139, -6233, 0), - (78, 5, 139, -6265, 0), - (78, 6, 125, 5, 5), - (78, 7, 137, 147, 0), - (78, 8, 141, 1, 0), - (79, 1, 125, 10, 10), - (79, 2, 137, 0, 0), - (79, 3, 141, 1, 0), - (79, 4, 139, -6233, 0), - (79, 5, 139, -6265, 0), - (79, 6, 125, 10, 10), - (79, 7, 137, 147, 0), - (79, 8, 141, 1, 0), - (80, 1, 274, 3, 0), - (81, 1, 274, 6, 0), - (82, 1, 274, 10, 0), - (83, 1, 132, 2, 2), - (84, 1, 132, 5, 5), - (85, 1, 132, 10, 10), - (86, 1, 128, 5, 5), - (86, 2, 138, 1, 0), - (86, 3, 140, 1, 0), - (86, 4, 139, -2741, 0), - (86, 5, 139, -16843, 0), - (86, 6, 385, -16192, 0), - (86, 7, 385, -10547, 0), - (86, 8, 385, -13543, 0), - (87, 1, 128, 15, 15), - (87, 2, 138, 1, 0), - (87, 3, 140, 1, 0), - (87, 4, 139, -2741, 0), - (87, 5, 139, -16843, 0), - (87, 6, 385, -16192, 0), - (87, 7, 385, -10547, 0), - (87, 8, 385, -13543, 0), - (88, 1, 128, 30, 30), - (88, 2, 138, 1, 0), - (88, 3, 140, 1, 0), - (88, 4, 139, -2741, 0), - (88, 5, 139, -16843, 0), - (88, 6, 385, -16192, 0), - (88, 7, 385, -10547, 0), - (88, 8, 385, -13543, 0), - (92, 1, 294, 2, 100), - (93, 1, 294, 4, 100), - (94, 1, 294, 7, 100), - (98, 1, 114, -5, 0), - (99, 1, 114, -10, 0), - (100, 1, 114, -20, 0), - (101, 1, 265, 20, 0), - (102, 1, 265, 40, 0), - (103, 1, 265, 52, 0), - (104, 1, 127, 10, 10), - (104, 2, 138, 1, 0), - (104, 3, 140, 1, 0), - (104, 4, 143, 3000, 0), - (105, 1, 127, 25, 25), - (105, 2, 138, 1, 0), - (105, 3, 140, 1, 0), - (105, 4, 143, 3000, 0), - (106, 1, 127, 50, 50), - (106, 2, 138, 1, 0), - (106, 3, 140, 1, 0), - (106, 4, 143, 3000, 0), - (107, 1, 214, 200, 0), - (108, 1, 214, 500, 0), - (109, 1, 214, 1000, 0), - (110, 1, 0, 1, 0), - (111, 1, 0, 2, 0), - (112, 1, 0, 3, 0), - (113, 1, 169, 15, -1), - (114, 1, 169, 40, -1), - (115, 1, 169, 75, -1), - (116, 1, 181, 5, 0), - (117, 1, 181, 10, 0), - (118, 1, 181, 25, 0), - (119, 1, 278, 500, 16000), - (119, 2, 440, 50, 100), - (120, 1, 278, 510, 17102), - (120, 2, 440, 52, 100), - (121, 1, 278, 520, 19635), - (121, 2, 440, 54, 100), - (122, 1, 259, 2, 0), - (123, 1, 259, 5, 0), - (124, 1, 259, 10, 0), - (125, 1, 172, 2, 0), - (126, 1, 172, 5, 0), - (127, 1, 172, 10, 0), - (137, 1, 127, 10, 10), - (137, 2, 137, 88, 0), - (138, 1, 127, 25, 25), - (138, 2, 137, 88, 0), - (139, 1, 127, 50, 50), - (139, 2, 137, 88, 0), - (141, 1, 127, 2, 2), - (141, 2, 137, 0, 0), - (141, 3, 138, 0, 0), - (141, 4, 141, 1, 0), - (141, 5, 143, 3000, 0), - (141, 6, 127, 2, 2), - (141, 7, 385, 16555, 0), - (141, 8, 385, 16655, 0), - (142, 1, 127, 5, 5), - (142, 2, 137, 0, 0), - (142, 3, 138, 0, 0), - (142, 4, 141, 1, 0), - (142, 5, 143, 3000, 0), - (142, 6, 127, 5, 5), - (142, 7, 385, 16555, 0), - (142, 8, 385, 16655, 0), - (143, 1, 127, 10, 10), - (143, 2, 137, 0, 0), - (143, 3, 138, 0, 0), - (143, 4, 141, 1, 0), - (143, 5, 143, 3000, 0), - (143, 6, 127, 10, 10), - (143, 7, 385, 16555, 0), - (143, 8, 385, 16655, 0), - (144, 1, 244, 50, 0), - (147, 1, 127, 10, 10), - (147, 2, 138, 1, 0), - (147, 3, 140, 1, 0), - (147, 4, 143, 3000, 0), - (148, 1, 127, 25, 25), - (148, 2, 138, 1, 0), - (148, 3, 140, 1, 0), - (148, 4, 143, 3000, 0), - (149, 1, 127, 50, 50), - (149, 2, 138, 1, 0), - (149, 3, 140, 1, 0), - (149, 4, 143, 3000, 0), - (150, 1, 268, 10, 59), - (151, 1, 268, 25, 59), - (152, 1, 268, 50, 59), - (158, 1, 238, 1, 0), - (159, 1, 268, 10, 68), - (160, 1, 268, 25, 68), - (161, 1, 268, 50, 68), - (182, 1, 131, 100, 0), - (182, 2, 137, 33, 0), - (190, 1, 219, 225, 680), - (191, 1, 219, 235, 1190), - (192, 1, 219, 240, 1700), - (195, 1, 181, 100, 0), - (196, 1, 226, 1, 0), - (198, 1, 276, 32, 0), - (199, 1, 301, 30, 0), - (200, 1, 301, 60, 0), - (201, 1, 301, 100, 0), - (205, 1, 251, 100, 0), - (210, 1, 302, 50, 50), - (210, 2, 385, 99, 0), - (211, 1, 302, 100, 100), - (211, 2, 385, 99, 0), - (212, 1, 302, 200, 200), - (212, 2, 385, 99, 0), - (213, 1, 260, 2, 23), - (213, 2, 260, 2, 24), - (213, 3, 260, 2, 25), - (213, 4, 260, 2, 26), - (214, 1, 260, 4, 23), - (214, 2, 260, 4, 24), - (214, 3, 260, 4, 25), - (214, 4, 260, 4, 26), - (215, 1, 260, 6, 23), - (215, 2, 260, 6, 24), - (215, 3, 260, 6, 25), - (215, 4, 260, 6, 26), - (225, 1, 272, 1, 0), - (226, 1, 272, 3, 0), - (227, 1, 272, 5, 0), - (230, 1, 275, 10, 0), - (231, 1, 275, 20, 0), - (232, 1, 275, 30, 0), - (237, 1, 227, 1, 25), - (238, 1, 227, 3, 25), - (239, 1, 227, 5, 25), - (240, 1, 224, 20, 26), - (240, 2, 173, 1, 0), - (241, 1, 224, 35, 26), - (241, 2, 173, 2, 0), - (242, 1, 224, 50, 26), - (242, 2, 173, 3, 0), - (244, 1, 268, 10, 56), - (244, 2, 234, 7500, 0), - (245, 1, 268, 25, 56), - (245, 2, 234, 5000, 0), - (246, 1, 268, 50, 56), - (246, 2, 234, 2500, 0), - (247, 1, 224, 15, 0), - (248, 1, 224, 30, 0), - (249, 1, 224, 50, 0), - (255, 1, 279, 7, 0), - (256, 1, 279, 11, 0), - (257, 1, 279, 15, 0), - (263, 1, 282, 10, 0), - (264, 1, 282, 25, 0), - (265, 1, 282, 50, 0), - (266, 1, 128, 50, 50), - (266, 2, 138, 1, 0), - (266, 3, 140, 1, 0), - (266, 4, 139, -2741, 0), - (266, 5, 139, -16843, 0), - (266, 6, 385, -16192, 0), - (266, 7, 385, -10547, 0), - (266, 8, 385, -13543, 0), - (267, 1, 294, 2, 100), - (268, 1, 294, 4, 100), - (269, 1, 294, 6, 100), - (273, 1, 288, 1000, 21), - (275, 1, 260, 2, 50), - (276, 1, 260, 4, 50), - (277, 1, 260, 6, 50), - (278, 1, 0, 1, 0), - (278, 2, 15, 1, 0), - (279, 1, 214, 200, 0), - (279, 2, 259, 2, 0), - (279, 3, 172, 2, 0), - (280, 1, 227, 1, 62), - (280, 2, 227, 1, 17), - (281, 1, 227, 3, 62), - (281, 2, 227, 3, 17), - (282, 1, 227, 5, 62), - (282, 2, 227, 5, 17), - (283, 1, 228, 10, 0), - (284, 1, 228, 20, 0), - (285, 1, 228, 30, 0), - (286, 1, 10, 0, 0), - (287, 1, 253, 1, 0), - (288, 1, 257, 1, 0), - (288, 2, 267, 1, 31), - (288, 3, 267, 1, 32), - (288, 4, 267, 1, 33), - (288, 5, 267, 1, 15), - (288, 6, 267, 1, 16), - (288, 7, 267, 1, 17), - (288, 8, 267, 1, 18), - (288, 9, 267, 1, 19), - (288, 10, 267, 1, 20), - (292, 1, 4, 12, 0), - (293, 1, 4, 14, 0), - (294, 1, 4, 16, 0), - (295, 1, 4, 18, 0), - (296, 1, 4, 20, 0), - (297, 1, 4, 22, 0), - (298, 1, 4, 24, 0), - (299, 1, 4, 26, 0), - (300, 1, 4, 28, 0), - (301, 1, 4, 30, 0), - (302, 1, 7, 12, 0), - (303, 1, 7, 14, 0), - (304, 1, 7, 16, 0), - (305, 1, 7, 18, 0), - (306, 1, 7, 20, 0), - (307, 1, 7, 22, 0), - (308, 1, 7, 24, 0), - (309, 1, 7, 26, 0), - (310, 1, 7, 28, 0), - (311, 1, 7, 30, 0), - (312, 1, 6, 12, 0), - (313, 1, 6, 14, 0), - (314, 1, 6, 16, 0), - (315, 1, 6, 18, 0), - (316, 1, 6, 20, 0), - (317, 1, 6, 22, 0), - (318, 1, 6, 24, 0), - (319, 1, 6, 26, 0), - (320, 1, 6, 28, 0), - (321, 1, 6, 30, 0), - (322, 1, 5, 12, 0), - (323, 1, 5, 14, 0), - (324, 1, 5, 16, 0), - (325, 1, 5, 18, 0), - (326, 1, 5, 20, 0), - (327, 1, 5, 22, 0), - (328, 1, 5, 24, 0), - (329, 1, 5, 26, 0), - (330, 1, 5, 28, 0), - (331, 1, 5, 30, 0), - (332, 1, 8, 12, 0), - (333, 1, 8, 14, 0), - (334, 1, 8, 16, 0), - (335, 1, 8, 18, 0), - (336, 1, 8, 20, 0), - (337, 1, 8, 22, 0), - (338, 1, 8, 24, 0), - (339, 1, 8, 26, 0), - (340, 1, 8, 28, 0), - (341, 1, 8, 30, 0), - (342, 1, 9, 12, 0), - (343, 1, 9, 14, 0), - (344, 1, 9, 16, 0), - (345, 1, 9, 18, 0), - (346, 1, 9, 20, 0), - (347, 1, 9, 22, 0), - (348, 1, 9, 24, 0), - (349, 1, 9, 26, 0), - (350, 1, 9, 28, 0), - (351, 1, 9, 30, 0), - (352, 1, 10, 12, 0), - (353, 1, 10, 14, 0), - (354, 1, 10, 16, 0), - (355, 1, 10, 18, 0), - (356, 1, 10, 20, 0), - (357, 1, 10, 22, 0), - (358, 1, 10, 24, 0), - (359, 1, 10, 26, 0), - (360, 1, 10, 28, 0), - (361, 1, 10, 30, 0), - (362, 1, 46, 12, 0), - (363, 1, 46, 14, 0), - (364, 1, 46, 16, 0), - (365, 1, 46, 18, 0), - (366, 1, 46, 20, 0), - (367, 1, 46, 22, 0), - (368, 1, 46, 24, 0), - (369, 1, 46, 26, 0), - (370, 1, 46, 28, 0), - (371, 1, 46, 30, 0), - (372, 1, 47, 12, 0), - (373, 1, 47, 14, 0), - (374, 1, 47, 16, 0), - (375, 1, 47, 18, 0), - (376, 1, 47, 20, 0), - (377, 1, 47, 22, 0), - (378, 1, 47, 24, 0), - (379, 1, 47, 26, 0), - (380, 1, 47, 28, 0), - (381, 1, 47, 30, 0), - (382, 1, 50, 12, 0), - (383, 1, 50, 14, 0), - (384, 1, 50, 16, 0), - (385, 1, 50, 18, 0), - (386, 1, 50, 20, 0), - (387, 1, 50, 22, 0), - (388, 1, 50, 24, 0), - (389, 1, 50, 26, 0), - (390, 1, 50, 28, 0), - (391, 1, 50, 30, 0), - (392, 1, 48, 12, 0), - (393, 1, 48, 14, 0), - (394, 1, 48, 16, 0), - (395, 1, 48, 18, 0), - (396, 1, 48, 20, 0), - (397, 1, 48, 22, 0), - (398, 1, 48, 24, 0), - (399, 1, 48, 26, 0), - (400, 1, 48, 28, 0), - (401, 1, 48, 30, 0), - (402, 1, 49, 12, 0), - (403, 1, 49, 14, 0), - (404, 1, 49, 16, 0), - (405, 1, 49, 18, 0), - (406, 1, 49, 20, 0), - (407, 1, 49, 22, 0), - (408, 1, 49, 24, 0), - (409, 1, 49, 26, 0), - (410, 1, 49, 28, 0), - (411, 1, 49, 30, 0), - (412, 1, 263, 1, 0), - (413, 1, 263, 2, 0), - (414, 1, 263, 3, 0), - (415, 1, 263, 4, 0), - (416, 1, 263, 5, 0), - (417, 1, 263, 6, 0), - (418, 1, 262, 5, 0), - (418, 2, 262, 5, 1), - (418, 3, 262, 5, 2), - (418, 4, 262, 5, 3), - (418, 5, 262, 5, 4), - (418, 6, 262, 5, 5), - (418, 7, 262, 5, 6), - (419, 1, 262, 10, 0), - (419, 2, 262, 10, 1), - (419, 3, 262, 10, 2), - (419, 4, 262, 10, 3), - (419, 5, 262, 10, 4), - (419, 6, 262, 10, 5), - (419, 7, 262, 10, 6), - (420, 1, 262, 15, 0), - (420, 2, 262, 15, 1), - (420, 3, 262, 15, 2), - (420, 4, 262, 15, 3), - (420, 5, 262, 15, 4), - (420, 6, 262, 15, 5), - (420, 7, 262, 15, 6), - (421, 1, 262, 20, 0), - (421, 2, 262, 20, 1), - (421, 3, 262, 20, 2), - (421, 4, 262, 20, 3), - (421, 5, 262, 20, 4), - (421, 6, 262, 20, 5), - (421, 7, 262, 20, 6), - (422, 1, 262, 25, 0), - (422, 2, 262, 25, 1), - (422, 3, 262, 25, 2), - (422, 4, 262, 25, 3), - (422, 5, 262, 25, 4), - (422, 6, 262, 25, 5), - (422, 7, 262, 25, 6), - (423, 1, 214, 150, 0), - (424, 1, 214, 300, 0), - (425, 1, 214, 450, 0), - (426, 1, 262, 10, 5), - (426, 2, 262, 10, 4), - (427, 1, 262, 20, 5), - (427, 2, 262, 20, 4), - (428, 1, 262, 30, 5), - (428, 2, 262, 30, 4), - (429, 1, 262, 40, 5), - (429, 2, 262, 40, 4), - (430, 1, 262, 50, 5), - (430, 2, 262, 50, 4), - (434, 1, 125, 13, 13), - (434, 2, 137, 0, 0), - (434, 3, 141, 1, 0), - (434, 4, 139, -6233, 0), - (434, 5, 139, -6265, 0), - (434, 6, 125, 13, 13), - (434, 7, 137, 147, 0), - (434, 8, 141, 1, 0), - (435, 1, 125, 16, 16), - (435, 2, 137, 0, 0), - (435, 3, 141, 1, 0), - (435, 4, 139, -6233, 0), - (435, 5, 139, -6265, 0), - (435, 6, 125, 16, 16), - (435, 7, 137, 147, 0), - (435, 8, 141, 1, 0), - (436, 1, 125, 19, 19), - (436, 2, 137, 0, 0), - (436, 3, 141, 1, 0), - (436, 4, 139, -6233, 0), - (436, 5, 139, -6265, 0), - (436, 6, 125, 19, 19), - (436, 7, 137, 147, 0), - (436, 8, 141, 1, 0), - (437, 1, 274, 12, 0), - (438, 1, 274, 14, 0), - (439, 1, 274, 16, 0), - (440, 1, 278, 530, 21210), - (440, 2, 440, 56, 100), - (441, 1, 278, 540, 23160), - (441, 2, 440, 58, 100), - (442, 1, 278, 550, 25230), - (442, 2, 440, 60, 100), - (443, 1, 169, 100, -1), - (444, 1, 169, 125, -1), - (445, 1, 169, 150, -1), - (446, 1, 265, 54, 0), - (447, 1, 265, 56, 0), - (448, 1, 265, 58, 0), - (449, 1, 172, 13, 0), - (450, 1, 172, 16, 0), - (451, 1, 172, 19, 0), - (452, 1, 172, 22, 0), - (453, 1, 172, 25, 0), - (454, 1, 259, 13, 0), - (455, 1, 259, 16, 0), - (456, 1, 259, 19, 0), - (457, 1, 259, 22, 0), - (458, 1, 259, 25, 0), - (462, 1, 264, 60, 39), - (462, 2, 264, 864, 1061), - (463, 1, 264, 120, 39), - (463, 2, 264, 1728, 1061), - (464, 1, 264, 180, 39), - (464, 2, 264, 2592, 1061), - (468, 1, 264, 180, 41), - (469, 1, 264, 360, 41), - (470, 1, 264, 540, 41), - (471, 1, 264, 864, 57), - (471, 2, 264, 864, 616), - (472, 1, 264, 1728, 57), - (472, 2, 264, 1728, 616), - (473, 1, 264, 2592, 57), - (473, 2, 264, 2592, 616), - (474, 1, 264, 240, 50), - (475, 1, 264, 480, 50), - (476, 1, 264, 720, 50), - (477, 1, 264, 432, 43), - (478, 1, 264, 864, 43), - (479, 1, 264, 1296, 43), - (480, 1, 264, 432, 117), - (481, 1, 264, 864, 117), - (482, 1, 264, 1296, 117), - (483, 1, 264, 540, 58), - (483, 2, 264, 540, 418), - (484, 1, 264, 1080, 58), - (484, 2, 264, 1080, 418), - (485, 1, 264, 1620, 58), - (485, 2, 264, 1620, 418), - (489, 1, 264, 90, 110), - (490, 1, 264, 180, 110), - (491, 1, 264, 270, 110), - (492, 1, 264, 60, 109), - (493, 1, 264, 120, 109), - (494, 1, 264, 180, 109), - (495, 1, 264, 180, 98), - (496, 1, 264, 360, 98), - (497, 1, 264, 540, 98), - (498, 1, 264, 144, 102), - (499, 1, 264, 288, 102), - (500, 1, 264, 432, 102), - (501, 1, 264, 432, 107), - (502, 1, 264, 864, 107), - (503, 1, 264, 1296, 107), - (504, 1, 224, 110, 0), - (505, 1, 224, 120, 0), - (506, 1, 224, 130, 0), - (537, 1, 282, 60, 0), - (538, 1, 282, 75, 0), - (539, 1, 275, 68, 0), - (540, 1, 275, 76, 0), - (541, 1, 275, 84, 0), - (542, 1, 279, 17, 0), - (543, 1, 279, 19, 0), - (544, 1, 279, 21, 0), - (551, 1, 225, 3, 0), - (552, 1, 225, 6, 0), - (553, 1, 225, 9, 0), - (554, 1, 225, 12, 0), - (555, 1, 225, 15, 0), - (556, 1, 225, 3, 0), - (557, 1, 225, 6, 0), - (558, 1, 225, 9, 0), - (559, 1, 225, 12, 0), - (560, 1, 225, 15, 0), - (561, 1, 177, 3, -1), - (562, 1, 177, 6, -1), - (563, 1, 177, 9, -1), - (564, 1, 177, 3, -1), - (565, 1, 177, 6, -1), - (566, 1, 177, 9, -1), - (567, 1, 244, -12, 0), - (574, 1, 281, 25, 0), - (575, 1, 281, 50, 0), - (576, 1, 281, 75, 0), - (577, 1, 277, 20, 0), - (578, 1, 277, 40, 0), - (579, 1, 277, 60, 0), - (580, 1, 267, 1, 4), - (580, 2, 267, 1, 5), - (580, 3, 267, 1, 29), - (581, 1, 267, 1, 2), - (581, 2, 267, 1, 3), - (581, 3, 267, 1, 4), - (581, 4, 267, 1, 5), - (581, 5, 267, 1, 29), - (582, 1, 267, 1, 0), - (582, 2, 267, 1, 1), - (582, 3, 267, 1, 2), - (582, 4, 267, 1, 3), - (582, 5, 267, 1, 4), - (582, 6, 267, 1, 4), - (582, 7, 267, 1, 5), - (582, 8, 267, 1, 6), - (582, 9, 267, 1, 7), - (582, 10, 267, 1, 8), - (582, 11, 267, 1, 9), - (582, 12, 267, 1, 10), - (582, 13, 267, 1, 11), - (582, 14, 267, 1, 12), - (582, 15, 267, 1, 13), - (582, 16, 267, 1, 14), - (582, 17, 267, 1, 28), - (582, 18, 267, 1, 29), - (582, 19, 267, 1, 30), - (583, 1, 264, 7, 73), - (583, 2, 264, 7, 702), - (583, 3, 264, 7, 3826), - (583, 4, 264, 7, 7712), - (584, 1, 264, 14, 73), - (584, 2, 264, 14, 702), - (584, 3, 264, 14, 3826), - (584, 4, 264, 14, 7712), - (585, 1, 264, 21, 73), - (585, 2, 264, 21, 702), - (585, 3, 264, 21, 3826), - (585, 4, 264, 21, 7712), - (586, 1, 255, 12, 0), - (587, 1, 255, 24, 0), - (588, 1, 255, 36, 0), - (589, 1, 303, 500, 500), - (589, 2, 139, 2766, 0), - (590, 1, 303, 1000, 1000), - (590, 2, 139, 2766, 0), - (591, 1, 303, 1500, 1500), - (591, 2, 139, 2766, 0), - (593, 1, 264, 720, 6001), - (593, 2, 264, 720, 3676), - (594, 1, 264, 1440, 6001), - (594, 2, 264, 1440, 3676), - (595, 1, 264, 2160, 6001), - (595, 2, 264, 2160, 3676), - (596, 1, 264, 720, 6000), - (596, 2, 264, 720, 87), - (597, 1, 264, 1440, 6000), - (597, 2, 264, 1440, 87), - (598, 1, 264, 2160, 6000), - (598, 2, 264, 2160, 87), - (599, 1, 266, 2, 0), - (600, 1, 266, 5, 0), - (601, 1, 266, 8, 0), - (602, 1, 266, 2, 0), - (603, 1, 266, 5, 0), - (604, 1, 266, 8, 0), - (605, 1, 256, 1, 0), - (606, 1, 285, 20, 0), - (607, 1, 285, 40, 0), - (608, 1, 285, 60, 0), - (609, 1, 285, 80, 0), - (610, 1, 285, 100, 0), - (611, 1, 283, 20, 0), - (612, 1, 283, 40, 0), - (613, 1, 283, 60, 0), - (614, 1, 283, 80, 0), - (615, 1, 283, 100, 0), - (622, 1, 227, 1, 29), - (622, 2, 227, 1, 42), - (623, 1, 227, 2, 29), - (623, 2, 227, 2, 42), - (624, 1, 227, 3, 29), - (624, 2, 227, 3, 42), - (625, 1, 294, 3, 100), - (626, 1, 294, 6, 100), - (627, 1, 294, 9, 100), - (628, 1, 290, 5, 0), - (629, 1, 290, 10, 0), - (631, 1, 292, 15, 0), - (632, 1, 292, 30, 0), - (633, 1, 292, 45, 0), - (634, 1, 274, 3, 0), - (635, 1, 274, 6, 0), - (636, 1, 274, 10, 0), - (637, 1, 294, 2, 100), - (638, 1, 294, 4, 100), - (639, 1, 294, 6, 100), - (640, 1, 294, 7, 100), - (641, 1, 294, 8, 100), - (642, 1, 294, 9, 100), - (644, 1, 217, 0, 32000), - (644, 2, 346, 59, 0), - (649, 1, 243, 15, 0), - (650, 1, 243, 25, 0), - (651, 1, 243, 35, 0), - (652, 1, 293, 25, 0), - (653, 1, 293, 50, 0), - (654, 1, 293, 75, 0), - (655, 1, 127, 10, 10), - (655, 2, 137, 32, 0), - (655, 3, 127, 10, 10), - (655, 4, 137, 33, 0), - (655, 5, 127, 10, 10), - (655, 6, 137, 82, 0), - (655, 7, 127, 2, 2), - (655, 8, 137, 152, 0), - (655, 9, 143, 3000, 0), - (656, 1, 127, 25, 25), - (656, 2, 137, 32, 0), - (656, 3, 127, 25, 25), - (656, 4, 137, 33, 0), - (656, 5, 127, 25, 25), - (656, 6, 137, 82, 0), - (656, 7, 127, 5, 5), - (656, 8, 137, 152, 0), - (656, 9, 143, 3000, 0), - (657, 1, 127, 50, 50), - (657, 2, 137, 32, 0), - (657, 3, 127, 50, 50), - (657, 4, 137, 33, 0), - (657, 5, 127, 50, 50), - (657, 6, 137, 82, 0), - (657, 7, 127, 10, 10), - (657, 8, 137, 152, 0), - (657, 9, 143, 3000, 0), - (658, 1, 15, 1, 0), - (659, 1, 15, 2, 0), - (660, 1, 15, 3, 0), - (661, 1, 0, 1, 0), - (662, 1, 0, 2, 0), - (663, 1, 0, 3, 0), - (665, 1, 270, 10, 0), - (666, 1, 270, 15, 0), - (667, 1, 270, 25, 0), - (668, 1, 270, 55, 0), - (669, 1, 270, 60, 0), - (670, 1, 270, 65, 0), - (671, 1, 241, 95, 0), - (672, 1, 271, 28, 0), - (673, 1, 271, 35, 0), - (674, 1, 0, 4, 0), - (675, 1, 0, 5, 0), - (676, 1, 246, 325, 0), - (677, 1, 246, 350, 0), - (678, 1, 221, 3, 0), - (679, 1, 221, 6, 0), - (680, 1, 221, 9, 0), - (681, 1, 221, 12, 0), - (682, 1, 221, 15, 0), - (683, 1, 189, 1, 0), - (684, 1, 189, 2, 0), - (685, 1, 189, 3, 0), - (686, 1, 200, 10, 0), - (687, 1, 200, 20, 0), - (688, 1, 200, 30, 0), - (689, 1, 200, 40, 0), - (690, 1, 200, 50, 0), - (691, 1, 248, 100, 0), - (692, 1, 229, 5, 0), - (693, 1, 229, 10, 0), - (694, 1, 229, 15, 0), - (695, 1, 247, 10, 53), - (696, 1, 247, 20, 53), - (697, 1, 247, 30, 53), - (698, 1, 247, 40, 53), - (699, 1, 247, 50, 53), - (700, 1, 260, 8, 23), - (700, 2, 260, 8, 24), - (700, 3, 260, 8, 25), - (700, 4, 260, 8, 26), - (701, 1, 260, 8, 50), - (724, 1, 218, 1, 0), - (725, 1, 218, 2, 0), - (726, 1, 218, 3, 0), - (727, 1, 218, 4, 0), - (728, 1, 218, 5, 0), - (729, 1, 280, 4, 0), - (730, 1, 280, 8, 0), - (731, 1, 280, 12, 0), - (732, 1, 280, 16, 0), - (733, 1, 280, 20, 0), - (734, 1, 237, 1, 0), - (735, 1, 265, 54, 0), - (736, 1, 265, 56, 0), - (737, 1, 265, 58, 0), - (738, 1, 114, -5, 0), - (739, 1, 114, -10, 0), - (740, 1, 114, -20, 0), - (754, 1, 264, 18, 153), - (755, 1, 264, 36, 153), - (756, 1, 264, 54, 153), - (762, 1, 247, 10, 53), - (763, 1, 247, 20, 53), - (764, 1, 247, 30, 53), - (765, 1, 247, 40, 53), - (766, 1, 247, 50, 53), - (767, 1, 273, 3, 0), - (768, 1, 273, 6, 0), - (769, 1, 273, 9, 0), - (770, 1, 294, 7, 100), - (771, 1, 294, 8, 100), - (772, 1, 294, 9, 100), - (776, 1, 242, 10, 0), - (777, 1, 242, 20, 0), - (778, 1, 242, 30, 0), - (779, 1, 242, 40, 0), - (780, 1, 242, 50, 0), - (781, 1, 287, 1, 1), - (781, 2, 137, 31, 0), - (781, 3, 136, 5, 0), - (782, 1, 264, 432, 35), - (783, 1, 264, 864, 35), - (784, 1, 264, 1296, 35), - (790, 1, 218, 1, 0), - (791, 1, 218, 2, 0), - (792, 1, 218, 3, 0), - (793, 1, 218, 4, 0), - (794, 1, 218, 5, 0), - (795, 1, 280, 4, 0), - (796, 1, 280, 8, 0), - (797, 1, 280, 12, 0), - (798, 1, 280, 16, 0), - (799, 1, 280, 20, 0), - (800, 1, 215, 2, 0), - (801, 1, 215, 5, 0), - (802, 1, 215, 10, 0), - (803, 1, 213, 2, 0), - (804, 1, 213, 5, 0), - (805, 1, 213, 10, 0), - (806, 1, 249, 1, 0), - (807, 1, 292, 5, 0), - (808, 1, 292, 10, 0), - (809, 1, 292, 15, 0), - (810, 1, 239, 10, 0), - (811, 1, 239, 20, 0), - (812, 1, 239, 30, 0), - (813, 1, 239, 40, 0), - (814, 1, 239, 50, 0), - (815, 1, 279, 7, 0), - (816, 1, 279, 11, 0), - (817, 1, 279, 15, 0), - (818, 1, 279, 17, 0), - (819, 1, 279, 19, 0), - (820, 1, 220, 10, 26), - (820, 2, 220, 10, 30), - (820, 3, 220, 10, 38), - (821, 1, 220, 20, 26), - (821, 2, 220, 20, 30), - (821, 3, 220, 20, 38), - (822, 1, 220, 30, 26), - (822, 2, 220, 30, 30), - (822, 3, 220, 30, 38), - (823, 1, 222, 20, 0), - (824, 1, 222, 40, 0), - (825, 1, 222, 60, 0), - (826, 1, 222, 80, 0), - (827, 1, 222, 100, 0), - (834, 1, 218, 1, 0), - (835, 1, 218, 2, 0), - (836, 1, 218, 3, 0), - (837, 1, 218, 4, 0), - (838, 1, 218, 5, 0), - (839, 1, 280, 4, 0), - (840, 1, 280, 8, 0), - (841, 1, 280, 12, 0), - (842, 1, 280, 16, 0), - (843, 1, 280, 20, 0), - (844, 1, 274, 12, 0), - (845, 1, 274, 14, 0), - (846, 1, 258, 5, 0), - (847, 1, 258, 10, 0), - (848, 1, 258, 15, 0), - (849, 1, 264, 240, 180), - (850, 1, 264, 480, 180), - (851, 1, 264, 720, 180), - (852, 1, 231, 1, 0), - (853, 1, 231, 2, 0), - (854, 1, 231, 3, 0), - (855, 1, 220, 5, 10), - (856, 1, 220, 10, 10), - (857, 1, 220, 15, 10), - (858, 1, 220, 20, 10), - (859, 1, 220, 25, 10), - (864, 1, 216, 10, 0), - (864, 2, 216, 10, 1), - (864, 3, 216, 10, 2), - (864, 4, 216, 10, 3), - (864, 5, 216, 10, 10), - (864, 6, 216, 10, 28), - (864, 7, 216, 10, 30), - (864, 8, 216, 10, 36), - (864, 9, 216, 10, 77), - (865, 1, 216, 20, 0), - (865, 2, 216, 20, 1), - (865, 3, 216, 20, 2), - (865, 4, 216, 20, 3), - (865, 5, 216, 20, 10), - (865, 6, 216, 20, 28), - (865, 7, 216, 20, 30), - (865, 8, 216, 20, 36), - (865, 9, 216, 20, 77), - (866, 1, 216, 30, 0), - (866, 2, 216, 30, 1), - (866, 3, 216, 30, 2), - (866, 4, 216, 30, 3), - (866, 5, 216, 30, 10), - (866, 6, 216, 30, 28), - (866, 7, 216, 30, 30), - (866, 8, 216, 30, 36), - (866, 9, 216, 30, 77), - (867, 1, 59, -3, 0), - (868, 1, 59, -6, 0), - (869, 1, 59, -9, 0), - (870, 1, 59, -12, 0), - (871, 1, 59, -15, 0), - (878, 1, 252, 10, 0), - (879, 1, 252, 20, 0), - (880, 1, 252, 30, 0), - (881, 1, 245, 10, 0), - (882, 1, 245, 20, 0), - (883, 1, 245, 30, 0), - (884, 1, 245, 40, 0), - (885, 1, 245, 50, 0), - (886, 1, 264, 576, 102), - (887, 1, 264, 720, 102), - (888, 1, 250, 10, 0), - (889, 1, 250, 20, 0), - (890, 1, 250, 30, 0), - (891, 1, 250, 40, 0), - (892, 1, 250, 50, 0), - (893, 1, 303, 2000, 2000), - (893, 2, 139, 2766, 0), - (894, 1, 303, 2500, 2500), - (894, 2, 139, 2766, 0), - (895, 1, 59, -3, 0), - (896, 1, 59, -6, 0), - (897, 1, 59, -9, 0), - (898, 1, 59, -12, 0), - (899, 1, 59, -15, 0), - (907, 1, 69, 100, 0), - (908, 1, 69, 200, 0), - (909, 1, 69, 300, 0), - (910, 1, 69, 400, 0), - (911, 1, 69, 500, 0), - (915, 1, 220, 5, 10), - (915, 2, 220, 5, 30), - (916, 1, 220, 10, 10), - (916, 2, 220, 10, 30), - (917, 1, 220, 15, 10), - (917, 2, 220, 15, 30), - (918, 1, 230, 2, 0), - (919, 1, 230, 4, 0), - (920, 1, 230, 6, 0), - (924, 1, 294, 10, 100), - (925, 1, 294, 11, 100), - (934, 1, 169, 15, -1), - (935, 1, 169, 30, -1), - (936, 1, 169, 60, -1), - (937, 1, 169, 15, 0), - (937, 2, 169, 15, 1), - (937, 3, 169, 15, 2), - (937, 4, 169, 15, 3), - (937, 5, 169, 15, 7), - (937, 6, 169, 15, 8), - (937, 7, 169, 15, 10), - (937, 8, 169, 15, 28), - (937, 9, 169, 15, 30), - (937, 10, 169, 15, 36), - (937, 11, 169, 15, 51), - (938, 1, 169, 40, 0), - (938, 2, 169, 40, 1), - (938, 3, 169, 40, 2), - (938, 4, 169, 40, 3), - (938, 5, 169, 40, 7), - (938, 6, 169, 40, 8), - (938, 7, 169, 40, 10), - (938, 8, 169, 40, 28), - (938, 9, 169, 40, 30), - (938, 10, 169, 40, 36), - (938, 11, 169, 30, 51), - (939, 1, 169, 75, 0), - (939, 2, 169, 75, 1), - (939, 3, 169, 75, 2), - (939, 4, 169, 75, 3), - (939, 5, 169, 75, 7), - (939, 6, 169, 75, 8), - (939, 7, 169, 75, 10), - (939, 8, 169, 75, 28), - (939, 9, 169, 75, 30), - (939, 10, 169, 75, 36), - (939, 11, 169, 60, 51), - (940, 1, 169, 15, 0), - (940, 2, 169, 15, 1), - (940, 3, 169, 15, 2), - (940, 4, 169, 15, 3), - (940, 5, 169, 15, 7), - (940, 6, 169, 15, 8), - (940, 7, 169, 15, 10), - (940, 8, 169, 15, 28), - (940, 9, 169, 15, 30), - (940, 10, 169, 15, 36), - (940, 11, 169, 15, 51), - (940, 12, 169, 15, 77), - (941, 1, 169, 40, 0), - (941, 2, 169, 40, 1), - (941, 3, 169, 40, 2), - (941, 4, 169, 40, 3), - (941, 5, 169, 30, 7), - (941, 6, 169, 40, 8), - (941, 7, 169, 40, 10), - (941, 8, 169, 40, 28), - (941, 9, 169, 40, 30), - (941, 10, 169, 40, 36), - (941, 11, 169, 40, 51), - (941, 12, 169, 40, 77), - (942, 1, 169, 75, 0), - (942, 2, 169, 75, 1), - (942, 3, 169, 75, 2), - (942, 4, 169, 75, 3), - (942, 5, 169, 60, 7), - (942, 6, 169, 75, 8), - (942, 7, 169, 75, 10), - (942, 8, 169, 75, 28), - (942, 9, 169, 75, 30), - (942, 10, 169, 75, 36), - (942, 11, 169, 75, 51), - (942, 12, 169, 75, 77), - (943, 1, 169, 146, -1), - (944, 1, 169, 172, -1), - (945, 1, 169, 198, -1), - (946, 1, 169, 175, 0), - (946, 2, 169, 175, 1), - (946, 3, 169, 175, 2), - (946, 4, 169, 175, 3), - (946, 5, 169, 175, 7), - (946, 6, 169, 175, 8), - (946, 7, 169, 175, 10), - (946, 8, 169, 175, 28), - (946, 9, 169, 175, 30), - (946, 10, 169, 175, 36), - (946, 11, 169, 146, 51), - (947, 1, 169, 200, 0), - (947, 2, 169, 200, 1), - (947, 3, 169, 200, 2), - (947, 4, 169, 200, 3), - (947, 5, 169, 200, 7), - (947, 6, 169, 200, 8), - (947, 7, 169, 200, 10), - (947, 8, 169, 200, 28), - (947, 9, 169, 200, 30), - (947, 10, 169, 200, 36), - (947, 11, 169, 172, 51), - (948, 1, 169, 225, 0), - (948, 2, 169, 225, 1), - (948, 3, 169, 225, 2), - (948, 4, 169, 225, 3), - (948, 5, 169, 225, 7), - (948, 6, 169, 225, 8), - (948, 7, 169, 225, 10), - (948, 8, 169, 225, 28), - (948, 9, 169, 225, 30), - (948, 10, 169, 225, 36), - (948, 11, 169, 198, 51), - (949, 1, 169, 175, 0), - (949, 2, 169, 175, 1), - (949, 3, 169, 175, 2), - (949, 4, 169, 175, 3), - (949, 5, 169, 161, 7), - (949, 6, 169, 175, 8), - (949, 7, 169, 175, 10), - (949, 8, 169, 175, 28), - (949, 9, 169, 175, 30), - (949, 10, 169, 175, 36), - (949, 11, 169, 175, 51), - (949, 12, 169, 175, 77), - (950, 1, 169, 200, 0), - (950, 2, 169, 200, 1), - (950, 3, 169, 200, 2), - (950, 4, 169, 200, 3), - (950, 5, 169, 187, 7), - (950, 6, 169, 200, 8), - (950, 7, 169, 200, 10), - (950, 8, 169, 200, 28), - (950, 9, 169, 200, 30), - (950, 10, 169, 200, 36), - (950, 11, 169, 200, 51), - (950, 12, 169, 200, 77), - (951, 1, 169, 225, 0), - (951, 2, 169, 225, 1), - (951, 3, 169, 225, 2), - (951, 4, 169, 225, 3), - (951, 5, 169, 213, 7), - (951, 6, 169, 225, 8), - (951, 7, 169, 225, 10), - (951, 8, 169, 225, 28), - (951, 9, 169, 225, 30), - (951, 10, 169, 225, 36), - (951, 11, 169, 225, 51), - (951, 12, 169, 225, 77), - (952, 1, 214, 125, 0), - (953, 1, 214, 250, 0), - (954, 1, 214, 375, 0), - (955, 1, 262, 10, 4), - (955, 2, 262, 10, 5), - (956, 1, 262, 20, 4), - (956, 2, 262, 20, 5), - (957, 1, 262, 30, 4), - (957, 2, 262, 30, 5), - (958, 1, 262, 40, 4), - (958, 2, 262, 40, 5), - (959, 1, 262, 50, 4), - (959, 2, 262, 50, 5), - (962, 1, 232, 2, 4544), - (963, 1, 232, 4, 4544), - (964, 1, 232, 6, 4544), - (965, 1, 232, 8, 4544), - (966, 1, 232, 10, 4544), - (975, 1, 264, 864, 102), - (976, 1, 131, 100, 0), - (976, 2, 137, 33, 0), - (978, 1, 14, 1, 0), - (978, 2, 246, 350, 0), - (979, 1, 268, 10, 63), - (980, 1, 268, 25, 63), - (981, 1, 268, 50, 63), - (982, 1, 268, 10, 60), - (983, 1, 268, 25, 60), - (984, 1, 268, 50, 60), - (985, 1, 268, 10, 65), - (986, 1, 268, 25, 65), - (987, 1, 268, 50, 65), - (988, 1, 268, 10, 64), - (989, 1, 268, 25, 64), - (990, 1, 268, 50, 64), - (991, 1, 268, 10, 69), - (992, 1, 268, 25, 69), - (993, 1, 268, 50, 69), - (994, 1, 268, 10, 61), - (995, 1, 268, 25, 61), - (996, 1, 268, 50, 61), - (997, 1, 331, 5, 0), - (998, 1, 331, 15, 0), - (999, 1, 331, 25, 0), - (1001, 1, 262, 30, 0), - (1001, 2, 262, 30, 1), - (1001, 3, 262, 30, 2), - (1001, 4, 262, 30, 3), - (1001, 5, 262, 30, 4), - (1001, 6, 262, 30, 5), - (1001, 7, 262, 30, 6), - (1002, 1, 262, 35, 0), - (1002, 2, 262, 35, 1), - (1002, 3, 262, 35, 2), - (1002, 4, 262, 35, 3), - (1002, 5, 262, 35, 4), - (1002, 6, 262, 35, 5), - (1002, 7, 262, 35, 6), - (1003, 1, 262, 40, 0), - (1003, 2, 262, 40, 1), - (1003, 3, 262, 40, 2), - (1003, 4, 262, 40, 3), - (1003, 5, 262, 40, 4), - (1003, 6, 262, 40, 5), - (1003, 7, 262, 40, 6), - (1004, 1, 262, 45, 0), - (1004, 2, 262, 45, 1), - (1004, 3, 262, 45, 2), - (1004, 4, 262, 45, 3), - (1004, 5, 262, 45, 4), - (1004, 6, 262, 45, 5), - (1004, 7, 262, 45, 6), - (1005, 1, 262, 50, 0), - (1005, 2, 262, 50, 1), - (1005, 3, 262, 50, 2), - (1005, 4, 262, 50, 3), - (1005, 5, 262, 50, 4), - (1005, 6, 262, 50, 5), - (1005, 7, 262, 50, 6), - (1006, 1, 262, 5, 7), - (1006, 2, 262, 5, 8), - (1006, 3, 262, 5, 9), - (1006, 4, 262, 5, 10), - (1006, 5, 262, 5, 11), - (1007, 1, 262, 10, 7), - (1007, 2, 262, 10, 8), - (1007, 3, 262, 10, 9), - (1007, 4, 262, 10, 10), - (1007, 5, 262, 10, 11), - (1008, 1, 262, 15, 7), - (1008, 2, 262, 15, 8), - (1008, 3, 262, 15, 9), - (1008, 4, 262, 15, 10), - (1008, 5, 262, 15, 11), - (1009, 1, 262, 20, 7), - (1009, 2, 262, 20, 8), - (1009, 3, 262, 20, 9), - (1009, 4, 262, 20, 10), - (1009, 5, 262, 20, 11), - (1010, 1, 262, 25, 7), - (1010, 2, 262, 25, 8), - (1010, 3, 262, 25, 9), - (1010, 4, 262, 25, 10), - (1010, 5, 262, 25, 11), - (1011, 1, 262, 8, 7), - (1011, 2, 262, 8, 8), - (1011, 3, 262, 8, 9), - (1011, 4, 262, 8, 10), - (1011, 5, 262, 8, 11), - (1012, 1, 262, 16, 7), - (1012, 2, 262, 16, 8), - (1012, 3, 262, 16, 9), - (1012, 4, 262, 16, 10), - (1012, 5, 262, 16, 11), - (1013, 1, 262, 24, 7), - (1013, 2, 262, 24, 8), - (1013, 3, 262, 24, 9), - (1013, 4, 262, 24, 10), - (1013, 5, 262, 24, 11), - (1014, 1, 262, 32, 7), - (1014, 2, 262, 32, 8), - (1014, 3, 262, 32, 9), - (1014, 4, 262, 32, 10), - (1014, 5, 262, 32, 11), - (1015, 1, 262, 40, 7), - (1015, 2, 262, 40, 8), - (1015, 3, 262, 40, 9), - (1015, 4, 262, 40, 10), - (1015, 5, 262, 40, 11), - (1016, 1, 262, 50, 7), - (1016, 2, 262, 50, 8), - (1016, 3, 262, 50, 9), - (1016, 4, 262, 50, 10), - (1016, 5, 262, 50, 11), - (1021, 1, 327, 1, 0), - (1022, 1, 327, 2, 0), - (1023, 1, 327, 3, 0), - (1024, 1, 327, 4, 0), - (1025, 1, 327, 5, 0), - (1026, 1, 328, 50, 0), - (1027, 1, 328, 100, 0), - (1028, 1, 328, 150, 0), - (1029, 1, 328, 200, 0), - (1030, 1, 328, 250, 0), - (1031, 1, 0, 6, 0), - (1032, 1, 0, 7, 0), - (1033, 1, 0, 8, 0), - (1034, 1, 0, 9, 0), - (1035, 1, 0, 10, 0), - (1036, 1, 189, 4, 0), - (1037, 1, 189, 5, 0), - (1038, 1, 189, 6, 0), - (1041, 1, 330, 25, 0), - (1041, 2, 330, 25, 1), - (1041, 3, 330, 25, 2), - (1041, 4, 330, 25, 3), - (1041, 5, 330, 25, 28), - (1041, 6, 330, 25, 36), - (1041, 7, 330, 25, 77), - (1042, 1, 330, 50, 0), - (1042, 2, 330, 50, 1), - (1042, 3, 330, 50, 2), - (1042, 4, 330, 50, 3), - (1042, 5, 330, 50, 28), - (1042, 6, 330, 50, 36), - (1042, 7, 330, 50, 77), - (1043, 1, 330, 75, 0), - (1043, 2, 330, 75, 1), - (1043, 3, 330, 75, 2), - (1043, 4, 330, 75, 3), - (1043, 5, 330, 75, 28), - (1043, 6, 330, 75, 36), - (1043, 7, 330, 75, 77), - (1044, 1, 330, 25, 0), - (1044, 2, 330, 25, 1), - (1044, 3, 330, 25, 2), - (1044, 4, 330, 25, 3), - (1044, 5, 330, 25, 28), - (1044, 6, 330, 25, 36), - (1045, 1, 330, 50, 0), - (1045, 2, 330, 50, 1), - (1045, 3, 330, 50, 2), - (1045, 4, 330, 50, 3), - (1045, 5, 330, 50, 28), - (1045, 6, 330, 50, 36), - (1046, 1, 330, 75, 0), - (1046, 2, 330, 75, 1), - (1046, 3, 330, 75, 2), - (1046, 4, 330, 75, 3), - (1046, 5, 330, 75, 28), - (1046, 6, 330, 75, 36), - (1047, 1, 330, 25, 0), - (1047, 2, 330, 25, 1), - (1047, 3, 330, 25, 2), - (1047, 4, 330, 25, 3), - (1047, 5, 330, 25, 28), - (1047, 6, 330, 25, 36), - (1047, 7, 330, 25, 77), - (1048, 1, 330, 50, 0), - (1048, 2, 330, 50, 1), - (1048, 3, 330, 50, 2), - (1048, 4, 330, 50, 3), - (1048, 5, 330, 50, 28), - (1048, 6, 330, 50, 36), - (1048, 7, 330, 50, 77), - (1049, 1, 330, 75, 0), - (1049, 2, 330, 75, 1), - (1049, 3, 330, 75, 2), - (1049, 4, 330, 75, 3), - (1049, 5, 330, 75, 28), - (1049, 6, 330, 75, 36), - (1049, 7, 330, 75, 77), - (1050, 1, 330, 15, 0), - (1050, 2, 330, 15, 1), - (1050, 3, 330, 15, 2), - (1050, 4, 330, 15, 3), - (1050, 5, 330, 15, 28), - (1050, 6, 330, 15, 36), - (1050, 7, 330, 15, 77), - (1051, 1, 330, 30, 0), - (1051, 2, 330, 30, 1), - (1051, 3, 330, 30, 2), - (1051, 4, 330, 30, 3), - (1051, 5, 330, 30, 28), - (1051, 6, 330, 30, 36), - (1051, 7, 330, 30, 77), - (1052, 1, 330, 50, 0), - (1052, 2, 330, 50, 1), - (1052, 3, 330, 50, 2), - (1052, 4, 330, 50, 3), - (1052, 5, 330, 50, 28), - (1052, 6, 330, 50, 36), - (1052, 7, 330, 50, 77), - (1053, 1, 278, 560, 27200), - (1053, 2, 440, 61, 100), - (1054, 1, 278, 580, 30135), - (1054, 2, 440, 63, 100), - (1055, 1, 278, 600, 32780), - (1055, 2, 440, 65, 100), - (1056, 1, 317, 1, 0), - (1057, 1, 317, 2, 0), - (1058, 1, 317, 3, 0), - (1059, 1, 317, 4, 0), - (1060, 1, 317, 5, 0), - (1061, 1, 172, 26, 0), - (1062, 1, 172, 27, 0), - (1063, 1, 172, 28, 0), - (1064, 1, 172, 30, 0), - (1065, 1, 172, 32, 0), - (1066, 1, 259, 27, 0), - (1067, 1, 259, 29, 0), - (1068, 1, 259, 31, 0), - (1069, 1, 259, 33, 0), - (1070, 1, 259, 35, 0), - (1071, 1, 326, 1, 0), - (1072, 1, 318, 1, 0), - (1073, 1, 318, 2, 0), - (1074, 1, 318, 3, 0), - (1075, 1, 318, 4, 0), - (1076, 1, 318, 5, 0), - (1083, 1, 125, 22, 22), - (1083, 2, 137, 0, 0), - (1083, 3, 141, 1, 0), - (1083, 4, 139, -6233, 0), - (1083, 5, 139, -6265, 0), - (1083, 6, 125, 22, 22), - (1083, 7, 137, 147, 0), - (1083, 8, 141, 1, 0), - (1084, 1, 125, 25, 25), - (1084, 2, 137, 0, 0), - (1084, 3, 141, 1, 0), - (1084, 4, 139, -6233, 0), - (1084, 5, 139, -6265, 0), - (1084, 6, 125, 25, 25), - (1084, 7, 137, 147, 0), - (1084, 8, 141, 1, 0), - (1085, 1, 125, 28, 28), - (1085, 2, 137, 0, 0), - (1085, 3, 141, 1, 0), - (1085, 4, 139, -6233, 0), - (1085, 5, 139, -6265, 0), - (1085, 6, 125, 28, 28), - (1085, 7, 137, 147, 0), - (1085, 8, 141, 1, 0), - (1086, 1, 274, 18, 0), - (1087, 1, 274, 20, 0), - (1088, 1, 274, 22, 0), - (1089, 1, 268, 10, 58), - (1090, 1, 268, 25, 58), - (1091, 1, 268, 50, 58), - (1092, 1, 238, 1, 0), - (1093, 1, 304, -20, 0), - (1094, 1, 304, -40, 0), - (1095, 1, 304, -60, 0), - (1096, 1, 304, -80, 0), - (1097, 1, 304, -100, 0), - (1099, 1, 273, 12, 0), - (1100, 1, 273, 15, 0), - (1101, 1, 273, 18, 0), - (1107, 1, 294, 2, 100), - (1108, 1, 294, 4, 100), - (1109, 1, 294, 6, 100), - (1113, 1, 331, 30, 0), - (1114, 1, 331, 35, 0), - (1115, 1, 331, 40, 0), - (1122, 1, 308, 1, 0), - (1129, 1, 267, 1, 24), - (1129, 2, 267, 1, 25), - (1129, 3, 267, 1, 26), - (1130, 1, 267, 1, 18), - (1130, 2, 267, 1, 19), - (1130, 3, 267, 1, 20), - (1130, 4, 267, 1, 21), - (1130, 5, 267, 1, 22), - (1130, 6, 267, 1, 23), - (1130, 7, 267, 1, 24), - (1130, 8, 267, 1, 25), - (1130, 9, 267, 1, 26), - (1131, 1, 185, 10, 51), - (1132, 1, 185, 20, 51), - (1133, 1, 185, 30, 51), - (1134, 1, 220, 32, 74), - (1135, 1, 220, 64, 74), - (1136, 1, 220, 96, 74), - (1137, 1, 310, 180000, 0), - (1137, 2, 139, 5027, 0), - (1137, 3, 310, 180000, 0), - (1137, 4, 139, 5028, 0), - (1137, 5, 310, 180000, 0), - (1137, 6, 139, 5029, 0), - (1137, 7, 310, 180000, 0), - (1137, 8, 139, 5030, 0), - (1137, 9, 310, 180000, 0), - (1137, 10, 139, 5031, 0), - (1137, 11, 310, 180000, 0), - (1137, 12, 139, 5032, 0), - (1137, 13, 310, 180000, 0), - (1137, 14, 139, 8476, 0), - (1138, 1, 310, 360000, 0), - (1138, 2, 139, 5027, 0), - (1138, 3, 310, 360000, 0), - (1138, 4, 139, 5028, 0), - (1138, 5, 310, 360000, 0), - (1138, 6, 139, 5029, 0), - (1138, 7, 310, 360000, 0), - (1138, 8, 139, 5030, 0), - (1138, 9, 310, 360000, 0), - (1138, 10, 139, 5031, 0), - (1138, 11, 310, 360000, 0), - (1138, 12, 139, 5032, 0), - (1138, 13, 310, 360000, 0), - (1138, 14, 139, 8476, 0), - (1139, 1, 310, 540000, 0), - (1139, 2, 139, 5027, 0), - (1139, 3, 310, 540000, 0), - (1139, 4, 139, 5028, 0), - (1139, 5, 310, 540000, 0), - (1139, 6, 139, 5029, 0), - (1139, 7, 310, 540000, 0), - (1139, 8, 139, 5030, 0), - (1139, 9, 310, 540000, 0), - (1139, 10, 139, 5031, 0), - (1139, 11, 310, 540000, 0), - (1139, 12, 139, 5032, 0), - (1139, 13, 310, 540000, 0), - (1139, 14, 139, 8476, 0), - (1140, 1, 216, 10, 51), - (1141, 1, 216, 20, 51), - (1142, 1, 216, 30, 51), - (1155, 1, 128, 25, 0), - (1155, 2, 139, 5027, 0), - (1155, 3, 128, 25, 0), - (1155, 4, 139, 5028, 0), - (1155, 5, 128, 25, 0), - (1155, 6, 139, 5029, 0), - (1155, 7, 128, 25, 0), - (1155, 8, 139, 5030, 0), - (1155, 9, 128, 25, 0), - (1155, 10, 139, 5031, 0), - (1155, 11, 128, 25, 0), - (1155, 12, 139, 5032, 0), - (1155, 13, 128, 25, 0), - (1155, 14, 139, 8476, 0), - (1156, 1, 128, 50, 0), - (1156, 2, 139, 5027, 0), - (1156, 3, 128, 50, 0), - (1156, 4, 139, 5028, 0), - (1156, 5, 128, 50, 0), - (1156, 6, 139, 5029, 0), - (1156, 7, 128, 50, 0), - (1156, 8, 139, 5030, 0), - (1156, 9, 128, 50, 0), - (1156, 10, 139, 5031, 0), - (1156, 11, 128, 50, 0), - (1156, 12, 139, 5032, 0), - (1156, 13, 128, 50, 0), - (1156, 14, 139, 8476, 0), - (1157, 1, 128, 100, 0), - (1157, 2, 139, 5027, 0), - (1157, 3, 128, 100, 0), - (1157, 4, 139, 5028, 0), - (1157, 5, 128, 100, 0), - (1157, 6, 139, 5029, 0), - (1157, 7, 128, 100, 0), - (1157, 8, 139, 5030, 0), - (1157, 9, 128, 100, 0), - (1157, 10, 139, 5031, 0), - (1157, 11, 128, 100, 0), - (1157, 12, 139, 5032, 0), - (1157, 13, 128, 100, 0), - (1157, 14, 139, 8476, 0), - (1158, 1, 220, 128, 74), - (1159, 1, 220, 160, 74), - (1160, 1, 220, 192, 74), - (1161, 1, 220, 224, 74), - (1162, 1, 220, 256, 74), - (1163, 1, 279, 23, 0), - (1164, 1, 279, 25, 0), - (1165, 1, 279, 27, 0), - (1166, 1, 224, 20, 74), - (1166, 2, 173, 1, 0), - (1167, 1, 224, 35, 74), - (1167, 2, 173, 1, 0), - (1168, 1, 224, 50, 74), - (1168, 2, 173, 2, 0), - (1172, 1, 292, 50, 0), - (1173, 1, 292, 55, 0), - (1174, 1, 292, 60, 0), - (1181, 1, 305, -20, 0), - (1182, 1, 305, -40, 0), - (1183, 1, 305, -60, 0), - (1184, 1, 305, -80, 0), - (1185, 1, 305, -100, 0), - (1186, 1, 319, 3, 0), - (1187, 1, 319, 6, 0), - (1188, 1, 319, 10, 0), - (1196, 1, 220, 20, 7), - (1197, 1, 220, 40, 7), - (1198, 1, 220, 60, 7), - (1199, 1, 220, 80, 7), - (1200, 1, 220, 100, 7), - (1210, 1, 294, 0, 107), - (1211, 1, 294, 0, 115), - (1212, 1, 294, 0, 125), - (1213, 1, 294, 0, 107), - (1214, 1, 294, 0, 115), - (1215, 1, 294, 0, 125), - (1216, 1, 132, 2, 2), - (1217, 1, 132, 5, 5), - (1218, 1, 132, 10, 10), - (1219, 1, 339, 3, 8105), - (1219, 2, 142, 65, 0), - (1219, 3, 311, 0, 0), - (1219, 4, 134, 70, 0), - (1219, 5, 348, 10, 0), - (1219, 6, 137, 0, 0), - (1219, 7, 339, 3, 8105), - (1219, 8, 142, 65, 0), - (1219, 9, 311, 0, 0), - (1219, 10, 134, 70, 0), - (1219, 11, 348, 10, 0), - (1219, 12, 137, 100, 0), - (1219, 13, 339, 3, 8105), - (1219, 14, 142, 65, 0), - (1219, 15, 311, 0, 0), - (1219, 16, 134, 70, 0), - (1219, 17, 348, 10, 0), - (1219, 18, 137, 79, 0), - (1219, 19, 339, 3, 8105), - (1219, 20, 142, 65, 0), - (1219, 21, 311, 0, 0), - (1219, 22, 134, 70, 0), - (1219, 23, 348, 10, 0), - (1219, 24, 137, 147, 0), - (1220, 1, 339, 6, 8105), - (1220, 2, 142, 65, 0), - (1220, 3, 311, 0, 0), - (1220, 4, 134, 70, 0), - (1220, 5, 348, 10, 0), - (1220, 6, 137, 0, 0), - (1220, 7, 339, 6, 8105), - (1220, 8, 142, 65, 0), - (1220, 9, 311, 0, 0), - (1220, 10, 134, 70, 0), - (1220, 11, 348, 10, 0), - (1220, 12, 137, 100, 0), - (1220, 13, 339, 6, 8105), - (1220, 14, 142, 65, 0), - (1220, 15, 311, 0, 0), - (1220, 16, 134, 70, 0), - (1220, 17, 348, 10, 0), - (1220, 18, 137, 79, 0), - (1220, 19, 339, 6, 8105), - (1220, 20, 142, 65, 0), - (1220, 21, 311, 0, 0), - (1220, 22, 134, 70, 0), - (1220, 23, 348, 10, 0), - (1220, 24, 137, 147, 0), - (1221, 1, 339, 10, 8105), - (1221, 2, 142, 65, 0), - (1221, 3, 311, 0, 0), - (1221, 4, 134, 70, 0), - (1221, 5, 348, 10, 0), - (1221, 6, 137, 0, 0), - (1221, 7, 339, 10, 8105), - (1221, 8, 142, 65, 0), - (1221, 9, 311, 0, 0), - (1221, 10, 134, 70, 0), - (1221, 11, 348, 10, 0), - (1221, 12, 137, 100, 0), - (1221, 13, 339, 10, 8105), - (1221, 14, 142, 65, 0), - (1221, 15, 311, 0, 0), - (1221, 16, 134, 70, 0), - (1221, 17, 348, 10, 0), - (1221, 18, 137, 79, 0), - (1221, 19, 339, 10, 8105), - (1221, 20, 142, 65, 0), - (1221, 21, 311, 0, 0), - (1221, 22, 134, 70, 0), - (1221, 23, 348, 10, 0), - (1221, 24, 137, 147, 0), - (1230, 1, 313, 25, 0), - (1231, 1, 313, 50, 0), - (1232, 1, 313, 75, 0), - (1265, 1, 220, 40, 26), - (1265, 2, 220, 40, 30), - (1265, 3, 220, 40, 38), - (1266, 1, 220, 50, 26), - (1266, 2, 220, 50, 30), - (1266, 3, 220, 50, 38), - (1267, 1, 220, 60, 26), - (1267, 2, 220, 60, 30), - (1267, 3, 220, 60, 38), - (1268, 1, 292, 20, 0), - (1269, 1, 292, 25, 0), - (1270, 1, 292, 30, 0), - (1284, 1, 293, 15, 0), - (1285, 1, 293, 30, 0), - (1286, 1, 293, 50, 0), - (1287, 1, 320, 1, 0), - (1288, 1, 320, 3, 0), - (1289, 1, 320, 5, 0), - (1290, 1, 216, 40, 0), - (1290, 2, 216, 40, 1), - (1290, 3, 216, 40, 2), - (1290, 4, 216, 40, 3), - (1290, 5, 216, 40, 10), - (1290, 6, 216, 40, 28), - (1290, 7, 216, 40, 30), - (1290, 8, 216, 40, 36), - (1290, 9, 216, 40, 77), - (1291, 1, 216, 50, 0), - (1291, 2, 216, 50, 1), - (1291, 3, 216, 50, 2), - (1291, 4, 216, 50, 3), - (1291, 5, 216, 50, 10), - (1291, 6, 216, 50, 28), - (1291, 7, 216, 50, 30), - (1291, 8, 216, 50, 36), - (1291, 9, 216, 50, 77), - (1292, 1, 216, 60, 0), - (1292, 2, 216, 60, 1), - (1292, 3, 216, 60, 2), - (1292, 4, 216, 60, 3), - (1292, 5, 216, 60, 10), - (1292, 6, 216, 60, 28), - (1292, 7, 216, 60, 30), - (1292, 8, 216, 60, 36), - (1292, 9, 216, 60, 77), - (1296, 1, 247, 20, 53), - (1297, 1, 247, 40, 53), - (1298, 1, 247, 60, 53), - (1299, 1, 247, 80, 53), - (1300, 1, 247, 100, 53), - (1301, 1, 258, 20, 0), - (1302, 1, 258, 25, 0), - (1303, 1, 258, 30, 0), - (1304, 1, 216, 50, 8), - (1305, 1, 216, 100, 8), - (1306, 1, 216, 150, 8), - (1307, 1, 325, 10, 0), - (1308, 1, 325, 20, 0), - (1309, 1, 325, 30, 0), - (1310, 1, 325, 40, 0), - (1311, 1, 325, 50, 0), - (1313, 1, 85, 6037, 0), - (1314, 1, 85, 6038, 0), - (1315, 1, 85, 6039, 0), - (1316, 1, 302, 216, 216), - (1316, 2, 385, 99, 0), - (1317, 1, 302, 233, 233), - (1317, 2, 385, 99, 0), - (1318, 1, 302, 250, 250), - (1318, 2, 385, 99, 0), - (1319, 1, 274, 16, 0), - (1320, 1, 274, 18, 0), - (1321, 1, 274, 20, 0), - (1361, 1, 159, 10, 0), - (1361, 2, 262, 10, 0), - (1361, 3, 262, 10, 1), - (1361, 4, 262, 10, 2), - (1361, 5, 262, 10, 3), - (1361, 6, 262, 10, 4), - (1361, 7, 262, 10, 5), - (1361, 8, 262, 10, 6), - (1362, 1, 214, 300, 0), - (1362, 2, 97, 200, 0), - (1362, 3, 190, 200, 0), - (1363, 1, 327, 1, 0), - (1364, 1, 273, 1, 0), - (1364, 2, 274, 1, 0), - (1364, 3, 294, 1, 100), - (1364, 4, 169, 40, 0), - (1364, 5, 169, 40, 1), - (1364, 6, 169, 40, 2), - (1364, 7, 169, 40, 3), - (1364, 8, 169, 40, 8), - (1364, 9, 169, 40, 10), - (1364, 10, 169, 40, 26), - (1364, 11, 169, 40, 28), - (1364, 12, 169, 40, 30), - (1364, 13, 169, 40, 36), - (1364, 14, 169, 40, 74), - (1365, 1, 180, 2, 0), - (1366, 1, 159, 10, 0), - (1366, 2, 262, 10, 0), - (1366, 3, 262, 10, 1), - (1366, 4, 262, 10, 2), - (1366, 5, 262, 10, 3), - (1366, 6, 262, 10, 4), - (1366, 7, 262, 10, 5), - (1366, 8, 262, 10, 6), - (1367, 1, 214, 300, 0), - (1367, 2, 97, 200, 0), - (1367, 3, 190, 200, 0), - (1368, 1, 327, 1, 0), - (1369, 1, 273, 1, 0), - (1369, 2, 274, 1, 0), - (1369, 3, 294, 1, 100), - (1369, 4, 169, 40, 0), - (1369, 5, 169, 40, 1), - (1369, 6, 169, 40, 2), - (1369, 7, 169, 40, 3), - (1369, 8, 169, 40, 8), - (1369, 9, 169, 40, 10), - (1369, 10, 169, 40, 26), - (1369, 11, 169, 40, 28), - (1369, 12, 169, 40, 30), - (1369, 13, 169, 40, 36), - (1369, 14, 169, 40, 74), - (1370, 1, 180, 2, 0), - (1378, 1, 10, 0, 0), - (1379, 1, 10, 0, 0), - (1380, 1, 10, 0, 0), - (1382, 1, 10, 0, 0), - (1388, 2, 13, 1, 0), - (1389, 1, 328, 300, 0), - (1390, 1, 328, 350, 0), - (1391, 1, 328, 400, 0), - (1392, 1, 328, 450, 0), - (1393, 1, 328, 500, 0), - (1394, 1, 172, 33, 0), - (1395, 1, 172, 34, 0), - (1396, 1, 172, 35, 0), - (1397, 1, 172, 37, 0), - (1398, 1, 172, 39, 0), - (1399, 1, 259, 37, 0), - (1400, 1, 259, 39, 0), - (1401, 1, 259, 41, 0), - (1402, 1, 259, 43, 0), - (1403, 1, 259, 45, 0), - (1414, 1, 264, 432, 451), - (1415, 1, 264, 864, 451), - (1416, 1, 264, 1296, 451), - (1417, 1, 264, 1728, 451), - (1418, 1, 264, 2160, 451), - (1420, 1, 282, 20, 0), - (1421, 1, 282, 40, 0), - (1422, 1, 282, 60, 0), - (1423, 1, 282, 80, 0), - (1424, 1, 282, 100, 0), - (1430, 1, 280, 27, 0), - (1431, 1, 280, 34, 0), - (1432, 1, 280, 41, 0), - (1435, 1, 339, 3, 8105), - (1435, 2, 142, 65, 0), - (1435, 3, 311, 0, 0), - (1435, 4, 134, 70, 0), - (1435, 5, 348, 10, 0), - (1435, 6, 137, 0, 0), - (1435, 7, 339, 3, 8105), - (1435, 8, 142, 65, 0), - (1435, 9, 311, 0, 0), - (1435, 10, 134, 70, 0), - (1435, 11, 348, 10, 0), - (1435, 12, 137, 100, 0), - (1435, 13, 339, 3, 8105), - (1435, 14, 142, 65, 0), - (1435, 15, 311, 0, 0), - (1435, 16, 134, 70, 0), - (1435, 17, 348, 10, 0), - (1435, 18, 137, 79, 0), - (1435, 19, 339, 3, 8105), - (1435, 20, 142, 65, 0), - (1435, 21, 311, 0, 0), - (1435, 22, 134, 70, 0), - (1435, 23, 348, 10, 0), - (1435, 24, 137, 147, 0), - (1436, 1, 339, 6, 8105), - (1436, 2, 142, 65, 0), - (1436, 3, 311, 0, 0), - (1436, 4, 134, 70, 0), - (1436, 5, 348, 10, 0), - (1436, 6, 137, 0, 0), - (1436, 7, 339, 6, 8105), - (1436, 8, 142, 65, 0), - (1436, 9, 311, 0, 0), - (1436, 10, 134, 70, 0), - (1436, 11, 348, 10, 0), - (1436, 12, 137, 100, 0), - (1436, 13, 339, 6, 8105), - (1436, 14, 142, 65, 0), - (1436, 15, 311, 0, 0), - (1436, 16, 134, 70, 0), - (1436, 17, 348, 10, 0), - (1436, 18, 137, 79, 0), - (1436, 19, 339, 6, 8105), - (1436, 20, 142, 65, 0), - (1436, 21, 311, 0, 0), - (1436, 22, 134, 70, 0), - (1436, 23, 348, 10, 0), - (1436, 24, 137, 147, 0), - (1437, 1, 339, 10, 8105), - (1437, 2, 142, 65, 0), - (1437, 3, 311, 0, 0), - (1437, 4, 134, 70, 0), - (1437, 5, 348, 10, 0), - (1437, 6, 137, 0, 0), - (1437, 7, 339, 10, 8105), - (1437, 8, 142, 65, 0), - (1437, 9, 311, 0, 0), - (1437, 10, 134, 70, 0), - (1437, 11, 348, 10, 0), - (1437, 12, 137, 100, 0), - (1437, 13, 339, 10, 8105), - (1437, 14, 142, 65, 0), - (1437, 15, 311, 0, 0), - (1437, 16, 134, 70, 0), - (1437, 17, 348, 10, 0), - (1437, 18, 137, 79, 0), - (1437, 19, 339, 10, 8105), - (1437, 20, 142, 65, 0), - (1437, 21, 311, 0, 0), - (1437, 22, 134, 70, 0), - (1437, 23, 348, 10, 0), - (1437, 24, 137, 147, 0), - (1453, 1, 131, 10, 10), - (1453, 2, 137, 32, 0), - (1453, 3, 311, 1, 0), - (1454, 1, 131, 20, 20), - (1454, 2, 137, 32, 0), - (1454, 3, 311, 1, 0), - (1455, 1, 131, 30, 30), - (1455, 2, 137, 32, 0), - (1455, 3, 311, 1, 0), - (1456, 1, 131, 40, 40), - (1456, 2, 137, 32, 0), - (1456, 3, 311, 1, 0), - (1457, 1, 131, 50, 50), - (1457, 2, 137, 32, 0), - (1457, 3, 311, 1, 0), - (1467, 1, 280, 27, 0), - (1468, 1, 280, 34, 0), - (1469, 1, 280, 41, 0), - (1471, 1, 264, 90, 362), - (1472, 1, 264, 180, 362), - (1473, 1, 264, 270, 362), - (1474, 1, 264, 360, 362), - (1475, 1, 264, 450, 362), - (1483, 1, 294, 0, 133), - (1484, 1, 294, 0, 141), - (1485, 1, 294, 0, 150), - (1486, 1, 339, 1, 8165), - (1486, 2, 138, 1, 0), - (1486, 3, 141, 1, 0), - (1486, 4, 142, 60, 0), - (1486, 5, 137, 0, 0), - (1486, 6, 311, 0, 0), - (1486, 7, 134, 75, 0), - (1486, 8, 139, -265, 0), - (1486, 9, 139, -754, 0), - (1486, 10, 139, -1332, 0), - (1486, 11, 139, -1572, 0), - (1486, 12, 139, -2749, 0), - (1486, 13, 139, -4979, 0), - (1486, 14, 139, -5418, 0), - (1486, 15, 139, -5403, 0), - (1486, 16, 348, 10, 0), - (1487, 1, 339, 3, 8166), - (1487, 2, 138, 1, 0), - (1487, 3, 141, 1, 0), - (1487, 4, 142, 60, 0), - (1487, 5, 137, 0, 0), - (1487, 6, 311, 0, 0), - (1487, 7, 134, 75, 0), - (1487, 8, 139, -265, 0), - (1487, 9, 139, -754, 0), - (1487, 10, 139, -1332, 0), - (1487, 11, 139, -1572, 0), - (1487, 12, 139, -2749, 0), - (1487, 13, 139, -4979, 0), - (1487, 14, 139, -5418, 0), - (1487, 15, 139, -5403, 0), - (1487, 16, 348, 10, 0), - (1488, 1, 339, 5, 8167), - (1488, 2, 138, 1, 0), - (1488, 3, 141, 1, 0), - (1488, 4, 142, 60, 0), - (1488, 5, 137, 0, 0), - (1488, 6, 311, 0, 0), - (1488, 7, 134, 75, 0), - (1488, 8, 139, -265, 0), - (1488, 9, 139, -754, 0), - (1488, 10, 139, -1332, 0), - (1488, 11, 139, -1572, 0), - (1488, 12, 139, -2749, 0), - (1488, 13, 139, -4979, 0), - (1488, 14, 139, -5418, 0), - (1488, 15, 139, -5403, 0), - (1488, 16, 348, 10, 0), - (1489, 1, 339, 7, 8168), - (1489, 2, 138, 1, 0), - (1489, 3, 141, 1, 0), - (1489, 4, 142, 60, 0), - (1489, 5, 137, 0, 0), - (1489, 6, 311, 0, 0), - (1489, 7, 134, 75, 0), - (1489, 8, 139, -265, 0), - (1489, 9, 139, -754, 0), - (1489, 10, 139, -1332, 0), - (1489, 11, 139, -1572, 0), - (1489, 12, 139, -2749, 0), - (1489, 13, 139, -4979, 0), - (1489, 14, 139, -5418, 0), - (1489, 15, 139, -5403, 0), - (1489, 16, 348, 10, 0), - (1490, 1, 339, 9, 8169), - (1490, 2, 138, 1, 0), - (1490, 3, 141, 1, 0), - (1490, 4, 142, 60, 0), - (1490, 5, 137, 0, 0), - (1490, 6, 311, 0, 0), - (1490, 7, 134, 75, 0), - (1490, 8, 139, -265, 0), - (1490, 9, 139, -754, 0), - (1490, 10, 139, -1332, 0), - (1490, 11, 139, -1572, 0), - (1490, 12, 139, -2749, 0), - (1490, 13, 139, -4979, 0), - (1490, 14, 139, -5418, 0), - (1490, 15, 139, -5403, 0), - (1490, 16, 348, 10, 0), - (1504, 1, 287, 2, 0), - (1504, 2, 385, 2754, 1), - (1505, 1, 287, 4, 0), - (1505, 2, 385, 2754, 1), - (1506, 1, 287, 6, 0), - (1506, 2, 385, 2754, 1), - (1511, 1, 264, 60, 175), - (1511, 2, 264, 60, 792), - (1512, 1, 264, 120, 175), - (1512, 2, 264, 120, 792), - (1513, 1, 264, 180, 175), - (1513, 2, 264, 180, 792), - (1514, 1, 273, 2, 0), - (1515, 1, 273, 4, 0), - (1516, 1, 273, 6, 0), - (1524, 1, 219, 260, 1800), - (1525, 1, 219, 300, 2000), - (1526, 1, 219, 280, 1900), - (1528, 1, 239, 30, 0), - (1529, 1, 239, 35, 0), - (1530, 1, 239, 40, 0), - (1531, 1, 239, 45, 0), - (1532, 1, 239, 50, 0), - (1533, 1, 266, 11, 0), - (1534, 1, 266, 14, 0), - (1535, 1, 266, 17, 0), - (1536, 1, 266, 11, 0), - (1537, 1, 266, 14, 0), - (1538, 1, 266, 17, 0), - (1539, 1, 252, 37, 0), - (1540, 1, 252, 44, 0), - (1541, 1, 252, 50, 0), - (1543, 1, 220, 10, 8), - (1544, 1, 220, 20, 8), - (1545, 1, 220, 30, 8), - (1546, 1, 264, 120, 420), - (1547, 1, 264, 240, 420), - (1548, 1, 264, 360, 420), - (1549, 1, 293, 25, 0), - (1550, 1, 293, 50, 0), - (1551, 1, 293, 75, 0), - (1552, 1, 271, 5, 0), - (1553, 1, 271, 10, 0), - (1554, 1, 271, 15, 0), - (1555, 1, 264, 240, 359), - (1556, 1, 264, 480, 359), - (1557, 1, 264, 720, 359), - (1563, 1, 225, 18, 0), - (1564, 1, 225, 21, 0), - (1565, 1, 225, 24, 0), - (1566, 1, 225, 27, 0), - (1567, 1, 225, 30, 0), - (1572, 1, 339, 2, 8261), - (1572, 2, 138, 0, 0), - (1572, 3, 137, 31, 0), - (1572, 4, 311, 0, 0), - (1573, 1, 339, 4, 8262), - (1573, 2, 138, 0, 0), - (1573, 3, 137, 31, 0), - (1573, 4, 311, 0, 0), - (1574, 1, 339, 6, 8263), - (1574, 2, 138, 0, 0), - (1574, 3, 137, 31, 0), - (1574, 4, 311, 0, 0), - (1575, 1, 339, 8, 8264), - (1575, 2, 138, 0, 0), - (1575, 3, 137, 31, 0), - (1575, 4, 311, 0, 0), - (1576, 1, 339, 10, 8265), - (1576, 2, 138, 0, 0), - (1576, 3, 137, 31, 0), - (1576, 4, 311, 0, 0), - (1577, 1, 274, 3, 0), - (1578, 1, 274, 6, 0), - (1579, 1, 274, 10, 0), - (1583, 1, 264, 360, 300), - (1584, 1, 264, 720, 300), - (1585, 1, 264, 1080, 300), - (1586, 1, 264, 1440, 300), - (1587, 1, 264, 1800, 300), - (1588, 1, 344, 50, 0), - (1589, 1, 344, 100, 0), - (1590, 1, 344, 150, 0), - (1591, 1, 293, 25, 0), - (1592, 1, 341, 10, 0), - (1593, 1, 341, 20, 0), - (1594, 1, 341, 30, 0), - (1595, 1, 341, 40, 0), - (1596, 1, 341, 50, 0), - (1601, 1, 217, 0, 35200), - (1601, 2, 346, 60, 0), - (1602, 1, 217, 0, 42440), - (1602, 2, 346, 62, 0), - (1603, 1, 217, 0, 46480), - (1603, 2, 346, 64, 0), - (1604, 1, 439, 0, 32000), - (1604, 2, 345, 59, 0), - (1605, 1, 439, 0, 35200), - (1605, 2, 345, 60, 0), - (1606, 1, 439, 0, 42440), - (1606, 2, 345, 61, 0), - (1608, 1, 347, 2, 0), - (1609, 1, 347, 4, 0), - (1610, 1, 347, 6, 0), - (1611, 1, 282, 20, 0), - (1612, 1, 282, 40, 0), - (1613, 1, 282, 60, 0), - (1614, 1, 282, 80, 0), - (1615, 1, 282, 100, 0), - (1616, 1, 279, 7, 0), - (1617, 1, 279, 11, 0), - (1618, 1, 279, 15, 0), - (1619, 1, 279, 17, 0), - (1620, 1, 279, 19, 0), - (1621, 1, 177, 20, -1), - (1622, 1, 177, 22, -1), - (1623, 1, 177, 24, -1), - (1624, 1, 177, 20, -1), - (1625, 1, 177, 22, -1), - (1626, 1, 177, 24, -1), - (1627, 1, 271, 5, 0), - (1628, 1, 271, 10, 0), - (1629, 1, 271, 15, 0), - (1633, 1, 225, 18, 0), - (1634, 1, 225, 21, 0), - (1635, 1, 225, 24, 0), - (1636, 1, 225, 27, 0), - (1637, 1, 225, 30, 0), - (1641, 1, 359, 100, 0), - (1642, 1, 359, 60, 0), - (1648, 1, 339, 10, 8105), - (1648, 2, 142, 65, 0), - (1648, 3, 311, 0, 0), - (1648, 4, 134, 70, 0), - (1648, 5, 348, 10, 0), - (1648, 6, 137, 0, 0), - (1648, 7, 339, 10, 8105), - (1648, 8, 142, 65, 0), - (1648, 9, 311, 0, 0), - (1648, 10, 134, 70, 0), - (1648, 11, 348, 10, 0), - (1648, 12, 137, 100, 0), - (1648, 13, 339, 10, 8105), - (1648, 14, 142, 65, 0), - (1648, 15, 311, 0, 0), - (1648, 16, 134, 70, 0), - (1648, 17, 348, 10, 0), - (1648, 18, 137, 79, 0), - (1648, 19, 339, 10, 8105), - (1648, 20, 142, 65, 0), - (1648, 21, 311, 0, 0), - (1648, 22, 134, 70, 0), - (1648, 23, 348, 10, 0), - (1648, 24, 137, 147, 0), - (1648, 25, 339, 10, 11404), - (1648, 26, 142, 71, 0), - (1648, 27, 311, 0, 0), - (1648, 28, 134, 75, 0), - (1648, 29, 348, 10, 0), - (1648, 30, 137, 0, 0), - (1648, 31, 339, 10, 11404), - (1648, 32, 142, 71, 0), - (1648, 33, 311, 0, 0), - (1648, 34, 134, 75, 0), - (1648, 35, 348, 10, 0), - (1648, 36, 137, 100, 0), - (1648, 37, 339, 10, 11404), - (1648, 38, 142, 71, 0), - (1648, 39, 311, 0, 0), - (1648, 40, 134, 75, 0), - (1648, 41, 348, 10, 0), - (1648, 42, 137, 79, 0), - (1648, 43, 339, 10, 11404), - (1648, 44, 142, 71, 0), - (1648, 45, 311, 0, 0), - (1648, 46, 134, 75, 0), - (1648, 47, 348, 10, 0), - (1648, 48, 137, 147, 0), - (1649, 1, 339, 10, 8105), - (1649, 2, 142, 65, 0), - (1649, 3, 311, 0, 0), - (1649, 4, 134, 70, 0), - (1649, 5, 348, 10, 0), - (1649, 6, 137, 0, 0), - (1649, 7, 339, 10, 8105), - (1649, 8, 142, 65, 0), - (1649, 9, 311, 0, 0), - (1649, 10, 134, 70, 0), - (1649, 11, 348, 10, 0), - (1649, 12, 137, 100, 0), - (1649, 13, 339, 10, 8105), - (1649, 14, 142, 65, 0), - (1649, 15, 311, 0, 0), - (1649, 16, 134, 70, 0), - (1649, 17, 348, 10, 0), - (1649, 18, 137, 79, 0), - (1649, 19, 339, 10, 8105), - (1649, 20, 142, 65, 0), - (1649, 21, 311, 0, 0), - (1649, 22, 134, 70, 0), - (1649, 23, 348, 10, 0), - (1649, 24, 137, 147, 0), - (1649, 25, 339, 10, 11404), - (1649, 26, 142, 71, 0), - (1649, 27, 311, 0, 0), - (1649, 28, 134, 75, 0), - (1649, 29, 348, 10, 0), - (1649, 30, 137, 0, 0), - (1649, 31, 339, 10, 11404), - (1649, 32, 142, 71, 0), - (1649, 33, 311, 0, 0), - (1649, 34, 134, 75, 0), - (1649, 35, 348, 10, 0), - (1649, 36, 137, 100, 0), - (1649, 37, 339, 10, 11404), - (1649, 38, 142, 71, 0), - (1649, 39, 311, 0, 0), - (1649, 40, 134, 75, 0), - (1649, 41, 348, 10, 0), - (1649, 42, 137, 79, 0), - (1649, 43, 339, 10, 11404), - (1649, 44, 142, 71, 0), - (1649, 45, 311, 0, 0), - (1649, 46, 134, 75, 0), - (1649, 47, 348, 10, 0), - (1649, 48, 137, 147, 0), - (1649, 49, 339, 10, 13199), - (1649, 50, 142, 76, 0), - (1649, 51, 311, 0, 0), - (1649, 52, 134, 80, 0), - (1649, 53, 348, 10, 0), - (1649, 54, 137, 0, 0), - (1649, 55, 339, 10, 13199), - (1649, 56, 142, 76, 0), - (1649, 57, 311, 0, 0), - (1649, 58, 134, 80, 0), - (1649, 59, 348, 10, 0), - (1649, 60, 137, 100, 0), - (1649, 61, 339, 10, 13199), - (1649, 62, 142, 76, 0), - (1649, 63, 311, 0, 0), - (1649, 64, 134, 80, 0), - (1649, 65, 348, 10, 0), - (1649, 66, 137, 79, 0), - (1649, 67, 339, 10, 13199), - (1649, 68, 142, 76, 0), - (1649, 69, 311, 0, 0), - (1649, 70, 134, 80, 0), - (1649, 71, 348, 10, 0), - (1649, 72, 137, 147, 0), - (1650, 1, 339, 10, 8105), - (1650, 2, 142, 65, 0), - (1650, 3, 311, 0, 0), - (1650, 4, 134, 70, 0), - (1650, 5, 348, 10, 0), - (1650, 6, 137, 0, 0), - (1650, 7, 339, 10, 8105), - (1650, 8, 142, 65, 0), - (1650, 9, 311, 0, 0), - (1650, 10, 134, 70, 0), - (1650, 11, 348, 10, 0), - (1650, 12, 137, 100, 0), - (1650, 13, 339, 10, 8105), - (1650, 14, 142, 65, 0), - (1650, 15, 311, 0, 0), - (1650, 16, 134, 70, 0), - (1650, 17, 348, 10, 0), - (1650, 18, 137, 79, 0), - (1650, 19, 339, 10, 8105), - (1650, 20, 142, 65, 0), - (1650, 21, 311, 0, 0), - (1650, 22, 134, 70, 0), - (1650, 23, 348, 10, 0), - (1650, 24, 137, 147, 0), - (1650, 25, 339, 10, 11404), - (1650, 26, 142, 71, 0), - (1650, 27, 311, 0, 0), - (1650, 28, 134, 75, 0), - (1650, 29, 348, 10, 0), - (1650, 30, 137, 0, 0), - (1650, 31, 339, 10, 11404), - (1650, 32, 142, 71, 0), - (1650, 33, 311, 0, 0), - (1650, 34, 134, 75, 0), - (1650, 35, 348, 10, 0), - (1650, 36, 137, 100, 0), - (1650, 37, 339, 10, 11404), - (1650, 38, 142, 71, 0), - (1650, 39, 311, 0, 0), - (1650, 40, 134, 75, 0), - (1650, 41, 348, 10, 0), - (1650, 42, 137, 79, 0), - (1650, 43, 339, 10, 11404), - (1650, 44, 142, 71, 0), - (1650, 45, 311, 0, 0), - (1650, 46, 134, 75, 0), - (1650, 47, 348, 10, 0), - (1650, 48, 137, 147, 0), - (1650, 49, 339, 10, 13199), - (1650, 50, 142, 76, 0), - (1650, 51, 311, 0, 0), - (1650, 52, 134, 80, 0), - (1650, 53, 348, 10, 0), - (1650, 54, 137, 0, 0), - (1650, 55, 339, 10, 13199), - (1650, 56, 142, 76, 0), - (1650, 57, 311, 0, 0), - (1650, 58, 134, 80, 0), - (1650, 59, 348, 10, 0), - (1650, 60, 137, 100, 0), - (1650, 61, 339, 10, 13199), - (1650, 62, 142, 76, 0), - (1650, 63, 311, 0, 0), - (1650, 64, 134, 80, 0), - (1650, 65, 348, 10, 0), - (1650, 66, 137, 79, 0), - (1650, 67, 339, 10, 13199), - (1650, 68, 142, 76, 0), - (1650, 69, 311, 0, 0), - (1650, 70, 134, 80, 0), - (1650, 71, 348, 10, 0), - (1650, 72, 137, 147, 0), - (1650, 73, 339, 10, 13830), - (1650, 74, 142, 81, 0), - (1650, 75, 311, 0, 0), - (1650, 76, 134, 85, 0), - (1650, 77, 348, 10, 0), - (1650, 78, 137, 0, 0), - (1650, 79, 339, 10, 13830), - (1650, 80, 142, 81, 0), - (1650, 81, 311, 0, 0), - (1650, 82, 134, 85, 0), - (1650, 83, 348, 10, 0), - (1650, 84, 137, 100, 0), - (1650, 85, 339, 10, 13830), - (1650, 86, 142, 81, 0), - (1650, 87, 311, 0, 0), - (1650, 88, 134, 85, 0), - (1650, 89, 348, 10, 0), - (1650, 90, 137, 79, 0), - (1650, 91, 339, 10, 13830), - (1650, 92, 142, 81, 0), - (1650, 93, 311, 0, 0), - (1650, 94, 134, 85, 0), - (1650, 95, 348, 10, 0), - (1650, 96, 137, 147, 0), - (1651, 1, 97, 300, 0), - (1652, 1, 97, 350, 0), - (1653, 1, 97, 400, 0), - (1654, 1, 97, 450, 0), - (1655, 1, 97, 500, 0), - (1656, 1, 127, 40, 0), - (1656, 2, 137, 154, 0), - (1656, 3, 403, 2, 0), - (1656, 4, 404, 10, 0), - (1657, 1, 127, 50, 0), - (1657, 2, 137, 154, 0), - (1657, 3, 403, 2, 0), - (1657, 4, 404, 10, 0), - (1659, 1, 127, 40, 0), - (1659, 2, 137, 154, 0), - (1659, 3, 403, 2, 0), - (1659, 4, 404, 10, 0), - (1660, 1, 127, 50, 0), - (1660, 2, 137, 154, 0), - (1660, 3, 403, 2, 0), - (1660, 4, 404, 10, 0), - (1662, 1, 370, 2, 0), - (1663, 1, 370, 4, 0), - (1664, 1, 370, 6, 0), - (1665, 1, 370, 8, 0), - (1666, 1, 370, 10, 0), - (2400, 1, 264, 90, 38), - (2401, 1, 264, 180, 38), - (2402, 1, 264, 270, 38), - (4666, 0, 366, 10, 50), - (4666, 1, 349, 5, 0), - (4667, 0, 366, 30, 50), - (4667, 1, 349, 10, 0), - (4668, 0, 366, 60, 50), - (4668, 1, 349, 15, 0), - (4669, 0, 366, 10, 500), - (4669, 1, 349, 20, 0), - (4670, 0, 366, 30, 500), - (4670, 1, 349, 25, 0), - (4672, 1, 268, 10, 57), - (4673, 1, 268, 25, 57), - (4674, 1, 268, 50, 57), - (4675, 1, 268, 10, 68), - (4676, 1, 268, 25, 68), - (4677, 1, 268, 50, 68), - (4678, 1, 262, 55, 0), - (4678, 2, 262, 55, 1), - (4678, 3, 262, 55, 2), - (4678, 4, 262, 55, 3), - (4678, 5, 262, 55, 4), - (4678, 6, 262, 55, 5), - (4678, 7, 262, 55, 6), - (4679, 1, 262, 60, 0), - (4679, 2, 262, 60, 1), - (4679, 3, 262, 60, 2), - (4679, 4, 262, 60, 3), - (4679, 5, 262, 60, 4), - (4679, 6, 262, 60, 5), - (4679, 7, 262, 60, 6), - (4680, 1, 262, 65, 0), - (4680, 2, 262, 65, 1), - (4680, 3, 262, 65, 2), - (4680, 4, 262, 65, 3), - (4680, 5, 262, 65, 4), - (4680, 6, 262, 65, 5), - (4680, 7, 262, 65, 6), - (4681, 1, 262, 70, 0), - (4681, 2, 262, 70, 1), - (4681, 3, 262, 70, 2), - (4681, 4, 262, 70, 3), - (4681, 5, 262, 70, 4), - (4681, 6, 262, 70, 5), - (4681, 7, 262, 70, 6), - (4682, 1, 262, 75, 0), - (4682, 2, 262, 75, 1), - (4682, 3, 262, 75, 2), - (4682, 4, 262, 75, 3), - (4682, 5, 262, 75, 4), - (4682, 6, 262, 75, 5), - (4682, 7, 262, 75, 6), - (4683, 1, 328, 550, 0), - (4684, 1, 328, 600, 0), - (4685, 1, 328, 650, 0), - (4686, 1, 328, 700, 0), - (4687, 1, 328, 750, 0), - (4688, 1, 282, 20, 0), - (4689, 1, 282, 40, 0), - (4690, 1, 282, 60, 0), - (4691, 1, 282, 80, 0), - (4692, 1, 282, 100, 0), - (4693, 1, 0, 11, 0), - (4694, 1, 0, 12, 0), - (4695, 1, 0, 13, 0), - (4696, 1, 0, 14, 0), - (4697, 1, 0, 15, 0), - (4698, 1, 362, 1, 0), - (4699, 1, 363, 1, 0), - (4707, 1, 330, 85, 0), - (4707, 2, 330, 85, 1), - (4707, 3, 330, 85, 2), - (4707, 4, 330, 85, 3), - (4707, 5, 330, 85, 28), - (4707, 6, 330, 85, 36), - (4707, 7, 330, 85, 77), - (4708, 1, 330, 95, 0), - (4708, 2, 330, 95, 1), - (4708, 3, 330, 95, 2), - (4708, 4, 330, 95, 3), - (4708, 5, 330, 95, 28), - (4708, 6, 330, 95, 36), - (4708, 7, 330, 95, 77), - (4709, 1, 330, 105, 0), - (4709, 2, 330, 105, 1), - (4709, 3, 330, 105, 2), - (4709, 4, 330, 105, 3), - (4709, 5, 330, 105, 28), - (4709, 6, 330, 105, 36), - (4709, 7, 330, 105, 77), - (4710, 1, 330, 85, 0), - (4710, 2, 330, 85, 1), - (4710, 3, 330, 85, 2), - (4710, 4, 330, 85, 3), - (4710, 5, 330, 85, 28), - (4710, 6, 330, 85, 36), - (4711, 1, 330, 95, 0), - (4711, 2, 330, 95, 1), - (4711, 3, 330, 95, 2), - (4711, 4, 330, 95, 3), - (4711, 5, 330, 95, 28), - (4711, 6, 330, 95, 36), - (4712, 1, 330, 105, 0), - (4712, 2, 330, 105, 1), - (4712, 3, 330, 105, 2), - (4712, 4, 330, 105, 3), - (4712, 5, 330, 105, 28), - (4712, 6, 330, 105, 36), - (4713, 1, 330, 85, 0), - (4713, 2, 330, 85, 1), - (4713, 3, 330, 85, 2), - (4713, 4, 330, 85, 3), - (4713, 5, 330, 85, 28), - (4713, 6, 330, 85, 36), - (4713, 7, 330, 85, 77), - (4714, 1, 330, 95, 0), - (4714, 2, 330, 95, 1), - (4714, 3, 330, 95, 2), - (4714, 4, 330, 95, 3), - (4714, 5, 330, 95, 28), - (4714, 6, 330, 95, 36), - (4714, 7, 330, 95, 77), - (4715, 1, 330, 105, 0), - (4715, 2, 330, 105, 1), - (4715, 3, 330, 105, 2), - (4715, 4, 330, 105, 3), - (4715, 5, 330, 105, 28), - (4715, 6, 330, 105, 36), - (4715, 7, 330, 105, 77), - (4716, 1, 330, 60, 0), - (4716, 2, 330, 60, 1), - (4716, 3, 330, 60, 2), - (4716, 4, 330, 60, 3), - (4716, 5, 330, 60, 28), - (4716, 6, 330, 60, 36), - (4716, 7, 330, 60, 77), - (4717, 1, 330, 70, 0), - (4717, 2, 330, 70, 1), - (4717, 3, 330, 70, 2), - (4717, 4, 330, 70, 3), - (4717, 5, 330, 70, 28), - (4717, 6, 330, 70, 36), - (4717, 7, 330, 70, 77), - (4718, 1, 330, 80, 0), - (4718, 2, 330, 80, 1), - (4718, 3, 330, 80, 2), - (4718, 4, 330, 80, 3), - (4718, 5, 330, 80, 28), - (4718, 6, 330, 80, 36), - (4718, 7, 330, 80, 77), - (4722, 1, 278, 620, 35216), - (4722, 2, 440, 66, 100), - (4723, 1, 278, 650, 38310), - (4723, 2, 440, 68, 100), - (4724, 1, 278, 670, 41300), - (4724, 2, 440, 70, 100), - (4725, 1, 341, 60, 0), - (4726, 1, 341, 70, 0), - (4727, 1, 341, 80, 0), - (4728, 1, 341, 90, 0), - (4729, 1, 341, 100, 0), - (4733, 1, 294, 11, 100), - (4734, 1, 294, 13, 100), - (4735, 1, 294, 15, 100), - (4739, 1, 360, 10, 11023), - (4740, 1, 360, 20, 11023), - (4741, 1, 360, 30, 11023), - (4744, 1, 318, 6, 0), - (4745, 1, 318, 7, 0), - (4746, 1, 318, 8, 0), - (4747, 1, 318, 9, 0), - (4748, 1, 318, 10, 0), - (4749, 1, 294, 11, 100), - (4750, 1, 294, 13, 100), - (4751, 1, 294, 15, 100), - (4752, 1, 294, 0, 155), - (4753, 1, 294, 0, 160), - (4754, 1, 294, 0, 165), - (4755, 1, 294, 0, 130), - (4756, 1, 294, 0, 135), - (4757, 1, 294, 0, 140), - (4758, 1, 266, 27, 0), - (4759, 1, 266, 28, 0), - (4760, 1, 266, 29, 0), - (4761, 1, 273, 2, 0), - (4762, 1, 273, 3, 0), - (4763, 1, 273, 4, 0), - (4764, 1, 326, 2, 0), - (4767, 1, 114, -43, 0), - (4768, 1, 114, -46, 0), - (4769, 1, 114, -50, 0), - (4773, 1, 339, 10, 8105), - (4773, 2, 142, 65, 0), - (4773, 3, 311, 0, 0), - (4773, 4, 134, 70, 0), - (4773, 5, 348, 10, 0), - (4773, 6, 137, 0, 0), - (4773, 7, 339, 10, 8105), - (4773, 8, 142, 65, 0), - (4773, 9, 311, 0, 0), - (4773, 10, 134, 70, 0), - (4773, 11, 348, 10, 0), - (4773, 12, 137, 100, 0), - (4773, 13, 339, 10, 8105), - (4773, 14, 142, 65, 0), - (4773, 15, 311, 0, 0), - (4773, 16, 134, 70, 0), - (4773, 17, 348, 10, 0), - (4773, 18, 137, 79, 0), - (4773, 19, 339, 10, 8105), - (4773, 20, 142, 65, 0), - (4773, 21, 311, 0, 0), - (4773, 22, 134, 70, 0), - (4773, 23, 348, 10, 0), - (4773, 24, 137, 147, 0), - (4773, 25, 339, 10, 11404), - (4773, 26, 142, 71, 0), - (4773, 27, 311, 0, 0), - (4773, 28, 134, 75, 0), - (4773, 29, 348, 10, 0), - (4773, 30, 137, 0, 0), - (4773, 31, 339, 10, 11404), - (4773, 32, 142, 71, 0), - (4773, 33, 311, 0, 0), - (4773, 34, 134, 75, 0), - (4773, 35, 348, 10, 0), - (4773, 36, 137, 100, 0), - (4773, 37, 339, 10, 11404), - (4773, 38, 142, 71, 0), - (4773, 39, 311, 0, 0), - (4773, 40, 134, 75, 0), - (4773, 41, 348, 10, 0), - (4773, 42, 137, 79, 0), - (4773, 43, 339, 10, 11404), - (4773, 44, 142, 71, 0), - (4773, 45, 311, 0, 0), - (4773, 46, 134, 75, 0), - (4773, 47, 348, 10, 0), - (4773, 48, 137, 147, 0), - (4776, 1, 319, 12, 0), - (4777, 1, 319, 14, 0), - (4778, 1, 319, 16, 0), - (4779, 1, 274, 24, 0), - (4780, 1, 274, 26, 0), - (4781, 1, 274, 28, 0), - (4790, 1, 220, 288, 74), - (4791, 1, 220, 320, 74), - (4792, 1, 220, 352, 74), - (4793, 1, 220, 384, 74), - (4794, 1, 220, 416, 74), - (4795, 1, 279, 28, 0), - (4796, 1, 279, 29, 0), - (4797, 1, 279, 30, 0), - (4798, 1, 292, 65, 0), - (4799, 1, 292, 70, 0), - (4800, 1, 292, 75, 0), - (4801, 1, 227, 30, 32), - (4802, 1, 227, 60, 32), - (4803, 1, 227, 90, 32), - (4804, 1, 220, 448, 74), - (4805, 1, 220, 480, 74), - (4806, 1, 220, 512, 74), - (4807, 1, 220, 544, 74), - (4808, 1, 220, 576, 74), - (4809, 1, 216, 40, 74), - (4810, 1, 216, 80, 74), - (4811, 1, 216, 120, 74), - (4813, 1, 220, 70, 26), - (4813, 2, 220, 70, 30), - (4813, 3, 220, 70, 38), - (4814, 1, 220, 80, 26), - (4814, 2, 220, 80, 30), - (4814, 3, 220, 80, 38), - (4815, 1, 220, 90, 26), - (4815, 2, 220, 90, 30), - (4815, 3, 220, 90, 38), - (4819, 1, 239, 52, 0), - (4820, 1, 239, 54, 0), - (4821, 1, 239, 56, 0), - (4822, 1, 239, 58, 0), - (4823, 1, 239, 60, 0), - (4824, 1, 239, 52, 0), - (4825, 1, 239, 54, 0), - (4826, 1, 239, 56, 0), - (4827, 1, 239, 58, 0), - (4828, 1, 239, 60, 0), - (4829, 1, 264, 480, 420), - (4830, 1, 264, 600, 420), - (4831, 1, 264, 720, 420), - (4844, 1, 349, 5, 0), - (4845, 1, 349, 10, 0), - (4846, 1, 349, 15, 0), - (4847, 1, 349, 20, 0), - (4848, 1, 349, 25, 0), - (4861, 1, 264, 600, 68), - (4862, 1, 264, 1200, 68), - (4863, 1, 264, 1800, 68), - (4887, 1, 264, 120, 413), - (4888, 1, 264, 240, 413), - (4889, 1, 264, 360, 413), - (4897, 1, 280, 44, 0), - (4898, 1, 280, 47, 0), - (4899, 1, 280, 50, 0), - (4921, 1, 264, 1896, 117), - (4921, 2, 244, 75, 0), - (4922, 1, 264, 2496, 117), - (4922, 2, 244, 60, 0), - (4923, 1, 264, 3096, 117), - (4923, 2, 244, 45, 0), - (4924, 1, 273, 1, 0), - (4925, 1, 273, 2, 0), - (4926, 1, 273, 3, 0), - (4948, 1, 258, 35, 0), - (4949, 1, 258, 40, 0), - (4950, 1, 258, 45, 0), - (4951, 1, 220, 40, 8), - (4952, 1, 220, 50, 8), - (4953, 1, 220, 60, 8), - (4957, 1, 252, 55, 0), - (4958, 1, 252, 60, 0), - (4959, 1, 252, 65, 0), - (4960, 1, 280, 46, 0), - (4961, 1, 280, 51, 0), - (4962, 1, 280, 56, 0), - (4983, 1, 216, 65, 0), - (4983, 2, 216, 65, 1), - (4983, 3, 216, 65, 2), - (4983, 4, 216, 65, 3), - (4983, 5, 216, 65, 10), - (4983, 6, 216, 65, 28), - (4983, 7, 216, 65, 30), - (4983, 8, 216, 65, 36), - (4983, 9, 216, 65, 77), - (4984, 1, 216, 70, 0), - (4984, 2, 216, 70, 1), - (4984, 3, 216, 70, 2), - (4984, 4, 216, 70, 3), - (4984, 5, 216, 70, 10), - (4984, 6, 216, 70, 28), - (4984, 7, 216, 70, 30), - (4984, 8, 216, 70, 36), - (4984, 9, 216, 70, 77), - (4985, 1, 216, 75, 0), - (4985, 2, 216, 75, 1), - (4985, 3, 216, 75, 2), - (4985, 4, 216, 75, 3), - (4985, 5, 216, 75, 10), - (4985, 6, 216, 75, 28), - (4985, 7, 216, 75, 30), - (4985, 8, 216, 75, 36), - (4985, 9, 216, 75, 77), - (4986, 1, 217, 0, 52960), - (4986, 2, 346, 66, 40), - (4987, 1, 217, 0, 55400), - (4987, 2, 346, 68, 40), - (4988, 1, 217, 0, 60280), - (4988, 2, 346, 70, 40), - (4989, 1, 347, 8, 0), - (4990, 1, 347, 10, 0), - (4991, 1, 347, 12, 0), - (4992, 1, 279, 21, 0), - (4993, 1, 279, 23, 0), - (4994, 1, 279, 25, 0), - (4995, 1, 279, 27, 0), - (4996, 1, 279, 28, 0), - (5000, 1, 313, 80, 0), - (5001, 1, 313, 90, 0), - (5002, 1, 313, 100, 0), - (5010, 1, 264, 432, 35), - (5011, 1, 264, 864, 35), - (5012, 1, 264, 1296, 35), - (5013, 1, 293, 90, 0), - (5014, 1, 293, 100, 0), - (5029, 1, 85, 11621, 0), - (5030, 1, 85, 11622, 0), - (5031, 1, 85, 11623, 0), - (5032, 1, 274, 22, 0), - (5033, 1, 274, 24, 0), - (5034, 1, 274, 26, 0), - (5035, 1, 293, 60, 0), - (5036, 1, 293, 70, 0), - (5037, 1, 293, 80, 0), - (5038, 1, 219, 330, 2100), - (5039, 1, 219, 360, 2200), - (5040, 1, 219, 390, 2300), - (5045, 1, 180, 5, 0), - (5061, 1, 244, -25, 0), - (5085, 1, 360, 25, 11297), - (5086, 1, 360, 25, 11298), - (5087, 1, 360, 25, 11299), - (5118, 1, 264, 720, 396), - (5118, 2, 264, 720, 8504), - (5118, 3, 264, 720, 8505), - (5119, 1, 264, 1440, 396), - (5119, 2, 264, 1440, 8504), - (5119, 3, 264, 1440, 8505), - (5120, 1, 264, 2160, 396), - (5120, 2, 264, 2160, 8504), - (5120, 3, 264, 2160, 8505), - (5127, 1, 264, 300, 261), - (5128, 1, 264, 600, 261), - (5129, 1, 264, 900, 261), - (5133, 1, 294, 13, 100), - (5134, 1, 294, 15, 100), - (5135, 1, 294, 17, 100), - (5136, 1, 282, 20, 0), - (5137, 1, 282, 40, 0), - (5138, 1, 282, 60, 0), - (5139, 1, 282, 80, 0), - (5140, 1, 282, 100, 0), - (5141, 1, 279, 21, 0), - (5142, 1, 279, 23, 0), - (5143, 1, 279, 25, 0), - (5144, 1, 279, 27, 0), - (5145, 1, 279, 28, 0), - (5243, 1, 69, 600, 0), - (5244, 1, 69, 700, 0), - (5245, 1, 69, 800, 0), - (5246, 1, 69, 900, 0), - (5247, 1, 69, 1000, 0), - (5248, 1, 360, 10, 11232), - (5249, 1, 360, 20, 11232), - (5250, 1, 360, 30, 11232), - (5254, 1, 218, 6, 0), - (5255, 1, 218, 7, 0), - (5256, 1, 218, 8, 0), - (5257, 1, 218, 9, 0), - (5258, 1, 218, 10, 0), - (5259, 1, 218, 6, 0), - (5260, 1, 218, 7, 0), - (5261, 1, 218, 8, 0), - (5262, 1, 218, 9, 0), - (5263, 1, 218, 10, 0), - (5264, 1, 218, 1, 0), - (5265, 1, 218, 2, 0), - (5266, 1, 218, 3, 0), - (5267, 1, 218, 4, 0), - (5268, 1, 218, 5, 0), - (5269, 1, 131, 50, 50), - (5269, 2, 137, 82, 0), - (5270, 1, 303, 3000, 3000), - (5270, 2, 139, 2766, 0), - (5271, 1, 303, 3500, 3500), - (5271, 2, 139, 2766, 0), - (5272, 1, 303, 4000, 4000), - (5272, 2, 139, 2766, 0), - (5276, 1, 264, 60, 621), - (5276, 2, 264, 60, 622), - (5276, 3, 264, 60, 623), - (5276, 4, 264, 60, 784), - (5276, 5, 264, 60, 785), - (5276, 6, 264, 60, 786), - (5276, 7, 264, 60, 787), - (5276, 8, 264, 60, 624), - (5277, 1, 264, 120, 621), - (5277, 2, 264, 120, 622), - (5277, 3, 264, 120, 623), - (5277, 4, 264, 120, 784), - (5277, 5, 264, 120, 785), - (5277, 6, 264, 120, 786), - (5277, 7, 264, 120, 787), - (5277, 8, 264, 120, 624), - (5278, 1, 264, 180, 621), - (5278, 2, 264, 180, 622), - (5278, 3, 264, 180, 623), - (5278, 4, 264, 180, 784), - (5278, 5, 264, 180, 785), - (5278, 6, 264, 180, 786), - (5278, 7, 264, 180, 787), - (5278, 8, 264, 180, 624), - (5283, 1, 320, 1, 0), - (5284, 1, 320, 3, 0), - (5285, 1, 320, 5, 0), - (5286, 1, 294, 7, 100), - (5287, 1, 294, 8, 100), - (5288, 1, 294, 9, 100), - (5290, 1, 439, 0, 46480), - (5290, 2, 345, 62, 0), - (5291, 1, 439, 0, 52960), - (5291, 2, 345, 63, 0), - (5292, 1, 439, 0, 55400), - (5292, 2, 345, 64, 0), - (5293, 1, 439, 0, 60280), - (5293, 2, 345, 65, 0), - (5294, 1, 439, 0, 65440), - (5294, 2, 345, 66, 50), - (5295, 1, 360, 10, 11629), - (5296, 1, 360, 20, 11629), - (5297, 1, 360, 30, 11629), - (5301, 1, 189, 7, 0), - (5302, 1, 189, 8, 0), - (5303, 1, 189, 9, 0), - (5304, 1, 189, 10, 0), - (5305, 1, 189, 11, 0), - (5306, 1, 15, 4, 0), - (5307, 1, 15, 5, 0), - (5308, 1, 15, 6, 0), - (5309, 1, 15, 7, 0), - (5310, 1, 15, 8, 0), - (5317, 1, 114, -43, 0), - (5318, 1, 114, -46, 0), - (5319, 1, 114, -50, 0), - (5320, 1, 218, 11, 0), - (5321, 1, 218, 12, 0), - (5322, 1, 218, 13, 0), - (5323, 1, 218, 14, 0), - (5324, 1, 218, 15, 0), - (5325, 1, 280, 27, 0), - (5326, 1, 280, 34, 0), - (5327, 1, 280, 41, 0), - (5328, 1, 280, 44, 0), - (5329, 1, 280, 47, 0), - (5339, 1, 215, 24, 0), - (5347, 1, 375, 225, 0), - (5348, 1, 375, 230, 0), - (5360, 1, 397, 1300, 0), - (5366, 1, 247, 75, 20), - (5500, 1, 231, 5, 0), - (5501, 1, 231, 7, 0), - (5502, 1, 231, 9, 0), - (5516, 1, 320, 6, 0), - (5517, 1, 320, 7, 0), - (5518, 1, 320, 8, 0), - (5519, 1, 172, 40, 0), - (5520, 1, 172, 41, 0), - (5521, 1, 172, 42, 0), - (5522, 1, 172, 43, 0), - (5523, 1, 172, 44, 0), - (5524, 1, 259, 46, 0), - (5525, 1, 259, 47, 0), - (5526, 1, 259, 48, 0), - (5527, 1, 259, 49, 0), - (5528, 1, 259, 50, 0), - (5529, 1, 339, 11, 12680), - (5529, 2, 138, 1, 0), - (5529, 3, 141, 1, 0), - (5529, 4, 142, 60, 0), - (5529, 5, 137, 0, 0), - (5529, 6, 311, 0, 0), - (5529, 7, 134, 80, 0), - (5529, 8, 139, -265, 0), - (5529, 9, 139, -754, 0), - (5529, 10, 139, -1332, 0), - (5529, 11, 139, -1572, 0), - (5529, 12, 139, -2749, 0), - (5529, 13, 139, -4979, 0), - (5529, 14, 139, -5418, 0), - (5529, 15, 139, -5403, 0), - (5529, 16, 348, 10, 0), - (5530, 1, 339, 13, 12681), - (5530, 2, 138, 1, 0), - (5530, 3, 141, 1, 0), - (5530, 4, 142, 60, 0), - (5530, 5, 137, 0, 0), - (5530, 6, 311, 0, 0), - (5530, 7, 134, 80, 0), - (5530, 8, 139, -265, 0), - (5530, 9, 139, -754, 0), - (5530, 10, 139, -1332, 0), - (5530, 11, 139, -1572, 0), - (5530, 12, 139, -2749, 0), - (5530, 13, 139, -4979, 0), - (5530, 14, 139, -5418, 0), - (5530, 15, 139, -5403, 0), - (5530, 16, 348, 10, 0), - (5531, 1, 339, 15, 12682), - (5531, 2, 138, 1, 0), - (5531, 3, 141, 1, 0), - (5531, 4, 142, 60, 0), - (5531, 5, 137, 0, 0), - (5531, 6, 311, 0, 0), - (5531, 7, 134, 80, 0), - (5531, 8, 139, -265, 0), - (5531, 9, 139, -754, 0), - (5531, 10, 139, -1332, 0), - (5531, 11, 139, -1572, 0), - (5531, 12, 139, -2749, 0), - (5531, 13, 139, -4979, 0), - (5531, 14, 139, -5418, 0), - (5531, 15, 139, -5403, 0), - (5531, 16, 348, 10, 0), - (5532, 1, 339, 17, 12683), - (5532, 2, 138, 1, 0), - (5532, 3, 141, 1, 0), - (5532, 4, 142, 60, 0), - (5532, 5, 137, 0, 0), - (5532, 6, 311, 0, 0), - (5532, 7, 134, 80, 0), - (5532, 8, 139, -265, 0), - (5532, 9, 139, -754, 0), - (5532, 10, 139, -1332, 0), - (5532, 11, 139, -1572, 0), - (5532, 12, 139, -2749, 0), - (5532, 13, 139, -4979, 0), - (5532, 14, 139, -5418, 0), - (5532, 15, 139, -5403, 0), - (5532, 16, 348, 10, 0), - (5533, 1, 339, 19, 12684), - (5533, 2, 138, 1, 0), - (5533, 3, 141, 1, 0), - (5533, 4, 142, 60, 0), - (5533, 5, 137, 0, 0), - (5533, 6, 311, 0, 0), - (5533, 7, 134, 80, 0), - (5533, 8, 139, -265, 0), - (5533, 9, 139, -754, 0), - (5533, 10, 139, -1332, 0), - (5533, 11, 139, -1572, 0), - (5533, 12, 139, -2749, 0), - (5533, 13, 139, -4979, 0), - (5533, 14, 139, -5418, 0), - (5533, 15, 139, -5403, 0), - (5533, 16, 348, 10, 0), - (5534, 1, 266, 18, 0), - (5535, 1, 266, 20, 0), - (5536, 1, 266, 22, 0), - (5542, 1, 330, 110, 0), - (5542, 2, 330, 110, 1), - (5542, 3, 330, 110, 2), - (5542, 4, 330, 110, 3), - (5542, 5, 330, 110, 28), - (5542, 6, 330, 110, 36), - (5542, 7, 330, 110, 77), - (5543, 1, 330, 115, 0), - (5543, 2, 330, 115, 1), - (5543, 3, 330, 115, 2), - (5543, 4, 330, 115, 3), - (5543, 5, 330, 115, 28), - (5543, 6, 330, 115, 36), - (5543, 7, 330, 115, 77), - (5544, 1, 330, 120, 0), - (5544, 2, 330, 120, 1), - (5544, 3, 330, 120, 2), - (5544, 4, 330, 120, 3), - (5544, 5, 330, 120, 28), - (5544, 6, 330, 120, 36), - (5544, 7, 330, 120, 77), - (5545, 1, 330, 110, 0), - (5545, 2, 330, 110, 1), - (5545, 3, 330, 110, 2), - (5545, 4, 330, 110, 3), - (5545, 5, 330, 110, 28), - (5545, 6, 330, 110, 36), - (5546, 1, 330, 115, 0), - (5546, 2, 330, 115, 1), - (5546, 3, 330, 115, 2), - (5546, 4, 330, 115, 3), - (5546, 5, 330, 115, 28), - (5546, 6, 330, 115, 36), - (5547, 1, 330, 120, 0), - (5547, 2, 330, 120, 1), - (5547, 3, 330, 120, 2), - (5547, 4, 330, 120, 3), - (5547, 5, 330, 120, 28), - (5547, 6, 330, 120, 36), - (5548, 1, 330, 110, 0), - (5548, 2, 330, 110, 1), - (5548, 3, 330, 110, 2), - (5548, 4, 330, 110, 3), - (5548, 5, 330, 110, 28), - (5548, 6, 330, 110, 36), - (5548, 7, 330, 110, 77), - (5549, 1, 330, 115, 0), - (5549, 2, 330, 115, 1), - (5549, 3, 330, 115, 2), - (5549, 4, 330, 115, 3), - (5549, 5, 330, 115, 28), - (5549, 6, 330, 115, 36), - (5549, 7, 330, 115, 77), - (5550, 1, 330, 120, 0), - (5550, 2, 330, 120, 1), - (5550, 3, 330, 120, 2), - (5550, 4, 330, 120, 3), - (5550, 5, 330, 120, 28), - (5550, 6, 330, 120, 36), - (5550, 7, 330, 120, 77), - (5551, 1, 330, 85, 0), - (5551, 2, 330, 85, 1), - (5551, 3, 330, 85, 2), - (5551, 4, 330, 85, 3), - (5551, 5, 330, 85, 28), - (5551, 6, 330, 85, 36), - (5551, 7, 330, 85, 77), - (5552, 1, 330, 90, 0), - (5552, 2, 330, 90, 1), - (5552, 3, 330, 90, 2), - (5552, 4, 330, 90, 3), - (5552, 5, 330, 90, 28), - (5552, 6, 330, 90, 36), - (5552, 7, 330, 90, 77), - (5553, 1, 330, 95, 0), - (5553, 2, 330, 95, 1), - (5553, 3, 330, 95, 2), - (5553, 4, 330, 95, 3), - (5553, 5, 330, 95, 28), - (5553, 6, 330, 95, 36), - (5553, 7, 330, 95, 77), - (5554, 1, 278, 700, 44340), - (5554, 2, 440, 71, 100), - (5555, 1, 278, 720, 47230), - (5555, 2, 440, 73, 100), - (5556, 1, 278, 750, 51057), - (5556, 2, 440, 75, 100), - (5557, 1, 341, 110, 0), - (5558, 1, 341, 120, 0), - (5559, 1, 341, 130, 0), - (5560, 1, 341, 140, 0), - (5561, 1, 341, 150, 0), - (5562, 1, 360, 40, 11023), - (5563, 1, 360, 50, 11023), - (5564, 1, 360, 60, 11023), - (5566, 1, 318, 11, 0), - (5567, 1, 318, 12, 0), - (5568, 1, 318, 13, 0), - (5569, 1, 318, 14, 0), - (5570, 1, 318, 15, 0), - (5571, 1, 294, 16, 100), - (5572, 1, 294, 17, 100), - (5573, 1, 294, 18, 100), - (5574, 1, 294, 0, 170), - (5575, 1, 294, 0, 175), - (5576, 1, 294, 0, 180), - (5577, 1, 294, 0, 145), - (5578, 1, 294, 0, 150), - (5579, 1, 294, 0, 155), - (5580, 1, 266, 30, 0), - (5581, 1, 266, 31, 0), - (5582, 1, 266, 32, 0), - (5586, 1, 114, -53, 0), - (5587, 1, 114, -56, 0), - (5588, 1, 114, -59, 0), - (5589, 1, 319, 17, 0), - (5590, 1, 319, 19, 0), - (5591, 1, 319, 21, 0), - (5592, 1, 274, 30, 0), - (5593, 1, 274, 32, 0), - (5594, 1, 274, 34, 0), - (5595, 1, 279, 31, 0), - (5596, 1, 279, 32, 0), - (5597, 1, 279, 33, 0), - (5611, 1, 274, 28, 0), - (5612, 1, 274, 30, 0), - (5613, 1, 274, 32, 0), - (5617, 1, 294, 18, 100), - (5618, 1, 294, 19, 100), - (5619, 1, 294, 20, 100), - (5620, 1, 320, 6, 0), - (5621, 1, 320, 7, 0), - (5622, 1, 320, 8, 0), - (5623, 1, 15, 9, 0), - (5624, 1, 15, 10, 0), - (5625, 1, 15, 11, 0), - (5626, 1, 15, 12, 0), - (5627, 1, 15, 13, 0), - (5628, 1, 114, -53, 0), - (5629, 1, 114, -56, 0), - (5630, 1, 114, -59, 0), - (5729, 1, 218, 11, 0), - (5730, 1, 218, 12, 0), - (5731, 1, 218, 13, 0), - (5732, 1, 218, 14, 0), - (5733, 1, 218, 15, 0), - (5738, 1, 280, 62, 0), - (5739, 1, 280, 63, 0), - (5740, 1, 280, 64, 0), - (5776, 1, 169, 5, -1), - (5777, 1, 169, 10, -1), - (5778, 1, 169, 15, -1), - (5797, 1, 264, 2520, 396), - (5797, 2, 264, 2520, 8504), - (5797, 3, 264, 2520, 8505), - (5798, 1, 264, 2880, 396), - (5798, 2, 264, 2880, 8504), - (5798, 3, 264, 2880, 8505), - (5799, 1, 264, 3240, 396), - (5799, 2, 264, 3240, 8504), - (5799, 3, 264, 3240, 8505), - (5806, 1, 279, 7, 0), - (5807, 1, 279, 11, 0), - (5808, 1, 279, 15, 0), - (5825, 1, 244, -40, 0), - (5850, 1, 287, 2, 1), - (5850, 2, 137, 31, 0), - (5850, 3, 136, 5, 0), - (5860, 1, 243, 40, 0), - (5861, 1, 243, 45, 0), - (5862, 1, 243, 50, 0), - (5880, 1, 287, 8, 0), - (5880, 2, 385, 2754, 1), - (5881, 1, 287, 10, 0), - (5881, 2, 385, 2754, 1), - (5882, 1, 287, 12, 0), - (5882, 2, 385, 2754, 1), - (5883, 2, 139, 2754, 1), - (5886, 1, 274, 12, 0), - (5887, 1, 274, 14, 0), - (5888, 1, 274, 16, 0), - (5889, 1, 280, 51, 0), - (5890, 1, 280, 52, 0), - (5891, 1, 280, 53, 0), - (5909, 1, 279, 29, 0), - (5910, 1, 279, 30, 0), - (5911, 1, 279, 31, 0), - (5912, 1, 279, 32, 0), - (5913, 1, 279, 33, 0), - (5917, 1, 220, 100, 26), - (5917, 2, 220, 100, 30), - (5917, 3, 220, 100, 38), - (5918, 1, 220, 110, 26), - (5918, 2, 220, 110, 30), - (5918, 3, 220, 110, 38), - (5919, 1, 220, 120, 26), - (5919, 2, 220, 120, 30), - (5919, 3, 220, 120, 38), - (5922, 1, 292, 35, 0), - (5923, 1, 292, 40, 0), - (5924, 1, 292, 45, 0), - (5939, 1, 218, 6, 0), - (5940, 1, 218, 7, 0), - (5941, 1, 218, 8, 0), - (5942, 1, 218, 9, 0), - (5943, 1, 218, 10, 0), - (5944, 1, 273, 4, 0), - (5945, 1, 273, 5, 0), - (5946, 1, 273, 6, 0), - (5950, 1, 264, 240, 175), - (5950, 2, 264, 240, 792), - (5951, 1, 264, 300, 175), - (5951, 2, 264, 300, 792), - (5952, 1, 264, 360, 175), - (5952, 2, 264, 360, 792), - (5954, 1, 264, 2400, 68), - (5955, 1, 264, 3000, 68), - (5956, 1, 264, 3600, 68), - (5972, 1, 264, 2880, 6001), - (5972, 2, 264, 2880, 3676), - (5973, 1, 264, 2880, 6000), - (5973, 2, 264, 2880, 87), - (6003, 1, 279, 29, 0), - (6004, 1, 279, 30, 0), - (6005, 1, 279, 31, 0), - (6006, 1, 279, 32, 0), - (6007, 1, 279, 33, 0), - (6011, 1, 216, 95, 0), - (6011, 2, 216, 95, 1), - (6011, 3, 216, 95, 2), - (6011, 4, 216, 95, 3), - (6011, 5, 216, 95, 10), - (6011, 6, 216, 95, 28), - (6011, 7, 216, 95, 30), - (6011, 8, 216, 95, 36), - (6011, 9, 216, 95, 77), - (6012, 1, 216, 100, 0), - (6012, 2, 216, 100, 1), - (6012, 3, 216, 100, 2), - (6012, 4, 216, 100, 3), - (6012, 5, 216, 100, 10), - (6012, 6, 216, 100, 28), - (6012, 7, 216, 100, 30), - (6012, 8, 216, 100, 36), - (6012, 9, 216, 100, 77), - (6013, 1, 216, 105, 0), - (6013, 2, 216, 105, 1), - (6013, 3, 216, 105, 2), - (6013, 4, 216, 105, 3), - (6013, 5, 216, 105, 10), - (6013, 6, 216, 105, 28), - (6013, 7, 216, 105, 30), - (6013, 8, 216, 105, 36), - (6013, 9, 216, 105, 77), - (6014, 1, 360, 40, 12617), - (6015, 1, 360, 50, 12617), - (6016, 1, 360, 60, 12617), - (6017, 1, 217, 0, 65440), - (6017, 2, 346, 72, 28), - (6018, 1, 217, 0, 70880), - (6018, 2, 346, 74, 28), - (6019, 1, 217, 0, 76600), - (6019, 2, 346, 76, 28), - (6020, 1, 220, 15, 21), - (6020, 2, 220, 15, 23), - (6020, 3, 220, 30, 52), - (6020, 4, 220, 15, 28), - (6021, 1, 220, 25, 21), - (6021, 2, 220, 25, 23), - (6021, 3, 220, 50, 52), - (6021, 4, 220, 25, 28), - (6022, 1, 220, 35, 21), - (6022, 2, 220, 35, 23), - (6022, 3, 220, 70, 52), - (6022, 4, 220, 35, 28), - (6023, 1, 278, 900, 66950), - (6023, 2, 440, 82, 100), - (6024, 1, 278, 900, 70230), - (6024, 2, 440, 84, 100), - (6025, 1, 278, 900, 74935), - (6025, 2, 440, 86, 100), - (6026, 1, 127, 10, 0), - (6026, 2, 139, 16106, 0), - (6027, 1, 127, 25, 0), - (6027, 2, 139, 16106, 0), - (6028, 1, 127, 50, 0), - (6028, 2, 139, 16106, 0), - (6029, 1, 216, 200, 8), - (6030, 1, 216, 250, 8), - (6031, 1, 216, 300, 8), - (6032, 1, 439, 0, 70880), - (6032, 2, 345, 68, 50), - (6033, 1, 439, 0, 76600), - (6033, 2, 345, 70, 50), - (6034, 1, 439, 0, 82600), - (6034, 2, 345, 72, 35), - (6035, 1, 258, 48, 0), - (6036, 1, 258, 51, 0), - (6037, 1, 258, 54, 0), - (6042, 1, 220, 70, 8), - (6043, 1, 220, 80, 8), - (6044, 1, 220, 100, 8), - (6045, 1, 220, 45, 21), - (6045, 2, 220, 45, 23), - (6045, 3, 220, 90, 52), - (6045, 4, 220, 45, 28), - (6046, 1, 220, 55, 21), - (6046, 2, 220, 55, 23), - (6046, 3, 220, 110, 52), - (6046, 4, 220, 55, 28), - (6047, 1, 220, 65, 21), - (6047, 2, 220, 65, 23), - (6047, 3, 220, 130, 52), - (6047, 4, 220, 65, 28), - (6048, 1, 220, 75, 21), - (6048, 2, 220, 75, 23), - (6048, 3, 220, 150, 52), - (6048, 4, 220, 75, 28), - (6049, 1, 220, 85, 21), - (6049, 2, 220, 85, 23), - (6049, 3, 220, 170, 52), - (6049, 4, 220, 85, 28), - (6050, 1, 220, 95, 21), - (6050, 2, 220, 95, 23), - (6050, 3, 220, 190, 52), - (6050, 4, 220, 95, 28), - (6051, 1, 213, 1, 0), - (6052, 1, 213, 3, 0), - (6053, 1, 213, 5, 0), - (6057, 1, 220, 105, 21), - (6057, 2, 220, 105, 23), - (6057, 3, 220, 210, 52), - (6057, 4, 220, 105, 28), - (6058, 1, 220, 115, 21), - (6058, 2, 220, 115, 23), - (6058, 3, 220, 230, 52), - (6058, 4, 220, 115, 28), - (6059, 1, 220, 125, 21), - (6059, 2, 220, 125, 23), - (6059, 3, 220, 250, 52), - (6059, 4, 220, 125, 28), - (6060, 1, 247, 5, 76), - (6061, 1, 247, 10, 76), - (6063, 1, 303, 4500, 4500), - (6063, 2, 139, 2766, 0), - (6064, 1, 303, 5000, 5000), - (6064, 2, 139, 2766, 0), - (6065, 1, 303, 5500, 5500), - (6065, 2, 139, 2766, 0), - (6066, 1, 85, 12629, 0), - (6067, 1, 85, 12630, 0), - (6068, 1, 85, 12631, 0), - (6069, 1, 85, 12632, 0), - (6070, 1, 85, 12633, 0), - (6071, 1, 85, 12634, 0), - (6072, 1, 302, 266, 266), - (6072, 2, 385, 99, 0), - (6073, 1, 302, 290, 290), - (6073, 2, 385, 99, 0), - (6074, 1, 302, 310, 310), - (6074, 2, 385, 99, 0), - (6075, 1, 59, -18, 0), - (6076, 1, 59, -21, 0), - (6077, 1, 59, -24, 0), - (6078, 1, 59, -27, 0), - (6079, 1, 59, -30, 0), - (6080, 1, 189, 12, 0), - (6081, 1, 189, 13, 0), - (6082, 1, 247, 50, 20), - (6083, 1, 247, 75, 20), - (6084, 1, 247, 100, 20), - (6085, 1, 292, 20, 0), - (6086, 1, 292, 30, 0), - (6087, 1, 292, 40, 0), - (6088, 1, 264, 180, 392), - (6089, 1, 264, 360, 392), - (6090, 1, 264, 540, 392), - (6112, 1, 131, 10, 10), - (6112, 2, 348, 10, 0), - (6112, 3, 137, -32, 0), - (6113, 1, 287, 2, 0), - (6113, 2, 137, 100, 0), - (6113, 3, 385, -4232, 0), - (6113, 4, 385, -4332, 0), - (6113, 5, 139, -2741, 0), - (6113, 6, 385, -16192, 0), - (6113, 7, 139, -16843, 0), - (6114, 1, 287, 3, 0), - (6114, 2, 137, 100, 0), - (6114, 3, 385, -4232, 0), - (6114, 4, 385, -4332, 0), - (6114, 5, 139, -2741, 0), - (6114, 6, 385, -16192, 0), - (6114, 7, 139, -16843, 0), - (6115, 1, 287, 4, 0), - (6115, 2, 137, 100, 0), - (6115, 3, 385, -4232, 0), - (6115, 4, 385, -4332, 0), - (6115, 5, 139, -2741, 0), - (6115, 6, 385, -16192, 0), - (6115, 7, 139, -16843, 0), - (6119, 1, 69, 100, 0), - (6120, 1, 69, 200, 0), - (6121, 1, 69, 300, 0), - (6122, 1, 69, 400, 0), - (6123, 1, 69, 500, 0), - (6124, 1, 320, 1, 0), - (6125, 1, 320, 3, 0), - (6126, 1, 320, 5, 0), - (6127, 1, 320, 6, 0), - (6128, 1, 320, 7, 0), - (6129, 1, 320, 8, 0), - (6130, 1, 255, 48, 0), - (6131, 1, 255, 60, 0), - (6132, 1, 255, 72, 0), - (6136, 1, 264, 360, 300), - (6202, 1, 247, 10, 35), - (6203, 1, 247, 20, 35), - (6204, 1, 247, 60, 35), - (6209, 1, 264, 720, 245), - (6210, 1, 264, 1440, 245), - (6211, 1, 264, 2160, 245), - (6215, 1, 247, 5, 76), - (6216, 1, 247, 10, 76), - (6217, 1, 247, 15, 76), - (6223, 1, 232, 11, 4544), - (6224, 1, 232, 12, 4544), - (6225, 1, 232, 13, 4544), - (6226, 1, 232, 14, 4544), - (6227, 1, 232, 15, 4544), - (6228, 1, 264, 120, 404), - (6229, 1, 264, 240, 404), - (6230, 1, 264, 360, 404), - (6231, 1, 264, 480, 404), - (6233, 1, 264, 1728, 43), - (6234, 1, 264, 2160, 43), - (6235, 1, 264, 2592, 43), - (6236, 1, 287, 1, 0), - (6236, 2, 137, 3, 0), - (6236, 3, 137, 99, 0), - (6236, 4, 138, 0, 0), - (6236, 5, 244, 50, 0), - (6237, 1, 287, 2, 0), - (6237, 2, 137, 3, 0), - (6237, 3, 137, 99, 0), - (6237, 4, 138, 0, 0), - (6237, 5, 244, 38, 0), - (6238, 1, 287, 3, 0), - (6238, 2, 137, 3, 0), - (6238, 3, 137, 99, 0), - (6238, 4, 138, 0, 0), - (6238, 5, 244, 25, 0), - (6240, 1, 273, 3, 0), - (6241, 1, 273, 6, 0), - (6242, 1, 273, 9, 0), - (6243, 1, 273, 12, 0), - (6244, 1, 273, 15, 0), - (6245, 1, 273, 18, 0), - (6249, 1, 310, 1000, 0), - (6249, 2, 139, 11903, 0), - (6249, 3, 310, 1000, 0), - (6249, 4, 139, 11904, 0), - (6249, 5, 310, 1000, 0), - (6249, 6, 139, 11905, 0), - (6249, 7, 310, 1000, 0), - (6249, 8, 139, 1362, 0), - (6249, 9, 310, 1000, 0), - (6249, 10, 139, 8032, 0), - (6249, 11, 310, 1000, 0), - (6249, 12, 385, 6131, 0), - (6249, 13, 385, 6231, 0), - (6249, 14, 385, 6331, 0), - (6249, 15, 385, 6431, 0), - (6249, 16, 385, 6531, 0), - (6249, 17, 385, 6631, 0), - (6250, 1, 310, 2000, 0), - (6250, 2, 139, 11903, 0), - (6250, 3, 310, 2000, 0), - (6250, 4, 139, 11904, 0), - (6250, 5, 310, 2000, 0), - (6250, 6, 139, 11905, 0), - (6250, 7, 310, 2000, 0), - (6250, 8, 139, 1362, 0), - (6250, 9, 310, 2000, 0), - (6250, 10, 139, 8032, 0), - (6250, 11, 310, 2000, 0), - (6250, 12, 385, 6131, 0), - (6250, 13, 385, 6231, 0), - (6250, 14, 385, 6331, 0), - (6250, 15, 385, 6431, 0), - (6250, 16, 385, 6531, 0), - (6250, 17, 385, 6631, 0), - (6251, 1, 310, 3000, 0), - (6251, 2, 139, 11903, 0), - (6251, 3, 310, 3000, 0), - (6251, 4, 139, 11904, 0), - (6251, 5, 310, 3000, 0), - (6251, 6, 139, 11905, 0), - (6251, 7, 310, 3000, 0), - (6251, 8, 139, 1362, 0), - (6251, 9, 310, 3000, 0), - (6251, 10, 139, 8032, 0), - (6251, 11, 310, 3000, 0), - (6251, 12, 385, 6131, 0), - (6251, 13, 385, 6231, 0), - (6251, 14, 385, 6331, 0), - (6251, 15, 385, 6431, 0), - (6251, 16, 385, 6531, 0), - (6251, 17, 385, 6631, 0), - (6252, 1, 310, 4000, 0), - (6252, 2, 139, 11903, 0), - (6252, 3, 310, 4000, 0), - (6252, 4, 139, 11904, 0), - (6252, 5, 310, 4000, 0), - (6252, 6, 139, 11905, 0), - (6252, 7, 310, 4000, 0), - (6252, 8, 139, 1362, 0), - (6252, 9, 310, 4000, 0), - (6252, 10, 139, 8032, 0), - (6252, 11, 310, 4000, 0), - (6252, 12, 385, 6131, 0), - (6252, 13, 385, 6231, 0), - (6252, 14, 385, 6331, 0), - (6252, 15, 385, 6431, 0), - (6252, 16, 385, 6531, 0), - (6252, 17, 385, 6631, 0), - (6253, 1, 310, 5000, 0), - (6253, 2, 139, 11903, 0), - (6253, 3, 310, 5000, 0), - (6253, 4, 139, 11904, 0), - (6253, 5, 310, 5000, 0), - (6253, 6, 139, 11905, 0), - (6253, 7, 310, 5000, 0), - (6253, 8, 139, 1362, 0), - (6253, 9, 310, 5000, 0), - (6253, 10, 139, 8032, 0), - (6253, 11, 310, 5000, 0), - (6253, 12, 385, 6131, 0), - (6253, 13, 385, 6231, 0), - (6253, 14, 385, 6331, 0), - (6253, 15, 385, 6431, 0), - (6253, 16, 385, 6531, 0), - (6253, 17, 385, 6631, 0), - (6257, 1, 128, 5, 5), - (6257, 2, 138, 1, 0), - (6257, 3, 140, 1, 0), - (6257, 4, 139, -2741, 0), - (6257, 5, 139, -16843, 0), - (6257, 6, 385, -16192, 0), - (6258, 1, 128, 15, 15), - (6258, 2, 138, 1, 0), - (6258, 3, 140, 1, 0), - (6258, 4, 139, -2741, 0), - (6258, 5, 139, -16843, 0), - (6258, 6, 385, -16192, 0), - (6259, 1, 128, 30, 30), - (6259, 2, 138, 1, 0), - (6259, 3, 140, 1, 0), - (6259, 4, 139, -2741, 0), - (6259, 5, 139, -16843, 0), - (6259, 6, 385, -16192, 0), - (6260, 1, 264, 720, 98), - (6261, 1, 264, 900, 98), - (6262, 1, 264, 1080, 98), - (6266, 1, 224, 20, 10), - (6266, 2, 173, 1, 0), - (6267, 1, 224, 35, 10), - (6267, 2, 173, 2, 0), - (6268, 1, 224, 50, 10), - (6268, 2, 173, 3, 0), - (6269, 1, 224, 20, 30), - (6269, 2, 173, 1, 0), - (6270, 1, 224, 35, 30), - (6270, 2, 173, 2, 0), - (6271, 1, 224, 50, 30), - (6271, 2, 173, 3, 0), - (6272, 1, 264, 15, 672), - (6273, 1, 264, 30, 672), - (6274, 1, 264, 45, 672), - (6275, 1, 224, 20, 8), - (6275, 2, 173, 1, 0), - (6276, 1, 224, 35, 8), - (6276, 2, 173, 2, 0), - (6277, 1, 224, 50, 8), - (6277, 2, 173, 3, 0), - (6283, 1, 85, 13200, 0), - (6284, 1, 85, 13200, 25), - (6285, 1, 85, 13200, 50), - (6287, 1, 224, 20, 30), - (6287, 2, 173, 1, 0), - (6288, 1, 224, 35, 30), - (6288, 2, 173, 3, 0), - (6289, 1, 224, 50, 30), - (6289, 2, 173, 3, 0), - (6300, 1, 247, 20, 76), - (6301, 1, 247, 25, 76), - (6302, 1, 264, 120, 3710), - (6303, 1, 264, 240, 3710), - (6304, 1, 264, 360, 3710), - (6319, 1, 264, 1728, 107), - (6320, 1, 264, 2160, 107), - (6321, 1, 264, 2592, 107), - (6322, 1, 216, 5, 51), - (6323, 1, 216, 15, 51), - (6324, 1, 216, 25, 51), - (6331, 1, 252, 70, 0), - (6332, 1, 252, 75, 0), - (6334, 1, 185, 5, 51), - (6335, 1, 185, 10, 51), - (6336, 1, 185, 15, 51), - (6337, 1, 264, 60, 553), - (6338, 1, 264, 120, 553), - (6339, 1, 264, 180, 553), - (6340, 1, 264, 180, 777), - (6341, 1, 264, 360, 777), - (6342, 1, 264, 540, 777), - (6343, 1, 264, 5, 468), - (6343, 2, 264, 5, 469), - (6343, 3, 264, 5, 470), - (6344, 1, 264, 10, 468), - (6344, 2, 264, 10, 469), - (6344, 3, 264, 10, 470), - (6345, 1, 264, 15, 468), - (6345, 2, 264, 15, 469), - (6345, 3, 264, 15, 470), - (6346, 1, 264, 180, 494), - (6347, 1, 264, 360, 494), - (6348, 1, 264, 540, 494), - (6349, 1, 264, 180, 500), - (6350, 1, 264, 360, 500), - (6351, 1, 264, 540, 500), - (6355, 1, 310, 360000, 0), - (6355, 2, 139, 4506, 0), - (6355, 3, 310, 360000, 0), - (6355, 4, 385, 11122, 0), - (6355, 5, 385, 11222, 0), - (6355, 6, 385, 11322, 0), - (6355, 7, 385, 11522, 0), - (6356, 1, 310, 720000, 0), - (6356, 2, 139, 4506, 0), - (6356, 3, 310, 720000, 0), - (6356, 4, 385, 11122, 0), - (6356, 5, 385, 11222, 0), - (6356, 6, 385, 11322, 0), - (6356, 7, 385, 11522, 0), - (6357, 1, 310, 1080000, 0), - (6357, 2, 139, 4506, 0), - (6357, 3, 310, 1080000, 0), - (6357, 4, 385, 11122, 0), - (6357, 5, 385, 11222, 0), - (6357, 6, 385, 11322, 0), - (6357, 7, 385, 11522, 0), - (6358, 1, 310, 1440000, 0), - (6358, 2, 139, 4506, 0), - (6358, 3, 310, 1440000, 0), - (6358, 4, 385, 11122, 0), - (6358, 5, 385, 11222, 0), - (6358, 6, 385, 11322, 0), - (6358, 7, 385, 11522, 0), - (6359, 1, 310, 1800000, 0), - (6359, 2, 139, 4506, 0), - (6359, 3, 310, 1800000, 0), - (6359, 4, 385, 11122, 0), - (6359, 5, 385, 11222, 0), - (6359, 6, 385, 11322, 0), - (6359, 7, 385, 11522, 0), - (6360, 1, 310, 2160000, 0), - (6360, 2, 139, 4506, 0), - (6360, 3, 310, 2160000, 0), - (6360, 4, 385, 11122, 0), - (6360, 5, 385, 11222, 0), - (6360, 6, 385, 11322, 0), - (6360, 7, 385, 11522, 0), - (6361, 1, 213, 3, 0), - (6362, 1, 310, 120000, 0), - (6362, 2, 139, 5040, 0), - (6363, 1, 310, 240000, 0), - (6363, 2, 139, 5040, 0), - (6364, 1, 310, 360000, 0), - (6364, 2, 139, 5040, 0), - (6365, 1, 310, 480000, 0), - (6365, 2, 139, 5040, 0), - (6366, 1, 310, 600000, 0), - (6366, 2, 139, 5040, 0), - (6375, 1, 375, 107, 0), - (6376, 1, 375, 115, 0), - (6377, 1, 375, 125, 0), - (6383, 1, 215, 5, 0), - (6384, 1, 215, 7, 0), - (6385, 1, 215, 10, 0), - (6386, 1, 293, 5, 0), - (6387, 1, 293, 10, 0), - (6388, 1, 293, 15, 0), - (6389, 1, 293, 20, 0), - (6390, 1, 0, 16, 0), - (6391, 1, 0, 17, 0), - (6392, 1, 0, 18, 0), - (6393, 1, 0, 19, 0), - (6394, 1, 0, 20, 0), - (6395, 1, 85, 13502, 0), - (6396, 1, 85, 13503, 0), - (6397, 1, 85, 13504, 0), - (6403, 1, 294, 11, 100), - (6404, 1, 294, 13, 100), - (6405, 1, 294, 15, 100), - (6406, 1, 360, 25, 13201), - (6407, 1, 360, 25, 13202), - (6408, 1, 360, 25, 13203), - (6409, 1, 247, 5, 76), - (6410, 1, 247, 10, 76), - (6411, 1, 247, 15, 76), - (6412, 1, 247, 20, 76), - (6413, 1, 247, 25, 76), - (6414, 1, 247, 30, 76), - (6415, 1, 247, 35, 76), - (6416, 1, 247, 40, 76), - (6417, 1, 247, 45, 76), - (6418, 1, 247, 50, 76), - (6419, 1, 247, 5, 76), - (6420, 1, 247, 10, 76), - (6421, 1, 247, 15, 76), - (6422, 1, 214, 100, 0), - (6423, 1, 214, 200, 0), - (6424, 1, 214, 300, 0), - (6428, 1, 320, 1, 0), - (6429, 1, 320, 3, 0), - (6430, 1, 320, 5, 0), - (6431, 1, 317, 6, 0), - (6432, 1, 317, 7, 0), - (6433, 1, 317, 8, 0), - (6434, 1, 317, 9, 0), - (6435, 1, 317, 10, 0), - (6436, 1, 244, 70, 0), - (6437, 1, 244, 60, 0), - (6438, 1, 244, 50, 0), - (6439, 1, 264, 720, 41), - (6440, 1, 264, 900, 41), - (6441, 1, 264, 840, 420), - (6442, 1, 264, 540, 362), - (6443, 1, 264, 630, 362), - (6445, 1, 127, 15, 0), - (6445, 2, 139, 3248, 0), - (6445, 3, 127, 15, 0), - (6445, 4, 139, 3249, 0), - (6446, 1, 127, 30, 0), - (6446, 2, 139, 3248, 0), - (6446, 3, 127, 30, 0), - (6446, 4, 139, 3249, 0), - (6447, 1, 127, 50, 0), - (6447, 2, 139, 3248, 0), - (6447, 3, 127, 50, 0), - (6447, 4, 139, 3249, 0), - (6452, 1, 310, 1000, 0), - (6452, 2, 403, 7, 0), - (6452, 3, 404, 35, 0), - (6452, 4, 144, 2000, 0), - (6452, 5, 310, 5000, 0), - (6452, 6, 403, 7, 0), - (6452, 7, 404, 35, 0), - (6452, 8, 144, 10000, 0), - (6453, 1, 310, 2000, 0), - (6453, 2, 403, 7, 0), - (6453, 3, 404, 35, 0), - (6453, 4, 144, 2000, 0), - (6453, 5, 310, 10000, 0), - (6453, 6, 403, 7, 0), - (6453, 7, 404, 35, 0), - (6453, 8, 144, 10000, 0), - (6454, 1, 310, 3000, 0), - (6454, 2, 403, 7, 0), - (6454, 3, 404, 35, 0), - (6454, 4, 144, 2000, 0), - (6454, 5, 310, 15000, 0), - (6454, 6, 403, 7, 0), - (6454, 7, 404, 35, 0), - (6454, 8, 144, 10000, 0), - (6458, 1, 310, 30000, 0), - (6458, 2, 385, 5137, 0), - (6458, 3, 385, 5237, 0), - (6458, 4, 385, 5337, 0), - (6458, 5, 385, 5437, 0), - (6458, 6, 385, 5537, 0), - (6458, 7, 385, 5637, 0), - (6458, 8, 127, 15, 15), - (6458, 9, 385, 5137, 0), - (6458, 10, 385, 5237, 0), - (6458, 11, 385, 5337, 0), - (6458, 12, 385, 5437, 0), - (6458, 13, 385, 5537, 0), - (6458, 14, 385, 5637, 0), - (6459, 1, 310, 60000, 0), - (6459, 2, 385, 5137, 0), - (6459, 3, 385, 5237, 0), - (6459, 4, 385, 5337, 0), - (6459, 5, 385, 5437, 0), - (6459, 6, 385, 5537, 0), - (6459, 7, 385, 5637, 0), - (6459, 8, 127, 30, 30), - (6459, 9, 385, 5137, 0), - (6459, 10, 385, 5237, 0), - (6459, 11, 385, 5337, 0), - (6459, 12, 385, 5437, 0), - (6459, 13, 385, 5537, 0), - (6459, 14, 385, 5637, 0), - (6460, 1, 310, 90000, 0), - (6460, 2, 385, 5137, 0), - (6460, 3, 385, 5237, 0), - (6460, 4, 385, 5337, 0), - (6460, 5, 385, 5437, 0), - (6460, 6, 385, 5537, 0), - (6460, 7, 385, 5637, 0), - (6460, 8, 127, 50, 50), - (6460, 9, 385, 5137, 0), - (6460, 10, 385, 5237, 0), - (6460, 11, 385, 5337, 0), - (6460, 12, 385, 5437, 0), - (6460, 13, 385, 5537, 0), - (6460, 14, 385, 5637, 0), - (6461, 1, 127, 15, 0), - (6461, 2, 385, 14130, 0), - (6461, 3, 385, 14230, 0), - (6461, 4, 385, 14330, 0), - (6461, 5, 385, 14430, 0), - (6461, 6, 385, 14530, 0), - (6461, 7, 385, 14630, 0), - (6461, 8, 310, 30000, 0), - (6461, 9, 385, 14130, 0), - (6461, 10, 385, 14230, 0), - (6461, 11, 385, 14330, 0), - (6461, 12, 385, 14430, 0), - (6461, 13, 385, 14530, 0), - (6461, 14, 385, 14630, 0), - (6462, 1, 127, 30, 0), - (6462, 2, 385, 14130, 0), - (6462, 3, 385, 14230, 0), - (6462, 4, 385, 14330, 0), - (6462, 5, 385, 14430, 0), - (6462, 6, 385, 14530, 0), - (6462, 7, 385, 14630, 0), - (6462, 8, 310, 60000, 0), - (6462, 9, 385, 14130, 0), - (6462, 10, 385, 14230, 0), - (6462, 11, 385, 14330, 0), - (6462, 12, 385, 14430, 0), - (6462, 13, 385, 14530, 0), - (6462, 14, 385, 14630, 0), - (6463, 1, 127, 50, 0), - (6463, 2, 385, 14130, 0), - (6463, 3, 385, 14230, 0), - (6463, 4, 385, 14330, 0), - (6463, 5, 385, 14430, 0), - (6463, 6, 385, 14530, 0), - (6463, 7, 385, 14630, 0), - (6463, 8, 310, 90000, 0), - (6463, 9, 385, 14130, 0), - (6463, 10, 385, 14230, 0), - (6463, 11, 385, 14330, 0), - (6463, 12, 385, 14430, 0), - (6463, 13, 385, 14530, 0), - (6463, 14, 385, 14630, 0), - (6467, 1, 214, 100, 0), - (6468, 1, 214, 200, 0), - (6469, 1, 214, 300, 0), - (6470, 1, 247, 15, 76), - (6471, 1, 247, 20, 76), - (6472, 1, 247, 30, 76), - (6473, 1, 247, 35, 76), - (6474, 1, 247, 55, 76), - (6475, 1, 247, 60, 76), - (6476, 1, 247, 20, 76), - (6477, 1, 247, 25, 76), - (6478, 1, 264, 1, 3800), - (6479, 1, 264, 2, 3800), - (6480, 1, 264, 3, 3800), - (6481, 1, 264, 6480, 36), - (6482, 1, 264, 12960, 36), - (6483, 1, 264, 19440, 36), - (6484, 1, 264, 105, 558), - (6485, 1, 264, 120, 558), - (6486, 1, 264, 135, 558), - (6489, 1, 310, 600000, 0), - (6489, 2, 139, 4500, 0), - (6489, 3, 411, 8, 0), - (6490, 1, 310, 1200000, 0), - (6490, 2, 139, 4500, 0), - (6490, 3, 411, 8, 0), - (6491, 1, 310, 1800000, 0), - (6491, 2, 139, 4500, 0), - (6491, 3, 411, 8, 0), - (6500, 1, 273, 5, 0), - (6501, 1, 273, 6, 0), - (6502, 1, 273, 7, 0), - (6503, 1, 127, 12, 0), - (6503, 2, 385, 3338, 0), - (6504, 1, 127, 24, 0), - (6504, 2, 385, 3338, 0), - (6505, 1, 127, 36, 0), - (6505, 2, 385, 3338, 0), - (6506, 1, 127, 50, 0), - (6506, 2, 385, 3338, 0), - (6511, 1, 216, 5, 7), - (6512, 1, 216, 15, 7), - (6513, 1, 216, 25, 7), - (6514, 1, 127, 15, 0), - (6514, 2, 139, 5880, 0), - (6515, 1, 127, 30, 0), - (6515, 2, 139, 5880, 0), - (6516, 1, 127, 50, 0), - (6516, 2, 139, 5880, 0), - (6517, 1, 339, 10, 8105), - (6517, 2, 142, 65, 0), - (6517, 3, 311, 0, 0), - (6517, 4, 134, 70, 0), - (6517, 5, 348, 10, 0), - (6517, 6, 137, 0, 0), - (6517, 7, 339, 10, 8105), - (6517, 8, 142, 65, 0), - (6517, 9, 311, 0, 0), - (6517, 10, 134, 70, 0), - (6517, 11, 348, 10, 0), - (6517, 12, 137, 100, 0), - (6517, 13, 339, 10, 8105), - (6517, 14, 142, 65, 0), - (6517, 15, 311, 0, 0), - (6517, 16, 134, 70, 0), - (6517, 17, 348, 10, 0), - (6517, 18, 137, 79, 0), - (6517, 19, 339, 10, 8105), - (6517, 20, 142, 65, 0), - (6517, 21, 311, 0, 0), - (6517, 22, 134, 70, 0), - (6517, 23, 348, 10, 0), - (6517, 24, 137, 147, 0), - (6517, 25, 339, 10, 11404), - (6517, 26, 142, 71, 0), - (6517, 27, 311, 0, 0), - (6517, 28, 134, 75, 0), - (6517, 29, 348, 10, 0), - (6517, 30, 137, 0, 0), - (6517, 31, 339, 10, 11404), - (6517, 32, 142, 71, 0), - (6517, 33, 311, 0, 0), - (6517, 34, 134, 75, 0), - (6517, 35, 348, 10, 0), - (6517, 36, 137, 100, 0), - (6517, 37, 339, 10, 11404), - (6517, 38, 142, 71, 0), - (6517, 39, 311, 0, 0), - (6517, 40, 134, 75, 0), - (6517, 41, 348, 10, 0), - (6517, 42, 137, 79, 0), - (6517, 43, 339, 10, 11404), - (6517, 44, 142, 71, 0), - (6517, 45, 311, 0, 0), - (6517, 46, 134, 75, 0), - (6517, 47, 348, 10, 0), - (6517, 48, 137, 147, 0), - (6517, 49, 339, 10, 13199), - (6517, 50, 142, 76, 0), - (6517, 51, 311, 0, 0), - (6517, 52, 134, 80, 0), - (6517, 53, 348, 10, 0), - (6517, 54, 137, 0, 0), - (6517, 55, 339, 10, 13199), - (6517, 56, 142, 76, 0), - (6517, 57, 311, 0, 0), - (6517, 58, 134, 80, 0), - (6517, 59, 348, 10, 0), - (6517, 60, 137, 100, 0), - (6517, 61, 339, 10, 13199), - (6517, 62, 142, 76, 0), - (6517, 63, 311, 0, 0), - (6517, 64, 134, 80, 0), - (6517, 65, 348, 10, 0), - (6517, 66, 137, 79, 0), - (6517, 67, 339, 10, 13199), - (6517, 68, 142, 76, 0), - (6517, 69, 311, 0, 0), - (6517, 70, 134, 80, 0), - (6517, 71, 348, 10, 0), - (6517, 72, 137, 147, 0), - (6518, 1, 221, 18, 0), - (6519, 1, 221, 21, 0), - (6520, 1, 221, 24, 0), - (6521, 1, 327, 6, 0), - (6522, 1, 327, 7, 0), - (6523, 1, 328, 800, 0), - (6524, 1, 328, 850, 0), - (6525, 1, 328, 900, 0), - (6526, 1, 328, 950, 0), - (6527, 1, 328, 1000, 0), - (6528, 1, 264, 3024, 107), - (6531, 1, 360, 40, 11629), - (6532, 1, 360, 50, 11629), - (6533, 1, 360, 60, 11629), - (6540, 1, 363, 2, 0), - (6545, 1, 362, 2, 0), - (6546, 1, 2, 4, 0), - (6547, 1, 2, 8, 0), - (6548, 1, 2, 12, 0), - (6549, 1, 2, 16, 0), - (6550, 1, 2, 20, 0), - (6551, 1, 2, 24, 0), - (6552, 1, 2, 28, 0), - (6553, 1, 2, 32, 0), - (6554, 1, 2, 36, 0), - (6555, 1, 2, 40, 0), - (6556, 1, 2, 44, 0), - (6557, 1, 2, 48, 0), - (6558, 1, 2, 52, 0), - (6559, 1, 2, 56, 0), - (6560, 1, 2, 60, 0), - (6561, 1, 2, 64, 0), - (6562, 1, 2, 68, 0), - (6563, 1, 2, 72, 0), - (6564, 1, 2, 76, 0), - (6565, 1, 2, 80, 0), - (6566, 1, 2, 84, 0), - (6567, 1, 2, 88, 0), - (6568, 1, 2, 92, 0), - (6569, 1, 2, 96, 0), - (6570, 1, 2, 100, 0), - (6571, 1, 2, 104, 0), - (6601, 1, 339, 5, 13519), - (6601, 2, 137, 21, 0), - (6602, 1, 339, 10, 13519), - (6602, 2, 137, 21, 0), - (6603, 1, 339, 15, 13519), - (6603, 2, 137, 21, 0), - (6604, 1, 339, 20, 13519), - (6604, 2, 137, 21, 0), - (6605, 1, 339, 25, 13519), - (6605, 2, 137, 21, 0), - (6611, 1, 310, 120000, 0), - (6611, 2, 139, 4670, 0), - (6612, 1, 310, 240000, 0), - (6612, 2, 139, 4670, 0), - (6613, 1, 310, 360000, 0), - (6613, 2, 139, 4670, 0), - (6614, 1, 310, 120000, 0), - (6614, 2, 139, 4674, 0), - (6615, 1, 310, 240000, 0), - (6615, 2, 139, 4674, 0), - (6616, 1, 310, 360000, 0), - (6616, 2, 139, 4674, 0), - (6618, 1, 310, 480000, 0), - (6618, 2, 139, 4670, 0), - (6619, 1, 310, 600000, 0), - (6619, 2, 139, 4670, 0), - (6630, 1, 218, 1, 0), - (6631, 1, 218, 2, 0), - (6632, 1, 218, 3, 0), - (6633, 1, 218, 4, 0), - (6634, 1, 218, 5, 0), - (6636, 1, 294, 0, 107), - (6637, 1, 294, 0, 115), - (6638, 1, 294, 0, 125), - (6641, 1, 339, 10, 16101), - (6641, 2, 138, 0, 0), - (6641, 3, 142, 70, 0), - (6641, 4, 403, 4, 0), - (6641, 5, 348, 1, 0), - (6641, 6, 404, 2, 0), - (6641, 7, 141, 1, 0), - (6642, 1, 339, 10, 16102), - (6642, 2, 138, 0, 0), - (6642, 3, 142, 70, 0), - (6642, 4, 403, 4, 0), - (6642, 5, 348, 1, 0), - (6642, 6, 404, 2, 0), - (6642, 7, 141, 1, 0), - (6643, 1, 339, 10, 16103), - (6643, 2, 138, 0, 0), - (6643, 3, 142, 70, 0), - (6643, 4, 403, 4, 0), - (6643, 5, 348, 1, 0), - (6643, 6, 404, 2, 0), - (6643, 7, 141, 1, 0), - (6660, 1, 325, 55, 0), - (6661, 1, 325, 60, 0), - (6662, 1, 325, 65, 0), - (6666, 1, 287, 2, 0), - (6666, 2, 139, 8001, 0), - (6666, 3, 385, 12529, 0), - (6667, 1, 287, 4, 0), - (6667, 2, 139, 8001, 0), - (6667, 3, 385, 12529, 0), - (6668, 1, 287, 2, 0), - (6668, 2, 139, 11251, 0), - (6668, 3, 139, 11252, 0), - (6668, 4, 139, 11253, 0), - (6669, 1, 287, 4, 0), - (6669, 2, 139, 11251, 0), - (6669, 3, 139, 11252, 0), - (6669, 4, 139, 11253, 0), - (6670, 1, 287, 6, 0), - (6670, 2, 139, 11251, 0), - (6670, 3, 139, 11252, 0), - (6670, 4, 139, 11253, 0), - (6697, 1, 264, 30, 857), - (6698, 1, 264, 60, 857), - (6699, 1, 264, 90, 857), - (6700, 1, 264, 120, 857), - (6701, 1, 264, 150, 857), - (6703, 1, 264, 10, 171), - (6704, 1, 264, 20, 171), - (6705, 1, 264, 30, 171), - (6709, 1, 127, 5, 0), - (6709, 2, 139, 3842, 0), - (6710, 1, 127, 10, 0), - (6710, 2, 139, 3842, 0), - (6711, 1, 127, 15, 0), - (6711, 2, 139, 3842, 0), - (6712, 1, 264, 30, 177), - (6713, 1, 264, 60, 177), - (6714, 1, 264, 90, 177), - (6715, 1, 264, 120, 177), - (6716, 1, 264, 150, 177), - (6751, 1, 310, 240000, 0), - (6751, 2, 139, 4519, 0), - (6752, 1, 310, 480000, 0), - (6752, 2, 139, 4519, 0), - (6753, 1, 310, 720000, 0), - (6753, 2, 139, 4519, 0), - (6761, 1, 292, 5, 0), - (6762, 1, 292, 10, 0), - (6763, 1, 292, 15, 0), - (6765, 1, 330, 15, 7), - (6766, 1, 330, 30, 7), - (6767, 1, 330, 50, 7), - (6768, 1, 310, 960000, 0), - (6768, 2, 139, 4519, 0), - (6769, 1, 310, 1200000, 0), - (6769, 2, 139, 4519, 0), - (6791, 1, 339, 20, 16139), - (6791, 2, 137, 21, 0), - (6791, 3, 385, -18000, 0), - (6791, 4, 339, 20, 16139), - (6791, 5, 137, 343, 0), - (6791, 6, 385, -18000, 0), - (6792, 1, 339, 20, 16140), - (6792, 2, 137, 21, 0), - (6792, 3, 385, -18000, 0), - (6792, 4, 339, 20, 16140), - (6792, 5, 137, 343, 0), - (6792, 6, 385, -18000, 0), - (6793, 1, 339, 20, 16141), - (6793, 2, 137, 21, 0), - (6793, 3, 385, -18000, 0), - (6793, 4, 339, 20, 16141), - (6793, 5, 137, 343, 0), - (6793, 6, 385, -18000, 0), - (6819, 1, 264, 180, 524), - (6820, 1, 264, 360, 524), - (6821, 1, 264, 540, 524), - (6823, 1, 264, 180, 320), - (6824, 1, 264, 360, 320), - (6825, 1, 264, 540, 320), - (6826, 1, 264, 720, 320), - (6827, 1, 264, 900, 320), - (6870, 1, 264, 180, 544), - (6871, 1, 264, 360, 544), - (6872, 1, 264, 540, 544), - (6873, 1, 279, 7, 0), - (6874, 1, 279, 11, 0), - (6875, 1, 279, 15, 0), - (6876, 1, 375, 107, 0), - (6877, 1, 375, 115, 0), - (6878, 1, 375, 125, 0), - (6879, 1, 243, 15, 0), - (6880, 1, 243, 25, 0), - (6881, 1, 243, 35, 0), - (6882, 1, 242, 5, 0), - (6883, 1, 242, 10, 0), - (6884, 1, 242, 15, 0), - (6900, 1, 264, 840, 465), - (6901, 1, 264, 1140, 465), - (6902, 1, 264, 1440, 465), - (6903, 1, 264, 1740, 465), - (6904, 1, 264, 2040, 465), - (6905, 1, 225, 33, 0), - (6906, 1, 225, 36, 0), - (6907, 1, 225, 39, 0), - (6908, 1, 264, 180, 499), - (6909, 1, 264, 360, 499), - (6910, 1, 264, 540, 499), - (6911, 1, 224, 60, 74), - (6911, 2, 173, 2, 0), - (6912, 1, 224, 70, 74), - (6912, 2, 173, 3, 0), - (6913, 1, 224, 80, 74), - (6913, 2, 173, 3, 0), - (6935, 1, 264, 180, 465), - (6936, 1, 264, 360, 465), - (6937, 1, 264, 540, 465), - (6938, 1, 361, 65, 16164), - (6939, 1, 361, 75, 16165), - (6940, 1, 361, 85, 16166), - (6941, 1, 264, 120, 962), - (6942, 1, 264, 240, 962), - (6943, 1, 264, 360, 962), - (6944, 1, 264, 480, 962), - (6945, 1, 264, 600, 962), - (6974, 1, 264, 3, 247), - (6974, 2, 264, 2, 986), - (6974, 3, 264, 2, 987), - (6974, 4, 264, 2, 988), - (6975, 1, 264, 6, 247), - (6975, 2, 264, 4, 986), - (6975, 3, 264, 4, 987), - (6975, 4, 264, 4, 988), - (6976, 1, 264, 12, 247), - (6976, 2, 264, 6, 986), - (6976, 3, 264, 6, 987), - (6976, 4, 264, 6, 988), - (6977, 1, 264, 6, 3817), - (6978, 1, 264, 12, 3817), - (6979, 1, 264, 18, 3817), - (6980, 1, 264, 45, 128), - (6981, 1, 264, 90, 128), - (6982, 1, 264, 135, 128), - (6987, 1, 353, 1, 0), - (6988, 1, 287, 1, 0), - (6988, 2, 385, 16439, 0), - (6988, 3, 411, 32768, 0), - (6989, 1, 287, 2, 0), - (6989, 2, 385, 16439, 0), - (6989, 3, 411, 32768, 0), - (6990, 1, 287, 3, 0), - (6990, 2, 385, 16439, 0), - (6990, 3, 411, 32768, 0), - (7005, 1, 264, 432, 789), - (7006, 1, 264, 864, 789), - (7007, 1, 264, 1296, 789), - (7008, 1, 439, 0, 109400), - (7008, 2, 345, 80, 35), - (7009, 1, 439, 0, 116800), - (7009, 2, 345, 82, 35), - (7010, 1, 378, 25, 96), - (7011, 1, 378, 30, 96), - (7012, 1, 378, 35, 96), - (7013, 1, 378, 40, 96), - (7014, 1, 378, 45, 96), - (7015, 1, 378, 50, 96), - (7033, 1, 421, 5, 0), - (7033, 2, 139, 16097, 0), - (7033, 3, 139, 23612, 0), - (7033, 4, 139, 32196, 0), - (7033, 5, 139, 32565, 0), - (7033, 6, 423, 6, 0), - (7033, 7, 422, 5, 0), - (7033, 8, 411, 2, 0), - (7034, 1, 421, 10, 0), - (7034, 2, 139, 16097, 0), - (7034, 3, 139, 23612, 0), - (7034, 4, 139, 32196, 0), - (7034, 5, 139, 32565, 0), - (7034, 6, 423, 6, 0), - (7034, 7, 422, 5, 0), - (7034, 8, 411, 2, 0), - (7035, 1, 421, 15, 0), - (7035, 2, 139, 16097, 0), - (7035, 3, 139, 23612, 0), - (7035, 4, 139, 32196, 0), - (7035, 5, 139, 32565, 0), - (7035, 6, 423, 6, 0), - (7035, 7, 422, 5, 0), - (7035, 8, 411, 2, 0), - (7036, 1, 264, 10, 3646), - (7037, 1, 264, 20, 3646), - (7038, 1, 264, 30, 3646), - (7050, 1, 265, 62, 0), - (7051, 1, 265, 64, 0), - (7052, 1, 265, 66, 0), - (7053, 1, 265, 67, 0), - (7054, 1, 265, 69, 0), - (7055, 1, 265, 71, 0), - (7056, 1, 265, 62, 0), - (7057, 1, 265, 64, 0), - (7058, 1, 265, 66, 0), - (7059, 1, 265, 67, 0), - (7060, 1, 265, 69, 0), - (7061, 1, 265, 71, 0), - (7062, 1, 372, 50, 0), - (7063, 1, 265, 72, 0), - (7064, 1, 265, 74, 0), - (7065, 1, 265, 76, 0), - (7066, 1, 265, 72, 0), - (7067, 1, 265, 74, 0), - (7068, 1, 265, 76, 0), - (7100, 1, 264, 180, 254), - (7101, 1, 264, 360, 254), - (7102, 1, 264, 540, 254), - (7103, 1, 264, 432, 286), - (7103, 2, 264, 432, 10753), - (7103, 3, 264, 432, 9101), - (7104, 1, 264, 864, 286), - (7104, 2, 264, 864, 10753), - (7104, 3, 264, 864, 9101), - (7105, 1, 264, 1296, 286), - (7105, 2, 264, 1296, 10753), - (7105, 3, 264, 1296, 9101), - (7106, 1, 224, 20, 30), - (7106, 2, 173, 1, 0), - (7107, 1, 224, 35, 30), - (7107, 2, 173, 2, 0), - (7108, 1, 224, 50, 30), - (7108, 2, 173, 3, 0), - (7112, 1, 85, 13596, 50), - (7113, 1, 85, 13597, 50), - (7114, 1, 85, 13598, 50), - (7116, 1, 264, 360, 110), - (7117, 1, 264, 450, 110), - (7118, 1, 264, 540, 110), - (7122, 1, 349, 30, 0), - (7123, 1, 349, 35, 0), - (7124, 1, 349, 40, 0), - (7125, 1, 349, 45, 0), - (7126, 1, 349, 50, 0), - (7128, 1, 264, 240, 109), - (7129, 1, 264, 300, 109), - (7130, 1, 264, 360, 109), - (7131, 1, 439, 0, 88880), - (7131, 2, 345, 74, 28), - (7132, 1, 439, 0, 95440), - (7132, 2, 345, 76, 28), - (7133, 1, 439, 0, 102280), - (7133, 2, 345, 78, 28), - (7134, 1, 220, 120, 8), - (7135, 1, 220, 140, 8), - (7136, 1, 220, 165, 8), - (7137, 1, 264, 60, 672), - (7138, 1, 264, 75, 672), - (7139, 1, 264, 90, 672), - (7146, 1, 252, 80, 0), - (7147, 1, 252, 85, 0), - (7148, 1, 216, 350, 8), - (7149, 1, 216, 400, 8), - (7150, 1, 216, 450, 8), - (7151, 1, 258, 59, 0), - (7152, 1, 258, 64, 0), - (7153, 1, 258, 69, 0), - (7160, 1, 227, 120, 32), - (7161, 1, 227, 150, 32), - (7162, 1, 227, 180, 32), - (7163, 1, 220, 130, 26), - (7163, 2, 220, 130, 30), - (7163, 3, 220, 130, 38), - (7164, 1, 220, 140, 26), - (7164, 2, 220, 140, 30), - (7164, 3, 220, 140, 38), - (7165, 1, 220, 150, 26), - (7165, 2, 220, 150, 30), - (7165, 3, 220, 150, 38), - (7166, 1, 264, 20, 468), - (7166, 2, 264, 20, 469), - (7166, 3, 264, 20, 470), - (7167, 1, 264, 25, 468), - (7167, 2, 264, 25, 469), - (7167, 3, 264, 25, 470), - (7168, 1, 264, 30, 468), - (7168, 2, 264, 30, 469), - (7168, 3, 264, 30, 470), - (7169, 1, 220, 135, 21), - (7169, 2, 220, 135, 23), - (7169, 3, 220, 270, 52), - (7169, 4, 220, 135, 28), - (7170, 1, 220, 145, 21), - (7170, 2, 220, 145, 23), - (7170, 3, 220, 290, 52), - (7170, 4, 220, 145, 28), - (7171, 1, 220, 155, 21), - (7171, 2, 220, 155, 23), - (7171, 3, 220, 310, 52), - (7171, 4, 220, 155, 28), - (7175, 1, 283, 120, 0), - (7176, 1, 283, 140, 0), - (7177, 1, 283, 160, 0), - (7196, 1, 169, 20, -1), - (7197, 1, 169, 25, -1), - (7198, 1, 169, 30, -1), - (7204, 1, 218, 11, 0), - (7205, 1, 218, 12, 0), - (7206, 1, 218, 13, 0), - (7207, 1, 218, 14, 0), - (7208, 1, 218, 15, 0), - (7210, 1, 280, 50, 0), - (7211, 1, 280, 53, 0), - (7212, 1, 280, 56, 0), - (7213, 1, 280, 59, 0), - (7214, 1, 280, 62, 0), - (7215, 1, 264, 4200, 68), - (7216, 1, 264, 4800, 68), - (7220, 1, 360, 60, 12701), - (7221, 1, 360, 60, 12702), - (7222, 1, 360, 60, 12703), - (7232, 1, 294, 0, 185), - (7233, 1, 294, 0, 190), - (7234, 1, 294, 0, 195), - (7260, 1, 287, 14, 0), - (7260, 2, 385, 2754, 1), - (7261, 1, 287, 16, 0), - (7261, 2, 385, 2754, 1), - (7262, 1, 287, 18, 0), - (7262, 2, 385, 2754, 1), - (7263, 1, 274, 18, 0), - (7264, 1, 274, 20, 0), - (7265, 1, 274, 22, 0), - (7267, 1, 280, 54, 0), - (7268, 1, 280, 55, 0), - (7269, 1, 280, 56, 0), - (7270, 1, 218, 16, 0), - (7271, 1, 218, 17, 0), - (7272, 1, 218, 18, 0), - (7273, 1, 218, 19, 0), - (7274, 1, 218, 20, 0), - (7279, 1, 310, 6000, 0), - (7279, 2, 139, 11903, 0), - (7279, 3, 310, 6000, 0), - (7279, 4, 139, 11904, 0), - (7279, 5, 310, 6000, 0), - (7279, 6, 139, 11905, 0), - (7279, 7, 310, 6000, 0), - (7279, 8, 139, 1362, 0), - (7279, 9, 310, 6000, 0), - (7279, 10, 139, 8032, 0), - (7279, 11, 310, 6000, 0), - (7279, 12, 385, 6131, 0), - (7279, 13, 385, 6231, 0), - (7279, 14, 385, 6331, 0), - (7279, 15, 385, 6431, 0), - (7279, 16, 385, 6531, 0), - (7279, 17, 385, 6631, 0), - (7280, 1, 310, 7000, 0), - (7280, 2, 139, 11903, 0), - (7280, 3, 310, 7000, 0), - (7280, 4, 139, 11904, 0), - (7280, 5, 310, 7000, 0), - (7280, 6, 139, 11905, 0), - (7280, 7, 310, 7000, 0), - (7280, 8, 139, 1362, 0), - (7280, 9, 310, 7000, 0), - (7280, 10, 139, 8032, 0), - (7280, 11, 310, 7000, 0), - (7280, 12, 385, 6131, 0), - (7280, 13, 385, 6231, 0), - (7280, 14, 385, 6331, 0), - (7280, 15, 385, 6431, 0), - (7280, 16, 385, 6531, 0), - (7280, 17, 385, 6631, 0), - (7281, 1, 310, 8000, 0), - (7281, 2, 139, 11903, 0), - (7281, 3, 310, 8000, 0), - (7281, 4, 139, 11904, 0), - (7281, 5, 310, 8000, 0), - (7281, 6, 139, 11905, 0), - (7281, 7, 310, 8000, 0), - (7281, 8, 139, 1362, 0), - (7281, 9, 310, 8000, 0), - (7281, 10, 139, 8032, 0), - (7281, 11, 310, 8000, 0), - (7281, 12, 385, 6131, 0), - (7281, 13, 385, 6231, 0), - (7281, 14, 385, 6331, 0), - (7281, 15, 385, 6431, 0), - (7281, 16, 385, 6531, 0), - (7281, 17, 385, 6631, 0), - (7282, 1, 310, 9000, 0), - (7282, 2, 139, 11903, 0), - (7282, 3, 310, 9000, 0), - (7282, 4, 139, 11904, 0), - (7282, 5, 310, 9000, 0), - (7282, 6, 139, 11905, 0), - (7282, 7, 310, 9000, 0), - (7282, 8, 139, 1362, 0), - (7282, 9, 310, 9000, 0), - (7282, 10, 139, 8032, 0), - (7282, 11, 310, 9000, 0), - (7282, 12, 385, 6131, 0), - (7282, 13, 385, 6231, 0), - (7282, 14, 385, 6331, 0), - (7282, 15, 385, 6431, 0), - (7282, 16, 385, 6531, 0), - (7282, 17, 385, 6631, 0), - (7283, 1, 310, 10000, 0), - (7283, 2, 139, 11903, 0), - (7283, 3, 310, 10000, 0), - (7283, 4, 139, 11904, 0), - (7283, 5, 310, 10000, 0), - (7283, 6, 139, 11905, 0), - (7283, 7, 310, 10000, 0), - (7283, 8, 139, 1362, 0), - (7283, 9, 310, 10000, 0), - (7283, 10, 139, 8032, 0), - (7283, 11, 310, 10000, 0), - (7283, 12, 385, 6131, 0), - (7283, 13, 385, 6231, 0), - (7283, 14, 385, 6331, 0), - (7283, 15, 385, 6431, 0), - (7283, 16, 385, 6531, 0), - (7283, 17, 385, 6631, 0), - (7284, 1, 287, 3, 0), - (7284, 2, 137, 31, 0), - (7284, 3, 136, 5, 0), - (7313, 1, 244, 40, 0), - (7314, 1, 244, 30, 0), - (7315, 1, 244, 20, 0), - (7316, 1, 264, 1080, 41), - (7317, 1, 264, 1260, 41), - (7318, 1, 339, 25, 16015), - (7318, 2, 137, 21, 0), - (7319, 1, 339, 25, 16016), - (7319, 2, 137, 21, 0), - (7320, 1, 339, 25, 16017), - (7320, 2, 137, 21, 0), - (7321, 1, 339, 25, 16018), - (7321, 2, 137, 21, 0), - (7322, 1, 339, 25, 16019), - (7322, 2, 137, 21, 0), - (7323, 1, 264, 720, 254), - (7324, 1, 264, 900, 254), - (7325, 1, 264, 1080, 254), - (7326, 1, 264, 1728, 286), - (7326, 2, 264, 1728, 10753), - (7326, 3, 264, 1728, 9101), - (7327, 1, 264, 2160, 286), - (7327, 2, 264, 2160, 10753), - (7327, 3, 264, 2160, 9101), - (7328, 1, 264, 2592, 286), - (7328, 2, 264, 2592, 10753), - (7328, 3, 264, 2592, 9101), - (7336, 1, 85, 16029, 0), - (7337, 1, 85, 16030, 0), - (7338, 1, 85, 16031, 0), - (7353, 1, 216, 115, 0), - (7353, 2, 216, 115, 1), - (7353, 3, 216, 115, 2), - (7353, 4, 216, 115, 3), - (7353, 5, 216, 115, 10), - (7353, 6, 216, 115, 28), - (7353, 7, 216, 115, 30), - (7353, 8, 216, 115, 36), - (7353, 9, 216, 115, 77), - (7354, 1, 216, 120, 0), - (7354, 2, 216, 120, 1), - (7354, 3, 216, 120, 2), - (7354, 4, 216, 120, 3), - (7354, 5, 216, 120, 10), - (7354, 6, 216, 120, 28), - (7354, 7, 216, 120, 30), - (7354, 8, 216, 120, 36), - (7354, 9, 216, 120, 77), - (7355, 1, 216, 125, 0), - (7355, 2, 216, 125, 1), - (7355, 3, 216, 125, 2), - (7355, 4, 216, 125, 3), - (7355, 5, 216, 125, 10), - (7355, 6, 216, 125, 28), - (7355, 7, 216, 125, 30), - (7355, 8, 216, 125, 36), - (7355, 9, 216, 125, 77), - (7356, 1, 360, 60, 16056), - (7357, 1, 360, 60, 16057), - (7358, 1, 360, 60, 16058), - (7359, 1, 217, 0, 82600), - (7359, 2, 346, 78, 22), - (7360, 1, 217, 0, 88880), - (7360, 2, 346, 80, 22), - (7361, 1, 217, 0, 95440), - (7361, 2, 346, 82, 22), - (7362, 1, 59, -18, 0), - (7363, 1, 59, -21, 0), - (7364, 1, 59, -24, 0), - (7365, 1, 59, -27, 0), - (7366, 1, 59, -30, 0), - (7373, 1, 2, 108, 0), - (7374, 1, 2, 112, 0), - (7375, 1, 2, 116, 0), - (7376, 1, 2, 120, 0), - (7377, 1, 2, 124, 0), - (7378, 1, 347, 14, 0), - (7379, 1, 347, 16, 0), - (7380, 1, 347, 18, 0), - (7381, 1, 347, 20, 0), - (7382, 1, 347, 22, 0), - (7383, 1, 347, 24, 0), - (7384, 1, 360, 25, 16063), - (7385, 1, 360, 25, 16064), - (7386, 1, 360, 25, 16065), - (7390, 1, 303, 6000, 6000), - (7390, 2, 139, 2766, 0), - (7391, 1, 303, 6500, 6500), - (7391, 2, 139, 2766, 0), - (7392, 1, 303, 7500, 8500), - (7392, 2, 139, 2766, 0), - (7393, 1, 85, 16066, 0), - (7394, 1, 85, 16067, 0), - (7395, 1, 85, 16068, 0), - (7396, 1, 85, 16069, 0), - (7397, 1, 85, 16070, 0), - (7398, 1, 85, 16071, 0), - (7399, 1, 302, 350, 350), - (7399, 2, 385, 99, 0), - (7400, 1, 302, 370, 370), - (7400, 2, 385, 99, 0), - (7401, 1, 302, 400, 400), - (7401, 2, 385, 99, 0), - (7402, 1, 59, -33, 0), - (7403, 1, 59, -36, 0), - (7404, 1, 59, -39, 0), - (7405, 1, 59, -42, 0), - (7406, 1, 59, -45, 0), - (7407, 1, 181, 100, -1), - (7448, 1, 264, 240, 553), - (7449, 1, 264, 300, 553), - (7450, 1, 264, 360, 553), - (7451, 1, 264, 720, 777), - (7452, 1, 264, 900, 777), - (7453, 1, 264, 1080, 777), - (7478, 1, 264, 2880, 245), - (7489, 1, 218, 16, 0), - (7490, 1, 218, 17, 0), - (7491, 1, 218, 18, 0), - (7492, 1, 218, 19, 0), - (7493, 1, 218, 20, 0), - (7494, 1, 280, 65, 0), - (7495, 1, 280, 66, 0), - (7496, 1, 280, 67, 0), - (7500, 1, 363, 3, 0), - (7501, 1, 172, 45, 0), - (7502, 1, 172, 46, 0), - (7503, 1, 172, 47, 0), - (7504, 1, 172, 48, 0), - (7505, 1, 172, 49, 0), - (7506, 1, 259, 51, 0), - (7507, 1, 259, 52, 0), - (7508, 1, 259, 53, 0), - (7509, 1, 259, 54, 0), - (7510, 1, 259, 55, 0), - (7511, 1, 328, 1050, 0), - (7512, 1, 328, 1100, 0), - (7513, 1, 328, 1150, 0), - (7514, 1, 328, 1200, 0), - (7515, 1, 328, 1250, 0), - (7516, 1, 262, 30, 7), - (7516, 2, 262, 30, 8), - (7516, 3, 262, 30, 9), - (7516, 4, 262, 30, 10), - (7516, 5, 262, 30, 11), - (7517, 1, 262, 35, 7), - (7517, 2, 262, 35, 8), - (7517, 3, 262, 35, 9), - (7517, 4, 262, 35, 10), - (7517, 5, 262, 35, 11), - (7518, 1, 262, 40, 7), - (7518, 2, 262, 40, 8), - (7518, 3, 262, 40, 9), - (7518, 4, 262, 40, 10), - (7518, 5, 262, 40, 11), - (7519, 1, 262, 45, 7), - (7519, 2, 262, 45, 8), - (7519, 3, 262, 45, 9), - (7519, 4, 262, 45, 10), - (7519, 5, 262, 45, 11), - (7520, 1, 262, 50, 7), - (7520, 2, 262, 50, 8), - (7520, 3, 262, 50, 9), - (7520, 4, 262, 50, 10), - (7520, 5, 262, 50, 11), - (7521, 1, 317, 11, 0), - (7522, 1, 317, 12, 0), - (7523, 1, 317, 13, 0), - (7524, 1, 317, 14, 0), - (7525, 1, 317, 15, 0), - (7526, 1, 69, 600, 0), - (7527, 1, 69, 700, 0), - (7528, 1, 69, 800, 0), - (7529, 1, 69, 900, 0), - (7530, 1, 69, 1000, 0), - (7534, 1, 0, 21, 0), - (7535, 1, 0, 22, 0), - (7536, 1, 0, 23, 0), - (7537, 1, 0, 24, 0), - (7538, 1, 0, 25, 0), - (7539, 1, 327, 8, 0), - (7540, 1, 327, 9, 0), - (7541, 1, 214, 1100, 0), - (7542, 1, 214, 1200, 0), - (7543, 1, 214, 1300, 0), - (7544, 1, 221, 27, 0), - (7545, 1, 221, 30, 0), - (7546, 1, 221, 33, 0), - (7547, 1, 262, 80, 0), - (7547, 2, 262, 80, 1), - (7547, 3, 262, 80, 2), - (7547, 4, 262, 80, 3), - (7547, 5, 262, 80, 4), - (7547, 6, 262, 80, 5), - (7547, 7, 262, 80, 6), - (7548, 1, 262, 85, 0), - (7548, 2, 262, 85, 1), - (7548, 3, 262, 85, 2), - (7548, 4, 262, 85, 3), - (7548, 5, 262, 85, 4), - (7548, 6, 262, 85, 5), - (7548, 7, 262, 85, 6), - (7549, 1, 262, 90, 0), - (7549, 2, 262, 90, 1), - (7549, 3, 262, 90, 2), - (7549, 4, 262, 90, 3), - (7549, 5, 262, 90, 4), - (7549, 6, 262, 90, 5), - (7549, 7, 262, 90, 6), - (7550, 1, 262, 95, 0), - (7550, 2, 262, 95, 1), - (7550, 3, 262, 95, 2), - (7550, 4, 262, 95, 3), - (7550, 5, 262, 95, 4), - (7550, 6, 262, 95, 5), - (7550, 7, 262, 95, 6), - (7551, 1, 262, 100, 0), - (7551, 2, 262, 100, 1), - (7551, 3, 262, 100, 2), - (7551, 4, 262, 100, 3), - (7551, 5, 262, 100, 4), - (7551, 6, 262, 100, 5), - (7551, 7, 262, 100, 6), - (7553, 1, 326, 3, 0), - (7554, 1, 339, 20, 16194), - (7554, 2, 138, 1, 0), - (7554, 3, 141, 1, 0), - (7554, 4, 142, 65, 0), - (7554, 5, 137, 0, 0), - (7554, 6, 311, 0, 0), - (7554, 7, 134, 85, 0), - (7554, 8, 139, -265, 0), - (7554, 9, 139, -754, 0), - (7554, 10, 139, -1332, 0), - (7554, 11, 139, -1572, 0), - (7554, 12, 139, -2749, 0), - (7554, 13, 139, -4979, 0), - (7554, 14, 139, -5418, 0), - (7554, 15, 139, -5403, 0), - (7554, 16, 348, 10, 0), - (7555, 1, 339, 21, 16195), - (7555, 2, 138, 1, 0), - (7555, 3, 141, 1, 0), - (7555, 4, 142, 65, 0), - (7555, 5, 137, 0, 0), - (7555, 6, 311, 0, 0), - (7555, 7, 134, 85, 0), - (7555, 8, 139, -265, 0), - (7555, 9, 139, -754, 0), - (7555, 10, 139, -1332, 0), - (7555, 11, 139, -1572, 0), - (7555, 12, 139, -2749, 0), - (7555, 13, 139, -4979, 0), - (7555, 14, 139, -5418, 0), - (7555, 15, 139, -5403, 0), - (7555, 16, 348, 10, 0), - (7556, 1, 339, 22, 16196), - (7556, 2, 138, 1, 0), - (7556, 3, 141, 1, 0), - (7556, 4, 142, 65, 0), - (7556, 5, 137, 0, 0), - (7556, 6, 311, 0, 0), - (7556, 7, 134, 85, 0), - (7556, 8, 139, -265, 0), - (7556, 9, 139, -754, 0), - (7556, 10, 139, -1332, 0), - (7556, 11, 139, -1572, 0), - (7556, 12, 139, -2749, 0), - (7556, 13, 139, -4979, 0), - (7556, 14, 139, -5418, 0), - (7556, 15, 139, -5403, 0), - (7556, 16, 348, 10, 0), - (7557, 1, 339, 23, 16417), - (7557, 2, 138, 1, 0), - (7557, 3, 141, 1, 0), - (7557, 4, 142, 65, 0), - (7557, 5, 137, 0, 0), - (7557, 6, 311, 0, 0), - (7557, 7, 134, 85, 0), - (7557, 8, 139, -265, 0), - (7557, 9, 139, -754, 0), - (7557, 10, 139, -1332, 0), - (7557, 11, 139, -1572, 0), - (7557, 12, 139, -2749, 0), - (7557, 13, 139, -4979, 0), - (7557, 14, 139, -5418, 0), - (7557, 15, 139, -5403, 0), - (7557, 16, 348, 10, 0), - (7558, 1, 339, 24, 16418), - (7558, 2, 138, 1, 0), - (7558, 3, 141, 1, 0), - (7558, 4, 142, 65, 0), - (7558, 5, 137, 0, 0), - (7558, 6, 311, 0, 0), - (7558, 7, 134, 85, 0), - (7558, 8, 139, -265, 0), - (7558, 9, 139, -754, 0), - (7558, 10, 139, -1332, 0), - (7558, 11, 139, -1572, 0), - (7558, 12, 139, -2749, 0), - (7558, 13, 139, -4979, 0), - (7558, 14, 139, -5418, 0), - (7558, 15, 139, -5403, 0), - (7558, 16, 348, 10, 0), - (7559, 1, 266, 23, 0), - (7560, 1, 266, 24, 0), - (7561, 1, 266, 25, 0), - (7562, 1, 330, 125, 0), - (7562, 2, 330, 125, 1), - (7562, 3, 330, 125, 2), - (7562, 4, 330, 125, 3), - (7562, 5, 330, 125, 28), - (7562, 6, 330, 125, 36), - (7562, 7, 330, 125, 77), - (7563, 1, 330, 130, 0), - (7563, 2, 330, 130, 1), - (7563, 3, 330, 130, 2), - (7563, 4, 330, 130, 3), - (7563, 5, 330, 130, 28), - (7563, 6, 330, 130, 36), - (7563, 7, 330, 130, 77), - (7564, 1, 330, 135, 0), - (7564, 2, 330, 135, 1), - (7564, 3, 330, 135, 2), - (7564, 4, 330, 135, 3), - (7564, 5, 330, 135, 28), - (7564, 6, 330, 135, 36), - (7564, 7, 330, 135, 77), - (7565, 1, 278, 800, 54510), - (7565, 2, 440, 76, 100), - (7566, 1, 278, 850, 58400), - (7566, 2, 440, 78, 100), - (7567, 1, 278, 900, 62680), - (7567, 2, 440, 80, 100), - (7568, 1, 341, 160, 0), - (7569, 1, 341, 170, 0), - (7570, 1, 341, 180, 0), - (7571, 1, 341, 190, 0), - (7572, 1, 341, 200, 0), - (7573, 1, 360, 70, 11023), - (7574, 1, 360, 80, 11023), - (7575, 1, 360, 90, 11023), - (7576, 1, 318, 16, 0), - (7577, 1, 318, 17, 0), - (7578, 1, 318, 18, 0), - (7579, 1, 318, 19, 0), - (7580, 1, 318, 20, 0), - (7581, 1, 294, 0, 160), - (7582, 1, 294, 0, 165), - (7583, 1, 294, 0, 170), - (7584, 1, 114, -60, 0), - (7585, 1, 114, -61, 0), - (7586, 1, 114, -62, 0), - (7587, 1, 319, 22, 0), - (7588, 1, 319, 23, 0), - (7589, 1, 319, 24, 0), - (7590, 1, 274, 35, 0), - (7591, 1, 274, 36, 0), - (7592, 1, 274, 37, 0), - (7593, 1, 15, 14, 0), - (7594, 1, 15, 15, 0), - (7595, 1, 15, 16, 0), - (7596, 1, 15, 17, 0), - (7597, 1, 15, 18, 0), - (7598, 1, 114, -60, 0), - (7599, 1, 114, -61, 0), - (7600, 1, 114, -62, 0), - (7601, 1, 213, 7, 0), - (7602, 1, 213, 9, 0), - (7603, 1, 213, 11, 0), - (7604, 1, 189, 14, 0), - (7605, 1, 189, 15, 0), - (7612, 1, 270, 70, 0), - (7613, 1, 270, 75, 0), - (7614, 1, 270, 80, 0), - (7615, 1, 264, 720, 494), - (7616, 1, 264, 900, 494), - (7617, 1, 264, 1080, 494), - (7618, 1, 264, 720, 500), - (7619, 1, 264, 900, 500), - (7620, 1, 264, 1080, 500), - (7621, 1, 339, 10, 8105), - (7621, 2, 142, 65, 0), - (7621, 3, 311, 0, 0), - (7621, 4, 134, 70, 0), - (7621, 5, 348, 10, 0), - (7621, 6, 137, 0, 0), - (7621, 7, 339, 10, 8105), - (7621, 8, 142, 65, 0), - (7621, 9, 311, 0, 0), - (7621, 10, 134, 70, 0), - (7621, 11, 348, 10, 0), - (7621, 12, 137, 100, 0), - (7621, 13, 339, 10, 8105), - (7621, 14, 142, 65, 0), - (7621, 15, 311, 0, 0), - (7621, 16, 134, 70, 0), - (7621, 17, 348, 10, 0), - (7621, 18, 137, 79, 0), - (7621, 19, 339, 10, 8105), - (7621, 20, 142, 65, 0), - (7621, 21, 311, 0, 0), - (7621, 22, 134, 70, 0), - (7621, 23, 348, 10, 0), - (7621, 24, 137, 147, 0), - (7621, 25, 339, 10, 11404), - (7621, 26, 142, 71, 0), - (7621, 27, 311, 0, 0), - (7621, 28, 134, 75, 0), - (7621, 29, 348, 10, 0), - (7621, 30, 137, 0, 0), - (7621, 31, 339, 10, 11404), - (7621, 32, 142, 71, 0), - (7621, 33, 311, 0, 0), - (7621, 34, 134, 75, 0), - (7621, 35, 348, 10, 0), - (7621, 36, 137, 100, 0), - (7621, 37, 339, 10, 11404), - (7621, 38, 142, 71, 0), - (7621, 39, 311, 0, 0), - (7621, 40, 134, 75, 0), - (7621, 41, 348, 10, 0), - (7621, 42, 137, 79, 0), - (7621, 43, 339, 10, 11404), - (7621, 44, 142, 71, 0), - (7621, 45, 311, 0, 0), - (7621, 46, 134, 75, 0), - (7621, 47, 348, 10, 0), - (7621, 48, 137, 147, 0), - (7621, 49, 339, 10, 13199), - (7621, 50, 142, 76, 0), - (7621, 51, 311, 0, 0), - (7621, 52, 134, 80, 0), - (7621, 53, 348, 10, 0), - (7621, 54, 137, 0, 0), - (7621, 55, 339, 10, 13199), - (7621, 56, 142, 76, 0), - (7621, 57, 311, 0, 0), - (7621, 58, 134, 80, 0), - (7621, 59, 348, 10, 0), - (7621, 60, 137, 100, 0), - (7621, 61, 339, 10, 13199), - (7621, 62, 142, 76, 0), - (7621, 63, 311, 0, 0), - (7621, 64, 134, 80, 0), - (7621, 65, 348, 10, 0), - (7621, 66, 137, 79, 0), - (7621, 67, 339, 10, 13199), - (7621, 68, 142, 76, 0), - (7621, 69, 311, 0, 0), - (7621, 70, 134, 80, 0), - (7621, 71, 348, 10, 0), - (7621, 72, 137, 147, 0), - (7621, 73, 339, 10, 13830), - (7621, 74, 142, 81, 0), - (7621, 75, 311, 0, 0), - (7621, 76, 134, 85, 0), - (7621, 77, 348, 10, 0), - (7621, 78, 137, 0, 0), - (7621, 79, 339, 10, 13830), - (7621, 80, 142, 81, 0), - (7621, 81, 311, 0, 0), - (7621, 82, 134, 85, 0), - (7621, 83, 348, 10, 0), - (7621, 84, 137, 100, 0), - (7621, 85, 339, 10, 13830), - (7621, 86, 142, 81, 0), - (7621, 87, 311, 0, 0), - (7621, 88, 134, 85, 0), - (7621, 89, 348, 10, 0), - (7621, 90, 137, 79, 0), - (7621, 91, 339, 10, 13830), - (7621, 92, 142, 81, 0), - (7621, 93, 311, 0, 0), - (7621, 94, 134, 85, 0), - (7621, 95, 348, 10, 0), - (7621, 96, 137, 147, 0), - (7622, 1, 265, 79, 0), - (7623, 1, 265, 80, 0), - (7624, 1, 265, 81, 0), - (7625, 1, 265, 79, 0), - (7626, 1, 265, 80, 0), - (7627, 1, 265, 81, 0), - (7628, 1, 292, 46, 0), - (7629, 1, 292, 47, 0), - (7630, 1, 292, 48, 0), - (7631, 1, 279, 34, 0), - (7632, 1, 279, 35, 0), - (7633, 1, 279, 36, 0), - (7634, 1, 279, 34, 0), - (7635, 1, 279, 35, 0), - (7636, 1, 279, 36, 0), - (7637, 1, 279, 34, 0), - (7638, 1, 279, 35, 0), - (7639, 1, 279, 36, 0), - (7640, 1, 200, 60, 0), - (7641, 1, 294, 17, 100), - (7642, 1, 294, 19, 100), - (7643, 1, 294, 21, 100), - (7644, 1, 375, 130, 0), - (7645, 1, 375, 135, 0), - (7646, 1, 375, 140, 0), - (7647, 1, 229, 20, 0), - (7648, 1, 229, 25, 0), - (7649, 1, 229, 30, 0), - (7650, 1, 330, 125, 0), - (7650, 2, 330, 125, 1), - (7650, 3, 330, 125, 2), - (7650, 4, 330, 125, 3), - (7650, 5, 330, 125, 28), - (7650, 6, 330, 125, 36), - (7651, 1, 330, 130, 0), - (7651, 2, 330, 130, 1), - (7651, 3, 330, 130, 2), - (7651, 4, 330, 130, 3), - (7651, 5, 330, 130, 28), - (7651, 6, 330, 130, 36), - (7652, 1, 330, 135, 0), - (7652, 2, 330, 135, 1), - (7652, 3, 330, 135, 2), - (7652, 4, 330, 135, 3), - (7652, 5, 330, 135, 28), - (7652, 6, 330, 135, 36), - (7653, 1, 330, 125, 0), - (7653, 2, 330, 125, 1), - (7653, 3, 330, 125, 2), - (7653, 4, 330, 125, 3), - (7653, 5, 330, 125, 28), - (7653, 6, 330, 125, 36), - (7653, 7, 330, 125, 77), - (7654, 1, 330, 130, 0), - (7654, 2, 330, 130, 1), - (7654, 3, 330, 130, 2), - (7654, 4, 330, 130, 3), - (7654, 5, 330, 130, 28), - (7654, 6, 330, 130, 36), - (7654, 7, 330, 130, 77), - (7655, 1, 330, 135, 0), - (7655, 2, 330, 135, 1), - (7655, 3, 330, 135, 2), - (7655, 4, 330, 135, 3), - (7655, 5, 330, 135, 28), - (7655, 6, 330, 135, 36), - (7655, 7, 330, 135, 77), - (7656, 1, 330, 100, 0), - (7656, 2, 330, 100, 1), - (7656, 3, 330, 100, 2), - (7656, 4, 330, 100, 3), - (7656, 5, 330, 100, 28), - (7656, 6, 330, 100, 36), - (7656, 7, 330, 100, 77), - (7657, 1, 330, 105, 0), - (7657, 2, 330, 105, 1), - (7657, 3, 330, 105, 2), - (7657, 4, 330, 105, 3), - (7657, 5, 330, 105, 28), - (7657, 6, 330, 105, 36), - (7657, 7, 330, 105, 77), - (7658, 1, 330, 110, 0), - (7658, 2, 330, 110, 1), - (7658, 3, 330, 110, 2), - (7658, 4, 330, 110, 3), - (7658, 5, 330, 110, 28), - (7658, 6, 330, 110, 36), - (7658, 7, 330, 110, 77), - (7659, 1, 264, 72, 153), - (7660, 1, 264, 90, 153), - (7661, 1, 264, 108, 153), - (7663, 1, 375, 150, 0), - (7664, 1, 264, 10, 170), - (7665, 1, 264, 20, 170), - (7666, 1, 264, 30, 170), - (7667, 1, 264, 40, 170), - (7668, 1, 264, 50, 170), - (7670, 1, 229, 35, 0), - (7671, 1, 229, 40, 0), - (7672, 1, 229, 45, 0), - (7673, 1, 220, 50, 10), - (7674, 1, 220, 65, 10), - (7675, 1, 220, 80, 10), - (7676, 1, 220, 95, 10), - (7677, 1, 220, 110, 10), - (7678, 1, 231, 11, 0), - (7679, 1, 231, 13, 0), - (7680, 1, 231, 15, 0), - (7681, 1, 326, 4, 0), - (7682, 1, 264, 5400, 68), - (7683, 1, 327, 10, 0), - (7684, 1, 327, 11, 0), - (7685, 1, 327, 12, 0), - (7686, 1, 349, 55, 0), - (7687, 1, 349, 60, 0), - (7688, 1, 349, 65, 0), - (7690, 1, 353, 1, 0), - (7692, 1, 319, 25, 0), - (7693, 1, 319, 26, 0), - (7694, 1, 319, 27, 0), - (7695, 1, 127, 5, 0), - (7695, 2, 385, 14232, 0), - (7696, 1, 127, 10, 0), - (7696, 2, 385, 14232, 0), - (7697, 1, 127, 15, 0), - (7697, 2, 385, 14232, 0), - (7699, 1, 181, 100, 0), - (7700, 1, 279, 7, 0), - (7701, 1, 279, 11, 0), - (7702, 1, 279, 15, 0), - (7704, 1, 264, 540, 3707), - (7705, 1, 264, 720, 3707), - (7706, 1, 264, 900, 3707), - (7707, 1, 303, 8500, 9500), - (7707, 2, 139, 2766, 0), - (7708, 1, 303, 9500, 11000), - (7708, 2, 139, 2766, 0), - (7709, 1, 303, 11000, 14000), - (7709, 2, 139, 2766, 0), - (7713, 1, 274, 34, 0), - (7714, 1, 274, 36, 0), - (7715, 1, 264, 2, 901), - (7716, 1, 264, 4, 901), - (7717, 1, 264, 6, 901), - (7718, 1, 281, 90, 0), - (7722, 1, 339, 25, 23492), - (7722, 2, 138, 1, 0), - (7722, 3, 141, 1, 0), - (7722, 4, 142, 70, 0), - (7722, 5, 137, 0, 0), - (7722, 6, 311, 0, 0), - (7722, 7, 134, 90, 0), - (7722, 8, 139, -265, 0), - (7722, 9, 139, -754, 0), - (7722, 10, 139, -1332, 0), - (7722, 11, 139, -1572, 0), - (7722, 12, 139, -2749, 0), - (7722, 13, 139, -4979, 0), - (7722, 14, 139, -5418, 0), - (7722, 15, 139, -5403, 0), - (7722, 16, 348, 10, 0), - (7723, 1, 339, 26, 23493), - (7723, 2, 138, 1, 0), - (7723, 3, 141, 1, 0), - (7723, 4, 142, 70, 0), - (7723, 5, 137, 0, 0), - (7723, 6, 311, 0, 0), - (7723, 7, 134, 90, 0), - (7723, 8, 139, -265, 0), - (7723, 9, 139, -754, 0), - (7723, 10, 139, -1332, 0), - (7723, 11, 139, -1572, 0), - (7723, 12, 139, -2749, 0), - (7723, 13, 139, -4979, 0), - (7723, 14, 139, -5418, 0), - (7723, 15, 139, -5403, 0), - (7723, 16, 348, 10, 0), - (7724, 1, 339, 27, 23494), - (7724, 2, 138, 1, 0), - (7724, 3, 141, 1, 0), - (7724, 4, 142, 70, 0), - (7724, 5, 137, 0, 0), - (7724, 6, 311, 0, 0), - (7724, 7, 134, 90, 0), - (7724, 8, 139, -265, 0), - (7724, 9, 139, -754, 0), - (7724, 10, 139, -1332, 0), - (7724, 11, 139, -1572, 0), - (7724, 12, 139, -2749, 0), - (7724, 13, 139, -4979, 0), - (7724, 14, 139, -5418, 0), - (7724, 15, 139, -5403, 0), - (7724, 16, 348, 10, 0), - (7725, 1, 339, 28, 23495), - (7725, 2, 138, 1, 0), - (7725, 3, 141, 1, 0), - (7725, 4, 142, 70, 0), - (7725, 5, 137, 0, 0), - (7725, 6, 311, 0, 0), - (7725, 7, 134, 90, 0), - (7725, 8, 139, -265, 0), - (7725, 9, 139, -754, 0), - (7725, 10, 139, -1332, 0), - (7725, 11, 139, -1572, 0), - (7725, 12, 139, -2749, 0), - (7725, 13, 139, -4979, 0), - (7725, 14, 139, -5418, 0), - (7725, 15, 139, -5403, 0), - (7725, 16, 348, 10, 0), - (7726, 1, 339, 29, 23496), - (7726, 2, 138, 1, 0), - (7726, 3, 141, 1, 0), - (7726, 4, 142, 70, 0), - (7726, 5, 137, 0, 0), - (7726, 6, 311, 0, 0), - (7726, 7, 134, 90, 0), - (7726, 8, 139, -265, 0), - (7726, 9, 139, -754, 0), - (7726, 10, 139, -1332, 0), - (7726, 11, 139, -1572, 0), - (7726, 12, 139, -2749, 0), - (7726, 13, 139, -4979, 0), - (7726, 14, 139, -5418, 0), - (7726, 15, 139, -5403, 0), - (7726, 16, 348, 10, 0), - (7733, 1, 257, 1, 0), - (7733, 2, 267, 1, 31), - (7733, 3, 267, 1, 32), - (7733, 4, 267, 1, 33), - (7733, 5, 267, 1, 15), - (7733, 6, 267, 1, 16), - (7733, 7, 267, 1, 17), - (7733, 8, 267, 1, 18), - (7733, 9, 267, 1, 19), - (7733, 10, 267, 1, 20), - (7743, 1, 264, 90, 184), - (7744, 1, 264, 180, 184), - (7745, 1, 264, 270, 184), - (7746, 1, 310, 2000, 0), - (7746, 2, 385, 11233, 0), - (7746, 3, 385, 11333, 0), - (7746, 4, 411, 16, 0), - (7748, 1, 271, 5, 0), - (7749, 1, 271, 10, 0), - (7750, 1, 271, 15, 0), - (7751, 1, 264, 60, 2234), - (7752, 1, 264, 120, 2234), - (7753, 1, 264, 180, 2234), - (7757, 1, 264, 120, 9403), - (7758, 1, 264, 240, 9403), - (7759, 1, 264, 360, 9403), - (7760, 1, 264, 2, 824), - (7761, 1, 264, 4, 824), - (7762, 1, 264, 6, 824), - (7763, 1, 310, 4000, 0), - (7763, 2, 385, 11233, 0), - (7763, 3, 385, 11333, 0), - (7763, 4, 411, 16, 0), - (7764, 1, 310, 6000, 0), - (7764, 2, 385, 11233, 0), - (7764, 3, 385, 11333, 0), - (7764, 4, 411, 16, 0), - (7765, 1, 392, 1000, 0), - (7765, 2, 139, 21820, 0), - (7765, 3, 411, 4, 0), - (7766, 1, 392, 2000, 0), - (7766, 2, 139, 21820, 0), - (7766, 3, 411, 4, 0), - (7767, 1, 392, 3000, 0), - (7767, 2, 139, 21820, 0), - (7767, 3, 411, 4, 0), - (7768, 1, 392, 4000, 0), - (7768, 2, 139, 21820, 0), - (7768, 3, 411, 4, 0), - (7818, 1, 288, 200, 51), - (7818, 2, 288, 50, 51), - (7819, 1, 405, 7, 0), - (7820, 1, 405, 9, 0), - (7821, 1, 405, 11, 0), - (7822, 1, 264, 1, 1154), - (7823, 1, 264, 2, 1154), - (7824, 1, 264, 3, 1154), - (7825, 1, 264, 4, 1154), - (7826, 1, 264, 5, 1154), - (7827, 1, 398, 9000, 0), - (7827, 2, 385, 7225, 0), - (7827, 3, 385, 7325, 0), - (7827, 4, 385, 7425, 0), - (7828, 1, 310, 2000, 0), - (7828, 2, 385, 7225, 0), - (7828, 3, 385, 7325, 0), - (7828, 4, 385, 7425, 0), - (7828, 5, 385, 7525, 0), - (7828, 6, 385, 7625, 0), - (7829, 1, 310, 4000, 0), - (7829, 2, 385, 7225, 0), - (7829, 3, 385, 7325, 0), - (7829, 4, 385, 7425, 0), - (7829, 5, 385, 7525, 0), - (7829, 6, 385, 7625, 0), - (7830, 1, 310, 6000, 0), - (7830, 2, 385, 7225, 0), - (7830, 3, 385, 7325, 0), - (7830, 4, 385, 7425, 0), - (7830, 5, 385, 7525, 0), - (7830, 6, 385, 7625, 0), - (7832, 1, 264, 60, 60), - (7833, 2, 264, 120, 60), - (7834, 3, 264, 180, 60), - (7835, 4, 264, 240, 60), - (7836, 5, 264, 300, 60), - (7837, 1, 262, 55, 7), - (7837, 2, 262, 55, 8), - (7837, 3, 262, 55, 9), - (7837, 4, 262, 55, 10), - (7837, 5, 262, 55, 11), - (7838, 1, 262, 60, 7), - (7838, 2, 262, 60, 8), - (7838, 3, 262, 60, 9), - (7838, 4, 262, 60, 10), - (7838, 5, 262, 60, 11), - (7839, 1, 262, 65, 7), - (7839, 2, 262, 65, 8), - (7839, 3, 262, 65, 9), - (7839, 4, 262, 65, 10), - (7839, 5, 262, 65, 11), - (7840, 1, 262, 70, 7), - (7840, 2, 262, 70, 8), - (7840, 3, 262, 70, 9), - (7840, 4, 262, 70, 10), - (7840, 5, 262, 70, 11), - (7841, 1, 262, 75, 7), - (7841, 2, 262, 75, 8), - (7841, 3, 262, 75, 9), - (7841, 4, 262, 75, 10), - (7841, 5, 262, 75, 11), - (7842, 1, 339, 30, 27695), - (7842, 2, 138, 1, 0), - (7842, 3, 141, 1, 0), - (7842, 4, 142, 70, 0), - (7842, 5, 137, 0, 0), - (7842, 6, 311, 0, 0), - (7842, 7, 134, 100, 0), - (7842, 8, 139, -265, 0), - (7842, 9, 139, -754, 0), - (7842, 10, 139, -1332, 0), - (7842, 11, 139, -1572, 0), - (7842, 12, 139, -2749, 0), - (7842, 13, 139, -4979, 0), - (7842, 14, 139, -5418, 0), - (7842, 15, 139, -5403, 0), - (7842, 16, 348, 10, 0), - (7843, 1, 339, 31, 27696), - (7843, 2, 138, 1, 0), - (7843, 3, 141, 1, 0), - (7843, 4, 142, 70, 0), - (7843, 5, 137, 0, 0), - (7843, 6, 311, 0, 0), - (7843, 7, 134, 100, 0), - (7843, 8, 139, -265, 0), - (7843, 9, 139, -754, 0), - (7843, 10, 139, -1332, 0), - (7843, 11, 139, -1572, 0), - (7843, 12, 139, -2749, 0), - (7843, 13, 139, -4979, 0), - (7843, 14, 139, -5418, 0), - (7843, 15, 139, -5403, 0), - (7843, 16, 348, 10, 0), - (7844, 1, 339, 32, 27697), - (7844, 2, 138, 1, 0), - (7844, 3, 141, 1, 0), - (7844, 4, 142, 70, 0), - (7844, 5, 137, 0, 0), - (7844, 6, 311, 0, 0), - (7844, 7, 134, 100, 0), - (7844, 8, 139, -265, 0), - (7844, 9, 139, -754, 0), - (7844, 10, 139, -1332, 0), - (7844, 11, 139, -1572, 0), - (7844, 12, 139, -2749, 0), - (7844, 13, 139, -4979, 0), - (7844, 14, 139, -5418, 0), - (7844, 15, 139, -5403, 0), - (7844, 16, 348, 10, 0), - (7881, 1, 405, 13, 0), - (7882, 1, 405, 15, 0), - (7883, 1, 405, 17, 0), - (7884, 1, 287, 1, 0), - (7884, 2, 139, 4691, 0), - (7884, 3, 411, 128, 0), - (7885, 1, 287, 1, 0), - (7885, 2, 385, 8111, 0), - (7885, 3, 385, 15008, 0), - (7885, 4, 385, 8411, 0), - (7885, 5, 385, 8511, 0), - (7885, 6, 411, 128, 0), - (7886, 1, 328, 1300, 0), - (7887, 1, 328, 1350, 0), - (7888, 1, 328, 1400, 0), - (7889, 1, 328, 1450, 0), - (7890, 1, 328, 1500, 0), - (7900, 1, 339, 45, 16189), - (7900, 2, 136, 11, 0), - (7900, 3, 383, 45, 16189), - (7900, 4, 385, 11012, 0), - (7900, 5, 383, 45, 16189), - (7900, 6, 385, 5130, 0), - (7900, 7, 383, 45, 16189), - (7900, 8, 385, 5230, 0), - (7900, 9, 383, 45, 16189), - (7900, 10, 136, 22, 0), - (7900, 11, 383, 45, 16189), - (7900, 12, 385, 5330, 0), - (7900, 13, 385, 5430, 0), - (7900, 14, 385, 5530, 0), - (7901, 1, 339, 45, 16190), - (7901, 2, 136, 11, 0), - (7901, 3, 383, 45, 16190), - (7901, 4, 385, 11012, 0), - (7901, 5, 383, 45, 16190), - (7901, 6, 385, 5130, 0), - (7901, 7, 383, 45, 16190), - (7901, 8, 385, 5230, 0), - (7901, 9, 383, 45, 16190), - (7901, 10, 136, 22, 0), - (7901, 11, 383, 45, 16190), - (7901, 12, 385, 5330, 0), - (7901, 13, 385, 5430, 0), - (7901, 14, 385, 5530, 0), - (7902, 1, 339, 45, 16191), - (7902, 2, 136, 11, 0), - (7902, 3, 383, 45, 16191), - (7902, 4, 385, 11012, 0), - (7902, 5, 383, 45, 16191), - (7902, 6, 385, 5130, 0), - (7902, 7, 383, 45, 16191), - (7902, 8, 385, 5230, 0), - (7902, 9, 383, 45, 16191), - (7902, 10, 136, 22, 0), - (7902, 11, 383, 45, 16191), - (7902, 12, 385, 5330, 0), - (7902, 13, 385, 5430, 0), - (7902, 14, 385, 5530, 0), - (7904, 1, 0, 26, 0), - (7905, 1, 0, 27, 0), - (7906, 1, 0, 28, 0), - (7907, 1, 0, 29, 0), - (7908, 1, 0, 30, 0), - (7940, 1, 264, 15, 558), - (7941, 1, 264, 30, 558), - (7942, 1, 264, 45, 558), - (7945, 1, 310, 2000, 0), - (7945, 2, 139, 8007, 0), - (7945, 3, 310, 2000, 0), - (7945, 4, 385, 4140, 0), - (7945, 5, 385, 4240, 0), - (7945, 6, 385, 4340, 0), - (7945, 7, 385, 4440, 0), - (7945, 8, 385, 4540, 0), - (7945, 9, 385, 4640, 0), - (7946, 1, 310, 4000, 0), - (7946, 2, 139, 8007, 0), - (7946, 3, 310, 4000, 0), - (7946, 4, 385, 4140, 0), - (7946, 5, 385, 4240, 0), - (7946, 6, 385, 4340, 0), - (7946, 7, 385, 4440, 0), - (7946, 8, 385, 4540, 0), - (7946, 9, 385, 4640, 0), - (7947, 1, 310, 6000, 0), - (7947, 2, 139, 8007, 0), - (7947, 3, 310, 6000, 0), - (7947, 4, 385, 4140, 0), - (7947, 5, 385, 4240, 0), - (7947, 6, 385, 4340, 0), - (7947, 7, 385, 4440, 0), - (7947, 8, 385, 4540, 0), - (7947, 9, 385, 4640, 0), - (7948, 1, 339, 25, 16197), - (7948, 2, 138, 1, 0), - (7948, 3, 142, 60, 0), - (7948, 4, 137, 35, 0), - (7948, 5, 134, 75, 0), - (7948, 6, 339, 25, 16197), - (7948, 7, 138, 1, 0), - (7948, 8, 142, 60, 0), - (7948, 9, 137, 36, 0), - (7948, 10, 134, 75, 0), - (7948, 11, 339, 25, 16197), - (7948, 12, 138, 1, 0), - (7948, 13, 142, 60, 0), - (7948, 14, 137, 369, 0), - (7948, 15, 134, 75, 0), - (7948, 16, 339, 25, 16197), - (7948, 17, 138, 1, 0), - (7948, 18, 142, 60, 0), - (7948, 19, 137, 116, 0), - (7948, 20, 134, 75, 0), - (7949, 1, 339, 25, 16198), - (7949, 2, 138, 1, 0), - (7949, 3, 142, 60, 0), - (7949, 4, 137, 35, 0), - (7949, 5, 134, 80, 0), - (7949, 6, 339, 25, 16198), - (7949, 7, 138, 1, 0), - (7949, 8, 142, 60, 0), - (7949, 9, 137, 36, 0), - (7949, 10, 134, 80, 0), - (7949, 11, 339, 25, 16198), - (7949, 12, 138, 1, 0), - (7949, 13, 142, 60, 0), - (7949, 14, 137, 369, 0), - (7949, 15, 134, 80, 0), - (7949, 16, 339, 25, 16198), - (7949, 17, 138, 1, 0), - (7949, 18, 142, 60, 0), - (7949, 19, 137, 116, 0), - (7949, 20, 134, 80, 0), - (7950, 1, 339, 25, 16199), - (7950, 2, 138, 1, 0), - (7950, 3, 142, 60, 0), - (7950, 4, 137, 35, 0), - (7950, 5, 134, 85, 0), - (7950, 6, 339, 25, 16199), - (7950, 7, 138, 1, 0), - (7950, 8, 142, 60, 0), - (7950, 9, 137, 36, 0), - (7950, 10, 134, 85, 0), - (7950, 11, 339, 25, 16199), - (7950, 12, 138, 1, 0), - (7950, 13, 142, 60, 0), - (7950, 14, 137, 369, 0), - (7950, 15, 134, 85, 0), - (7950, 16, 339, 25, 16199), - (7950, 17, 138, 1, 0), - (7950, 18, 142, 60, 0), - (7950, 19, 137, 116, 0), - (7950, 20, 134, 85, 0), - (7980, 1, 243, 15, 0), - (7981, 1, 243, 25, 0), - (7982, 1, 243, 35, 0), - (7983, 1, 264, 120, 520), - (7984, 1, 264, 240, 520), - (7985, 1, 264, 360, 520), - (7989, 1, 264, 30, 705), - (7989, 2, 264, 30, 1092), - (7989, 3, 264, 30, 10396), - (7989, 4, 264, 30, 10397), - (7990, 1, 264, 60, 705), - (7990, 2, 264, 60, 1092), - (7990, 3, 264, 60, 10396), - (7990, 4, 264, 60, 10397), - (7991, 1, 264, 90, 705), - (7991, 2, 264, 90, 1092), - (7991, 3, 264, 90, 10396), - (7991, 4, 264, 90, 10397), - (7992, 1, 264, 120, 705), - (7992, 2, 264, 120, 1092), - (7992, 3, 264, 120, 10396), - (7992, 4, 264, 120, 10397), - (7994, 1, 264, 240, 39), - (7994, 2, 264, 3456, 1061), - (7995, 1, 264, 300, 39), - (7995, 2, 264, 4320, 1061), - (8000, 1, 69, 200, 0), - (8000, 2, 2, 75, 0), - (8000, 3, 97, 200, 0), - (8000, 4, 317, 8, 0), - (8031, 1, 264, 30, 791), - (8032, 1, 264, 60, 791), - (8033, 1, 264, 90, 791), - (8035, 1, 264, 180, 521), - (8036, 1, 264, 360, 521), - (8037, 1, 264, 540, 521), - (8040, 1, 128, 5, 5), - (8040, 2, 138, 1, 0), - (8040, 3, 140, 1, 0), - (8040, 4, 311, 0, 0), - (8040, 5, 411, 256, 0), - (8040, 6, 137, -40, 0), - (8040, 7, 391, 1, 0), - (8041, 1, 128, 15, 15), - (8041, 2, 138, 1, 0), - (8041, 3, 140, 1, 0), - (8041, 4, 311, 0, 0), - (8041, 5, 411, 256, 0), - (8041, 6, 137, -40, 0), - (8041, 7, 391, 1, 0), - (8042, 1, 128, 30, 30), - (8042, 2, 138, 1, 0), - (8042, 3, 140, 1, 0), - (8042, 4, 311, 0, 0), - (8042, 5, 411, 256, 0), - (8042, 6, 137, -40, 0), - (8042, 7, 391, 1, 0), - (8043, 1, 128, 50, 50), - (8043, 2, 138, 1, 0), - (8043, 3, 140, 1, 0), - (8043, 4, 311, 0, 0), - (8043, 5, 411, 256, 0), - (8043, 6, 137, -40, 0), - (8043, 7, 391, 1, 0), - (8059, 1, 128, 50, 50), - (8059, 2, 138, 1, 0), - (8059, 3, 140, 1, 0), - (8059, 4, 311, 0, 0), - (8059, 5, 411, 66434, 0), - (8059, 6, 137, -40, 0), - (8069, 1, 244, -10, 0), - (8070, 1, 244, -15, 0), - (8071, 1, 244, -20, 0), - (8076, 1, 264, 360, 565), - (8076, 2, 264, 360, 793), - (8076, 3, 264, 360, 794), - (8077, 1, 264, 720, 565), - (8077, 2, 264, 720, 793), - (8077, 3, 264, 720, 794), - (8078, 1, 264, 1080, 565), - (8078, 2, 264, 1080, 793), - (8078, 3, 264, 1080, 794), - (8079, 1, 264, 1440, 565), - (8079, 2, 264, 1440, 793), - (8079, 3, 264, 1440, 794), - (8080, 1, 264, 1800, 565), - (8080, 2, 264, 1800, 793), - (8080, 3, 264, 1800, 794), - (8081, 1, 264, 2160, 565), - (8081, 2, 264, 2160, 793), - (8081, 3, 264, 2160, 794), - (8082, 1, 264, 60, 208), - (8083, 1, 264, 120, 208), - (8084, 1, 264, 180, 208), - (8190, 1, 280, 2, 0), - (8191, 1, 280, 4, 0), - (8192, 1, 280, 6, 0), - (8193, 1, 339, 100, 16225), - (8193, 2, 139, 6838, 0), - (8195, 1, 264, 120, 3707), - (8196, 1, 264, 240, 3707), - (8197, 1, 264, 360, 3707), - (8198, 1, 294, 0, 110), - (8199, 1, 294, 0, 120), - (8200, 1, 294, 0, 130), - (8201, 1, 218, 1, 0), - (8202, 1, 218, 2, 0), - (8203, 1, 218, 3, 0), - (8204, 1, 127, 10, 0), - (8204, 2, 137, 154, 0), - (8204, 3, 403, 2, 0), - (8204, 4, 404, 10, 0), - (8205, 1, 127, 20, 0), - (8205, 2, 137, 154, 0), - (8205, 3, 403, 2, 0), - (8205, 4, 404, 10, 0), - (8206, 1, 127, 30, 0), - (8206, 2, 137, 154, 0), - (8206, 3, 403, 2, 0), - (8206, 4, 404, 10, 0), - (8207, 1, 127, 10, 0), - (8207, 2, 137, 154, 0), - (8207, 3, 403, 2, 0), - (8207, 4, 404, 10, 0), - (8208, 1, 127, 20, 0), - (8208, 2, 137, 154, 0), - (8208, 3, 403, 2, 0), - (8208, 4, 404, 10, 0), - (8209, 1, 127, 30, 0), - (8209, 2, 137, 154, 0), - (8209, 3, 403, 2, 0), - (8209, 4, 404, 10, 0), - (8210, 1, 97, 50, 0), - (8211, 1, 97, 100, 0), - (8212, 1, 97, 150, 0), - (8213, 1, 97, 200, 0), - (8214, 1, 97, 250, 0), - (8215, 1, 190, 50, 0), - (8216, 1, 190, 100, 0), - (8217, 1, 190, 150, 0), - (8218, 1, 190, 200, 0), - (8219, 1, 190, 250, 0), - (8223, 1, 128, 50, 50), - (8223, 2, 138, 1, 0), - (8223, 3, 140, 1, 0), - (8223, 4, 139, -2741, 0), - (8223, 5, 139, -16843, 0), - (8223, 6, 385, -16192, 0), - (8224, 1, 339, 10, 16230), - (8224, 2, 138, 1, 0), - (8224, 3, 141, 1, 0), - (8224, 4, 142, 60, 0), - (8224, 5, 137, 0, 0), - (8224, 6, 311, 0, 0), - (8224, 7, 134, 80, 0), - (8224, 8, 139, -265, 0), - (8224, 9, 139, -754, 0), - (8224, 10, 139, -1332, 0), - (8224, 11, 139, -1572, 0), - (8224, 12, 139, -2749, 0), - (8224, 13, 139, -4979, 0), - (8224, 14, 139, -5418, 0), - (8224, 15, 139, -5403, 0), - (8225, 1, 339, 10, 16231), - (8225, 2, 138, 1, 0), - (8225, 3, 141, 1, 0), - (8225, 4, 142, 65, 0), - (8225, 5, 137, 0, 0), - (8225, 6, 311, 0, 0), - (8225, 7, 134, 85, 0), - (8225, 8, 139, -265, 0), - (8225, 9, 139, -754, 0), - (8225, 10, 139, -1332, 0), - (8225, 11, 139, -1572, 0), - (8225, 12, 139, -2749, 0), - (8225, 13, 139, -4979, 0), - (8225, 14, 139, -5418, 0), - (8225, 15, 139, -5403, 0), - (8226, 1, 339, 10, 16232), - (8226, 2, 138, 1, 0), - (8226, 3, 141, 1, 0), - (8226, 4, 142, 70, 0), - (8226, 5, 137, 0, 0), - (8226, 6, 311, 0, 0), - (8226, 7, 134, 90, 0), - (8226, 8, 139, -265, 0), - (8226, 9, 139, -754, 0), - (8226, 10, 139, -1332, 0), - (8226, 11, 139, -1572, 0), - (8226, 12, 139, -2749, 0), - (8226, 13, 139, -4979, 0), - (8226, 14, 139, -5418, 0), - (8226, 15, 139, -5403, 0), - (8228, 1, 378, 5, 22), - (8229, 1, 378, 10, 22), - (8230, 1, 378, 15, 22), - (8232, 1, 128, 5, 5), - (8232, 2, 138, 1, 0), - (8232, 3, 140, 1, 0), - (8232, 4, 311, 0, 0), - (8232, 5, 411, 66434, 0), - (8232, 6, 137, -40, 0), - (8233, 1, 128, 15, 15), - (8233, 2, 138, 1, 0), - (8233, 3, 140, 1, 0), - (8233, 4, 311, 0, 0), - (8233, 5, 411, 66434, 0), - (8233, 6, 137, -40, 0), - (8234, 1, 128, 30, 30), - (8234, 2, 138, 1, 0), - (8234, 3, 140, 1, 0), - (8234, 4, 311, 0, 0), - (8234, 5, 411, 66434, 0), - (8234, 6, 137, -40, 0), - (8235, 1, 1, 29, 0), - (8236, 1, 1, 58, 0), - (8237, 1, 1, 87, 0), - (8238, 1, 1, 116, 0), - (8239, 1, 1, 145, 0), - (8240, 1, 1, 31, 0), - (8241, 1, 1, 62, 0), - (8242, 1, 1, 93, 0), - (8243, 1, 1, 124, 0), - (8244, 1, 1, 155, 0), - (8245, 1, 1, 33, 0), - (8246, 1, 1, 66, 0), - (8247, 1, 1, 99, 0), - (8248, 1, 1, 132, 0), - (8249, 1, 1, 165, 0), - (8250, 1, 1, 40, 0), - (8251, 1, 1, 80, 0), - (8252, 1, 1, 120, 0), - (8253, 1, 1, 160, 0), - (8254, 1, 1, 200, 0), - (8255, 1, 1, 50, 0), - (8256, 1, 1, 100, 0), - (8257, 1, 1, 150, 0), - (8258, 1, 1, 200, 0), - (8259, 1, 1, 250, 0), - (8261, 1, 128, 65, 65), - (8261, 2, 138, 1, 0), - (8261, 3, 140, 1, 0), - (8261, 4, 311, 0, 0), - (8261, 5, 411, 66434, 0), - (8261, 6, 137, -40, 0), - (8262, 1, 128, 70, 70), - (8262, 2, 138, 1, 0), - (8262, 3, 140, 1, 0), - (8262, 4, 139, -2741, 0), - (8262, 5, 139, -16843, 0), - (8262, 6, 385, -16192, 0), - (8263, 1, 262, 5, 0), - (8264, 1, 262, 10, 0), - (8265, 1, 262, 15, 0), - (8266, 1, 262, 20, 0), - (8267, 1, 262, 25, 0), - (8268, 1, 262, 5, 1), - (8269, 1, 262, 10, 1), - (8270, 1, 262, 15, 1), - (8271, 1, 262, 20, 1), - (8272, 1, 262, 25, 1), - (8273, 1, 262, 5, 2), - (8274, 1, 262, 10, 2), - (8275, 1, 262, 15, 2), - (8276, 1, 262, 20, 2), - (8277, 1, 262, 25, 2), - (8278, 1, 262, 5, 3), - (8279, 1, 262, 10, 3), - (8280, 1, 262, 15, 3), - (8281, 1, 262, 20, 3), - (8282, 1, 262, 25, 3), - (8283, 1, 262, 5, 4), - (8284, 1, 262, 10, 4), - (8285, 1, 262, 15, 4), - (8286, 1, 262, 20, 4), - (8287, 1, 262, 25, 4), - (8288, 1, 262, 5, 5), - (8289, 1, 262, 10, 5), - (8290, 1, 262, 15, 5), - (8291, 1, 262, 20, 5), - (8292, 1, 262, 25, 5), - (8293, 1, 262, 5, 6), - (8294, 1, 262, 10, 6), - (8295, 1, 262, 15, 6), - (8296, 1, 262, 20, 6), - (8297, 1, 262, 25, 6), - (8304, 1, 1, 174, 0), - (8305, 1, 1, 203, 0), - (8306, 1, 1, 232, 0), - (8307, 1, 1, 261, 0), - (8308, 1, 1, 290, 0), - (8313, 1, 128, 65, 65), - (8313, 2, 138, 1, 0), - (8313, 3, 140, 1, 0), - (8313, 4, 311, 0, 0), - (8313, 5, 411, 256, 0), - (8313, 6, 137, -40, 0), - (8313, 7, 391, 1, 0), - (8314, 1, 378, 2, 3), - (8315, 1, 378, 3, 3), - (8316, 1, 378, 4, 3), - (8317, 1, 264, 1, 8205), - (8318, 1, 264, 2, 8205), - (8319, 1, 264, 2, 199), - (8320, 1, 264, 4, 199), - (8321, 1, 264, 6, 199), - (8322, 1, 378, 15, 31), - (8323, 1, 378, 20, 31), - (8324, 1, 378, 25, 31), - (8325, 1, 114, -3, 0), - (8326, 1, 114, -6, 0), - (8327, 1, 114, -9, 0), - (8328, 1, 268, 75, 56), - (8328, 2, 234, 1000, 0), - (8329, 1, 227, 4, 29), - (8329, 2, 227, 4, 42), - (8331, 1, 413, 10, 0), - (8331, 2, 139, 8001, 0), - (8331, 3, 385, 12529, 0), - (8331, 4, 411, 512, 0), - (8332, 1, 287, 1, 0), - (8332, 2, 385, 116121, 0), - (8333, 1, 287, 2, 0), - (8333, 2, 385, 116121, 0), - (8334, 1, 287, 3, 0), - (8334, 2, 385, 116121, 0), - (8335, 1, 127, 10, 0), - (8335, 2, 385, 16188, 0), - (8336, 1, 127, 20, 0), - (8336, 2, 385, 16188, 0), - (8337, 1, 127, 30, 0), - (8337, 2, 385, 16188, 0), - (8338, 1, 127, 40, 0), - (8338, 2, 385, 16188, 0), - (8339, 1, 127, 50, 0), - (8339, 2, 385, 16188, 0), - (8344, 1, 294, 0, 175), - (8345, 1, 294, 0, 180), - (8346, 1, 294, 0, 185), - (8347, 1, 264, 600, 616), - (8348, 1, 264, 1200, 616), - (8349, 1, 264, 1800, 616), - (8350, 1, 310, 1200, 0), - (8350, 2, 385, 6212, 0), - (8350, 3, 310, 600, 0), - (8350, 4, 385, 6215, 0), - (8350, 5, 310, 150, 0), - (8350, 6, 385, 6218, 0), - (8350, 7, 310, 9000, 0), - (8350, 8, 385, 6232, 0), - (8350, 9, 310, 600, 0), - (8350, 10, 385, 6243, 0), - (8350, 11, 310, 150, 0), - (8350, 12, 385, 6245, 0), - (8350, 13, 310, 1200, 0), - (8350, 14, 385, 6412, 0), - (8350, 15, 310, 600, 0), - (8350, 16, 385, 6415, 0), - (8350, 17, 310, 150, 0), - (8350, 18, 385, 6418, 0), - (8350, 19, 310, 9000, 0), - (8350, 20, 385, 6432, 0), - (8350, 21, 310, 600, 0), - (8350, 22, 385, 6443, 0), - (8350, 23, 310, 150, 0), - (8350, 24, 385, 6445, 0), - (8351, 1, 262, 30, 0), - (8352, 1, 262, 35, 0), - (8353, 1, 262, 40, 0), - (8354, 1, 262, 45, 0), - (8355, 1, 262, 50, 0), - (8356, 1, 262, 55, 0), - (8357, 1, 262, 60, 0), - (8358, 1, 262, 65, 0), - (8359, 1, 262, 70, 0), - (8360, 1, 262, 75, 0), - (8361, 1, 262, 30, 1), - (8362, 1, 262, 35, 1), - (8363, 1, 262, 40, 1), - (8364, 1, 262, 45, 1), - (8365, 1, 262, 50, 1), - (8366, 1, 262, 55, 1), - (8367, 1, 262, 60, 1), - (8368, 1, 262, 65, 1), - (8369, 1, 262, 70, 1), - (8370, 1, 262, 75, 1), - (8371, 1, 262, 30, 2), - (8372, 1, 262, 35, 2), - (8373, 1, 262, 40, 2), - (8374, 1, 262, 45, 2), - (8375, 1, 262, 50, 2), - (8376, 1, 262, 55, 2), - (8377, 1, 262, 60, 2), - (8378, 1, 262, 65, 2), - (8379, 1, 262, 70, 2), - (8380, 1, 262, 75, 2), - (8381, 1, 262, 30, 3), - (8382, 1, 262, 35, 3), - (8383, 1, 262, 40, 3), - (8384, 1, 262, 45, 3), - (8385, 1, 262, 50, 3), - (8386, 1, 262, 55, 3), - (8387, 1, 262, 60, 3), - (8388, 1, 262, 65, 3), - (8389, 1, 262, 70, 3), - (8390, 1, 262, 75, 3), - (8391, 1, 262, 30, 4), - (8392, 1, 262, 35, 4), - (8393, 1, 262, 40, 4), - (8394, 1, 262, 45, 4), - (8395, 1, 262, 50, 4), - (8396, 1, 262, 55, 4), - (8397, 1, 262, 60, 4), - (8398, 1, 262, 65, 4), - (8399, 1, 262, 70, 4), - (8400, 1, 262, 75, 4), - (8401, 1, 262, 30, 5), - (8402, 1, 262, 35, 5), - (8403, 1, 262, 40, 5), - (8404, 1, 262, 45, 5), - (8405, 1, 262, 50, 5), - (8406, 1, 262, 55, 5), - (8407, 1, 262, 60, 5), - (8408, 1, 262, 65, 5), - (8409, 1, 262, 70, 5), - (8410, 1, 262, 75, 5), - (8411, 1, 262, 30, 6), - (8412, 1, 262, 35, 6), - (8413, 1, 262, 40, 6), - (8414, 1, 262, 45, 6), - (8415, 1, 262, 50, 6), - (8416, 1, 262, 55, 6), - (8417, 1, 262, 60, 6), - (8418, 1, 262, 65, 6), - (8419, 1, 262, 70, 6), - (8420, 1, 262, 75, 6), - (8421, 1, 339, 10, 27535), - (8421, 2, 138, 1, 0), - (8421, 3, 141, 1, 0), - (8421, 4, 142, 75, 0), - (8421, 5, 137, 0, 0), - (8421, 6, 311, 0, 0), - (8421, 7, 134, 95, 0), - (8421, 8, 139, -265, 0), - (8421, 9, 139, -754, 0), - (8421, 10, 139, -1332, 0), - (8421, 11, 139, -1572, 0), - (8421, 12, 139, -2749, 0), - (8421, 13, 139, -4979, 0), - (8421, 14, 139, -5418, 0), - (8421, 15, 139, -5403, 0), - (8422, 1, 1, 198, 0), - (8423, 1, 1, 231, 0), - (8424, 1, 1, 264, 0), - (8425, 1, 1, 297, 0), - (8426, 1, 1, 330, 0), - (8427, 1, 264, 1260, 254), - (8428, 1, 264, 1440, 254), - (8429, 1, 264, 1620, 254), - (8430, 1, 328, 1600, 0), - (8435, 1, 0, 35, 0), - (8440, 1, 259, 66, 0), - (8445, 1, 426, 3, 0), - (8446, 1, 426, 4, 0), - (8447, 1, 426, 5, 0), - (8448, 1, 69, 2200, 0), - (8463, 1, 172, 60, 0), - (8464, 1, 172, 61, 0), - (8470, 1, 262, 80, 7), - (8470, 2, 262, 80, 8), - (8470, 3, 262, 80, 9), - (8470, 4, 262, 80, 10), - (8470, 5, 262, 80, 11), - (9001, 1, 247, 10, 58), - (9002, 1, 247, 20, 58), - (9003, 1, 247, 30, 58), - (9004, 1, 247, 40, 58), - (9005, 1, 247, 50, 58), - (9006, 1, 247, 60, 58), - (9007, 1, 247, 70, 58), - (9008, 1, 247, 80, 58), - (9009, 1, 247, 90, 58), - (9010, 1, 247, 100, 58), - (9011, 1, 247, 10, 58), - (9012, 1, 247, 20, 58), - (9013, 1, 247, 30, 58), - (9014, 1, 247, 40, 58), - (9015, 1, 247, 50, 58), - (9016, 1, 247, 60, 58), - (9017, 1, 247, 70, 58), - (9018, 1, 247, 80, 58), - (9019, 1, 247, 90, 58), - (9020, 1, 247, 100, 58), - (9021, 1, 247, 10, 58), - (9022, 1, 247, 20, 58), - (9023, 1, 247, 30, 58), - (9024, 1, 247, 40, 58), - (9025, 1, 247, 50, 58), - (9026, 1, 247, 60, 58), - (9027, 1, 247, 70, 58), - (9028, 1, 247, 80, 58), - (9029, 1, 247, 90, 58), - (9030, 1, 247, 100, 58), - (9033, 1, 264, 18000, 481), - (9033, 2, 264, 18000, 482), - (9033, 3, 264, 18000, 483), - (9033, 4, 264, 147600, 484), - (9033, 5, 264, 18000, 485), - (9033, 6, 264, 61200, 486), - (9033, 7, 264, 3600, 487), - (9033, 8, 264, 1080, 511), - (9033, 9, 264, 18000, 182), - (9033, 10, 264, 18000, 8081), - (9033, 11, 264, 18000, 8130), - (9033, 12, 264, 18000, 453), - (9033, 13, 264, 18000, 2000), - (9100, 1, 97, 10, 0), - (9100, 2, 262, 1, 5), - (9101, 1, 97, 20, 0), - (9101, 2, 262, 2, 5), - (9102, 1, 97, 30, 0), - (9102, 2, 262, 3, 5), - (9103, 1, 97, 40, 0), - (9103, 2, 262, 4, 5), - (9104, 1, 97, 50, 0), - (9104, 2, 262, 5, 5), - (9105, 1, 97, 60, 0), - (9105, 2, 262, 6, 5), - (9106, 1, 97, 70, 0), - (9106, 2, 262, 7, 5), - (9107, 1, 97, 80, 0), - (9107, 2, 262, 8, 5), - (9108, 1, 97, 90, 0), - (9108, 2, 262, 9, 5), - (9109, 1, 69, 10, 0), - (9109, 2, 262, 1, 1), - (9110, 1, 69, 20, 0), - (9110, 2, 262, 2, 1), - (9111, 1, 69, 30, 0), - (9111, 2, 262, 3, 1), - (9112, 1, 69, 40, 0), - (9112, 2, 262, 4, 1), - (9113, 1, 69, 50, 0), - (9113, 2, 262, 5, 1), - (9114, 1, 69, 60, 0), - (9114, 2, 262, 6, 1), - (9115, 1, 69, 70, 0), - (9115, 2, 262, 7, 1), - (9116, 1, 69, 80, 0), - (9116, 2, 262, 8, 1), - (9117, 1, 69, 90, 0), - (9117, 2, 262, 9, 1), - (9118, 1, 97, 10, 0), - (9118, 2, 262, 1, 5), - (9119, 1, 97, 20, 0), - (9119, 2, 262, 2, 5), - (9120, 1, 97, 30, 0), - (9120, 2, 262, 3, 5), - (9121, 1, 97, 40, 0), - (9121, 2, 262, 4, 5), - (9122, 1, 97, 50, 0), - (9122, 2, 262, 5, 5), - (9123, 1, 97, 60, 0), - (9123, 2, 262, 6, 5), - (9124, 1, 97, 70, 0), - (9124, 2, 262, 7, 5), - (9125, 1, 97, 80, 0), - (9125, 2, 262, 8, 5), - (9126, 1, 97, 90, 0), - (9126, 2, 262, 9, 5), - (9127, 1, 69, 10, 0), - (9127, 2, 262, 1, 5), - (9128, 1, 69, 20, 0), - (9128, 2, 262, 2, 5), - (9129, 1, 69, 30, 0), - (9129, 2, 262, 3, 5), - (9130, 1, 69, 40, 0), - (9130, 2, 262, 4, 5), - (9131, 1, 69, 50, 0), - (9131, 2, 262, 5, 5), - (9132, 1, 69, 60, 0), - (9132, 2, 262, 6, 5), - (9133, 1, 69, 70, 0), - (9133, 2, 262, 7, 5), - (9134, 1, 69, 80, 0), - (9134, 2, 262, 8, 5), - (9135, 1, 69, 90, 0), - (9135, 2, 262, 9, 5), - (9136, 1, 97, 10, 0), - (9136, 2, 262, 1, 4), - (9137, 1, 97, 20, 0), - (9137, 2, 262, 2, 4), - (9138, 1, 97, 30, 0), - (9138, 2, 262, 3, 4), - (9139, 1, 97, 40, 0), - (9139, 2, 262, 4, 4), - (9140, 1, 97, 50, 0), - (9140, 2, 262, 5, 4), - (9141, 1, 97, 60, 0), - (9141, 2, 262, 6, 4), - (9142, 1, 97, 70, 0), - (9142, 2, 262, 7, 4), - (9143, 1, 97, 80, 0), - (9143, 2, 262, 8, 4), - (9144, 1, 97, 90, 0), - (9144, 2, 262, 9, 4), - (9145, 1, 97, 10, 0), - (9145, 2, 262, 1, 4), - (9146, 1, 97, 20, 0), - (9146, 2, 262, 2, 4), - (9147, 1, 97, 30, 0), - (9147, 2, 262, 3, 4), - (9148, 1, 97, 40, 0), - (9148, 2, 262, 4, 4), - (9149, 1, 97, 50, 0), - (9149, 2, 262, 5, 4), - (9150, 1, 97, 60, 0), - (9150, 2, 262, 6, 4), - (9151, 1, 97, 70, 0), - (9151, 2, 262, 7, 4), - (9152, 1, 97, 80, 0), - (9152, 2, 262, 8, 4), - (9153, 1, 97, 90, 0), - (9153, 2, 262, 9, 4), - (9154, 1, 69, 10, 0), - (9154, 2, 262, 1, 1), - (9155, 1, 69, 20, 0), - (9155, 2, 262, 2, 1), - (9156, 1, 69, 30, 0), - (9156, 2, 262, 3, 1), - (9157, 1, 69, 40, 0), - (9157, 2, 262, 4, 1), - (9158, 1, 69, 50, 0), - (9158, 2, 262, 5, 1), - (9159, 1, 69, 60, 0), - (9159, 2, 262, 6, 1), - (9160, 1, 69, 70, 0), - (9160, 2, 262, 7, 1), - (9161, 1, 69, 80, 0), - (9161, 2, 262, 8, 1), - (9162, 1, 69, 90, 0), - (9162, 2, 262, 9, 1), - (9163, 1, 69, 10, 0), - (9163, 2, 262, 1, 3), - (9164, 1, 69, 20, 0), - (9164, 2, 262, 2, 3), - (9165, 1, 69, 30, 0), - (9165, 2, 262, 3, 3), - (9166, 1, 69, 40, 0), - (9166, 2, 262, 4, 3), - (9167, 1, 69, 50, 0), - (9167, 2, 262, 5, 3), - (9168, 1, 69, 60, 0), - (9168, 2, 262, 6, 3), - (9169, 1, 69, 70, 0), - (9169, 2, 262, 7, 3), - (9170, 1, 69, 80, 0), - (9170, 2, 262, 8, 3), - (9171, 1, 69, 90, 0), - (9171, 2, 262, 9, 3), - (9172, 1, 69, 10, 0), - (9172, 2, 262, 1, 0), - (9173, 1, 69, 20, 0), - (9173, 2, 262, 2, 0), - (9174, 1, 69, 30, 0), - (9174, 2, 262, 3, 0), - (9175, 1, 69, 40, 0), - (9175, 2, 262, 4, 0), - (9176, 1, 69, 50, 0), - (9176, 2, 262, 5, 0), - (9177, 1, 69, 60, 0), - (9177, 2, 262, 6, 0), - (9178, 1, 69, 70, 0), - (9178, 2, 262, 7, 0), - (9179, 1, 69, 80, 0), - (9179, 2, 262, 8, 0), - (9180, 1, 69, 90, 0), - (9180, 2, 262, 9, 0), - (9181, 1, 69, 10, 0), - (9181, 2, 262, 1, 0), - (9182, 1, 69, 20, 0), - (9182, 2, 262, 2, 0), - (9183, 1, 69, 30, 0), - (9183, 2, 262, 3, 0), - (9184, 1, 69, 40, 0), - (9184, 2, 262, 4, 0), - (9185, 1, 69, 50, 0), - (9185, 2, 262, 5, 0), - (9186, 1, 69, 60, 0), - (9186, 2, 262, 6, 0), - (9187, 1, 69, 70, 0), - (9187, 2, 262, 7, 0), - (9188, 1, 69, 80, 0), - (9188, 2, 262, 8, 0), - (9189, 1, 69, 90, 0), - (9189, 2, 262, 9, 0), - (9190, 1, 69, 10, 0), - (9190, 2, 262, 1, 0), - (9191, 1, 69, 20, 0), - (9191, 2, 262, 2, 0), - (9192, 1, 69, 30, 0), - (9192, 2, 262, 3, 0), - (9193, 1, 69, 40, 0), - (9193, 2, 262, 4, 0), - (9194, 1, 69, 50, 0), - (9194, 2, 262, 5, 0), - (9195, 1, 69, 60, 0), - (9195, 2, 262, 6, 0), - (9196, 1, 69, 70, 0), - (9196, 2, 262, 7, 0), - (9197, 1, 69, 80, 0), - (9197, 2, 262, 8, 0), - (9198, 1, 69, 90, 0), - (9198, 2, 262, 9, 0), - (9199, 1, 97, 10, 0), - (9199, 2, 262, 1, 0), - (9200, 1, 97, 20, 0), - (9200, 2, 262, 2, 0), - (9201, 1, 97, 30, 0), - (9201, 2, 262, 3, 0), - (9202, 1, 97, 40, 0), - (9202, 2, 262, 4, 0), - (9203, 1, 97, 50, 0), - (9203, 2, 262, 5, 0), - (9204, 1, 97, 60, 0), - (9204, 2, 262, 6, 0), - (9205, 1, 97, 70, 0), - (9205, 2, 262, 7, 0), - (9206, 1, 97, 80, 0), - (9206, 2, 262, 8, 0), - (9207, 1, 97, 90, 0), - (9207, 2, 262, 9, 0), - (9208, 1, 69, 10, 0), - (9208, 2, 262, 1, 0), - (9209, 1, 69, 20, 0), - (9209, 2, 262, 2, 0), - (9210, 1, 69, 30, 0), - (9210, 2, 262, 3, 0), - (9211, 1, 69, 40, 0), - (9211, 2, 262, 4, 0), - (9212, 1, 69, 50, 0), - (9212, 2, 262, 5, 0), - (9213, 1, 69, 60, 0), - (9213, 2, 262, 6, 0), - (9214, 1, 69, 70, 0), - (9214, 2, 262, 7, 0), - (9215, 1, 69, 80, 0), - (9215, 2, 262, 8, 0), - (9216, 1, 69, 90, 0), - (9216, 2, 262, 9, 0), - (9217, 1, 190, 10, 0), - (9217, 2, 262, 1, 0), - (9218, 1, 190, 20, 0), - (9218, 2, 262, 2, 0), - (9219, 1, 190, 30, 0), - (9219, 2, 262, 3, 0), - (9220, 1, 190, 40, 0), - (9220, 2, 262, 4, 0), - (9221, 1, 190, 50, 0), - (9221, 2, 262, 5, 0), - (9222, 1, 190, 60, 0), - (9222, 2, 262, 6, 0), - (9223, 1, 190, 70, 0), - (9223, 2, 262, 7, 0), - (9224, 1, 190, 80, 0), - (9224, 2, 262, 8, 0), - (9225, 1, 190, 90, 0), - (9225, 2, 262, 9, 0), - (9226, 1, 69, 10, 0), - (9226, 2, 262, 1, 0), - (9227, 1, 69, 20, 0), - (9227, 2, 262, 2, 0), - (9228, 1, 69, 30, 0), - (9228, 2, 262, 3, 0), - (9229, 1, 69, 40, 0), - (9229, 2, 262, 4, 0), - (9230, 1, 69, 50, 0), - (9230, 2, 262, 5, 0), - (9231, 1, 69, 60, 0), - (9231, 2, 262, 6, 0), - (9232, 1, 69, 70, 0), - (9232, 2, 262, 7, 0), - (9233, 1, 69, 80, 0), - (9233, 2, 262, 8, 0), - (9234, 1, 69, 90, 0), - (9234, 2, 262, 9, 0), - (9235, 1, 190, 10, 0), - (9235, 2, 262, 1, 0), - (9236, 1, 190, 20, 0), - (9236, 2, 262, 2, 0), - (9237, 1, 190, 30, 0), - (9237, 2, 262, 3, 0), - (9238, 1, 190, 40, 0), - (9238, 2, 262, 4, 0), - (9239, 1, 190, 50, 0), - (9239, 2, 262, 5, 0), - (9240, 1, 190, 60, 0), - (9240, 2, 262, 6, 0), - (9241, 1, 190, 70, 0), - (9241, 2, 262, 7, 0), - (9242, 1, 190, 80, 0), - (9242, 2, 262, 8, 0), - (9243, 1, 190, 90, 0), - (9243, 2, 262, 9, 0), - (9503, 1, 397, 100, 0), - (9504, 1, 397, 200, 0), - (9505, 1, 397, 300, 0), - (9506, 1, 398, 1000, 0), - (9506, 2, 137, 152, 0), - (9507, 1, 398, 2000, 0), - (9507, 2, 137, 152, 0), - (9508, 1, 398, 3000, 0), - (9508, 2, 137, 152, 0), - (9509, 1, 399, 1, 0), - (9509, 2, 141, 1, 0), - (9509, 3, 138, 0, 0), - (9509, 4, 134, 254, 0), - (9509, 5, 348, 10, 0), - (9509, 6, 137, 0, 0), - (9509, 7, 311, 0, 0), - (9509, 8, 137, -152, 0), - (9509, 9, 137, -39, 0), - (9510, 1, 399, 2, 0), - (9510, 2, 141, 1, 0), - (9510, 3, 138, 0, 0), - (9510, 4, 134, 254, 0), - (9510, 5, 348, 10, 0), - (9510, 6, 137, 0, 0), - (9510, 7, 311, 0, 0), - (9510, 8, 137, -152, 0), - (9510, 9, 137, -39, 0), - (9511, 1, 399, 3, 0), - (9511, 2, 141, 1, 0), - (9511, 3, 138, 0, 0), - (9511, 4, 134, 254, 0), - (9511, 5, 348, 10, 0), - (9511, 6, 137, 0, 0), - (9511, 7, 311, 0, 0), - (9511, 8, 137, -152, 0), - (9511, 9, 137, -39, 0), - (9512, 1, 405, 1, 0), - (9513, 1, 405, 3, 0), - (9514, 1, 405, 5, 0), - (9515, 1, 399, 4, 0), - (9515, 2, 141, 1, 0), - (9515, 3, 138, 0, 0), - (9515, 4, 134, 254, 0), - (9515, 5, 348, 10, 0), - (9515, 6, 137, 0, 0), - (9515, 7, 311, 0, 0), - (9515, 8, 137, -152, 0), - (9515, 9, 137, -39, 0), - (10004, 1, 310, 480000, 0), - (10004, 2, 139, 4674, 0), - (10005, 1, 310, 600000, 0), - (10005, 2, 139, 4674, 0), - (10007, 1, 85, 16500, 50), - (10008, 1, 85, 16501, 50), - (10009, 1, 85, 16502, 50), - (10025, 1, 339, 25, 16517), - (10025, 2, 137, 21, 0), - (10026, 1, 339, 25, 16518), - (10026, 2, 137, 21, 0), - (10027, 1, 339, 25, 16519), - (10027, 2, 137, 21, 0), - (10028, 1, 339, 25, 16520), - (10028, 2, 137, 21, 0), - (10029, 1, 339, 25, 16555), - (10029, 2, 137, 21, 0), - (10030, 1, 264, 60, 558), - (10031, 1, 264, 75, 558), - (10032, 1, 264, 90, 558), - (10033, 1, 310, 8000, 0), - (10033, 2, 139, 8007, 0), - (10033, 3, 310, 8000, 0), - (10033, 4, 385, 4140, 0), - (10033, 5, 385, 4240, 0), - (10033, 6, 385, 4340, 0), - (10033, 7, 385, 4440, 0), - (10033, 8, 385, 4540, 0), - (10033, 9, 385, 4640, 0), - (10034, 1, 310, 10000, 0), - (10034, 2, 139, 8007, 0), - (10034, 3, 310, 10000, 0), - (10034, 4, 385, 4140, 0), - (10034, 5, 385, 4240, 0), - (10034, 6, 385, 4340, 0), - (10034, 7, 385, 4440, 0), - (10034, 8, 385, 4540, 0), - (10034, 9, 385, 4640, 0), - (10035, 1, 339, 25, 16556), - (10035, 2, 138, 1, 0), - (10035, 3, 142, 60, 0), - (10035, 4, 137, 35, 0), - (10035, 5, 134, 85, 0), - (10035, 6, 339, 25, 16556), - (10035, 7, 138, 1, 0), - (10035, 8, 142, 60, 0), - (10035, 9, 137, 36, 0), - (10035, 10, 134, 85, 0), - (10035, 11, 339, 25, 16556), - (10035, 12, 138, 1, 0), - (10035, 13, 142, 60, 0), - (10035, 14, 137, 369, 0), - (10035, 15, 134, 85, 0), - (10035, 16, 339, 25, 16556), - (10035, 17, 138, 1, 0), - (10035, 18, 142, 60, 0), - (10035, 19, 137, 116, 0), - (10035, 20, 134, 85, 0), - (10036, 1, 339, 25, 16557), - (10036, 2, 138, 1, 0), - (10036, 3, 142, 60, 0), - (10036, 4, 137, 35, 0), - (10036, 5, 134, 85, 0), - (10036, 6, 339, 25, 16557), - (10036, 7, 138, 1, 0), - (10036, 8, 142, 60, 0), - (10036, 9, 137, 36, 0), - (10036, 10, 134, 85, 0), - (10036, 11, 339, 25, 16557), - (10036, 12, 138, 1, 0), - (10036, 13, 142, 60, 0), - (10036, 14, 137, 369, 0), - (10036, 15, 134, 85, 0), - (10036, 16, 339, 25, 16557), - (10036, 17, 138, 1, 0), - (10036, 18, 142, 60, 0), - (10036, 19, 137, 116, 0), - (10036, 20, 134, 85, 0), - (10037, 1, 339, 25, 16558), - (10037, 2, 138, 1, 0), - (10037, 3, 142, 60, 0), - (10037, 4, 137, 35, 0), - (10037, 5, 134, 85, 0), - (10037, 6, 339, 25, 16558), - (10037, 7, 138, 1, 0), - (10037, 8, 142, 60, 0), - (10037, 9, 137, 36, 0), - (10037, 10, 134, 85, 0), - (10037, 11, 339, 25, 16558), - (10037, 12, 138, 1, 0), - (10037, 13, 142, 60, 0), - (10037, 14, 137, 369, 0), - (10037, 15, 134, 85, 0), - (10037, 16, 339, 25, 16558), - (10037, 17, 138, 1, 0), - (10037, 18, 142, 60, 0), - (10037, 19, 137, 116, 0), - (10037, 20, 134, 85, 0), - (10041, 1, 294, 0, 135), - (10042, 1, 294, 0, 145), - (10043, 1, 294, 0, 155), - (10044, 1, 339, 20, 16564), - (10044, 2, 137, 21, 0), - (10044, 3, 385, -18000, 0), - (10044, 4, 339, 20, 16564), - (10044, 5, 137, 343, 0), - (10044, 6, 385, -18000, 0), - (10045, 1, 339, 20, 16565), - (10045, 2, 137, 21, 0), - (10045, 3, 385, -18000, 0), - (10045, 4, 339, 20, 16565), - (10045, 5, 137, 343, 0), - (10045, 6, 385, -18000, 0), - (10046, 1, 339, 20, 16566), - (10046, 2, 137, 21, 0), - (10046, 3, 385, -18000, 0), - (10046, 4, 339, 20, 16566), - (10046, 5, 137, 343, 0), - (10046, 6, 385, -18000, 0), - (10050, 1, 85, 16567, 0), - (10051, 1, 85, 16568, 0), - (10052, 1, 85, 16569, 0), - (10058, 1, 330, 55, 7), - (10059, 1, 330, 60, 7), - (10060, 1, 330, 65, 7), - (10064, 1, 347, 25, 0), - (10065, 1, 347, 26, 0), - (10066, 1, 347, 27, 0), - (10067, 1, 347, 28, 0), - (10068, 1, 347, 29, 0), - (10069, 1, 347, 30, 0), - (10070, 1, 218, 6, 0), - (10071, 1, 218, 7, 0), - (10072, 1, 218, 8, 0), - (10073, 1, 218, 9, 0), - (10074, 1, 218, 10, 0), - (10075, 1, 339, 10, 16581), - (10075, 2, 138, 0, 0), - (10075, 3, 142, 70, 0), - (10075, 4, 403, 4, 0), - (10075, 5, 348, 1, 0), - (10075, 6, 404, 2, 0), - (10075, 7, 141, 1, 0), - (10076, 1, 339, 10, 16582), - (10076, 2, 138, 0, 0), - (10076, 3, 142, 70, 0), - (10076, 4, 403, 4, 0), - (10076, 5, 348, 1, 0), - (10076, 6, 404, 2, 0), - (10076, 7, 141, 1, 0), - (10077, 1, 339, 10, 16583), - (10077, 2, 138, 0, 0), - (10077, 3, 142, 70, 0), - (10077, 4, 403, 4, 0), - (10077, 5, 348, 1, 0), - (10077, 6, 404, 2, 0), - (10077, 7, 141, 1, 0), - (10081, 1, 85, 16584, 0), - (10082, 1, 85, 16585, 0), - (10083, 1, 85, 16586, 0), - (10084, 1, 375, 175, 0), - (10085, 1, 375, 200, 0), - (10086, 1, 375, 215, 0), - (10087, 1, 397, 400, 0), - (10088, 1, 397, 600, 0), - (10089, 1, 397, 800, 0), - (10105, 1, 264, 60, 170), - (10106, 1, 264, 70, 170), - (10107, 1, 264, 80, 170), - (10108, 1, 264, 90, 170), - (10109, 1, 264, 100, 170), - (10110, 1, 264, 480, 520), - (10111, 1, 264, 600, 520), - (10112, 1, 264, 720, 520), - (10122, 1, 227, 210, 32), - (10123, 1, 227, 240, 32), - (10124, 1, 283, 180, 0), - (10125, 1, 283, 200, 0), - (10126, 1, 283, 220, 0), - (10130, 1, 264, 720, 544), - (10131, 1, 264, 900, 544), - (10132, 1, 264, 1080, 544), - (10133, 1, 279, 19, 0), - (10134, 1, 279, 23, 0), - (10135, 1, 279, 27, 0), - (10136, 1, 375, 130, 0), - (10137, 1, 375, 135, 0), - (10138, 1, 375, 140, 0), - (10153, 1, 264, 420, 553), - (10154, 1, 264, 480, 553), - (10155, 1, 264, 540, 553), - (10165, 1, 220, 195, 8), - (10166, 1, 220, 225, 8), - (10167, 1, 220, 255, 8), - (10171, 1, 252, 90, 0), - (10172, 1, 252, 95, 0), - (10173, 1, 258, 70, 0), - (10174, 1, 258, 71, 0), - (10175, 1, 258, 72, 0), - (10176, 1, 264, 40, 171), - (10177, 1, 264, 50, 171), - (10178, 1, 264, 60, 171), - (10182, 1, 264, 180, 177), - (10183, 1, 264, 210, 177), - (10184, 1, 264, 240, 177), - (10185, 1, 264, 270, 177), - (10186, 1, 264, 300, 177), - (10203, 1, 264, 720, 524), - (10204, 1, 264, 900, 524), - (10205, 1, 264, 1080, 524), - (10206, 1, 264, 1080, 320), - (10207, 1, 264, 1260, 320), - (10213, 1, 218, 16, 0), - (10214, 1, 218, 17, 0), - (10215, 1, 218, 18, 0), - (10216, 1, 218, 19, 0), - (10217, 1, 218, 20, 0), - (10219, 1, 280, 63, 0), - (10220, 1, 280, 64, 0), - (10221, 1, 280, 65, 0), - (10222, 1, 280, 66, 0), - (10223, 1, 280, 67, 0), - (10227, 1, 360, 60, 16720), - (10228, 1, 360, 60, 16721), - (10229, 1, 360, 60, 16722), - (10249, 1, 264, 240, 208), - (10250, 1, 264, 300, 208), - (10251, 1, 264, 360, 208), - (10262, 1, 274, 23, 0), - (10263, 1, 274, 24, 0), - (10264, 1, 274, 25, 0), - (10265, 1, 280, 57, 0), - (10266, 1, 280, 58, 0), - (10267, 1, 280, 59, 0), - (10268, 1, 339, 45, 16736), - (10268, 2, 136, 11, 0), - (10268, 3, 383, 45, 16736), - (10268, 4, 385, 11012, 0), - (10268, 5, 383, 45, 16736), - (10268, 6, 385, 5130, 0), - (10268, 7, 383, 45, 16736), - (10268, 8, 385, 5230, 0), - (10268, 9, 383, 45, 16736), - (10268, 10, 136, 22, 0), - (10268, 11, 383, 45, 16736), - (10268, 12, 385, 5330, 0), - (10268, 13, 385, 5430, 0), - (10268, 14, 385, 5530, 0), - (10269, 1, 339, 45, 16737), - (10269, 2, 136, 11, 0), - (10269, 3, 383, 45, 16737), - (10269, 4, 385, 11012, 0), - (10269, 5, 383, 45, 16737), - (10269, 6, 385, 5130, 0), - (10269, 7, 383, 45, 16737), - (10269, 8, 385, 5230, 0), - (10269, 9, 383, 45, 16737), - (10269, 10, 136, 22, 0), - (10269, 11, 383, 45, 16737), - (10269, 12, 385, 5330, 0), - (10269, 13, 385, 5430, 0), - (10269, 14, 385, 5530, 0), - (10270, 1, 339, 45, 16738), - (10270, 2, 136, 11, 0), - (10270, 3, 383, 45, 16738), - (10270, 4, 385, 11012, 0), - (10270, 5, 383, 45, 16738), - (10270, 6, 385, 5130, 0), - (10270, 7, 383, 45, 16738), - (10270, 8, 385, 5230, 0), - (10270, 9, 383, 45, 16738), - (10270, 10, 136, 22, 0), - (10270, 11, 383, 45, 16738), - (10270, 12, 385, 5330, 0), - (10270, 13, 385, 5430, 0), - (10270, 14, 385, 5530, 0), - (10282, 1, 264, 120, 791), - (10283, 1, 264, 150, 791), - (10284, 1, 264, 180, 791), - (10285, 1, 264, 720, 521), - (10286, 1, 264, 900, 521), - (10287, 1, 264, 1080, 521), - (10291, 1, 264, 15, 247), - (10291, 2, 264, 8, 986), - (10291, 3, 264, 8, 987), - (10291, 4, 264, 8, 988), - (10292, 1, 264, 18, 247), - (10292, 2, 264, 10, 986), - (10292, 3, 264, 10, 987), - (10292, 4, 264, 10, 988), - (10293, 1, 264, 21, 247), - (10293, 2, 264, 12, 986), - (10293, 3, 264, 12, 987), - (10293, 4, 264, 12, 988), - (10305, 1, 280, 68, 0), - (10306, 1, 280, 69, 0), - (10307, 1, 280, 70, 0), - (10311, 1, 220, 608, 74), - (10312, 1, 220, 640, 74), - (10313, 1, 220, 672, 74), - (10314, 1, 220, 704, 74), - (10315, 1, 220, 736, 74), - (10316, 1, 216, 160, 74), - (10317, 1, 216, 200, 74), - (10318, 1, 216, 240, 74), - (10329, 1, 264, 60, 3701), - (10332, 1, 287, 1, 0), - (10332, 2, 137, 22, 0), - (10332, 3, 411, 256, 0), - (10340, 1, 220, 100, 26), - (10341, 1, 220, 160, 26), - (10342, 1, 220, 235, 26), - (10343, 1, 264, 5, 469), - (10344, 1, 264, 10, 469), - (10345, 1, 264, 15, 469), - (10347, 1, 310, 12000, 0), - (10347, 2, 139, 8007, 0), - (10347, 3, 310, 12000, 0), - (10347, 4, 385, 4140, 0), - (10347, 5, 385, 4240, 0), - (10347, 6, 385, 4340, 0), - (10347, 7, 385, 4440, 0), - (10347, 8, 385, 4540, 0), - (10347, 9, 385, 4640, 0), - (10348, 1, 244, 60, 0), - (10349, 1, 244, 50, 0), - (10350, 1, 244, 40, 0), - (10355, 1, 124, 50, 50), - (10355, 2, 385, 19, 0), - (10355, 3, 144, 0, 0), - (10355, 4, 403, 3, 0), - (10355, 5, 404, 48, 0), - (10355, 6, 385, -21768, 0), - (10356, 1, 124, 100, 100), - (10356, 2, 385, 19, 0), - (10356, 3, 144, 0, 0), - (10356, 4, 403, 3, 0), - (10356, 5, 404, 48, 0), - (10356, 6, 385, -21768, 0), - (10357, 1, 124, 150, 150), - (10357, 2, 385, 19, 0), - (10357, 3, 144, 0, 0), - (10357, 4, 403, 3, 0), - (10357, 5, 404, 48, 0), - (10357, 6, 385, -21768, 0), - (10358, 1, 310, 10000, 0), - (10358, 2, 139, 1546, 0), - (10358, 3, 310, 10000, 0), - (10358, 4, 385, 4357, 0), - (10358, 5, 385, 4457, 0), - (10358, 6, 385, 4557, 0), - (10358, 7, 385, 4657, 0), - (10358, 8, 411, 4, 0), - (10359, 1, 310, 20000, 0), - (10359, 2, 139, 1546, 0), - (10359, 3, 310, 20000, 0), - (10359, 4, 385, 4357, 0), - (10359, 5, 385, 4457, 0), - (10359, 6, 385, 4557, 0), - (10359, 7, 385, 4657, 0), - (10359, 8, 411, 4, 0), - (10360, 1, 310, 30000, 0), - (10360, 2, 139, 1546, 0), - (10360, 3, 310, 30000, 0), - (10360, 4, 385, 4357, 0), - (10360, 5, 385, 4457, 0), - (10360, 6, 385, 4557, 0), - (10360, 7, 385, 4657, 0), - (10360, 8, 411, 4, 0), - (10361, 1, 232, 17, 4544), - (10362, 1, 232, 19, 4544), - (10363, 1, 232, 21, 4544), - (10364, 1, 413, -5, 0), - (10364, 2, 139, 480, 0), - (10364, 3, 385, 4352, 0), - (10364, 4, 385, 4452, 0), - (10365, 1, 413, -10, 0), - (10365, 2, 139, 480, 0), - (10365, 3, 385, 4352, 0), - (10365, 4, 385, 4452, 0), - (10366, 1, 413, -15, 0), - (10366, 2, 139, 480, 0), - (10366, 3, 385, 4352, 0), - (10366, 4, 385, 4452, 0), - (10370, 1, 114, -5, 0), - (10371, 1, 114, -10, 0), - (10372, 1, 114, -20, 0), - (10380, 1, 126, 5, 0), - (10380, 2, 134, 85, 0), - (10380, 3, 135, 4, 0), - (10380, 4, 135, 5, 0), - (10381, 1, 126, 10, 0), - (10381, 2, 134, 85, 0), - (10381, 3, 135, 4, 0), - (10381, 4, 135, 5, 0), - (10382, 1, 126, 15, 0), - (10382, 2, 134, 85, 0), - (10382, 3, 135, 4, 0), - (10382, 4, 135, 5, 0), - (10383, 1, 360, 25, 21770), - (10384, 1, 360, 25, 21771), - (10385, 1, 360, 25, 21772), - (10388, 1, 323, 21850, 0), - (10389, 1, 287, 5, 0), - (10389, 2, 385, 16107, 0), - (10389, 3, 411, 512, 0), - (10390, 1, 287, 10, 0), - (10390, 2, 385, 16107, 0), - (10390, 3, 411, 512, 0), - (10391, 1, 287, 15, 0), - (10391, 2, 385, 16107, 0), - (10391, 3, 411, 512, 0), - (10398, 1, 264, 120, 3701), - (10399, 1, 264, 180, 3701), - (10401, 1, 310, 30000, 0), - (10401, 2, 385, 3107, 0), - (10401, 3, 385, 3207, 0), - (10401, 4, 385, 3307, 0), - (10401, 5, 385, 3407, 0), - (10401, 6, 385, 3507, 0), - (10401, 7, 385, 3607, 0), - (10402, 1, 310, 60000, 0), - (10402, 2, 385, 3107, 0), - (10402, 3, 385, 3207, 0), - (10402, 4, 385, 3307, 0), - (10402, 5, 385, 3407, 0), - (10402, 6, 385, 3507, 0), - (10402, 7, 385, 3607, 0), - (10403, 1, 310, 90000, 0), - (10403, 2, 385, 3107, 0), - (10403, 3, 385, 3207, 0), - (10403, 4, 385, 3307, 0), - (10403, 5, 385, 3407, 0), - (10403, 6, 385, 3507, 0), - (10403, 7, 385, 3607, 0), - (10404, 1, 287, 1, 0), - (10404, 2, 139, 8003, 0), - (10405, 1, 310, 120000, 0), - (10405, 2, 139, 4590, 0), - (10406, 1, 310, 240000, 0), - (10406, 2, 139, 4590, 0), - (10407, 1, 310, 360000, 0), - (10407, 2, 139, 4590, 0), - (10408, 1, 310, 480000, 0), - (10408, 2, 139, 4590, 0), - (10409, 1, 310, 600000, 0), - (10409, 2, 139, 4590, 0), - (10410, 1, 247, 130, 76), - (10413, 1, 264, 60, 207), - (10414, 2, 264, 120, 207), - (10415, 3, 264, 180, 207), - (10416, 4, 264, 240, 207), - (10417, 5, 264, 300, 207), - (10431, 1, 264, 210, 791), - (10432, 1, 264, 240, 791), - (10433, 1, 264, 270, 791), - (10434, 1, 127, 16, 0), - (10434, 2, 385, 5921, 0), - (10435, 1, 127, 33, 0), - (10435, 2, 385, 5921, 0), - (10436, 1, 127, 50, 0), - (10436, 2, 385, 5921, 0), - (10437, 1, 339, 25, 23523), - (10437, 2, 137, 21, 0), - (10438, 1, 339, 25, 23524), - (10438, 2, 137, 21, 0), - (10439, 1, 339, 25, 23525), - (10439, 2, 137, 21, 0), - (10440, 1, 339, 25, 23526), - (10440, 2, 137, 21, 0), - (10442, 1, 413, -20, 0), - (10442, 2, 139, 480, 0), - (10442, 3, 385, 4352, 0), - (10442, 4, 385, 4452, 0), - (10443, 1, 413, -25, 0), - (10443, 2, 139, 480, 0), - (10443, 3, 385, 4352, 0), - (10443, 4, 385, 4452, 0), - (10453, 1, 126, 1, 1), - (10453, 2, 137, 21, 0), - (10453, 3, 231, 1, 0), - (10454, 1, 126, 2, 2), - (10454, 2, 137, 21, 0), - (10454, 3, 231, 2, 0), - (10455, 1, 126, 3, 3), - (10455, 2, 137, 21, 0), - (10455, 3, 231, 3, 0), - (10456, 1, 127, 15, 15), - (10456, 2, 139, 12786, 0), - (10457, 1, 127, 30, 30), - (10457, 2, 139, 12786, 0), - (10458, 1, 127, 50, 50), - (10458, 2, 139, 12786, 0), - (10459, 1, 310, 3000, 0), - (10459, 2, 139, 480, 0), - (10459, 3, 310, 3000, 0), - (10459, 4, 385, 4352, 0), - (10459, 5, 385, 4452, 0), - (10459, 6, 385, 4552, 0), - (10460, 1, 310, 6000, 0), - (10460, 2, 139, 480, 0), - (10460, 3, 310, 6000, 0), - (10460, 4, 385, 4352, 0), - (10460, 5, 385, 4452, 0), - (10460, 6, 385, 4552, 0), - (10461, 1, 310, 10000, 0), - (10461, 2, 139, 480, 0), - (10461, 3, 310, 10000, 0), - (10461, 4, 385, 4352, 0), - (10461, 5, 385, 4452, 0), - (10461, 6, 385, 4552, 0), - (10464, 1, 264, 120, 391), - (10465, 1, 264, 240, 391), - (10466, 1, 264, 360, 391), - (10467, 1, 128, 70, 70), - (10467, 2, 138, 1, 0), - (10467, 3, 140, 1, 0), - (10467, 4, 139, -2741, 0), - (10467, 5, 139, -16843, 0), - (10467, 6, 385, -16192, 0), - (10467, 7, 385, -10547, 0), - (10467, 8, 385, -13543, 0), - (10470, 1, 127, 10, 0), - (10470, 2, 385, 8048, 0), - (10471, 1, 127, 20, 0), - (10471, 2, 385, 8048, 0), - (10472, 1, 127, 30, 0), - (10472, 2, 385, 8048, 0), - (10473, 1, 265, 82, 0), - (10474, 1, 265, 83, 0), - (10475, 1, 265, 84, 0), - (10476, 1, 265, 85, 0), - (10477, 1, 265, 86, 0), - (10478, 1, 360, 3, 46246), - (10511, 1, 264, 60, 185), - (10511, 2, 264, 60, 10426), - (10512, 1, 264, 120, 185), - (10512, 2, 264, 120, 10426), - (10513, 1, 264, 180, 185), - (10513, 2, 264, 180, 10426), - (10514, 1, 264, 60, 519), - (10514, 2, 264, 60, 10427), - (10515, 1, 264, 180, 519), - (10515, 2, 264, 180, 10427), - (10516, 1, 264, 120, 519), - (10516, 2, 264, 120, 10427), - (10519, 1, 264, 60, 3213), - (10522, 1, 264, 2, 3732), - (10527, 1, 264, 30, 1400), - (10532, 1, 264, 30, 1401), - (10537, 1, 264, 30, 1402), - (10548, 1, 349, 10, 0), - (10548, 2, 200, 10, 0), - (10548, 3, 419, 27672, 20), - (10551, 1, 339, 10, 16825), - (10551, 2, 137, 31, 0), - (10552, 1, 339, 10, 16826), - (10552, 2, 137, 31, 0), - (10553, 1, 339, 10, 16827), - (10553, 2, 137, 31, 0), - (10554, 1, 339, 12, 8265), - (10554, 2, 138, 0, 0), - (10554, 3, 137, 31, 0), - (10554, 4, 311, 0, 0), - (10555, 1, 339, 14, 8265), - (10555, 2, 138, 0, 0), - (10555, 3, 137, 31, 0), - (10555, 4, 311, 0, 0), - (10556, 1, 339, 16, 8265), - (10556, 2, 138, 0, 0), - (10556, 3, 137, 31, 0), - (10556, 4, 311, 0, 0), - (10558, 1, 264, 60, 1120), - (10559, 1, 264, 120, 1120), - (10560, 1, 264, 180, 1120), - (10561, 1, 126, 5, 5), - (10561, 2, 139, 12576, 0), - (10561, 3, 126, 5, 5), - (10561, 4, 139, 12828, 0), - (10562, 1, 126, 10, 10), - (10562, 2, 139, 12576, 0), - (10562, 3, 126, 10, 10), - (10562, 4, 139, 12828, 0), - (10563, 1, 126, 15, 15), - (10563, 2, 139, 12576, 0), - (10563, 3, 126, 15, 15), - (10563, 4, 139, 12828, 0), - (10568, 1, 85, 23614, 50), - (10574, 1, 310, 720000, 0), - (10574, 2, 139, 4670, 0), - (10575, 1, 310, 720000, 0), - (10575, 2, 139, 4674, 0), - (10576, 1, 264, 420, 109), - (10579, 1, 264, 40, 3646), - (10580, 1, 264, 50, 3646), - (10588, 1, 264, 2, 601), - (10589, 1, 264, 4, 601), - (10590, 1, 264, 6, 601), - (10591, 1, 264, 8, 601), - (10592, 1, 264, 10, 601), - (10604, 1, 213, 13, 0), - (10605, 1, 213, 15, 0), - (10606, 1, 213, 17, 0), - (10607, 1, 215, 12, 0), - (10608, 1, 215, 14, 0), - (10609, 1, 215, 16, 0), - (10610, 1, 129, 25, 25), - (10610, 2, 385, 100265, 0), - (10611, 1, 129, 25, 25), - (10611, 2, 385, 100265, 0), - (10612, 1, 129, 25, 25), - (10612, 2, 385, 100265, 0), - (10621, 1, 264, 960, 180), - (10622, 1, 264, 1200, 180), - (10623, 1, 279, 19, 0), - (10624, 1, 279, 24, 0), - (10625, 1, 279, 30, 0), - (10627, 1, 224, 20, 74), - (10627, 2, 173, 1, 0), - (10628, 1, 224, 35, 74), - (10628, 2, 173, 2, 0), - (10629, 1, 224, 50, 74), - (10629, 2, 173, 3, 0), - (10632, 1, 265, 82, 0), - (10633, 1, 265, 83, 0), - (10634, 1, 265, 84, 0), - (10635, 1, 265, 85, 0), - (10636, 1, 265, 86, 0), - (10637, 1, 320, 12, 0), - (10638, 1, 320, 13, 0), - (10639, 1, 320, 14, 0), - (10641, 2, 385, 11064, 0), - (10643, 1, 124, 200, 200), - (10643, 2, 385, 19, 0), - (10643, 3, 144, 0, 0), - (10643, 4, 403, 3, 0), - (10643, 5, 404, 48, 0), - (10643, 6, 385, -21768, 0), - (10644, 1, 124, 250, 250), - (10644, 2, 385, 19, 0), - (10644, 3, 144, 0, 0), - (10644, 4, 403, 3, 0), - (10644, 5, 404, 48, 0), - (10644, 6, 385, -21768, 0), - (10645, 1, 124, 300, 300), - (10645, 2, 385, 19, 0), - (10645, 3, 144, 0, 0), - (10645, 4, 403, 3, 0), - (10645, 5, 404, 48, 0), - (10645, 6, 385, -21768, 0), - (10650, 1, 378, 1, 3), - (10651, 1, 378, 2, 3), - (10652, 1, 378, 3, 3), - (10653, 1, 310, 120000, 0), - (10653, 2, 139, 4502, 0), - (10653, 3, 139, 4509, 0), - (10654, 1, 310, 240000, 0), - (10654, 2, 139, 4502, 0), - (10654, 3, 139, 4509, 0), - (10655, 1, 310, 360000, 0), - (10655, 2, 139, 4502, 0), - (10655, 3, 139, 4509, 0), - (10656, 1, 287, 1, 0), - (10656, 2, 385, 15002, 0), - (10656, 3, 385, 15003, 0), - (10656, 4, 411, 128, 0), - (10657, 1, 264, 300, 276), - (10658, 1, 264, 600, 276), - (10659, 1, 264, 900, 276), - (10660, 1, 220, 175, 26), - (10660, 2, 220, 175, 30), - (10660, 3, 220, 175, 38), - (10661, 1, 220, 200, 26), - (10661, 2, 220, 200, 30), - (10661, 3, 220, 200, 38), - (10662, 1, 220, 225, 26), - (10662, 2, 220, 225, 30), - (10662, 3, 220, 225, 38), - (10663, 1, 220, 165, 21), - (10663, 2, 220, 165, 23), - (10663, 3, 220, 330, 52), - (10663, 4, 220, 165, 28), - (10664, 1, 220, 175, 21), - (10664, 2, 220, 175, 23), - (10664, 3, 220, 350, 52), - (10664, 4, 220, 175, 28), - (10665, 1, 220, 185, 21), - (10665, 2, 220, 185, 23), - (10665, 3, 220, 370, 52), - (10665, 4, 220, 185, 28), - (10666, 1, 264, 1200, 98), - (10667, 1, 264, 1320, 98), - (10668, 1, 264, 1440, 98), - (10671, 1, 310, 720000, 0), - (10671, 2, 139, 4590, 0), - (10672, 1, 310, 840000, 0), - (10672, 2, 139, 4590, 0), - (10673, 1, 310, 960000, 0), - (10673, 2, 139, 4590, 0), - (10674, 1, 310, 1080000, 0), - (10674, 2, 139, 4590, 0), - (10675, 1, 310, 1200000, 0), - (10675, 2, 139, 4590, 0), - (10676, 1, 339, 20, 23623), - (10676, 2, 137, 21, 0), - (10676, 3, 385, -18000, 0), - (10676, 4, 339, 20, 23623), - (10676, 5, 137, 343, 0), - (10676, 6, 385, -18000, 0), - (10677, 1, 339, 20, 23624), - (10677, 2, 137, 21, 0), - (10677, 3, 385, -18000, 0), - (10677, 4, 339, 20, 23624), - (10677, 5, 137, 343, 0), - (10677, 6, 385, -18000, 0), - (10678, 1, 339, 20, 23625), - (10678, 2, 137, 21, 0), - (10678, 3, 385, -18000, 0), - (10678, 4, 339, 20, 23625), - (10678, 5, 137, 343, 0), - (10678, 6, 385, -18000, 0), - (10685, 1, 266, 34, 0), - (10686, 1, 266, 39, 0), - (10687, 1, 266, 45, 0), - (10688, 1, 220, 125, 10), - (10689, 1, 220, 145, 10), - (10690, 1, 220, 165, 10), - (10691, 1, 220, 190, 10), - (10692, 1, 220, 220, 10), - (10705, 1, 85, 23542, 0), - (10706, 1, 85, 23543, 0), - (10707, 1, 85, 23544, 0), - (10714, 1, 264, 90, 873), - (10715, 1, 264, 180, 873), - (10717, 1, 264, 360, 184), - (10718, 1, 264, 450, 184), - (10719, 1, 264, 120, 872), - (10720, 1, 264, 240, 872), - (10721, 1, 264, 360, 872), - (10722, 1, 264, 120, 778), - (10723, 1, 264, 240, 778), - (10724, 1, 264, 360, 778), - (10725, 1, 264, 480, 778), - (10726, 1, 264, 600, 778), - (10727, 1, 264, 120, 2235), - (10728, 1, 264, 240, 2235), - (10730, 1, 264, 10, 870), - (10731, 1, 264, 20, 870), - (10733, 1, 264, 1, 219), - (10734, 1, 264, 2, 219), - (10735, 1, 264, 3, 219), - (10743, 1, 220, 135, 7), - (10744, 1, 220, 170, 7), - (10745, 1, 220, 205, 7), - (10748, 1, 59, -35, 0), - (10749, 1, 59, -42, 0), - (10750, 1, 264, 3024, 286), - (10750, 2, 264, 3024, 10753), - (10750, 3, 264, 3024, 9101), - (10751, 1, 264, 3456, 286), - (10751, 2, 264, 3456, 10753), - (10751, 3, 264, 3456, 9101), - (10755, 1, 59, -50, 0), - (10763, 1, 292, 50, 0), - (10764, 1, 292, 60, 0), - (10766, 1, 330, 70, 7), - (10767, 1, 330, 75, 7), - (10768, 1, 330, 80, 7), - (10769, 1, 310, 1440000, 0), - (10769, 2, 139, 4519, 0), - (10770, 1, 310, 1680000, 0), - (10770, 2, 139, 4519, 0), - (10778, 1, 274, 38, 0), - (10779, 1, 274, 40, 0), - (10780, 1, 274, 42, 0), - (10781, 1, 1, 186, 0), - (10782, 1, 1, 217, 0), - (10783, 1, 1, 248, 0), - (10784, 1, 1, 279, 0), - (10785, 1, 1, 310, 0), - (10788, 1, 363, 4, 0), - (10792, 1, 287, 1, 0), - (10792, 2, 385, 5240, 0), - (10792, 3, 385, 5340, 0), - (10792, 4, 385, 5440, 0), - (10792, 5, 385, 5540, 0), - (10792, 6, 385, 5640, 0), - (10793, 1, 287, 2, 0), - (10793, 2, 385, 5240, 0), - (10793, 3, 385, 5340, 0), - (10793, 4, 385, 5440, 0), - (10793, 5, 385, 5540, 0), - (10793, 6, 385, 5640, 0), - (10794, 1, 287, 3, 0), - (10794, 2, 385, 5240, 0), - (10794, 3, 385, 5340, 0), - (10794, 4, 385, 5440, 0), - (10794, 5, 385, 5540, 0), - (10794, 6, 385, 5640, 0), - (10795, 1, 287, 4, 0), - (10795, 2, 385, 5240, 0), - (10795, 3, 385, 5340, 0), - (10795, 4, 385, 5440, 0), - (10795, 5, 385, 5540, 0), - (10795, 6, 385, 5640, 0), - (10796, 1, 287, 5, 0), - (10796, 2, 385, 5240, 0), - (10796, 3, 385, 5340, 0), - (10796, 4, 385, 5440, 0), - (10796, 5, 385, 5540, 0), - (10796, 6, 385, 5640, 0), - (10800, 1, 264, 60, 462), - (10801, 1, 264, 120, 462), - (10802, 1, 264, 180, 462), - (10803, 1, 293, 25, 0), - (10804, 1, 293, 50, 0), - (10805, 1, 293, 75, 0), - (10815, 1, 185, 2, 1), - (10815, 2, 185, 2, 3), - (10816, 1, 185, 4, 1), - (10816, 2, 185, 4, 3), - (10817, 1, 185, 6, 1), - (10817, 2, 185, 6, 3), - (10818, 1, 185, 1, 36), - (10819, 1, 185, 3, 36), - (10820, 1, 185, 5, 36), - (10821, 1, 185, 2, 0), - (10821, 2, 185, 2, 2), - (10822, 1, 185, 4, 0), - (10822, 2, 185, 4, 2), - (10823, 1, 185, 6, 0), - (10823, 2, 185, 6, 2), - (10850, 1, 288, 100, 8), - (10851, 1, 288, 100, 8), - (10852, 1, 288, 100, 8), - (10853, 1, 292, 5, 0), - (10854, 1, 292, 10, 0), - (10855, 1, 292, 15, 0), - (10856, 1, 292, 20, 0), - (10857, 1, 292, 25, 0), - (10858, 1, 292, 30, 0), - (10859, 1, 292, 35, 0), - (10860, 1, 292, 40, 0), - (10861, 1, 292, 45, 0), - (10862, 1, 292, 46, 0), - (10863, 1, 292, 47, 0), - (10864, 1, 292, 48, 0), - (10865, 1, 216, 500, 8), - (10866, 1, 216, 550, 8), - (10867, 1, 216, 650, 8), - (10903, 1, 281, 25, 0), - (10904, 1, 281, 50, 0), - (10905, 1, 281, 75, 0), - (10906, 1, 59, -48, 0), - (10907, 1, 59, -51, 0), - (10908, 1, 59, -54, 0), - (10909, 1, 264, 60, 7007), - (10910, 1, 264, 120, 7007), - (10911, 1, 264, 180, 7007), - (10915, 1, 339, 10, 16876), - (10915, 2, 138, 0, 0), - (10915, 3, 142, 70, 0), - (10915, 4, 411, 32, 0), - (10915, 5, 348, 1, 0), - (10915, 6, 141, 1, 0), - (10916, 1, 339, 10, 16877), - (10916, 2, 138, 0, 0), - (10916, 3, 142, 70, 0), - (10916, 4, 411, 32, 0), - (10916, 5, 348, 1, 0), - (10916, 6, 141, 1, 0), - (10917, 1, 339, 10, 16878), - (10917, 2, 138, 0, 0), - (10917, 3, 142, 70, 0), - (10917, 4, 411, 32, 0), - (10917, 5, 348, 1, 0), - (10917, 6, 141, 1, 0), - (10950, 1, 287, 1, 0), - (10950, 2, 403, 4, 0), - (10950, 3, 404, 38, 0), - (10950, 4, 348, 1, 0), - (10950, 5, 137, 11, 0), - (10950, 6, 140, 2, 0), - (10951, 1, 264, 60, 447), - (10952, 1, 264, 120, 447), - (10953, 1, 264, 180, 447), - (10954, 1, 264, 60, 662), - (10955, 1, 264, 120, 662), - (10956, 1, 264, 180, 662), - (11000, 1, 227, 1, 73), - (11001, 1, 227, 2, 73), - (11002, 1, 227, 3, 73), - (11003, 1, 287, 1, 0), - (11003, 2, 137, 158, 0), - (11003, 3, 411, 2, 0), - (11004, 1, 287, 1, 0), - (11004, 2, 139, 8000, 0), - (11005, 1, 287, 2, 0), - (11005, 2, 139, 8000, 0), - (11006, 1, 287, 3, 0), - (11006, 2, 139, 8000, 0), - (11011, 1, 264, 480, 3710), - (11012, 1, 264, 600, 3710), - (11013, 1, 264, 720, 3710), - (11014, 1, 264, 10, 3899), - (11014, 2, 264, 10, 611), - (11014, 3, 264, 10, 960), - (11014, 4, 264, 10, 1252), - (11015, 1, 264, 20, 3899), - (11015, 2, 264, 20, 611), - (11015, 3, 264, 20, 960), - (11015, 4, 264, 20, 1252), - (11016, 1, 264, 30, 3899), - (11016, 2, 264, 30, 611), - (11016, 3, 264, 30, 960), - (11016, 4, 264, 30, 1252), - (11020, 1, 264, 40, 3899), - (11020, 2, 264, 40, 611), - (11020, 3, 264, 40, 960), - (11020, 4, 264, 40, 1252), - (11050, 1, 264, 360, 452), - (11050, 2, 264, 360, 6106), - (11050, 3, 264, 360, 493), - (11051, 1, 264, 720, 452), - (11051, 2, 264, 720, 6106), - (11051, 3, 264, 720, 493), - (11052, 1, 264, 1080, 452), - (11052, 2, 264, 1080, 6106), - (11052, 3, 264, 1080, 493), - (11053, 1, 264, 1260, 500), - (11054, 1, 264, 1440, 500), - (11059, 1, 264, 1440, 452), - (11059, 2, 264, 1440, 6106), - (11059, 3, 264, 1440, 493), - (11060, 1, 264, 1800, 452), - (11060, 2, 264, 1800, 6106), - (11060, 3, 264, 1800, 493), - (11061, 1, 114, -63, 0), - (11062, 1, 114, -64, 0), - (11063, 1, 114, -65, 0), - (11074, 1, 247, 100, 39), - (11075, 1, 247, 150, 39), - (11076, 1, 247, 200, 39), - (11077, 1, 264, 10, 986), - (11078, 1, 264, 10, 988), - (11079, 1, 264, 10, 987), - (11082, 1, 185, 40, 51), - (11083, 1, 185, 50, 51), - (11084, 1, 185, 60, 51), - (11085, 1, 247, 20, 2), - (11085, 2, 247, 20, 3), - (11085, 3, 247, 20, 77), - (11085, 4, 220, 25, 77), - (11085, 5, 220, 25, 2), - (11085, 6, 220, 25, 3), - (11086, 1, 247, 40, 2), - (11086, 2, 247, 40, 3), - (11086, 3, 247, 40, 77), - (11086, 4, 220, 35, 77), - (11086, 5, 220, 35, 2), - (11086, 6, 220, 35, 3), - (11087, 1, 247, 60, 2), - (11087, 2, 247, 60, 3), - (11087, 3, 247, 60, 77), - (11087, 4, 220, 50, 77), - (11087, 5, 220, 50, 2), - (11087, 6, 220, 50, 3), - (11088, 1, 264, 180, 505), - (11089, 1, 264, 360, 505), - (11090, 1, 264, 540, 505), - (11091, 1, 264, 720, 505), - (12396, 1, 172, 50, 0), - (12397, 1, 172, 51, 0), - (12398, 1, 172, 52, 0), - (12399, 1, 172, 53, 0), - (12400, 1, 172, 54, 0), - (12401, 1, 259, 56, 0), - (12402, 1, 259, 57, 0), - (12403, 1, 259, 58, 0), - (12404, 1, 259, 59, 0), - (12405, 1, 259, 60, 0), - (12406, 1, 69, 1100, 0), - (12407, 1, 69, 1200, 0), - (12408, 1, 69, 1300, 0), - (12409, 1, 69, 1400, 0), - (12410, 1, 69, 1500, 0), - (12411, 1, 1, 300, 0), - (12412, 1, 1, 350, 0), - (12413, 1, 1, 400, 0), - (12414, 1, 1, 450, 0), - (12415, 1, 1, 500, 0), - (12416, 1, 399, 3, 0), - (12416, 2, 141, 1, 0), - (12416, 3, 138, 0, 0), - (12416, 4, 142, 255, 0), - (12416, 5, 391, 0, 0), - (12416, 6, 311, 0, 0), - (12416, 7, 137, -152, 0), - (12416, 8, 411, 100350, 0), - (12416, 9, 137, -39, 0), - (12417, 1, 399, 6, 0), - (12417, 2, 141, 1, 0), - (12417, 3, 138, 0, 0), - (12417, 4, 142, 255, 0), - (12417, 5, 391, 0, 0), - (12417, 6, 311, 0, 0), - (12417, 7, 137, -152, 0), - (12417, 8, 411, 100350, 0), - (12417, 9, 137, -39, 0), - (12418, 1, 399, 9, 0), - (12418, 2, 141, 1, 0), - (12418, 3, 138, 0, 0), - (12418, 4, 142, 255, 0), - (12418, 5, 391, 0, 0), - (12418, 6, 311, 0, 0), - (12418, 7, 137, -152, 0), - (12418, 8, 411, 100350, 0), - (12418, 9, 137, -39, 0), - (12419, 1, 292, 15, 0), - (12420, 1, 292, 30, 0), - (12421, 1, 292, 45, 0), - (12423, 1, 273, 21, 0), - (12424, 1, 273, 24, 0), - (12425, 1, 273, 27, 0), - (12426, 1, 273, 21, 0), - (12427, 1, 273, 24, 0), - (12428, 1, 273, 27, 0), - (12432, 1, 294, 17, 100), - (12433, 1, 294, 19, 100), - (12434, 1, 294, 21, 100), - (12435, 1, 294, 23, 100), - (12436, 1, 294, 25, 100), - (12437, 1, 294, 27, 100), - (12438, 1, 200, 70, 0), - (12439, 1, 341, 210, 0), - (12440, 1, 341, 220, 0), - (12441, 1, 341, 230, 0), - (12442, 1, 341, 240, 0), - (12443, 1, 341, 250, 0), - (12444, 1, 318, 21, 0), - (12445, 1, 318, 22, 0), - (12446, 1, 318, 23, 0), - (12447, 1, 318, 24, 0), - (12448, 1, 318, 25, 0), - (12449, 1, 125, 31, 31), - (12449, 2, 137, 0, 0), - (12449, 3, 141, 1, 0), - (12449, 4, 139, -6233, 0), - (12449, 5, 139, -6265, 0), - (12449, 6, 125, 31, 31), - (12449, 7, 137, 147, 0), - (12449, 8, 141, 1, 0), - (12450, 1, 125, 34, 34), - (12450, 2, 137, 0, 0), - (12450, 3, 141, 1, 0), - (12450, 4, 139, -6233, 0), - (12450, 5, 139, -6265, 0), - (12450, 6, 125, 34, 34), - (12450, 7, 137, 147, 0), - (12450, 8, 141, 1, 0), - (12451, 1, 125, 37, 37), - (12451, 2, 137, 0, 0), - (12451, 3, 141, 1, 0), - (12451, 4, 139, -6233, 0), - (12451, 5, 139, -6265, 0), - (12451, 6, 125, 37, 37), - (12451, 7, 137, 147, 0), - (12451, 8, 141, 1, 0), - (12452, 1, 274, 38, 0), - (12453, 1, 274, 39, 0), - (12454, 1, 274, 40, 0), - (12455, 1, 15, 19, 0), - (12456, 1, 15, 20, 0), - (12457, 1, 15, 21, 0), - (12458, 1, 15, 22, 0), - (12459, 1, 15, 23, 0), - (12463, 1, 320, 9, 0), - (12464, 1, 320, 10, 0), - (12465, 1, 320, 11, 0), - (12466, 1, 320, 9, 0), - (12467, 1, 320, 10, 0), - (12468, 1, 320, 11, 0), - (12469, 1, 320, 9, 0), - (12470, 1, 320, 10, 0), - (12471, 1, 320, 11, 0), - (12472, 1, 320, 6, 0), - (12473, 1, 320, 7, 0), - (12474, 1, 320, 8, 0), - (12475, 1, 264, 180, 7003), - (12476, 1, 264, 360, 7003), - (12477, 1, 264, 540, 7003), - (12478, 1, 264, 60, 3705), - (12479, 1, 264, 120, 3705), - (12480, 1, 264, 180, 3705), - (12481, 1, 247, 40, 76), - (12482, 1, 247, 45, 76), - (12483, 1, 247, 65, 76), - (12484, 1, 247, 70, 76), - (12485, 1, 247, 30, 76), - (12486, 1, 247, 35, 76), - (12487, 1, 247, 25, 76), - (12488, 1, 247, 30, 76), - (12492, 1, 69, 1600, 0), - (12493, 1, 69, 1700, 0), - (12494, 1, 69, 1800, 0), - (12495, 1, 69, 1900, 0), - (12496, 1, 69, 2000, 0), - (12497, 1, 125, 40, 40), - (12497, 2, 137, 0, 0), - (12497, 3, 141, 1, 0), - (12497, 4, 139, -6233, 0), - (12497, 5, 139, -6265, 0), - (12497, 6, 125, 40, 40), - (12497, 7, 137, 147, 0), - (12497, 8, 141, 1, 0), - (12498, 1, 125, 43, 43), - (12498, 2, 137, 0, 0), - (12498, 3, 141, 1, 0), - (12498, 4, 139, -6233, 0), - (12498, 5, 139, -6265, 0), - (12498, 6, 125, 43, 43), - (12498, 7, 137, 147, 0), - (12498, 8, 141, 1, 0), - (12499, 1, 125, 46, 46), - (12499, 2, 137, 0, 0), - (12499, 3, 141, 1, 0), - (12499, 4, 139, -6233, 0), - (12499, 5, 139, -6265, 0), - (12499, 6, 125, 46, 46), - (12499, 7, 137, 147, 0), - (12499, 8, 141, 1, 0), - (12500, 1, 310, 1000, 0), - (12500, 2, 385, 4004, 0), - (12500, 3, 385, 11202, 0), - (12500, 4, 385, 11302, 0), - (12500, 5, 385, 11402, 0), - (12500, 6, 385, 11502, 0), - (12500, 7, 385, 11602, 0), - (12501, 1, 310, 2000, 0), - (12501, 2, 385, 4004, 0), - (12501, 3, 385, 11202, 0), - (12501, 4, 385, 11302, 0), - (12501, 5, 385, 11402, 0), - (12501, 6, 385, 11502, 0), - (12501, 7, 385, 11602, 0), - (12502, 1, 310, 3000, 0), - (12502, 2, 385, 4004, 0), - (12502, 3, 385, 11202, 0), - (12502, 4, 385, 11302, 0), - (12502, 5, 385, 11402, 0), - (12502, 6, 385, 11502, 0), - (12502, 7, 385, 11602, 0), - (12505, 1, 310, 4000, 0), - (12505, 2, 385, 4004, 0), - (12505, 3, 385, 11202, 0), - (12505, 4, 385, 11302, 0), - (12505, 5, 385, 11402, 0), - (12505, 6, 385, 11502, 0), - (12505, 7, 385, 11602, 0), - (12506, 1, 310, 5000, 0), - (12506, 2, 385, 4004, 0), - (12506, 3, 385, 11202, 0), - (12506, 4, 385, 11302, 0), - (12506, 5, 385, 11402, 0), - (12506, 6, 385, 11502, 0), - (12506, 7, 385, 11602, 0), - (12507, 1, 301, 120, 0), - (12508, 1, 247, 50, 76), - (12509, 1, 247, 55, 76), - (12510, 1, 247, 60, 76), - (12511, 1, 247, 75, 76), - (12512, 1, 247, 80, 76), - (12513, 1, 247, 85, 76), - (12514, 1, 247, 40, 76), - (12515, 1, 247, 45, 76), - (12516, 1, 247, 50, 76), - (12517, 1, 247, 35, 76), - (12518, 1, 247, 40, 76), - (12519, 1, 247, 45, 76), - (12523, 1, 294, 0, 200), - (12526, 1, 294, 0, 190), - (12527, 1, 294, 0, 195), - (12528, 1, 294, 0, 200), - (12529, 1, 294, 0, 165), - (12530, 1, 294, 0, 175), - (12531, 1, 294, 0, 185), - (12532, 1, 341, 260, 0), - (12533, 1, 341, 270, 0), - (12534, 1, 341, 280, 0), - (12535, 1, 341, 290, 0), - (12536, 1, 341, 300, 0), - (12537, 1, 318, 26, 0), - (12538, 1, 318, 27, 0), - (12539, 1, 318, 28, 0), - (12540, 1, 318, 29, 0), - (12541, 1, 318, 30, 0), - (12548, 1, 278, 900, 79230), - (12548, 2, 440, 87, 100), - (12549, 1, 278, 900, 86260), - (12549, 2, 440, 88, 100), - (12550, 1, 278, 900, 88260), - (12550, 2, 440, 89, 100), - (12551, 1, 278, 900, 91510), - (12551, 2, 440, 90, 100), - (12552, 1, 278, 900, 96305), - (12552, 2, 440, 91, 100), - (12553, 1, 294, 29, 102), - (12554, 1, 294, 31, 104), - (12555, 1, 294, 33, 106), - (12556, 1, 294, 23, 100), - (12557, 1, 294, 25, 100), - (12558, 1, 294, 27, 100), - (12559, 1, 190, 300, 0), - (12560, 1, 190, 350, 0), - (12561, 1, 190, 400, 0), - (12562, 1, 190, 450, 0), - (12563, 1, 190, 500, 0), - (12564, 1, 319, 28, 0), - (12565, 1, 319, 29, 0), - (12566, 1, 319, 30, 0), - (12567, 1, 274, 41, 0), - (12568, 1, 274, 42, 0), - (12569, 1, 274, 43, 0), - (12570, 1, 15, 24, 0), - (12571, 1, 15, 25, 0), - (12572, 1, 15, 26, 0), - (12573, 1, 15, 27, 0), - (12574, 1, 15, 28, 0), - (12575, 1, 292, 60, 0), - (12576, 1, 231, 17, 0), - (12577, 1, 231, 19, 0), - (12578, 1, 231, 21, 0), - (12579, 1, 85, 23569, 0), - (12580, 1, 85, 23570, 0), - (12581, 1, 85, 23571, 0), - (12582, 1, 264, 10, 9400), - (12583, 1, 264, 20, 9400), - (12584, 1, 264, 30, 9400), - (12587, 1, 264, 480, 9403), - (12588, 1, 264, 600, 9403), - (12589, 1, 264, 720, 9403), - (12591, 1, 247, 90, 76), - (12594, 1, 247, 55, 76), - (12597, 1, 247, 50, 76), - (12598, 1, 247, 55, 76), - (12600, 1, 310, 60000, 0), - (12600, 2, 139, 6197, 0), - (12600, 3, 411, 512, 0), - (12603, 1, 287, 1, 0), - (12603, 2, 139, 6197, 0), - (12603, 3, 411, 512, 0), - (12606, 1, 271, 5, 0), - (12607, 1, 310, 12000, 0), - (12607, 2, 385, 13007, 0), - (12607, 3, 385, 12105, 0), - (12607, 4, 385, 12205, 0), - (12607, 5, 310, 36000, 0), - (12607, 6, 385, 12305, 0), - (12607, 7, 385, 12405, 0), - (12607, 8, 385, 12505, 0), - (12607, 9, 411, 512, 0), - (12610, 1, 279, 19, 0), - (12612, 1, 439, 0, 124480), - (12612, 2, 345, 84, 25), - (12613, 1, 439, 0, 132440), - (12613, 2, 345, 86, 25), - (12615, 1, 310, 120000, 0), - (12615, 2, 139, 4695, 0), - (12615, 3, 411, 512, 0), - (12616, 1, 310, 240000, 0), - (12616, 2, 139, 4695, 0), - (12616, 3, 411, 512, 0), - (12617, 1, 310, 360000, 0), - (12617, 2, 139, 4695, 0), - (12617, 3, 411, 512, 0), - (12636, 1, 426, 1, 0), - (12637, 1, 426, 2, 0), - (12639, 1, 264, 240, 519), - (12639, 2, 264, 240, 10427), - (12642, 1, 264, 240, 185), - (12642, 2, 264, 240, 10426), - (12645, 1, 287, 1, 0), - (12645, 2, 385, 8190, 0), - (12645, 3, 287, 1, 0), - (12645, 4, 385, 21818, 0), - (12645, 5, 411, 64, 0), - (12646, 1, 287, 1, 0), - (12646, 2, 385, 3277, 0), - (12646, 3, 287, 1, 0), - (12646, 4, 385, 21816, 0), - (12652, 1, 399, 1, 0), - (12652, 2, 138, 1, 0), - (12652, 3, 137, 0, 0), - (12652, 4, 348, 10, 0), - (12652, 5, 311, 0, 0), - (12652, 6, 141, 1, 0), - (12652, 7, 134, 254, 0), - (12652, 8, 137, -39, 0), - (12653, 1, 399, 2, 0), - (12653, 2, 138, 1, 0), - (12653, 3, 137, 0, 0), - (12653, 4, 348, 10, 0), - (12653, 5, 311, 0, 0), - (12653, 6, 141, 1, 0), - (12653, 7, 134, 254, 0), - (12653, 8, 137, -39, 0), - (12654, 1, 399, 3, 0), - (12654, 2, 138, 1, 0), - (12654, 3, 137, 0, 0), - (12654, 4, 348, 10, 0), - (12654, 5, 311, 0, 0), - (12654, 6, 141, 1, 0), - (12654, 7, 134, 254, 0), - (12654, 8, 137, -39, 0), - (12664, 1, 264, 2, 3728), - (12667, 1, 220, 250, 26), - (12667, 2, 220, 250, 30), - (12667, 3, 220, 250, 38), - (12668, 1, 220, 275, 26), - (12668, 2, 220, 275, 30), - (12668, 3, 220, 275, 38), - (12669, 1, 220, 300, 26), - (12669, 2, 220, 300, 30), - (12669, 3, 220, 300, 38), - (12670, 1, 220, 200, 21), - (12670, 2, 220, 200, 23), - (12670, 3, 220, 400, 52), - (12670, 4, 220, 200, 28), - (12671, 1, 220, 215, 21), - (12671, 2, 220, 215, 23), - (12671, 3, 220, 450, 52), - (12671, 4, 220, 215, 28), - (12672, 1, 220, 235, 21), - (12672, 2, 220, 235, 23), - (12672, 3, 220, 510, 52), - (12672, 4, 220, 235, 28), - (12673, 1, 264, 960, 420), - (12674, 1, 227, 270, 32), - (12675, 1, 227, 300, 32), - (12676, 1, 227, 330, 32), - (12677, 1, 275, 92, 0), - (12678, 1, 287, 2, 0), - (12678, 2, 385, 15002, 0), - (12678, 3, 385, 15003, 0), - (12678, 4, 411, 128, 0), - (12679, 1, 264, 1200, 276), - (12680, 1, 264, 1500, 276), - (12681, 1, 264, 1800, 276), - (12685, 1, 292, 49, 0), - (12686, 1, 292, 50, 0), - (12687, 1, 292, 51, 0), - (12688, 1, 287, 1, 0), - (12688, 2, 385, 8473, 0), - (12688, 3, 385, 8318, 0), - (12688, 4, 385, 8418, 0), - (12688, 5, 385, 8518, 0), - (12688, 6, 411, 128, 0), - (12689, 1, 287, 2, 0), - (12689, 2, 139, 4691, 0), - (12689, 3, 411, 128, 0), - (12690, 1, 287, 2, 0), - (12690, 2, 385, 8111, 0), - (12690, 3, 385, 15008, 0), - (12690, 4, 385, 8411, 0), - (12690, 5, 385, 8511, 0), - (12690, 6, 411, 128, 0), - (12691, 1, 287, 1, 0), - (12691, 2, 385, 15007, 0), - (12691, 3, 411, 128, 0), - (12691, 4, 385, 8316, 0), - (12692, 1, 220, 255, 21), - (12692, 2, 220, 255, 23), - (12692, 3, 220, 570, 52), - (12692, 4, 220, 255, 28), - (12693, 1, 220, 275, 21), - (12693, 2, 220, 275, 23), - (12693, 3, 220, 630, 52), - (12693, 4, 220, 275, 28), - (12694, 1, 189, 16, 0), - (12695, 1, 189, 17, 0), - (12696, 1, 189, 18, 0), - (12697, 1, 330, 140, 0), - (12697, 2, 330, 140, 1), - (12697, 3, 330, 140, 2), - (12697, 4, 330, 140, 3), - (12697, 5, 330, 140, 28), - (12697, 6, 330, 140, 36), - (12697, 7, 330, 140, 77), - (12698, 1, 330, 145, 0), - (12698, 2, 330, 145, 1), - (12698, 3, 330, 145, 2), - (12698, 4, 330, 145, 3), - (12698, 5, 330, 145, 28), - (12698, 6, 330, 145, 36), - (12698, 7, 330, 145, 77), - (12699, 1, 330, 150, 0), - (12699, 2, 330, 150, 1), - (12699, 3, 330, 150, 2), - (12699, 4, 330, 150, 3), - (12699, 5, 330, 150, 28), - (12699, 6, 330, 150, 36), - (12699, 7, 330, 150, 77), - (12703, 1, 283, 240, 0), - (12704, 1, 283, 260, 0), - (12705, 1, 283, 280, 0), - (12706, 1, 220, 60, 28), - (12706, 2, 220, 60, 0), - (12706, 3, 427, 23598, 3), - (12706, 4, 428, 28, 0), - (12706, 5, 428, 0, 0), - (12707, 1, 220, 85, 28), - (12707, 2, 220, 85, 0), - (12707, 3, 427, 23598, 5), - (12707, 4, 428, 28, 0), - (12707, 5, 428, 0, 0), - (12708, 1, 220, 115, 28), - (12708, 2, 220, 115, 0), - (12708, 3, 427, 23598, 7), - (12708, 4, 428, 28, 0), - (12708, 5, 428, 0, 0), - (12709, 1, 287, 1, 0), - (12709, 2, 139, 4516, 0), - (12709, 3, 411, 256, 0), - (12710, 1, 310, 360000, 0), - (12710, 2, 139, 4516, 0), - (12710, 3, 411, 256, 0), - (12711, 1, 310, 720000, 0), - (12711, 2, 139, 4516, 0), - (12711, 3, 411, 256, 0), - (12712, 1, 310, 1080000, 0), - (12712, 2, 139, 4516, 0), - (12712, 3, 411, 256, 0), - (12713, 1, 264, 2, 8202), - (12714, 1, 264, 4, 8202), - (12715, 1, 264, 6, 8202), - (12716, 1, 264, 30, 3702), - (12717, 1, 264, 60, 3702), - (12718, 1, 264, 90, 3702), - (12719, 1, 128, 10, 0), - (12719, 2, 385, 12769, 0), - (12719, 3, 411, 256, 0), - (12720, 1, 287, 1, 0), - (12720, 2, 139, 12519, 0), - (12720, 3, 411, 256, 0), - (12721, 1, 264, 60, 3506), - (12722, 1, 264, 120, 3506), - (12723, 1, 264, 180, 3506), - (12727, 1, 264, 960, 359), - (12728, 1, 264, 1200, 359), - (12729, 1, 264, 1440, 359), - (12733, 1, 287, 2, 0), - (12733, 2, 137, 22, 0), - (12733, 3, 411, 256, 0), - (12734, 1, 375, 145, 0), - (12735, 1, 375, 150, 0), - (12736, 1, 375, 155, 0), - (12737, 1, 129, 5, 0), - (12737, 2, 385, 12768, 0), - (12737, 3, 411, 256, 0), - (12738, 1, 129, 10, 0), - (12738, 2, 385, 12768, 0), - (12738, 3, 411, 256, 0), - (12739, 1, 129, 15, 0), - (12739, 2, 385, 12768, 0), - (12739, 3, 411, 256, 0), - (12757, 1, 264, 6000, 68), - (12758, 1, 264, 6600, 68), - (12759, 1, 264, 7200, 68), - (12767, 1, 229, 50, 0), - (12768, 1, 229, 55, 0), - (12769, 1, 229, 60, 0), - (12773, 1, 264, 60, 1580), - (12774, 1, 264, 120, 1580), - (12775, 1, 264, 180, 1580), - (12776, 1, 264, 240, 1580), - (12777, 1, 264, 300, 1580), - (12779, 1, 264, 0, 826), - (12780, 1, 264, 1, 826), - (12781, 1, 264, 1, 826), - (12782, 1, 129, 10, 0), - (12782, 2, 385, 16106, 0), - (12783, 1, 129, 20, 0), - (12783, 2, 385, 16106, 0), - (12784, 1, 129, 30, 0), - (12784, 2, 385, 16106, 0), - (12792, 1, 397, 1000, 0), - (12793, 1, 397, 1200, 0), - (12794, 1, 397, 1250, 0), - (12795, 1, 213, 19, 0), - (12796, 1, 213, 21, 0), - (12797, 1, 213, 23, 0), - (12798, 1, 218, 21, 0), - (12799, 1, 218, 22, 0), - (12800, 1, 218, 23, 0), - (12801, 1, 215, 18, 0), - (12802, 1, 215, 20, 0), - (12803, 1, 215, 22, 0), - (12813, 1, 320, 2, 0), - (12814, 1, 320, 4, 0), - (12815, 1, 320, 6, 0), - (12816, 1, 128, 1, 0), - (12816, 2, 385, 2223, 0), - (12816, 3, 385, 2323, 0), - (12816, 4, 385, 2240, 0), - (12816, 5, 385, 2340, 0), - (12816, 6, 385, 2440, 0), - (12816, 7, 385, 2540, 0), - (12816, 8, 398, 6000, 0), - (12816, 9, 385, 11872, 0), - (12816, 10, 385, 14154, 0), - (12816, 11, 385, 18166, 0), - (12816, 12, 385, 27225, 0), - (12816, 13, 385, 2419, 0), - (12816, 14, 385, 2427, 0), - (12816, 15, 385, 30374, 0), - (12816, 16, 385, 2527, 0), - (12816, 17, 385, 36431, 0), - (12819, 1, 310, 23400, 0), - (12819, 2, 139, 4671, 0), - (12819, 3, 411, 32768, 0), - (12820, 1, 310, 46800, 0), - (12820, 2, 139, 4671, 0), - (12820, 3, 411, 32768, 0), - (12822, 1, 310, 153000, 0), - (12822, 2, 139, 8233, 0), - (12822, 3, 310, 120000, 0), - (12822, 4, 385, 2439, 0), - (12822, 5, 385, 2539, 0), - (12822, 6, 411, 32768, 0), - (12831, 1, 127, 17, 0), - (12831, 2, 385, 3291, 0), - (12831, 3, 385, 3817, 0), - (12831, 4, 411, 32768, 0), - (12834, 1, 264, 180, 128), - (12835, 1, 264, 225, 128), - (12840, 1, 264, 24, 3817), - (12841, 1, 264, 30, 3817), - (12843, 1, 225, 42, 0), - (12846, 1, 288, 20, 28), - (12846, 2, 288, 20, 0), - (12849, 1, 127, 14, 0), - (12849, 2, 385, 16794, 0), - (12849, 3, 411, 32768, 0), - (12860, 1, 294, 21, 102), - (12863, 1, 127, 15, 15), - (12863, 2, 137, 0, 0), - (12863, 3, 138, 0, 0), - (12863, 4, 141, 1, 0), - (12863, 5, 143, 3000, 0), - (12863, 6, 127, 15, 15), - (12863, 7, 385, 16555, 0), - (12863, 8, 385, 16655, 0), - (12871, 1, 264, 2160, 452), - (12871, 2, 264, 2160, 6106), - (12871, 3, 264, 2160, 493), - (12872, 1, 264, 2520, 452), - (12872, 2, 264, 2520, 6106), - (12872, 3, 264, 2520, 493), - (12874, 1, 264, 2572, 451), - (12876, 1, 264, 900, 7003), - (12877, 1, 264, 1260, 7003), - (12878, 1, 264, 1620, 7003), - (12881, 1, 264, 45, 172), - (12886, 1, 10, 0, 0), - (12887, 1, 10, 0, 0), - (12888, 1, 10, 0, 0), - (12889, 1, 10, 0, 0), - (12890, 1, 10, 0, 0), - (12894, 1, 264, 30, 1122), - (12899, 1, 264, 3456, 57), - (12899, 2, 264, 3456, 616), - (12900, 1, 264, 4320, 57), - (12900, 2, 264, 4320, 616), - (12902, 1, 264, 30, 1380), - (12903, 1, 264, 60, 1380), - (12907, 1, 264, 30, 1381), - (12908, 1, 264, 60, 1381), - (12912, 1, 264, 30, 1382), - (12913, 1, 264, 60, 1382), - (12920, 1, 130, 10, 10), - (12920, 2, 139, 2569, 0), - (12920, 3, 130, -10, -10), - (12920, 4, 139, 2568, 0), - (12929, 1, 287, 4, 0), - (12929, 2, 137, 3, 0), - (12929, 3, 137, 99, 0), - (12929, 4, 138, 0, 0), - (12929, 5, 244, 20, 0), - (12930, 1, 287, 5, 0), - (12930, 2, 137, 3, 0), - (12930, 3, 137, 99, 0), - (12930, 4, 138, 0, 0), - (12930, 5, 244, 15, 0), - (12945, 1, 280, 60, 0), - (12946, 1, 280, 61, 0), - (12947, 1, 280, 62, 0), - (12948, 1, 280, 63, 0), - (12949, 1, 280, 64, 0), - (12950, 1, 218, 21, 0), - (12951, 1, 218, 22, 0), - (12952, 1, 218, 23, 0), - (12953, 1, 218, 24, 0), - (12954, 1, 218, 25, 0), - (12966, 1, 131, 25, 25), - (12966, 2, 348, 10, 0), - (12966, 3, 137, -32, 0), - (12967, 1, 131, 50, 50), - (12967, 2, 348, 10, 0), - (12967, 3, 137, -32, 0), - (12968, 1, 264, 3, 1041), - (12969, 1, 264, 6, 1041), - (12970, 1, 264, 9, 1041), - (12977, 1, 287, 2, 0), - (12977, 2, 385, 16188, 0), - (12978, 1, 287, 4, 0), - (12978, 2, 385, 16188, 0), - (12979, 1, 287, 6, 0), - (12979, 2, 385, 16188, 0), - (12980, 1, 287, 8, 0), - (12980, 2, 385, 16188, 0), - (12981, 1, 287, 10, 0), - (12981, 2, 385, 16188, 0), - (12988, 1, 287, 3, 0), - (12988, 2, 140, 3, 0), - (12988, 3, 348, 1, 0), - (12988, 4, 138, 0, 0), - (12988, 5, 137, 0, 0), - (13001, 1, 264, 60, 9504), - (13002, 1, 264, 120, 9504), - (13003, 1, 264, 180, 9504), - (13005, 1, 264, 70, 171), - (13006, 1, 264, 80, 171), - (13007, 1, 264, 90, 171), - (13010, 1, 264, 10, 47), - (13011, 1, 264, 20, 47), - (13012, 1, 264, 30, 47), - (13013, 1, 264, 120, 446), - (13014, 1, 264, 240, 446), - (13015, 1, 264, 360, 446), - (13017, 1, 375, 15, 0), - (13018, 1, 375, 25, 0), - (13019, 1, 375, 35, 0), - (13021, 1, 247, 80, 2), - (13021, 2, 247, 80, 3), - (13021, 3, 247, 80, 77), - (13021, 4, 220, 75, 77), - (13021, 5, 220, 75, 2), - (13021, 6, 220, 75, 3), - (13023, 1, 330, 115, 0), - (13023, 2, 330, 115, 1), - (13023, 3, 330, 115, 2), - (13023, 4, 330, 115, 3), - (13023, 5, 330, 115, 28), - (13023, 6, 330, 115, 36), - (13023, 7, 330, 115, 77), - (13026, 1, 266, 26, 0), - (13027, 1, 266, 27, 0), - (13028, 1, 266, 28, 0), - (13029, 1, 288, 250, 51), - (13029, 2, 288, 60, 51), - (13032, 1, 185, 70, 51), - (13033, 1, 185, 80, 51), - (13035, 1, 220, 768, 74), - (13040, 1, 216, 280, 74), - (13043, 1, 169, 35, -1), - (13046, 1, 1, 240, 0), - (13047, 1, 1, 280, 0), - (13048, 1, 1, 320, 0), - (13049, 1, 1, 360, 0), - (13050, 1, 1, 400, 0), - (13051, 1, 287, 2, 0), - (13051, 2, 139, 8003, 0), - (13052, 1, 310, 120000, 0), - (13052, 2, 385, 3107, 0), - (13052, 3, 385, 3207, 0), - (13052, 4, 385, 3307, 0), - (13052, 5, 385, 3407, 0), - (13052, 6, 385, 3507, 0), - (13052, 7, 385, 3607, 0), - (13055, 1, 264, 60, 8400), - (13067, 1, 264, 120, 643), - (13072, 1, 310, 120000, 0), - (13072, 2, 139, 6197, 0), - (13072, 3, 411, 512, 0), - (13073, 1, 310, 180000, 0), - (13073, 2, 139, 6197, 0), - (13073, 3, 411, 512, 0), - (13074, 1, 330, 140, 0), - (13074, 2, 330, 140, 1), - (13074, 3, 330, 140, 2), - (13074, 4, 330, 140, 3), - (13074, 5, 330, 140, 28), - (13074, 6, 330, 140, 36), - (13075, 1, 330, 145, 0), - (13075, 2, 330, 145, 1), - (13075, 3, 330, 145, 2), - (13075, 4, 330, 145, 3), - (13075, 5, 330, 145, 28), - (13075, 6, 330, 145, 36), - (13076, 1, 330, 150, 0), - (13076, 2, 330, 150, 1), - (13076, 3, 330, 150, 2), - (13076, 4, 330, 150, 3), - (13076, 5, 330, 150, 28), - (13076, 6, 330, 150, 36), - (13077, 1, 330, 140, 0), - (13077, 2, 330, 140, 1), - (13077, 3, 330, 140, 2), - (13077, 4, 330, 140, 3), - (13077, 5, 330, 140, 28), - (13077, 6, 330, 140, 36), - (13077, 7, 330, 140, 77), - (13078, 1, 330, 145, 0), - (13078, 2, 330, 145, 1), - (13078, 3, 330, 145, 2), - (13078, 4, 330, 145, 3), - (13078, 5, 330, 145, 28), - (13078, 6, 330, 145, 36), - (13078, 7, 330, 145, 77), - (13080, 1, 172, 55, 0), - (13081, 1, 172, 56, 0), - (13082, 1, 172, 57, 0), - (13083, 1, 172, 58, 0), - (13084, 1, 172, 59, 0), - (13085, 1, 259, 61, 0), - (13086, 1, 259, 62, 0), - (13087, 1, 259, 63, 0), - (13088, 1, 259, 64, 0), - (13089, 1, 259, 65, 0), - (13090, 1, 339, 10, 8105), - (13090, 2, 142, 65, 0), - (13090, 3, 311, 0, 0), - (13090, 4, 134, 70, 0), - (13090, 5, 348, 10, 0), - (13090, 6, 137, 0, 0), - (13090, 7, 339, 10, 8105), - (13090, 8, 142, 65, 0), - (13090, 9, 311, 0, 0), - (13090, 10, 134, 70, 0), - (13090, 11, 348, 10, 0), - (13090, 12, 137, 100, 0), - (13090, 13, 339, 10, 8105), - (13090, 14, 142, 65, 0), - (13090, 15, 311, 0, 0), - (13090, 16, 134, 70, 0), - (13090, 17, 348, 10, 0), - (13090, 18, 137, 79, 0), - (13090, 19, 339, 10, 8105), - (13090, 20, 142, 65, 0), - (13090, 21, 311, 0, 0), - (13090, 22, 134, 70, 0), - (13090, 23, 348, 10, 0), - (13090, 24, 137, 147, 0), - (13090, 25, 339, 10, 11404), - (13090, 26, 142, 71, 0), - (13090, 27, 311, 0, 0), - (13090, 28, 134, 75, 0), - (13090, 29, 348, 10, 0), - (13090, 30, 137, 0, 0), - (13090, 31, 339, 10, 11404), - (13090, 32, 142, 71, 0), - (13090, 33, 311, 0, 0), - (13090, 34, 134, 75, 0), - (13090, 35, 348, 10, 0), - (13090, 36, 137, 100, 0), - (13090, 37, 339, 10, 11404), - (13090, 38, 142, 71, 0), - (13090, 39, 311, 0, 0), - (13090, 40, 134, 75, 0), - (13090, 41, 348, 10, 0), - (13090, 42, 137, 79, 0), - (13090, 43, 339, 10, 11404), - (13090, 44, 142, 71, 0), - (13090, 45, 311, 0, 0), - (13090, 46, 134, 75, 0), - (13090, 47, 348, 10, 0), - (13090, 48, 137, 147, 0), - (13090, 49, 339, 10, 13199), - (13090, 50, 142, 76, 0), - (13090, 51, 311, 0, 0), - (13090, 52, 134, 80, 0), - (13090, 53, 348, 10, 0), - (13090, 54, 137, 0, 0), - (13090, 55, 339, 10, 13199), - (13090, 56, 142, 76, 0), - (13090, 57, 311, 0, 0), - (13090, 58, 134, 80, 0), - (13090, 59, 348, 10, 0), - (13090, 60, 137, 100, 0), - (13090, 61, 339, 10, 13199), - (13090, 62, 142, 76, 0), - (13090, 63, 311, 0, 0), - (13090, 64, 134, 80, 0), - (13090, 65, 348, 10, 0), - (13090, 66, 137, 79, 0), - (13090, 67, 339, 10, 13199), - (13090, 68, 142, 76, 0), - (13090, 69, 311, 0, 0), - (13090, 70, 134, 80, 0), - (13090, 71, 348, 10, 0), - (13090, 72, 137, 147, 0), - (13090, 73, 339, 10, 13830), - (13090, 74, 142, 81, 0), - (13090, 75, 311, 0, 0), - (13090, 76, 134, 85, 0), - (13090, 77, 348, 10, 0), - (13090, 78, 137, 0, 0), - (13090, 79, 339, 10, 13830), - (13090, 80, 142, 81, 0), - (13090, 81, 311, 0, 0), - (13090, 82, 134, 85, 0), - (13090, 83, 348, 10, 0), - (13090, 84, 137, 100, 0), - (13090, 85, 339, 10, 13830), - (13090, 86, 142, 81, 0), - (13090, 87, 311, 0, 0), - (13090, 88, 134, 85, 0), - (13090, 89, 348, 10, 0), - (13090, 90, 137, 79, 0), - (13090, 91, 339, 10, 13830), - (13090, 92, 142, 81, 0), - (13090, 93, 311, 0, 0), - (13090, 94, 134, 85, 0), - (13090, 95, 348, 10, 0), - (13090, 96, 137, 147, 0), - (13090, 97, 339, 10, 27527), - (13090, 98, 142, 86, 0), - (13090, 99, 311, 0, 0), - (13090, 100, 134, 90, 0), - (13090, 101, 348, 10, 0), - (13090, 102, 137, 0, 0), - (13090, 103, 339, 10, 27527), - (13090, 104, 142, 86, 0), - (13090, 105, 311, 0, 0), - (13090, 106, 134, 90, 0), - (13090, 107, 348, 10, 0), - (13090, 108, 137, 100, 0), - (13090, 109, 339, 10, 27527), - (13090, 110, 142, 86, 0), - (13090, 111, 311, 0, 0), - (13090, 112, 134, 90, 0), - (13090, 113, 348, 10, 0), - (13090, 114, 137, 79, 0), - (13090, 115, 339, 10, 27527), - (13090, 116, 142, 86, 0), - (13090, 117, 311, 0, 0), - (13090, 118, 134, 90, 0), - (13090, 119, 348, 10, 0), - (13090, 120, 137, 147, 0), - (13091, 1, 339, 10, 8105), - (13091, 2, 142, 65, 0), - (13091, 3, 311, 0, 0), - (13091, 4, 134, 70, 0), - (13091, 5, 348, 10, 0), - (13091, 6, 137, 0, 0), - (13091, 7, 339, 10, 8105), - (13091, 8, 142, 65, 0), - (13091, 9, 311, 0, 0), - (13091, 10, 134, 70, 0), - (13091, 11, 348, 10, 0), - (13091, 12, 137, 100, 0), - (13091, 13, 339, 10, 8105), - (13091, 14, 142, 65, 0), - (13091, 15, 311, 0, 0), - (13091, 16, 134, 70, 0), - (13091, 17, 348, 10, 0), - (13091, 18, 137, 79, 0), - (13091, 19, 339, 10, 8105), - (13091, 20, 142, 65, 0), - (13091, 21, 311, 0, 0), - (13091, 22, 134, 70, 0), - (13091, 23, 348, 10, 0), - (13091, 24, 137, 147, 0), - (13091, 25, 339, 10, 11404), - (13091, 26, 142, 71, 0), - (13091, 27, 311, 0, 0), - (13091, 28, 134, 75, 0), - (13091, 29, 348, 10, 0), - (13091, 30, 137, 0, 0), - (13091, 31, 339, 10, 11404), - (13091, 32, 142, 71, 0), - (13091, 33, 311, 0, 0), - (13091, 34, 134, 75, 0), - (13091, 35, 348, 10, 0), - (13091, 36, 137, 100, 0), - (13091, 37, 339, 10, 11404), - (13091, 38, 142, 71, 0), - (13091, 39, 311, 0, 0), - (13091, 40, 134, 75, 0), - (13091, 41, 348, 10, 0), - (13091, 42, 137, 79, 0), - (13091, 43, 339, 10, 11404), - (13091, 44, 142, 71, 0), - (13091, 45, 311, 0, 0), - (13091, 46, 134, 75, 0), - (13091, 47, 348, 10, 0), - (13091, 48, 137, 147, 0), - (13091, 49, 339, 10, 13199), - (13091, 50, 142, 76, 0), - (13091, 51, 311, 0, 0), - (13091, 52, 134, 80, 0), - (13091, 53, 348, 10, 0), - (13091, 54, 137, 0, 0), - (13091, 55, 339, 10, 13199), - (13091, 56, 142, 76, 0), - (13091, 57, 311, 0, 0), - (13091, 58, 134, 80, 0), - (13091, 59, 348, 10, 0), - (13091, 60, 137, 100, 0), - (13091, 61, 339, 10, 13199), - (13091, 62, 142, 76, 0), - (13091, 63, 311, 0, 0), - (13091, 64, 134, 80, 0), - (13091, 65, 348, 10, 0), - (13091, 66, 137, 79, 0), - (13091, 67, 339, 10, 13199), - (13091, 68, 142, 76, 0), - (13091, 69, 311, 0, 0), - (13091, 70, 134, 80, 0), - (13091, 71, 348, 10, 0), - (13091, 72, 137, 147, 0), - (13091, 73, 339, 10, 13830), - (13091, 74, 142, 81, 0), - (13091, 75, 311, 0, 0), - (13091, 76, 134, 85, 0), - (13091, 77, 348, 10, 0), - (13091, 78, 137, 0, 0), - (13091, 79, 339, 10, 13830), - (13091, 80, 142, 81, 0), - (13091, 81, 311, 0, 0), - (13091, 82, 134, 85, 0), - (13091, 83, 348, 10, 0), - (13091, 84, 137, 100, 0), - (13091, 85, 339, 10, 13830), - (13091, 86, 142, 81, 0), - (13091, 87, 311, 0, 0), - (13091, 88, 134, 85, 0), - (13091, 89, 348, 10, 0), - (13091, 90, 137, 79, 0), - (13091, 91, 339, 10, 13830), - (13091, 92, 142, 81, 0), - (13091, 93, 311, 0, 0), - (13091, 94, 134, 85, 0), - (13091, 95, 348, 10, 0), - (13091, 96, 137, 147, 0), - (13091, 97, 339, 10, 27527), - (13091, 98, 142, 86, 0), - (13091, 99, 311, 0, 0), - (13091, 100, 134, 90, 0), - (13091, 101, 348, 10, 0), - (13091, 102, 137, 0, 0), - (13091, 103, 339, 10, 27527), - (13091, 104, 142, 86, 0), - (13091, 105, 311, 0, 0), - (13091, 106, 134, 90, 0), - (13091, 107, 348, 10, 0), - (13091, 108, 137, 100, 0), - (13091, 109, 339, 10, 27527), - (13091, 110, 142, 86, 0), - (13091, 111, 311, 0, 0), - (13091, 112, 134, 90, 0), - (13091, 113, 348, 10, 0), - (13091, 114, 137, 79, 0), - (13091, 115, 339, 10, 27527), - (13091, 116, 142, 86, 0), - (13091, 117, 311, 0, 0), - (13091, 118, 134, 90, 0), - (13091, 119, 348, 10, 0), - (13091, 120, 137, 147, 0), - (13092, 1, 217, 0, 102280), - (13092, 2, 346, 84, 18), - (13093, 1, 217, 0, 109400), - (13093, 2, 346, 86, 18), - (13094, 1, 217, 0, 116800), - (13094, 2, 346, 88, 18), - (13095, 1, 439, 0, 140680), - (13095, 2, 345, 88, 25), - (13096, 1, 287, 1, 0), - (13096, 2, 140, 3, 0), - (13096, 3, 348, 1, 0), - (13096, 4, 138, 0, 0), - (13096, 5, 137, 0, 0), - (13097, 1, 287, 2, 0), - (13097, 2, 140, 3, 0), - (13097, 3, 348, 1, 0), - (13097, 4, 138, 0, 0), - (13097, 5, 137, 0, 0), - (13098, 1, 287, 3, 0), - (13098, 2, 140, 3, 0), - (13098, 3, 348, 1, 0), - (13098, 4, 138, 0, 0), - (13098, 5, 137, 0, 0), - (13099, 1, 132, 15, 15), - (13101, 1, 360, 25, 27537), - (13102, 1, 360, 25, 27538), - (13103, 1, 360, 25, 27539), - (13104, 1, 303, 14000, 18000), - (13104, 2, 139, 2766, 0), - (13105, 1, 303, 18000, 22500), - (13105, 2, 139, 2766, 0), - (13106, 1, 303, 22500, 27500), - (13106, 2, 139, 2766, 0), - (13110, 1, 185, 8, 1), - (13110, 2, 185, 8, 3), - (13111, 1, 185, 10, 1), - (13111, 2, 185, 10, 3), - (13113, 1, 185, 7, 36), - (13114, 1, 185, 9, 36), - (13116, 1, 185, 8, 0), - (13116, 2, 185, 8, 2), - (13117, 1, 185, 10, 0), - (13117, 2, 185, 10, 2), - (13122, 1, 2, 128, 0), - (13123, 1, 2, 132, 0), - (13124, 1, 2, 136, 0), - (13127, 1, 287, 4, 0), - (13127, 2, 140, 3, 0), - (13127, 3, 348, 1, 0), - (13127, 4, 138, 0, 0), - (13127, 5, 137, 0, 0), - (13130, 1, 264, 1440, 7003), - (13140, 1, 264, 480, 391), - (13141, 1, 264, 600, 391), - (13142, 1, 264, 720, 391), - (13143, 1, 127, 17, 0), - (13143, 2, 385, 8054, 0), - (13144, 1, 127, 34, 0), - (13144, 2, 385, 8054, 0), - (13145, 1, 127, 50, 0), - (13145, 2, 385, 8054, 0), - (13146, 1, 127, 17, 0), - (13146, 2, 385, 8054, 0), - (13147, 1, 127, 34, 0), - (13147, 2, 385, 8054, 0), - (13148, 1, 127, 50, 0), - (13148, 2, 385, 8054, 0), - (13149, 1, 97, 550, 0), - (13150, 1, 97, 600, 0), - (13151, 1, 97, 650, 0), - (13152, 1, 97, 700, 0), - (13153, 1, 97, 750, 0), - (13166, 1, 264, 5, 749), - (13166, 2, 264, 5, 822), - (13166, 3, 264, 5, 1274), - (13166, 4, 264, 5, 1275), - (13167, 1, 264, 10, 749), - (13167, 2, 264, 10, 822), - (13167, 3, 264, 10, 1274), - (13167, 4, 264, 10, 1275), - (13168, 1, 264, 15, 749), - (13168, 2, 264, 15, 822), - (13168, 3, 264, 15, 1274), - (13168, 4, 264, 15, 1275), - (13184, 1, 220, 315, 26), - (13185, 1, 220, 400, 26), - (13186, 1, 220, 500, 26), - (13187, 1, 405, 19, 0), - (13188, 1, 405, 21, 0), - (13189, 1, 405, 23, 0), - (13196, 1, 279, 31, 0), - (13197, 1, 279, 35, 0), - (13198, 1, 279, 39, 0), - (13199, 1, 378, 30, 31), - (13200, 1, 378, 35, 31), - (13201, 1, 378, 40, 31), - (13204, 1, 264, 180, 8261), - (13205, 1, 264, 360, 8261), - (13206, 1, 264, 540, 8261), - (13207, 1, 288, 100, 8), - (13208, 1, 288, 100, 8), - (13209, 1, 288, 100, 8), - (13210, 1, 325, 70, 0), - (13211, 1, 325, 75, 0), - (13212, 1, 325, 80, 0), - (13213, 1, 220, 285, 8), - (13214, 1, 220, 315, 8), - (13215, 1, 220, 350, 8), - (13216, 1, 220, 390, 8), - (13217, 1, 220, 440, 8), - (13218, 1, 216, 750, 8), - (13219, 1, 114, -12, 0), - (13220, 1, 114, -15, 0), - (13221, 1, 114, -18, 0), - (13222, 1, 310, 240000, 0), - (13222, 2, 139, 6197, 0), - (13222, 3, 411, 512, 0), - (13223, 1, 310, 300000, 0), - (13223, 2, 139, 6197, 0), - (13223, 3, 411, 512, 0), - (13226, 1, 360, 60, 27593), - (13238, 1, 320, 9, 0), - (13239, 1, 320, 10, 0), - (13240, 1, 320, 11, 0), - (13262, 1, 264, 1008, 102), - (13263, 1, 264, 1152, 102), - (13264, 1, 264, 1290, 102), - (13278, 1, 213, 25, 0), - (13281, 1, 318, 31, 0), - (13286, 1, 278, 900, 102200), - (13286, 2, 440, 92, 100), - (13294, 1, 339, 10, 8105), - (13294, 2, 142, 65, 0), - (13294, 3, 311, 0, 0), - (13294, 4, 134, 70, 0), - (13294, 5, 348, 10, 0), - (13294, 6, 137, 0, 0), - (13294, 7, 339, 10, 8105), - (13294, 8, 142, 65, 0), - (13294, 9, 311, 0, 0), - (13294, 10, 134, 70, 0), - (13294, 11, 348, 10, 0), - (13294, 12, 137, 100, 0), - (13294, 13, 339, 10, 8105), - (13294, 14, 142, 65, 0), - (13294, 15, 311, 0, 0), - (13294, 16, 134, 70, 0), - (13294, 17, 348, 10, 0), - (13294, 18, 137, 79, 0), - (13294, 19, 339, 10, 8105), - (13294, 20, 142, 65, 0), - (13294, 21, 311, 0, 0), - (13294, 22, 134, 70, 0), - (13294, 23, 348, 10, 0), - (13294, 24, 137, 147, 0), - (13294, 25, 339, 10, 11404), - (13294, 26, 142, 71, 0), - (13294, 27, 311, 0, 0), - (13294, 28, 134, 75, 0), - (13294, 29, 348, 10, 0), - (13294, 30, 137, 0, 0), - (13294, 31, 339, 10, 11404), - (13294, 32, 142, 71, 0), - (13294, 33, 311, 0, 0), - (13294, 34, 134, 75, 0), - (13294, 35, 348, 10, 0), - (13294, 36, 137, 100, 0), - (13294, 37, 339, 10, 11404), - (13294, 38, 142, 71, 0), - (13294, 39, 311, 0, 0), - (13294, 40, 134, 75, 0), - (13294, 41, 348, 10, 0), - (13294, 42, 137, 79, 0), - (13294, 43, 339, 10, 11404), - (13294, 44, 142, 71, 0), - (13294, 45, 311, 0, 0), - (13294, 46, 134, 75, 0), - (13294, 47, 348, 10, 0), - (13294, 48, 137, 147, 0), - (13294, 49, 339, 10, 13199), - (13294, 50, 142, 76, 0), - (13294, 51, 311, 0, 0), - (13294, 52, 134, 80, 0), - (13294, 53, 348, 10, 0), - (13294, 54, 137, 0, 0), - (13294, 55, 339, 10, 13199), - (13294, 56, 142, 76, 0), - (13294, 57, 311, 0, 0), - (13294, 58, 134, 80, 0), - (13294, 59, 348, 10, 0), - (13294, 60, 137, 100, 0), - (13294, 61, 339, 10, 13199), - (13294, 62, 142, 76, 0), - (13294, 63, 311, 0, 0), - (13294, 64, 134, 80, 0), - (13294, 65, 348, 10, 0), - (13294, 66, 137, 79, 0), - (13294, 67, 339, 10, 13199), - (13294, 68, 142, 76, 0), - (13294, 69, 311, 0, 0), - (13294, 70, 134, 80, 0), - (13294, 71, 348, 10, 0), - (13294, 72, 137, 147, 0), - (13294, 73, 339, 10, 13830), - (13294, 74, 142, 81, 0), - (13294, 75, 311, 0, 0), - (13294, 76, 134, 85, 0), - (13294, 77, 348, 10, 0), - (13294, 78, 137, 0, 0), - (13294, 79, 339, 10, 13830), - (13294, 80, 142, 81, 0), - (13294, 81, 311, 0, 0), - (13294, 82, 134, 85, 0), - (13294, 83, 348, 10, 0), - (13294, 84, 137, 100, 0), - (13294, 85, 339, 10, 13830), - (13294, 86, 142, 81, 0), - (13294, 87, 311, 0, 0), - (13294, 88, 134, 85, 0), - (13294, 89, 348, 10, 0), - (13294, 90, 137, 79, 0), - (13294, 91, 339, 10, 13830), - (13294, 92, 142, 81, 0), - (13294, 93, 311, 0, 0), - (13294, 94, 134, 85, 0), - (13294, 95, 348, 10, 0), - (13294, 96, 137, 147, 0), - (13294, 97, 339, 10, 27527), - (13294, 98, 142, 86, 0), - (13294, 99, 311, 0, 0), - (13294, 100, 134, 90, 0), - (13294, 101, 348, 10, 0), - (13294, 102, 137, 0, 0), - (13294, 103, 339, 10, 27527), - (13294, 104, 142, 86, 0), - (13294, 105, 311, 0, 0), - (13294, 106, 134, 90, 0), - (13294, 107, 348, 10, 0), - (13294, 108, 137, 100, 0), - (13294, 109, 339, 10, 27527), - (13294, 110, 142, 86, 0), - (13294, 111, 311, 0, 0), - (13294, 112, 134, 90, 0), - (13294, 113, 348, 10, 0), - (13294, 114, 137, 79, 0), - (13294, 115, 339, 10, 27527), - (13294, 116, 142, 86, 0), - (13294, 117, 311, 0, 0), - (13294, 118, 134, 90, 0), - (13294, 119, 348, 10, 0), - (13294, 120, 137, 147, 0), - (13294, 121, 339, 10, 30644), - (13294, 122, 142, 91, 0), - (13294, 123, 311, 0, 0), - (13294, 124, 134, 95, 0), - (13294, 125, 348, 10, 0), - (13294, 126, 137, 0, 0), - (13294, 127, 339, 10, 30644), - (13294, 128, 142, 91, 0), - (13294, 129, 311, 0, 0), - (13294, 130, 134, 95, 0), - (13294, 131, 348, 10, 0), - (13294, 132, 137, 100, 0), - (13294, 133, 339, 10, 30644), - (13294, 134, 142, 91, 0), - (13294, 135, 311, 0, 0), - (13294, 136, 134, 95, 0), - (13294, 137, 348, 10, 0), - (13294, 138, 137, 79, 0), - (13294, 139, 339, 10, 30644), - (13294, 140, 142, 91, 0), - (13294, 141, 311, 0, 0), - (13294, 142, 134, 95, 0), - (13294, 143, 348, 10, 0), - (13294, 144, 137, 147, 0), - (13295, 1, 339, 10, 8105), - (13295, 2, 142, 65, 0), - (13295, 3, 311, 0, 0), - (13295, 4, 134, 70, 0), - (13295, 5, 348, 10, 0), - (13295, 6, 137, 0, 0), - (13295, 7, 339, 10, 8105), - (13295, 8, 142, 65, 0), - (13295, 9, 311, 0, 0), - (13295, 10, 134, 70, 0), - (13295, 11, 348, 10, 0), - (13295, 12, 137, 100, 0), - (13295, 13, 339, 10, 8105), - (13295, 14, 142, 65, 0), - (13295, 15, 311, 0, 0), - (13295, 16, 134, 70, 0), - (13295, 17, 348, 10, 0), - (13295, 18, 137, 79, 0), - (13295, 19, 339, 10, 8105), - (13295, 20, 142, 65, 0), - (13295, 21, 311, 0, 0), - (13295, 22, 134, 70, 0), - (13295, 23, 348, 10, 0), - (13295, 24, 137, 147, 0), - (13295, 25, 339, 10, 11404), - (13295, 26, 142, 71, 0), - (13295, 27, 311, 0, 0), - (13295, 28, 134, 75, 0), - (13295, 29, 348, 10, 0), - (13295, 30, 137, 0, 0), - (13295, 31, 339, 10, 11404), - (13295, 32, 142, 71, 0), - (13295, 33, 311, 0, 0), - (13295, 34, 134, 75, 0), - (13295, 35, 348, 10, 0), - (13295, 36, 137, 100, 0), - (13295, 37, 339, 10, 11404), - (13295, 38, 142, 71, 0), - (13295, 39, 311, 0, 0), - (13295, 40, 134, 75, 0), - (13295, 41, 348, 10, 0), - (13295, 42, 137, 79, 0), - (13295, 43, 339, 10, 11404), - (13295, 44, 142, 71, 0), - (13295, 45, 311, 0, 0), - (13295, 46, 134, 75, 0), - (13295, 47, 348, 10, 0), - (13295, 48, 137, 147, 0), - (13295, 49, 339, 10, 13199), - (13295, 50, 142, 76, 0), - (13295, 51, 311, 0, 0), - (13295, 52, 134, 80, 0), - (13295, 53, 348, 10, 0), - (13295, 54, 137, 0, 0), - (13295, 55, 339, 10, 13199), - (13295, 56, 142, 76, 0), - (13295, 57, 311, 0, 0), - (13295, 58, 134, 80, 0), - (13295, 59, 348, 10, 0), - (13295, 60, 137, 100, 0), - (13295, 61, 339, 10, 13199), - (13295, 62, 142, 76, 0), - (13295, 63, 311, 0, 0), - (13295, 64, 134, 80, 0), - (13295, 65, 348, 10, 0), - (13295, 66, 137, 79, 0), - (13295, 67, 339, 10, 13199), - (13295, 68, 142, 76, 0), - (13295, 69, 311, 0, 0), - (13295, 70, 134, 80, 0), - (13295, 71, 348, 10, 0), - (13295, 72, 137, 147, 0), - (13295, 73, 339, 10, 13830), - (13295, 74, 142, 81, 0), - (13295, 75, 311, 0, 0), - (13295, 76, 134, 85, 0), - (13295, 77, 348, 10, 0), - (13295, 78, 137, 0, 0), - (13295, 79, 339, 10, 13830), - (13295, 80, 142, 81, 0), - (13295, 81, 311, 0, 0), - (13295, 82, 134, 85, 0), - (13295, 83, 348, 10, 0), - (13295, 84, 137, 100, 0), - (13295, 85, 339, 10, 13830), - (13295, 86, 142, 81, 0), - (13295, 87, 311, 0, 0), - (13295, 88, 134, 85, 0), - (13295, 89, 348, 10, 0), - (13295, 90, 137, 79, 0), - (13295, 91, 339, 10, 13830), - (13295, 92, 142, 81, 0), - (13295, 93, 311, 0, 0), - (13295, 94, 134, 85, 0), - (13295, 95, 348, 10, 0), - (13295, 96, 137, 147, 0), - (13295, 97, 339, 10, 27527), - (13295, 98, 142, 86, 0), - (13295, 99, 311, 0, 0), - (13295, 100, 134, 90, 0), - (13295, 101, 348, 10, 0), - (13295, 102, 137, 0, 0), - (13295, 103, 339, 10, 27527), - (13295, 104, 142, 86, 0), - (13295, 105, 311, 0, 0), - (13295, 106, 134, 90, 0), - (13295, 107, 348, 10, 0), - (13295, 108, 137, 100, 0), - (13295, 109, 339, 10, 27527), - (13295, 110, 142, 86, 0), - (13295, 111, 311, 0, 0), - (13295, 112, 134, 90, 0), - (13295, 113, 348, 10, 0), - (13295, 114, 137, 79, 0), - (13295, 115, 339, 10, 27527), - (13295, 116, 142, 86, 0), - (13295, 117, 311, 0, 0), - (13295, 118, 134, 90, 0), - (13295, 119, 348, 10, 0), - (13295, 120, 137, 147, 0), - (13295, 121, 339, 10, 30644), - (13295, 122, 142, 91, 0), - (13295, 123, 311, 0, 0), - (13295, 124, 134, 95, 0), - (13295, 125, 348, 10, 0), - (13295, 126, 137, 0, 0), - (13295, 127, 339, 10, 30644), - (13295, 128, 142, 91, 0), - (13295, 129, 311, 0, 0), - (13295, 130, 134, 95, 0), - (13295, 131, 348, 10, 0), - (13295, 132, 137, 100, 0), - (13295, 133, 339, 10, 30644), - (13295, 134, 142, 91, 0), - (13295, 135, 311, 0, 0), - (13295, 136, 134, 95, 0), - (13295, 137, 348, 10, 0), - (13295, 138, 137, 79, 0), - (13295, 139, 339, 10, 30644), - (13295, 140, 142, 91, 0), - (13295, 141, 311, 0, 0), - (13295, 142, 134, 95, 0), - (13295, 143, 348, 10, 0), - (13295, 144, 137, 147, 0), - (13296, 1, 125, 49, 49), - (13296, 2, 137, 0, 0), - (13296, 3, 141, 1, 0), - (13296, 4, 139, -6233, 0), - (13296, 5, 139, -6265, 0), - (13296, 6, 125, 49, 49), - (13296, 7, 137, 147, 0), - (13296, 8, 141, 1, 0), - (13297, 1, 125, 52, 52), - (13297, 2, 137, 0, 0), - (13297, 3, 141, 1, 0), - (13297, 4, 139, -6233, 0), - (13297, 5, 139, -6265, 0), - (13297, 6, 125, 52, 52), - (13297, 7, 137, 147, 0), - (13297, 8, 141, 1, 0), - (13299, 1, 319, 31, 0), - (13302, 1, 274, 44, 0), - (13305, 1, 189, 19, 0), - (13308, 1, 265, 87, 0), - (13313, 1, 15, 29, 0), - (13318, 1, 97, 850, 0), - (13323, 1, 320, 15, 0), - (13326, 1, 330, 155, 0), - (13326, 2, 330, 155, 1), - (13326, 3, 330, 155, 2), - (13326, 4, 330, 155, 3), - (13326, 5, 330, 155, 28), - (13326, 6, 330, 155, 36), - (13332, 1, 330, 155, 0), - (13332, 2, 330, 155, 1), - (13332, 3, 330, 155, 2), - (13332, 4, 330, 155, 3), - (13332, 5, 330, 155, 28), - (13332, 6, 330, 155, 36), - (13332, 7, 330, 155, 77), - (13338, 1, 1, 370, 0), - (13343, 1, 1, 340, 0), - (13348, 1, 1, 440, 0), - (13353, 1, 1, 330, 0), - (13358, 1, 1, 540, 0), - (13396, 1, 375, 40, 0), - (13404, 1, 273, 8, 0), - (13411, 1, 399, 4, 0), - (13411, 2, 138, 1, 0), - (13411, 3, 137, 0, 0), - (13411, 4, 348, 10, 0), - (13411, 5, 311, 0, 0), - (13411, 6, 141, 1, 0), - (13411, 7, 134, 254, 0), - (13411, 8, 137, -39, 0), - (13413, 1, 399, 12, 0), - (13413, 2, 141, 1, 0), - (13413, 3, 138, 0, 0), - (13413, 4, 142, 255, 0), - (13413, 5, 391, 0, 0), - (13413, 6, 311, 0, 0), - (13413, 7, 137, -152, 0), - (13413, 8, 411, 100350, 0), - (13413, 9, 137, -39, 0), - (13415, 1, 264, 150, 705), - (13415, 2, 264, 150, 1092), - (13415, 3, 264, 150, 10396), - (13415, 4, 264, 150, 10397), - (13416, 1, 264, 20, 626), - (13438, 1, 266, 29, 0), - (13449, 1, 264, 2, 11073), - (13463, 1, 264, 90, 458), - (13474, 1, 264, 120, 444), - (13477, 1, 126, 20, 0), - (13477, 2, 134, 95, 0), - (13477, 3, 135, 4, 0), - (13477, 4, 135, 5, 0), - (13485, 1, 279, 3, 0), - (13502, 1, 375, 160, 0), - (13508, 1, 378, 5, 3), - (13511, 1, 279, 43, 0), - (13520, 1, 292, 70, 0), - (13521, 1, 293, 25, 0), - (13533, 1, 378, 55, 96), - (13545, 1, 323, 30787, 0), - (13562, 1, 264, 480, 872), - (13565, 1, 264, 60, 3804), - (13568, 1, 264, 60, 876), - (13578, 1, 244, 30, 0), - (13589, 1, 279, 34, 0), - (13590, 1, 279, 38, 0), - (13598, 1, 339, 20, 30809), - (13598, 2, 137, 21, 0), - (13598, 3, 385, -18000, 0), - (13598, 4, 339, 20, 30809), - (13598, 5, 137, 343, 0), - (13598, 6, 385, -18000, 0), - (13601, 1, 231, 22, 0), - (13607, 1, 126, 4, 4), - (13607, 2, 137, 21, 0), - (13607, 3, 231, 4, 4), - (13610, 1, 266, 47, 0), - (13613, 1, 220, 260, 10), - (13616, 1, 220, 150, 2), - (13616, 2, 220, 150, 3), - (13616, 3, 220, 150, 77), - (13617, 1, 220, 375, 2), - (13617, 2, 220, 375, 3), - (13617, 3, 220, 375, 77), - (13618, 1, 220, 500, 2), - (13618, 2, 220, 500, 3), - (13618, 3, 220, 500, 77), - (13621, 1, 218, 11, 0), - (13627, 1, 59, -59, 0), - (13628, 1, 59, -64, 0), - (13630, 1, 398, 10000, 0), - (13630, 2, 137, 152, 0), - (13667, 1, 287, 1, 0), - (13667, 2, 385, 8054, 0), - (13675, 1, 218, 24, 0), - (13684, 1, 399, 2, 0), - (13684, 2, 140, 2, 0), - (13684, 3, 348, 10, 0), - (13684, 4, 138, 0, 0), - (13684, 5, 137, -152, 0), - (13684, 6, 137, -39, 0), - (13685, 1, 399, 3, 0), - (13685, 2, 140, 2, 0), - (13685, 3, 348, 10, 0), - (13685, 4, 138, 0, 0), - (13685, 5, 137, -152, 0), - (13685, 6, 137, -39, 0), - (13686, 1, 399, 4, 0), - (13686, 2, 140, 2, 0), - (13686, 3, 348, 10, 0), - (13686, 4, 138, 0, 0), - (13686, 5, 137, -152, 0), - (13686, 6, 137, -39, 0), - (13689, 1, 127, 10, 0), - (13689, 2, 139, 27592, 0), - (13689, 3, 139, 31548, 0), - (13707, 1, 274, 26, 0), - (13710, 1, 280, 65, 0), - (13713, 1, 218, 26, 0), - (13753, 1, 264, 360, 534), - (13758, 1, 264, 360, 602), - (13763, 1, 287, 4, 0), - (13763, 2, 137, 31, 0), - (13763, 3, 136, 5, 0), - (13764, 1, 264, 60, 535), - (13767, 1, 439, 0, 153514), - (13767, 2, 345, 90, 22), - (13773, 1, 279, 21, 0), - (13774, 1, 279, 23, 0), - (13775, 1, 279, 25, 0), - (13779, 1, 288, 100, 8), - (13782, 1, 220, 490, 8), - (13789, 1, 216, 850, 8), - (13790, 1, 216, 950, 8), - (13795, 1, 258, 73, 0), - (13798, 1, 114, -21, 0), - (13804, 1, 378, 4, 3), - (13813, 1, 220, 150, 28), - (13813, 2, 220, 150, 0), - (13813, 3, 427, 23598, 9), - (13813, 4, 428, 28, 0), - (13813, 5, 428, 0, 0), - (13820, 1, 220, 325, 26), - (13820, 2, 220, 325, 30), - (13820, 3, 220, 325, 38), - (13823, 1, 220, 295, 21), - (13823, 2, 220, 295, 23), - (13823, 3, 220, 670, 52), - (13823, 4, 220, 295, 28), - (13826, 1, 405, 25, 0), - (13829, 1, 220, 550, 26), - (13835, 1, 283, 300, 0), - (13841, 1, 264, 17, 469), - (13873, 1, 264, 30, 961), - (13878, 1, 264, 60, 609), - (13881, 1, 264, 60, 387), - (13884, 1, 265, 87, 0), - (13889, 1, 264, 60, 1012), - (13894, 1, 327, 13, 0), - (13905, 1, 310, 24000, 0), - (13905, 2, 385, 15319, 0), - (13908, 1, 310, 3000, 0), - (13908, 2, 385, 15307, 0), - (13908, 3, 385, 15407, 0), - (13908, 4, 385, 15507, 0), - (13908, 5, 385, 15607, 0), - (13911, 1, 310, 3000, 0), - (13911, 2, 385, 16005, 0), - (13911, 3, 310, 3000, 0), - (13911, 4, 385, 15405, 0), - (13911, 5, 385, 15505, 0), - (13911, 6, 385, 15605, 0), - (13911, 7, 411, 2, 0), - (13917, 1, 264, 120, 606), - (13921, 1, 114, -66, 0), - (13924, 1, 114, -64, 0), - (13927, 1, 114, -25, 0), - (13930, 1, 341, 310, 0), - (13933, 1, 262, 80, 0), - (13943, 1, 262, 80, 1), - (13953, 1, 262, 80, 2), - (13963, 1, 262, 80, 3), - (13973, 1, 262, 80, 4), - (13983, 1, 262, 80, 5), - (13993, 1, 262, 80, 6), - (14011, 1, 264, 30, 10394), - (14017, 1, 69, 10, 0), - (14018, 1, 69, 10, 0), - (14026, 1, 185, 3, 2), - (14026, 2, 185, 3, 3), - (14026, 3, 185, 3, 77), - (14026, 4, 220, 50, 2), - (14026, 5, 220, 50, 3), - (14026, 6, 220, 50, 77), - (14029, 1, 395, 5, 5), - (14029, 2, 385, 9758, 0), - (14029, 3, 385, 9858, 0), - (14029, 4, 385, 9958, 0), - (14032, 1, 181, 100, 0), - (14037, 1, 264, 180, 804), - (14040, 1, 264, 180, 300), - (14043, 1, 85, 32197, 0), - (14046, 1, 264, 90, 87), - (14056, 1, 310, 360000, 0), - (14056, 2, 139, 4504, 0), - (14059, 1, 310, -180000, 0), - (14059, 2, 139, 4520, 0), - (14062, 1, 264, 60, 821), - (14065, 1, 264, 60, 3215), - (14068, 1, 264, 60, 3216), - (14076, 1, 310, 480000, 0), - (14076, 2, 139, 4518, 0), - (14082, 1, 360, 26, 32314), - (14085, 1, 264, 2, 741), - (14088, 1, 264, 30, 769), - (14091, 1, 264, 120, 701), - (14094, 1, 124, 325, 350), - (14094, 2, 385, 19, 0), - (14094, 3, 144, 0, 0), - (14094, 4, 403, 3, 0), - (14094, 5, 404, 48, 0), - (14094, 6, 385, -21768, 0), - (14097, 1, 85, 32317, 5), - (14100, 1, 127, 50, 0), - (14100, 2, 137, 21, 0), - (14100, 3, 143, 1, 0), - (14100, 4, 134, 253, 0), - (14100, 5, 348, 1, 0), - (14101, 1, 310, 2520000, 0), - (14101, 2, 139, 4506, 0), - (14101, 3, 310, 2520000, 0), - (14101, 4, 385, 11122, 0), - (14101, 5, 385, 11222, 0), - (14101, 6, 385, 11322, 0), - (14101, 7, 385, 11522, 0), - (14115, 1, 287, 1, 0), - (14115, 2, 385, 16130, 0), - (14129, 1, 220, 60, 36), - (14129, 2, 427, 32327, 3), - (14129, 3, 428, 36, 0), - (14130, 1, 220, 90, 36), - (14130, 2, 427, 32327, 5), - (14130, 3, 428, 36, 0), - (14132, 1, 264, 240, 2234), - (14135, 1, 310, 132000, 0), - (14135, 2, 385, 13005, 0), - (14135, 3, 385, 12423, 0), - (14135, 4, 385, 12504, 0), - (14135, 5, 310, 132000, 0), - (14135, 6, 139, 4676, 0), - (14135, 7, 411, 512, 0), - (14138, 1, 310, 480000, 0), - (14138, 2, 139, 4695, 0), - (14138, 3, 411, 512, 0), - (14140, 1, 310, 24000, 0), - (14140, 2, 385, 13007, 0), - (14140, 3, 385, 12105, 0), - (14140, 4, 385, 12205, 0), - (14140, 5, 310, 72000, 0), - (14140, 6, 385, 12305, 0), - (14140, 7, 385, 12405, 0), - (14140, 8, 385, 12505, 0), - (14140, 9, 411, 512, 0), - (14141, 1, 185, 2, 36), - (14144, 1, 287, 1, 0), - (14144, 2, 385, 13204, 0), - (14144, 3, 411, 512, 0), - (14148, 1, 310, 90000, 0), - (14148, 2, 139, 4691, 0), - (14151, 1, 185, 2, 26), - (14151, 2, 220, 100, 26), - (14154, 1, 264, 2100, 276), - (14157, 1, 216, 150, 26), - (14160, 1, 264, 60, 7001), - (14163, 1, 287, 1, 0), - (14163, 2, 385, 16178, 0), - (14163, 3, 411, 128, 0), - (14166, 1, 264, 60, 945), - (14169, 1, 310, 202500, 0), - (14169, 2, 139, 8030, 0), - (14169, 3, 411, 256, 0), - (14173, 1, 310, 1440000, 0), - (14173, 2, 139, 4516, 0), - (14173, 3, 411, 256, 0), - (14176, 1, 264, 660, 8261), - (14179, 1, 287, 1, 0), - (14179, 2, 385, 5830, 0), - (14179, 3, 411, 256, 0), - (14180, 1, 287, 1, 0), - (14180, 2, 139, 8030, 0), - (14180, 3, 411, 256, 0), - (14181, 1, 247, 25, 20), - (14186, 1, 247, 25, 76), - (14196, 1, 264, 2340, 465), - (14199, 1, 264, 720, 499), - (14200, 1, 288, 15, 2), - (14200, 2, 288, 15, 3), - (14200, 3, 288, 15, 51), - (14200, 4, 288, 15, 77), - (14203, 1, 310, 150000, 0), - (14203, 2, 385, 3419, 0), - (14203, 3, 385, 14005, 0), - (14203, 4, 385, 3519, 0), - (14203, 5, 411, 65536, 0), - (14210, 1, 310, 40000, 0), - (14210, 2, 139, 1546, 0), - (14210, 3, 310, 40000, 0), - (14210, 4, 385, 4357, 0), - (14210, 5, 385, 4457, 0), - (14210, 6, 385, 4557, 0), - (14210, 7, 385, 4657, 0), - (14210, 8, 411, 4, 0), - (14213, 1, 264, 120, 1065), - (14218, 1, 232, 23, 4544), - (14223, 1, 264, 40, 47), - (14225, 1, 127, 16, 0), - (14225, 2, 385, 3283, 0), - (14225, 3, 411, 1024, 0), - (14238, 1, 264, 12, 1041), - (14241, 1, 264, 180, 386), - (14244, 1, 286, 100, 0), - (14244, 2, 138, 0, 0), - (14244, 3, 143, 1, 0), - (14244, 4, 348, 1, 0), - (14244, 5, 411, 64, 0), - (14249, 1, 392, 200, 0), - (14249, 2, 138, 1, 0), - (14249, 3, 348, 1, 0), - (14254, 1, 287, 1, 0), - (14254, 2, 385, 2025, 0), - (14254, 3, 385, 5121, 0), - (14254, 4, 385, 5221, 0), - (14254, 5, 385, 5562, 0), - (14259, 1, 287, 1, 0), - (14259, 2, 139, 23585, 0), - (14275, 1, 239, 20, 0), - (14278, 1, 287, 4, 0), - (14278, 2, 385, 16439, 0), - (14278, 3, 411, 32768, 0), - (14279, 1, 320, 8, 0), - (14283, 1, 127, 17, 0), - (14283, 2, 385, 3151, 0), - (14283, 3, 385, 5887, 0), - (14286, 1, 287, 1, 0), - (14286, 2, 385, 4877, 0), - (14289, 1, 127, 10, 0), - (14289, 2, 385, 2754, 0), - (14292, 1, 127, 10, 0), - (14292, 2, 385, 3286, 0), - (14295, 1, 264, 1, 3816), - (14301, 1, 405, 5, 0), - (14304, 1, 264, 45, 8341), - (14308, 1, 264, 20, 431), - (14311, 1, 264, 360, 430), - (14314, 1, 264, 8, 901), - (14318, 1, 127, 10, 0), - (14318, 2, 139, 21754, 0), - (14328, 1, 264, 6, 1154), - (14331, 1, 264, 120, 515), - (14341, 1, 264, 360, 748), - (14349, 1, 294, 0, 205), - (14361, 1, 294, 35, 109), - (14364, 1, 264, 90, 173), - (14367, 1, 445, 1, 0), - (14764, 1, 339, 10, 33950), - (14764, 2, 137, 31, 0), - (15074, 1, 264, 5, 15073), - (15100, 1, 264, 2, 467), - (15105, 1, 264, 120, 131), - (15108, 1, 310, 60000, 0), - (15108, 2, 385, 15521, 0), - (15108, 3, 411, 2, 0), - (15111, 1, 287, 1, 0), - (15111, 2, 385, 21778, 0), - (15113, 1, 287, 3, 0), - (15113, 2, 385, 21778, 0), - (15113, 3, 411, 2, 0), - (15120, 1, 264, 60, 800), - (15123, 1, 310, 120000, 0), - (15123, 2, 385, 15422, 0), - (15123, 3, 411, 2, 0), - (15126, 1, 310, 1000, 0), - (15126, 2, 385, 15212, 0), - (15126, 3, 411, 2, 0), - (15132, 1, 264, 10, 660), - (15135, 1, 287, 1, 0), - (15135, 2, 139, 32313, 0), - (15141, 1, 219, 420, 2400), - (15150, 1, 127, 10, 0), - (15150, 2, 385, 10505, 0), - (15150, 3, 385, 10105, 0), - (15150, 4, 385, 10205, 0), - (15150, 5, 385, 10305, 0), - (15150, 6, 385, 10405, 0), - (15150, 7, 385, 10605, 0), - (15153, 1, 287, 1, 0), - (15153, 2, 139, 4518, 0), - (15154, 1, 287, 1, 0), - (15154, 2, 139, 32312, 0), - (15155, 1, 287, 1, 0), - (15155, 2, 385, 10320, 0), - (15155, 3, 385, 10420, 0), - (15155, 4, 385, 10520, 0), - (15158, 1, 287, 1, 0), - (15158, 2, 385, 32307, 0), - (15159, 1, 287, 1, 0), - (15159, 2, 385, 27537, 0), - (15162, 1, 264, 120, 659), - (15168, 1, 264, 60, 657), - (15172, 1, 302, 430, 430), - (15172, 2, 385, 99, 0), - (15174, 1, 264, 40, 9400), - (15179, 1, 127, 10, 0), - (15179, 2, 139, 21804, 0), - (15179, 3, 139, 38280, 0), - (15182, 1, 264, 840, 9403), - (15188, 1, 239, 62, 0), - (15194, 1, 287, 1, 0), - (15194, 2, 385, 13407, 0), - (15194, 3, 385, 13507, 0), - (15204, 1, 264, 60, 390), - (15207, 1, 264, 60, 323), - (15217, 1, 339, 10, 38319), - (15217, 2, 385, 11006, 0), - (15217, 3, 385, 7108, 0), - (15217, 4, 385, 7208, 0), - (15217, 5, 385, 7308, 0), - (15217, 6, 385, 7408, 0), - (15217, 7, 385, 7508, 0), - (15217, 8, 385, 7608, 0), - (15220, 1, 287, 1, 0), - (15220, 2, 385, 11065, 0), - (15223, 1, 287, 1, 0), - (15223, 2, 385, 11067, 0), - (15226, 1, 287, 1, 0), - (15226, 2, 385, 11064, 0), - (15229, 1, 287, 1, 0), - (15229, 2, 385, 11066, 0), - (15232, 1, 339, 100, 38322), - (15232, 2, 385, 7518, 0), - (15238, 1, 264, 240, 621), - (15238, 2, 264, 240, 622), - (15238, 3, 264, 240, 623), - (15238, 4, 264, 240, 784), - (15238, 5, 264, 240, 785), - (15238, 6, 264, 240, 786), - (15238, 7, 264, 240, 787), - (15238, 8, 264, 240, 624), - (15253, 1, 127, 10, 0), - (15253, 2, 385, 32322, 0), - (15258, 1, 264, 540, 184), - (15270, 1, 264, 1980, 7003), - (15280, 1, 264, 720, 778), - (15283, 1, 310, 1000, 0), - (15283, 2, 385, 11402, 0), - (15283, 3, 385, 11502, 0), - (15283, 4, 385, 11441, 0), - (15283, 5, 385, 11541, 0), - (15283, 6, 385, 11641, 0), - (15288, 1, 220, 50, 0), - (15288, 2, 220, 50, 1), - (15288, 3, 220, 100, 2), - (15288, 4, 220, 100, 3), - (15288, 5, 220, 50, 36), - (15288, 6, 220, 100, 77), - (15295, 1, 127, 10, 0), - (15295, 2, 385, 21654, 0), - (15314, 1, 264, 25920, 36), - (15317, 1, 264, 1728, 35), - (15320, 1, 264, 150, 558), - (15328, 1, 339, 25, 38037), - (15328, 2, 138, 1, 0), - (15328, 3, 142, 65, 0), - (15328, 4, 137, 35, 0), - (15328, 5, 134, 90, 0), - (15328, 6, 339, 25, 38037), - (15328, 7, 138, 1, 0), - (15328, 8, 142, 65, 0), - (15328, 9, 137, 36, 0), - (15328, 10, 134, 90, 0), - (15328, 11, 339, 25, 38037), - (15328, 12, 138, 1, 0), - (15328, 13, 142, 65, 0), - (15328, 14, 137, 369, 0), - (15328, 15, 134, 90, 0), - (15328, 16, 339, 25, 38037), - (15328, 17, 138, 1, 0), - (15328, 18, 142, 65, 0), - (15328, 19, 137, 116, 0), - (15328, 20, 134, 90, 0), - (15342, 1, 287, 1, 0), - (15342, 2, 385, 23605, 0), - (15344, 1, 264, 360, 38), - (15348, 1, 264, 240, 9504), - (15356, 1, 232, 20, 4544), - (15358, 1, 287, 1, 0), - (15358, 2, 385, 32350, 0), - (15359, 1, 264, 960, 50), - (15363, 1, 264, 240, 447), - (15371, 1, 264, 1, 3729), - (15374, 1, 195, 20, 0), - (15383, 1, 310, 1000, 0), - (15383, 2, 385, 5132, 0), - (15383, 3, 385, 5232, 0), - (15383, 4, 385, 5332, 0), - (15383, 5, 385, 5432, 0), - (15383, 6, 385, 5532, 0), - (15383, 7, 385, 5032, 0), - (15383, 8, 385, 5632, 0), - (15389, 1, 127, 16, 0), - (15389, 2, 385, 23575, 0), - (15396, 1, 127, 20, 20), - (15396, 2, 137, 0, 0), - (15396, 3, 138, 0, 0), - (15396, 4, 141, 1, 0), - (15396, 5, 143, 3000, 0), - (15396, 6, 127, 20, 20), - (15396, 7, 385, 16555, 0), - (15396, 8, 385, 16655, 0), - (15397, 1, 264, 1260, 494), - (15403, 1, 264, 10, 8604), - (15406, 1, 127, 10, 10), - (15406, 2, 385, 37097, 0), - (15414, 1, 287, 1, 0), - (15414, 2, 139, 30736, 0), - (15421, 1, 264, 3600, 245), - (15422, 1, 132, 15, 15), - (15426, 1, 239, 62, 0), - (15429, 1, 220, 135, 2), - (15432, 1, 184, 5, -1), - (15438, 1, 310, 180000, 0), - (15438, 2, 385, 8316, 0), - (15438, 3, 411, 128, 0), - (15441, 1, 279, 38, 0), - (15444, 1, 288, 60, 26), - (15450, 1, 310, 3000, 0), - (15450, 2, 385, 8202, 0), - (15450, 3, 385, 8302, 0), - (15450, 4, 385, 8402, 0), - (15450, 5, 385, 8502, 0), - (15450, 6, 385, 8602, 0), - (15450, 7, 411, 128, 0), - (15453, 1, 310, 60000, 0), - (15453, 2, 385, 8421, 0), - (15453, 3, 411, 128, 0), - (15456, 1, 264, 5, 470), - (15466, 1, 126, 20, 20), - (15466, 2, 139, 12576, 0), - (15466, 3, 126, 20, 20), - (15466, 4, 139, 12828, 0), - (15469, 1, 264, 240, 1120), - (15472, 1, 264, 1260, 521), - (15478, 1, 264, 120, 578), - (15485, 1, 339, 10, 38417), - (15485, 2, 142, 96, 0), - (15485, 3, 311, 0, 0), - (15485, 4, 134, 105, 0), - (15485, 5, 348, 10, 0), - (15485, 6, 137, 0, 0), - (15485, 7, 339, 10, 38417), - (15485, 8, 142, 96, 0), - (15485, 9, 311, 0, 0), - (15485, 10, 134, 105, 0), - (15485, 11, 348, 10, 0), - (15485, 12, 137, 100, 0), - (15485, 13, 339, 10, 38417), - (15485, 14, 142, 96, 0), - (15485, 15, 311, 0, 0), - (15485, 16, 134, 105, 0), - (15485, 17, 348, 10, 0), - (15485, 18, 137, 79, 0), - (15485, 19, 339, 10, 38417), - (15485, 20, 142, 96, 0), - (15485, 21, 311, 0, 0), - (15485, 22, 134, 105, 0), - (15485, 23, 348, 10, 0), - (15485, 24, 137, 147, 0), - (15493, 1, 127, 10, 0), - (15493, 2, 137, 31, 0), - (15502, 1, 310, 240000, 0), - (15502, 2, 139, 4673, 0), - (15502, 3, 411, 512, 0), - (15509, 1, 310, 3000, 0), - (15509, 2, 385, 12315, 0), - (15509, 3, 385, 12415, 0), - (15509, 4, 385, 12515, 0), - (15509, 5, 385, 12615, 0), - (15509, 10, 411, 512, 0), - (15512, 1, 288, 50, 8), - (15516, 1, 126, 20, 0), - (15516, 2, 139, 3066, 0), - (15516, 3, 411, 256, 0), - (15517, 1, 127, 16, 0), - (15517, 2, 139, 3066, 0), - (15517, 3, 411, 256, 0), - (15526, 1, 264, 120, 3702), - (15529, 1, 247, 60, 53), - (15540, 1, 185, 5, 1), - (15543, 1, 185, 5, 0), - (15546, 1, 185, 5, 36), - (15549, 1, 264, 15, 244), - (15552, 1, 264, 840, 3710), - (15555, 1, 339, 5, 38103), - (15555, 2, 385, 3208, 0), - (15555, 3, 385, 3308, 0), - (15555, 4, 385, 3408, 0), - (15555, 5, 385, 3508, 0), - (15564, 1, 220, 68, 51), - (15571, 1, 264, 180, 351), - (15579, 1, 287, 2, 0), - (15579, 2, 139, 16106, 0), - (15585, 1, 274, 44, 0), - (15591, 1, 127, 10, 0), - (15591, 2, 139, 16839, 0), - (15598, 1, 264, 180, 759), - (15598, 2, 264, 180, 1150), - (15598, 3, 264, 180, 1151), - (15598, 4, 264, 180, 1152), - (15602, 1, 124, 1, 0), - (15602, 2, 138, 0, 0), - (15602, 3, 141, 1, 0), - (15602, 4, 348, 10, 0), - (15606, 1, 244, -25, 0), - (15609, 1, 383, 10, 38134), - (15609, 2, 141, 1, 0), - (15609, 3, 348, 10, 0), - (15609, 4, 142, 85, 0), - (15609, 5, 143, 3000, 0), - (15622, 1, 127, 5, 5), - (15622, 2, 137, 0, 0), - (15622, 3, 138, 0, 0), - (15622, 4, 141, 1, 0), - (15625, 1, 330, 10, 8), - (15632, 1, 264, 1728, 789), - (15634, 1, 310, 1500, 0), - (15634, 2, 385, 12110, 0), - (15634, 3, 385, 12210, 0), - (15634, 4, 385, 12310, 0), - (15634, 5, 385, 12410, 0), - (15634, 6, 385, 12510, 0), - (15635, 1, 310, 3000, 0), - (15635, 2, 385, 12110, 0), - (15635, 3, 385, 12210, 0), - (15635, 4, 385, 12310, 0), - (15635, 5, 385, 12410, 0), - (15635, 6, 385, 12510, 0), - (15648, 1, 185, 3, 74), - (15694, 1, 190, 550, 0), - (15714, 1, 320, 12, 0), - (15719, 1, 320, 12, 0), - (15746, 1, 421, 20, 0), - (15746, 2, 139, 16097, 0), - (15746, 3, 139, 23612, 0), - (15746, 4, 139, 32196, 0), - (15746, 5, 139, 32565, 0), - (15746, 6, 423, 6, 0), - (15746, 7, 422, 5, 0), - (15746, 8, 411, 2, 0), - (15768, 1, 125, 1, 2), - (15768, 2, 136, 46, 0), - (15772, 1, 128, 80, 80), - (15772, 2, 138, 1, 0), - (15772, 3, 140, 1, 0), - (15772, 4, 311, 0, 0), - (15772, 5, 411, 66434, 0), - (15772, 6, 137, -40, 0), - (15773, 1, 128, 80, 80), - (15773, 2, 138, 1, 0), - (15773, 3, 140, 1, 0), - (15773, 4, 311, 0, 0), - (15773, 5, 411, 256, 0), - (15773, 6, 137, -40, 0), - (15773, 7, 391, 1, 0), - (15778, 1, 303, 27500, 32500), - (15778, 2, 139, 2766, 0), - (15833, 1, 264, 60, 2045), - (15836, 1, 264, 60, 463), - (15891, 1, 264, 20, 988), - (15893, 1, 264, 20, 987), - (15895, 1, 264, 20, 986), - (15908, 1, 220, 125, 0), - (15908, 2, 220, 200, 2), - (15909, 1, 220, 155, 0), - (15909, 2, 220, 290, 2), - (15910, 1, 220, 185, 0), - (15910, 2, 220, 385, 2), - (15954, 1, 292, 49, 0), - (15961, 1, 129, 20, 0), - (15961, 2, 385, 12768, 0), - (15961, 3, 411, 256, 0), - (16062, 1, 339, 20, 40941), - (16062, 2, 138, 0, 0), - (16062, 3, 137, 31, 0), - (16062, 4, 311, 0, 0), - (16084, 1, 158, 1, 0), - (16087, 1, 264, 432, 53), - (16094, 1, 264, 3024, 43), - (16104, 1, 10, 0, 0), - (16109, 1, 69, 3000, 0), - (16114, 1, 114, 2, 0), - (16117, 1, 171, 2, 0), - (16120, 1, 226, 1, 0), - (16121, 1, 310, 840000, 0), - (16121, 2, 139, 4670, 0), - (16124, 1, 264, 2, 3711), - (16128, 1, 127, 8, 0), - (16128, 2, 139, 13143, 0), - (16131, 1, 130, 10, 0), - (16131, 2, 385, 18000, 0), - (16137, 1, 287, 1, 0), - (16137, 2, 385, 21821, 0), - (16140, 1, 287, 1, 0), - (16140, 2, 385, 30666, 0), - (16146, 1, 339, 2, 41107), - (16146, 2, 142, 95, 0), - (16146, 3, 138, 1, 0), - (16146, 4, 137, 0, 0), - (16146, 5, 348, 10, 0), - (16146, 6, 141, 1, 0), - (16149, 1, 129, 20, 0), - (16149, 2, 385, 4357, 0), - (16149, 3, 385, 4457, 0), - (16149, 4, 385, 4557, 0), - (16149, 5, 411, 4, 0), - (16152, 1, 339, 3, 41108), - (16152, 2, 142, 90, 0), - (16152, 3, 138, 0, 0), - (16152, 4, 137, 0, 0), - (16152, 5, 348, 10, 0), - (16152, 6, 141, 1, 0), - (16156, 1, 392, 1000, 0), - (16156, 2, 385, 32341, 0), - (16159, 1, 287, 1, 0), - (16159, 2, 385, 32307, 0), - (16164, 1, 294, 0, 195), - (16170, 1, 360, 70, 41119), - (16173, 1, 320, 12, 0), - (16176, 1, 264, 2, 337), - (16179, 1, 288, 8, 7), - (16180, 1, 264, 5, 584), - (16186, 1, 288, 100, 30), - (16189, 1, 339, 12, 41127), - (16189, 2, 138, 0, 0), - (16189, 3, 142, 70, 0), - (16189, 4, 411, 32, 0), - (16189, 5, 348, 1, 0), - (16189, 6, 141, 1, 0), - (16192, 1, 339, 12, 41130), - (16192, 2, 138, 0, 0), - (16192, 3, 142, 70, 0), - (16192, 4, 403, 4, 0), - (16192, 5, 348, 1, 0), - (16192, 6, 404, 2, 0), - (16192, 7, 141, 1, 0), - (16208, 1, 247, 5, 27), - (16211, 1, 287, 1, 0), - (16211, 2, 139, 23581, 0), - (16211, 3, 139, 32359, 0), - (16218, 1, 264, 10, 403), - (16221, 1, 287, 1, 0), - (16221, 2, 385, 23586, 0), - (16225, 1, 264, 1, 219), - (16230, 1, 310, 1000, 0), - (16230, 2, 385, 2431, 0), - (16230, 3, 385, 2531, 0), - (16230, 4, 385, 2545, 0), - (16230, 5, 385, 2631, 0), - (16235, 1, 126, 35, 0), - (16235, 2, 134, 100, 0), - (16235, 3, 135, 3, 0), - (16238, 1, 287, 2, 0), - (16238, 2, 385, 23693, 0), - (16238, 3, 460, 1, 0), - (16249, 1, 275, 100, 0), - (16257, 1, 429, 37114, 2), - (16257, 2, 428, 52, 0), - (16260, 1, 427, 41160, 3), - (16260, 2, 428, 23, 0), - (16266, 1, 224, 50, 8), - (16266, 2, 173, 4, 0), - (16267, 1, 250, 52, 0), - (16272, 1, 175, 2, 0), - (16276, 1, 247, 10, 36), - (16287, 1, 264, 20, 669), - (16297, 1, 264, 600, 553), - (16300, 1, 264, 60, 668), - (16303, 1, 264, 240, 3506), - (16306, 1, 264, 1260, 777), - (16317, 1, 220, 100, -1), - (16327, 1, 310, 720000, 0), - (16327, 2, 139, 5040, 0), - (16330, 1, 330, 105, 74), - (16336, 1, 264, 30, 1257), - (16339, 1, 264, 10, 773), - (16342, 1, 127, 10, 0), - (16342, 2, 385, 38115, 0), - (16361, 1, 399, 5, 0), - (16361, 2, 141, 1, 0), - (16361, 3, 138, 0, 0), - (16361, 4, 134, 254, 0), - (16361, 5, 348, 10, 0), - (16361, 6, 137, 0, 0), - (16361, 7, 311, 0, 0), - (16361, 8, 137, -152, 0), - (16361, 9, 137, -39, 0), - (16366, 1, 286, 200, 0), - (16366, 2, 138, 0, 0), - (16366, 3, 143, 1, 0), - (16366, 4, 348, 10, 0), - (16371, 1, 129, 20, 0), - (16371, 2, 385, 2754, 0), - (16380, 1, 264, 30, 2061), - (16386, 1, 264, 10, 2064), - (16392, 1, 264, 90, 2202), - (16396, 1, 127, 5, 5), - (16396, 2, 137, 0, 0), - (16396, 3, 138, 0, 0), - (16396, 4, 141, 1, 0), - (16402, 1, 131, 60, 60), - (16402, 2, 348, 10, 0), - (16402, 3, 137, -32, 0), - (16414, 1, 317, 16, 0), - (16419, 1, 426, 6, 0), - (16420, 1, 426, 7, 0), - (16421, 1, 426, 8, 0), - (16440, 1, 247, 65, 76), - (16475, 1, 218, 4, 0), - (16489, 1, 294, 29, 102), - (16536, 1, 405, 3, 0), - (16604, 1, 264, 1440, 180), - (16644, 1, 264, 60, 747), - (16666, 1, 264, 60, 742), - (16730, 1, 347, 31, 0), - (16745, 1, 264, 60, 706), - (16887, 1, 280, 75, 0), - (16890, 1, 218, 21, 0), - (17004, 1, 225, 35, 0), - (17206, 1, 264, 12, 601), - (17209, 1, 264, 180, 111), - (17212, 1, 264, 60, 10367), - (17215, 1, 378, 2, 22), - (17215, 2, 378, 2, 31), - (17215, 3, 378, 2, 3), - (17215, 4, 378, 2, 20), - (17218, 1, 127, 10, 0), - (17218, 2, 139, 27560, 0), - (17229, 1, 220, 900, 3), - (17229, 2, 220, 900, 2), - (17229, 3, 220, 900, 77), - (17235, 1, 127, 15, 0), - (17235, 2, 385, 12609, 0), - (17239, 1, 310, 2400000, 0), - (17239, 2, 139, 4500, 0), - (17239, 3, 411, 8, 0), - (17242, 1, 378, 1, 22), - (17242, 2, 378, 1, 31), - (17242, 3, 378, 1, 3), - (17242, 4, 378, 1, 20), - (17245, 1, 378, 1, 22), - (17245, 2, 378, 1, 31), - (17245, 3, 378, 1, 3), - (17245, 4, 378, 1, 20), - (17249, 1, 264, 120, 651), - (17252, 1, 310, 3000, 0), - (17252, 2, 385, 13438, 0), - (17252, 3, 385, 13538, 0), - (17252, 4, 385, 13638, 0), - (17258, 1, 399, 2, 0), - (17258, 2, 137, 457, 0), - (17258, 3, 399, 2, 0), - (17258, 4, 134, 253, 0), - (17258, 5, 142, 100, 0), - (17258, 6, 138, 0, 0), - (17258, 7, 136, 13, 0), - (17258, 8, 136, 20, 0), - (17258, 9, 137, -39, 0), - (17267, 1, 127, 10, 0), - (17267, 2, 385, 13507, 0), - (17267, 3, 385, 13107, 0), - (17267, 4, 385, 13207, 0), - (17267, 5, 385, 13307, 0), - (17267, 6, 385, 13407, 0), - (17267, 7, 385, 13607, 0), - (17281, 1, 287, 1, 0), - (17281, 2, 385, 16646, 0), - (17288, 1, 264, 1440, 41), - (17289, 1, 264, 180, 1062), - (17295, 1, 229, 62, 0), - (17307, 1, 127, 8, 0), - (17307, 2, 139, 38058, 0), - (17310, 1, 310, 14000, 0), - (17310, 2, 139, 8007, 0), - (17310, 3, 310, 14000, 0), - (17310, 4, 385, 4140, 0), - (17310, 5, 385, 4240, 0), - (17310, 6, 385, 4340, 0), - (17310, 7, 385, 4440, 0), - (17310, 8, 385, 4540, 0), - (17310, 9, 385, 4640, 0), - (17317, 1, 264, 60, 1270), - (17334, 1, 287, 12, 0), - (17334, 2, 385, 16188, 0), - (17336, 1, 287, 1, 0), - (17336, 2, 385, 32348, 0), - (17339, 1, 264, 12, 760), - (17350, 1, 264, 110, 170), - (17357, 1, 287, 1, 0), - (17357, 2, 137, 100, 0), - (17357, 3, 138, 1, 0), - (17361, 1, 264, 60, 405), - (17361, 2, 264, 60, 426), - (17365, 1, 287, 6, 0), - (17365, 2, 385, 5240, 0), - (17365, 3, 385, 5340, 0), - (17365, 4, 385, 5440, 0), - (17365, 5, 385, 5540, 0), - (17365, 6, 385, 5640, 0), - (17370, 1, 287, 1, 0), - (17370, 2, 138, 0, 0), - (17370, 3, 137, 0, 0), - (17370, 4, 137, 100, 0), - (17370, 5, 140, 1, 0), - (17370, 6, 348, 10, 0), - (17375, 1, 127, 10, 0), - (17375, 2, 385, 38078, 0), - (17391, 1, 264, 1560, 98), - (17406, 1, 310, 480000, 0), - (17406, 2, 139, 4502, 0), - (17406, 3, 139, 4509, 0), - (17409, 1, 214, 205, 0), - (17409, 2, 259, 4, 0), - (17409, 3, 172, 4, 0), - (17414, 1, 264, 120, 673), - (17418, 1, 247, 10, 74), - (17428, 1, 288, 5, 51), - (17436, 1, 264, 60, 372), - (17439, 1, 287, 1, 0), - (17439, 2, 385, 6040, 0), - (17441, 1, 279, 37, 0), - (17445, 1, 310, 60000, 0), - (17445, 2, 385, 3312, 0), - (17448, 1, 287, 1, 0), - (17448, 2, 385, 14005, 0), - (17448, 3, 385, 3519, 0), - (17476, 1, 264, 240, 462), - (17492, 1, 264, 120, 840), - (17495, 1, 264, 20, 9702), - (17515, 1, 127, 25, 0), - (17515, 2, 385, 7125, 0), - (17517, 1, 127, 17, 0), - (17517, 2, 385, 23683, 0), - (17517, 3, 460, 1, 0), - (17522, 1, 264, 30, 764), - (17533, 1, 287, 1, 0), - (17533, 2, 139, 32399, 0), - (17533, 3, 460, 1, 0), - (17547, 1, 287, 1, 0), - (17547, 2, 137, 0, 0), - (17547, 3, 137, 100, 0), - (17547, 4, 140, 2, 0), - (17547, 5, 138, 0, 0), - (17547, 6, 348, 10, 0), - (17549, 1, 264, 10, 8700), - (17553, 1, 339, 8, 41768), - (17553, 2, 138, 0, 0), - (17553, 3, 141, 1, 0), - (17553, 4, 134, 253, 0), - (17553, 5, 142, 85, 0), - (17553, 6, 143, 1, 0), - (17553, 7, 311, 0, 0), - (17553, 8, 348, 1, 0), - (17553, 9, 137, 0, 0), - (17554, 1, 227, 2, 74), - (17555, 1, 286, 126, 2), - (17555, 2, 385, 9606, 0), - (17555, 3, 303, 252, 0), - (17555, 4, 385, 9606, 0), - (17558, 1, 413, 2, 2), - (17558, 2, 385, 9603, 0), - (17558, 3, 411, 2048, 0), - (17561, 1, 413, 2, 2), - (17561, 2, 385, 9609, 0), - (17561, 3, 411, 2048, 0), - (17564, 1, 413, 2, 2), - (17564, 2, 385, 9619, 0), - (17564, 3, 411, 2048, 0), - (17567, 1, 413, 2, 2), - (17567, 2, 385, 9613, 0), - (17567, 3, 411, 2048, 0), - (17570, 1, 413, 2, 2), - (17570, 2, 385, 9604, 0), - (17570, 3, 411, 2048, 0), - (17573, 1, 413, 2, 2), - (17573, 2, 385, 9651, 0), - (17573, 3, 411, 2048, 0), - (17576, 1, 413, 2, 2), - (17576, 2, 385, 16652, 0), - (17576, 3, 411, 4096, 0), - (17579, 1, 413, 2, 2), - (17579, 2, 385, 16629, 0), - (17579, 3, 411, 4096, 0), - (17582, 1, 413, 2, 2), - (17582, 2, 385, 16650, 0), - (17582, 3, 411, 4096, 0), - (17585, 1, 413, 2, 2), - (17585, 2, 385, 16608, 0), - (17585, 3, 411, 4096, 0), - (17588, 1, 413, 2, 2), - (17588, 2, 385, 16615, 0), - (17588, 3, 411, 4096, 0), - (17591, 1, 413, 2, 2), - (17591, 2, 385, 16618, 0), - (17591, 3, 411, 4096, 0), - (17594, 1, 413, 2, 2), - (17594, 2, 385, 16625, 0), - (17594, 3, 411, 4096, 0), - (17597, 1, 286, 345, 0), - (17597, 2, 385, 7604, 0), - (17600, 1, 413, 2, 2), - (17600, 2, 385, 7608, 0), - (17600, 3, 411, 8192, 0), - (17603, 1, 413, 2, 2), - (17603, 2, 385, 7612, 0), - (17603, 3, 411, 8192, 0), - (17606, 1, 392, 419, 0), - (17606, 2, 385, 7613, 0), - (17606, 3, 396, 838, 0), - (17606, 4, 385, 7613, 0), - (17609, 1, 413, 2, 2), - (17609, 2, 385, 7636, 0), - (17609, 3, 411, 8192, 0), - (17612, 1, 413, 2, 2), - (17612, 2, 385, 7618, 0), - (17612, 3, 411, 8192, 0), - (17615, 1, 286, 539, 0), - (17615, 2, 385, 7638, 0), - (17618, 1, 413, 2, 2), - (17618, 2, 385, 6664, 0), - (17618, 3, 411, 16384, 0), - (17621, 1, 413, 2, 2), - (17621, 2, 385, 6648, 0), - (17621, 3, 411, 16384, 0), - (17624, 1, 413, 2, 2), - (17624, 2, 385, 6649, 0), - (17624, 3, 411, 16384, 0), - (17627, 1, 413, 2, 2), - (17627, 2, 385, 6611, 0), - (17627, 3, 411, 16384, 0), - (17630, 1, 413, 2, 2), - (17630, 2, 385, 6652, 0), - (17630, 3, 411, 16384, 0), - (17633, 1, 413, 2, 2), - (17633, 2, 385, 6655, 0), - (17633, 3, 411, 16384, 0), - (17639, 1, 323, 37182, 100), - (18972, 1, 214, 210, 0), - (18972, 2, 259, 5, 0), - (18972, 3, 172, 5, 0), - (30050, 1, 69, 25, 0), - (30050, 2, 97, 25, 0), - (30050, 3, 190, 25, 0), - (30050, 4, 328, 25, 0), - (30100, 1, 1, 10, 0), - (30100, 2, 2, 10, 0), - (30100, 3, 341, 10, 0), - (30150, 1, 262, 5, 0), - (30150, 2, 262, 5, 1), - (30150, 3, 262, 5, 2), - (30150, 4, 262, 5, 3), - (30150, 5, 262, 5, 4), - (30150, 6, 262, 5, 5), - (30150, 7, 262, 5, 6), - (30150, 8, 159, 5, 0), - (30150, 9, 0, 2, 0), - (30150, 10, 15, 2, 0), - (30150, 11, 189, 2, 0), - (30150, 12, 317, 2, 0), - (30150, 13, 318, 2, 0), - (30175, 1, 271, 1, 0), - (30180, 1, 264, 1, 8202), - (30185, 1, 264, 1, 1011), - (30195, 1, 432, 1, 0), - (49999, 1, 10, 0, 0); +-- +-- Dumping data for table `aa_rank_effects` +-- + +LOCK TABLES `aa_rank_effects` WRITE; +/*!40000 ALTER TABLE `aa_rank_effects` DISABLE KEYS */; +INSERT INTO `aa_rank_effects` VALUES (2,1,4,2,0),(3,1,4,4,0),(4,1,4,6,0),(5,1,4,8,0),(6,1,4,10,0),(7,1,7,2,0),(8,1,7,4,0),(9,1,7,6,0),(10,1,7,8,0),(11,1,7,10,0),(12,1,6,2,0),(13,1,6,4,0),(14,1,6,6,0),(15,1,6,8,0),(16,1,6,10,0),(17,1,5,2,0),(18,1,5,4,0),(19,1,5,6,0),(20,1,5,8,0),(21,1,5,10,0),(22,1,8,2,0),(23,1,8,4,0),(24,1,8,6,0),(25,1,8,8,0),(26,1,8,10,0),(27,1,9,2,0),(28,1,9,4,0),(29,1,9,6,0),(30,1,9,8,0),(31,1,9,10,0),(32,1,10,2,0),(33,1,10,4,0),(34,1,10,6,0),(35,1,10,8,0),(36,1,10,10,0),(37,1,46,2,0),(38,1,46,4,0),(39,1,46,6,0),(40,1,46,8,0),(41,1,46,10,0),(42,1,47,2,0),(43,1,47,4,0),(44,1,47,6,0),(45,1,47,8,0),(46,1,47,10,0),(47,1,50,2,0),(48,1,50,4,0),(49,1,50,6,0),(50,1,50,8,0),(51,1,50,10,0),(52,1,48,2,0),(53,1,48,4,0),(54,1,48,6,0),(55,1,48,8,0),(56,1,48,10,0),(57,1,49,2,0),(58,1,49,4,0),(59,1,49,6,0),(60,1,49,8,0),(61,1,49,10,0),(62,1,271,8,0),(63,1,271,14,0),(64,1,271,21,0),(68,1,233,110,0),(69,1,233,125,0),(70,1,233,150,0),(71,1,246,110,0),(72,1,246,125,0),(73,1,246,150,0),(74,1,269,10,0),(75,1,269,20,0),(76,1,269,30,0),(77,1,125,2,2),(77,2,137,0,0),(77,3,141,1,0),(77,4,139,-6233,0),(77,5,139,-6265,0),(77,6,125,2,2),(77,7,137,147,0),(77,8,141,1,0),(78,1,125,5,5),(78,2,137,0,0),(78,3,141,1,0),(78,4,139,-6233,0),(78,5,139,-6265,0),(78,6,125,5,5),(78,7,137,147,0),(78,8,141,1,0),(79,1,125,10,10),(79,2,137,0,0),(79,3,141,1,0),(79,4,139,-6233,0),(79,5,139,-6265,0),(79,6,125,10,10),(79,7,137,147,0),(79,8,141,1,0),(80,1,274,3,0),(81,1,274,6,0),(82,1,274,10,0),(83,1,132,2,2),(84,1,132,5,5),(85,1,132,10,10),(86,1,128,5,5),(86,2,138,1,0),(86,3,140,1,0),(86,4,139,-2741,0),(86,5,139,-16843,0),(86,6,385,-16192,0),(86,7,385,-10547,0),(86,8,385,-13543,0),(87,1,128,15,15),(87,2,138,1,0),(87,3,140,1,0),(87,4,139,-2741,0),(87,5,139,-16843,0),(87,6,385,-16192,0),(87,7,385,-10547,0),(87,8,385,-13543,0),(88,1,128,30,30),(88,2,138,1,0),(88,3,140,1,0),(88,4,139,-2741,0),(88,5,139,-16843,0),(88,6,385,-16192,0),(88,7,385,-10547,0),(88,8,385,-13543,0),(92,1,294,2,100),(93,1,294,4,100),(94,1,294,7,100),(98,1,114,-5,0),(99,1,114,-10,0),(100,1,114,-20,0),(101,1,265,20,0),(102,1,265,40,0),(103,1,265,52,0),(104,1,127,10,10),(104,2,138,1,0),(104,3,140,1,0),(104,4,143,3000,0),(105,1,127,25,25),(105,2,138,1,0),(105,3,140,1,0),(105,4,143,3000,0),(106,1,127,50,50),(106,2,138,1,0),(106,3,140,1,0),(106,4,143,3000,0),(107,1,214,200,0),(108,1,214,500,0),(109,1,214,1000,0),(110,1,0,1,0),(111,1,0,2,0),(112,1,0,3,0),(113,1,169,15,-1),(114,1,169,40,-1),(115,1,169,75,-1),(116,1,181,5,0),(117,1,181,10,0),(118,1,181,25,0),(119,1,278,500,16000),(119,2,440,50,100),(120,1,278,510,17102),(120,2,440,52,100),(121,1,278,520,19635),(121,2,440,54,100),(122,1,259,2,0),(123,1,259,5,0),(124,1,259,10,0),(125,1,172,2,0),(126,1,172,5,0),(127,1,172,10,0),(137,1,127,10,10),(137,2,137,88,0),(138,1,127,25,25),(138,2,137,88,0),(139,1,127,50,50),(139,2,137,88,0),(141,1,127,2,2),(141,2,137,0,0),(141,3,138,0,0),(141,4,141,1,0),(141,5,143,3000,0),(141,6,127,2,2),(141,7,385,16555,0),(141,8,385,16655,0),(142,1,127,5,5),(142,2,137,0,0),(142,3,138,0,0),(142,4,141,1,0),(142,5,143,3000,0),(142,6,127,5,5),(142,7,385,16555,0),(142,8,385,16655,0),(143,1,127,10,10),(143,2,137,0,0),(143,3,138,0,0),(143,4,141,1,0),(143,5,143,3000,0),(143,6,127,10,10),(143,7,385,16555,0),(143,8,385,16655,0),(144,1,244,50,0),(147,1,127,10,10),(147,2,138,1,0),(147,3,140,1,0),(147,4,143,3000,0),(148,1,127,25,25),(148,2,138,1,0),(148,3,140,1,0),(148,4,143,3000,0),(149,1,127,50,50),(149,2,138,1,0),(149,3,140,1,0),(149,4,143,3000,0),(150,1,268,10,59),(151,1,268,25,59),(152,1,268,50,59),(158,1,238,1,0),(159,1,268,10,68),(160,1,268,25,68),(161,1,268,50,68),(182,1,131,100,0),(182,2,137,33,0),(190,1,219,225,680),(191,1,219,235,1190),(192,1,219,240,1700),(195,1,181,100,0),(196,1,226,1,0),(198,1,276,32,0),(199,1,301,30,0),(200,1,301,60,0),(201,1,301,100,0),(205,1,251,100,0),(210,1,302,50,50),(210,2,385,99,0),(211,1,302,100,100),(211,2,385,99,0),(212,1,302,200,200),(212,2,385,99,0),(213,1,260,2,23),(213,2,260,2,24),(213,3,260,2,25),(213,4,260,2,26),(214,1,260,4,23),(214,2,260,4,24),(214,3,260,4,25),(214,4,260,4,26),(215,1,260,6,23),(215,2,260,6,24),(215,3,260,6,25),(215,4,260,6,26),(225,1,272,1,0),(226,1,272,3,0),(227,1,272,5,0),(230,1,275,10,0),(231,1,275,20,0),(232,1,275,30,0),(237,1,227,1,25),(238,1,227,3,25),(239,1,227,5,25),(240,1,224,20,26),(240,2,173,1,0),(241,1,224,35,26),(241,2,173,2,0),(242,1,224,50,26),(242,2,173,3,0),(244,1,268,10,56),(244,2,234,7500,0),(245,1,268,25,56),(245,2,234,5000,0),(246,1,268,50,56),(246,2,234,2500,0),(247,1,224,15,0),(248,1,224,30,0),(249,1,224,50,0),(255,1,279,7,0),(256,1,279,11,0),(257,1,279,15,0),(263,1,282,10,0),(264,1,282,25,0),(265,1,282,50,0),(266,1,128,50,50),(266,2,138,1,0),(266,3,140,1,0),(266,4,139,-2741,0),(266,5,139,-16843,0),(266,6,385,-16192,0),(266,7,385,-10547,0),(266,8,385,-13543,0),(267,1,294,2,100),(268,1,294,4,100),(269,1,294,6,100),(273,1,288,1000,21),(275,1,260,2,50),(276,1,260,4,50),(277,1,260,6,50),(278,1,0,1,0),(278,2,15,1,0),(279,1,214,200,0),(279,2,259,2,0),(279,3,172,2,0),(280,1,227,1,62),(280,2,227,1,17),(281,1,227,3,62),(281,2,227,3,17),(282,1,227,5,62),(282,2,227,5,17),(283,1,228,10,0),(284,1,228,20,0),(285,1,228,30,0),(286,1,10,0,0),(287,1,253,1,0),(288,1,257,1,0),(288,2,267,1,31),(288,3,267,1,32),(288,4,267,1,33),(288,5,267,1,15),(288,6,267,1,16),(288,7,267,1,17),(288,8,267,1,18),(288,9,267,1,19),(288,10,267,1,20),(292,1,4,12,0),(293,1,4,14,0),(294,1,4,16,0),(295,1,4,18,0),(296,1,4,20,0),(297,1,4,22,0),(298,1,4,24,0),(299,1,4,26,0),(300,1,4,28,0),(301,1,4,30,0),(302,1,7,12,0),(303,1,7,14,0),(304,1,7,16,0),(305,1,7,18,0),(306,1,7,20,0),(307,1,7,22,0),(308,1,7,24,0),(309,1,7,26,0),(310,1,7,28,0),(311,1,7,30,0),(312,1,6,12,0),(313,1,6,14,0),(314,1,6,16,0),(315,1,6,18,0),(316,1,6,20,0),(317,1,6,22,0),(318,1,6,24,0),(319,1,6,26,0),(320,1,6,28,0),(321,1,6,30,0),(322,1,5,12,0),(323,1,5,14,0),(324,1,5,16,0),(325,1,5,18,0),(326,1,5,20,0),(327,1,5,22,0),(328,1,5,24,0),(329,1,5,26,0),(330,1,5,28,0),(331,1,5,30,0),(332,1,8,12,0),(333,1,8,14,0),(334,1,8,16,0),(335,1,8,18,0),(336,1,8,20,0),(337,1,8,22,0),(338,1,8,24,0),(339,1,8,26,0),(340,1,8,28,0),(341,1,8,30,0),(342,1,9,12,0),(343,1,9,14,0),(344,1,9,16,0),(345,1,9,18,0),(346,1,9,20,0),(347,1,9,22,0),(348,1,9,24,0),(349,1,9,26,0),(350,1,9,28,0),(351,1,9,30,0),(352,1,10,12,0),(353,1,10,14,0),(354,1,10,16,0),(355,1,10,18,0),(356,1,10,20,0),(357,1,10,22,0),(358,1,10,24,0),(359,1,10,26,0),(360,1,10,28,0),(361,1,10,30,0),(362,1,46,12,0),(363,1,46,14,0),(364,1,46,16,0),(365,1,46,18,0),(366,1,46,20,0),(367,1,46,22,0),(368,1,46,24,0),(369,1,46,26,0),(370,1,46,28,0),(371,1,46,30,0),(372,1,47,12,0),(373,1,47,14,0),(374,1,47,16,0),(375,1,47,18,0),(376,1,47,20,0),(377,1,47,22,0),(378,1,47,24,0),(379,1,47,26,0),(380,1,47,28,0),(381,1,47,30,0),(382,1,50,12,0),(383,1,50,14,0),(384,1,50,16,0),(385,1,50,18,0),(386,1,50,20,0),(387,1,50,22,0),(388,1,50,24,0),(389,1,50,26,0),(390,1,50,28,0),(391,1,50,30,0),(392,1,48,12,0),(393,1,48,14,0),(394,1,48,16,0),(395,1,48,18,0),(396,1,48,20,0),(397,1,48,22,0),(398,1,48,24,0),(399,1,48,26,0),(400,1,48,28,0),(401,1,48,30,0),(402,1,49,12,0),(403,1,49,14,0),(404,1,49,16,0),(405,1,49,18,0),(406,1,49,20,0),(407,1,49,22,0),(408,1,49,24,0),(409,1,49,26,0),(410,1,49,28,0),(411,1,49,30,0),(412,1,263,1,0),(413,1,263,2,0),(414,1,263,3,0),(415,1,263,4,0),(416,1,263,5,0),(417,1,263,6,0),(418,1,262,5,0),(418,2,262,5,1),(418,3,262,5,2),(418,4,262,5,3),(418,5,262,5,4),(418,6,262,5,5),(418,7,262,5,6),(419,1,262,10,0),(419,2,262,10,1),(419,3,262,10,2),(419,4,262,10,3),(419,5,262,10,4),(419,6,262,10,5),(419,7,262,10,6),(420,1,262,15,0),(420,2,262,15,1),(420,3,262,15,2),(420,4,262,15,3),(420,5,262,15,4),(420,6,262,15,5),(420,7,262,15,6),(421,1,262,20,0),(421,2,262,20,1),(421,3,262,20,2),(421,4,262,20,3),(421,5,262,20,4),(421,6,262,20,5),(421,7,262,20,6),(422,1,262,25,0),(422,2,262,25,1),(422,3,262,25,2),(422,4,262,25,3),(422,5,262,25,4),(422,6,262,25,5),(422,7,262,25,6),(423,1,214,150,0),(424,1,214,300,0),(425,1,214,450,0),(426,1,262,10,5),(426,2,262,10,4),(427,1,262,20,5),(427,2,262,20,4),(428,1,262,30,5),(428,2,262,30,4),(429,1,262,40,5),(429,2,262,40,4),(430,1,262,50,5),(430,2,262,50,4),(434,1,125,13,13),(434,2,137,0,0),(434,3,141,1,0),(434,4,139,-6233,0),(434,5,139,-6265,0),(434,6,125,13,13),(434,7,137,147,0),(434,8,141,1,0),(435,1,125,16,16),(435,2,137,0,0),(435,3,141,1,0),(435,4,139,-6233,0),(435,5,139,-6265,0),(435,6,125,16,16),(435,7,137,147,0),(435,8,141,1,0),(436,1,125,19,19),(436,2,137,0,0),(436,3,141,1,0),(436,4,139,-6233,0),(436,5,139,-6265,0),(436,6,125,19,19),(436,7,137,147,0),(436,8,141,1,0),(437,1,274,12,0),(438,1,274,14,0),(439,1,274,16,0),(440,1,278,530,21210),(440,2,440,56,100),(441,1,278,540,23160),(441,2,440,58,100),(442,1,278,550,25230),(442,2,440,60,100),(443,1,169,100,-1),(444,1,169,125,-1),(445,1,169,150,-1),(446,1,265,54,0),(447,1,265,56,0),(448,1,265,58,0),(449,1,172,13,0),(450,1,172,16,0),(451,1,172,19,0),(452,1,172,22,0),(453,1,172,25,0),(454,1,259,13,0),(455,1,259,16,0),(456,1,259,19,0),(457,1,259,22,0),(458,1,259,25,0),(462,1,264,60,39),(462,2,264,864,1061),(463,1,264,120,39),(463,2,264,1728,1061),(464,1,264,180,39),(464,2,264,2592,1061),(468,1,264,180,41),(469,1,264,360,41),(470,1,264,540,41),(471,1,264,864,57),(471,2,264,864,616),(472,1,264,1728,57),(472,2,264,1728,616),(473,1,264,2592,57),(473,2,264,2592,616),(474,1,264,240,50),(475,1,264,480,50),(476,1,264,720,50),(477,1,264,432,43),(478,1,264,864,43),(479,1,264,1296,43),(480,1,264,432,117),(481,1,264,864,117),(482,1,264,1296,117),(483,1,264,540,58),(483,2,264,540,418),(484,1,264,1080,58),(484,2,264,1080,418),(485,1,264,1620,58),(485,2,264,1620,418),(489,1,264,90,110),(490,1,264,180,110),(491,1,264,270,110),(492,1,264,60,109),(493,1,264,120,109),(494,1,264,180,109),(495,1,264,180,98),(496,1,264,360,98),(497,1,264,540,98),(498,1,264,144,102),(499,1,264,288,102),(500,1,264,432,102),(501,1,264,432,107),(502,1,264,864,107),(503,1,264,1296,107),(504,1,224,110,0),(505,1,224,120,0),(506,1,224,130,0),(537,1,282,60,0),(538,1,282,75,0),(539,1,275,68,0),(540,1,275,76,0),(541,1,275,84,0),(542,1,279,17,0),(543,1,279,19,0),(544,1,279,21,0),(551,1,225,3,0),(552,1,225,6,0),(553,1,225,9,0),(554,1,225,12,0),(555,1,225,15,0),(556,1,225,3,0),(557,1,225,6,0),(558,1,225,9,0),(559,1,225,12,0),(560,1,225,15,0),(561,1,177,3,-1),(562,1,177,6,-1),(563,1,177,9,-1),(564,1,177,3,-1),(565,1,177,6,-1),(566,1,177,9,-1),(567,1,244,-12,0),(574,1,281,25,0),(575,1,281,50,0),(576,1,281,75,0),(577,1,277,20,0),(578,1,277,40,0),(579,1,277,60,0),(580,1,267,1,4),(580,2,267,1,5),(580,3,267,1,29),(581,1,267,1,2),(581,2,267,1,3),(581,3,267,1,4),(581,4,267,1,5),(581,5,267,1,29),(582,1,267,1,0),(582,2,267,1,1),(582,3,267,1,2),(582,4,267,1,3),(582,5,267,1,4),(582,6,267,1,4),(582,7,267,1,5),(582,8,267,1,6),(582,9,267,1,7),(582,10,267,1,8),(582,11,267,1,9),(582,12,267,1,10),(582,13,267,1,11),(582,14,267,1,12),(582,15,267,1,13),(582,16,267,1,14),(582,17,267,1,28),(582,18,267,1,29),(582,19,267,1,30),(583,1,264,7,73),(583,2,264,7,702),(583,3,264,7,3826),(583,4,264,7,7712),(584,1,264,14,73),(584,2,264,14,702),(584,3,264,14,3826),(584,4,264,14,7712),(585,1,264,21,73),(585,2,264,21,702),(585,3,264,21,3826),(585,4,264,21,7712),(586,1,255,12,0),(587,1,255,24,0),(588,1,255,36,0),(589,1,303,500,500),(589,2,139,2766,0),(590,1,303,1000,1000),(590,2,139,2766,0),(591,1,303,1500,1500),(591,2,139,2766,0),(593,1,264,720,6001),(593,2,264,720,3676),(594,1,264,1440,6001),(594,2,264,1440,3676),(595,1,264,2160,6001),(595,2,264,2160,3676),(596,1,264,720,6000),(596,2,264,720,87),(597,1,264,1440,6000),(597,2,264,1440,87),(598,1,264,2160,6000),(598,2,264,2160,87),(599,1,266,2,0),(600,1,266,5,0),(601,1,266,8,0),(602,1,266,2,0),(603,1,266,5,0),(604,1,266,8,0),(605,1,256,1,0),(606,1,285,20,0),(607,1,285,40,0),(608,1,285,60,0),(609,1,285,80,0),(610,1,285,100,0),(611,1,283,20,0),(612,1,283,40,0),(613,1,283,60,0),(614,1,283,80,0),(615,1,283,100,0),(622,1,227,1,29),(622,2,227,1,42),(623,1,227,2,29),(623,2,227,2,42),(624,1,227,3,29),(624,2,227,3,42),(625,1,294,3,100),(626,1,294,6,100),(627,1,294,9,100),(628,1,290,5,0),(629,1,290,10,0),(631,1,292,15,0),(632,1,292,30,0),(633,1,292,45,0),(634,1,274,3,0),(635,1,274,6,0),(636,1,274,10,0),(637,1,294,2,100),(638,1,294,4,100),(639,1,294,6,100),(640,1,294,7,100),(641,1,294,8,100),(642,1,294,9,100),(644,1,217,0,32000),(644,2,346,59,0),(649,1,243,15,0),(650,1,243,25,0),(651,1,243,35,0),(652,1,293,25,0),(653,1,293,50,0),(654,1,293,75,0),(655,1,127,10,10),(655,2,137,32,0),(655,3,127,10,10),(655,4,137,33,0),(655,5,127,10,10),(655,6,137,82,0),(655,7,127,2,2),(655,8,137,152,0),(655,9,143,3000,0),(656,1,127,25,25),(656,2,137,32,0),(656,3,127,25,25),(656,4,137,33,0),(656,5,127,25,25),(656,6,137,82,0),(656,7,127,5,5),(656,8,137,152,0),(656,9,143,3000,0),(657,1,127,50,50),(657,2,137,32,0),(657,3,127,50,50),(657,4,137,33,0),(657,5,127,50,50),(657,6,137,82,0),(657,7,127,10,10),(657,8,137,152,0),(657,9,143,3000,0),(658,1,15,1,0),(659,1,15,2,0),(660,1,15,3,0),(661,1,0,1,0),(662,1,0,2,0),(663,1,0,3,0),(665,1,270,10,0),(666,1,270,15,0),(667,1,270,25,0),(668,1,270,55,0),(669,1,270,60,0),(670,1,270,65,0),(671,1,241,95,0),(672,1,271,28,0),(673,1,271,35,0),(674,1,0,4,0),(675,1,0,5,0),(676,1,246,325,0),(677,1,246,350,0),(678,1,221,3,0),(679,1,221,6,0),(680,1,221,9,0),(681,1,221,12,0),(682,1,221,15,0),(683,1,189,1,0),(684,1,189,2,0),(685,1,189,3,0),(686,1,200,10,0),(687,1,200,20,0),(688,1,200,30,0),(689,1,200,40,0),(690,1,200,50,0),(691,1,248,100,0),(692,1,229,5,0),(693,1,229,10,0),(694,1,229,15,0),(695,1,247,10,53),(696,1,247,20,53),(697,1,247,30,53),(698,1,247,40,53),(699,1,247,50,53),(700,1,260,8,23),(700,2,260,8,24),(700,3,260,8,25),(700,4,260,8,26),(701,1,260,8,50),(724,1,218,1,0),(725,1,218,2,0),(726,1,218,3,0),(727,1,218,4,0),(728,1,218,5,0),(729,1,280,4,0),(730,1,280,8,0),(731,1,280,12,0),(732,1,280,16,0),(733,1,280,20,0),(734,1,237,1,0),(735,1,265,54,0),(736,1,265,56,0),(737,1,265,58,0),(738,1,114,-5,0),(739,1,114,-10,0),(740,1,114,-20,0),(754,1,264,18,153),(755,1,264,36,153),(756,1,264,54,153),(762,1,247,10,53),(763,1,247,20,53),(764,1,247,30,53),(765,1,247,40,53),(766,1,247,50,53),(767,1,273,3,0),(768,1,273,6,0),(769,1,273,9,0),(770,1,294,7,100),(771,1,294,8,100),(772,1,294,9,100),(776,1,242,10,0),(777,1,242,20,0),(778,1,242,30,0),(779,1,242,40,0),(780,1,242,50,0),(781,1,287,1,1),(781,2,137,31,0),(781,3,136,5,0),(782,1,264,432,35),(783,1,264,864,35),(784,1,264,1296,35),(790,1,218,1,0),(791,1,218,2,0),(792,1,218,3,0),(793,1,218,4,0),(794,1,218,5,0),(795,1,280,4,0),(796,1,280,8,0),(797,1,280,12,0),(798,1,280,16,0),(799,1,280,20,0),(800,1,215,2,0),(801,1,215,5,0),(802,1,215,10,0),(803,1,213,2,0),(804,1,213,5,0),(805,1,213,10,0),(806,1,249,1,0),(807,1,292,5,0),(808,1,292,10,0),(809,1,292,15,0),(810,1,239,10,0),(811,1,239,20,0),(812,1,239,30,0),(813,1,239,40,0),(814,1,239,50,0),(815,1,279,7,0),(816,1,279,11,0),(817,1,279,15,0),(818,1,279,17,0),(819,1,279,19,0),(820,1,220,10,26),(820,2,220,10,30),(820,3,220,10,38),(821,1,220,20,26),(821,2,220,20,30),(821,3,220,20,38),(822,1,220,30,26),(822,2,220,30,30),(822,3,220,30,38),(823,1,222,20,0),(824,1,222,40,0),(825,1,222,60,0),(826,1,222,80,0),(827,1,222,100,0),(834,1,218,1,0),(835,1,218,2,0),(836,1,218,3,0),(837,1,218,4,0),(838,1,218,5,0),(839,1,280,4,0),(840,1,280,8,0),(841,1,280,12,0),(842,1,280,16,0),(843,1,280,20,0),(844,1,274,12,0),(845,1,274,14,0),(846,1,258,5,0),(847,1,258,10,0),(848,1,258,15,0),(849,1,264,240,180),(850,1,264,480,180),(851,1,264,720,180),(852,1,231,1,0),(853,1,231,2,0),(854,1,231,3,0),(855,1,220,5,10),(856,1,220,10,10),(857,1,220,15,10),(858,1,220,20,10),(859,1,220,25,10),(864,1,216,10,0),(864,2,216,10,1),(864,3,216,10,2),(864,4,216,10,3),(864,5,216,10,10),(864,6,216,10,28),(864,7,216,10,30),(864,8,216,10,36),(864,9,216,10,77),(865,1,216,20,0),(865,2,216,20,1),(865,3,216,20,2),(865,4,216,20,3),(865,5,216,20,10),(865,6,216,20,28),(865,7,216,20,30),(865,8,216,20,36),(865,9,216,20,77),(866,1,216,30,0),(866,2,216,30,1),(866,3,216,30,2),(866,4,216,30,3),(866,5,216,30,10),(866,6,216,30,28),(866,7,216,30,30),(866,8,216,30,36),(866,9,216,30,77),(867,1,59,-3,0),(868,1,59,-6,0),(869,1,59,-9,0),(870,1,59,-12,0),(871,1,59,-15,0),(878,1,252,10,0),(879,1,252,20,0),(880,1,252,30,0),(881,1,245,10,0),(882,1,245,20,0),(883,1,245,30,0),(884,1,245,40,0),(885,1,245,50,0),(886,1,264,576,102),(887,1,264,720,102),(888,1,250,10,0),(889,1,250,20,0),(890,1,250,30,0),(891,1,250,40,0),(892,1,250,50,0),(893,1,303,2000,2000),(893,2,139,2766,0),(894,1,303,2500,2500),(894,2,139,2766,0),(895,1,59,-3,0),(896,1,59,-6,0),(897,1,59,-9,0),(898,1,59,-12,0),(899,1,59,-15,0),(907,1,69,100,0),(908,1,69,200,0),(909,1,69,300,0),(910,1,69,400,0),(911,1,69,500,0),(915,1,220,5,10),(915,2,220,5,30),(916,1,220,10,10),(916,2,220,10,30),(917,1,220,15,10),(917,2,220,15,30),(918,1,230,2,0),(919,1,230,4,0),(920,1,230,6,0),(924,1,294,10,100),(925,1,294,11,100),(934,1,169,15,-1),(935,1,169,30,-1),(936,1,169,60,-1),(937,1,169,15,0),(937,2,169,15,1),(937,3,169,15,2),(937,4,169,15,3),(937,5,169,15,7),(937,6,169,15,8),(937,7,169,15,10),(937,8,169,15,28),(937,9,169,15,30),(937,10,169,15,36),(937,11,169,15,51),(938,1,169,40,0),(938,2,169,40,1),(938,3,169,40,2),(938,4,169,40,3),(938,5,169,40,7),(938,6,169,40,8),(938,7,169,40,10),(938,8,169,40,28),(938,9,169,40,30),(938,10,169,40,36),(938,11,169,30,51),(939,1,169,75,0),(939,2,169,75,1),(939,3,169,75,2),(939,4,169,75,3),(939,5,169,75,7),(939,6,169,75,8),(939,7,169,75,10),(939,8,169,75,28),(939,9,169,75,30),(939,10,169,75,36),(939,11,169,60,51),(940,1,169,15,0),(940,2,169,15,1),(940,3,169,15,2),(940,4,169,15,3),(940,5,169,15,7),(940,6,169,15,8),(940,7,169,15,10),(940,8,169,15,28),(940,9,169,15,30),(940,10,169,15,36),(940,11,169,15,51),(940,12,169,15,77),(941,1,169,40,0),(941,2,169,40,1),(941,3,169,40,2),(941,4,169,40,3),(941,5,169,30,7),(941,6,169,40,8),(941,7,169,40,10),(941,8,169,40,28),(941,9,169,40,30),(941,10,169,40,36),(941,11,169,40,51),(941,12,169,40,77),(942,1,169,75,0),(942,2,169,75,1),(942,3,169,75,2),(942,4,169,75,3),(942,5,169,60,7),(942,6,169,75,8),(942,7,169,75,10),(942,8,169,75,28),(942,9,169,75,30),(942,10,169,75,36),(942,11,169,75,51),(942,12,169,75,77),(943,1,169,146,-1),(944,1,169,172,-1),(945,1,169,198,-1),(946,1,169,175,0),(946,2,169,175,1),(946,3,169,175,2),(946,4,169,175,3),(946,5,169,175,7),(946,6,169,175,8),(946,7,169,175,10),(946,8,169,175,28),(946,9,169,175,30),(946,10,169,175,36),(946,11,169,146,51),(947,1,169,200,0),(947,2,169,200,1),(947,3,169,200,2),(947,4,169,200,3),(947,5,169,200,7),(947,6,169,200,8),(947,7,169,200,10),(947,8,169,200,28),(947,9,169,200,30),(947,10,169,200,36),(947,11,169,172,51),(948,1,169,225,0),(948,2,169,225,1),(948,3,169,225,2),(948,4,169,225,3),(948,5,169,225,7),(948,6,169,225,8),(948,7,169,225,10),(948,8,169,225,28),(948,9,169,225,30),(948,10,169,225,36),(948,11,169,198,51),(949,1,169,175,0),(949,2,169,175,1),(949,3,169,175,2),(949,4,169,175,3),(949,5,169,161,7),(949,6,169,175,8),(949,7,169,175,10),(949,8,169,175,28),(949,9,169,175,30),(949,10,169,175,36),(949,11,169,175,51),(949,12,169,175,77),(950,1,169,200,0),(950,2,169,200,1),(950,3,169,200,2),(950,4,169,200,3),(950,5,169,187,7),(950,6,169,200,8),(950,7,169,200,10),(950,8,169,200,28),(950,9,169,200,30),(950,10,169,200,36),(950,11,169,200,51),(950,12,169,200,77),(951,1,169,225,0),(951,2,169,225,1),(951,3,169,225,2),(951,4,169,225,3),(951,5,169,213,7),(951,6,169,225,8),(951,7,169,225,10),(951,8,169,225,28),(951,9,169,225,30),(951,10,169,225,36),(951,11,169,225,51),(951,12,169,225,77),(952,1,214,125,0),(953,1,214,250,0),(954,1,214,375,0),(955,1,262,10,4),(955,2,262,10,5),(956,1,262,20,4),(956,2,262,20,5),(957,1,262,30,4),(957,2,262,30,5),(958,1,262,40,4),(958,2,262,40,5),(959,1,262,50,4),(959,2,262,50,5),(962,1,232,2,4544),(963,1,232,4,4544),(964,1,232,6,4544),(965,1,232,8,4544),(966,1,232,10,4544),(975,1,264,864,102),(976,1,131,100,0),(976,2,137,33,0),(978,1,14,1,0),(978,2,246,350,0),(979,1,268,10,63),(980,1,268,25,63),(981,1,268,50,63),(982,1,268,10,60),(983,1,268,25,60),(984,1,268,50,60),(985,1,268,10,65),(986,1,268,25,65),(987,1,268,50,65),(988,1,268,10,64),(989,1,268,25,64),(990,1,268,50,64),(991,1,268,10,69),(992,1,268,25,69),(993,1,268,50,69),(994,1,268,10,61),(995,1,268,25,61),(996,1,268,50,61),(997,1,331,5,0),(998,1,331,15,0),(999,1,331,25,0),(1001,1,262,30,0),(1001,2,262,30,1),(1001,3,262,30,2),(1001,4,262,30,3),(1001,5,262,30,4),(1001,6,262,30,5),(1001,7,262,30,6),(1002,1,262,35,0),(1002,2,262,35,1),(1002,3,262,35,2),(1002,4,262,35,3),(1002,5,262,35,4),(1002,6,262,35,5),(1002,7,262,35,6),(1003,1,262,40,0),(1003,2,262,40,1),(1003,3,262,40,2),(1003,4,262,40,3),(1003,5,262,40,4),(1003,6,262,40,5),(1003,7,262,40,6),(1004,1,262,45,0),(1004,2,262,45,1),(1004,3,262,45,2),(1004,4,262,45,3),(1004,5,262,45,4),(1004,6,262,45,5),(1004,7,262,45,6),(1005,1,262,50,0),(1005,2,262,50,1),(1005,3,262,50,2),(1005,4,262,50,3),(1005,5,262,50,4),(1005,6,262,50,5),(1005,7,262,50,6),(1006,1,262,5,7),(1006,2,262,5,8),(1006,3,262,5,9),(1006,4,262,5,10),(1006,5,262,5,11),(1007,1,262,10,7),(1007,2,262,10,8),(1007,3,262,10,9),(1007,4,262,10,10),(1007,5,262,10,11),(1008,1,262,15,7),(1008,2,262,15,8),(1008,3,262,15,9),(1008,4,262,15,10),(1008,5,262,15,11),(1009,1,262,20,7),(1009,2,262,20,8),(1009,3,262,20,9),(1009,4,262,20,10),(1009,5,262,20,11),(1010,1,262,25,7),(1010,2,262,25,8),(1010,3,262,25,9),(1010,4,262,25,10),(1010,5,262,25,11),(1011,1,262,8,7),(1011,2,262,8,8),(1011,3,262,8,9),(1011,4,262,8,10),(1011,5,262,8,11),(1012,1,262,16,7),(1012,2,262,16,8),(1012,3,262,16,9),(1012,4,262,16,10),(1012,5,262,16,11),(1013,1,262,24,7),(1013,2,262,24,8),(1013,3,262,24,9),(1013,4,262,24,10),(1013,5,262,24,11),(1014,1,262,32,7),(1014,2,262,32,8),(1014,3,262,32,9),(1014,4,262,32,10),(1014,5,262,32,11),(1015,1,262,40,7),(1015,2,262,40,8),(1015,3,262,40,9),(1015,4,262,40,10),(1015,5,262,40,11),(1016,1,262,50,7),(1016,2,262,50,8),(1016,3,262,50,9),(1016,4,262,50,10),(1016,5,262,50,11),(1021,1,327,1,0),(1022,1,327,2,0),(1023,1,327,3,0),(1024,1,327,4,0),(1025,1,327,5,0),(1026,1,328,50,0),(1027,1,328,100,0),(1028,1,328,150,0),(1029,1,328,200,0),(1030,1,328,250,0),(1031,1,0,6,0),(1032,1,0,7,0),(1033,1,0,8,0),(1034,1,0,9,0),(1035,1,0,10,0),(1036,1,189,4,0),(1037,1,189,5,0),(1038,1,189,6,0),(1041,1,330,25,0),(1041,2,330,25,1),(1041,3,330,25,2),(1041,4,330,25,3),(1041,5,330,25,28),(1041,6,330,25,36),(1041,7,330,25,77),(1042,1,330,50,0),(1042,2,330,50,1),(1042,3,330,50,2),(1042,4,330,50,3),(1042,5,330,50,28),(1042,6,330,50,36),(1042,7,330,50,77),(1043,1,330,75,0),(1043,2,330,75,1),(1043,3,330,75,2),(1043,4,330,75,3),(1043,5,330,75,28),(1043,6,330,75,36),(1043,7,330,75,77),(1044,1,330,25,0),(1044,2,330,25,1),(1044,3,330,25,2),(1044,4,330,25,3),(1044,5,330,25,28),(1044,6,330,25,36),(1045,1,330,50,0),(1045,2,330,50,1),(1045,3,330,50,2),(1045,4,330,50,3),(1045,5,330,50,28),(1045,6,330,50,36),(1046,1,330,75,0),(1046,2,330,75,1),(1046,3,330,75,2),(1046,4,330,75,3),(1046,5,330,75,28),(1046,6,330,75,36),(1047,1,330,25,0),(1047,2,330,25,1),(1047,3,330,25,2),(1047,4,330,25,3),(1047,5,330,25,28),(1047,6,330,25,36),(1047,7,330,25,77),(1048,1,330,50,0),(1048,2,330,50,1),(1048,3,330,50,2),(1048,4,330,50,3),(1048,5,330,50,28),(1048,6,330,50,36),(1048,7,330,50,77),(1049,1,330,75,0),(1049,2,330,75,1),(1049,3,330,75,2),(1049,4,330,75,3),(1049,5,330,75,28),(1049,6,330,75,36),(1049,7,330,75,77),(1050,1,330,15,0),(1050,2,330,15,1),(1050,3,330,15,2),(1050,4,330,15,3),(1050,5,330,15,28),(1050,6,330,15,36),(1050,7,330,15,77),(1051,1,330,30,0),(1051,2,330,30,1),(1051,3,330,30,2),(1051,4,330,30,3),(1051,5,330,30,28),(1051,6,330,30,36),(1051,7,330,30,77),(1052,1,330,50,0),(1052,2,330,50,1),(1052,3,330,50,2),(1052,4,330,50,3),(1052,5,330,50,28),(1052,6,330,50,36),(1052,7,330,50,77),(1053,1,278,560,27200),(1053,2,440,61,100),(1054,1,278,580,30135),(1054,2,440,63,100),(1055,1,278,600,32780),(1055,2,440,65,100),(1056,1,317,1,0),(1057,1,317,2,0),(1058,1,317,3,0),(1059,1,317,4,0),(1060,1,317,5,0),(1061,1,172,26,0),(1062,1,172,27,0),(1063,1,172,28,0),(1064,1,172,30,0),(1065,1,172,32,0),(1066,1,259,27,0),(1067,1,259,29,0),(1068,1,259,31,0),(1069,1,259,33,0),(1070,1,259,35,0),(1071,1,326,1,0),(1072,1,318,1,0),(1073,1,318,2,0),(1074,1,318,3,0),(1075,1,318,4,0),(1076,1,318,5,0),(1083,1,125,22,22),(1083,2,137,0,0),(1083,3,141,1,0),(1083,4,139,-6233,0),(1083,5,139,-6265,0),(1083,6,125,22,22),(1083,7,137,147,0),(1083,8,141,1,0),(1084,1,125,25,25),(1084,2,137,0,0),(1084,3,141,1,0),(1084,4,139,-6233,0),(1084,5,139,-6265,0),(1084,6,125,25,25),(1084,7,137,147,0),(1084,8,141,1,0),(1085,1,125,28,28),(1085,2,137,0,0),(1085,3,141,1,0),(1085,4,139,-6233,0),(1085,5,139,-6265,0),(1085,6,125,28,28),(1085,7,137,147,0),(1085,8,141,1,0),(1086,1,274,18,0),(1087,1,274,20,0),(1088,1,274,22,0),(1089,1,268,10,58),(1090,1,268,25,58),(1091,1,268,50,58),(1092,1,238,1,0),(1093,1,304,-20,0),(1094,1,304,-40,0),(1095,1,304,-60,0),(1096,1,304,-80,0),(1097,1,304,-100,0),(1099,1,273,12,0),(1100,1,273,15,0),(1101,1,273,18,0),(1107,1,294,2,100),(1108,1,294,4,100),(1109,1,294,6,100),(1113,1,331,30,0),(1114,1,331,35,0),(1115,1,331,40,0),(1122,1,308,1,0),(1129,1,267,1,24),(1129,2,267,1,25),(1129,3,267,1,26),(1130,1,267,1,18),(1130,2,267,1,19),(1130,3,267,1,20),(1130,4,267,1,21),(1130,5,267,1,22),(1130,6,267,1,23),(1130,7,267,1,24),(1130,8,267,1,25),(1130,9,267,1,26),(1131,1,185,10,51),(1132,1,185,20,51),(1133,1,185,30,51),(1134,1,220,32,74),(1135,1,220,64,74),(1136,1,220,96,74),(1137,1,310,180000,0),(1137,2,139,5027,0),(1137,3,310,180000,0),(1137,4,139,5028,0),(1137,5,310,180000,0),(1137,6,139,5029,0),(1137,7,310,180000,0),(1137,8,139,5030,0),(1137,9,310,180000,0),(1137,10,139,5031,0),(1137,11,310,180000,0),(1137,12,139,5032,0),(1137,13,310,180000,0),(1137,14,139,8476,0),(1138,1,310,360000,0),(1138,2,139,5027,0),(1138,3,310,360000,0),(1138,4,139,5028,0),(1138,5,310,360000,0),(1138,6,139,5029,0),(1138,7,310,360000,0),(1138,8,139,5030,0),(1138,9,310,360000,0),(1138,10,139,5031,0),(1138,11,310,360000,0),(1138,12,139,5032,0),(1138,13,310,360000,0),(1138,14,139,8476,0),(1139,1,310,540000,0),(1139,2,139,5027,0),(1139,3,310,540000,0),(1139,4,139,5028,0),(1139,5,310,540000,0),(1139,6,139,5029,0),(1139,7,310,540000,0),(1139,8,139,5030,0),(1139,9,310,540000,0),(1139,10,139,5031,0),(1139,11,310,540000,0),(1139,12,139,5032,0),(1139,13,310,540000,0),(1139,14,139,8476,0),(1140,1,216,10,51),(1141,1,216,20,51),(1142,1,216,30,51),(1155,1,128,25,0),(1155,2,139,5027,0),(1155,3,128,25,0),(1155,4,139,5028,0),(1155,5,128,25,0),(1155,6,139,5029,0),(1155,7,128,25,0),(1155,8,139,5030,0),(1155,9,128,25,0),(1155,10,139,5031,0),(1155,11,128,25,0),(1155,12,139,5032,0),(1155,13,128,25,0),(1155,14,139,8476,0),(1156,1,128,50,0),(1156,2,139,5027,0),(1156,3,128,50,0),(1156,4,139,5028,0),(1156,5,128,50,0),(1156,6,139,5029,0),(1156,7,128,50,0),(1156,8,139,5030,0),(1156,9,128,50,0),(1156,10,139,5031,0),(1156,11,128,50,0),(1156,12,139,5032,0),(1156,13,128,50,0),(1156,14,139,8476,0),(1157,1,128,100,0),(1157,2,139,5027,0),(1157,3,128,100,0),(1157,4,139,5028,0),(1157,5,128,100,0),(1157,6,139,5029,0),(1157,7,128,100,0),(1157,8,139,5030,0),(1157,9,128,100,0),(1157,10,139,5031,0),(1157,11,128,100,0),(1157,12,139,5032,0),(1157,13,128,100,0),(1157,14,139,8476,0),(1158,1,220,128,74),(1159,1,220,160,74),(1160,1,220,192,74),(1161,1,220,224,74),(1162,1,220,256,74),(1163,1,279,23,0),(1164,1,279,25,0),(1165,1,279,27,0),(1166,1,224,20,74),(1166,2,173,1,0),(1167,1,224,35,74),(1167,2,173,1,0),(1168,1,224,50,74),(1168,2,173,2,0),(1172,1,292,50,0),(1173,1,292,55,0),(1174,1,292,60,0),(1181,1,305,-20,0),(1182,1,305,-40,0),(1183,1,305,-60,0),(1184,1,305,-80,0),(1185,1,305,-100,0),(1186,1,319,3,0),(1187,1,319,6,0),(1188,1,319,10,0),(1196,1,220,20,7),(1197,1,220,40,7),(1198,1,220,60,7),(1199,1,220,80,7),(1200,1,220,100,7),(1210,1,294,0,107),(1211,1,294,0,115),(1212,1,294,0,125),(1213,1,294,0,107),(1214,1,294,0,115),(1215,1,294,0,125),(1216,1,132,2,2),(1217,1,132,5,5),(1218,1,132,10,10),(1219,1,339,3,8105),(1219,2,142,65,0),(1219,3,311,0,0),(1219,4,134,70,0),(1219,5,348,10,0),(1219,6,137,0,0),(1219,7,339,3,8105),(1219,8,142,65,0),(1219,9,311,0,0),(1219,10,134,70,0),(1219,11,348,10,0),(1219,12,137,100,0),(1219,13,339,3,8105),(1219,14,142,65,0),(1219,15,311,0,0),(1219,16,134,70,0),(1219,17,348,10,0),(1219,18,137,79,0),(1219,19,339,3,8105),(1219,20,142,65,0),(1219,21,311,0,0),(1219,22,134,70,0),(1219,23,348,10,0),(1219,24,137,147,0),(1220,1,339,6,8105),(1220,2,142,65,0),(1220,3,311,0,0),(1220,4,134,70,0),(1220,5,348,10,0),(1220,6,137,0,0),(1220,7,339,6,8105),(1220,8,142,65,0),(1220,9,311,0,0),(1220,10,134,70,0),(1220,11,348,10,0),(1220,12,137,100,0),(1220,13,339,6,8105),(1220,14,142,65,0),(1220,15,311,0,0),(1220,16,134,70,0),(1220,17,348,10,0),(1220,18,137,79,0),(1220,19,339,6,8105),(1220,20,142,65,0),(1220,21,311,0,0),(1220,22,134,70,0),(1220,23,348,10,0),(1220,24,137,147,0),(1221,1,339,10,8105),(1221,2,142,65,0),(1221,3,311,0,0),(1221,4,134,70,0),(1221,5,348,10,0),(1221,6,137,0,0),(1221,7,339,10,8105),(1221,8,142,65,0),(1221,9,311,0,0),(1221,10,134,70,0),(1221,11,348,10,0),(1221,12,137,100,0),(1221,13,339,10,8105),(1221,14,142,65,0),(1221,15,311,0,0),(1221,16,134,70,0),(1221,17,348,10,0),(1221,18,137,79,0),(1221,19,339,10,8105),(1221,20,142,65,0),(1221,21,311,0,0),(1221,22,134,70,0),(1221,23,348,10,0),(1221,24,137,147,0),(1230,1,313,25,0),(1231,1,313,50,0),(1232,1,313,75,0),(1265,1,220,40,26),(1265,2,220,40,30),(1265,3,220,40,38),(1266,1,220,50,26),(1266,2,220,50,30),(1266,3,220,50,38),(1267,1,220,60,26),(1267,2,220,60,30),(1267,3,220,60,38),(1268,1,292,20,0),(1269,1,292,25,0),(1270,1,292,30,0),(1284,1,293,15,0),(1285,1,293,30,0),(1286,1,293,50,0),(1287,1,320,1,0),(1288,1,320,3,0),(1289,1,320,5,0),(1290,1,216,40,0),(1290,2,216,40,1),(1290,3,216,40,2),(1290,4,216,40,3),(1290,5,216,40,10),(1290,6,216,40,28),(1290,7,216,40,30),(1290,8,216,40,36),(1290,9,216,40,77),(1291,1,216,50,0),(1291,2,216,50,1),(1291,3,216,50,2),(1291,4,216,50,3),(1291,5,216,50,10),(1291,6,216,50,28),(1291,7,216,50,30),(1291,8,216,50,36),(1291,9,216,50,77),(1292,1,216,60,0),(1292,2,216,60,1),(1292,3,216,60,2),(1292,4,216,60,3),(1292,5,216,60,10),(1292,6,216,60,28),(1292,7,216,60,30),(1292,8,216,60,36),(1292,9,216,60,77),(1296,1,247,20,53),(1297,1,247,40,53),(1298,1,247,60,53),(1299,1,247,80,53),(1300,1,247,100,53),(1301,1,258,20,0),(1302,1,258,25,0),(1303,1,258,30,0),(1304,1,216,50,8),(1305,1,216,100,8),(1306,1,216,150,8),(1307,1,325,10,0),(1308,1,325,20,0),(1309,1,325,30,0),(1310,1,325,40,0),(1311,1,325,50,0),(1313,1,85,6037,0),(1314,1,85,6038,0),(1315,1,85,6039,0),(1316,1,302,216,216),(1316,2,385,99,0),(1317,1,302,233,233),(1317,2,385,99,0),(1318,1,302,250,250),(1318,2,385,99,0),(1319,1,274,16,0),(1320,1,274,18,0),(1321,1,274,20,0),(1361,1,159,10,0),(1361,2,262,10,0),(1361,3,262,10,1),(1361,4,262,10,2),(1361,5,262,10,3),(1361,6,262,10,4),(1361,7,262,10,5),(1361,8,262,10,6),(1362,1,214,300,0),(1362,2,97,200,0),(1362,3,190,200,0),(1363,1,327,1,0),(1364,1,273,1,0),(1364,2,274,1,0),(1364,3,294,1,100),(1364,4,169,40,0),(1364,5,169,40,1),(1364,6,169,40,2),(1364,7,169,40,3),(1364,8,169,40,8),(1364,9,169,40,10),(1364,10,169,40,26),(1364,11,169,40,28),(1364,12,169,40,30),(1364,13,169,40,36),(1364,14,169,40,74),(1365,1,180,2,0),(1366,1,159,10,0),(1366,2,262,10,0),(1366,3,262,10,1),(1366,4,262,10,2),(1366,5,262,10,3),(1366,6,262,10,4),(1366,7,262,10,5),(1366,8,262,10,6),(1367,1,214,300,0),(1367,2,97,200,0),(1367,3,190,200,0),(1368,1,327,1,0),(1369,1,273,1,0),(1369,2,274,1,0),(1369,3,294,1,100),(1369,4,169,40,0),(1369,5,169,40,1),(1369,6,169,40,2),(1369,7,169,40,3),(1369,8,169,40,8),(1369,9,169,40,10),(1369,10,169,40,26),(1369,11,169,40,28),(1369,12,169,40,30),(1369,13,169,40,36),(1369,14,169,40,74),(1370,1,180,2,0),(1378,1,10,0,0),(1379,1,10,0,0),(1380,1,10,0,0),(1382,1,10,0,0),(1388,2,13,1,0),(1389,1,328,300,0),(1390,1,328,350,0),(1391,1,328,400,0),(1392,1,328,450,0),(1393,1,328,500,0),(1394,1,172,33,0),(1395,1,172,34,0),(1396,1,172,35,0),(1397,1,172,37,0),(1398,1,172,39,0),(1399,1,259,37,0),(1400,1,259,39,0),(1401,1,259,41,0),(1402,1,259,43,0),(1403,1,259,45,0),(1414,1,264,432,451),(1415,1,264,864,451),(1416,1,264,1296,451),(1417,1,264,1728,451),(1418,1,264,2160,451),(1420,1,282,20,0),(1421,1,282,40,0),(1422,1,282,60,0),(1423,1,282,80,0),(1424,1,282,100,0),(1430,1,280,27,0),(1431,1,280,34,0),(1432,1,280,41,0),(1435,1,339,3,8105),(1435,2,142,65,0),(1435,3,311,0,0),(1435,4,134,70,0),(1435,5,348,10,0),(1435,6,137,0,0),(1435,7,339,3,8105),(1435,8,142,65,0),(1435,9,311,0,0),(1435,10,134,70,0),(1435,11,348,10,0),(1435,12,137,100,0),(1435,13,339,3,8105),(1435,14,142,65,0),(1435,15,311,0,0),(1435,16,134,70,0),(1435,17,348,10,0),(1435,18,137,79,0),(1435,19,339,3,8105),(1435,20,142,65,0),(1435,21,311,0,0),(1435,22,134,70,0),(1435,23,348,10,0),(1435,24,137,147,0),(1436,1,339,6,8105),(1436,2,142,65,0),(1436,3,311,0,0),(1436,4,134,70,0),(1436,5,348,10,0),(1436,6,137,0,0),(1436,7,339,6,8105),(1436,8,142,65,0),(1436,9,311,0,0),(1436,10,134,70,0),(1436,11,348,10,0),(1436,12,137,100,0),(1436,13,339,6,8105),(1436,14,142,65,0),(1436,15,311,0,0),(1436,16,134,70,0),(1436,17,348,10,0),(1436,18,137,79,0),(1436,19,339,6,8105),(1436,20,142,65,0),(1436,21,311,0,0),(1436,22,134,70,0),(1436,23,348,10,0),(1436,24,137,147,0),(1437,1,339,10,8105),(1437,2,142,65,0),(1437,3,311,0,0),(1437,4,134,70,0),(1437,5,348,10,0),(1437,6,137,0,0),(1437,7,339,10,8105),(1437,8,142,65,0),(1437,9,311,0,0),(1437,10,134,70,0),(1437,11,348,10,0),(1437,12,137,100,0),(1437,13,339,10,8105),(1437,14,142,65,0),(1437,15,311,0,0),(1437,16,134,70,0),(1437,17,348,10,0),(1437,18,137,79,0),(1437,19,339,10,8105),(1437,20,142,65,0),(1437,21,311,0,0),(1437,22,134,70,0),(1437,23,348,10,0),(1437,24,137,147,0),(1453,1,131,10,10),(1453,2,137,32,0),(1453,3,311,1,0),(1454,1,131,20,20),(1454,2,137,32,0),(1454,3,311,1,0),(1455,1,131,30,30),(1455,2,137,32,0),(1455,3,311,1,0),(1456,1,131,40,40),(1456,2,137,32,0),(1456,3,311,1,0),(1457,1,131,50,50),(1457,2,137,32,0),(1457,3,311,1,0),(1467,1,280,27,0),(1468,1,280,34,0),(1469,1,280,41,0),(1471,1,264,90,362),(1472,1,264,180,362),(1473,1,264,270,362),(1474,1,264,360,362),(1475,1,264,450,362),(1483,1,294,0,133),(1484,1,294,0,141),(1485,1,294,0,150),(1486,1,339,1,8165),(1486,2,138,1,0),(1486,3,141,1,0),(1486,4,142,60,0),(1486,5,137,0,0),(1486,6,311,0,0),(1486,7,134,75,0),(1486,8,139,-265,0),(1486,9,139,-754,0),(1486,10,139,-1332,0),(1486,11,139,-1572,0),(1486,12,139,-2749,0),(1486,13,139,-4979,0),(1486,14,139,-5418,0),(1486,15,139,-5403,0),(1486,16,348,10,0),(1487,1,339,3,8166),(1487,2,138,1,0),(1487,3,141,1,0),(1487,4,142,60,0),(1487,5,137,0,0),(1487,6,311,0,0),(1487,7,134,75,0),(1487,8,139,-265,0),(1487,9,139,-754,0),(1487,10,139,-1332,0),(1487,11,139,-1572,0),(1487,12,139,-2749,0),(1487,13,139,-4979,0),(1487,14,139,-5418,0),(1487,15,139,-5403,0),(1487,16,348,10,0),(1488,1,339,5,8167),(1488,2,138,1,0),(1488,3,141,1,0),(1488,4,142,60,0),(1488,5,137,0,0),(1488,6,311,0,0),(1488,7,134,75,0),(1488,8,139,-265,0),(1488,9,139,-754,0),(1488,10,139,-1332,0),(1488,11,139,-1572,0),(1488,12,139,-2749,0),(1488,13,139,-4979,0),(1488,14,139,-5418,0),(1488,15,139,-5403,0),(1488,16,348,10,0),(1489,1,339,7,8168),(1489,2,138,1,0),(1489,3,141,1,0),(1489,4,142,60,0),(1489,5,137,0,0),(1489,6,311,0,0),(1489,7,134,75,0),(1489,8,139,-265,0),(1489,9,139,-754,0),(1489,10,139,-1332,0),(1489,11,139,-1572,0),(1489,12,139,-2749,0),(1489,13,139,-4979,0),(1489,14,139,-5418,0),(1489,15,139,-5403,0),(1489,16,348,10,0),(1490,1,339,9,8169),(1490,2,138,1,0),(1490,3,141,1,0),(1490,4,142,60,0),(1490,5,137,0,0),(1490,6,311,0,0),(1490,7,134,75,0),(1490,8,139,-265,0),(1490,9,139,-754,0),(1490,10,139,-1332,0),(1490,11,139,-1572,0),(1490,12,139,-2749,0),(1490,13,139,-4979,0),(1490,14,139,-5418,0),(1490,15,139,-5403,0),(1490,16,348,10,0),(1504,1,287,2,0),(1504,2,385,2754,1),(1505,1,287,4,0),(1505,2,385,2754,1),(1506,1,287,6,0),(1506,2,385,2754,1),(1511,1,264,60,175),(1511,2,264,60,792),(1512,1,264,120,175),(1512,2,264,120,792),(1513,1,264,180,175),(1513,2,264,180,792),(1514,1,273,2,0),(1515,1,273,4,0),(1516,1,273,6,0),(1524,1,219,260,1800),(1525,1,219,300,2000),(1526,1,219,280,1900),(1528,1,239,30,0),(1529,1,239,35,0),(1530,1,239,40,0),(1531,1,239,45,0),(1532,1,239,50,0),(1533,1,266,11,0),(1534,1,266,14,0),(1535,1,266,17,0),(1536,1,266,11,0),(1537,1,266,14,0),(1538,1,266,17,0),(1539,1,252,37,0),(1540,1,252,44,0),(1541,1,252,50,0),(1543,1,220,10,8),(1544,1,220,20,8),(1545,1,220,30,8),(1546,1,264,120,420),(1547,1,264,240,420),(1548,1,264,360,420),(1549,1,293,25,0),(1550,1,293,50,0),(1551,1,293,75,0),(1552,1,271,5,0),(1553,1,271,10,0),(1554,1,271,15,0),(1555,1,264,240,359),(1556,1,264,480,359),(1557,1,264,720,359),(1563,1,225,18,0),(1564,1,225,21,0),(1565,1,225,24,0),(1566,1,225,27,0),(1567,1,225,30,0),(1572,1,339,2,8261),(1572,2,138,0,0),(1572,3,137,31,0),(1572,4,311,0,0),(1573,1,339,4,8262),(1573,2,138,0,0),(1573,3,137,31,0),(1573,4,311,0,0),(1574,1,339,6,8263),(1574,2,138,0,0),(1574,3,137,31,0),(1574,4,311,0,0),(1575,1,339,8,8264),(1575,2,138,0,0),(1575,3,137,31,0),(1575,4,311,0,0),(1576,1,339,10,8265),(1576,2,138,0,0),(1576,3,137,31,0),(1576,4,311,0,0),(1577,1,274,3,0),(1578,1,274,6,0),(1579,1,274,10,0),(1583,1,264,360,300),(1584,1,264,720,300),(1585,1,264,1080,300),(1586,1,264,1440,300),(1587,1,264,1800,300),(1588,1,344,50,0),(1589,1,344,100,0),(1590,1,344,150,0),(1591,1,293,25,0),(1592,1,341,10,0),(1593,1,341,20,0),(1594,1,341,30,0),(1595,1,341,40,0),(1596,1,341,50,0),(1601,1,217,0,35200),(1601,2,346,60,0),(1602,1,217,0,42440),(1602,2,346,62,0),(1603,1,217,0,46480),(1603,2,346,64,0),(1604,1,439,0,32000),(1604,2,345,59,0),(1605,1,439,0,35200),(1605,2,345,60,0),(1606,1,439,0,42440),(1606,2,345,61,0),(1608,1,347,2,0),(1609,1,347,4,0),(1610,1,347,6,0),(1611,1,282,20,0),(1612,1,282,40,0),(1613,1,282,60,0),(1614,1,282,80,0),(1615,1,282,100,0),(1616,1,279,7,0),(1617,1,279,11,0),(1618,1,279,15,0),(1619,1,279,17,0),(1620,1,279,19,0),(1621,1,177,20,-1),(1622,1,177,22,-1),(1623,1,177,24,-1),(1624,1,177,20,-1),(1625,1,177,22,-1),(1626,1,177,24,-1),(1627,1,271,5,0),(1628,1,271,10,0),(1629,1,271,15,0),(1633,1,225,18,0),(1634,1,225,21,0),(1635,1,225,24,0),(1636,1,225,27,0),(1637,1,225,30,0),(1641,1,359,100,0),(1642,1,359,60,0),(1648,1,339,10,8105),(1648,2,142,65,0),(1648,3,311,0,0),(1648,4,134,70,0),(1648,5,348,10,0),(1648,6,137,0,0),(1648,7,339,10,8105),(1648,8,142,65,0),(1648,9,311,0,0),(1648,10,134,70,0),(1648,11,348,10,0),(1648,12,137,100,0),(1648,13,339,10,8105),(1648,14,142,65,0),(1648,15,311,0,0),(1648,16,134,70,0),(1648,17,348,10,0),(1648,18,137,79,0),(1648,19,339,10,8105),(1648,20,142,65,0),(1648,21,311,0,0),(1648,22,134,70,0),(1648,23,348,10,0),(1648,24,137,147,0),(1648,25,339,10,11404),(1648,26,142,71,0),(1648,27,311,0,0),(1648,28,134,75,0),(1648,29,348,10,0),(1648,30,137,0,0),(1648,31,339,10,11404),(1648,32,142,71,0),(1648,33,311,0,0),(1648,34,134,75,0),(1648,35,348,10,0),(1648,36,137,100,0),(1648,37,339,10,11404),(1648,38,142,71,0),(1648,39,311,0,0),(1648,40,134,75,0),(1648,41,348,10,0),(1648,42,137,79,0),(1648,43,339,10,11404),(1648,44,142,71,0),(1648,45,311,0,0),(1648,46,134,75,0),(1648,47,348,10,0),(1648,48,137,147,0),(1649,1,339,10,8105),(1649,2,142,65,0),(1649,3,311,0,0),(1649,4,134,70,0),(1649,5,348,10,0),(1649,6,137,0,0),(1649,7,339,10,8105),(1649,8,142,65,0),(1649,9,311,0,0),(1649,10,134,70,0),(1649,11,348,10,0),(1649,12,137,100,0),(1649,13,339,10,8105),(1649,14,142,65,0),(1649,15,311,0,0),(1649,16,134,70,0),(1649,17,348,10,0),(1649,18,137,79,0),(1649,19,339,10,8105),(1649,20,142,65,0),(1649,21,311,0,0),(1649,22,134,70,0),(1649,23,348,10,0),(1649,24,137,147,0),(1649,25,339,10,11404),(1649,26,142,71,0),(1649,27,311,0,0),(1649,28,134,75,0),(1649,29,348,10,0),(1649,30,137,0,0),(1649,31,339,10,11404),(1649,32,142,71,0),(1649,33,311,0,0),(1649,34,134,75,0),(1649,35,348,10,0),(1649,36,137,100,0),(1649,37,339,10,11404),(1649,38,142,71,0),(1649,39,311,0,0),(1649,40,134,75,0),(1649,41,348,10,0),(1649,42,137,79,0),(1649,43,339,10,11404),(1649,44,142,71,0),(1649,45,311,0,0),(1649,46,134,75,0),(1649,47,348,10,0),(1649,48,137,147,0),(1649,49,339,10,13199),(1649,50,142,76,0),(1649,51,311,0,0),(1649,52,134,80,0),(1649,53,348,10,0),(1649,54,137,0,0),(1649,55,339,10,13199),(1649,56,142,76,0),(1649,57,311,0,0),(1649,58,134,80,0),(1649,59,348,10,0),(1649,60,137,100,0),(1649,61,339,10,13199),(1649,62,142,76,0),(1649,63,311,0,0),(1649,64,134,80,0),(1649,65,348,10,0),(1649,66,137,79,0),(1649,67,339,10,13199),(1649,68,142,76,0),(1649,69,311,0,0),(1649,70,134,80,0),(1649,71,348,10,0),(1649,72,137,147,0),(1650,1,339,10,8105),(1650,2,142,65,0),(1650,3,311,0,0),(1650,4,134,70,0),(1650,5,348,10,0),(1650,6,137,0,0),(1650,7,339,10,8105),(1650,8,142,65,0),(1650,9,311,0,0),(1650,10,134,70,0),(1650,11,348,10,0),(1650,12,137,100,0),(1650,13,339,10,8105),(1650,14,142,65,0),(1650,15,311,0,0),(1650,16,134,70,0),(1650,17,348,10,0),(1650,18,137,79,0),(1650,19,339,10,8105),(1650,20,142,65,0),(1650,21,311,0,0),(1650,22,134,70,0),(1650,23,348,10,0),(1650,24,137,147,0),(1650,25,339,10,11404),(1650,26,142,71,0),(1650,27,311,0,0),(1650,28,134,75,0),(1650,29,348,10,0),(1650,30,137,0,0),(1650,31,339,10,11404),(1650,32,142,71,0),(1650,33,311,0,0),(1650,34,134,75,0),(1650,35,348,10,0),(1650,36,137,100,0),(1650,37,339,10,11404),(1650,38,142,71,0),(1650,39,311,0,0),(1650,40,134,75,0),(1650,41,348,10,0),(1650,42,137,79,0),(1650,43,339,10,11404),(1650,44,142,71,0),(1650,45,311,0,0),(1650,46,134,75,0),(1650,47,348,10,0),(1650,48,137,147,0),(1650,49,339,10,13199),(1650,50,142,76,0),(1650,51,311,0,0),(1650,52,134,80,0),(1650,53,348,10,0),(1650,54,137,0,0),(1650,55,339,10,13199),(1650,56,142,76,0),(1650,57,311,0,0),(1650,58,134,80,0),(1650,59,348,10,0),(1650,60,137,100,0),(1650,61,339,10,13199),(1650,62,142,76,0),(1650,63,311,0,0),(1650,64,134,80,0),(1650,65,348,10,0),(1650,66,137,79,0),(1650,67,339,10,13199),(1650,68,142,76,0),(1650,69,311,0,0),(1650,70,134,80,0),(1650,71,348,10,0),(1650,72,137,147,0),(1650,73,339,10,13830),(1650,74,142,81,0),(1650,75,311,0,0),(1650,76,134,85,0),(1650,77,348,10,0),(1650,78,137,0,0),(1650,79,339,10,13830),(1650,80,142,81,0),(1650,81,311,0,0),(1650,82,134,85,0),(1650,83,348,10,0),(1650,84,137,100,0),(1650,85,339,10,13830),(1650,86,142,81,0),(1650,87,311,0,0),(1650,88,134,85,0),(1650,89,348,10,0),(1650,90,137,79,0),(1650,91,339,10,13830),(1650,92,142,81,0),(1650,93,311,0,0),(1650,94,134,85,0),(1650,95,348,10,0),(1650,96,137,147,0),(1651,1,97,300,0),(1652,1,97,350,0),(1653,1,97,400,0),(1654,1,97,450,0),(1655,1,97,500,0),(1656,1,127,40,0),(1656,2,137,154,0),(1656,3,403,2,0),(1656,4,404,10,0),(1657,1,127,50,0),(1657,2,137,154,0),(1657,3,403,2,0),(1657,4,404,10,0),(1659,1,127,40,0),(1659,2,137,154,0),(1659,3,403,2,0),(1659,4,404,10,0),(1660,1,127,50,0),(1660,2,137,154,0),(1660,3,403,2,0),(1660,4,404,10,0),(1662,1,370,2,0),(1663,1,370,4,0),(1664,1,370,6,0),(1665,1,370,8,0),(1666,1,370,10,0),(2400,1,264,90,38),(2401,1,264,180,38),(2402,1,264,270,38),(4666,0,366,10,50),(4666,1,349,5,0),(4667,0,366,30,50),(4667,1,349,10,0),(4668,0,366,60,50),(4668,1,349,15,0),(4669,0,366,10,500),(4669,1,349,20,0),(4670,0,366,30,500),(4670,1,349,25,0),(4672,1,268,10,57),(4673,1,268,25,57),(4674,1,268,50,57),(4675,1,268,10,68),(4676,1,268,25,68),(4677,1,268,50,68),(4678,1,262,55,0),(4678,2,262,55,1),(4678,3,262,55,2),(4678,4,262,55,3),(4678,5,262,55,4),(4678,6,262,55,5),(4678,7,262,55,6),(4679,1,262,60,0),(4679,2,262,60,1),(4679,3,262,60,2),(4679,4,262,60,3),(4679,5,262,60,4),(4679,6,262,60,5),(4679,7,262,60,6),(4680,1,262,65,0),(4680,2,262,65,1),(4680,3,262,65,2),(4680,4,262,65,3),(4680,5,262,65,4),(4680,6,262,65,5),(4680,7,262,65,6),(4681,1,262,70,0),(4681,2,262,70,1),(4681,3,262,70,2),(4681,4,262,70,3),(4681,5,262,70,4),(4681,6,262,70,5),(4681,7,262,70,6),(4682,1,262,75,0),(4682,2,262,75,1),(4682,3,262,75,2),(4682,4,262,75,3),(4682,5,262,75,4),(4682,6,262,75,5),(4682,7,262,75,6),(4683,1,328,550,0),(4684,1,328,600,0),(4685,1,328,650,0),(4686,1,328,700,0),(4687,1,328,750,0),(4688,1,282,20,0),(4689,1,282,40,0),(4690,1,282,60,0),(4691,1,282,80,0),(4692,1,282,100,0),(4693,1,0,11,0),(4694,1,0,12,0),(4695,1,0,13,0),(4696,1,0,14,0),(4697,1,0,15,0),(4698,1,362,1,0),(4699,1,363,1,0),(4707,1,330,85,0),(4707,2,330,85,1),(4707,3,330,85,2),(4707,4,330,85,3),(4707,5,330,85,28),(4707,6,330,85,36),(4707,7,330,85,77),(4708,1,330,95,0),(4708,2,330,95,1),(4708,3,330,95,2),(4708,4,330,95,3),(4708,5,330,95,28),(4708,6,330,95,36),(4708,7,330,95,77),(4709,1,330,105,0),(4709,2,330,105,1),(4709,3,330,105,2),(4709,4,330,105,3),(4709,5,330,105,28),(4709,6,330,105,36),(4709,7,330,105,77),(4710,1,330,85,0),(4710,2,330,85,1),(4710,3,330,85,2),(4710,4,330,85,3),(4710,5,330,85,28),(4710,6,330,85,36),(4711,1,330,95,0),(4711,2,330,95,1),(4711,3,330,95,2),(4711,4,330,95,3),(4711,5,330,95,28),(4711,6,330,95,36),(4712,1,330,105,0),(4712,2,330,105,1),(4712,3,330,105,2),(4712,4,330,105,3),(4712,5,330,105,28),(4712,6,330,105,36),(4713,1,330,85,0),(4713,2,330,85,1),(4713,3,330,85,2),(4713,4,330,85,3),(4713,5,330,85,28),(4713,6,330,85,36),(4713,7,330,85,77),(4714,1,330,95,0),(4714,2,330,95,1),(4714,3,330,95,2),(4714,4,330,95,3),(4714,5,330,95,28),(4714,6,330,95,36),(4714,7,330,95,77),(4715,1,330,105,0),(4715,2,330,105,1),(4715,3,330,105,2),(4715,4,330,105,3),(4715,5,330,105,28),(4715,6,330,105,36),(4715,7,330,105,77),(4716,1,330,60,0),(4716,2,330,60,1),(4716,3,330,60,2),(4716,4,330,60,3),(4716,5,330,60,28),(4716,6,330,60,36),(4716,7,330,60,77),(4717,1,330,70,0),(4717,2,330,70,1),(4717,3,330,70,2),(4717,4,330,70,3),(4717,5,330,70,28),(4717,6,330,70,36),(4717,7,330,70,77),(4718,1,330,80,0),(4718,2,330,80,1),(4718,3,330,80,2),(4718,4,330,80,3),(4718,5,330,80,28),(4718,6,330,80,36),(4718,7,330,80,77),(4722,1,278,620,35216),(4722,2,440,66,100),(4723,1,278,650,38310),(4723,2,440,68,100),(4724,1,278,670,41300),(4724,2,440,70,100),(4725,1,341,60,0),(4726,1,341,70,0),(4727,1,341,80,0),(4728,1,341,90,0),(4729,1,341,100,0),(4733,1,294,11,100),(4734,1,294,13,100),(4735,1,294,15,100),(4739,1,360,10,11023),(4740,1,360,20,11023),(4741,1,360,30,11023),(4744,1,318,6,0),(4745,1,318,7,0),(4746,1,318,8,0),(4747,1,318,9,0),(4748,1,318,10,0),(4749,1,294,11,100),(4750,1,294,13,100),(4751,1,294,15,100),(4752,1,294,0,155),(4753,1,294,0,160),(4754,1,294,0,165),(4755,1,294,0,130),(4756,1,294,0,135),(4757,1,294,0,140),(4758,1,266,27,0),(4759,1,266,28,0),(4760,1,266,29,0),(4761,1,273,2,0),(4762,1,273,3,0),(4763,1,273,4,0),(4764,1,326,2,0),(4767,1,114,-43,0),(4768,1,114,-46,0),(4769,1,114,-50,0),(4773,1,339,10,8105),(4773,2,142,65,0),(4773,3,311,0,0),(4773,4,134,70,0),(4773,5,348,10,0),(4773,6,137,0,0),(4773,7,339,10,8105),(4773,8,142,65,0),(4773,9,311,0,0),(4773,10,134,70,0),(4773,11,348,10,0),(4773,12,137,100,0),(4773,13,339,10,8105),(4773,14,142,65,0),(4773,15,311,0,0),(4773,16,134,70,0),(4773,17,348,10,0),(4773,18,137,79,0),(4773,19,339,10,8105),(4773,20,142,65,0),(4773,21,311,0,0),(4773,22,134,70,0),(4773,23,348,10,0),(4773,24,137,147,0),(4773,25,339,10,11404),(4773,26,142,71,0),(4773,27,311,0,0),(4773,28,134,75,0),(4773,29,348,10,0),(4773,30,137,0,0),(4773,31,339,10,11404),(4773,32,142,71,0),(4773,33,311,0,0),(4773,34,134,75,0),(4773,35,348,10,0),(4773,36,137,100,0),(4773,37,339,10,11404),(4773,38,142,71,0),(4773,39,311,0,0),(4773,40,134,75,0),(4773,41,348,10,0),(4773,42,137,79,0),(4773,43,339,10,11404),(4773,44,142,71,0),(4773,45,311,0,0),(4773,46,134,75,0),(4773,47,348,10,0),(4773,48,137,147,0),(4776,1,319,12,0),(4777,1,319,14,0),(4778,1,319,16,0),(4779,1,274,24,0),(4780,1,274,26,0),(4781,1,274,28,0),(4790,1,220,288,74),(4791,1,220,320,74),(4792,1,220,352,74),(4793,1,220,384,74),(4794,1,220,416,74),(4795,1,279,28,0),(4796,1,279,29,0),(4797,1,279,30,0),(4798,1,292,65,0),(4799,1,292,70,0),(4800,1,292,75,0),(4801,1,227,30,32),(4802,1,227,60,32),(4803,1,227,90,32),(4804,1,220,448,74),(4805,1,220,480,74),(4806,1,220,512,74),(4807,1,220,544,74),(4808,1,220,576,74),(4809,1,216,40,74),(4810,1,216,80,74),(4811,1,216,120,74),(4813,1,220,70,26),(4813,2,220,70,30),(4813,3,220,70,38),(4814,1,220,80,26),(4814,2,220,80,30),(4814,3,220,80,38),(4815,1,220,90,26),(4815,2,220,90,30),(4815,3,220,90,38),(4819,1,239,52,0),(4820,1,239,54,0),(4821,1,239,56,0),(4822,1,239,58,0),(4823,1,239,60,0),(4824,1,239,52,0),(4825,1,239,54,0),(4826,1,239,56,0),(4827,1,239,58,0),(4828,1,239,60,0),(4829,1,264,480,420),(4830,1,264,600,420),(4831,1,264,720,420),(4844,1,349,5,0),(4845,1,349,10,0),(4846,1,349,15,0),(4847,1,349,20,0),(4848,1,349,25,0),(4861,1,264,600,68),(4862,1,264,1200,68),(4863,1,264,1800,68),(4887,1,264,120,413),(4888,1,264,240,413),(4889,1,264,360,413),(4897,1,280,44,0),(4898,1,280,47,0),(4899,1,280,50,0),(4921,1,264,1896,117),(4921,2,244,75,0),(4922,1,264,2496,117),(4922,2,244,60,0),(4923,1,264,3096,117),(4923,2,244,45,0),(4924,1,273,1,0),(4925,1,273,2,0),(4926,1,273,3,0),(4948,1,258,35,0),(4949,1,258,40,0),(4950,1,258,45,0),(4951,1,220,40,8),(4952,1,220,50,8),(4953,1,220,60,8),(4957,1,252,55,0),(4958,1,252,60,0),(4959,1,252,65,0),(4960,1,280,46,0),(4961,1,280,51,0),(4962,1,280,56,0),(4983,1,216,65,0),(4983,2,216,65,1),(4983,3,216,65,2),(4983,4,216,65,3),(4983,5,216,65,10),(4983,6,216,65,28),(4983,7,216,65,30),(4983,8,216,65,36),(4983,9,216,65,77),(4984,1,216,70,0),(4984,2,216,70,1),(4984,3,216,70,2),(4984,4,216,70,3),(4984,5,216,70,10),(4984,6,216,70,28),(4984,7,216,70,30),(4984,8,216,70,36),(4984,9,216,70,77),(4985,1,216,75,0),(4985,2,216,75,1),(4985,3,216,75,2),(4985,4,216,75,3),(4985,5,216,75,10),(4985,6,216,75,28),(4985,7,216,75,30),(4985,8,216,75,36),(4985,9,216,75,77),(4986,1,217,0,52960),(4986,2,346,66,40),(4987,1,217,0,55400),(4987,2,346,68,40),(4988,1,217,0,60280),(4988,2,346,70,40),(4989,1,347,8,0),(4990,1,347,10,0),(4991,1,347,12,0),(4992,1,279,21,0),(4993,1,279,23,0),(4994,1,279,25,0),(4995,1,279,27,0),(4996,1,279,28,0),(5000,1,313,80,0),(5001,1,313,90,0),(5002,1,313,100,0),(5010,1,264,432,35),(5011,1,264,864,35),(5012,1,264,1296,35),(5013,1,293,90,0),(5014,1,293,100,0),(5029,1,85,11621,0),(5030,1,85,11622,0),(5031,1,85,11623,0),(5032,1,274,22,0),(5033,1,274,24,0),(5034,1,274,26,0),(5035,1,293,60,0),(5036,1,293,70,0),(5037,1,293,80,0),(5038,1,219,330,2100),(5039,1,219,360,2200),(5040,1,219,390,2300),(5045,1,180,5,0),(5061,1,244,-25,0),(5085,1,360,25,11297),(5086,1,360,25,11298),(5087,1,360,25,11299),(5118,1,264,720,396),(5118,2,264,720,8504),(5118,3,264,720,8505),(5119,1,264,1440,396),(5119,2,264,1440,8504),(5119,3,264,1440,8505),(5120,1,264,2160,396),(5120,2,264,2160,8504),(5120,3,264,2160,8505),(5127,1,264,300,261),(5128,1,264,600,261),(5129,1,264,900,261),(5133,1,294,13,100),(5134,1,294,15,100),(5135,1,294,17,100),(5136,1,282,20,0),(5137,1,282,40,0),(5138,1,282,60,0),(5139,1,282,80,0),(5140,1,282,100,0),(5141,1,279,21,0),(5142,1,279,23,0),(5143,1,279,25,0),(5144,1,279,27,0),(5145,1,279,28,0),(5243,1,69,600,0),(5244,1,69,700,0),(5245,1,69,800,0),(5246,1,69,900,0),(5247,1,69,1000,0),(5248,1,360,10,11232),(5249,1,360,20,11232),(5250,1,360,30,11232),(5254,1,218,6,0),(5255,1,218,7,0),(5256,1,218,8,0),(5257,1,218,9,0),(5258,1,218,10,0),(5259,1,218,6,0),(5260,1,218,7,0),(5261,1,218,8,0),(5262,1,218,9,0),(5263,1,218,10,0),(5264,1,218,1,0),(5265,1,218,2,0),(5266,1,218,3,0),(5267,1,218,4,0),(5268,1,218,5,0),(5269,1,131,50,50),(5269,2,137,82,0),(5270,1,303,3000,3000),(5270,2,139,2766,0),(5271,1,303,3500,3500),(5271,2,139,2766,0),(5272,1,303,4000,4000),(5272,2,139,2766,0),(5276,1,264,60,621),(5276,2,264,60,622),(5276,3,264,60,623),(5276,4,264,60,784),(5276,5,264,60,785),(5276,6,264,60,786),(5276,7,264,60,787),(5276,8,264,60,624),(5277,1,264,120,621),(5277,2,264,120,622),(5277,3,264,120,623),(5277,4,264,120,784),(5277,5,264,120,785),(5277,6,264,120,786),(5277,7,264,120,787),(5277,8,264,120,624),(5278,1,264,180,621),(5278,2,264,180,622),(5278,3,264,180,623),(5278,4,264,180,784),(5278,5,264,180,785),(5278,6,264,180,786),(5278,7,264,180,787),(5278,8,264,180,624),(5283,1,320,1,0),(5284,1,320,3,0),(5285,1,320,5,0),(5286,1,294,7,100),(5287,1,294,8,100),(5288,1,294,9,100),(5290,1,439,0,46480),(5290,2,345,62,0),(5291,1,439,0,52960),(5291,2,345,63,0),(5292,1,439,0,55400),(5292,2,345,64,0),(5293,1,439,0,60280),(5293,2,345,65,0),(5294,1,439,0,65440),(5294,2,345,66,50),(5295,1,360,10,11629),(5296,1,360,20,11629),(5297,1,360,30,11629),(5301,1,189,7,0),(5302,1,189,8,0),(5303,1,189,9,0),(5304,1,189,10,0),(5305,1,189,11,0),(5306,1,15,4,0),(5307,1,15,5,0),(5308,1,15,6,0),(5309,1,15,7,0),(5310,1,15,8,0),(5317,1,114,-43,0),(5318,1,114,-46,0),(5319,1,114,-50,0),(5320,1,218,11,0),(5321,1,218,12,0),(5322,1,218,13,0),(5323,1,218,14,0),(5324,1,218,15,0),(5325,1,280,27,0),(5326,1,280,34,0),(5327,1,280,41,0),(5328,1,280,44,0),(5329,1,280,47,0),(5339,1,215,24,0),(5347,1,375,225,0),(5348,1,375,230,0),(5360,1,397,1300,0),(5366,1,247,75,20),(5500,1,231,5,0),(5501,1,231,7,0),(5502,1,231,9,0),(5516,1,320,6,0),(5517,1,320,7,0),(5518,1,320,8,0),(5519,1,172,40,0),(5520,1,172,41,0),(5521,1,172,42,0),(5522,1,172,43,0),(5523,1,172,44,0),(5524,1,259,46,0),(5525,1,259,47,0),(5526,1,259,48,0),(5527,1,259,49,0),(5528,1,259,50,0),(5529,1,339,11,12680),(5529,2,138,1,0),(5529,3,141,1,0),(5529,4,142,60,0),(5529,5,137,0,0),(5529,6,311,0,0),(5529,7,134,80,0),(5529,8,139,-265,0),(5529,9,139,-754,0),(5529,10,139,-1332,0),(5529,11,139,-1572,0),(5529,12,139,-2749,0),(5529,13,139,-4979,0),(5529,14,139,-5418,0),(5529,15,139,-5403,0),(5529,16,348,10,0),(5530,1,339,13,12681),(5530,2,138,1,0),(5530,3,141,1,0),(5530,4,142,60,0),(5530,5,137,0,0),(5530,6,311,0,0),(5530,7,134,80,0),(5530,8,139,-265,0),(5530,9,139,-754,0),(5530,10,139,-1332,0),(5530,11,139,-1572,0),(5530,12,139,-2749,0),(5530,13,139,-4979,0),(5530,14,139,-5418,0),(5530,15,139,-5403,0),(5530,16,348,10,0),(5531,1,339,15,12682),(5531,2,138,1,0),(5531,3,141,1,0),(5531,4,142,60,0),(5531,5,137,0,0),(5531,6,311,0,0),(5531,7,134,80,0),(5531,8,139,-265,0),(5531,9,139,-754,0),(5531,10,139,-1332,0),(5531,11,139,-1572,0),(5531,12,139,-2749,0),(5531,13,139,-4979,0),(5531,14,139,-5418,0),(5531,15,139,-5403,0),(5531,16,348,10,0),(5532,1,339,17,12683),(5532,2,138,1,0),(5532,3,141,1,0),(5532,4,142,60,0),(5532,5,137,0,0),(5532,6,311,0,0),(5532,7,134,80,0),(5532,8,139,-265,0),(5532,9,139,-754,0),(5532,10,139,-1332,0),(5532,11,139,-1572,0),(5532,12,139,-2749,0),(5532,13,139,-4979,0),(5532,14,139,-5418,0),(5532,15,139,-5403,0),(5532,16,348,10,0),(5533,1,339,19,12684),(5533,2,138,1,0),(5533,3,141,1,0),(5533,4,142,60,0),(5533,5,137,0,0),(5533,6,311,0,0),(5533,7,134,80,0),(5533,8,139,-265,0),(5533,9,139,-754,0),(5533,10,139,-1332,0),(5533,11,139,-1572,0),(5533,12,139,-2749,0),(5533,13,139,-4979,0),(5533,14,139,-5418,0),(5533,15,139,-5403,0),(5533,16,348,10,0),(5534,1,266,18,0),(5535,1,266,20,0),(5536,1,266,22,0),(5542,1,330,110,0),(5542,2,330,110,1),(5542,3,330,110,2),(5542,4,330,110,3),(5542,5,330,110,28),(5542,6,330,110,36),(5542,7,330,110,77),(5543,1,330,115,0),(5543,2,330,115,1),(5543,3,330,115,2),(5543,4,330,115,3),(5543,5,330,115,28),(5543,6,330,115,36),(5543,7,330,115,77),(5544,1,330,120,0),(5544,2,330,120,1),(5544,3,330,120,2),(5544,4,330,120,3),(5544,5,330,120,28),(5544,6,330,120,36),(5544,7,330,120,77),(5545,1,330,110,0),(5545,2,330,110,1),(5545,3,330,110,2),(5545,4,330,110,3),(5545,5,330,110,28),(5545,6,330,110,36),(5546,1,330,115,0),(5546,2,330,115,1),(5546,3,330,115,2),(5546,4,330,115,3),(5546,5,330,115,28),(5546,6,330,115,36),(5547,1,330,120,0),(5547,2,330,120,1),(5547,3,330,120,2),(5547,4,330,120,3),(5547,5,330,120,28),(5547,6,330,120,36),(5548,1,330,110,0),(5548,2,330,110,1),(5548,3,330,110,2),(5548,4,330,110,3),(5548,5,330,110,28),(5548,6,330,110,36),(5548,7,330,110,77),(5549,1,330,115,0),(5549,2,330,115,1),(5549,3,330,115,2),(5549,4,330,115,3),(5549,5,330,115,28),(5549,6,330,115,36),(5549,7,330,115,77),(5550,1,330,120,0),(5550,2,330,120,1),(5550,3,330,120,2),(5550,4,330,120,3),(5550,5,330,120,28),(5550,6,330,120,36),(5550,7,330,120,77),(5551,1,330,85,0),(5551,2,330,85,1),(5551,3,330,85,2),(5551,4,330,85,3),(5551,5,330,85,28),(5551,6,330,85,36),(5551,7,330,85,77),(5552,1,330,90,0),(5552,2,330,90,1),(5552,3,330,90,2),(5552,4,330,90,3),(5552,5,330,90,28),(5552,6,330,90,36),(5552,7,330,90,77),(5553,1,330,95,0),(5553,2,330,95,1),(5553,3,330,95,2),(5553,4,330,95,3),(5553,5,330,95,28),(5553,6,330,95,36),(5553,7,330,95,77),(5554,1,278,700,44340),(5554,2,440,71,100),(5555,1,278,720,47230),(5555,2,440,73,100),(5556,1,278,750,51057),(5556,2,440,75,100),(5557,1,341,110,0),(5558,1,341,120,0),(5559,1,341,130,0),(5560,1,341,140,0),(5561,1,341,150,0),(5562,1,360,40,11023),(5563,1,360,50,11023),(5564,1,360,60,11023),(5566,1,318,11,0),(5567,1,318,12,0),(5568,1,318,13,0),(5569,1,318,14,0),(5570,1,318,15,0),(5571,1,294,16,100),(5572,1,294,17,100),(5573,1,294,18,100),(5574,1,294,0,170),(5575,1,294,0,175),(5576,1,294,0,180),(5577,1,294,0,145),(5578,1,294,0,150),(5579,1,294,0,155),(5580,1,266,30,0),(5581,1,266,31,0),(5582,1,266,32,0),(5586,1,114,-53,0),(5587,1,114,-56,0),(5588,1,114,-59,0),(5589,1,319,17,0),(5590,1,319,19,0),(5591,1,319,21,0),(5592,1,274,30,0),(5593,1,274,32,0),(5594,1,274,34,0),(5595,1,279,31,0),(5596,1,279,32,0),(5597,1,279,33,0),(5611,1,274,28,0),(5612,1,274,30,0),(5613,1,274,32,0),(5617,1,294,18,100),(5618,1,294,19,100),(5619,1,294,20,100),(5620,1,320,6,0),(5621,1,320,7,0),(5622,1,320,8,0),(5623,1,15,9,0),(5624,1,15,10,0),(5625,1,15,11,0),(5626,1,15,12,0),(5627,1,15,13,0),(5628,1,114,-53,0),(5629,1,114,-56,0),(5630,1,114,-59,0),(5729,1,218,11,0),(5730,1,218,12,0),(5731,1,218,13,0),(5732,1,218,14,0),(5733,1,218,15,0),(5738,1,280,62,0),(5739,1,280,63,0),(5740,1,280,64,0),(5776,1,169,5,-1),(5777,1,169,10,-1),(5778,1,169,15,-1),(5797,1,264,2520,396),(5797,2,264,2520,8504),(5797,3,264,2520,8505),(5798,1,264,2880,396),(5798,2,264,2880,8504),(5798,3,264,2880,8505),(5799,1,264,3240,396),(5799,2,264,3240,8504),(5799,3,264,3240,8505),(5806,1,279,7,0),(5807,1,279,11,0),(5808,1,279,15,0),(5825,1,244,-40,0),(5850,1,287,2,1),(5850,2,137,31,0),(5850,3,136,5,0),(5860,1,243,40,0),(5861,1,243,45,0),(5862,1,243,50,0),(5880,1,287,8,0),(5880,2,385,2754,1),(5881,1,287,10,0),(5881,2,385,2754,1),(5882,1,287,12,0),(5882,2,385,2754,1),(5883,2,139,2754,1),(5886,1,274,12,0),(5887,1,274,14,0),(5888,1,274,16,0),(5889,1,280,51,0),(5890,1,280,52,0),(5891,1,280,53,0),(5909,1,279,29,0),(5910,1,279,30,0),(5911,1,279,31,0),(5912,1,279,32,0),(5913,1,279,33,0),(5917,1,220,100,26),(5917,2,220,100,30),(5917,3,220,100,38),(5918,1,220,110,26),(5918,2,220,110,30),(5918,3,220,110,38),(5919,1,220,120,26),(5919,2,220,120,30),(5919,3,220,120,38),(5922,1,292,35,0),(5923,1,292,40,0),(5924,1,292,45,0),(5939,1,218,6,0),(5940,1,218,7,0),(5941,1,218,8,0),(5942,1,218,9,0),(5943,1,218,10,0),(5944,1,273,4,0),(5945,1,273,5,0),(5946,1,273,6,0),(5950,1,264,240,175),(5950,2,264,240,792),(5951,1,264,300,175),(5951,2,264,300,792),(5952,1,264,360,175),(5952,2,264,360,792),(5954,1,264,2400,68),(5955,1,264,3000,68),(5956,1,264,3600,68),(5972,1,264,2880,6001),(5972,2,264,2880,3676),(5973,1,264,2880,6000),(5973,2,264,2880,87),(6003,1,279,29,0),(6004,1,279,30,0),(6005,1,279,31,0),(6006,1,279,32,0),(6007,1,279,33,0),(6011,1,216,95,0),(6011,2,216,95,1),(6011,3,216,95,2),(6011,4,216,95,3),(6011,5,216,95,10),(6011,6,216,95,28),(6011,7,216,95,30),(6011,8,216,95,36),(6011,9,216,95,77),(6012,1,216,100,0),(6012,2,216,100,1),(6012,3,216,100,2),(6012,4,216,100,3),(6012,5,216,100,10),(6012,6,216,100,28),(6012,7,216,100,30),(6012,8,216,100,36),(6012,9,216,100,77),(6013,1,216,105,0),(6013,2,216,105,1),(6013,3,216,105,2),(6013,4,216,105,3),(6013,5,216,105,10),(6013,6,216,105,28),(6013,7,216,105,30),(6013,8,216,105,36),(6013,9,216,105,77),(6014,1,360,40,12617),(6015,1,360,50,12617),(6016,1,360,60,12617),(6017,1,217,0,65440),(6017,2,346,72,28),(6018,1,217,0,70880),(6018,2,346,74,28),(6019,1,217,0,76600),(6019,2,346,76,28),(6020,1,220,15,21),(6020,2,220,15,23),(6020,3,220,30,52),(6020,4,220,15,28),(6021,1,220,25,21),(6021,2,220,25,23),(6021,3,220,50,52),(6021,4,220,25,28),(6022,1,220,35,21),(6022,2,220,35,23),(6022,3,220,70,52),(6022,4,220,35,28),(6023,1,278,900,66950),(6023,2,440,82,100),(6024,1,278,900,70230),(6024,2,440,84,100),(6025,1,278,900,74935),(6025,2,440,86,100),(6026,1,127,10,0),(6026,2,139,16106,0),(6027,1,127,25,0),(6027,2,139,16106,0),(6028,1,127,50,0),(6028,2,139,16106,0),(6029,1,216,200,8),(6030,1,216,250,8),(6031,1,216,300,8),(6032,1,439,0,70880),(6032,2,345,68,50),(6033,1,439,0,76600),(6033,2,345,70,50),(6034,1,439,0,82600),(6034,2,345,72,35),(6035,1,258,48,0),(6036,1,258,51,0),(6037,1,258,54,0),(6042,1,220,70,8),(6043,1,220,80,8),(6044,1,220,100,8),(6045,1,220,45,21),(6045,2,220,45,23),(6045,3,220,90,52),(6045,4,220,45,28),(6046,1,220,55,21),(6046,2,220,55,23),(6046,3,220,110,52),(6046,4,220,55,28),(6047,1,220,65,21),(6047,2,220,65,23),(6047,3,220,130,52),(6047,4,220,65,28),(6048,1,220,75,21),(6048,2,220,75,23),(6048,3,220,150,52),(6048,4,220,75,28),(6049,1,220,85,21),(6049,2,220,85,23),(6049,3,220,170,52),(6049,4,220,85,28),(6050,1,220,95,21),(6050,2,220,95,23),(6050,3,220,190,52),(6050,4,220,95,28),(6051,1,213,1,0),(6052,1,213,3,0),(6053,1,213,5,0),(6057,1,220,105,21),(6057,2,220,105,23),(6057,3,220,210,52),(6057,4,220,105,28),(6058,1,220,115,21),(6058,2,220,115,23),(6058,3,220,230,52),(6058,4,220,115,28),(6059,1,220,125,21),(6059,2,220,125,23),(6059,3,220,250,52),(6059,4,220,125,28),(6060,1,247,5,76),(6061,1,247,10,76),(6063,1,303,4500,4500),(6063,2,139,2766,0),(6064,1,303,5000,5000),(6064,2,139,2766,0),(6065,1,303,5500,5500),(6065,2,139,2766,0),(6066,1,85,12629,0),(6067,1,85,12630,0),(6068,1,85,12631,0),(6069,1,85,12632,0),(6070,1,85,12633,0),(6071,1,85,12634,0),(6072,1,302,266,266),(6072,2,385,99,0),(6073,1,302,290,290),(6073,2,385,99,0),(6074,1,302,310,310),(6074,2,385,99,0),(6075,1,59,-18,0),(6076,1,59,-21,0),(6077,1,59,-24,0),(6078,1,59,-27,0),(6079,1,59,-30,0),(6080,1,189,12,0),(6081,1,189,13,0),(6082,1,247,50,20),(6083,1,247,75,20),(6084,1,247,100,20),(6085,1,292,20,0),(6086,1,292,30,0),(6087,1,292,40,0),(6088,1,264,180,392),(6089,1,264,360,392),(6090,1,264,540,392),(6112,1,131,10,10),(6112,2,348,10,0),(6112,3,137,-32,0),(6113,1,287,2,0),(6113,2,137,100,0),(6113,3,385,-4232,0),(6113,4,385,-4332,0),(6113,5,139,-2741,0),(6113,6,385,-16192,0),(6113,7,139,-16843,0),(6114,1,287,3,0),(6114,2,137,100,0),(6114,3,385,-4232,0),(6114,4,385,-4332,0),(6114,5,139,-2741,0),(6114,6,385,-16192,0),(6114,7,139,-16843,0),(6115,1,287,4,0),(6115,2,137,100,0),(6115,3,385,-4232,0),(6115,4,385,-4332,0),(6115,5,139,-2741,0),(6115,6,385,-16192,0),(6115,7,139,-16843,0),(6119,1,69,100,0),(6120,1,69,200,0),(6121,1,69,300,0),(6122,1,69,400,0),(6123,1,69,500,0),(6124,1,320,1,0),(6125,1,320,3,0),(6126,1,320,5,0),(6127,1,320,6,0),(6128,1,320,7,0),(6129,1,320,8,0),(6130,1,255,48,0),(6131,1,255,60,0),(6132,1,255,72,0),(6136,1,264,360,300),(6202,1,247,10,35),(6203,1,247,20,35),(6204,1,247,60,35),(6209,1,264,720,245),(6210,1,264,1440,245),(6211,1,264,2160,245),(6215,1,247,5,76),(6216,1,247,10,76),(6217,1,247,15,76),(6223,1,232,11,4544),(6224,1,232,12,4544),(6225,1,232,13,4544),(6226,1,232,14,4544),(6227,1,232,15,4544),(6228,1,264,120,404),(6229,1,264,240,404),(6230,1,264,360,404),(6231,1,264,480,404),(6233,1,264,1728,43),(6234,1,264,2160,43),(6235,1,264,2592,43),(6236,1,287,1,0),(6236,2,137,3,0),(6236,3,137,99,0),(6236,4,138,0,0),(6236,5,244,50,0),(6237,1,287,2,0),(6237,2,137,3,0),(6237,3,137,99,0),(6237,4,138,0,0),(6237,5,244,38,0),(6238,1,287,3,0),(6238,2,137,3,0),(6238,3,137,99,0),(6238,4,138,0,0),(6238,5,244,25,0),(6240,1,273,3,0),(6241,1,273,6,0),(6242,1,273,9,0),(6243,1,273,12,0),(6244,1,273,15,0),(6245,1,273,18,0),(6249,1,310,1000,0),(6249,2,139,11903,0),(6249,3,310,1000,0),(6249,4,139,11904,0),(6249,5,310,1000,0),(6249,6,139,11905,0),(6249,7,310,1000,0),(6249,8,139,1362,0),(6249,9,310,1000,0),(6249,10,139,8032,0),(6249,11,310,1000,0),(6249,12,385,6131,0),(6249,13,385,6231,0),(6249,14,385,6331,0),(6249,15,385,6431,0),(6249,16,385,6531,0),(6249,17,385,6631,0),(6250,1,310,2000,0),(6250,2,139,11903,0),(6250,3,310,2000,0),(6250,4,139,11904,0),(6250,5,310,2000,0),(6250,6,139,11905,0),(6250,7,310,2000,0),(6250,8,139,1362,0),(6250,9,310,2000,0),(6250,10,139,8032,0),(6250,11,310,2000,0),(6250,12,385,6131,0),(6250,13,385,6231,0),(6250,14,385,6331,0),(6250,15,385,6431,0),(6250,16,385,6531,0),(6250,17,385,6631,0),(6251,1,310,3000,0),(6251,2,139,11903,0),(6251,3,310,3000,0),(6251,4,139,11904,0),(6251,5,310,3000,0),(6251,6,139,11905,0),(6251,7,310,3000,0),(6251,8,139,1362,0),(6251,9,310,3000,0),(6251,10,139,8032,0),(6251,11,310,3000,0),(6251,12,385,6131,0),(6251,13,385,6231,0),(6251,14,385,6331,0),(6251,15,385,6431,0),(6251,16,385,6531,0),(6251,17,385,6631,0),(6252,1,310,4000,0),(6252,2,139,11903,0),(6252,3,310,4000,0),(6252,4,139,11904,0),(6252,5,310,4000,0),(6252,6,139,11905,0),(6252,7,310,4000,0),(6252,8,139,1362,0),(6252,9,310,4000,0),(6252,10,139,8032,0),(6252,11,310,4000,0),(6252,12,385,6131,0),(6252,13,385,6231,0),(6252,14,385,6331,0),(6252,15,385,6431,0),(6252,16,385,6531,0),(6252,17,385,6631,0),(6253,1,310,5000,0),(6253,2,139,11903,0),(6253,3,310,5000,0),(6253,4,139,11904,0),(6253,5,310,5000,0),(6253,6,139,11905,0),(6253,7,310,5000,0),(6253,8,139,1362,0),(6253,9,310,5000,0),(6253,10,139,8032,0),(6253,11,310,5000,0),(6253,12,385,6131,0),(6253,13,385,6231,0),(6253,14,385,6331,0),(6253,15,385,6431,0),(6253,16,385,6531,0),(6253,17,385,6631,0),(6257,1,128,5,5),(6257,2,138,1,0),(6257,3,140,1,0),(6257,4,139,-2741,0),(6257,5,139,-16843,0),(6257,6,385,-16192,0),(6258,1,128,15,15),(6258,2,138,1,0),(6258,3,140,1,0),(6258,4,139,-2741,0),(6258,5,139,-16843,0),(6258,6,385,-16192,0),(6259,1,128,30,30),(6259,2,138,1,0),(6259,3,140,1,0),(6259,4,139,-2741,0),(6259,5,139,-16843,0),(6259,6,385,-16192,0),(6260,1,264,720,98),(6261,1,264,900,98),(6262,1,264,1080,98),(6266,1,224,20,10),(6266,2,173,1,0),(6267,1,224,35,10),(6267,2,173,2,0),(6268,1,224,50,10),(6268,2,173,3,0),(6269,1,224,20,30),(6269,2,173,1,0),(6270,1,224,35,30),(6270,2,173,2,0),(6271,1,224,50,30),(6271,2,173,3,0),(6272,1,264,15,672),(6273,1,264,30,672),(6274,1,264,45,672),(6275,1,224,20,8),(6275,2,173,1,0),(6276,1,224,35,8),(6276,2,173,2,0),(6277,1,224,50,8),(6277,2,173,3,0),(6283,1,85,13200,0),(6284,1,85,13200,25),(6285,1,85,13200,50),(6287,1,224,20,30),(6287,2,173,1,0),(6288,1,224,35,30),(6288,2,173,3,0),(6289,1,224,50,30),(6289,2,173,3,0),(6300,1,247,20,76),(6301,1,247,25,76),(6302,1,264,120,3710),(6303,1,264,240,3710),(6304,1,264,360,3710),(6319,1,264,1728,107),(6320,1,264,2160,107),(6321,1,264,2592,107),(6322,1,216,5,51),(6323,1,216,15,51),(6324,1,216,25,51),(6331,1,252,70,0),(6332,1,252,75,0),(6334,1,185,5,51),(6335,1,185,10,51),(6336,1,185,15,51),(6337,1,264,60,553),(6338,1,264,120,553),(6339,1,264,180,553),(6340,1,264,180,777),(6341,1,264,360,777),(6342,1,264,540,777),(6343,1,264,5,468),(6343,2,264,5,469),(6343,3,264,5,470),(6344,1,264,10,468),(6344,2,264,10,469),(6344,3,264,10,470),(6345,1,264,15,468),(6345,2,264,15,469),(6345,3,264,15,470),(6346,1,264,180,494),(6347,1,264,360,494),(6348,1,264,540,494),(6349,1,264,180,500),(6350,1,264,360,500),(6351,1,264,540,500),(6355,1,310,360000,0),(6355,2,139,4506,0),(6355,3,310,360000,0),(6355,4,385,11122,0),(6355,5,385,11222,0),(6355,6,385,11322,0),(6355,7,385,11522,0),(6356,1,310,720000,0),(6356,2,139,4506,0),(6356,3,310,720000,0),(6356,4,385,11122,0),(6356,5,385,11222,0),(6356,6,385,11322,0),(6356,7,385,11522,0),(6357,1,310,1080000,0),(6357,2,139,4506,0),(6357,3,310,1080000,0),(6357,4,385,11122,0),(6357,5,385,11222,0),(6357,6,385,11322,0),(6357,7,385,11522,0),(6358,1,310,1440000,0),(6358,2,139,4506,0),(6358,3,310,1440000,0),(6358,4,385,11122,0),(6358,5,385,11222,0),(6358,6,385,11322,0),(6358,7,385,11522,0),(6359,1,310,1800000,0),(6359,2,139,4506,0),(6359,3,310,1800000,0),(6359,4,385,11122,0),(6359,5,385,11222,0),(6359,6,385,11322,0),(6359,7,385,11522,0),(6360,1,310,2160000,0),(6360,2,139,4506,0),(6360,3,310,2160000,0),(6360,4,385,11122,0),(6360,5,385,11222,0),(6360,6,385,11322,0),(6360,7,385,11522,0),(6361,1,213,3,0),(6362,1,310,120000,0),(6362,2,139,5040,0),(6363,1,310,240000,0),(6363,2,139,5040,0),(6364,1,310,360000,0),(6364,2,139,5040,0),(6365,1,310,480000,0),(6365,2,139,5040,0),(6366,1,310,600000,0),(6366,2,139,5040,0),(6375,1,375,107,0),(6376,1,375,115,0),(6377,1,375,125,0),(6383,1,215,5,0),(6384,1,215,7,0),(6385,1,215,10,0),(6386,1,293,5,0),(6387,1,293,10,0),(6388,1,293,15,0),(6389,1,293,20,0),(6390,1,0,16,0),(6391,1,0,17,0),(6392,1,0,18,0),(6393,1,0,19,0),(6394,1,0,20,0),(6395,1,85,13502,0),(6396,1,85,13503,0),(6397,1,85,13504,0),(6403,1,294,11,100),(6404,1,294,13,100),(6405,1,294,15,100),(6406,1,360,25,13201),(6407,1,360,25,13202),(6408,1,360,25,13203),(6409,1,247,5,76),(6410,1,247,10,76),(6411,1,247,15,76),(6412,1,247,20,76),(6413,1,247,25,76),(6414,1,247,30,76),(6415,1,247,35,76),(6416,1,247,40,76),(6417,1,247,45,76),(6418,1,247,50,76),(6419,1,247,5,76),(6420,1,247,10,76),(6421,1,247,15,76),(6422,1,214,100,0),(6423,1,214,200,0),(6424,1,214,300,0),(6428,1,320,1,0),(6429,1,320,3,0),(6430,1,320,5,0),(6431,1,317,6,0),(6432,1,317,7,0),(6433,1,317,8,0),(6434,1,317,9,0),(6435,1,317,10,0),(6436,1,244,70,0),(6437,1,244,60,0),(6438,1,244,50,0),(6439,1,264,720,41),(6440,1,264,900,41),(6441,1,264,840,420),(6442,1,264,540,362),(6443,1,264,630,362),(6445,1,127,15,0),(6445,2,139,3248,0),(6445,3,127,15,0),(6445,4,139,3249,0),(6446,1,127,30,0),(6446,2,139,3248,0),(6446,3,127,30,0),(6446,4,139,3249,0),(6447,1,127,50,0),(6447,2,139,3248,0),(6447,3,127,50,0),(6447,4,139,3249,0),(6452,1,310,1000,0),(6452,2,403,7,0),(6452,3,404,35,0),(6452,4,144,2000,0),(6452,5,310,5000,0),(6452,6,403,7,0),(6452,7,404,35,0),(6452,8,144,10000,0),(6453,1,310,2000,0),(6453,2,403,7,0),(6453,3,404,35,0),(6453,4,144,2000,0),(6453,5,310,10000,0),(6453,6,403,7,0),(6453,7,404,35,0),(6453,8,144,10000,0),(6454,1,310,3000,0),(6454,2,403,7,0),(6454,3,404,35,0),(6454,4,144,2000,0),(6454,5,310,15000,0),(6454,6,403,7,0),(6454,7,404,35,0),(6454,8,144,10000,0),(6458,1,310,30000,0),(6458,2,385,5137,0),(6458,3,385,5237,0),(6458,4,385,5337,0),(6458,5,385,5437,0),(6458,6,385,5537,0),(6458,7,385,5637,0),(6458,8,127,15,15),(6458,9,385,5137,0),(6458,10,385,5237,0),(6458,11,385,5337,0),(6458,12,385,5437,0),(6458,13,385,5537,0),(6458,14,385,5637,0),(6459,1,310,60000,0),(6459,2,385,5137,0),(6459,3,385,5237,0),(6459,4,385,5337,0),(6459,5,385,5437,0),(6459,6,385,5537,0),(6459,7,385,5637,0),(6459,8,127,30,30),(6459,9,385,5137,0),(6459,10,385,5237,0),(6459,11,385,5337,0),(6459,12,385,5437,0),(6459,13,385,5537,0),(6459,14,385,5637,0),(6460,1,310,90000,0),(6460,2,385,5137,0),(6460,3,385,5237,0),(6460,4,385,5337,0),(6460,5,385,5437,0),(6460,6,385,5537,0),(6460,7,385,5637,0),(6460,8,127,50,50),(6460,9,385,5137,0),(6460,10,385,5237,0),(6460,11,385,5337,0),(6460,12,385,5437,0),(6460,13,385,5537,0),(6460,14,385,5637,0),(6461,1,127,15,0),(6461,2,385,14130,0),(6461,3,385,14230,0),(6461,4,385,14330,0),(6461,5,385,14430,0),(6461,6,385,14530,0),(6461,7,385,14630,0),(6461,8,310,30000,0),(6461,9,385,14130,0),(6461,10,385,14230,0),(6461,11,385,14330,0),(6461,12,385,14430,0),(6461,13,385,14530,0),(6461,14,385,14630,0),(6462,1,127,30,0),(6462,2,385,14130,0),(6462,3,385,14230,0),(6462,4,385,14330,0),(6462,5,385,14430,0),(6462,6,385,14530,0),(6462,7,385,14630,0),(6462,8,310,60000,0),(6462,9,385,14130,0),(6462,10,385,14230,0),(6462,11,385,14330,0),(6462,12,385,14430,0),(6462,13,385,14530,0),(6462,14,385,14630,0),(6463,1,127,50,0),(6463,2,385,14130,0),(6463,3,385,14230,0),(6463,4,385,14330,0),(6463,5,385,14430,0),(6463,6,385,14530,0),(6463,7,385,14630,0),(6463,8,310,90000,0),(6463,9,385,14130,0),(6463,10,385,14230,0),(6463,11,385,14330,0),(6463,12,385,14430,0),(6463,13,385,14530,0),(6463,14,385,14630,0),(6467,1,214,100,0),(6468,1,214,200,0),(6469,1,214,300,0),(6470,1,247,15,76),(6471,1,247,20,76),(6472,1,247,30,76),(6473,1,247,35,76),(6474,1,247,55,76),(6475,1,247,60,76),(6476,1,247,20,76),(6477,1,247,25,76),(6478,1,264,1,3800),(6479,1,264,2,3800),(6480,1,264,3,3800),(6481,1,264,6480,36),(6482,1,264,12960,36),(6483,1,264,19440,36),(6484,1,264,105,558),(6485,1,264,120,558),(6486,1,264,135,558),(6489,1,310,600000,0),(6489,2,139,4500,0),(6489,3,411,8,0),(6490,1,310,1200000,0),(6490,2,139,4500,0),(6490,3,411,8,0),(6491,1,310,1800000,0),(6491,2,139,4500,0),(6491,3,411,8,0),(6500,1,273,5,0),(6501,1,273,6,0),(6502,1,273,7,0),(6503,1,127,12,0),(6503,2,385,3338,0),(6504,1,127,24,0),(6504,2,385,3338,0),(6505,1,127,36,0),(6505,2,385,3338,0),(6506,1,127,50,0),(6506,2,385,3338,0),(6511,1,216,5,7),(6512,1,216,15,7),(6513,1,216,25,7),(6514,1,127,15,0),(6514,2,139,5880,0),(6515,1,127,30,0),(6515,2,139,5880,0),(6516,1,127,50,0),(6516,2,139,5880,0),(6517,1,339,10,8105),(6517,2,142,65,0),(6517,3,311,0,0),(6517,4,134,70,0),(6517,5,348,10,0),(6517,6,137,0,0),(6517,7,339,10,8105),(6517,8,142,65,0),(6517,9,311,0,0),(6517,10,134,70,0),(6517,11,348,10,0),(6517,12,137,100,0),(6517,13,339,10,8105),(6517,14,142,65,0),(6517,15,311,0,0),(6517,16,134,70,0),(6517,17,348,10,0),(6517,18,137,79,0),(6517,19,339,10,8105),(6517,20,142,65,0),(6517,21,311,0,0),(6517,22,134,70,0),(6517,23,348,10,0),(6517,24,137,147,0),(6517,25,339,10,11404),(6517,26,142,71,0),(6517,27,311,0,0),(6517,28,134,75,0),(6517,29,348,10,0),(6517,30,137,0,0),(6517,31,339,10,11404),(6517,32,142,71,0),(6517,33,311,0,0),(6517,34,134,75,0),(6517,35,348,10,0),(6517,36,137,100,0),(6517,37,339,10,11404),(6517,38,142,71,0),(6517,39,311,0,0),(6517,40,134,75,0),(6517,41,348,10,0),(6517,42,137,79,0),(6517,43,339,10,11404),(6517,44,142,71,0),(6517,45,311,0,0),(6517,46,134,75,0),(6517,47,348,10,0),(6517,48,137,147,0),(6517,49,339,10,13199),(6517,50,142,76,0),(6517,51,311,0,0),(6517,52,134,80,0),(6517,53,348,10,0),(6517,54,137,0,0),(6517,55,339,10,13199),(6517,56,142,76,0),(6517,57,311,0,0),(6517,58,134,80,0),(6517,59,348,10,0),(6517,60,137,100,0),(6517,61,339,10,13199),(6517,62,142,76,0),(6517,63,311,0,0),(6517,64,134,80,0),(6517,65,348,10,0),(6517,66,137,79,0),(6517,67,339,10,13199),(6517,68,142,76,0),(6517,69,311,0,0),(6517,70,134,80,0),(6517,71,348,10,0),(6517,72,137,147,0),(6518,1,221,18,0),(6519,1,221,21,0),(6520,1,221,24,0),(6521,1,327,6,0),(6522,1,327,7,0),(6523,1,328,800,0),(6524,1,328,850,0),(6525,1,328,900,0),(6526,1,328,950,0),(6527,1,328,1000,0),(6528,1,264,3024,107),(6531,1,360,40,11629),(6532,1,360,50,11629),(6533,1,360,60,11629),(6540,1,363,2,0),(6545,1,362,2,0),(6546,1,2,4,0),(6547,1,2,8,0),(6548,1,2,12,0),(6549,1,2,16,0),(6550,1,2,20,0),(6551,1,2,24,0),(6552,1,2,28,0),(6553,1,2,32,0),(6554,1,2,36,0),(6555,1,2,40,0),(6556,1,2,44,0),(6557,1,2,48,0),(6558,1,2,52,0),(6559,1,2,56,0),(6560,1,2,60,0),(6561,1,2,64,0),(6562,1,2,68,0),(6563,1,2,72,0),(6564,1,2,76,0),(6565,1,2,80,0),(6566,1,2,84,0),(6567,1,2,88,0),(6568,1,2,92,0),(6569,1,2,96,0),(6570,1,2,100,0),(6571,1,2,104,0),(6601,1,339,5,13519),(6601,2,137,21,0),(6602,1,339,10,13519),(6602,2,137,21,0),(6603,1,339,15,13519),(6603,2,137,21,0),(6604,1,339,20,13519),(6604,2,137,21,0),(6605,1,339,25,13519),(6605,2,137,21,0),(6611,1,310,120000,0),(6611,2,139,4670,0),(6612,1,310,240000,0),(6612,2,139,4670,0),(6613,1,310,360000,0),(6613,2,139,4670,0),(6614,1,310,120000,0),(6614,2,139,4674,0),(6615,1,310,240000,0),(6615,2,139,4674,0),(6616,1,310,360000,0),(6616,2,139,4674,0),(6618,1,310,480000,0),(6618,2,139,4670,0),(6619,1,310,600000,0),(6619,2,139,4670,0),(6630,1,218,1,0),(6631,1,218,2,0),(6632,1,218,3,0),(6633,1,218,4,0),(6634,1,218,5,0),(6636,1,294,0,107),(6637,1,294,0,115),(6638,1,294,0,125),(6641,1,339,10,16101),(6641,2,138,0,0),(6641,3,142,70,0),(6641,4,403,4,0),(6641,5,348,1,0),(6641,6,404,2,0),(6641,7,141,1,0),(6642,1,339,10,16102),(6642,2,138,0,0),(6642,3,142,70,0),(6642,4,403,4,0),(6642,5,348,1,0),(6642,6,404,2,0),(6642,7,141,1,0),(6643,1,339,10,16103),(6643,2,138,0,0),(6643,3,142,70,0),(6643,4,403,4,0),(6643,5,348,1,0),(6643,6,404,2,0),(6643,7,141,1,0),(6660,1,325,55,0),(6661,1,325,60,0),(6662,1,325,65,0),(6666,1,287,2,0),(6666,2,139,8001,0),(6666,3,385,12529,0),(6667,1,287,4,0),(6667,2,139,8001,0),(6667,3,385,12529,0),(6668,1,287,2,0),(6668,2,139,11251,0),(6668,3,139,11252,0),(6668,4,139,11253,0),(6669,1,287,4,0),(6669,2,139,11251,0),(6669,3,139,11252,0),(6669,4,139,11253,0),(6670,1,287,6,0),(6670,2,139,11251,0),(6670,3,139,11252,0),(6670,4,139,11253,0),(6697,1,264,30,857),(6698,1,264,60,857),(6699,1,264,90,857),(6700,1,264,120,857),(6701,1,264,150,857),(6703,1,264,10,171),(6704,1,264,20,171),(6705,1,264,30,171),(6709,1,127,5,0),(6709,2,139,3842,0),(6710,1,127,10,0),(6710,2,139,3842,0),(6711,1,127,15,0),(6711,2,139,3842,0),(6712,1,264,30,177),(6713,1,264,60,177),(6714,1,264,90,177),(6715,1,264,120,177),(6716,1,264,150,177),(6751,1,310,240000,0),(6751,2,139,4519,0),(6752,1,310,480000,0),(6752,2,139,4519,0),(6753,1,310,720000,0),(6753,2,139,4519,0),(6761,1,292,5,0),(6762,1,292,10,0),(6763,1,292,15,0),(6765,1,330,15,7),(6766,1,330,30,7),(6767,1,330,50,7),(6768,1,310,960000,0),(6768,2,139,4519,0),(6769,1,310,1200000,0),(6769,2,139,4519,0),(6791,1,339,20,16139),(6791,2,137,21,0),(6791,3,385,-18000,0),(6791,4,339,20,16139),(6791,5,137,343,0),(6791,6,385,-18000,0),(6792,1,339,20,16140),(6792,2,137,21,0),(6792,3,385,-18000,0),(6792,4,339,20,16140),(6792,5,137,343,0),(6792,6,385,-18000,0),(6793,1,339,20,16141),(6793,2,137,21,0),(6793,3,385,-18000,0),(6793,4,339,20,16141),(6793,5,137,343,0),(6793,6,385,-18000,0),(6819,1,264,180,524),(6820,1,264,360,524),(6821,1,264,540,524),(6823,1,264,180,320),(6824,1,264,360,320),(6825,1,264,540,320),(6826,1,264,720,320),(6827,1,264,900,320),(6870,1,264,180,544),(6871,1,264,360,544),(6872,1,264,540,544),(6873,1,279,7,0),(6874,1,279,11,0),(6875,1,279,15,0),(6876,1,375,107,0),(6877,1,375,115,0),(6878,1,375,125,0),(6879,1,243,15,0),(6880,1,243,25,0),(6881,1,243,35,0),(6882,1,242,5,0),(6883,1,242,10,0),(6884,1,242,15,0),(6900,1,264,840,465),(6901,1,264,1140,465),(6902,1,264,1440,465),(6903,1,264,1740,465),(6904,1,264,2040,465),(6905,1,225,33,0),(6906,1,225,36,0),(6907,1,225,39,0),(6908,1,264,180,499),(6909,1,264,360,499),(6910,1,264,540,499),(6911,1,224,60,74),(6911,2,173,2,0),(6912,1,224,70,74),(6912,2,173,3,0),(6913,1,224,80,74),(6913,2,173,3,0),(6935,1,264,180,465),(6936,1,264,360,465),(6937,1,264,540,465),(6938,1,361,65,16164),(6939,1,361,75,16165),(6940,1,361,85,16166),(6941,1,264,120,962),(6942,1,264,240,962),(6943,1,264,360,962),(6944,1,264,480,962),(6945,1,264,600,962),(6974,1,264,3,247),(6974,2,264,2,986),(6974,3,264,2,987),(6974,4,264,2,988),(6975,1,264,6,247),(6975,2,264,4,986),(6975,3,264,4,987),(6975,4,264,4,988),(6976,1,264,12,247),(6976,2,264,6,986),(6976,3,264,6,987),(6976,4,264,6,988),(6977,1,264,6,3817),(6978,1,264,12,3817),(6979,1,264,18,3817),(6980,1,264,45,128),(6981,1,264,90,128),(6982,1,264,135,128),(6987,1,353,1,0),(6988,1,287,1,0),(6988,2,385,16439,0),(6988,3,411,32768,0),(6989,1,287,2,0),(6989,2,385,16439,0),(6989,3,411,32768,0),(6990,1,287,3,0),(6990,2,385,16439,0),(6990,3,411,32768,0),(7005,1,264,432,789),(7006,1,264,864,789),(7007,1,264,1296,789),(7008,1,439,0,109400),(7008,2,345,80,35),(7009,1,439,0,116800),(7009,2,345,82,35),(7010,1,378,25,96),(7011,1,378,30,96),(7012,1,378,35,96),(7013,1,378,40,96),(7014,1,378,45,96),(7015,1,378,50,96),(7033,1,421,5,0),(7033,2,139,16097,0),(7033,3,139,23612,0),(7033,4,139,32196,0),(7033,5,139,32565,0),(7033,6,423,6,0),(7033,7,422,5,0),(7033,8,411,2,0),(7034,1,421,10,0),(7034,2,139,16097,0),(7034,3,139,23612,0),(7034,4,139,32196,0),(7034,5,139,32565,0),(7034,6,423,6,0),(7034,7,422,5,0),(7034,8,411,2,0),(7035,1,421,15,0),(7035,2,139,16097,0),(7035,3,139,23612,0),(7035,4,139,32196,0),(7035,5,139,32565,0),(7035,6,423,6,0),(7035,7,422,5,0),(7035,8,411,2,0),(7036,1,264,10,3646),(7037,1,264,20,3646),(7038,1,264,30,3646),(7050,1,265,62,0),(7051,1,265,64,0),(7052,1,265,66,0),(7053,1,265,67,0),(7054,1,265,69,0),(7055,1,265,71,0),(7056,1,265,62,0),(7057,1,265,64,0),(7058,1,265,66,0),(7059,1,265,67,0),(7060,1,265,69,0),(7061,1,265,71,0),(7062,1,372,50,0),(7063,1,265,72,0),(7064,1,265,74,0),(7065,1,265,76,0),(7066,1,265,72,0),(7067,1,265,74,0),(7068,1,265,76,0),(7100,1,264,180,254),(7101,1,264,360,254),(7102,1,264,540,254),(7103,1,264,432,286),(7103,2,264,432,10753),(7103,3,264,432,9101),(7104,1,264,864,286),(7104,2,264,864,10753),(7104,3,264,864,9101),(7105,1,264,1296,286),(7105,2,264,1296,10753),(7105,3,264,1296,9101),(7106,1,224,20,30),(7106,2,173,1,0),(7107,1,224,35,30),(7107,2,173,2,0),(7108,1,224,50,30),(7108,2,173,3,0),(7112,1,85,13596,50),(7113,1,85,13597,50),(7114,1,85,13598,50),(7116,1,264,360,110),(7117,1,264,450,110),(7118,1,264,540,110),(7122,1,349,30,0),(7123,1,349,35,0),(7124,1,349,40,0),(7125,1,349,45,0),(7126,1,349,50,0),(7128,1,264,240,109),(7129,1,264,300,109),(7130,1,264,360,109),(7131,1,439,0,88880),(7131,2,345,74,28),(7132,1,439,0,95440),(7132,2,345,76,28),(7133,1,439,0,102280),(7133,2,345,78,28),(7134,1,220,120,8),(7135,1,220,140,8),(7136,1,220,165,8),(7137,1,264,60,672),(7138,1,264,75,672),(7139,1,264,90,672),(7146,1,252,80,0),(7147,1,252,85,0),(7148,1,216,350,8),(7149,1,216,400,8),(7150,1,216,450,8),(7151,1,258,59,0),(7152,1,258,64,0),(7153,1,258,69,0),(7160,1,227,120,32),(7161,1,227,150,32),(7162,1,227,180,32),(7163,1,220,130,26),(7163,2,220,130,30),(7163,3,220,130,38),(7164,1,220,140,26),(7164,2,220,140,30),(7164,3,220,140,38),(7165,1,220,150,26),(7165,2,220,150,30),(7165,3,220,150,38),(7166,1,264,20,468),(7166,2,264,20,469),(7166,3,264,20,470),(7167,1,264,25,468),(7167,2,264,25,469),(7167,3,264,25,470),(7168,1,264,30,468),(7168,2,264,30,469),(7168,3,264,30,470),(7169,1,220,135,21),(7169,2,220,135,23),(7169,3,220,270,52),(7169,4,220,135,28),(7170,1,220,145,21),(7170,2,220,145,23),(7170,3,220,290,52),(7170,4,220,145,28),(7171,1,220,155,21),(7171,2,220,155,23),(7171,3,220,310,52),(7171,4,220,155,28),(7175,1,283,120,0),(7176,1,283,140,0),(7177,1,283,160,0),(7196,1,169,20,-1),(7197,1,169,25,-1),(7198,1,169,30,-1),(7204,1,218,11,0),(7205,1,218,12,0),(7206,1,218,13,0),(7207,1,218,14,0),(7208,1,218,15,0),(7210,1,280,50,0),(7211,1,280,53,0),(7212,1,280,56,0),(7213,1,280,59,0),(7214,1,280,62,0),(7215,1,264,4200,68),(7216,1,264,4800,68),(7220,1,360,60,12701),(7221,1,360,60,12702),(7222,1,360,60,12703),(7232,1,294,0,185),(7233,1,294,0,190),(7234,1,294,0,195),(7260,1,287,14,0),(7260,2,385,2754,1),(7261,1,287,16,0),(7261,2,385,2754,1),(7262,1,287,18,0),(7262,2,385,2754,1),(7263,1,274,18,0),(7264,1,274,20,0),(7265,1,274,22,0),(7267,1,280,54,0),(7268,1,280,55,0),(7269,1,280,56,0),(7270,1,218,16,0),(7271,1,218,17,0),(7272,1,218,18,0),(7273,1,218,19,0),(7274,1,218,20,0),(7279,1,310,6000,0),(7279,2,139,11903,0),(7279,3,310,6000,0),(7279,4,139,11904,0),(7279,5,310,6000,0),(7279,6,139,11905,0),(7279,7,310,6000,0),(7279,8,139,1362,0),(7279,9,310,6000,0),(7279,10,139,8032,0),(7279,11,310,6000,0),(7279,12,385,6131,0),(7279,13,385,6231,0),(7279,14,385,6331,0),(7279,15,385,6431,0),(7279,16,385,6531,0),(7279,17,385,6631,0),(7280,1,310,7000,0),(7280,2,139,11903,0),(7280,3,310,7000,0),(7280,4,139,11904,0),(7280,5,310,7000,0),(7280,6,139,11905,0),(7280,7,310,7000,0),(7280,8,139,1362,0),(7280,9,310,7000,0),(7280,10,139,8032,0),(7280,11,310,7000,0),(7280,12,385,6131,0),(7280,13,385,6231,0),(7280,14,385,6331,0),(7280,15,385,6431,0),(7280,16,385,6531,0),(7280,17,385,6631,0),(7281,1,310,8000,0),(7281,2,139,11903,0),(7281,3,310,8000,0),(7281,4,139,11904,0),(7281,5,310,8000,0),(7281,6,139,11905,0),(7281,7,310,8000,0),(7281,8,139,1362,0),(7281,9,310,8000,0),(7281,10,139,8032,0),(7281,11,310,8000,0),(7281,12,385,6131,0),(7281,13,385,6231,0),(7281,14,385,6331,0),(7281,15,385,6431,0),(7281,16,385,6531,0),(7281,17,385,6631,0),(7282,1,310,9000,0),(7282,2,139,11903,0),(7282,3,310,9000,0),(7282,4,139,11904,0),(7282,5,310,9000,0),(7282,6,139,11905,0),(7282,7,310,9000,0),(7282,8,139,1362,0),(7282,9,310,9000,0),(7282,10,139,8032,0),(7282,11,310,9000,0),(7282,12,385,6131,0),(7282,13,385,6231,0),(7282,14,385,6331,0),(7282,15,385,6431,0),(7282,16,385,6531,0),(7282,17,385,6631,0),(7283,1,310,10000,0),(7283,2,139,11903,0),(7283,3,310,10000,0),(7283,4,139,11904,0),(7283,5,310,10000,0),(7283,6,139,11905,0),(7283,7,310,10000,0),(7283,8,139,1362,0),(7283,9,310,10000,0),(7283,10,139,8032,0),(7283,11,310,10000,0),(7283,12,385,6131,0),(7283,13,385,6231,0),(7283,14,385,6331,0),(7283,15,385,6431,0),(7283,16,385,6531,0),(7283,17,385,6631,0),(7284,1,287,3,0),(7284,2,137,31,0),(7284,3,136,5,0),(7313,1,244,40,0),(7314,1,244,30,0),(7315,1,244,20,0),(7316,1,264,1080,41),(7317,1,264,1260,41),(7318,1,339,25,16015),(7318,2,137,21,0),(7319,1,339,25,16016),(7319,2,137,21,0),(7320,1,339,25,16017),(7320,2,137,21,0),(7321,1,339,25,16018),(7321,2,137,21,0),(7322,1,339,25,16019),(7322,2,137,21,0),(7323,1,264,720,254),(7324,1,264,900,254),(7325,1,264,1080,254),(7326,1,264,1728,286),(7326,2,264,1728,10753),(7326,3,264,1728,9101),(7327,1,264,2160,286),(7327,2,264,2160,10753),(7327,3,264,2160,9101),(7328,1,264,2592,286),(7328,2,264,2592,10753),(7328,3,264,2592,9101),(7336,1,85,16029,0),(7337,1,85,16030,0),(7338,1,85,16031,0),(7353,1,216,115,0),(7353,2,216,115,1),(7353,3,216,115,2),(7353,4,216,115,3),(7353,5,216,115,10),(7353,6,216,115,28),(7353,7,216,115,30),(7353,8,216,115,36),(7353,9,216,115,77),(7354,1,216,120,0),(7354,2,216,120,1),(7354,3,216,120,2),(7354,4,216,120,3),(7354,5,216,120,10),(7354,6,216,120,28),(7354,7,216,120,30),(7354,8,216,120,36),(7354,9,216,120,77),(7355,1,216,125,0),(7355,2,216,125,1),(7355,3,216,125,2),(7355,4,216,125,3),(7355,5,216,125,10),(7355,6,216,125,28),(7355,7,216,125,30),(7355,8,216,125,36),(7355,9,216,125,77),(7356,1,360,60,16056),(7357,1,360,60,16057),(7358,1,360,60,16058),(7359,1,217,0,82600),(7359,2,346,78,22),(7360,1,217,0,88880),(7360,2,346,80,22),(7361,1,217,0,95440),(7361,2,346,82,22),(7362,1,59,-18,0),(7363,1,59,-21,0),(7364,1,59,-24,0),(7365,1,59,-27,0),(7366,1,59,-30,0),(7373,1,2,108,0),(7374,1,2,112,0),(7375,1,2,116,0),(7376,1,2,120,0),(7377,1,2,124,0),(7378,1,347,14,0),(7379,1,347,16,0),(7380,1,347,18,0),(7381,1,347,20,0),(7382,1,347,22,0),(7383,1,347,24,0),(7384,1,360,25,16063),(7385,1,360,25,16064),(7386,1,360,25,16065),(7390,1,303,6000,6000),(7390,2,139,2766,0),(7391,1,303,6500,6500),(7391,2,139,2766,0),(7392,1,303,7500,8500),(7392,2,139,2766,0),(7393,1,85,16066,0),(7394,1,85,16067,0),(7395,1,85,16068,0),(7396,1,85,16069,0),(7397,1,85,16070,0),(7398,1,85,16071,0),(7399,1,302,350,350),(7399,2,385,99,0),(7400,1,302,370,370),(7400,2,385,99,0),(7401,1,302,400,400),(7401,2,385,99,0),(7402,1,59,-33,0),(7403,1,59,-36,0),(7404,1,59,-39,0),(7405,1,59,-42,0),(7406,1,59,-45,0),(7407,1,181,100,-1),(7448,1,264,240,553),(7449,1,264,300,553),(7450,1,264,360,553),(7451,1,264,720,777),(7452,1,264,900,777),(7453,1,264,1080,777),(7478,1,264,2880,245),(7489,1,218,16,0),(7490,1,218,17,0),(7491,1,218,18,0),(7492,1,218,19,0),(7493,1,218,20,0),(7494,1,280,65,0),(7495,1,280,66,0),(7496,1,280,67,0),(7500,1,363,3,0),(7501,1,172,45,0),(7502,1,172,46,0),(7503,1,172,47,0),(7504,1,172,48,0),(7505,1,172,49,0),(7506,1,259,51,0),(7507,1,259,52,0),(7508,1,259,53,0),(7509,1,259,54,0),(7510,1,259,55,0),(7511,1,328,1050,0),(7512,1,328,1100,0),(7513,1,328,1150,0),(7514,1,328,1200,0),(7515,1,328,1250,0),(7516,1,262,30,7),(7516,2,262,30,8),(7516,3,262,30,9),(7516,4,262,30,10),(7516,5,262,30,11),(7517,1,262,35,7),(7517,2,262,35,8),(7517,3,262,35,9),(7517,4,262,35,10),(7517,5,262,35,11),(7518,1,262,40,7),(7518,2,262,40,8),(7518,3,262,40,9),(7518,4,262,40,10),(7518,5,262,40,11),(7519,1,262,45,7),(7519,2,262,45,8),(7519,3,262,45,9),(7519,4,262,45,10),(7519,5,262,45,11),(7520,1,262,50,7),(7520,2,262,50,8),(7520,3,262,50,9),(7520,4,262,50,10),(7520,5,262,50,11),(7521,1,317,11,0),(7522,1,317,12,0),(7523,1,317,13,0),(7524,1,317,14,0),(7525,1,317,15,0),(7526,1,69,600,0),(7527,1,69,700,0),(7528,1,69,800,0),(7529,1,69,900,0),(7530,1,69,1000,0),(7534,1,0,21,0),(7535,1,0,22,0),(7536,1,0,23,0),(7537,1,0,24,0),(7538,1,0,25,0),(7539,1,327,8,0),(7540,1,327,9,0),(7541,1,214,1100,0),(7542,1,214,1200,0),(7543,1,214,1300,0),(7544,1,221,27,0),(7545,1,221,30,0),(7546,1,221,33,0),(7547,1,262,80,0),(7547,2,262,80,1),(7547,3,262,80,2),(7547,4,262,80,3),(7547,5,262,80,4),(7547,6,262,80,5),(7547,7,262,80,6),(7548,1,262,85,0),(7548,2,262,85,1),(7548,3,262,85,2),(7548,4,262,85,3),(7548,5,262,85,4),(7548,6,262,85,5),(7548,7,262,85,6),(7549,1,262,90,0),(7549,2,262,90,1),(7549,3,262,90,2),(7549,4,262,90,3),(7549,5,262,90,4),(7549,6,262,90,5),(7549,7,262,90,6),(7550,1,262,95,0),(7550,2,262,95,1),(7550,3,262,95,2),(7550,4,262,95,3),(7550,5,262,95,4),(7550,6,262,95,5),(7550,7,262,95,6),(7551,1,262,100,0),(7551,2,262,100,1),(7551,3,262,100,2),(7551,4,262,100,3),(7551,5,262,100,4),(7551,6,262,100,5),(7551,7,262,100,6),(7553,1,326,3,0),(7554,1,339,20,16194),(7554,2,138,1,0),(7554,3,141,1,0),(7554,4,142,65,0),(7554,5,137,0,0),(7554,6,311,0,0),(7554,7,134,85,0),(7554,8,139,-265,0),(7554,9,139,-754,0),(7554,10,139,-1332,0),(7554,11,139,-1572,0),(7554,12,139,-2749,0),(7554,13,139,-4979,0),(7554,14,139,-5418,0),(7554,15,139,-5403,0),(7554,16,348,10,0),(7555,1,339,21,16195),(7555,2,138,1,0),(7555,3,141,1,0),(7555,4,142,65,0),(7555,5,137,0,0),(7555,6,311,0,0),(7555,7,134,85,0),(7555,8,139,-265,0),(7555,9,139,-754,0),(7555,10,139,-1332,0),(7555,11,139,-1572,0),(7555,12,139,-2749,0),(7555,13,139,-4979,0),(7555,14,139,-5418,0),(7555,15,139,-5403,0),(7555,16,348,10,0),(7556,1,339,22,16196),(7556,2,138,1,0),(7556,3,141,1,0),(7556,4,142,65,0),(7556,5,137,0,0),(7556,6,311,0,0),(7556,7,134,85,0),(7556,8,139,-265,0),(7556,9,139,-754,0),(7556,10,139,-1332,0),(7556,11,139,-1572,0),(7556,12,139,-2749,0),(7556,13,139,-4979,0),(7556,14,139,-5418,0),(7556,15,139,-5403,0),(7556,16,348,10,0),(7557,1,339,23,16417),(7557,2,138,1,0),(7557,3,141,1,0),(7557,4,142,65,0),(7557,5,137,0,0),(7557,6,311,0,0),(7557,7,134,85,0),(7557,8,139,-265,0),(7557,9,139,-754,0),(7557,10,139,-1332,0),(7557,11,139,-1572,0),(7557,12,139,-2749,0),(7557,13,139,-4979,0),(7557,14,139,-5418,0),(7557,15,139,-5403,0),(7557,16,348,10,0),(7558,1,339,24,16418),(7558,2,138,1,0),(7558,3,141,1,0),(7558,4,142,65,0),(7558,5,137,0,0),(7558,6,311,0,0),(7558,7,134,85,0),(7558,8,139,-265,0),(7558,9,139,-754,0),(7558,10,139,-1332,0),(7558,11,139,-1572,0),(7558,12,139,-2749,0),(7558,13,139,-4979,0),(7558,14,139,-5418,0),(7558,15,139,-5403,0),(7558,16,348,10,0),(7559,1,266,23,0),(7560,1,266,24,0),(7561,1,266,25,0),(7562,1,330,125,0),(7562,2,330,125,1),(7562,3,330,125,2),(7562,4,330,125,3),(7562,5,330,125,28),(7562,6,330,125,36),(7562,7,330,125,77),(7563,1,330,130,0),(7563,2,330,130,1),(7563,3,330,130,2),(7563,4,330,130,3),(7563,5,330,130,28),(7563,6,330,130,36),(7563,7,330,130,77),(7564,1,330,135,0),(7564,2,330,135,1),(7564,3,330,135,2),(7564,4,330,135,3),(7564,5,330,135,28),(7564,6,330,135,36),(7564,7,330,135,77),(7565,1,278,800,54510),(7565,2,440,76,100),(7566,1,278,850,58400),(7566,2,440,78,100),(7567,1,278,900,62680),(7567,2,440,80,100),(7568,1,341,160,0),(7569,1,341,170,0),(7570,1,341,180,0),(7571,1,341,190,0),(7572,1,341,200,0),(7573,1,360,70,11023),(7574,1,360,80,11023),(7575,1,360,90,11023),(7576,1,318,16,0),(7577,1,318,17,0),(7578,1,318,18,0),(7579,1,318,19,0),(7580,1,318,20,0),(7581,1,294,0,160),(7582,1,294,0,165),(7583,1,294,0,170),(7584,1,114,-60,0),(7585,1,114,-61,0),(7586,1,114,-62,0),(7587,1,319,22,0),(7588,1,319,23,0),(7589,1,319,24,0),(7590,1,274,35,0),(7591,1,274,36,0),(7592,1,274,37,0),(7593,1,15,14,0),(7594,1,15,15,0),(7595,1,15,16,0),(7596,1,15,17,0),(7597,1,15,18,0),(7598,1,114,-60,0),(7599,1,114,-61,0),(7600,1,114,-62,0),(7601,1,213,7,0),(7602,1,213,9,0),(7603,1,213,11,0),(7604,1,189,14,0),(7605,1,189,15,0),(7612,1,270,70,0),(7613,1,270,75,0),(7614,1,270,80,0),(7615,1,264,720,494),(7616,1,264,900,494),(7617,1,264,1080,494),(7618,1,264,720,500),(7619,1,264,900,500),(7620,1,264,1080,500),(7621,1,339,10,8105),(7621,2,142,65,0),(7621,3,311,0,0),(7621,4,134,70,0),(7621,5,348,10,0),(7621,6,137,0,0),(7621,7,339,10,8105),(7621,8,142,65,0),(7621,9,311,0,0),(7621,10,134,70,0),(7621,11,348,10,0),(7621,12,137,100,0),(7621,13,339,10,8105),(7621,14,142,65,0),(7621,15,311,0,0),(7621,16,134,70,0),(7621,17,348,10,0),(7621,18,137,79,0),(7621,19,339,10,8105),(7621,20,142,65,0),(7621,21,311,0,0),(7621,22,134,70,0),(7621,23,348,10,0),(7621,24,137,147,0),(7621,25,339,10,11404),(7621,26,142,71,0),(7621,27,311,0,0),(7621,28,134,75,0),(7621,29,348,10,0),(7621,30,137,0,0),(7621,31,339,10,11404),(7621,32,142,71,0),(7621,33,311,0,0),(7621,34,134,75,0),(7621,35,348,10,0),(7621,36,137,100,0),(7621,37,339,10,11404),(7621,38,142,71,0),(7621,39,311,0,0),(7621,40,134,75,0),(7621,41,348,10,0),(7621,42,137,79,0),(7621,43,339,10,11404),(7621,44,142,71,0),(7621,45,311,0,0),(7621,46,134,75,0),(7621,47,348,10,0),(7621,48,137,147,0),(7621,49,339,10,13199),(7621,50,142,76,0),(7621,51,311,0,0),(7621,52,134,80,0),(7621,53,348,10,0),(7621,54,137,0,0),(7621,55,339,10,13199),(7621,56,142,76,0),(7621,57,311,0,0),(7621,58,134,80,0),(7621,59,348,10,0),(7621,60,137,100,0),(7621,61,339,10,13199),(7621,62,142,76,0),(7621,63,311,0,0),(7621,64,134,80,0),(7621,65,348,10,0),(7621,66,137,79,0),(7621,67,339,10,13199),(7621,68,142,76,0),(7621,69,311,0,0),(7621,70,134,80,0),(7621,71,348,10,0),(7621,72,137,147,0),(7621,73,339,10,13830),(7621,74,142,81,0),(7621,75,311,0,0),(7621,76,134,85,0),(7621,77,348,10,0),(7621,78,137,0,0),(7621,79,339,10,13830),(7621,80,142,81,0),(7621,81,311,0,0),(7621,82,134,85,0),(7621,83,348,10,0),(7621,84,137,100,0),(7621,85,339,10,13830),(7621,86,142,81,0),(7621,87,311,0,0),(7621,88,134,85,0),(7621,89,348,10,0),(7621,90,137,79,0),(7621,91,339,10,13830),(7621,92,142,81,0),(7621,93,311,0,0),(7621,94,134,85,0),(7621,95,348,10,0),(7621,96,137,147,0),(7622,1,265,79,0),(7623,1,265,80,0),(7624,1,265,81,0),(7625,1,265,79,0),(7626,1,265,80,0),(7627,1,265,81,0),(7628,1,292,46,0),(7629,1,292,47,0),(7630,1,292,48,0),(7631,1,279,34,0),(7632,1,279,35,0),(7633,1,279,36,0),(7634,1,279,34,0),(7635,1,279,35,0),(7636,1,279,36,0),(7637,1,279,34,0),(7638,1,279,35,0),(7639,1,279,36,0),(7640,1,200,60,0),(7641,1,294,17,100),(7642,1,294,19,100),(7643,1,294,21,100),(7644,1,375,130,0),(7645,1,375,135,0),(7646,1,375,140,0),(7647,1,229,20,0),(7648,1,229,25,0),(7649,1,229,30,0),(7650,1,330,125,0),(7650,2,330,125,1),(7650,3,330,125,2),(7650,4,330,125,3),(7650,5,330,125,28),(7650,6,330,125,36),(7651,1,330,130,0),(7651,2,330,130,1),(7651,3,330,130,2),(7651,4,330,130,3),(7651,5,330,130,28),(7651,6,330,130,36),(7652,1,330,135,0),(7652,2,330,135,1),(7652,3,330,135,2),(7652,4,330,135,3),(7652,5,330,135,28),(7652,6,330,135,36),(7653,1,330,125,0),(7653,2,330,125,1),(7653,3,330,125,2),(7653,4,330,125,3),(7653,5,330,125,28),(7653,6,330,125,36),(7653,7,330,125,77),(7654,1,330,130,0),(7654,2,330,130,1),(7654,3,330,130,2),(7654,4,330,130,3),(7654,5,330,130,28),(7654,6,330,130,36),(7654,7,330,130,77),(7655,1,330,135,0),(7655,2,330,135,1),(7655,3,330,135,2),(7655,4,330,135,3),(7655,5,330,135,28),(7655,6,330,135,36),(7655,7,330,135,77),(7656,1,330,100,0),(7656,2,330,100,1),(7656,3,330,100,2),(7656,4,330,100,3),(7656,5,330,100,28),(7656,6,330,100,36),(7656,7,330,100,77),(7657,1,330,105,0),(7657,2,330,105,1),(7657,3,330,105,2),(7657,4,330,105,3),(7657,5,330,105,28),(7657,6,330,105,36),(7657,7,330,105,77),(7658,1,330,110,0),(7658,2,330,110,1),(7658,3,330,110,2),(7658,4,330,110,3),(7658,5,330,110,28),(7658,6,330,110,36),(7658,7,330,110,77),(7659,1,264,72,153),(7660,1,264,90,153),(7661,1,264,108,153),(7663,1,375,150,0),(7664,1,264,10,170),(7665,1,264,20,170),(7666,1,264,30,170),(7667,1,264,40,170),(7668,1,264,50,170),(7670,1,229,35,0),(7671,1,229,40,0),(7672,1,229,45,0),(7673,1,220,50,10),(7674,1,220,65,10),(7675,1,220,80,10),(7676,1,220,95,10),(7677,1,220,110,10),(7678,1,231,11,0),(7679,1,231,13,0),(7680,1,231,15,0),(7681,1,326,4,0),(7682,1,264,5400,68),(7683,1,327,10,0),(7684,1,327,11,0),(7685,1,327,12,0),(7686,1,349,55,0),(7687,1,349,60,0),(7688,1,349,65,0),(7690,1,353,1,0),(7692,1,319,25,0),(7693,1,319,26,0),(7694,1,319,27,0),(7695,1,127,5,0),(7695,2,385,14232,0),(7696,1,127,10,0),(7696,2,385,14232,0),(7697,1,127,15,0),(7697,2,385,14232,0),(7699,1,181,100,0),(7700,1,279,7,0),(7701,1,279,11,0),(7702,1,279,15,0),(7704,1,264,540,3707),(7705,1,264,720,3707),(7706,1,264,900,3707),(7707,1,303,8500,9500),(7707,2,139,2766,0),(7708,1,303,9500,11000),(7708,2,139,2766,0),(7709,1,303,11000,14000),(7709,2,139,2766,0),(7713,1,274,34,0),(7714,1,274,36,0),(7715,1,264,2,901),(7716,1,264,4,901),(7717,1,264,6,901),(7718,1,281,90,0),(7722,1,339,25,23492),(7722,2,138,1,0),(7722,3,141,1,0),(7722,4,142,70,0),(7722,5,137,0,0),(7722,6,311,0,0),(7722,7,134,90,0),(7722,8,139,-265,0),(7722,9,139,-754,0),(7722,10,139,-1332,0),(7722,11,139,-1572,0),(7722,12,139,-2749,0),(7722,13,139,-4979,0),(7722,14,139,-5418,0),(7722,15,139,-5403,0),(7722,16,348,10,0),(7723,1,339,26,23493),(7723,2,138,1,0),(7723,3,141,1,0),(7723,4,142,70,0),(7723,5,137,0,0),(7723,6,311,0,0),(7723,7,134,90,0),(7723,8,139,-265,0),(7723,9,139,-754,0),(7723,10,139,-1332,0),(7723,11,139,-1572,0),(7723,12,139,-2749,0),(7723,13,139,-4979,0),(7723,14,139,-5418,0),(7723,15,139,-5403,0),(7723,16,348,10,0),(7724,1,339,27,23494),(7724,2,138,1,0),(7724,3,141,1,0),(7724,4,142,70,0),(7724,5,137,0,0),(7724,6,311,0,0),(7724,7,134,90,0),(7724,8,139,-265,0),(7724,9,139,-754,0),(7724,10,139,-1332,0),(7724,11,139,-1572,0),(7724,12,139,-2749,0),(7724,13,139,-4979,0),(7724,14,139,-5418,0),(7724,15,139,-5403,0),(7724,16,348,10,0),(7725,1,339,28,23495),(7725,2,138,1,0),(7725,3,141,1,0),(7725,4,142,70,0),(7725,5,137,0,0),(7725,6,311,0,0),(7725,7,134,90,0),(7725,8,139,-265,0),(7725,9,139,-754,0),(7725,10,139,-1332,0),(7725,11,139,-1572,0),(7725,12,139,-2749,0),(7725,13,139,-4979,0),(7725,14,139,-5418,0),(7725,15,139,-5403,0),(7725,16,348,10,0),(7726,1,339,29,23496),(7726,2,138,1,0),(7726,3,141,1,0),(7726,4,142,70,0),(7726,5,137,0,0),(7726,6,311,0,0),(7726,7,134,90,0),(7726,8,139,-265,0),(7726,9,139,-754,0),(7726,10,139,-1332,0),(7726,11,139,-1572,0),(7726,12,139,-2749,0),(7726,13,139,-4979,0),(7726,14,139,-5418,0),(7726,15,139,-5403,0),(7726,16,348,10,0),(7733,1,257,1,0),(7733,2,267,1,31),(7733,3,267,1,32),(7733,4,267,1,33),(7733,5,267,1,15),(7733,6,267,1,16),(7733,7,267,1,17),(7733,8,267,1,18),(7733,9,267,1,19),(7733,10,267,1,20),(7743,1,264,90,184),(7744,1,264,180,184),(7745,1,264,270,184),(7746,1,310,2000,0),(7746,2,385,11233,0),(7746,3,385,11333,0),(7746,4,411,16,0),(7748,1,271,5,0),(7749,1,271,10,0),(7750,1,271,15,0),(7751,1,264,60,2234),(7752,1,264,120,2234),(7753,1,264,180,2234),(7757,1,264,120,9403),(7758,1,264,240,9403),(7759,1,264,360,9403),(7760,1,264,2,824),(7761,1,264,4,824),(7762,1,264,6,824),(7763,1,310,4000,0),(7763,2,385,11233,0),(7763,3,385,11333,0),(7763,4,411,16,0),(7764,1,310,6000,0),(7764,2,385,11233,0),(7764,3,385,11333,0),(7764,4,411,16,0),(7765,1,392,1000,0),(7765,2,139,21820,0),(7765,3,411,4,0),(7766,1,392,2000,0),(7766,2,139,21820,0),(7766,3,411,4,0),(7767,1,392,3000,0),(7767,2,139,21820,0),(7767,3,411,4,0),(7768,1,392,4000,0),(7768,2,139,21820,0),(7768,3,411,4,0),(7818,1,288,200,51),(7818,2,288,50,51),(7819,1,405,7,0),(7820,1,405,9,0),(7821,1,405,11,0),(7822,1,264,1,1154),(7823,1,264,2,1154),(7824,1,264,3,1154),(7825,1,264,4,1154),(7826,1,264,5,1154),(7827,1,398,9000,0),(7827,2,385,7225,0),(7827,3,385,7325,0),(7827,4,385,7425,0),(7828,1,310,2000,0),(7828,2,385,7225,0),(7828,3,385,7325,0),(7828,4,385,7425,0),(7828,5,385,7525,0),(7828,6,385,7625,0),(7829,1,310,4000,0),(7829,2,385,7225,0),(7829,3,385,7325,0),(7829,4,385,7425,0),(7829,5,385,7525,0),(7829,6,385,7625,0),(7830,1,310,6000,0),(7830,2,385,7225,0),(7830,3,385,7325,0),(7830,4,385,7425,0),(7830,5,385,7525,0),(7830,6,385,7625,0),(7832,1,264,60,60),(7833,2,264,120,60),(7834,3,264,180,60),(7835,4,264,240,60),(7836,5,264,300,60),(7837,1,262,55,7),(7837,2,262,55,8),(7837,3,262,55,9),(7837,4,262,55,10),(7837,5,262,55,11),(7838,1,262,60,7),(7838,2,262,60,8),(7838,3,262,60,9),(7838,4,262,60,10),(7838,5,262,60,11),(7839,1,262,65,7),(7839,2,262,65,8),(7839,3,262,65,9),(7839,4,262,65,10),(7839,5,262,65,11),(7840,1,262,70,7),(7840,2,262,70,8),(7840,3,262,70,9),(7840,4,262,70,10),(7840,5,262,70,11),(7841,1,262,75,7),(7841,2,262,75,8),(7841,3,262,75,9),(7841,4,262,75,10),(7841,5,262,75,11),(7842,1,339,30,27695),(7842,2,138,1,0),(7842,3,141,1,0),(7842,4,142,70,0),(7842,5,137,0,0),(7842,6,311,0,0),(7842,7,134,100,0),(7842,8,139,-265,0),(7842,9,139,-754,0),(7842,10,139,-1332,0),(7842,11,139,-1572,0),(7842,12,139,-2749,0),(7842,13,139,-4979,0),(7842,14,139,-5418,0),(7842,15,139,-5403,0),(7842,16,348,10,0),(7843,1,339,31,27696),(7843,2,138,1,0),(7843,3,141,1,0),(7843,4,142,70,0),(7843,5,137,0,0),(7843,6,311,0,0),(7843,7,134,100,0),(7843,8,139,-265,0),(7843,9,139,-754,0),(7843,10,139,-1332,0),(7843,11,139,-1572,0),(7843,12,139,-2749,0),(7843,13,139,-4979,0),(7843,14,139,-5418,0),(7843,15,139,-5403,0),(7843,16,348,10,0),(7844,1,339,32,27697),(7844,2,138,1,0),(7844,3,141,1,0),(7844,4,142,70,0),(7844,5,137,0,0),(7844,6,311,0,0),(7844,7,134,100,0),(7844,8,139,-265,0),(7844,9,139,-754,0),(7844,10,139,-1332,0),(7844,11,139,-1572,0),(7844,12,139,-2749,0),(7844,13,139,-4979,0),(7844,14,139,-5418,0),(7844,15,139,-5403,0),(7844,16,348,10,0),(7881,1,405,13,0),(7882,1,405,15,0),(7883,1,405,17,0),(7884,1,287,1,0),(7884,2,139,4691,0),(7884,3,411,128,0),(7885,1,287,1,0),(7885,2,385,8111,0),(7885,3,385,15008,0),(7885,4,385,8411,0),(7885,5,385,8511,0),(7885,6,411,128,0),(7886,1,328,1300,0),(7887,1,328,1350,0),(7888,1,328,1400,0),(7889,1,328,1450,0),(7890,1,328,1500,0),(7900,1,339,45,16189),(7900,2,136,11,0),(7900,3,383,45,16189),(7900,4,385,11012,0),(7900,5,383,45,16189),(7900,6,385,5130,0),(7900,7,383,45,16189),(7900,8,385,5230,0),(7900,9,383,45,16189),(7900,10,136,22,0),(7900,11,383,45,16189),(7900,12,385,5330,0),(7900,13,385,5430,0),(7900,14,385,5530,0),(7901,1,339,45,16190),(7901,2,136,11,0),(7901,3,383,45,16190),(7901,4,385,11012,0),(7901,5,383,45,16190),(7901,6,385,5130,0),(7901,7,383,45,16190),(7901,8,385,5230,0),(7901,9,383,45,16190),(7901,10,136,22,0),(7901,11,383,45,16190),(7901,12,385,5330,0),(7901,13,385,5430,0),(7901,14,385,5530,0),(7902,1,339,45,16191),(7902,2,136,11,0),(7902,3,383,45,16191),(7902,4,385,11012,0),(7902,5,383,45,16191),(7902,6,385,5130,0),(7902,7,383,45,16191),(7902,8,385,5230,0),(7902,9,383,45,16191),(7902,10,136,22,0),(7902,11,383,45,16191),(7902,12,385,5330,0),(7902,13,385,5430,0),(7902,14,385,5530,0),(7904,1,0,26,0),(7905,1,0,27,0),(7906,1,0,28,0),(7907,1,0,29,0),(7908,1,0,30,0),(7940,1,264,15,558),(7941,1,264,30,558),(7942,1,264,45,558),(7945,1,310,2000,0),(7945,2,139,8007,0),(7945,3,310,2000,0),(7945,4,385,4140,0),(7945,5,385,4240,0),(7945,6,385,4340,0),(7945,7,385,4440,0),(7945,8,385,4540,0),(7945,9,385,4640,0),(7946,1,310,4000,0),(7946,2,139,8007,0),(7946,3,310,4000,0),(7946,4,385,4140,0),(7946,5,385,4240,0),(7946,6,385,4340,0),(7946,7,385,4440,0),(7946,8,385,4540,0),(7946,9,385,4640,0),(7947,1,310,6000,0),(7947,2,139,8007,0),(7947,3,310,6000,0),(7947,4,385,4140,0),(7947,5,385,4240,0),(7947,6,385,4340,0),(7947,7,385,4440,0),(7947,8,385,4540,0),(7947,9,385,4640,0),(7948,1,339,25,16197),(7948,2,138,1,0),(7948,3,142,60,0),(7948,4,137,35,0),(7948,5,134,75,0),(7948,6,339,25,16197),(7948,7,138,1,0),(7948,8,142,60,0),(7948,9,137,36,0),(7948,10,134,75,0),(7948,11,339,25,16197),(7948,12,138,1,0),(7948,13,142,60,0),(7948,14,137,369,0),(7948,15,134,75,0),(7948,16,339,25,16197),(7948,17,138,1,0),(7948,18,142,60,0),(7948,19,137,116,0),(7948,20,134,75,0),(7949,1,339,25,16198),(7949,2,138,1,0),(7949,3,142,60,0),(7949,4,137,35,0),(7949,5,134,80,0),(7949,6,339,25,16198),(7949,7,138,1,0),(7949,8,142,60,0),(7949,9,137,36,0),(7949,10,134,80,0),(7949,11,339,25,16198),(7949,12,138,1,0),(7949,13,142,60,0),(7949,14,137,369,0),(7949,15,134,80,0),(7949,16,339,25,16198),(7949,17,138,1,0),(7949,18,142,60,0),(7949,19,137,116,0),(7949,20,134,80,0),(7950,1,339,25,16199),(7950,2,138,1,0),(7950,3,142,60,0),(7950,4,137,35,0),(7950,5,134,85,0),(7950,6,339,25,16199),(7950,7,138,1,0),(7950,8,142,60,0),(7950,9,137,36,0),(7950,10,134,85,0),(7950,11,339,25,16199),(7950,12,138,1,0),(7950,13,142,60,0),(7950,14,137,369,0),(7950,15,134,85,0),(7950,16,339,25,16199),(7950,17,138,1,0),(7950,18,142,60,0),(7950,19,137,116,0),(7950,20,134,85,0),(7980,1,243,15,0),(7981,1,243,25,0),(7982,1,243,35,0),(7983,1,264,120,520),(7984,1,264,240,520),(7985,1,264,360,520),(7989,1,264,30,705),(7989,2,264,30,1092),(7989,3,264,30,10396),(7989,4,264,30,10397),(7990,1,264,60,705),(7990,2,264,60,1092),(7990,3,264,60,10396),(7990,4,264,60,10397),(7991,1,264,90,705),(7991,2,264,90,1092),(7991,3,264,90,10396),(7991,4,264,90,10397),(7992,1,264,120,705),(7992,2,264,120,1092),(7992,3,264,120,10396),(7992,4,264,120,10397),(7994,1,264,240,39),(7994,2,264,3456,1061),(7995,1,264,300,39),(7995,2,264,4320,1061),(8000,1,69,200,0),(8000,2,2,75,0),(8000,3,97,200,0),(8000,4,317,8,0),(8031,1,264,30,791),(8032,1,264,60,791),(8033,1,264,90,791),(8035,1,264,180,521),(8036,1,264,360,521),(8037,1,264,540,521),(8040,1,128,5,5),(8040,2,138,1,0),(8040,3,140,1,0),(8040,4,311,0,0),(8040,5,411,256,0),(8040,6,137,-40,0),(8040,7,391,1,0),(8041,1,128,15,15),(8041,2,138,1,0),(8041,3,140,1,0),(8041,4,311,0,0),(8041,5,411,256,0),(8041,6,137,-40,0),(8041,7,391,1,0),(8042,1,128,30,30),(8042,2,138,1,0),(8042,3,140,1,0),(8042,4,311,0,0),(8042,5,411,256,0),(8042,6,137,-40,0),(8042,7,391,1,0),(8043,1,128,50,50),(8043,2,138,1,0),(8043,3,140,1,0),(8043,4,311,0,0),(8043,5,411,256,0),(8043,6,137,-40,0),(8043,7,391,1,0),(8059,1,128,50,50),(8059,2,138,1,0),(8059,3,140,1,0),(8059,4,311,0,0),(8059,5,411,66434,0),(8059,6,137,-40,0),(8069,1,244,-10,0),(8070,1,244,-15,0),(8071,1,244,-20,0),(8076,1,264,360,565),(8076,2,264,360,793),(8076,3,264,360,794),(8077,1,264,720,565),(8077,2,264,720,793),(8077,3,264,720,794),(8078,1,264,1080,565),(8078,2,264,1080,793),(8078,3,264,1080,794),(8079,1,264,1440,565),(8079,2,264,1440,793),(8079,3,264,1440,794),(8080,1,264,1800,565),(8080,2,264,1800,793),(8080,3,264,1800,794),(8081,1,264,2160,565),(8081,2,264,2160,793),(8081,3,264,2160,794),(8082,1,264,60,208),(8083,1,264,120,208),(8084,1,264,180,208),(8190,1,280,2,0),(8191,1,280,4,0),(8192,1,280,6,0),(8193,1,339,100,16225),(8193,2,139,6838,0),(8195,1,264,120,3707),(8196,1,264,240,3707),(8197,1,264,360,3707),(8198,1,294,0,110),(8199,1,294,0,120),(8200,1,294,0,130),(8201,1,218,1,0),(8202,1,218,2,0),(8203,1,218,3,0),(8204,1,127,10,0),(8204,2,137,154,0),(8204,3,403,2,0),(8204,4,404,10,0),(8205,1,127,20,0),(8205,2,137,154,0),(8205,3,403,2,0),(8205,4,404,10,0),(8206,1,127,30,0),(8206,2,137,154,0),(8206,3,403,2,0),(8206,4,404,10,0),(8207,1,127,10,0),(8207,2,137,154,0),(8207,3,403,2,0),(8207,4,404,10,0),(8208,1,127,20,0),(8208,2,137,154,0),(8208,3,403,2,0),(8208,4,404,10,0),(8209,1,127,30,0),(8209,2,137,154,0),(8209,3,403,2,0),(8209,4,404,10,0),(8210,1,97,50,0),(8211,1,97,100,0),(8212,1,97,150,0),(8213,1,97,200,0),(8214,1,97,250,0),(8215,1,190,50,0),(8216,1,190,100,0),(8217,1,190,150,0),(8218,1,190,200,0),(8219,1,190,250,0),(8223,1,128,50,50),(8223,2,138,1,0),(8223,3,140,1,0),(8223,4,139,-2741,0),(8223,5,139,-16843,0),(8223,6,385,-16192,0),(8224,1,339,10,16230),(8224,2,138,1,0),(8224,3,141,1,0),(8224,4,142,60,0),(8224,5,137,0,0),(8224,6,311,0,0),(8224,7,134,80,0),(8224,8,139,-265,0),(8224,9,139,-754,0),(8224,10,139,-1332,0),(8224,11,139,-1572,0),(8224,12,139,-2749,0),(8224,13,139,-4979,0),(8224,14,139,-5418,0),(8224,15,139,-5403,0),(8225,1,339,10,16231),(8225,2,138,1,0),(8225,3,141,1,0),(8225,4,142,65,0),(8225,5,137,0,0),(8225,6,311,0,0),(8225,7,134,85,0),(8225,8,139,-265,0),(8225,9,139,-754,0),(8225,10,139,-1332,0),(8225,11,139,-1572,0),(8225,12,139,-2749,0),(8225,13,139,-4979,0),(8225,14,139,-5418,0),(8225,15,139,-5403,0),(8226,1,339,10,16232),(8226,2,138,1,0),(8226,3,141,1,0),(8226,4,142,70,0),(8226,5,137,0,0),(8226,6,311,0,0),(8226,7,134,90,0),(8226,8,139,-265,0),(8226,9,139,-754,0),(8226,10,139,-1332,0),(8226,11,139,-1572,0),(8226,12,139,-2749,0),(8226,13,139,-4979,0),(8226,14,139,-5418,0),(8226,15,139,-5403,0),(8228,1,378,5,22),(8229,1,378,10,22),(8230,1,378,15,22),(8232,1,128,5,5),(8232,2,138,1,0),(8232,3,140,1,0),(8232,4,311,0,0),(8232,5,411,66434,0),(8232,6,137,-40,0),(8233,1,128,15,15),(8233,2,138,1,0),(8233,3,140,1,0),(8233,4,311,0,0),(8233,5,411,66434,0),(8233,6,137,-40,0),(8234,1,128,30,30),(8234,2,138,1,0),(8234,3,140,1,0),(8234,4,311,0,0),(8234,5,411,66434,0),(8234,6,137,-40,0),(8235,1,1,29,0),(8236,1,1,58,0),(8237,1,1,87,0),(8238,1,1,116,0),(8239,1,1,145,0),(8240,1,1,31,0),(8241,1,1,62,0),(8242,1,1,93,0),(8243,1,1,124,0),(8244,1,1,155,0),(8245,1,1,33,0),(8246,1,1,66,0),(8247,1,1,99,0),(8248,1,1,132,0),(8249,1,1,165,0),(8250,1,1,40,0),(8251,1,1,80,0),(8252,1,1,120,0),(8253,1,1,160,0),(8254,1,1,200,0),(8255,1,1,50,0),(8256,1,1,100,0),(8257,1,1,150,0),(8258,1,1,200,0),(8259,1,1,250,0),(8261,1,128,65,65),(8261,2,138,1,0),(8261,3,140,1,0),(8261,4,311,0,0),(8261,5,411,66434,0),(8261,6,137,-40,0),(8262,1,128,70,70),(8262,2,138,1,0),(8262,3,140,1,0),(8262,4,139,-2741,0),(8262,5,139,-16843,0),(8262,6,385,-16192,0),(8263,1,262,5,0),(8264,1,262,10,0),(8265,1,262,15,0),(8266,1,262,20,0),(8267,1,262,25,0),(8268,1,262,5,1),(8269,1,262,10,1),(8270,1,262,15,1),(8271,1,262,20,1),(8272,1,262,25,1),(8273,1,262,5,2),(8274,1,262,10,2),(8275,1,262,15,2),(8276,1,262,20,2),(8277,1,262,25,2),(8278,1,262,5,3),(8279,1,262,10,3),(8280,1,262,15,3),(8281,1,262,20,3),(8282,1,262,25,3),(8283,1,262,5,4),(8284,1,262,10,4),(8285,1,262,15,4),(8286,1,262,20,4),(8287,1,262,25,4),(8288,1,262,5,5),(8289,1,262,10,5),(8290,1,262,15,5),(8291,1,262,20,5),(8292,1,262,25,5),(8293,1,262,5,6),(8294,1,262,10,6),(8295,1,262,15,6),(8296,1,262,20,6),(8297,1,262,25,6),(8304,1,1,174,0),(8305,1,1,203,0),(8306,1,1,232,0),(8307,1,1,261,0),(8308,1,1,290,0),(8313,1,128,65,65),(8313,2,138,1,0),(8313,3,140,1,0),(8313,4,311,0,0),(8313,5,411,256,0),(8313,6,137,-40,0),(8313,7,391,1,0),(8314,1,378,2,3),(8315,1,378,3,3),(8316,1,378,4,3),(8317,1,264,1,8205),(8318,1,264,2,8205),(8319,1,264,2,199),(8320,1,264,4,199),(8321,1,264,6,199),(8322,1,378,15,31),(8323,1,378,20,31),(8324,1,378,25,31),(8325,1,114,-3,0),(8326,1,114,-6,0),(8327,1,114,-9,0),(8328,1,268,75,56),(8328,2,234,1000,0),(8329,1,227,4,29),(8329,2,227,4,42),(8331,1,413,10,0),(8331,2,139,8001,0),(8331,3,385,12529,0),(8331,4,411,512,0),(8332,1,287,1,0),(8332,2,385,116121,0),(8333,1,287,2,0),(8333,2,385,116121,0),(8334,1,287,3,0),(8334,2,385,116121,0),(8335,1,127,10,0),(8335,2,385,16188,0),(8336,1,127,20,0),(8336,2,385,16188,0),(8337,1,127,30,0),(8337,2,385,16188,0),(8338,1,127,40,0),(8338,2,385,16188,0),(8339,1,127,50,0),(8339,2,385,16188,0),(8344,1,294,0,175),(8345,1,294,0,180),(8346,1,294,0,185),(8347,1,264,600,616),(8348,1,264,1200,616),(8349,1,264,1800,616),(8350,1,310,1200,0),(8350,2,385,6212,0),(8350,3,310,600,0),(8350,4,385,6215,0),(8350,5,310,150,0),(8350,6,385,6218,0),(8350,7,310,9000,0),(8350,8,385,6232,0),(8350,9,310,600,0),(8350,10,385,6243,0),(8350,11,310,150,0),(8350,12,385,6245,0),(8350,13,310,1200,0),(8350,14,385,6412,0),(8350,15,310,600,0),(8350,16,385,6415,0),(8350,17,310,150,0),(8350,18,385,6418,0),(8350,19,310,9000,0),(8350,20,385,6432,0),(8350,21,310,600,0),(8350,22,385,6443,0),(8350,23,310,150,0),(8350,24,385,6445,0),(8351,1,262,30,0),(8352,1,262,35,0),(8353,1,262,40,0),(8354,1,262,45,0),(8355,1,262,50,0),(8356,1,262,55,0),(8357,1,262,60,0),(8358,1,262,65,0),(8359,1,262,70,0),(8360,1,262,75,0),(8361,1,262,30,1),(8362,1,262,35,1),(8363,1,262,40,1),(8364,1,262,45,1),(8365,1,262,50,1),(8366,1,262,55,1),(8367,1,262,60,1),(8368,1,262,65,1),(8369,1,262,70,1),(8370,1,262,75,1),(8371,1,262,30,2),(8372,1,262,35,2),(8373,1,262,40,2),(8374,1,262,45,2),(8375,1,262,50,2),(8376,1,262,55,2),(8377,1,262,60,2),(8378,1,262,65,2),(8379,1,262,70,2),(8380,1,262,75,2),(8381,1,262,30,3),(8382,1,262,35,3),(8383,1,262,40,3),(8384,1,262,45,3),(8385,1,262,50,3),(8386,1,262,55,3),(8387,1,262,60,3),(8388,1,262,65,3),(8389,1,262,70,3),(8390,1,262,75,3),(8391,1,262,30,4),(8392,1,262,35,4),(8393,1,262,40,4),(8394,1,262,45,4),(8395,1,262,50,4),(8396,1,262,55,4),(8397,1,262,60,4),(8398,1,262,65,4),(8399,1,262,70,4),(8400,1,262,75,4),(8401,1,262,30,5),(8402,1,262,35,5),(8403,1,262,40,5),(8404,1,262,45,5),(8405,1,262,50,5),(8406,1,262,55,5),(8407,1,262,60,5),(8408,1,262,65,5),(8409,1,262,70,5),(8410,1,262,75,5),(8411,1,262,30,6),(8412,1,262,35,6),(8413,1,262,40,6),(8414,1,262,45,6),(8415,1,262,50,6),(8416,1,262,55,6),(8417,1,262,60,6),(8418,1,262,65,6),(8419,1,262,70,6),(8420,1,262,75,6),(8421,1,339,10,27535),(8421,2,138,1,0),(8421,3,141,1,0),(8421,4,142,75,0),(8421,5,137,0,0),(8421,6,311,0,0),(8421,7,134,95,0),(8421,8,139,-265,0),(8421,9,139,-754,0),(8421,10,139,-1332,0),(8421,11,139,-1572,0),(8421,12,139,-2749,0),(8421,13,139,-4979,0),(8421,14,139,-5418,0),(8421,15,139,-5403,0),(8422,1,1,198,0),(8423,1,1,231,0),(8424,1,1,264,0),(8425,1,1,297,0),(8426,1,1,330,0),(8427,1,264,1260,254),(8428,1,264,1440,254),(8429,1,264,1620,254),(8430,1,328,1600,0),(8435,1,0,35,0),(8440,1,259,66,0),(8445,1,426,3,0),(8446,1,426,4,0),(8447,1,426,5,0),(8448,1,69,2200,0),(8463,1,172,60,0),(8464,1,172,61,0),(8470,1,262,80,7),(8470,2,262,80,8),(8470,3,262,80,9),(8470,4,262,80,10),(8470,5,262,80,11),(9001,1,247,10,58),(9002,1,247,20,58),(9003,1,247,30,58),(9004,1,247,40,58),(9005,1,247,50,58),(9006,1,247,60,58),(9007,1,247,70,58),(9008,1,247,80,58),(9009,1,247,90,58),(9010,1,247,100,58),(9011,1,247,10,58),(9012,1,247,20,58),(9013,1,247,30,58),(9014,1,247,40,58),(9015,1,247,50,58),(9016,1,247,60,58),(9017,1,247,70,58),(9018,1,247,80,58),(9019,1,247,90,58),(9020,1,247,100,58),(9021,1,247,10,58),(9022,1,247,20,58),(9023,1,247,30,58),(9024,1,247,40,58),(9025,1,247,50,58),(9026,1,247,60,58),(9027,1,247,70,58),(9028,1,247,80,58),(9029,1,247,90,58),(9030,1,247,100,58),(9033,1,264,18000,481),(9033,2,264,18000,482),(9033,3,264,18000,483),(9033,4,264,147600,484),(9033,5,264,18000,485),(9033,6,264,61200,486),(9033,7,264,3600,487),(9033,8,264,1080,511),(9033,9,264,18000,182),(9033,10,264,18000,8081),(9033,11,264,18000,8130),(9033,12,264,18000,453),(9033,13,264,18000,2000),(9100,1,97,10,0),(9100,2,262,1,5),(9101,1,97,20,0),(9101,2,262,2,5),(9102,1,97,30,0),(9102,2,262,3,5),(9103,1,97,40,0),(9103,2,262,4,5),(9104,1,97,50,0),(9104,2,262,5,5),(9105,1,97,60,0),(9105,2,262,6,5),(9106,1,97,70,0),(9106,2,262,7,5),(9107,1,97,80,0),(9107,2,262,8,5),(9108,1,97,90,0),(9108,2,262,9,5),(9109,1,69,10,0),(9109,2,262,1,1),(9110,1,69,20,0),(9110,2,262,2,1),(9111,1,69,30,0),(9111,2,262,3,1),(9112,1,69,40,0),(9112,2,262,4,1),(9113,1,69,50,0),(9113,2,262,5,1),(9114,1,69,60,0),(9114,2,262,6,1),(9115,1,69,70,0),(9115,2,262,7,1),(9116,1,69,80,0),(9116,2,262,8,1),(9117,1,69,90,0),(9117,2,262,9,1),(9118,1,97,10,0),(9118,2,262,1,5),(9119,1,97,20,0),(9119,2,262,2,5),(9120,1,97,30,0),(9120,2,262,3,5),(9121,1,97,40,0),(9121,2,262,4,5),(9122,1,97,50,0),(9122,2,262,5,5),(9123,1,97,60,0),(9123,2,262,6,5),(9124,1,97,70,0),(9124,2,262,7,5),(9125,1,97,80,0),(9125,2,262,8,5),(9126,1,97,90,0),(9126,2,262,9,5),(9127,1,69,10,0),(9127,2,262,1,5),(9128,1,69,20,0),(9128,2,262,2,5),(9129,1,69,30,0),(9129,2,262,3,5),(9130,1,69,40,0),(9130,2,262,4,5),(9131,1,69,50,0),(9131,2,262,5,5),(9132,1,69,60,0),(9132,2,262,6,5),(9133,1,69,70,0),(9133,2,262,7,5),(9134,1,69,80,0),(9134,2,262,8,5),(9135,1,69,90,0),(9135,2,262,9,5),(9136,1,97,10,0),(9136,2,262,1,4),(9137,1,97,20,0),(9137,2,262,2,4),(9138,1,97,30,0),(9138,2,262,3,4),(9139,1,97,40,0),(9139,2,262,4,4),(9140,1,97,50,0),(9140,2,262,5,4),(9141,1,97,60,0),(9141,2,262,6,4),(9142,1,97,70,0),(9142,2,262,7,4),(9143,1,97,80,0),(9143,2,262,8,4),(9144,1,97,90,0),(9144,2,262,9,4),(9145,1,97,10,0),(9145,2,262,1,4),(9146,1,97,20,0),(9146,2,262,2,4),(9147,1,97,30,0),(9147,2,262,3,4),(9148,1,97,40,0),(9148,2,262,4,4),(9149,1,97,50,0),(9149,2,262,5,4),(9150,1,97,60,0),(9150,2,262,6,4),(9151,1,97,70,0),(9151,2,262,7,4),(9152,1,97,80,0),(9152,2,262,8,4),(9153,1,97,90,0),(9153,2,262,9,4),(9154,1,69,10,0),(9154,2,262,1,1),(9155,1,69,20,0),(9155,2,262,2,1),(9156,1,69,30,0),(9156,2,262,3,1),(9157,1,69,40,0),(9157,2,262,4,1),(9158,1,69,50,0),(9158,2,262,5,1),(9159,1,69,60,0),(9159,2,262,6,1),(9160,1,69,70,0),(9160,2,262,7,1),(9161,1,69,80,0),(9161,2,262,8,1),(9162,1,69,90,0),(9162,2,262,9,1),(9163,1,69,10,0),(9163,2,262,1,3),(9164,1,69,20,0),(9164,2,262,2,3),(9165,1,69,30,0),(9165,2,262,3,3),(9166,1,69,40,0),(9166,2,262,4,3),(9167,1,69,50,0),(9167,2,262,5,3),(9168,1,69,60,0),(9168,2,262,6,3),(9169,1,69,70,0),(9169,2,262,7,3),(9170,1,69,80,0),(9170,2,262,8,3),(9171,1,69,90,0),(9171,2,262,9,3),(9172,1,69,10,0),(9172,2,262,1,0),(9173,1,69,20,0),(9173,2,262,2,0),(9174,1,69,30,0),(9174,2,262,3,0),(9175,1,69,40,0),(9175,2,262,4,0),(9176,1,69,50,0),(9176,2,262,5,0),(9177,1,69,60,0),(9177,2,262,6,0),(9178,1,69,70,0),(9178,2,262,7,0),(9179,1,69,80,0),(9179,2,262,8,0),(9180,1,69,90,0),(9180,2,262,9,0),(9181,1,69,10,0),(9181,2,262,1,0),(9182,1,69,20,0),(9182,2,262,2,0),(9183,1,69,30,0),(9183,2,262,3,0),(9184,1,69,40,0),(9184,2,262,4,0),(9185,1,69,50,0),(9185,2,262,5,0),(9186,1,69,60,0),(9186,2,262,6,0),(9187,1,69,70,0),(9187,2,262,7,0),(9188,1,69,80,0),(9188,2,262,8,0),(9189,1,69,90,0),(9189,2,262,9,0),(9190,1,69,10,0),(9190,2,262,1,0),(9191,1,69,20,0),(9191,2,262,2,0),(9192,1,69,30,0),(9192,2,262,3,0),(9193,1,69,40,0),(9193,2,262,4,0),(9194,1,69,50,0),(9194,2,262,5,0),(9195,1,69,60,0),(9195,2,262,6,0),(9196,1,69,70,0),(9196,2,262,7,0),(9197,1,69,80,0),(9197,2,262,8,0),(9198,1,69,90,0),(9198,2,262,9,0),(9199,1,97,10,0),(9199,2,262,1,0),(9200,1,97,20,0),(9200,2,262,2,0),(9201,1,97,30,0),(9201,2,262,3,0),(9202,1,97,40,0),(9202,2,262,4,0),(9203,1,97,50,0),(9203,2,262,5,0),(9204,1,97,60,0),(9204,2,262,6,0),(9205,1,97,70,0),(9205,2,262,7,0),(9206,1,97,80,0),(9206,2,262,8,0),(9207,1,97,90,0),(9207,2,262,9,0),(9208,1,69,10,0),(9208,2,262,1,0),(9209,1,69,20,0),(9209,2,262,2,0),(9210,1,69,30,0),(9210,2,262,3,0),(9211,1,69,40,0),(9211,2,262,4,0),(9212,1,69,50,0),(9212,2,262,5,0),(9213,1,69,60,0),(9213,2,262,6,0),(9214,1,69,70,0),(9214,2,262,7,0),(9215,1,69,80,0),(9215,2,262,8,0),(9216,1,69,90,0),(9216,2,262,9,0),(9217,1,190,10,0),(9217,2,262,1,0),(9218,1,190,20,0),(9218,2,262,2,0),(9219,1,190,30,0),(9219,2,262,3,0),(9220,1,190,40,0),(9220,2,262,4,0),(9221,1,190,50,0),(9221,2,262,5,0),(9222,1,190,60,0),(9222,2,262,6,0),(9223,1,190,70,0),(9223,2,262,7,0),(9224,1,190,80,0),(9224,2,262,8,0),(9225,1,190,90,0),(9225,2,262,9,0),(9226,1,69,10,0),(9226,2,262,1,0),(9227,1,69,20,0),(9227,2,262,2,0),(9228,1,69,30,0),(9228,2,262,3,0),(9229,1,69,40,0),(9229,2,262,4,0),(9230,1,69,50,0),(9230,2,262,5,0),(9231,1,69,60,0),(9231,2,262,6,0),(9232,1,69,70,0),(9232,2,262,7,0),(9233,1,69,80,0),(9233,2,262,8,0),(9234,1,69,90,0),(9234,2,262,9,0),(9235,1,190,10,0),(9235,2,262,1,0),(9236,1,190,20,0),(9236,2,262,2,0),(9237,1,190,30,0),(9237,2,262,3,0),(9238,1,190,40,0),(9238,2,262,4,0),(9239,1,190,50,0),(9239,2,262,5,0),(9240,1,190,60,0),(9240,2,262,6,0),(9241,1,190,70,0),(9241,2,262,7,0),(9242,1,190,80,0),(9242,2,262,8,0),(9243,1,190,90,0),(9243,2,262,9,0),(9503,1,397,100,0),(9504,1,397,200,0),(9505,1,397,300,0),(9506,1,398,1000,0),(9506,2,137,152,0),(9507,1,398,2000,0),(9507,2,137,152,0),(9508,1,398,3000,0),(9508,2,137,152,0),(9509,1,399,1,0),(9509,2,141,1,0),(9509,3,138,0,0),(9509,4,134,254,0),(9509,5,348,10,0),(9509,6,137,0,0),(9509,7,311,0,0),(9509,8,137,-152,0),(9509,9,137,-39,0),(9510,1,399,2,0),(9510,2,141,1,0),(9510,3,138,0,0),(9510,4,134,254,0),(9510,5,348,10,0),(9510,6,137,0,0),(9510,7,311,0,0),(9510,8,137,-152,0),(9510,9,137,-39,0),(9511,1,399,3,0),(9511,2,141,1,0),(9511,3,138,0,0),(9511,4,134,254,0),(9511,5,348,10,0),(9511,6,137,0,0),(9511,7,311,0,0),(9511,8,137,-152,0),(9511,9,137,-39,0),(9512,1,405,1,0),(9513,1,405,3,0),(9514,1,405,5,0),(9515,1,399,4,0),(9515,2,141,1,0),(9515,3,138,0,0),(9515,4,134,254,0),(9515,5,348,10,0),(9515,6,137,0,0),(9515,7,311,0,0),(9515,8,137,-152,0),(9515,9,137,-39,0),(10004,1,310,480000,0),(10004,2,139,4674,0),(10005,1,310,600000,0),(10005,2,139,4674,0),(10007,1,85,16500,50),(10008,1,85,16501,50),(10009,1,85,16502,50),(10025,1,339,25,16517),(10025,2,137,21,0),(10026,1,339,25,16518),(10026,2,137,21,0),(10027,1,339,25,16519),(10027,2,137,21,0),(10028,1,339,25,16520),(10028,2,137,21,0),(10029,1,339,25,16555),(10029,2,137,21,0),(10030,1,264,60,558),(10031,1,264,75,558),(10032,1,264,90,558),(10033,1,310,8000,0),(10033,2,139,8007,0),(10033,3,310,8000,0),(10033,4,385,4140,0),(10033,5,385,4240,0),(10033,6,385,4340,0),(10033,7,385,4440,0),(10033,8,385,4540,0),(10033,9,385,4640,0),(10034,1,310,10000,0),(10034,2,139,8007,0),(10034,3,310,10000,0),(10034,4,385,4140,0),(10034,5,385,4240,0),(10034,6,385,4340,0),(10034,7,385,4440,0),(10034,8,385,4540,0),(10034,9,385,4640,0),(10035,1,339,25,16556),(10035,2,138,1,0),(10035,3,142,60,0),(10035,4,137,35,0),(10035,5,134,85,0),(10035,6,339,25,16556),(10035,7,138,1,0),(10035,8,142,60,0),(10035,9,137,36,0),(10035,10,134,85,0),(10035,11,339,25,16556),(10035,12,138,1,0),(10035,13,142,60,0),(10035,14,137,369,0),(10035,15,134,85,0),(10035,16,339,25,16556),(10035,17,138,1,0),(10035,18,142,60,0),(10035,19,137,116,0),(10035,20,134,85,0),(10036,1,339,25,16557),(10036,2,138,1,0),(10036,3,142,60,0),(10036,4,137,35,0),(10036,5,134,85,0),(10036,6,339,25,16557),(10036,7,138,1,0),(10036,8,142,60,0),(10036,9,137,36,0),(10036,10,134,85,0),(10036,11,339,25,16557),(10036,12,138,1,0),(10036,13,142,60,0),(10036,14,137,369,0),(10036,15,134,85,0),(10036,16,339,25,16557),(10036,17,138,1,0),(10036,18,142,60,0),(10036,19,137,116,0),(10036,20,134,85,0),(10037,1,339,25,16558),(10037,2,138,1,0),(10037,3,142,60,0),(10037,4,137,35,0),(10037,5,134,85,0),(10037,6,339,25,16558),(10037,7,138,1,0),(10037,8,142,60,0),(10037,9,137,36,0),(10037,10,134,85,0),(10037,11,339,25,16558),(10037,12,138,1,0),(10037,13,142,60,0),(10037,14,137,369,0),(10037,15,134,85,0),(10037,16,339,25,16558),(10037,17,138,1,0),(10037,18,142,60,0),(10037,19,137,116,0),(10037,20,134,85,0),(10041,1,294,0,135),(10042,1,294,0,145),(10043,1,294,0,155),(10044,1,339,20,16564),(10044,2,137,21,0),(10044,3,385,-18000,0),(10044,4,339,20,16564),(10044,5,137,343,0),(10044,6,385,-18000,0),(10045,1,339,20,16565),(10045,2,137,21,0),(10045,3,385,-18000,0),(10045,4,339,20,16565),(10045,5,137,343,0),(10045,6,385,-18000,0),(10046,1,339,20,16566),(10046,2,137,21,0),(10046,3,385,-18000,0),(10046,4,339,20,16566),(10046,5,137,343,0),(10046,6,385,-18000,0),(10050,1,85,16567,0),(10051,1,85,16568,0),(10052,1,85,16569,0),(10058,1,330,55,7),(10059,1,330,60,7),(10060,1,330,65,7),(10064,1,347,25,0),(10065,1,347,26,0),(10066,1,347,27,0),(10067,1,347,28,0),(10068,1,347,29,0),(10069,1,347,30,0),(10070,1,218,6,0),(10071,1,218,7,0),(10072,1,218,8,0),(10073,1,218,9,0),(10074,1,218,10,0),(10075,1,339,10,16581),(10075,2,138,0,0),(10075,3,142,70,0),(10075,4,403,4,0),(10075,5,348,1,0),(10075,6,404,2,0),(10075,7,141,1,0),(10076,1,339,10,16582),(10076,2,138,0,0),(10076,3,142,70,0),(10076,4,403,4,0),(10076,5,348,1,0),(10076,6,404,2,0),(10076,7,141,1,0),(10077,1,339,10,16583),(10077,2,138,0,0),(10077,3,142,70,0),(10077,4,403,4,0),(10077,5,348,1,0),(10077,6,404,2,0),(10077,7,141,1,0),(10081,1,85,16584,0),(10082,1,85,16585,0),(10083,1,85,16586,0),(10084,1,375,175,0),(10085,1,375,200,0),(10086,1,375,215,0),(10087,1,397,400,0),(10088,1,397,600,0),(10089,1,397,800,0),(10105,1,264,60,170),(10106,1,264,70,170),(10107,1,264,80,170),(10108,1,264,90,170),(10109,1,264,100,170),(10110,1,264,480,520),(10111,1,264,600,520),(10112,1,264,720,520),(10122,1,227,210,32),(10123,1,227,240,32),(10124,1,283,180,0),(10125,1,283,200,0),(10126,1,283,220,0),(10130,1,264,720,544),(10131,1,264,900,544),(10132,1,264,1080,544),(10133,1,279,19,0),(10134,1,279,23,0),(10135,1,279,27,0),(10136,1,375,130,0),(10137,1,375,135,0),(10138,1,375,140,0),(10153,1,264,420,553),(10154,1,264,480,553),(10155,1,264,540,553),(10165,1,220,195,8),(10166,1,220,225,8),(10167,1,220,255,8),(10171,1,252,90,0),(10172,1,252,95,0),(10173,1,258,70,0),(10174,1,258,71,0),(10175,1,258,72,0),(10176,1,264,40,171),(10177,1,264,50,171),(10178,1,264,60,171),(10182,1,264,180,177),(10183,1,264,210,177),(10184,1,264,240,177),(10185,1,264,270,177),(10186,1,264,300,177),(10203,1,264,720,524),(10204,1,264,900,524),(10205,1,264,1080,524),(10206,1,264,1080,320),(10207,1,264,1260,320),(10213,1,218,16,0),(10214,1,218,17,0),(10215,1,218,18,0),(10216,1,218,19,0),(10217,1,218,20,0),(10219,1,280,63,0),(10220,1,280,64,0),(10221,1,280,65,0),(10222,1,280,66,0),(10223,1,280,67,0),(10227,1,360,60,16720),(10228,1,360,60,16721),(10229,1,360,60,16722),(10249,1,264,240,208),(10250,1,264,300,208),(10251,1,264,360,208),(10262,1,274,23,0),(10263,1,274,24,0),(10264,1,274,25,0),(10265,1,280,57,0),(10266,1,280,58,0),(10267,1,280,59,0),(10268,1,339,45,16736),(10268,2,136,11,0),(10268,3,383,45,16736),(10268,4,385,11012,0),(10268,5,383,45,16736),(10268,6,385,5130,0),(10268,7,383,45,16736),(10268,8,385,5230,0),(10268,9,383,45,16736),(10268,10,136,22,0),(10268,11,383,45,16736),(10268,12,385,5330,0),(10268,13,385,5430,0),(10268,14,385,5530,0),(10269,1,339,45,16737),(10269,2,136,11,0),(10269,3,383,45,16737),(10269,4,385,11012,0),(10269,5,383,45,16737),(10269,6,385,5130,0),(10269,7,383,45,16737),(10269,8,385,5230,0),(10269,9,383,45,16737),(10269,10,136,22,0),(10269,11,383,45,16737),(10269,12,385,5330,0),(10269,13,385,5430,0),(10269,14,385,5530,0),(10270,1,339,45,16738),(10270,2,136,11,0),(10270,3,383,45,16738),(10270,4,385,11012,0),(10270,5,383,45,16738),(10270,6,385,5130,0),(10270,7,383,45,16738),(10270,8,385,5230,0),(10270,9,383,45,16738),(10270,10,136,22,0),(10270,11,383,45,16738),(10270,12,385,5330,0),(10270,13,385,5430,0),(10270,14,385,5530,0),(10282,1,264,120,791),(10283,1,264,150,791),(10284,1,264,180,791),(10285,1,264,720,521),(10286,1,264,900,521),(10287,1,264,1080,521),(10291,1,264,15,247),(10291,2,264,8,986),(10291,3,264,8,987),(10291,4,264,8,988),(10292,1,264,18,247),(10292,2,264,10,986),(10292,3,264,10,987),(10292,4,264,10,988),(10293,1,264,21,247),(10293,2,264,12,986),(10293,3,264,12,987),(10293,4,264,12,988),(10305,1,280,68,0),(10306,1,280,69,0),(10307,1,280,70,0),(10311,1,220,608,74),(10312,1,220,640,74),(10313,1,220,672,74),(10314,1,220,704,74),(10315,1,220,736,74),(10316,1,216,160,74),(10317,1,216,200,74),(10318,1,216,240,74),(10329,1,264,60,3701),(10332,1,287,1,0),(10332,2,137,22,0),(10332,3,411,256,0),(10340,1,220,100,26),(10341,1,220,160,26),(10342,1,220,235,26),(10343,1,264,5,469),(10344,1,264,10,469),(10345,1,264,15,469),(10347,1,310,12000,0),(10347,2,139,8007,0),(10347,3,310,12000,0),(10347,4,385,4140,0),(10347,5,385,4240,0),(10347,6,385,4340,0),(10347,7,385,4440,0),(10347,8,385,4540,0),(10347,9,385,4640,0),(10348,1,244,60,0),(10349,1,244,50,0),(10350,1,244,40,0),(10355,1,124,50,50),(10355,2,385,19,0),(10355,3,144,0,0),(10355,4,403,3,0),(10355,5,404,48,0),(10355,6,385,-21768,0),(10356,1,124,100,100),(10356,2,385,19,0),(10356,3,144,0,0),(10356,4,403,3,0),(10356,5,404,48,0),(10356,6,385,-21768,0),(10357,1,124,150,150),(10357,2,385,19,0),(10357,3,144,0,0),(10357,4,403,3,0),(10357,5,404,48,0),(10357,6,385,-21768,0),(10358,1,310,10000,0),(10358,2,139,1546,0),(10358,3,310,10000,0),(10358,4,385,4357,0),(10358,5,385,4457,0),(10358,6,385,4557,0),(10358,7,385,4657,0),(10358,8,411,4,0),(10359,1,310,20000,0),(10359,2,139,1546,0),(10359,3,310,20000,0),(10359,4,385,4357,0),(10359,5,385,4457,0),(10359,6,385,4557,0),(10359,7,385,4657,0),(10359,8,411,4,0),(10360,1,310,30000,0),(10360,2,139,1546,0),(10360,3,310,30000,0),(10360,4,385,4357,0),(10360,5,385,4457,0),(10360,6,385,4557,0),(10360,7,385,4657,0),(10360,8,411,4,0),(10361,1,232,17,4544),(10362,1,232,19,4544),(10363,1,232,21,4544),(10364,1,413,-5,0),(10364,2,139,480,0),(10364,3,385,4352,0),(10364,4,385,4452,0),(10365,1,413,-10,0),(10365,2,139,480,0),(10365,3,385,4352,0),(10365,4,385,4452,0),(10366,1,413,-15,0),(10366,2,139,480,0),(10366,3,385,4352,0),(10366,4,385,4452,0),(10370,1,114,-5,0),(10371,1,114,-10,0),(10372,1,114,-20,0),(10380,1,126,5,0),(10380,2,134,85,0),(10380,3,135,4,0),(10380,4,135,5,0),(10381,1,126,10,0),(10381,2,134,85,0),(10381,3,135,4,0),(10381,4,135,5,0),(10382,1,126,15,0),(10382,2,134,85,0),(10382,3,135,4,0),(10382,4,135,5,0),(10383,1,360,25,21770),(10384,1,360,25,21771),(10385,1,360,25,21772),(10388,1,323,21850,0),(10389,1,287,5,0),(10389,2,385,16107,0),(10389,3,411,512,0),(10390,1,287,10,0),(10390,2,385,16107,0),(10390,3,411,512,0),(10391,1,287,15,0),(10391,2,385,16107,0),(10391,3,411,512,0),(10398,1,264,120,3701),(10399,1,264,180,3701),(10401,1,310,30000,0),(10401,2,385,3107,0),(10401,3,385,3207,0),(10401,4,385,3307,0),(10401,5,385,3407,0),(10401,6,385,3507,0),(10401,7,385,3607,0),(10402,1,310,60000,0),(10402,2,385,3107,0),(10402,3,385,3207,0),(10402,4,385,3307,0),(10402,5,385,3407,0),(10402,6,385,3507,0),(10402,7,385,3607,0),(10403,1,310,90000,0),(10403,2,385,3107,0),(10403,3,385,3207,0),(10403,4,385,3307,0),(10403,5,385,3407,0),(10403,6,385,3507,0),(10403,7,385,3607,0),(10404,1,287,1,0),(10404,2,139,8003,0),(10405,1,310,120000,0),(10405,2,139,4590,0),(10406,1,310,240000,0),(10406,2,139,4590,0),(10407,1,310,360000,0),(10407,2,139,4590,0),(10408,1,310,480000,0),(10408,2,139,4590,0),(10409,1,310,600000,0),(10409,2,139,4590,0),(10410,1,247,130,76),(10413,1,264,60,207),(10414,2,264,120,207),(10415,3,264,180,207),(10416,4,264,240,207),(10417,5,264,300,207),(10431,1,264,210,791),(10432,1,264,240,791),(10433,1,264,270,791),(10434,1,127,16,0),(10434,2,385,5921,0),(10435,1,127,33,0),(10435,2,385,5921,0),(10436,1,127,50,0),(10436,2,385,5921,0),(10437,1,339,25,23523),(10437,2,137,21,0),(10438,1,339,25,23524),(10438,2,137,21,0),(10439,1,339,25,23525),(10439,2,137,21,0),(10440,1,339,25,23526),(10440,2,137,21,0),(10442,1,413,-20,0),(10442,2,139,480,0),(10442,3,385,4352,0),(10442,4,385,4452,0),(10443,1,413,-25,0),(10443,2,139,480,0),(10443,3,385,4352,0),(10443,4,385,4452,0),(10453,1,126,1,1),(10453,2,137,21,0),(10453,3,231,1,0),(10454,1,126,2,2),(10454,2,137,21,0),(10454,3,231,2,0),(10455,1,126,3,3),(10455,2,137,21,0),(10455,3,231,3,0),(10456,1,127,15,15),(10456,2,139,12786,0),(10457,1,127,30,30),(10457,2,139,12786,0),(10458,1,127,50,50),(10458,2,139,12786,0),(10459,1,310,3000,0),(10459,2,139,480,0),(10459,3,310,3000,0),(10459,4,385,4352,0),(10459,5,385,4452,0),(10459,6,385,4552,0),(10460,1,310,6000,0),(10460,2,139,480,0),(10460,3,310,6000,0),(10460,4,385,4352,0),(10460,5,385,4452,0),(10460,6,385,4552,0),(10461,1,310,10000,0),(10461,2,139,480,0),(10461,3,310,10000,0),(10461,4,385,4352,0),(10461,5,385,4452,0),(10461,6,385,4552,0),(10464,1,264,120,391),(10465,1,264,240,391),(10466,1,264,360,391),(10467,1,128,70,70),(10467,2,138,1,0),(10467,3,140,1,0),(10467,4,139,-2741,0),(10467,5,139,-16843,0),(10467,6,385,-16192,0),(10467,7,385,-10547,0),(10467,8,385,-13543,0),(10470,1,127,10,0),(10470,2,385,8048,0),(10471,1,127,20,0),(10471,2,385,8048,0),(10472,1,127,30,0),(10472,2,385,8048,0),(10473,1,265,82,0),(10474,1,265,83,0),(10475,1,265,84,0),(10476,1,265,85,0),(10477,1,265,86,0),(10478,1,360,3,46246),(10511,1,264,60,185),(10511,2,264,60,10426),(10512,1,264,120,185),(10512,2,264,120,10426),(10513,1,264,180,185),(10513,2,264,180,10426),(10514,1,264,60,519),(10514,2,264,60,10427),(10515,1,264,180,519),(10515,2,264,180,10427),(10516,1,264,120,519),(10516,2,264,120,10427),(10519,1,264,60,3213),(10522,1,264,2,3732),(10527,1,264,30,1400),(10532,1,264,30,1401),(10537,1,264,30,1402),(10548,1,349,10,0),(10548,2,200,10,0),(10548,3,419,27672,20),(10551,1,339,10,16825),(10551,2,137,31,0),(10552,1,339,10,16826),(10552,2,137,31,0),(10553,1,339,10,16827),(10553,2,137,31,0),(10554,1,339,12,8265),(10554,2,138,0,0),(10554,3,137,31,0),(10554,4,311,0,0),(10555,1,339,14,8265),(10555,2,138,0,0),(10555,3,137,31,0),(10555,4,311,0,0),(10556,1,339,16,8265),(10556,2,138,0,0),(10556,3,137,31,0),(10556,4,311,0,0),(10558,1,264,60,1120),(10559,1,264,120,1120),(10560,1,264,180,1120),(10561,1,126,5,5),(10561,2,139,12576,0),(10561,3,126,5,5),(10561,4,139,12828,0),(10562,1,126,10,10),(10562,2,139,12576,0),(10562,3,126,10,10),(10562,4,139,12828,0),(10563,1,126,15,15),(10563,2,139,12576,0),(10563,3,126,15,15),(10563,4,139,12828,0),(10568,1,85,23614,50),(10574,1,310,720000,0),(10574,2,139,4670,0),(10575,1,310,720000,0),(10575,2,139,4674,0),(10576,1,264,420,109),(10579,1,264,40,3646),(10580,1,264,50,3646),(10588,1,264,2,601),(10589,1,264,4,601),(10590,1,264,6,601),(10591,1,264,8,601),(10592,1,264,10,601),(10604,1,213,13,0),(10605,1,213,15,0),(10606,1,213,17,0),(10607,1,215,12,0),(10608,1,215,14,0),(10609,1,215,16,0),(10610,1,129,25,25),(10610,2,385,100265,0),(10611,1,129,25,25),(10611,2,385,100265,0),(10612,1,129,25,25),(10612,2,385,100265,0),(10621,1,264,960,180),(10622,1,264,1200,180),(10623,1,279,19,0),(10624,1,279,24,0),(10625,1,279,30,0),(10627,1,224,20,74),(10627,2,173,1,0),(10628,1,224,35,74),(10628,2,173,2,0),(10629,1,224,50,74),(10629,2,173,3,0),(10632,1,265,82,0),(10633,1,265,83,0),(10634,1,265,84,0),(10635,1,265,85,0),(10636,1,265,86,0),(10637,1,320,12,0),(10638,1,320,13,0),(10639,1,320,14,0),(10641,2,385,11064,0),(10643,1,124,200,200),(10643,2,385,19,0),(10643,3,144,0,0),(10643,4,403,3,0),(10643,5,404,48,0),(10643,6,385,-21768,0),(10644,1,124,250,250),(10644,2,385,19,0),(10644,3,144,0,0),(10644,4,403,3,0),(10644,5,404,48,0),(10644,6,385,-21768,0),(10645,1,124,300,300),(10645,2,385,19,0),(10645,3,144,0,0),(10645,4,403,3,0),(10645,5,404,48,0),(10645,6,385,-21768,0),(10650,1,378,1,3),(10651,1,378,2,3),(10652,1,378,3,3),(10653,1,310,120000,0),(10653,2,139,4502,0),(10653,3,139,4509,0),(10654,1,310,240000,0),(10654,2,139,4502,0),(10654,3,139,4509,0),(10655,1,310,360000,0),(10655,2,139,4502,0),(10655,3,139,4509,0),(10656,1,287,1,0),(10656,2,385,15002,0),(10656,3,385,15003,0),(10656,4,411,128,0),(10657,1,264,300,276),(10658,1,264,600,276),(10659,1,264,900,276),(10660,1,220,175,26),(10660,2,220,175,30),(10660,3,220,175,38),(10661,1,220,200,26),(10661,2,220,200,30),(10661,3,220,200,38),(10662,1,220,225,26),(10662,2,220,225,30),(10662,3,220,225,38),(10663,1,220,165,21),(10663,2,220,165,23),(10663,3,220,330,52),(10663,4,220,165,28),(10664,1,220,175,21),(10664,2,220,175,23),(10664,3,220,350,52),(10664,4,220,175,28),(10665,1,220,185,21),(10665,2,220,185,23),(10665,3,220,370,52),(10665,4,220,185,28),(10666,1,264,1200,98),(10667,1,264,1320,98),(10668,1,264,1440,98),(10671,1,310,720000,0),(10671,2,139,4590,0),(10672,1,310,840000,0),(10672,2,139,4590,0),(10673,1,310,960000,0),(10673,2,139,4590,0),(10674,1,310,1080000,0),(10674,2,139,4590,0),(10675,1,310,1200000,0),(10675,2,139,4590,0),(10676,1,339,20,23623),(10676,2,137,21,0),(10676,3,385,-18000,0),(10676,4,339,20,23623),(10676,5,137,343,0),(10676,6,385,-18000,0),(10677,1,339,20,23624),(10677,2,137,21,0),(10677,3,385,-18000,0),(10677,4,339,20,23624),(10677,5,137,343,0),(10677,6,385,-18000,0),(10678,1,339,20,23625),(10678,2,137,21,0),(10678,3,385,-18000,0),(10678,4,339,20,23625),(10678,5,137,343,0),(10678,6,385,-18000,0),(10685,1,266,34,0),(10686,1,266,39,0),(10687,1,266,45,0),(10688,1,220,125,10),(10689,1,220,145,10),(10690,1,220,165,10),(10691,1,220,190,10),(10692,1,220,220,10),(10705,1,85,23542,0),(10706,1,85,23543,0),(10707,1,85,23544,0),(10714,1,264,90,873),(10715,1,264,180,873),(10717,1,264,360,184),(10718,1,264,450,184),(10719,1,264,120,872),(10720,1,264,240,872),(10721,1,264,360,872),(10722,1,264,120,778),(10723,1,264,240,778),(10724,1,264,360,778),(10725,1,264,480,778),(10726,1,264,600,778),(10727,1,264,120,2235),(10728,1,264,240,2235),(10730,1,264,10,870),(10731,1,264,20,870),(10733,1,264,1,219),(10734,1,264,2,219),(10735,1,264,3,219),(10743,1,220,135,7),(10744,1,220,170,7),(10745,1,220,205,7),(10748,1,59,-35,0),(10749,1,59,-42,0),(10750,1,264,3024,286),(10750,2,264,3024,10753),(10750,3,264,3024,9101),(10751,1,264,3456,286),(10751,2,264,3456,10753),(10751,3,264,3456,9101),(10755,1,59,-50,0),(10763,1,292,50,0),(10764,1,292,60,0),(10766,1,330,70,7),(10767,1,330,75,7),(10768,1,330,80,7),(10769,1,310,1440000,0),(10769,2,139,4519,0),(10770,1,310,1680000,0),(10770,2,139,4519,0),(10778,1,274,38,0),(10779,1,274,40,0),(10780,1,274,42,0),(10781,1,1,186,0),(10782,1,1,217,0),(10783,1,1,248,0),(10784,1,1,279,0),(10785,1,1,310,0),(10788,1,363,4,0),(10792,1,287,1,0),(10792,2,385,5240,0),(10792,3,385,5340,0),(10792,4,385,5440,0),(10792,5,385,5540,0),(10792,6,385,5640,0),(10793,1,287,2,0),(10793,2,385,5240,0),(10793,3,385,5340,0),(10793,4,385,5440,0),(10793,5,385,5540,0),(10793,6,385,5640,0),(10794,1,287,3,0),(10794,2,385,5240,0),(10794,3,385,5340,0),(10794,4,385,5440,0),(10794,5,385,5540,0),(10794,6,385,5640,0),(10795,1,287,4,0),(10795,2,385,5240,0),(10795,3,385,5340,0),(10795,4,385,5440,0),(10795,5,385,5540,0),(10795,6,385,5640,0),(10796,1,287,5,0),(10796,2,385,5240,0),(10796,3,385,5340,0),(10796,4,385,5440,0),(10796,5,385,5540,0),(10796,6,385,5640,0),(10800,1,264,60,462),(10801,1,264,120,462),(10802,1,264,180,462),(10803,1,293,25,0),(10804,1,293,50,0),(10805,1,293,75,0),(10815,1,185,2,1),(10815,2,185,2,3),(10816,1,185,4,1),(10816,2,185,4,3),(10817,1,185,6,1),(10817,2,185,6,3),(10818,1,185,1,36),(10819,1,185,3,36),(10820,1,185,5,36),(10821,1,185,2,0),(10821,2,185,2,2),(10822,1,185,4,0),(10822,2,185,4,2),(10823,1,185,6,0),(10823,2,185,6,2),(10850,1,288,100,8),(10851,1,288,100,8),(10852,1,288,100,8),(10853,1,292,5,0),(10854,1,292,10,0),(10855,1,292,15,0),(10856,1,292,20,0),(10857,1,292,25,0),(10858,1,292,30,0),(10859,1,292,35,0),(10860,1,292,40,0),(10861,1,292,45,0),(10862,1,292,46,0),(10863,1,292,47,0),(10864,1,292,48,0),(10865,1,216,500,8),(10866,1,216,550,8),(10867,1,216,650,8),(10903,1,281,25,0),(10904,1,281,50,0),(10905,1,281,75,0),(10906,1,59,-48,0),(10907,1,59,-51,0),(10908,1,59,-54,0),(10909,1,264,60,7007),(10910,1,264,120,7007),(10911,1,264,180,7007),(10915,1,339,10,16876),(10915,2,138,0,0),(10915,3,142,70,0),(10915,4,411,32,0),(10915,5,348,1,0),(10915,6,141,1,0),(10916,1,339,10,16877),(10916,2,138,0,0),(10916,3,142,70,0),(10916,4,411,32,0),(10916,5,348,1,0),(10916,6,141,1,0),(10917,1,339,10,16878),(10917,2,138,0,0),(10917,3,142,70,0),(10917,4,411,32,0),(10917,5,348,1,0),(10917,6,141,1,0),(10950,1,287,1,0),(10950,2,403,4,0),(10950,3,404,38,0),(10950,4,348,1,0),(10950,5,137,11,0),(10950,6,140,2,0),(10951,1,264,60,447),(10952,1,264,120,447),(10953,1,264,180,447),(10954,1,264,60,662),(10955,1,264,120,662),(10956,1,264,180,662),(11000,1,227,1,73),(11001,1,227,2,73),(11002,1,227,3,73),(11003,1,287,1,0),(11003,2,137,158,0),(11003,3,411,2,0),(11004,1,287,1,0),(11004,2,139,8000,0),(11005,1,287,2,0),(11005,2,139,8000,0),(11006,1,287,3,0),(11006,2,139,8000,0),(11011,1,264,480,3710),(11012,1,264,600,3710),(11013,1,264,720,3710),(11014,1,264,10,3899),(11014,2,264,10,611),(11014,3,264,10,960),(11014,4,264,10,1252),(11015,1,264,20,3899),(11015,2,264,20,611),(11015,3,264,20,960),(11015,4,264,20,1252),(11016,1,264,30,3899),(11016,2,264,30,611),(11016,3,264,30,960),(11016,4,264,30,1252),(11020,1,264,40,3899),(11020,2,264,40,611),(11020,3,264,40,960),(11020,4,264,40,1252),(11050,1,264,360,452),(11050,2,264,360,6106),(11050,3,264,360,493),(11051,1,264,720,452),(11051,2,264,720,6106),(11051,3,264,720,493),(11052,1,264,1080,452),(11052,2,264,1080,6106),(11052,3,264,1080,493),(11053,1,264,1260,500),(11054,1,264,1440,500),(11059,1,264,1440,452),(11059,2,264,1440,6106),(11059,3,264,1440,493),(11060,1,264,1800,452),(11060,2,264,1800,6106),(11060,3,264,1800,493),(11061,1,114,-63,0),(11062,1,114,-64,0),(11063,1,114,-65,0),(11074,1,247,100,39),(11075,1,247,150,39),(11076,1,247,200,39),(11077,1,264,10,986),(11078,1,264,10,988),(11079,1,264,10,987),(11082,1,185,40,51),(11083,1,185,50,51),(11084,1,185,60,51),(11085,1,247,20,2),(11085,2,247,20,3),(11085,3,247,20,77),(11085,4,220,25,77),(11085,5,220,25,2),(11085,6,220,25,3),(11086,1,247,40,2),(11086,2,247,40,3),(11086,3,247,40,77),(11086,4,220,35,77),(11086,5,220,35,2),(11086,6,220,35,3),(11087,1,247,60,2),(11087,2,247,60,3),(11087,3,247,60,77),(11087,4,220,50,77),(11087,5,220,50,2),(11087,6,220,50,3),(11088,1,264,180,505),(11089,1,264,360,505),(11090,1,264,540,505),(11091,1,264,720,505),(12396,1,172,50,0),(12397,1,172,51,0),(12398,1,172,52,0),(12399,1,172,53,0),(12400,1,172,54,0),(12401,1,259,56,0),(12402,1,259,57,0),(12403,1,259,58,0),(12404,1,259,59,0),(12405,1,259,60,0),(12406,1,69,1100,0),(12407,1,69,1200,0),(12408,1,69,1300,0),(12409,1,69,1400,0),(12410,1,69,1500,0),(12411,1,1,300,0),(12412,1,1,350,0),(12413,1,1,400,0),(12414,1,1,450,0),(12415,1,1,500,0),(12416,1,399,3,0),(12416,2,141,1,0),(12416,3,138,0,0),(12416,4,142,255,0),(12416,5,391,0,0),(12416,6,311,0,0),(12416,7,137,-152,0),(12416,8,411,100350,0),(12416,9,137,-39,0),(12417,1,399,6,0),(12417,2,141,1,0),(12417,3,138,0,0),(12417,4,142,255,0),(12417,5,391,0,0),(12417,6,311,0,0),(12417,7,137,-152,0),(12417,8,411,100350,0),(12417,9,137,-39,0),(12418,1,399,9,0),(12418,2,141,1,0),(12418,3,138,0,0),(12418,4,142,255,0),(12418,5,391,0,0),(12418,6,311,0,0),(12418,7,137,-152,0),(12418,8,411,100350,0),(12418,9,137,-39,0),(12419,1,292,15,0),(12420,1,292,30,0),(12421,1,292,45,0),(12423,1,273,21,0),(12424,1,273,24,0),(12425,1,273,27,0),(12426,1,273,21,0),(12427,1,273,24,0),(12428,1,273,27,0),(12432,1,294,17,100),(12433,1,294,19,100),(12434,1,294,21,100),(12435,1,294,23,100),(12436,1,294,25,100),(12437,1,294,27,100),(12438,1,200,70,0),(12439,1,341,210,0),(12440,1,341,220,0),(12441,1,341,230,0),(12442,1,341,240,0),(12443,1,341,250,0),(12444,1,318,21,0),(12445,1,318,22,0),(12446,1,318,23,0),(12447,1,318,24,0),(12448,1,318,25,0),(12449,1,125,31,31),(12449,2,137,0,0),(12449,3,141,1,0),(12449,4,139,-6233,0),(12449,5,139,-6265,0),(12449,6,125,31,31),(12449,7,137,147,0),(12449,8,141,1,0),(12450,1,125,34,34),(12450,2,137,0,0),(12450,3,141,1,0),(12450,4,139,-6233,0),(12450,5,139,-6265,0),(12450,6,125,34,34),(12450,7,137,147,0),(12450,8,141,1,0),(12451,1,125,37,37),(12451,2,137,0,0),(12451,3,141,1,0),(12451,4,139,-6233,0),(12451,5,139,-6265,0),(12451,6,125,37,37),(12451,7,137,147,0),(12451,8,141,1,0),(12452,1,274,38,0),(12453,1,274,39,0),(12454,1,274,40,0),(12455,1,15,19,0),(12456,1,15,20,0),(12457,1,15,21,0),(12458,1,15,22,0),(12459,1,15,23,0),(12463,1,320,9,0),(12464,1,320,10,0),(12465,1,320,11,0),(12466,1,320,9,0),(12467,1,320,10,0),(12468,1,320,11,0),(12469,1,320,9,0),(12470,1,320,10,0),(12471,1,320,11,0),(12472,1,320,6,0),(12473,1,320,7,0),(12474,1,320,8,0),(12475,1,264,180,7003),(12476,1,264,360,7003),(12477,1,264,540,7003),(12478,1,264,60,3705),(12479,1,264,120,3705),(12480,1,264,180,3705),(12481,1,247,40,76),(12482,1,247,45,76),(12483,1,247,65,76),(12484,1,247,70,76),(12485,1,247,30,76),(12486,1,247,35,76),(12487,1,247,25,76),(12488,1,247,30,76),(12492,1,69,1600,0),(12493,1,69,1700,0),(12494,1,69,1800,0),(12495,1,69,1900,0),(12496,1,69,2000,0),(12497,1,125,40,40),(12497,2,137,0,0),(12497,3,141,1,0),(12497,4,139,-6233,0),(12497,5,139,-6265,0),(12497,6,125,40,40),(12497,7,137,147,0),(12497,8,141,1,0),(12498,1,125,43,43),(12498,2,137,0,0),(12498,3,141,1,0),(12498,4,139,-6233,0),(12498,5,139,-6265,0),(12498,6,125,43,43),(12498,7,137,147,0),(12498,8,141,1,0),(12499,1,125,46,46),(12499,2,137,0,0),(12499,3,141,1,0),(12499,4,139,-6233,0),(12499,5,139,-6265,0),(12499,6,125,46,46),(12499,7,137,147,0),(12499,8,141,1,0),(12500,1,310,1000,0),(12500,2,385,4004,0),(12500,3,385,11202,0),(12500,4,385,11302,0),(12500,5,385,11402,0),(12500,6,385,11502,0),(12500,7,385,11602,0),(12501,1,310,2000,0),(12501,2,385,4004,0),(12501,3,385,11202,0),(12501,4,385,11302,0),(12501,5,385,11402,0),(12501,6,385,11502,0),(12501,7,385,11602,0),(12502,1,310,3000,0),(12502,2,385,4004,0),(12502,3,385,11202,0),(12502,4,385,11302,0),(12502,5,385,11402,0),(12502,6,385,11502,0),(12502,7,385,11602,0),(12505,1,310,4000,0),(12505,2,385,4004,0),(12505,3,385,11202,0),(12505,4,385,11302,0),(12505,5,385,11402,0),(12505,6,385,11502,0),(12505,7,385,11602,0),(12506,1,310,5000,0),(12506,2,385,4004,0),(12506,3,385,11202,0),(12506,4,385,11302,0),(12506,5,385,11402,0),(12506,6,385,11502,0),(12506,7,385,11602,0),(12507,1,301,120,0),(12508,1,247,50,76),(12509,1,247,55,76),(12510,1,247,60,76),(12511,1,247,75,76),(12512,1,247,80,76),(12513,1,247,85,76),(12514,1,247,40,76),(12515,1,247,45,76),(12516,1,247,50,76),(12517,1,247,35,76),(12518,1,247,40,76),(12519,1,247,45,76),(12523,1,294,0,200),(12526,1,294,0,190),(12527,1,294,0,195),(12528,1,294,0,200),(12529,1,294,0,165),(12530,1,294,0,175),(12531,1,294,0,185),(12532,1,341,260,0),(12533,1,341,270,0),(12534,1,341,280,0),(12535,1,341,290,0),(12536,1,341,300,0),(12537,1,318,26,0),(12538,1,318,27,0),(12539,1,318,28,0),(12540,1,318,29,0),(12541,1,318,30,0),(12548,1,278,900,79230),(12548,2,440,87,100),(12549,1,278,900,86260),(12549,2,440,88,100),(12550,1,278,900,88260),(12550,2,440,89,100),(12551,1,278,900,91510),(12551,2,440,90,100),(12552,1,278,900,96305),(12552,2,440,91,100),(12553,1,294,29,102),(12554,1,294,31,104),(12555,1,294,33,106),(12556,1,294,23,100),(12557,1,294,25,100),(12558,1,294,27,100),(12559,1,190,300,0),(12560,1,190,350,0),(12561,1,190,400,0),(12562,1,190,450,0),(12563,1,190,500,0),(12564,1,319,28,0),(12565,1,319,29,0),(12566,1,319,30,0),(12567,1,274,41,0),(12568,1,274,42,0),(12569,1,274,43,0),(12570,1,15,24,0),(12571,1,15,25,0),(12572,1,15,26,0),(12573,1,15,27,0),(12574,1,15,28,0),(12575,1,292,60,0),(12576,1,231,17,0),(12577,1,231,19,0),(12578,1,231,21,0),(12579,1,85,23569,0),(12580,1,85,23570,0),(12581,1,85,23571,0),(12582,1,264,10,9400),(12583,1,264,20,9400),(12584,1,264,30,9400),(12587,1,264,480,9403),(12588,1,264,600,9403),(12589,1,264,720,9403),(12591,1,247,90,76),(12594,1,247,55,76),(12597,1,247,50,76),(12598,1,247,55,76),(12600,1,310,60000,0),(12600,2,139,6197,0),(12600,3,411,512,0),(12603,1,287,1,0),(12603,2,139,6197,0),(12603,3,411,512,0),(12606,1,271,5,0),(12607,1,310,12000,0),(12607,2,385,13007,0),(12607,3,385,12105,0),(12607,4,385,12205,0),(12607,5,310,36000,0),(12607,6,385,12305,0),(12607,7,385,12405,0),(12607,8,385,12505,0),(12607,9,411,512,0),(12610,1,279,19,0),(12612,1,439,0,124480),(12612,2,345,84,25),(12613,1,439,0,132440),(12613,2,345,86,25),(12615,1,310,120000,0),(12615,2,139,4695,0),(12615,3,411,512,0),(12616,1,310,240000,0),(12616,2,139,4695,0),(12616,3,411,512,0),(12617,1,310,360000,0),(12617,2,139,4695,0),(12617,3,411,512,0),(12636,1,426,1,0),(12637,1,426,2,0),(12639,1,264,240,519),(12639,2,264,240,10427),(12642,1,264,240,185),(12642,2,264,240,10426),(12645,1,287,1,0),(12645,2,385,8190,0),(12645,3,287,1,0),(12645,4,385,21818,0),(12645,5,411,64,0),(12646,1,287,1,0),(12646,2,385,3277,0),(12646,3,287,1,0),(12646,4,385,21816,0),(12652,1,399,1,0),(12652,2,138,1,0),(12652,3,137,0,0),(12652,4,348,10,0),(12652,5,311,0,0),(12652,6,141,1,0),(12652,7,134,254,0),(12652,8,137,-39,0),(12653,1,399,2,0),(12653,2,138,1,0),(12653,3,137,0,0),(12653,4,348,10,0),(12653,5,311,0,0),(12653,6,141,1,0),(12653,7,134,254,0),(12653,8,137,-39,0),(12654,1,399,3,0),(12654,2,138,1,0),(12654,3,137,0,0),(12654,4,348,10,0),(12654,5,311,0,0),(12654,6,141,1,0),(12654,7,134,254,0),(12654,8,137,-39,0),(12664,1,264,2,3728),(12667,1,220,250,26),(12667,2,220,250,30),(12667,3,220,250,38),(12668,1,220,275,26),(12668,2,220,275,30),(12668,3,220,275,38),(12669,1,220,300,26),(12669,2,220,300,30),(12669,3,220,300,38),(12670,1,220,200,21),(12670,2,220,200,23),(12670,3,220,400,52),(12670,4,220,200,28),(12671,1,220,215,21),(12671,2,220,215,23),(12671,3,220,450,52),(12671,4,220,215,28),(12672,1,220,235,21),(12672,2,220,235,23),(12672,3,220,510,52),(12672,4,220,235,28),(12673,1,264,960,420),(12674,1,227,270,32),(12675,1,227,300,32),(12676,1,227,330,32),(12677,1,275,92,0),(12678,1,287,2,0),(12678,2,385,15002,0),(12678,3,385,15003,0),(12678,4,411,128,0),(12679,1,264,1200,276),(12680,1,264,1500,276),(12681,1,264,1800,276),(12685,1,292,49,0),(12686,1,292,50,0),(12687,1,292,51,0),(12688,1,287,1,0),(12688,2,385,8473,0),(12688,3,385,8318,0),(12688,4,385,8418,0),(12688,5,385,8518,0),(12688,6,411,128,0),(12689,1,287,2,0),(12689,2,139,4691,0),(12689,3,411,128,0),(12690,1,287,2,0),(12690,2,385,8111,0),(12690,3,385,15008,0),(12690,4,385,8411,0),(12690,5,385,8511,0),(12690,6,411,128,0),(12691,1,287,1,0),(12691,2,385,15007,0),(12691,3,411,128,0),(12691,4,385,8316,0),(12692,1,220,255,21),(12692,2,220,255,23),(12692,3,220,570,52),(12692,4,220,255,28),(12693,1,220,275,21),(12693,2,220,275,23),(12693,3,220,630,52),(12693,4,220,275,28),(12694,1,189,16,0),(12695,1,189,17,0),(12696,1,189,18,0),(12697,1,330,140,0),(12697,2,330,140,1),(12697,3,330,140,2),(12697,4,330,140,3),(12697,5,330,140,28),(12697,6,330,140,36),(12697,7,330,140,77),(12698,1,330,145,0),(12698,2,330,145,1),(12698,3,330,145,2),(12698,4,330,145,3),(12698,5,330,145,28),(12698,6,330,145,36),(12698,7,330,145,77),(12699,1,330,150,0),(12699,2,330,150,1),(12699,3,330,150,2),(12699,4,330,150,3),(12699,5,330,150,28),(12699,6,330,150,36),(12699,7,330,150,77),(12703,1,283,240,0),(12704,1,283,260,0),(12705,1,283,280,0),(12706,1,220,60,28),(12706,2,220,60,0),(12706,3,427,23598,3),(12706,4,428,28,0),(12706,5,428,0,0),(12707,1,220,85,28),(12707,2,220,85,0),(12707,3,427,23598,5),(12707,4,428,28,0),(12707,5,428,0,0),(12708,1,220,115,28),(12708,2,220,115,0),(12708,3,427,23598,7),(12708,4,428,28,0),(12708,5,428,0,0),(12709,1,287,1,0),(12709,2,139,4516,0),(12709,3,411,256,0),(12710,1,310,360000,0),(12710,2,139,4516,0),(12710,3,411,256,0),(12711,1,310,720000,0),(12711,2,139,4516,0),(12711,3,411,256,0),(12712,1,310,1080000,0),(12712,2,139,4516,0),(12712,3,411,256,0),(12713,1,264,2,8202),(12714,1,264,4,8202),(12715,1,264,6,8202),(12716,1,264,30,3702),(12717,1,264,60,3702),(12718,1,264,90,3702),(12719,1,128,10,0),(12719,2,385,12769,0),(12719,3,411,256,0),(12720,1,287,1,0),(12720,2,139,12519,0),(12720,3,411,256,0),(12721,1,264,60,3506),(12722,1,264,120,3506),(12723,1,264,180,3506),(12727,1,264,960,359),(12728,1,264,1200,359),(12729,1,264,1440,359),(12733,1,287,2,0),(12733,2,137,22,0),(12733,3,411,256,0),(12734,1,375,145,0),(12735,1,375,150,0),(12736,1,375,155,0),(12737,1,129,5,0),(12737,2,385,12768,0),(12737,3,411,256,0),(12738,1,129,10,0),(12738,2,385,12768,0),(12738,3,411,256,0),(12739,1,129,15,0),(12739,2,385,12768,0),(12739,3,411,256,0),(12757,1,264,6000,68),(12758,1,264,6600,68),(12759,1,264,7200,68),(12767,1,229,50,0),(12768,1,229,55,0),(12769,1,229,60,0),(12773,1,264,60,1580),(12774,1,264,120,1580),(12775,1,264,180,1580),(12776,1,264,240,1580),(12777,1,264,300,1580),(12779,1,264,0,826),(12780,1,264,1,826),(12781,1,264,1,826),(12782,1,129,10,0),(12782,2,385,16106,0),(12783,1,129,20,0),(12783,2,385,16106,0),(12784,1,129,30,0),(12784,2,385,16106,0),(12792,1,397,1000,0),(12793,1,397,1200,0),(12794,1,397,1250,0),(12795,1,213,19,0),(12796,1,213,21,0),(12797,1,213,23,0),(12798,1,218,21,0),(12799,1,218,22,0),(12800,1,218,23,0),(12801,1,215,18,0),(12802,1,215,20,0),(12803,1,215,22,0),(12813,1,320,2,0),(12814,1,320,4,0),(12815,1,320,6,0),(12816,1,128,1,0),(12816,2,385,2223,0),(12816,3,385,2323,0),(12816,4,385,2240,0),(12816,5,385,2340,0),(12816,6,385,2440,0),(12816,7,385,2540,0),(12816,8,398,6000,0),(12816,9,385,11872,0),(12816,10,385,14154,0),(12816,11,385,18166,0),(12816,12,385,27225,0),(12816,13,385,2419,0),(12816,14,385,2427,0),(12816,15,385,30374,0),(12816,16,385,2527,0),(12816,17,385,36431,0),(12819,1,310,23400,0),(12819,2,139,4671,0),(12819,3,411,32768,0),(12820,1,310,46800,0),(12820,2,139,4671,0),(12820,3,411,32768,0),(12822,1,310,153000,0),(12822,2,139,8233,0),(12822,3,310,120000,0),(12822,4,385,2439,0),(12822,5,385,2539,0),(12822,6,411,32768,0),(12831,1,127,17,0),(12831,2,385,3291,0),(12831,3,385,3817,0),(12831,4,411,32768,0),(12834,1,264,180,128),(12835,1,264,225,128),(12840,1,264,24,3817),(12841,1,264,30,3817),(12843,1,225,42,0),(12846,1,288,20,28),(12846,2,288,20,0),(12849,1,127,14,0),(12849,2,385,16794,0),(12849,3,411,32768,0),(12860,1,294,21,102),(12863,1,127,15,15),(12863,2,137,0,0),(12863,3,138,0,0),(12863,4,141,1,0),(12863,5,143,3000,0),(12863,6,127,15,15),(12863,7,385,16555,0),(12863,8,385,16655,0),(12871,1,264,2160,452),(12871,2,264,2160,6106),(12871,3,264,2160,493),(12872,1,264,2520,452),(12872,2,264,2520,6106),(12872,3,264,2520,493),(12874,1,264,2572,451),(12876,1,264,900,7003),(12877,1,264,1260,7003),(12878,1,264,1620,7003),(12881,1,264,45,172),(12886,1,10,0,0),(12887,1,10,0,0),(12888,1,10,0,0),(12889,1,10,0,0),(12890,1,10,0,0),(12894,1,264,30,1122),(12899,1,264,3456,57),(12899,2,264,3456,616),(12900,1,264,4320,57),(12900,2,264,4320,616),(12902,1,264,30,1380),(12903,1,264,60,1380),(12907,1,264,30,1381),(12908,1,264,60,1381),(12912,1,264,30,1382),(12913,1,264,60,1382),(12920,1,130,10,10),(12920,2,139,2569,0),(12920,3,130,-10,-10),(12920,4,139,2568,0),(12929,1,287,4,0),(12929,2,137,3,0),(12929,3,137,99,0),(12929,4,138,0,0),(12929,5,244,20,0),(12930,1,287,5,0),(12930,2,137,3,0),(12930,3,137,99,0),(12930,4,138,0,0),(12930,5,244,15,0),(12945,1,280,60,0),(12946,1,280,61,0),(12947,1,280,62,0),(12948,1,280,63,0),(12949,1,280,64,0),(12950,1,218,21,0),(12951,1,218,22,0),(12952,1,218,23,0),(12953,1,218,24,0),(12954,1,218,25,0),(12966,1,131,25,25),(12966,2,348,10,0),(12966,3,137,-32,0),(12967,1,131,50,50),(12967,2,348,10,0),(12967,3,137,-32,0),(12968,1,264,3,1041),(12969,1,264,6,1041),(12970,1,264,9,1041),(12977,1,287,2,0),(12977,2,385,16188,0),(12978,1,287,4,0),(12978,2,385,16188,0),(12979,1,287,6,0),(12979,2,385,16188,0),(12980,1,287,8,0),(12980,2,385,16188,0),(12981,1,287,10,0),(12981,2,385,16188,0),(12988,1,287,3,0),(12988,2,140,3,0),(12988,3,348,1,0),(12988,4,138,0,0),(12988,5,137,0,0),(13001,1,264,60,9504),(13002,1,264,120,9504),(13003,1,264,180,9504),(13005,1,264,70,171),(13006,1,264,80,171),(13007,1,264,90,171),(13010,1,264,10,47),(13011,1,264,20,47),(13012,1,264,30,47),(13013,1,264,120,446),(13014,1,264,240,446),(13015,1,264,360,446),(13017,1,375,15,0),(13018,1,375,25,0),(13019,1,375,35,0),(13021,1,247,80,2),(13021,2,247,80,3),(13021,3,247,80,77),(13021,4,220,75,77),(13021,5,220,75,2),(13021,6,220,75,3),(13023,1,330,115,0),(13023,2,330,115,1),(13023,3,330,115,2),(13023,4,330,115,3),(13023,5,330,115,28),(13023,6,330,115,36),(13023,7,330,115,77),(13026,1,266,26,0),(13027,1,266,27,0),(13028,1,266,28,0),(13029,1,288,250,51),(13029,2,288,60,51),(13032,1,185,70,51),(13033,1,185,80,51),(13035,1,220,768,74),(13040,1,216,280,74),(13043,1,169,35,-1),(13046,1,1,240,0),(13047,1,1,280,0),(13048,1,1,320,0),(13049,1,1,360,0),(13050,1,1,400,0),(13051,1,287,2,0),(13051,2,139,8003,0),(13052,1,310,120000,0),(13052,2,385,3107,0),(13052,3,385,3207,0),(13052,4,385,3307,0),(13052,5,385,3407,0),(13052,6,385,3507,0),(13052,7,385,3607,0),(13055,1,264,60,8400),(13067,1,264,120,643),(13072,1,310,120000,0),(13072,2,139,6197,0),(13072,3,411,512,0),(13073,1,310,180000,0),(13073,2,139,6197,0),(13073,3,411,512,0),(13074,1,330,140,0),(13074,2,330,140,1),(13074,3,330,140,2),(13074,4,330,140,3),(13074,5,330,140,28),(13074,6,330,140,36),(13075,1,330,145,0),(13075,2,330,145,1),(13075,3,330,145,2),(13075,4,330,145,3),(13075,5,330,145,28),(13075,6,330,145,36),(13076,1,330,150,0),(13076,2,330,150,1),(13076,3,330,150,2),(13076,4,330,150,3),(13076,5,330,150,28),(13076,6,330,150,36),(13077,1,330,140,0),(13077,2,330,140,1),(13077,3,330,140,2),(13077,4,330,140,3),(13077,5,330,140,28),(13077,6,330,140,36),(13077,7,330,140,77),(13078,1,330,145,0),(13078,2,330,145,1),(13078,3,330,145,2),(13078,4,330,145,3),(13078,5,330,145,28),(13078,6,330,145,36),(13078,7,330,145,77),(13080,1,172,55,0),(13081,1,172,56,0),(13082,1,172,57,0),(13083,1,172,58,0),(13084,1,172,59,0),(13085,1,259,61,0),(13086,1,259,62,0),(13087,1,259,63,0),(13088,1,259,64,0),(13089,1,259,65,0),(13090,1,339,10,8105),(13090,2,142,65,0),(13090,3,311,0,0),(13090,4,134,70,0),(13090,5,348,10,0),(13090,6,137,0,0),(13090,7,339,10,8105),(13090,8,142,65,0),(13090,9,311,0,0),(13090,10,134,70,0),(13090,11,348,10,0),(13090,12,137,100,0),(13090,13,339,10,8105),(13090,14,142,65,0),(13090,15,311,0,0),(13090,16,134,70,0),(13090,17,348,10,0),(13090,18,137,79,0),(13090,19,339,10,8105),(13090,20,142,65,0),(13090,21,311,0,0),(13090,22,134,70,0),(13090,23,348,10,0),(13090,24,137,147,0),(13090,25,339,10,11404),(13090,26,142,71,0),(13090,27,311,0,0),(13090,28,134,75,0),(13090,29,348,10,0),(13090,30,137,0,0),(13090,31,339,10,11404),(13090,32,142,71,0),(13090,33,311,0,0),(13090,34,134,75,0),(13090,35,348,10,0),(13090,36,137,100,0),(13090,37,339,10,11404),(13090,38,142,71,0),(13090,39,311,0,0),(13090,40,134,75,0),(13090,41,348,10,0),(13090,42,137,79,0),(13090,43,339,10,11404),(13090,44,142,71,0),(13090,45,311,0,0),(13090,46,134,75,0),(13090,47,348,10,0),(13090,48,137,147,0),(13090,49,339,10,13199),(13090,50,142,76,0),(13090,51,311,0,0),(13090,52,134,80,0),(13090,53,348,10,0),(13090,54,137,0,0),(13090,55,339,10,13199),(13090,56,142,76,0),(13090,57,311,0,0),(13090,58,134,80,0),(13090,59,348,10,0),(13090,60,137,100,0),(13090,61,339,10,13199),(13090,62,142,76,0),(13090,63,311,0,0),(13090,64,134,80,0),(13090,65,348,10,0),(13090,66,137,79,0),(13090,67,339,10,13199),(13090,68,142,76,0),(13090,69,311,0,0),(13090,70,134,80,0),(13090,71,348,10,0),(13090,72,137,147,0),(13090,73,339,10,13830),(13090,74,142,81,0),(13090,75,311,0,0),(13090,76,134,85,0),(13090,77,348,10,0),(13090,78,137,0,0),(13090,79,339,10,13830),(13090,80,142,81,0),(13090,81,311,0,0),(13090,82,134,85,0),(13090,83,348,10,0),(13090,84,137,100,0),(13090,85,339,10,13830),(13090,86,142,81,0),(13090,87,311,0,0),(13090,88,134,85,0),(13090,89,348,10,0),(13090,90,137,79,0),(13090,91,339,10,13830),(13090,92,142,81,0),(13090,93,311,0,0),(13090,94,134,85,0),(13090,95,348,10,0),(13090,96,137,147,0),(13090,97,339,10,27527),(13090,98,142,86,0),(13090,99,311,0,0),(13090,100,134,90,0),(13090,101,348,10,0),(13090,102,137,0,0),(13090,103,339,10,27527),(13090,104,142,86,0),(13090,105,311,0,0),(13090,106,134,90,0),(13090,107,348,10,0),(13090,108,137,100,0),(13090,109,339,10,27527),(13090,110,142,86,0),(13090,111,311,0,0),(13090,112,134,90,0),(13090,113,348,10,0),(13090,114,137,79,0),(13090,115,339,10,27527),(13090,116,142,86,0),(13090,117,311,0,0),(13090,118,134,90,0),(13090,119,348,10,0),(13090,120,137,147,0),(13091,1,339,10,8105),(13091,2,142,65,0),(13091,3,311,0,0),(13091,4,134,70,0),(13091,5,348,10,0),(13091,6,137,0,0),(13091,7,339,10,8105),(13091,8,142,65,0),(13091,9,311,0,0),(13091,10,134,70,0),(13091,11,348,10,0),(13091,12,137,100,0),(13091,13,339,10,8105),(13091,14,142,65,0),(13091,15,311,0,0),(13091,16,134,70,0),(13091,17,348,10,0),(13091,18,137,79,0),(13091,19,339,10,8105),(13091,20,142,65,0),(13091,21,311,0,0),(13091,22,134,70,0),(13091,23,348,10,0),(13091,24,137,147,0),(13091,25,339,10,11404),(13091,26,142,71,0),(13091,27,311,0,0),(13091,28,134,75,0),(13091,29,348,10,0),(13091,30,137,0,0),(13091,31,339,10,11404),(13091,32,142,71,0),(13091,33,311,0,0),(13091,34,134,75,0),(13091,35,348,10,0),(13091,36,137,100,0),(13091,37,339,10,11404),(13091,38,142,71,0),(13091,39,311,0,0),(13091,40,134,75,0),(13091,41,348,10,0),(13091,42,137,79,0),(13091,43,339,10,11404),(13091,44,142,71,0),(13091,45,311,0,0),(13091,46,134,75,0),(13091,47,348,10,0),(13091,48,137,147,0),(13091,49,339,10,13199),(13091,50,142,76,0),(13091,51,311,0,0),(13091,52,134,80,0),(13091,53,348,10,0),(13091,54,137,0,0),(13091,55,339,10,13199),(13091,56,142,76,0),(13091,57,311,0,0),(13091,58,134,80,0),(13091,59,348,10,0),(13091,60,137,100,0),(13091,61,339,10,13199),(13091,62,142,76,0),(13091,63,311,0,0),(13091,64,134,80,0),(13091,65,348,10,0),(13091,66,137,79,0),(13091,67,339,10,13199),(13091,68,142,76,0),(13091,69,311,0,0),(13091,70,134,80,0),(13091,71,348,10,0),(13091,72,137,147,0),(13091,73,339,10,13830),(13091,74,142,81,0),(13091,75,311,0,0),(13091,76,134,85,0),(13091,77,348,10,0),(13091,78,137,0,0),(13091,79,339,10,13830),(13091,80,142,81,0),(13091,81,311,0,0),(13091,82,134,85,0),(13091,83,348,10,0),(13091,84,137,100,0),(13091,85,339,10,13830),(13091,86,142,81,0),(13091,87,311,0,0),(13091,88,134,85,0),(13091,89,348,10,0),(13091,90,137,79,0),(13091,91,339,10,13830),(13091,92,142,81,0),(13091,93,311,0,0),(13091,94,134,85,0),(13091,95,348,10,0),(13091,96,137,147,0),(13091,97,339,10,27527),(13091,98,142,86,0),(13091,99,311,0,0),(13091,100,134,90,0),(13091,101,348,10,0),(13091,102,137,0,0),(13091,103,339,10,27527),(13091,104,142,86,0),(13091,105,311,0,0),(13091,106,134,90,0),(13091,107,348,10,0),(13091,108,137,100,0),(13091,109,339,10,27527),(13091,110,142,86,0),(13091,111,311,0,0),(13091,112,134,90,0),(13091,113,348,10,0),(13091,114,137,79,0),(13091,115,339,10,27527),(13091,116,142,86,0),(13091,117,311,0,0),(13091,118,134,90,0),(13091,119,348,10,0),(13091,120,137,147,0),(13092,1,217,0,102280),(13092,2,346,84,18),(13093,1,217,0,109400),(13093,2,346,86,18),(13094,1,217,0,116800),(13094,2,346,88,18),(13095,1,439,0,140680),(13095,2,345,88,25),(13096,1,287,1,0),(13096,2,140,3,0),(13096,3,348,1,0),(13096,4,138,0,0),(13096,5,137,0,0),(13097,1,287,2,0),(13097,2,140,3,0),(13097,3,348,1,0),(13097,4,138,0,0),(13097,5,137,0,0),(13098,1,287,3,0),(13098,2,140,3,0),(13098,3,348,1,0),(13098,4,138,0,0),(13098,5,137,0,0),(13099,1,132,15,15),(13101,1,360,25,27537),(13102,1,360,25,27538),(13103,1,360,25,27539),(13104,1,303,14000,18000),(13104,2,139,2766,0),(13105,1,303,18000,22500),(13105,2,139,2766,0),(13106,1,303,22500,27500),(13106,2,139,2766,0),(13110,1,185,8,1),(13110,2,185,8,3),(13111,1,185,10,1),(13111,2,185,10,3),(13113,1,185,7,36),(13114,1,185,9,36),(13116,1,185,8,0),(13116,2,185,8,2),(13117,1,185,10,0),(13117,2,185,10,2),(13122,1,2,128,0),(13123,1,2,132,0),(13124,1,2,136,0),(13127,1,287,4,0),(13127,2,140,3,0),(13127,3,348,1,0),(13127,4,138,0,0),(13127,5,137,0,0),(13130,1,264,1440,7003),(13140,1,264,480,391),(13141,1,264,600,391),(13142,1,264,720,391),(13143,1,127,17,0),(13143,2,385,8054,0),(13144,1,127,34,0),(13144,2,385,8054,0),(13145,1,127,50,0),(13145,2,385,8054,0),(13146,1,127,17,0),(13146,2,385,8054,0),(13147,1,127,34,0),(13147,2,385,8054,0),(13148,1,127,50,0),(13148,2,385,8054,0),(13149,1,97,550,0),(13150,1,97,600,0),(13151,1,97,650,0),(13152,1,97,700,0),(13153,1,97,750,0),(13166,1,264,5,749),(13166,2,264,5,822),(13166,3,264,5,1274),(13166,4,264,5,1275),(13167,1,264,10,749),(13167,2,264,10,822),(13167,3,264,10,1274),(13167,4,264,10,1275),(13168,1,264,15,749),(13168,2,264,15,822),(13168,3,264,15,1274),(13168,4,264,15,1275),(13184,1,220,315,26),(13185,1,220,400,26),(13186,1,220,500,26),(13187,1,405,19,0),(13188,1,405,21,0),(13189,1,405,23,0),(13196,1,279,31,0),(13197,1,279,35,0),(13198,1,279,39,0),(13199,1,378,30,31),(13200,1,378,35,31),(13201,1,378,40,31),(13204,1,264,180,8261),(13205,1,264,360,8261),(13206,1,264,540,8261),(13207,1,288,100,8),(13208,1,288,100,8),(13209,1,288,100,8),(13210,1,325,70,0),(13211,1,325,75,0),(13212,1,325,80,0),(13213,1,220,285,8),(13214,1,220,315,8),(13215,1,220,350,8),(13216,1,220,390,8),(13217,1,220,440,8),(13218,1,216,750,8),(13219,1,114,-12,0),(13220,1,114,-15,0),(13221,1,114,-18,0),(13222,1,310,240000,0),(13222,2,139,6197,0),(13222,3,411,512,0),(13223,1,310,300000,0),(13223,2,139,6197,0),(13223,3,411,512,0),(13226,1,360,60,27593),(13238,1,320,9,0),(13239,1,320,10,0),(13240,1,320,11,0),(13262,1,264,1008,102),(13263,1,264,1152,102),(13264,1,264,1290,102),(13278,1,213,25,0),(13281,1,318,31,0),(13286,1,278,900,102200),(13286,2,440,92,100),(13294,1,339,10,8105),(13294,2,142,65,0),(13294,3,311,0,0),(13294,4,134,70,0),(13294,5,348,10,0),(13294,6,137,0,0),(13294,7,339,10,8105),(13294,8,142,65,0),(13294,9,311,0,0),(13294,10,134,70,0),(13294,11,348,10,0),(13294,12,137,100,0),(13294,13,339,10,8105),(13294,14,142,65,0),(13294,15,311,0,0),(13294,16,134,70,0),(13294,17,348,10,0),(13294,18,137,79,0),(13294,19,339,10,8105),(13294,20,142,65,0),(13294,21,311,0,0),(13294,22,134,70,0),(13294,23,348,10,0),(13294,24,137,147,0),(13294,25,339,10,11404),(13294,26,142,71,0),(13294,27,311,0,0),(13294,28,134,75,0),(13294,29,348,10,0),(13294,30,137,0,0),(13294,31,339,10,11404),(13294,32,142,71,0),(13294,33,311,0,0),(13294,34,134,75,0),(13294,35,348,10,0),(13294,36,137,100,0),(13294,37,339,10,11404),(13294,38,142,71,0),(13294,39,311,0,0),(13294,40,134,75,0),(13294,41,348,10,0),(13294,42,137,79,0),(13294,43,339,10,11404),(13294,44,142,71,0),(13294,45,311,0,0),(13294,46,134,75,0),(13294,47,348,10,0),(13294,48,137,147,0),(13294,49,339,10,13199),(13294,50,142,76,0),(13294,51,311,0,0),(13294,52,134,80,0),(13294,53,348,10,0),(13294,54,137,0,0),(13294,55,339,10,13199),(13294,56,142,76,0),(13294,57,311,0,0),(13294,58,134,80,0),(13294,59,348,10,0),(13294,60,137,100,0),(13294,61,339,10,13199),(13294,62,142,76,0),(13294,63,311,0,0),(13294,64,134,80,0),(13294,65,348,10,0),(13294,66,137,79,0),(13294,67,339,10,13199),(13294,68,142,76,0),(13294,69,311,0,0),(13294,70,134,80,0),(13294,71,348,10,0),(13294,72,137,147,0),(13294,73,339,10,13830),(13294,74,142,81,0),(13294,75,311,0,0),(13294,76,134,85,0),(13294,77,348,10,0),(13294,78,137,0,0),(13294,79,339,10,13830),(13294,80,142,81,0),(13294,81,311,0,0),(13294,82,134,85,0),(13294,83,348,10,0),(13294,84,137,100,0),(13294,85,339,10,13830),(13294,86,142,81,0),(13294,87,311,0,0),(13294,88,134,85,0),(13294,89,348,10,0),(13294,90,137,79,0),(13294,91,339,10,13830),(13294,92,142,81,0),(13294,93,311,0,0),(13294,94,134,85,0),(13294,95,348,10,0),(13294,96,137,147,0),(13294,97,339,10,27527),(13294,98,142,86,0),(13294,99,311,0,0),(13294,100,134,90,0),(13294,101,348,10,0),(13294,102,137,0,0),(13294,103,339,10,27527),(13294,104,142,86,0),(13294,105,311,0,0),(13294,106,134,90,0),(13294,107,348,10,0),(13294,108,137,100,0),(13294,109,339,10,27527),(13294,110,142,86,0),(13294,111,311,0,0),(13294,112,134,90,0),(13294,113,348,10,0),(13294,114,137,79,0),(13294,115,339,10,27527),(13294,116,142,86,0),(13294,117,311,0,0),(13294,118,134,90,0),(13294,119,348,10,0),(13294,120,137,147,0),(13294,121,339,10,30644),(13294,122,142,91,0),(13294,123,311,0,0),(13294,124,134,95,0),(13294,125,348,10,0),(13294,126,137,0,0),(13294,127,339,10,30644),(13294,128,142,91,0),(13294,129,311,0,0),(13294,130,134,95,0),(13294,131,348,10,0),(13294,132,137,100,0),(13294,133,339,10,30644),(13294,134,142,91,0),(13294,135,311,0,0),(13294,136,134,95,0),(13294,137,348,10,0),(13294,138,137,79,0),(13294,139,339,10,30644),(13294,140,142,91,0),(13294,141,311,0,0),(13294,142,134,95,0),(13294,143,348,10,0),(13294,144,137,147,0),(13295,1,339,10,8105),(13295,2,142,65,0),(13295,3,311,0,0),(13295,4,134,70,0),(13295,5,348,10,0),(13295,6,137,0,0),(13295,7,339,10,8105),(13295,8,142,65,0),(13295,9,311,0,0),(13295,10,134,70,0),(13295,11,348,10,0),(13295,12,137,100,0),(13295,13,339,10,8105),(13295,14,142,65,0),(13295,15,311,0,0),(13295,16,134,70,0),(13295,17,348,10,0),(13295,18,137,79,0),(13295,19,339,10,8105),(13295,20,142,65,0),(13295,21,311,0,0),(13295,22,134,70,0),(13295,23,348,10,0),(13295,24,137,147,0),(13295,25,339,10,11404),(13295,26,142,71,0),(13295,27,311,0,0),(13295,28,134,75,0),(13295,29,348,10,0),(13295,30,137,0,0),(13295,31,339,10,11404),(13295,32,142,71,0),(13295,33,311,0,0),(13295,34,134,75,0),(13295,35,348,10,0),(13295,36,137,100,0),(13295,37,339,10,11404),(13295,38,142,71,0),(13295,39,311,0,0),(13295,40,134,75,0),(13295,41,348,10,0),(13295,42,137,79,0),(13295,43,339,10,11404),(13295,44,142,71,0),(13295,45,311,0,0),(13295,46,134,75,0),(13295,47,348,10,0),(13295,48,137,147,0),(13295,49,339,10,13199),(13295,50,142,76,0),(13295,51,311,0,0),(13295,52,134,80,0),(13295,53,348,10,0),(13295,54,137,0,0),(13295,55,339,10,13199),(13295,56,142,76,0),(13295,57,311,0,0),(13295,58,134,80,0),(13295,59,348,10,0),(13295,60,137,100,0),(13295,61,339,10,13199),(13295,62,142,76,0),(13295,63,311,0,0),(13295,64,134,80,0),(13295,65,348,10,0),(13295,66,137,79,0),(13295,67,339,10,13199),(13295,68,142,76,0),(13295,69,311,0,0),(13295,70,134,80,0),(13295,71,348,10,0),(13295,72,137,147,0),(13295,73,339,10,13830),(13295,74,142,81,0),(13295,75,311,0,0),(13295,76,134,85,0),(13295,77,348,10,0),(13295,78,137,0,0),(13295,79,339,10,13830),(13295,80,142,81,0),(13295,81,311,0,0),(13295,82,134,85,0),(13295,83,348,10,0),(13295,84,137,100,0),(13295,85,339,10,13830),(13295,86,142,81,0),(13295,87,311,0,0),(13295,88,134,85,0),(13295,89,348,10,0),(13295,90,137,79,0),(13295,91,339,10,13830),(13295,92,142,81,0),(13295,93,311,0,0),(13295,94,134,85,0),(13295,95,348,10,0),(13295,96,137,147,0),(13295,97,339,10,27527),(13295,98,142,86,0),(13295,99,311,0,0),(13295,100,134,90,0),(13295,101,348,10,0),(13295,102,137,0,0),(13295,103,339,10,27527),(13295,104,142,86,0),(13295,105,311,0,0),(13295,106,134,90,0),(13295,107,348,10,0),(13295,108,137,100,0),(13295,109,339,10,27527),(13295,110,142,86,0),(13295,111,311,0,0),(13295,112,134,90,0),(13295,113,348,10,0),(13295,114,137,79,0),(13295,115,339,10,27527),(13295,116,142,86,0),(13295,117,311,0,0),(13295,118,134,90,0),(13295,119,348,10,0),(13295,120,137,147,0),(13295,121,339,10,30644),(13295,122,142,91,0),(13295,123,311,0,0),(13295,124,134,95,0),(13295,125,348,10,0),(13295,126,137,0,0),(13295,127,339,10,30644),(13295,128,142,91,0),(13295,129,311,0,0),(13295,130,134,95,0),(13295,131,348,10,0),(13295,132,137,100,0),(13295,133,339,10,30644),(13295,134,142,91,0),(13295,135,311,0,0),(13295,136,134,95,0),(13295,137,348,10,0),(13295,138,137,79,0),(13295,139,339,10,30644),(13295,140,142,91,0),(13295,141,311,0,0),(13295,142,134,95,0),(13295,143,348,10,0),(13295,144,137,147,0),(13296,1,125,49,49),(13296,2,137,0,0),(13296,3,141,1,0),(13296,4,139,-6233,0),(13296,5,139,-6265,0),(13296,6,125,49,49),(13296,7,137,147,0),(13296,8,141,1,0),(13297,1,125,52,52),(13297,2,137,0,0),(13297,3,141,1,0),(13297,4,139,-6233,0),(13297,5,139,-6265,0),(13297,6,125,52,52),(13297,7,137,147,0),(13297,8,141,1,0),(13299,1,319,31,0),(13302,1,274,44,0),(13305,1,189,19,0),(13308,1,265,87,0),(13313,1,15,29,0),(13318,1,97,850,0),(13323,1,320,15,0),(13326,1,330,155,0),(13326,2,330,155,1),(13326,3,330,155,2),(13326,4,330,155,3),(13326,5,330,155,28),(13326,6,330,155,36),(13332,1,330,155,0),(13332,2,330,155,1),(13332,3,330,155,2),(13332,4,330,155,3),(13332,5,330,155,28),(13332,6,330,155,36),(13332,7,330,155,77),(13338,1,1,370,0),(13343,1,1,340,0),(13348,1,1,440,0),(13353,1,1,330,0),(13358,1,1,540,0),(13396,1,375,40,0),(13404,1,273,8,0),(13411,1,399,4,0),(13411,2,138,1,0),(13411,3,137,0,0),(13411,4,348,10,0),(13411,5,311,0,0),(13411,6,141,1,0),(13411,7,134,254,0),(13411,8,137,-39,0),(13413,1,399,12,0),(13413,2,141,1,0),(13413,3,138,0,0),(13413,4,142,255,0),(13413,5,391,0,0),(13413,6,311,0,0),(13413,7,137,-152,0),(13413,8,411,100350,0),(13413,9,137,-39,0),(13415,1,264,150,705),(13415,2,264,150,1092),(13415,3,264,150,10396),(13415,4,264,150,10397),(13416,1,264,20,626),(13438,1,266,29,0),(13449,1,264,2,11073),(13463,1,264,90,458),(13474,1,264,120,444),(13477,1,126,20,0),(13477,2,134,95,0),(13477,3,135,4,0),(13477,4,135,5,0),(13485,1,279,3,0),(13502,1,375,160,0),(13508,1,378,5,3),(13511,1,279,43,0),(13520,1,292,70,0),(13521,1,293,25,0),(13533,1,378,55,96),(13545,1,323,30787,0),(13562,1,264,480,872),(13565,1,264,60,3804),(13568,1,264,60,876),(13578,1,244,30,0),(13589,1,279,34,0),(13590,1,279,38,0),(13598,1,339,20,30809),(13598,2,137,21,0),(13598,3,385,-18000,0),(13598,4,339,20,30809),(13598,5,137,343,0),(13598,6,385,-18000,0),(13601,1,231,22,0),(13607,1,126,4,4),(13607,2,137,21,0),(13607,3,231,4,4),(13610,1,266,47,0),(13613,1,220,260,10),(13616,1,220,150,2),(13616,2,220,150,3),(13616,3,220,150,77),(13617,1,220,375,2),(13617,2,220,375,3),(13617,3,220,375,77),(13618,1,220,500,2),(13618,2,220,500,3),(13618,3,220,500,77),(13621,1,218,11,0),(13627,1,59,-59,0),(13628,1,59,-64,0),(13630,1,398,10000,0),(13630,2,137,152,0),(13667,1,287,1,0),(13667,2,385,8054,0),(13675,1,218,24,0),(13684,1,399,2,0),(13684,2,140,2,0),(13684,3,348,10,0),(13684,4,138,0,0),(13684,5,137,-152,0),(13684,6,137,-39,0),(13685,1,399,3,0),(13685,2,140,2,0),(13685,3,348,10,0),(13685,4,138,0,0),(13685,5,137,-152,0),(13685,6,137,-39,0),(13686,1,399,4,0),(13686,2,140,2,0),(13686,3,348,10,0),(13686,4,138,0,0),(13686,5,137,-152,0),(13686,6,137,-39,0),(13689,1,127,10,0),(13689,2,139,27592,0),(13689,3,139,31548,0),(13707,1,274,26,0),(13710,1,280,65,0),(13713,1,218,26,0),(13753,1,264,360,534),(13758,1,264,360,602),(13763,1,287,4,0),(13763,2,137,31,0),(13763,3,136,5,0),(13764,1,264,60,535),(13767,1,439,0,153514),(13767,2,345,90,22),(13773,1,279,21,0),(13774,1,279,23,0),(13775,1,279,25,0),(13779,1,288,100,8),(13782,1,220,490,8),(13789,1,216,850,8),(13790,1,216,950,8),(13795,1,258,73,0),(13798,1,114,-21,0),(13804,1,378,4,3),(13813,1,220,150,28),(13813,2,220,150,0),(13813,3,427,23598,9),(13813,4,428,28,0),(13813,5,428,0,0),(13820,1,220,325,26),(13820,2,220,325,30),(13820,3,220,325,38),(13823,1,220,295,21),(13823,2,220,295,23),(13823,3,220,670,52),(13823,4,220,295,28),(13826,1,405,25,0),(13829,1,220,550,26),(13835,1,283,300,0),(13841,1,264,17,469),(13873,1,264,30,961),(13878,1,264,60,609),(13881,1,264,60,387),(13884,1,265,87,0),(13889,1,264,60,1012),(13894,1,327,13,0),(13905,1,310,24000,0),(13905,2,385,15319,0),(13908,1,310,3000,0),(13908,2,385,15307,0),(13908,3,385,15407,0),(13908,4,385,15507,0),(13908,5,385,15607,0),(13911,1,310,3000,0),(13911,2,385,16005,0),(13911,3,310,3000,0),(13911,4,385,15405,0),(13911,5,385,15505,0),(13911,6,385,15605,0),(13911,7,411,2,0),(13917,1,264,120,606),(13921,1,114,-66,0),(13924,1,114,-64,0),(13927,1,114,-25,0),(13930,1,341,310,0),(13933,1,262,80,0),(13943,1,262,80,1),(13953,1,262,80,2),(13963,1,262,80,3),(13973,1,262,80,4),(13983,1,262,80,5),(13993,1,262,80,6),(14011,1,264,30,10394),(14017,1,69,10,0),(14018,1,69,10,0),(14026,1,185,3,2),(14026,2,185,3,3),(14026,3,185,3,77),(14026,4,220,50,2),(14026,5,220,50,3),(14026,6,220,50,77),(14029,1,395,5,5),(14029,2,385,9758,0),(14029,3,385,9858,0),(14029,4,385,9958,0),(14032,1,181,100,0),(14037,1,264,180,804),(14040,1,264,180,300),(14043,1,85,32197,0),(14046,1,264,90,87),(14056,1,310,360000,0),(14056,2,139,4504,0),(14059,1,310,-180000,0),(14059,2,139,4520,0),(14062,1,264,60,821),(14065,1,264,60,3215),(14068,1,264,60,3216),(14076,1,310,480000,0),(14076,2,139,4518,0),(14082,1,360,26,32314),(14085,1,264,2,741),(14088,1,264,30,769),(14091,1,264,120,701),(14094,1,124,325,350),(14094,2,385,19,0),(14094,3,144,0,0),(14094,4,403,3,0),(14094,5,404,48,0),(14094,6,385,-21768,0),(14097,1,85,32317,5),(14100,1,127,50,0),(14100,2,137,21,0),(14100,3,143,1,0),(14100,4,134,253,0),(14100,5,348,1,0),(14101,1,310,2520000,0),(14101,2,139,4506,0),(14101,3,310,2520000,0),(14101,4,385,11122,0),(14101,5,385,11222,0),(14101,6,385,11322,0),(14101,7,385,11522,0),(14115,1,287,1,0),(14115,2,385,16130,0),(14129,1,220,60,36),(14129,2,427,32327,3),(14129,3,428,36,0),(14130,1,220,90,36),(14130,2,427,32327,5),(14130,3,428,36,0),(14132,1,264,240,2234),(14135,1,310,132000,0),(14135,2,385,13005,0),(14135,3,385,12423,0),(14135,4,385,12504,0),(14135,5,310,132000,0),(14135,6,139,4676,0),(14135,7,411,512,0),(14138,1,310,480000,0),(14138,2,139,4695,0),(14138,3,411,512,0),(14140,1,310,24000,0),(14140,2,385,13007,0),(14140,3,385,12105,0),(14140,4,385,12205,0),(14140,5,310,72000,0),(14140,6,385,12305,0),(14140,7,385,12405,0),(14140,8,385,12505,0),(14140,9,411,512,0),(14141,1,185,2,36),(14144,1,287,1,0),(14144,2,385,13204,0),(14144,3,411,512,0),(14148,1,310,90000,0),(14148,2,139,4691,0),(14151,1,185,2,26),(14151,2,220,100,26),(14154,1,264,2100,276),(14157,1,216,150,26),(14160,1,264,60,7001),(14163,1,287,1,0),(14163,2,385,16178,0),(14163,3,411,128,0),(14166,1,264,60,945),(14169,1,310,202500,0),(14169,2,139,8030,0),(14169,3,411,256,0),(14173,1,310,1440000,0),(14173,2,139,4516,0),(14173,3,411,256,0),(14176,1,264,660,8261),(14179,1,287,1,0),(14179,2,385,5830,0),(14179,3,411,256,0),(14180,1,287,1,0),(14180,2,139,8030,0),(14180,3,411,256,0),(14181,1,247,25,20),(14186,1,247,25,76),(14196,1,264,2340,465),(14199,1,264,720,499),(14200,1,288,15,2),(14200,2,288,15,3),(14200,3,288,15,51),(14200,4,288,15,77),(14203,1,310,150000,0),(14203,2,385,3419,0),(14203,3,385,14005,0),(14203,4,385,3519,0),(14203,5,411,65536,0),(14210,1,310,40000,0),(14210,2,139,1546,0),(14210,3,310,40000,0),(14210,4,385,4357,0),(14210,5,385,4457,0),(14210,6,385,4557,0),(14210,7,385,4657,0),(14210,8,411,4,0),(14213,1,264,120,1065),(14218,1,232,23,4544),(14223,1,264,40,47),(14225,1,127,16,0),(14225,2,385,3283,0),(14225,3,411,1024,0),(14238,1,264,12,1041),(14241,1,264,180,386),(14244,1,286,100,0),(14244,2,138,0,0),(14244,3,143,1,0),(14244,4,348,1,0),(14244,5,411,64,0),(14249,1,392,200,0),(14249,2,138,1,0),(14249,3,348,1,0),(14254,1,287,1,0),(14254,2,385,2025,0),(14254,3,385,5121,0),(14254,4,385,5221,0),(14254,5,385,5562,0),(14259,1,287,1,0),(14259,2,139,23585,0),(14275,1,239,20,0),(14278,1,287,4,0),(14278,2,385,16439,0),(14278,3,411,32768,0),(14279,1,320,8,0),(14283,1,127,17,0),(14283,2,385,3151,0),(14283,3,385,5887,0),(14286,1,287,1,0),(14286,2,385,4877,0),(14289,1,127,10,0),(14289,2,385,2754,0),(14292,1,127,10,0),(14292,2,385,3286,0),(14295,1,264,1,3816),(14301,1,405,5,0),(14304,1,264,45,8341),(14308,1,264,20,431),(14311,1,264,360,430),(14314,1,264,8,901),(14318,1,127,10,0),(14318,2,139,21754,0),(14328,1,264,6,1154),(14331,1,264,120,515),(14341,1,264,360,748),(14349,1,294,0,205),(14361,1,294,35,109),(14364,1,264,90,173),(14367,1,445,1,0),(14764,1,339,10,33950),(14764,2,137,31,0),(15074,1,264,5,15073),(15100,1,264,2,467),(15105,1,264,120,131),(15108,1,310,60000,0),(15108,2,385,15521,0),(15108,3,411,2,0),(15111,1,287,1,0),(15111,2,385,21778,0),(15113,1,287,3,0),(15113,2,385,21778,0),(15113,3,411,2,0),(15120,1,264,60,800),(15123,1,310,120000,0),(15123,2,385,15422,0),(15123,3,411,2,0),(15126,1,310,1000,0),(15126,2,385,15212,0),(15126,3,411,2,0),(15132,1,264,10,660),(15135,1,287,1,0),(15135,2,139,32313,0),(15141,1,219,420,2400),(15150,1,127,10,0),(15150,2,385,10505,0),(15150,3,385,10105,0),(15150,4,385,10205,0),(15150,5,385,10305,0),(15150,6,385,10405,0),(15150,7,385,10605,0),(15153,1,287,1,0),(15153,2,139,4518,0),(15154,1,287,1,0),(15154,2,139,32312,0),(15155,1,287,1,0),(15155,2,385,10320,0),(15155,3,385,10420,0),(15155,4,385,10520,0),(15158,1,287,1,0),(15158,2,385,32307,0),(15159,1,287,1,0),(15159,2,385,27537,0),(15162,1,264,120,659),(15168,1,264,60,657),(15172,1,302,430,430),(15172,2,385,99,0),(15174,1,264,40,9400),(15179,1,127,10,0),(15179,2,139,21804,0),(15179,3,139,38280,0),(15182,1,264,840,9403),(15188,1,239,62,0),(15194,1,287,1,0),(15194,2,385,13407,0),(15194,3,385,13507,0),(15204,1,264,60,390),(15207,1,264,60,323),(15217,1,339,10,38319),(15217,2,385,11006,0),(15217,3,385,7108,0),(15217,4,385,7208,0),(15217,5,385,7308,0),(15217,6,385,7408,0),(15217,7,385,7508,0),(15217,8,385,7608,0),(15220,1,287,1,0),(15220,2,385,11065,0),(15223,1,287,1,0),(15223,2,385,11067,0),(15226,1,287,1,0),(15226,2,385,11064,0),(15229,1,287,1,0),(15229,2,385,11066,0),(15232,1,339,100,38322),(15232,2,385,7518,0),(15238,1,264,240,621),(15238,2,264,240,622),(15238,3,264,240,623),(15238,4,264,240,784),(15238,5,264,240,785),(15238,6,264,240,786),(15238,7,264,240,787),(15238,8,264,240,624),(15253,1,127,10,0),(15253,2,385,32322,0),(15258,1,264,540,184),(15270,1,264,1980,7003),(15280,1,264,720,778),(15283,1,310,1000,0),(15283,2,385,11402,0),(15283,3,385,11502,0),(15283,4,385,11441,0),(15283,5,385,11541,0),(15283,6,385,11641,0),(15288,1,220,50,0),(15288,2,220,50,1),(15288,3,220,100,2),(15288,4,220,100,3),(15288,5,220,50,36),(15288,6,220,100,77),(15295,1,127,10,0),(15295,2,385,21654,0),(15314,1,264,25920,36),(15317,1,264,1728,35),(15320,1,264,150,558),(15328,1,339,25,38037),(15328,2,138,1,0),(15328,3,142,65,0),(15328,4,137,35,0),(15328,5,134,90,0),(15328,6,339,25,38037),(15328,7,138,1,0),(15328,8,142,65,0),(15328,9,137,36,0),(15328,10,134,90,0),(15328,11,339,25,38037),(15328,12,138,1,0),(15328,13,142,65,0),(15328,14,137,369,0),(15328,15,134,90,0),(15328,16,339,25,38037),(15328,17,138,1,0),(15328,18,142,65,0),(15328,19,137,116,0),(15328,20,134,90,0),(15342,1,287,1,0),(15342,2,385,23605,0),(15344,1,264,360,38),(15348,1,264,240,9504),(15356,1,232,20,4544),(15358,1,287,1,0),(15358,2,385,32350,0),(15359,1,264,960,50),(15363,1,264,240,447),(15371,1,264,1,3729),(15374,1,195,20,0),(15383,1,310,1000,0),(15383,2,385,5132,0),(15383,3,385,5232,0),(15383,4,385,5332,0),(15383,5,385,5432,0),(15383,6,385,5532,0),(15383,7,385,5032,0),(15383,8,385,5632,0),(15389,1,127,16,0),(15389,2,385,23575,0),(15396,1,127,20,20),(15396,2,137,0,0),(15396,3,138,0,0),(15396,4,141,1,0),(15396,5,143,3000,0),(15396,6,127,20,20),(15396,7,385,16555,0),(15396,8,385,16655,0),(15397,1,264,1260,494),(15403,1,264,10,8604),(15406,1,127,10,10),(15406,2,385,37097,0),(15414,1,287,1,0),(15414,2,139,30736,0),(15421,1,264,3600,245),(15422,1,132,15,15),(15426,1,239,62,0),(15429,1,220,135,2),(15432,1,184,5,-1),(15438,1,310,180000,0),(15438,2,385,8316,0),(15438,3,411,128,0),(15441,1,279,38,0),(15444,1,288,60,26),(15450,1,310,3000,0),(15450,2,385,8202,0),(15450,3,385,8302,0),(15450,4,385,8402,0),(15450,5,385,8502,0),(15450,6,385,8602,0),(15450,7,411,128,0),(15453,1,310,60000,0),(15453,2,385,8421,0),(15453,3,411,128,0),(15456,1,264,5,470),(15466,1,126,20,20),(15466,2,139,12576,0),(15466,3,126,20,20),(15466,4,139,12828,0),(15469,1,264,240,1120),(15472,1,264,1260,521),(15478,1,264,120,578),(15485,1,339,10,38417),(15485,2,142,96,0),(15485,3,311,0,0),(15485,4,134,105,0),(15485,5,348,10,0),(15485,6,137,0,0),(15485,7,339,10,38417),(15485,8,142,96,0),(15485,9,311,0,0),(15485,10,134,105,0),(15485,11,348,10,0),(15485,12,137,100,0),(15485,13,339,10,38417),(15485,14,142,96,0),(15485,15,311,0,0),(15485,16,134,105,0),(15485,17,348,10,0),(15485,18,137,79,0),(15485,19,339,10,38417),(15485,20,142,96,0),(15485,21,311,0,0),(15485,22,134,105,0),(15485,23,348,10,0),(15485,24,137,147,0),(15493,1,127,10,0),(15493,2,137,31,0),(15502,1,310,240000,0),(15502,2,139,4673,0),(15502,3,411,512,0),(15509,1,310,3000,0),(15509,2,385,12315,0),(15509,3,385,12415,0),(15509,4,385,12515,0),(15509,5,385,12615,0),(15509,10,411,512,0),(15512,1,288,50,8),(15516,1,126,20,0),(15516,2,139,3066,0),(15516,3,411,256,0),(15517,1,127,16,0),(15517,2,139,3066,0),(15517,3,411,256,0),(15526,1,264,120,3702),(15529,1,247,60,53),(15540,1,185,5,1),(15543,1,185,5,0),(15546,1,185,5,36),(15549,1,264,15,244),(15552,1,264,840,3710),(15555,1,339,5,38103),(15555,2,385,3208,0),(15555,3,385,3308,0),(15555,4,385,3408,0),(15555,5,385,3508,0),(15564,1,220,68,51),(15571,1,264,180,351),(15579,1,287,2,0),(15579,2,139,16106,0),(15585,1,274,44,0),(15591,1,127,10,0),(15591,2,139,16839,0),(15598,1,264,180,759),(15598,2,264,180,1150),(15598,3,264,180,1151),(15598,4,264,180,1152),(15602,1,124,1,0),(15602,2,138,0,0),(15602,3,141,1,0),(15602,4,348,10,0),(15606,1,244,-25,0),(15609,1,383,10,38134),(15609,2,141,1,0),(15609,3,348,10,0),(15609,4,142,85,0),(15609,5,143,3000,0),(15622,1,127,5,5),(15622,2,137,0,0),(15622,3,138,0,0),(15622,4,141,1,0),(15625,1,330,10,8),(15632,1,264,1728,789),(15634,1,310,1500,0),(15634,2,385,12110,0),(15634,3,385,12210,0),(15634,4,385,12310,0),(15634,5,385,12410,0),(15634,6,385,12510,0),(15635,1,310,3000,0),(15635,2,385,12110,0),(15635,3,385,12210,0),(15635,4,385,12310,0),(15635,5,385,12410,0),(15635,6,385,12510,0),(15648,1,185,3,74),(15694,1,190,550,0),(15714,1,320,12,0),(15719,1,320,12,0),(15746,1,421,20,0),(15746,2,139,16097,0),(15746,3,139,23612,0),(15746,4,139,32196,0),(15746,5,139,32565,0),(15746,6,423,6,0),(15746,7,422,5,0),(15746,8,411,2,0),(15768,1,125,1,2),(15768,2,136,46,0),(15772,1,128,80,80),(15772,2,138,1,0),(15772,3,140,1,0),(15772,4,311,0,0),(15772,5,411,66434,0),(15772,6,137,-40,0),(15773,1,128,80,80),(15773,2,138,1,0),(15773,3,140,1,0),(15773,4,311,0,0),(15773,5,411,256,0),(15773,6,137,-40,0),(15773,7,391,1,0),(15778,1,303,27500,32500),(15778,2,139,2766,0),(15833,1,264,60,2045),(15836,1,264,60,463),(15891,1,264,20,988),(15893,1,264,20,987),(15895,1,264,20,986),(15908,1,220,125,0),(15908,2,220,200,2),(15909,1,220,155,0),(15909,2,220,290,2),(15910,1,220,185,0),(15910,2,220,385,2),(15954,1,292,49,0),(15961,1,129,20,0),(15961,2,385,12768,0),(15961,3,411,256,0),(16062,1,339,20,40941),(16062,2,138,0,0),(16062,3,137,31,0),(16062,4,311,0,0),(16084,1,158,1,0),(16087,1,264,432,53),(16094,1,264,3024,43),(16104,1,10,0,0),(16109,1,69,3000,0),(16114,1,114,2,0),(16117,1,171,2,0),(16120,1,226,1,0),(16121,1,310,840000,0),(16121,2,139,4670,0),(16124,1,264,2,3711),(16128,1,127,8,0),(16128,2,139,13143,0),(16131,1,130,10,0),(16131,2,385,18000,0),(16137,1,287,1,0),(16137,2,385,21821,0),(16140,1,287,1,0),(16140,2,385,30666,0),(16146,1,339,2,41107),(16146,2,142,95,0),(16146,3,138,1,0),(16146,4,137,0,0),(16146,5,348,10,0),(16146,6,141,1,0),(16149,1,129,20,0),(16149,2,385,4357,0),(16149,3,385,4457,0),(16149,4,385,4557,0),(16149,5,411,4,0),(16152,1,339,3,41108),(16152,2,142,90,0),(16152,3,138,0,0),(16152,4,137,0,0),(16152,5,348,10,0),(16152,6,141,1,0),(16156,1,392,1000,0),(16156,2,385,32341,0),(16159,1,287,1,0),(16159,2,385,32307,0),(16164,1,294,0,195),(16170,1,360,70,41119),(16173,1,320,12,0),(16176,1,264,2,337),(16179,1,288,8,7),(16180,1,264,5,584),(16186,1,288,100,30),(16189,1,339,12,41127),(16189,2,138,0,0),(16189,3,142,70,0),(16189,4,411,32,0),(16189,5,348,1,0),(16189,6,141,1,0),(16192,1,339,12,41130),(16192,2,138,0,0),(16192,3,142,70,0),(16192,4,403,4,0),(16192,5,348,1,0),(16192,6,404,2,0),(16192,7,141,1,0),(16208,1,247,5,27),(16211,1,287,1,0),(16211,2,139,23581,0),(16211,3,139,32359,0),(16218,1,264,10,403),(16221,1,287,1,0),(16221,2,385,23586,0),(16225,1,264,1,219),(16230,1,310,1000,0),(16230,2,385,2431,0),(16230,3,385,2531,0),(16230,4,385,2545,0),(16230,5,385,2631,0),(16235,1,126,35,0),(16235,2,134,100,0),(16235,3,135,3,0),(16238,1,287,2,0),(16238,2,385,23693,0),(16238,3,460,1,0),(16249,1,275,100,0),(16257,1,429,37114,2),(16257,2,428,52,0),(16260,1,427,41160,3),(16260,2,428,23,0),(16266,1,224,50,8),(16266,2,173,4,0),(16267,1,250,52,0),(16272,1,175,2,0),(16276,1,247,10,36),(16287,1,264,20,669),(16297,1,264,600,553),(16300,1,264,60,668),(16303,1,264,240,3506),(16306,1,264,1260,777),(16317,1,220,100,-1),(16327,1,310,720000,0),(16327,2,139,5040,0),(16330,1,330,105,74),(16336,1,264,30,1257),(16339,1,264,10,773),(16342,1,127,10,0),(16342,2,385,38115,0),(16361,1,399,5,0),(16361,2,141,1,0),(16361,3,138,0,0),(16361,4,134,254,0),(16361,5,348,10,0),(16361,6,137,0,0),(16361,7,311,0,0),(16361,8,137,-152,0),(16361,9,137,-39,0),(16366,1,286,200,0),(16366,2,138,0,0),(16366,3,143,1,0),(16366,4,348,10,0),(16371,1,129,20,0),(16371,2,385,2754,0),(16380,1,264,30,2061),(16386,1,264,10,2064),(16392,1,264,90,2202),(16396,1,127,5,5),(16396,2,137,0,0),(16396,3,138,0,0),(16396,4,141,1,0),(16402,1,131,60,60),(16402,2,348,10,0),(16402,3,137,-32,0),(16414,1,317,16,0),(16419,1,426,6,0),(16420,1,426,7,0),(16421,1,426,8,0),(16440,1,247,65,76),(16475,1,218,4,0),(16489,1,294,29,102),(16536,1,405,3,0),(16604,1,264,1440,180),(16644,1,264,60,747),(16666,1,264,60,742),(16730,1,347,31,0),(16745,1,264,60,706),(16887,1,280,75,0),(16890,1,218,21,0),(17004,1,225,35,0),(17206,1,264,12,601),(17209,1,264,180,111),(17212,1,264,60,10367),(17215,1,378,2,22),(17215,2,378,2,31),(17215,3,378,2,3),(17215,4,378,2,20),(17218,1,127,10,0),(17218,2,139,27560,0),(17229,1,220,900,3),(17229,2,220,900,2),(17229,3,220,900,77),(17235,1,127,15,0),(17235,2,385,12609,0),(17239,1,310,2400000,0),(17239,2,139,4500,0),(17239,3,411,8,0),(17242,1,378,1,22),(17242,2,378,1,31),(17242,3,378,1,3),(17242,4,378,1,20),(17245,1,378,1,22),(17245,2,378,1,31),(17245,3,378,1,3),(17245,4,378,1,20),(17249,1,264,120,651),(17252,1,310,3000,0),(17252,2,385,13438,0),(17252,3,385,13538,0),(17252,4,385,13638,0),(17258,1,399,2,0),(17258,2,137,457,0),(17258,3,399,2,0),(17258,4,134,253,0),(17258,5,142,100,0),(17258,6,138,0,0),(17258,7,136,13,0),(17258,8,136,20,0),(17258,9,137,-39,0),(17267,1,127,10,0),(17267,2,385,13507,0),(17267,3,385,13107,0),(17267,4,385,13207,0),(17267,5,385,13307,0),(17267,6,385,13407,0),(17267,7,385,13607,0),(17281,1,287,1,0),(17281,2,385,16646,0),(17288,1,264,1440,41),(17289,1,264,180,1062),(17295,1,229,62,0),(17307,1,127,8,0),(17307,2,139,38058,0),(17310,1,310,14000,0),(17310,2,139,8007,0),(17310,3,310,14000,0),(17310,4,385,4140,0),(17310,5,385,4240,0),(17310,6,385,4340,0),(17310,7,385,4440,0),(17310,8,385,4540,0),(17310,9,385,4640,0),(17317,1,264,60,1270),(17334,1,287,12,0),(17334,2,385,16188,0),(17336,1,287,1,0),(17336,2,385,32348,0),(17339,1,264,12,760),(17350,1,264,110,170),(17357,1,287,1,0),(17357,2,137,100,0),(17357,3,138,1,0),(17361,1,264,60,405),(17361,2,264,60,426),(17365,1,287,6,0),(17365,2,385,5240,0),(17365,3,385,5340,0),(17365,4,385,5440,0),(17365,5,385,5540,0),(17365,6,385,5640,0),(17370,1,287,1,0),(17370,2,138,0,0),(17370,3,137,0,0),(17370,4,137,100,0),(17370,5,140,1,0),(17370,6,348,10,0),(17375,1,127,10,0),(17375,2,385,38078,0),(17391,1,264,1560,98),(17406,1,310,480000,0),(17406,2,139,4502,0),(17406,3,139,4509,0),(17409,1,214,205,0),(17409,2,259,4,0),(17409,3,172,4,0),(17414,1,264,120,673),(17418,1,247,10,74),(17428,1,288,5,51),(17436,1,264,60,372),(17439,1,287,1,0),(17439,2,385,6040,0),(17441,1,279,37,0),(17445,1,310,60000,0),(17445,2,385,3312,0),(17448,1,287,1,0),(17448,2,385,14005,0),(17448,3,385,3519,0),(17476,1,264,240,462),(17492,1,264,120,840),(17495,1,264,20,9702),(17515,1,127,25,0),(17515,2,385,7125,0),(17517,1,127,17,0),(17517,2,385,23683,0),(17517,3,460,1,0),(17522,1,264,30,764),(17533,1,287,1,0),(17533,2,139,32399,0),(17533,3,460,1,0),(17547,1,287,1,0),(17547,2,137,0,0),(17547,3,137,100,0),(17547,4,140,2,0),(17547,5,138,0,0),(17547,6,348,10,0),(17549,1,264,10,8700),(17553,1,339,8,41768),(17553,2,138,0,0),(17553,3,141,1,0),(17553,4,134,253,0),(17553,5,142,85,0),(17553,6,143,1,0),(17553,7,311,0,0),(17553,8,348,1,0),(17553,9,137,0,0),(17554,1,227,2,74),(17555,1,286,126,2),(17555,2,385,9606,0),(17555,3,303,252,0),(17555,4,385,9606,0),(17558,1,413,2,2),(17558,2,385,9603,0),(17558,3,411,2048,0),(17561,1,413,2,2),(17561,2,385,9609,0),(17561,3,411,2048,0),(17564,1,413,2,2),(17564,2,385,9619,0),(17564,3,411,2048,0),(17567,1,413,2,2),(17567,2,385,9613,0),(17567,3,411,2048,0),(17570,1,413,2,2),(17570,2,385,9604,0),(17570,3,411,2048,0),(17573,1,413,2,2),(17573,2,385,9651,0),(17573,3,411,2048,0),(17576,1,413,2,2),(17576,2,385,16652,0),(17576,3,411,4096,0),(17579,1,413,2,2),(17579,2,385,16629,0),(17579,3,411,4096,0),(17582,1,413,2,2),(17582,2,385,16650,0),(17582,3,411,4096,0),(17585,1,413,2,2),(17585,2,385,16608,0),(17585,3,411,4096,0),(17588,1,413,2,2),(17588,2,385,16615,0),(17588,3,411,4096,0),(17591,1,413,2,2),(17591,2,385,16618,0),(17591,3,411,4096,0),(17594,1,413,2,2),(17594,2,385,16625,0),(17594,3,411,4096,0),(17597,1,286,345,0),(17597,2,385,7604,0),(17600,1,413,2,2),(17600,2,385,7608,0),(17600,3,411,8192,0),(17603,1,413,2,2),(17603,2,385,7612,0),(17603,3,411,8192,0),(17606,1,392,419,0),(17606,2,385,7613,0),(17606,3,396,838,0),(17606,4,385,7613,0),(17609,1,413,2,2),(17609,2,385,7636,0),(17609,3,411,8192,0),(17612,1,413,2,2),(17612,2,385,7618,0),(17612,3,411,8192,0),(17615,1,286,539,0),(17615,2,385,7638,0),(17618,1,413,2,2),(17618,2,385,6664,0),(17618,3,411,16384,0),(17621,1,413,2,2),(17621,2,385,6648,0),(17621,3,411,16384,0),(17624,1,413,2,2),(17624,2,385,6649,0),(17624,3,411,16384,0),(17627,1,413,2,2),(17627,2,385,6611,0),(17627,3,411,16384,0),(17630,1,413,2,2),(17630,2,385,6652,0),(17630,3,411,16384,0),(17633,1,413,2,2),(17633,2,385,6655,0),(17633,3,411,16384,0),(17639,1,323,37182,100),(18972,1,214,210,0),(18972,2,259,5,0),(18972,3,172,5,0),(30050,1,69,25,0),(30050,2,97,25,0),(30050,3,190,25,0),(30050,4,328,25,0),(30100,1,1,10,0),(30100,2,2,10,0),(30100,3,341,10,0),(30150,1,262,5,0),(30150,2,262,5,1),(30150,3,262,5,2),(30150,4,262,5,3),(30150,5,262,5,4),(30150,6,262,5,5),(30150,7,262,5,6),(30150,8,159,5,0),(30150,9,0,2,0),(30150,10,15,2,0),(30150,11,189,2,0),(30150,12,317,2,0),(30150,13,318,2,0),(30175,1,271,1,0),(30180,1,264,1,8202),(30185,1,264,1,1011),(30195,1,432,1,0),(49999,1,10,0,0); +/*!40000 ALTER TABLE `aa_rank_effects` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `aa_rank_prereqs` +-- DROP TABLE IF EXISTS `aa_rank_prereqs`; -CREATE TABLE IF NOT EXISTS `aa_rank_prereqs` ( +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `aa_rank_prereqs` ( `rank_id` int(10) unsigned NOT NULL, `aa_id` int(10) NOT NULL, `points` int(10) NOT NULL, PRIMARY KEY (`rank_id`,`aa_id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; -INSERT INTO `aa_rank_prereqs` (`rank_id`, `aa_id`, `points`) VALUES - (129, 19, 3), - (131, 19, 3), - (136, 19, 3), - (141, 23, 3), - (142, 23, 3), - (143, 23, 3), - (146, 224, 3), - (162, 224, 3), - (190, 30, 3), - (191, 30, 3), - (192, 30, 3), - (195, 31, 3), - (230, 17, 3), - (231, 17, 3), - (232, 17, 3), - (255, 309, 3), - (256, 309, 3), - (257, 309, 3), - (260, 31, 3), - (261, 31, 3), - (262, 31, 3), - (263, 17, 3), - (264, 17, 3), - (265, 17, 3), - (267, 23, 3), - (268, 23, 3), - (269, 23, 3), - (446, 26, 3), - (447, 26, 3), - (448, 26, 3), - (462, 39, 1), - (463, 39, 1), - (464, 39, 1), - (468, 41, 1), - (469, 41, 1), - (470, 41, 1), - (471, 57, 1), - (472, 57, 1), - (473, 57, 1), - (474, 50, 1), - (475, 50, 1), - (476, 50, 1), - (477, 43, 1), - (478, 43, 1), - (479, 43, 1), - (480, 117, 1), - (481, 117, 1), - (482, 117, 1), - (483, 58, 1), - (484, 58, 1), - (485, 58, 1), - (489, 110, 1), - (490, 110, 1), - (491, 110, 1), - (492, 109, 1), - (493, 109, 1), - (494, 109, 1), - (495, 98, 1), - (496, 98, 1), - (497, 98, 1), - (498, 102, 1), - (499, 102, 1), - (500, 102, 1), - (501, 107, 1), - (502, 107, 1), - (503, 107, 1), - (531, 19, 3), - (532, 19, 3), - (534, 6001, 11), - (535, 6001, 11), - (536, 6001, 11), - (537, 112, 3), - (538, 112, 3), - (539, 17, 3), - (540, 17, 3), - (541, 17, 3), - (542, 309, 3), - (543, 309, 3), - (544, 309, 3), - (567, 45, 1), - (574, 125, 1), - (575, 125, 1), - (576, 125, 1), - (583, 73, 1), - (584, 73, 1), - (585, 73, 1), - (586, 120, 1), - (587, 120, 1), - (588, 120, 1), - (589, 87, 1), - (590, 87, 1), - (591, 87, 1), - (592, 30, 1), - (593, 6001, 11), - (594, 6001, 11), - (595, 6001, 11), - (596, 6000, 11), - (597, 6000, 11), - (598, 6000, 11), - (637, 23, 3), - (638, 23, 3), - (639, 23, 3), - (640, 23, 3), - (641, 23, 3), - (642, 23, 3), - (643, 55, 1), - (644, 82, 1), - (702, 30, 1), - (703, 30, 1), - (704, 30, 1), - (705, 30, 1), - (706, 30, 1), - (715, 6001, 11), - (716, 6001, 11), - (717, 6001, 11), - (754, 153, 3), - (755, 153, 3), - (756, 153, 3), - (770, 23, 3), - (771, 23, 3), - (772, 23, 3), - (773, 217, 1), - (774, 217, 1), - (775, 217, 1), - (782, 35, 1), - (783, 35, 1), - (784, 35, 1), - (806, 81, 1), - (849, 180, 3), - (850, 180, 3), - (851, 180, 3), - (886, 102, 1), - (887, 102, 1), - (893, 87, 1), - (894, 87, 1), - (924, 23, 3), - (925, 23, 3), - (931, 23, 1), - (932, 23, 1), - (933, 23, 1), - (975, 102, 1), - (1018, 227, 3), - (1041, 30, 6), - (1042, 30, 6), - (1043, 30, 6), - (1044, 310, 6), - (1045, 310, 6), - (1046, 310, 6), - (1047, 311, 3), - (1048, 311, 3), - (1049, 311, 3), - (1050, 309, 6), - (1051, 309, 6), - (1052, 309, 6), - (1102, 30, 1), - (1103, 30, 1), - (1104, 30, 1), - (1105, 30, 1), - (1106, 30, 1), - (1107, 23, 3), - (1108, 23, 3), - (1109, 23, 3), - (1110, 187, 5), - (1111, 187, 5), - (1112, 187, 5), - (1122, 176, 2), - (1126, 58, 1), - (1127, 58, 1), - (1128, 58, 1), - (1129, 125, 1), - (1130, 125, 1), - (1150, 189, 3), - (1151, 189, 3), - (1152, 189, 3), - (1163, 309, 3), - (1164, 309, 3), - (1165, 309, 3), - (1203, 19, 3), - (1204, 19, 3), - (1205, 19, 3), - (1210, 114, 6), - (1211, 114, 6), - (1212, 114, 6), - (1213, 215, 6), - (1214, 215, 6), - (1215, 215, 6), - (1242, 173, 3), - (1243, 173, 3), - (1244, 173, 3), - (1251, 61, 1), - (1252, 64, 1), - (1253, 62, 1), - (1254, 63, 1), - (1274, 175, 3), - (1275, 175, 3), - (1276, 175, 3), - (1278, 6001, 11), - (1279, 6001, 11), - (1280, 6001, 11), - (1323, 47, 1), - (1337, 308, 3), - (1338, 308, 3), - (1339, 308, 3), - (1414, 451, 1), - (1415, 451, 1), - (1416, 451, 1), - (1417, 451, 1), - (1418, 451, 1), - (1420, 17, 3), - (1421, 17, 3), - (1422, 17, 3), - (1423, 17, 3), - (1424, 17, 3), - (1425, 374, 3), - (1426, 374, 3), - (1427, 374, 3), - (1428, 374, 3), - (1429, 374, 3), - (1435, 20, 3), - (1436, 20, 3), - (1437, 20, 3), - (1458, 375, 3), - (1459, 255, 5), - (1460, 255, 5), - (1461, 255, 5), - (1471, 362, 1), - (1472, 362, 1), - (1473, 362, 1), - (1474, 362, 1), - (1475, 362, 1), - (1483, 114, 6), - (1484, 114, 6), - (1485, 114, 6), - (1486, 19, 7), - (1487, 19, 7), - (1488, 19, 7), - (1489, 19, 7), - (1490, 19, 7), - (1494, 80, 1), - (1495, 185, 6), - (1496, 185, 6), - (1497, 185, 6), - (1501, 46, 1), - (1502, 46, 1), - (1503, 46, 1), - (1504, 60, 1), - (1505, 60, 1), - (1506, 60, 1), - (1511, 175, 3), - (1512, 175, 3), - (1513, 175, 3), - (1514, 259, 6), - (1515, 259, 6), - (1516, 259, 6), - (1524, 30, 3), - (1525, 30, 3), - (1526, 30, 3), - (1543, 439, 3), - (1544, 439, 3), - (1545, 439, 3), - (1546, 420, 1), - (1547, 420, 1), - (1548, 420, 1), - (1552, 13, 5), - (1553, 13, 5), - (1554, 13, 5), - (1555, 359, 3), - (1556, 359, 3), - (1557, 359, 3), - (1558, 46, 1), - (1559, 46, 1), - (1560, 46, 1), - (1572, 263, 1), - (1573, 263, 1), - (1574, 263, 1), - (1575, 263, 1), - (1576, 263, 1), - (1577, 58, 1), - (1578, 58, 1), - (1579, 58, 1), - (1583, 300, 6), - (1584, 300, 6), - (1585, 300, 6), - (1586, 300, 6), - (1587, 300, 6), - (1591, 222, 3), - (1601, 82, 1), - (1602, 82, 1), - (1603, 82, 1), - (1608, 82, 3), - (1609, 82, 3), - (1610, 82, 3), - (1611, 181, 2), - (1612, 181, 2), - (1613, 181, 2), - (1614, 181, 2), - (1615, 181, 2), - (1627, 13, 5), - (1628, 13, 5), - (1629, 13, 5), - (1638, 224, 3), - (1639, 565, 1), - (1640, 793, 1), - (1641, 121, 3), - (1642, 121, 3), - (1643, 77, 1), - (1644, 85, 1), - (1645, 77, 1), - (1646, 85, 1), - (1656, 153, 1), - (1657, 153, 1), - (1659, 285, 1), - (1660, 285, 1), - (1667, 570, 1), - (2400, 38, 1), - (2401, 38, 1), - (2402, 38, 1), - (3676, 35, 1), - (4666, 435, 3), - (4667, 435, 3), - (4668, 435, 3), - (4669, 435, 3), - (4670, 435, 3), - (4688, 497, 5), - (4689, 497, 5), - (4690, 497, 5), - (4691, 497, 5), - (4692, 497, 5), - (4707, 30, 6), - (4708, 30, 6), - (4709, 30, 6), - (4710, 310, 6), - (4711, 310, 6), - (4712, 310, 6), - (4713, 311, 3), - (4714, 311, 3), - (4715, 311, 3), - (4716, 309, 6), - (4717, 309, 6), - (4718, 309, 6), - (4749, 23, 3), - (4750, 23, 3), - (4751, 23, 3), - (4752, 114, 6), - (4753, 114, 6), - (4754, 114, 6), - (4755, 215, 6), - (4756, 215, 6), - (4757, 215, 6), - (4761, 526, 3), - (4762, 526, 3), - (4763, 526, 3), - (4773, 20, 3), - (4795, 309, 3), - (4796, 309, 3), - (4797, 309, 3), - (4829, 420, 1), - (4830, 420, 1), - (4831, 420, 1), - (4844, 435, 3), - (4845, 435, 3), - (4846, 435, 3), - (4847, 435, 3), - (4848, 435, 3), - (4861, 68, 1), - (4862, 68, 1), - (4863, 68, 1), - (4864, 175, 3), - (4865, 175, 3), - (4866, 175, 3), - (4887, 413, 3), - (4888, 413, 3), - (4889, 413, 3), - (4890, 57, 1), - (4894, 409, 3), - (4895, 409, 3), - (4896, 409, 3), - (4903, 784, 1), - (4906, 785, 1), - (4909, 786, 1), - (4912, 787, 1), - (4915, 794, 1), - (4916, 794, 1), - (4917, 794, 1), - (4921, 117, 1), - (4922, 117, 1), - (4923, 117, 1), - (4924, 740, 3), - (4925, 740, 3), - (4926, 740, 3), - (4931, 173, 8), - (4932, 173, 8), - (4933, 173, 8), - (4951, 439, 3), - (4952, 439, 3), - (4953, 439, 3), - (4975, 30, 1), - (4976, 30, 1), - (4977, 30, 1), - (4978, 30, 1), - (4979, 30, 1), - (4986, 82, 1), - (4987, 82, 1), - (4988, 82, 1), - (4989, 82, 3), - (4990, 82, 3), - (4991, 82, 3), - (5010, 35, 1), - (5011, 35, 1), - (5012, 35, 1), - (5038, 30, 3), - (5039, 30, 3), - (5040, 30, 3), - (5041, 6001, 11), - (5042, 6001, 11), - (5043, 6001, 11), - (5061, 45, 1), - (5069, 224, 3), - (5070, 19, 3), - (5071, 19, 3), - (5072, 19, 3), - (5080, 255, 5), - (5081, 255, 5), - (5082, 255, 5), - (5098, 73, 2), - (5118, 396, 1), - (5119, 396, 1), - (5120, 396, 1), - (5127, 261, 3), - (5128, 261, 3), - (5129, 261, 3), - (5133, 23, 3), - (5134, 23, 3), - (5135, 23, 3), - (5136, 496, 5), - (5137, 496, 5), - (5138, 496, 5), - (5139, 496, 5), - (5140, 496, 5), - (5251, 447, 3), - (5252, 447, 3), - (5253, 447, 3), - (5264, 278, 5), - (5265, 278, 5), - (5266, 278, 5), - (5267, 278, 5), - (5268, 278, 5), - (5270, 87, 1), - (5271, 87, 1), - (5272, 87, 1), - (5286, 23, 3), - (5287, 23, 3), - (5288, 23, 3), - (5311, 185, 6), - (5312, 185, 6), - (5313, 185, 6), - (5330, 1685, 1), - (5333, 1685, 1), - (5336, 1685, 1), - (5339, 1685, 1), - (5342, 1685, 1), - (5347, 1685, 1), - (5348, 1685, 1), - (5350, 707, 4), - (5350, 1685, 1), - (5353, 1685, 1), - (5356, 1685, 1), - (5357, 1685, 1), - (5360, 1685, 1), - (5363, 447, 3), - (5363, 1685, 1), - (5366, 1685, 1), - (5369, 1685, 1), - (5513, 58, 1), - (5514, 58, 1), - (5515, 58, 1), - (5529, 19, 7), - (5530, 19, 7), - (5531, 19, 7), - (5532, 19, 7), - (5533, 19, 7), - (5542, 30, 6), - (5543, 30, 6), - (5544, 30, 6), - (5545, 310, 6), - (5546, 310, 6), - (5547, 310, 6), - (5548, 311, 3), - (5549, 311, 3), - (5550, 311, 3), - (5551, 309, 6), - (5552, 309, 6), - (5553, 309, 6), - (5571, 23, 3), - (5572, 23, 3), - (5573, 23, 3), - (5574, 114, 6), - (5575, 114, 6), - (5576, 114, 6), - (5577, 215, 6), - (5578, 215, 6), - (5579, 215, 6), - (5595, 309, 3), - (5596, 309, 3), - (5597, 309, 3), - (5607, 794, 1), - (5608, 794, 1), - (5609, 794, 1), - (5617, 23, 3), - (5618, 23, 3), - (5619, 23, 3), - (5702, 30, 1), - (5703, 30, 1), - (5704, 30, 1), - (5705, 30, 1), - (5706, 30, 1), - (5759, 374, 3), - (5760, 374, 3), - (5761, 374, 3), - (5762, 374, 3), - (5763, 374, 3), - (5791, 19, 3), - (5792, 19, 3), - (5793, 19, 3), - (5797, 396, 1), - (5798, 396, 1), - (5799, 396, 1), - (5803, 255, 5), - (5804, 255, 5), - (5805, 255, 5), - (5806, 30, 3), - (5807, 30, 3), - (5808, 30, 3), - (5825, 45, 1), - (5826, 185, 6), - (5827, 185, 6), - (5828, 185, 6), - (5854, 217, 1), - (5855, 217, 1), - (5856, 217, 1), - (5857, 173, 3), - (5858, 173, 3), - (5859, 173, 3), - (5869, 57, 1), - (5871, 57, 1), - (5872, 57, 1), - (5880, 60, 1), - (5881, 60, 1), - (5882, 60, 1), - (5886, 58, 1), - (5887, 58, 1), - (5888, 58, 1), - (5892, 784, 1), - (5893, 785, 1), - (5894, 786, 1), - (5895, 787, 1), - (5939, 278, 5), - (5940, 278, 5), - (5941, 278, 5), - (5942, 278, 5), - (5943, 278, 5), - (5944, 740, 3), - (5945, 740, 3), - (5946, 740, 3), - (5947, 175, 3), - (5948, 175, 3), - (5949, 175, 3), - (5950, 175, 3), - (5951, 175, 3), - (5952, 175, 3), - (5954, 68, 1), - (5955, 68, 1), - (5956, 68, 1), - (5969, 6001, 11), - (5970, 6001, 11), - (5971, 6001, 11), - (5972, 6001, 11), - (5973, 6000, 11), - (5984, 702, 1), - (6017, 82, 1), - (6018, 82, 1), - (6019, 82, 1), - (6026, 826, 1), - (6027, 826, 1), - (6028, 826, 1), - (6042, 439, 3), - (6043, 439, 3), - (6044, 439, 3), - (6054, 173, 8), - (6055, 173, 8), - (6056, 173, 8), - (6063, 87, 1), - (6064, 87, 1), - (6065, 87, 1), - (6088, 392, 1), - (6089, 392, 1), - (6090, 392, 1), - (6092, 447, 3), - (6093, 447, 3), - (6094, 447, 3), - (6102, 224, 3), - (6106, 308, 3), - (6107, 308, 3), - (6108, 308, 3), - (6109, 308, 3), - (6110, 308, 3), - (6111, 308, 3), - (6130, 120, 1), - (6131, 120, 1), - (6132, 120, 1), - (6136, 300, 6), - (6158, 308, 3), - (6159, 308, 3), - (6160, 308, 3), - (6209, 245, 3), - (6210, 245, 3), - (6211, 245, 3), - (6228, 404, 1), - (6229, 404, 1), - (6230, 404, 1), - (6231, 404, 1), - (6233, 43, 1), - (6234, 43, 1), - (6235, 43, 1), - (6260, 98, 1), - (6261, 98, 1), - (6262, 98, 1), - (6272, 672, 1), - (6273, 672, 1), - (6274, 672, 1), - (6275, 790, 1), - (6276, 790, 1), - (6277, 790, 1), - (6302, 3710, 1), - (6303, 3710, 1), - (6304, 3710, 1), - (6319, 107, 1), - (6320, 107, 1), - (6321, 107, 1), - (6333, 125, 1), - (6337, 553, 1), - (6338, 553, 1), - (6339, 553, 1), - (6340, 777, 1), - (6341, 777, 1), - (6342, 777, 1), - (6346, 494, 3), - (6347, 494, 3), - (6348, 494, 3), - (6349, 500, 3), - (6350, 500, 3), - (6351, 500, 3), - (6352, 409, 3), - (6353, 409, 3), - (6354, 409, 3), - (6380, 128, 3), - (6381, 128, 3), - (6382, 128, 3), - (6400, 187, 5), - (6401, 187, 5), - (6402, 187, 5), - (6403, 23, 3), - (6404, 23, 3), - (6405, 23, 3), - (6439, 41, 1), - (6440, 41, 1), - (6441, 420, 1), - (6442, 362, 1), - (6443, 362, 1), - (6445, 176, 1), - (6446, 176, 1), - (6447, 176, 1), - (6478, 3800, 1), - (6479, 3800, 1), - (6480, 3800, 1), - (6481, 36, 1), - (6482, 36, 1), - (6483, 36, 1), - (6484, 558, 1), - (6485, 558, 1), - (6486, 558, 1), - (6499, 611, 1), - (6500, 526, 3), - (6501, 526, 3), - (6502, 526, 3), - (6503, 172, 1), - (6504, 172, 1), - (6505, 172, 1), - (6506, 172, 1), - (6514, 404, 1), - (6515, 404, 1), - (6516, 404, 1), - (6517, 20, 1), - (6528, 107, 1), - (6630, 278, 5), - (6631, 278, 5), - (6632, 278, 5), - (6633, 278, 5), - (6634, 278, 5), - (6636, 358, 3), - (6637, 358, 3), - (6638, 358, 3), - (6668, 672, 3), - (6669, 672, 3), - (6670, 672, 3), - (6697, 857, 1), - (6698, 857, 1), - (6699, 857, 1), - (6700, 857, 1), - (6701, 857, 1), - (6703, 171, 1), - (6704, 171, 1), - (6705, 171, 1), - (6712, 177, 1), - (6713, 177, 1), - (6714, 177, 1), - (6715, 177, 1), - (6716, 177, 1), - (6755, 184, 3), - (6756, 184, 3), - (6757, 184, 3), - (6819, 524, 1), - (6820, 524, 1), - (6821, 524, 1), - (6823, 320, 1), - (6824, 320, 1), - (6825, 320, 1), - (6826, 320, 1), - (6827, 320, 1), - (6870, 544, 1), - (6871, 544, 1), - (6872, 544, 1), - (6873, 3837, 3), - (6874, 3837, 3), - (6875, 3837, 3), - (6876, 259, 3), - (6877, 259, 3), - (6878, 259, 3), - (6900, 465, 3), - (6901, 465, 3), - (6902, 465, 3), - (6903, 465, 3), - (6904, 465, 3), - (6908, 499, 1), - (6909, 499, 1), - (6910, 499, 1), - (6930, 611, 1), - (6935, 465, 3), - (6936, 465, 3), - (6937, 465, 3), - (6941, 962, 1), - (6942, 962, 1), - (6943, 962, 1), - (6944, 962, 1), - (6945, 962, 1), - (6977, 3817, 1), - (6978, 3817, 1), - (6979, 3817, 1), - (6980, 128, 1), - (6981, 128, 1), - (6982, 128, 1), - (6983, 245, 3), - (6988, 985, 1), - (6989, 985, 1), - (6990, 985, 1), - (7005, 789, 1), - (7006, 789, 1), - (7007, 789, 1), - (7033, 804, 1), - (7034, 804, 1), - (7035, 804, 1), - (7036, 3646, 1), - (7037, 3646, 1), - (7038, 3646, 1), - (7050, 26, 3), - (7051, 26, 3), - (7052, 26, 3), - (7053, 26, 3), - (7054, 26, 3), - (7055, 26, 3), - (7063, 26, 3), - (7064, 26, 3), - (7065, 26, 3), - (7100, 254, 3), - (7101, 254, 3), - (7102, 254, 3), - (7103, 286, 1), - (7104, 286, 1), - (7105, 286, 1), - (7116, 110, 1), - (7117, 110, 1), - (7118, 110, 1), - (7122, 435, 3), - (7123, 435, 3), - (7124, 435, 3), - (7125, 435, 3), - (7126, 435, 3), - (7128, 109, 1), - (7129, 109, 1), - (7130, 109, 1), - (7134, 439, 3), - (7135, 439, 3), - (7136, 439, 3), - (7137, 672, 1), - (7138, 672, 1), - (7139, 672, 1), - (7184, 1685, 1), - (7199, 175, 3), - (7200, 175, 3), - (7201, 175, 3), - (7204, 278, 5), - (7205, 278, 5), - (7206, 278, 5), - (7207, 278, 5), - (7208, 278, 5), - (7215, 68, 1), - (7216, 68, 1), - (7232, 114, 6), - (7233, 114, 6), - (7234, 114, 6), - (7246, 794, 1), - (7247, 794, 1), - (7248, 794, 1), - (7253, 784, 1), - (7254, 785, 1), - (7255, 786, 1), - (7256, 787, 1), - (7260, 60, 1), - (7261, 60, 1), - (7262, 60, 1), - (7263, 58, 1), - (7264, 58, 1), - (7265, 58, 1), - (7266, 125, 1), - (7276, 217, 1), - (7277, 217, 1), - (7278, 217, 1), - (7285, 173, 3), - (7286, 173, 3), - (7287, 173, 3), - (7288, 409, 3), - (7289, 409, 3), - (7290, 409, 3), - (7291, 173, 8), - (7292, 173, 8), - (7293, 173, 8), - (7301, 19, 3), - (7302, 19, 3), - (7303, 19, 3), - (7310, 255, 5), - (7311, 255, 5), - (7312, 255, 5), - (7316, 41, 1), - (7317, 41, 1), - (7323, 254, 3), - (7324, 254, 3), - (7325, 254, 3), - (7326, 286, 1), - (7327, 286, 1), - (7328, 286, 1), - (7329, 6001, 11), - (7330, 6001, 11), - (7331, 6001, 11), - (7335, 702, 1), - (7359, 82, 1), - (7360, 82, 1), - (7361, 82, 1), - (7378, 82, 3), - (7379, 82, 3), - (7380, 82, 3), - (7381, 82, 3), - (7382, 82, 3), - (7383, 82, 3), - (7390, 87, 1), - (7391, 87, 1), - (7392, 87, 1), - (7407, 31, 3), - (7414, 185, 6), - (7415, 185, 6), - (7416, 185, 6), - (7433, 30, 1), - (7434, 30, 1), - (7435, 30, 1), - (7436, 30, 1), - (7437, 30, 1), - (7445, 187, 5), - (7446, 187, 5), - (7447, 187, 5), - (7448, 553, 1), - (7449, 553, 1), - (7450, 553, 1), - (7451, 777, 1), - (7452, 777, 1), - (7453, 777, 1), - (7466, 224, 3), - (7472, 447, 3), - (7473, 447, 3), - (7474, 447, 3), - (7478, 245, 3), - (7497, 128, 3), - (7498, 128, 3), - (7499, 128, 3), - (7554, 19, 7), - (7555, 19, 7), - (7556, 19, 7), - (7557, 19, 7), - (7558, 19, 7), - (7562, 30, 6), - (7563, 30, 6), - (7564, 30, 6), - (7581, 215, 6), - (7582, 215, 6), - (7583, 215, 6), - (7615, 494, 3), - (7616, 494, 3), - (7617, 494, 3), - (7618, 500, 3), - (7619, 500, 3), - (7620, 500, 3), - (7621, 20, 1), - (7622, 26, 3), - (7623, 26, 3), - (7624, 26, 3), - (7631, 309, 3), - (7632, 309, 3), - (7633, 309, 3), - (7650, 310, 6), - (7651, 310, 6), - (7652, 310, 6), - (7653, 311, 3), - (7654, 311, 3), - (7655, 311, 3), - (7656, 309, 6), - (7657, 309, 6), - (7658, 309, 6), - (7659, 153, 3), - (7660, 153, 3), - (7661, 153, 3), - (7664, 170, 3), - (7665, 170, 3), - (7666, 170, 3), - (7667, 170, 3), - (7668, 170, 3), - (7682, 68, 1), - (7686, 435, 3), - (7687, 435, 3), - (7688, 435, 3), - (7691, 224, 3), - (7695, 862, 3), - (7696, 862, 3), - (7697, 862, 3), - (7700, 310, 3), - (7701, 310, 3), - (7702, 310, 3), - (7704, 3707, 1), - (7705, 3707, 1), - (7706, 3707, 1), - (7707, 87, 1), - (7708, 87, 1), - (7709, 87, 1), - (7710, 702, 1), - (7711, 702, 1), - (7712, 3826, 1), - (7715, 901, 1), - (7716, 901, 1), - (7717, 901, 1), - (7718, 125, 1), - (7722, 19, 7), - (7723, 19, 7), - (7724, 19, 7), - (7725, 19, 7), - (7726, 19, 7), - (7733, 195, 3), - (7743, 184, 1), - (7744, 184, 1), - (7745, 184, 1), - (7748, 13, 5), - (7749, 13, 5), - (7750, 13, 5), - (7751, 2234, 1), - (7752, 2234, 1), - (7753, 2234, 1), - (7754, 85, 1), - (7757, 9403, 1), - (7758, 9403, 1), - (7759, 9403, 1), - (7760, 824, 1), - (7761, 824, 1), - (7762, 824, 1), - (7765, 7689, 1), - (7766, 7689, 1), - (7767, 7689, 1), - (7768, 7689, 1), - (7770, 19, 3), - (7771, 19, 3), - (7772, 19, 3), - (7773, 19, 3), - (7774, 19, 3), - (7775, 19, 3), - (7822, 1154, 1), - (7823, 1154, 1), - (7824, 1154, 1), - (7825, 1154, 1), - (7826, 1154, 1), - (7827, 1404, 3), - (7832, 60, 1), - (7833, 60, 1), - (7834, 60, 1), - (7835, 60, 1), - (7836, 60, 1), - (7842, 19, 7), - (7843, 19, 7), - (7844, 19, 7), - (7940, 558, 1), - (7941, 558, 1), - (7942, 558, 1), - (7943, 39, 1), - (7944, 41, 1), - (7951, 19, 3), - (7952, 19, 3), - (7953, 19, 3), - (7983, 520, 1), - (7984, 520, 1), - (7985, 520, 1), - (7986, 705, 1), - (7987, 705, 1), - (7988, 705, 1), - (7989, 1092, 1), - (7990, 1092, 1), - (7991, 1092, 1), - (7992, 1092, 1), - (7993, 39, 1), - (7994, 39, 1), - (7995, 39, 1), - (8031, 791, 1), - (8032, 791, 1), - (8033, 791, 1), - (8035, 521, 1), - (8036, 521, 1), - (8037, 521, 1), - (8069, 160, 4), - (8070, 160, 4), - (8071, 160, 4), - (8076, 565, 1), - (8077, 565, 1), - (8078, 565, 1), - (8079, 565, 1), - (8080, 565, 1), - (8081, 565, 1), - (8082, 208, 1), - (8083, 208, 1), - (8084, 208, 1), - (8195, 3707, 1), - (8196, 3707, 1), - (8197, 3707, 1), - (8198, 210, 1), - (8199, 210, 1), - (8200, 210, 1), - (8204, 153, 1), - (8205, 153, 1), - (8206, 153, 1), - (8207, 285, 1), - (8208, 285, 1), - (8209, 285, 1), - (8220, 3812, 1), - (8224, 516, 3), - (8225, 516, 3), - (8226, 516, 3), - (8260, 1211, 1), - (8263, 142, 20), - (8264, 142, 20), - (8265, 142, 20), - (8266, 142, 20), - (8267, 142, 20), - (8268, 142, 20), - (8269, 142, 20), - (8270, 142, 20), - (8271, 142, 20), - (8272, 142, 20), - (8273, 142, 20), - (8274, 142, 20), - (8275, 142, 20), - (8276, 142, 20), - (8277, 142, 20), - (8278, 142, 20), - (8279, 142, 20), - (8280, 142, 20), - (8281, 142, 20), - (8282, 142, 20), - (8283, 142, 20), - (8284, 142, 20), - (8285, 142, 20), - (8286, 142, 20), - (8287, 142, 20), - (8288, 142, 20), - (8289, 142, 20), - (8290, 142, 20), - (8291, 142, 20), - (8292, 142, 20), - (8293, 142, 20), - (8294, 142, 20), - (8295, 142, 20), - (8296, 142, 20), - (8297, 142, 20), - (8303, 309, 6), - (8309, 31, 3), - (8310, 31, 3), - (8311, 31, 3), - (8312, 110, 1), - (8317, 8205, 1), - (8318, 8205, 1), - (8319, 199, 1), - (8320, 199, 1), - (8321, 199, 1), - (8332, 861, 1), - (8333, 861, 1), - (8334, 861, 1), - (8335, 1041, 1), - (8336, 1041, 1), - (8337, 1041, 1), - (8338, 1041, 1), - (8339, 1041, 1), - (8344, 215, 6), - (8345, 215, 6), - (8346, 215, 6), - (8347, 616, 1), - (8348, 616, 1), - (8349, 616, 1), - (8351, 142, 20), - (8352, 142, 20), - (8353, 142, 20), - (8354, 142, 20), - (8355, 142, 20), - (8356, 142, 20), - (8357, 142, 20), - (8358, 142, 20), - (8359, 142, 20), - (8360, 142, 20), - (8361, 142, 20), - (8362, 142, 20), - (8363, 142, 20), - (8364, 142, 20), - (8365, 142, 20), - (8366, 142, 20), - (8367, 142, 20), - (8368, 142, 20), - (8369, 142, 20), - (8370, 142, 20), - (8371, 142, 20), - (8372, 142, 20), - (8373, 142, 20), - (8374, 142, 20), - (8375, 142, 20), - (8376, 142, 20), - (8377, 142, 20), - (8378, 142, 20), - (8379, 142, 20), - (8380, 142, 20), - (8381, 142, 20), - (8382, 142, 20), - (8383, 142, 20), - (8384, 142, 20), - (8385, 142, 20), - (8386, 142, 20), - (8387, 142, 20), - (8388, 142, 20), - (8389, 142, 20), - (8390, 142, 20), - (8391, 142, 20), - (8392, 142, 20), - (8393, 142, 20), - (8394, 142, 20), - (8395, 142, 20), - (8396, 142, 20), - (8397, 142, 20), - (8398, 142, 20), - (8399, 142, 20), - (8400, 142, 20), - (8401, 142, 20), - (8402, 142, 20), - (8403, 142, 20), - (8404, 142, 20), - (8405, 142, 20), - (8406, 142, 20), - (8407, 142, 20), - (8408, 142, 20), - (8409, 142, 20), - (8410, 142, 20), - (8411, 142, 20), - (8412, 142, 20), - (8413, 142, 20), - (8414, 142, 20), - (8415, 142, 20), - (8416, 142, 20), - (8417, 142, 20), - (8418, 142, 20), - (8419, 142, 20), - (8420, 142, 20), - (8421, 516, 3), - (8427, 254, 3), - (8428, 254, 3), - (8429, 254, 3), - (9103, 1350, 3), - (9104, 1350, 3), - (9105, 1350, 3), - (9106, 1351, 3), - (9107, 1351, 3), - (9108, 1351, 3), - (9112, 1390, 3), - (9113, 1390, 3), - (9114, 1390, 3), - (9115, 1391, 3), - (9116, 1391, 3), - (9117, 1391, 3), - (9121, 1370, 3), - (9122, 1370, 3), - (9123, 1370, 3), - (9124, 1371, 3), - (9125, 1371, 3), - (9126, 1371, 3), - (9130, 1380, 3), - (9131, 1380, 3), - (9132, 1380, 3), - (9133, 1381, 3), - (9134, 1381, 3), - (9135, 1381, 3), - (9139, 1470, 3), - (9140, 1470, 3), - (9141, 1470, 3), - (9142, 1471, 3), - (9143, 1471, 3), - (9144, 1471, 3), - (9148, 1480, 3), - (9149, 1480, 3), - (9150, 1480, 3), - (9151, 1481, 3), - (9152, 1481, 3), - (9153, 1481, 3), - (9157, 1490, 3), - (9158, 1490, 3), - (9159, 1490, 3), - (9160, 1491, 3), - (9161, 1491, 3), - (9162, 1491, 3), - (9166, 1460, 3), - (9167, 1460, 3), - (9168, 1460, 3), - (9169, 1461, 3), - (9170, 1461, 3), - (9171, 1461, 3), - (9175, 1450, 3), - (9176, 1450, 3), - (9177, 1450, 3), - (9178, 1451, 3), - (9179, 1451, 3), - (9180, 1451, 3), - (9184, 1440, 3), - (9185, 1440, 3), - (9186, 1440, 3), - (9187, 1441, 3), - (9188, 1441, 3), - (9189, 1441, 3), - (9193, 1420, 3), - (9194, 1420, 3), - (9195, 1420, 3), - (9196, 1421, 3), - (9197, 1421, 3), - (9198, 1421, 3), - (9202, 1430, 3), - (9203, 1430, 3), - (9204, 1430, 3), - (9205, 1431, 3), - (9206, 1431, 3), - (9207, 1431, 3), - (9211, 1400, 3), - (9212, 1400, 3), - (9213, 1400, 3), - (9214, 1401, 3), - (9215, 1401, 3), - (9216, 1401, 3), - (9220, 1360, 3), - (9221, 1360, 3), - (9222, 1360, 3), - (9223, 1361, 3), - (9224, 1361, 3), - (9225, 1361, 3), - (9229, 1500, 3), - (9230, 1500, 3), - (9231, 1500, 3), - (9232, 1501, 3), - (9233, 1501, 3), - (9234, 1501, 3), - (9238, 1410, 3), - (9239, 1410, 3), - (9240, 1410, 3), - (9241, 1411, 3), - (9242, 1411, 3), - (9243, 1411, 3), - (9300, 1300, 3), - (9301, 1300, 3), - (9302, 1300, 3), - (9303, 1300, 6), - (9304, 1300, 6), - (9305, 1300, 6), - (9306, 1300, 9), - (9307, 1300, 9), - (9308, 1300, 9), - (9309, 1313, 3), - (9310, 1313, 3), - (9311, 1313, 3), - (9312, 1313, 6), - (9313, 1313, 6), - (9314, 1313, 6), - (9315, 1313, 9), - (9316, 1313, 9), - (9317, 1313, 9), - (9318, 1302, 3), - (9319, 1302, 3), - (9320, 1302, 3), - (9321, 1302, 6), - (9322, 1302, 6), - (9323, 1302, 6), - (9324, 1302, 9), - (9325, 1302, 9), - (9326, 1302, 9), - (9327, 1303, 3), - (9328, 1303, 3), - (9329, 1303, 3), - (9330, 1303, 6), - (9331, 1303, 6), - (9332, 1303, 6), - (9333, 1303, 9), - (9334, 1303, 9), - (9335, 1303, 9), - (9336, 1301, 3), - (9337, 1301, 3), - (9338, 1301, 3), - (9339, 1301, 6), - (9340, 1301, 6), - (9341, 1301, 6), - (9342, 1301, 9), - (9343, 1301, 9), - (9344, 1301, 9), - (9345, 1312, 3), - (9346, 1312, 3), - (9347, 1312, 3), - (9348, 1312, 6), - (9349, 1312, 6), - (9350, 1312, 6), - (9351, 1312, 9), - (9352, 1312, 9), - (9353, 1312, 9), - (9354, 1315, 3), - (9355, 1315, 3), - (9356, 1315, 3), - (9357, 1315, 6), - (9358, 1315, 6), - (9359, 1315, 6), - (9360, 1315, 9), - (9361, 1315, 9), - (9362, 1315, 9), - (9363, 1310, 3), - (9364, 1310, 3), - (9365, 1310, 3), - (9366, 1310, 6), - (9367, 1310, 6), - (9368, 1310, 6), - (9369, 1310, 9), - (9370, 1310, 9), - (9371, 1310, 9), - (9372, 1311, 3), - (9373, 1311, 3), - (9374, 1311, 3), - (9375, 1311, 6), - (9376, 1311, 6), - (9377, 1311, 6), - (9378, 1311, 9), - (9379, 1311, 9), - (9380, 1311, 9), - (9381, 1309, 3), - (9382, 1309, 3), - (9383, 1309, 3), - (9384, 1309, 6), - (9385, 1309, 6), - (9386, 1309, 6), - (9387, 1309, 9), - (9388, 1309, 9), - (9389, 1309, 9), - (9390, 1308, 3), - (9391, 1308, 3), - (9392, 1308, 3), - (9393, 1308, 6), - (9394, 1308, 6), - (9395, 1308, 6), - (9396, 1308, 9), - (9397, 1308, 9), - (9398, 1308, 9), - (9399, 1307, 3), - (9400, 1307, 3), - (9401, 1307, 3), - (9402, 1307, 6), - (9403, 1307, 6), - (9404, 1307, 6), - (9405, 1307, 9), - (9406, 1307, 9), - (9407, 1307, 9), - (9408, 1304, 3), - (9409, 1304, 3), - (9410, 1304, 3), - (9411, 1304, 6), - (9412, 1304, 6), - (9413, 1304, 6), - (9414, 1304, 9), - (9415, 1304, 9), - (9416, 1304, 9), - (9417, 1305, 3), - (9418, 1305, 3), - (9419, 1305, 3), - (9420, 1305, 6), - (9421, 1305, 6), - (9422, 1305, 6), - (9423, 1305, 9), - (9424, 1305, 9), - (9425, 1305, 9), - (9426, 1306, 3), - (9427, 1306, 3), - (9428, 1306, 3), - (9429, 1306, 6), - (9430, 1306, 6), - (9431, 1306, 6), - (9432, 1306, 9), - (9433, 1306, 9), - (9434, 1306, 9), - (9435, 1314, 3), - (9436, 1314, 3), - (9437, 1314, 3), - (9438, 1314, 6), - (9439, 1314, 6), - (9440, 1314, 6), - (9441, 1314, 9), - (9442, 1314, 9), - (9443, 1314, 9), - (9500, 72, 1), - (10016, 19, 3), - (10017, 19, 3), - (10018, 19, 3), - (10030, 558, 1), - (10031, 558, 1), - (10032, 558, 1), - (10038, 19, 3), - (10039, 19, 3), - (10040, 19, 3), - (10041, 358, 3), - (10042, 358, 3), - (10043, 358, 3), - (10047, 6001, 11), - (10048, 6001, 11), - (10049, 6001, 11), - (10064, 82, 3), - (10065, 82, 3), - (10066, 82, 3), - (10067, 82, 3), - (10068, 82, 3), - (10069, 82, 3), - (10070, 278, 5), - (10071, 278, 5), - (10072, 278, 5), - (10073, 278, 5), - (10074, 278, 5), - (10093, 185, 6), - (10105, 170, 3), - (10106, 170, 3), - (10107, 170, 3), - (10108, 170, 3), - (10109, 170, 3), - (10110, 520, 1), - (10111, 520, 1), - (10112, 520, 1), - (10130, 544, 1), - (10131, 544, 1), - (10132, 544, 1), - (10133, 3837, 3), - (10134, 3837, 3), - (10135, 3837, 3), - (10136, 259, 3), - (10137, 259, 3), - (10138, 259, 3), - (10150, 187, 5), - (10151, 187, 5), - (10152, 187, 5), - (10153, 553, 1), - (10154, 553, 1), - (10155, 553, 1), - (10165, 439, 3), - (10166, 439, 3), - (10167, 439, 3), - (10176, 171, 1), - (10177, 171, 1), - (10178, 171, 1), - (10182, 177, 1), - (10183, 177, 1), - (10184, 177, 1), - (10185, 177, 1), - (10186, 177, 1), - (10197, 447, 3), - (10198, 447, 3), - (10199, 447, 3), - (10203, 524, 1), - (10204, 524, 1), - (10205, 524, 1), - (10206, 320, 1), - (10207, 320, 1), - (10209, 175, 3), - (10210, 175, 3), - (10211, 175, 3), - (10213, 278, 5), - (10214, 278, 5), - (10215, 278, 5), - (10216, 278, 5), - (10217, 278, 5), - (10249, 208, 1), - (10250, 208, 1), - (10251, 208, 1), - (10255, 784, 1), - (10256, 785, 1), - (10257, 786, 1), - (10258, 787, 1), - (10262, 58, 1), - (10263, 58, 1), - (10264, 58, 1), - (10271, 173, 3), - (10272, 173, 3), - (10273, 173, 3), - (10274, 173, 8), - (10275, 173, 8), - (10276, 173, 8), - (10282, 791, 1), - (10283, 791, 1), - (10284, 791, 1), - (10285, 521, 1), - (10286, 521, 1), - (10287, 521, 1), - (10308, 128, 3), - (10309, 128, 3), - (10310, 128, 3), - (10329, 3701, 1), - (10330, 199, 3), - (10332, 943, 3), - (10336, 941, 1), - (10337, 941, 1), - (10338, 941, 1), - (10354, 6001, 17), - (10389, 841, 1), - (10390, 841, 1), - (10391, 841, 1), - (10396, 705, 4), - (10397, 1092, 4), - (10398, 3701, 1), - (10399, 3701, 1), - (10413, 207, 1), - (10414, 207, 1), - (10415, 207, 1), - (10416, 207, 1), - (10417, 207, 1), - (10426, 185, 18), - (10427, 519, 15), - (10428, 173, 8), - (10429, 173, 8), - (10430, 173, 8), - (10431, 791, 1), - (10432, 791, 1), - (10433, 791, 1), - (10434, 792, 1), - (10435, 792, 1), - (10436, 792, 1), - (10450, 19, 9), - (10451, 19, 9), - (10452, 19, 9), - (10456, 3800, 1), - (10457, 3800, 1), - (10458, 3800, 1), - (10462, 396, 1), - (10463, 396, 1), - (10464, 391, 9), - (10465, 391, 9), - (10466, 391, 9), - (10468, 19, 9), - (10469, 19, 9), - (10470, 558, 1), - (10471, 558, 1), - (10472, 558, 1), - (10473, 26, 3), - (10474, 26, 3), - (10475, 26, 3), - (10476, 26, 3), - (10477, 26, 3), - (10510, 705, 1), - (10511, 185, 3), - (10512, 185, 3), - (10513, 185, 3), - (10514, 519, 3), - (10515, 519, 3), - (10516, 519, 3), - (10519, 3213, 1), - (10522, 3732, 1), - (10527, 1400, 1), - (10532, 1401, 1), - (10537, 1402, 1), - (10548, 605, 13), - (10554, 263, 1), - (10555, 263, 1), - (10556, 263, 1), - (10557, 1120, 1), - (10558, 1120, 1), - (10559, 1120, 1), - (10560, 1120, 1), - (10561, 3551, 1), - (10562, 3551, 1), - (10563, 3551, 1), - (10564, 217, 1), - (10565, 217, 1), - (10566, 217, 1), - (10576, 109, 1), - (10579, 3646, 1), - (10580, 3646, 1), - (10588, 601, 1), - (10589, 601, 1), - (10590, 601, 1), - (10591, 601, 1), - (10592, 601, 1), - (10610, 265, 5), - (10611, 265, 5), - (10612, 265, 5), - (10621, 180, 3), - (10622, 180, 3), - (10623, 30, 3), - (10624, 30, 3), - (10625, 30, 3), - (10626, 702, 1), - (10646, 3826, 1), - (10657, 276, 3), - (10658, 276, 3), - (10659, 276, 3), - (10666, 98, 1), - (10667, 98, 1), - (10668, 98, 1), - (10670, 19, 9), - (10708, 6001, 11), - (10709, 6001, 11), - (10710, 6001, 11), - (10711, 30, 6), - (10712, 30, 6), - (10713, 30, 6), - (10714, 873, 1), - (10715, 873, 1), - (10717, 184, 1), - (10718, 184, 1), - (10719, 872, 1), - (10720, 872, 1), - (10721, 872, 1), - (10722, 778, 1), - (10723, 778, 1), - (10724, 778, 1), - (10725, 778, 1), - (10726, 778, 1), - (10727, 2235, 1), - (10728, 2235, 1), - (10730, 870, 1), - (10731, 870, 1), - (10733, 219, 1), - (10734, 219, 1), - (10735, 219, 1), - (10750, 286, 1), - (10751, 286, 1), - (10752, 7108, 1), - (10753, 286, 1), - (10789, 10424, 1), - (10790, 705, 4), - (10791, 1092, 4), - (10800, 462, 3), - (10801, 462, 3), - (10802, 462, 3), - (10903, 125, 1), - (10904, 125, 1), - (10905, 125, 1), - (10909, 7007, 1), - (10910, 7007, 1), - (10911, 7007, 1), - (10915, 823, 3), - (10916, 823, 3), - (10917, 823, 3), - (10951, 447, 3), - (10952, 447, 3), - (10953, 447, 3), - (10954, 662, 3), - (10955, 662, 3), - (10956, 662, 3), - (11011, 3710, 1), - (11012, 3710, 1), - (11013, 3710, 1), - (11014, 3899, 1), - (11015, 3899, 1), - (11016, 3899, 1), - (11020, 3899, 1), - (11050, 452, 3), - (11051, 452, 3), - (11052, 452, 3), - (11053, 500, 3), - (11054, 500, 3), - (11059, 452, 3), - (11060, 452, 3), - (11077, 986, 1), - (11078, 988, 1), - (11079, 987, 1), - (11088, 505, 1), - (11089, 505, 1), - (11090, 505, 1), - (11091, 505, 1), - (12422, 1202, 1), - (12432, 23, 3), - (12433, 23, 3), - (12434, 23, 3), - (12435, 23, 3), - (12436, 23, 3), - (12437, 23, 3), - (12475, 7003, 1), - (12476, 7003, 1), - (12477, 7003, 1), - (12478, 3705, 9), - (12479, 3705, 9), - (12480, 3705, 9), - (12523, 114, 6), - (12526, 215, 6), - (12527, 215, 6), - (12528, 215, 6), - (12529, 358, 3), - (12530, 358, 3), - (12531, 358, 3), - (12553, 23, 3), - (12554, 23, 3), - (12555, 23, 3), - (12556, 23, 3), - (12557, 23, 3), - (12558, 23, 3), - (12582, 9400, 1), - (12583, 9400, 1), - (12584, 9400, 1), - (12587, 9403, 1), - (12588, 9403, 1), - (12589, 9403, 1), - (12600, 3514, 1), - (12606, 13, 5), - (12610, 310, 3), - (12626, 1410, 3), - (12629, 1411, 3), - (12632, 1412, 3), - (12635, 428, 2), - (12639, 519, 3), - (12642, 185, 3), - (12645, 519, 1), - (12646, 185, 1), - (12664, 3728, 1), - (12673, 420, 1), - (12677, 17, 3), - (12679, 276, 3), - (12680, 276, 3), - (12681, 276, 3), - (12697, 30, 6), - (12698, 30, 6), - (12699, 30, 6), - (12713, 8202, 1), - (12714, 8202, 1), - (12715, 8202, 1), - (12716, 3702, 1), - (12717, 3702, 1), - (12718, 3702, 1), - (12719, 3702, 1), - (12720, 3506, 1), - (12721, 3506, 1), - (12722, 3506, 1), - (12723, 3506, 1), - (12727, 359, 3), - (12728, 359, 3), - (12729, 359, 3), - (12730, 941, 1), - (12731, 941, 1), - (12732, 941, 1), - (12733, 943, 3), - (12734, 259, 3), - (12735, 259, 3), - (12736, 259, 3), - (12737, 3701, 1), - (12738, 3701, 1), - (12739, 3701, 1), - (12749, 30, 1), - (12750, 30, 1), - (12751, 30, 1), - (12757, 68, 1), - (12758, 68, 1), - (12759, 68, 1), - (12760, 175, 3), - (12761, 175, 3), - (12762, 175, 3), - (12773, 1580, 1), - (12774, 1580, 1), - (12775, 1580, 1), - (12776, 1580, 1), - (12777, 1580, 1), - (12779, 826, 1), - (12780, 826, 1), - (12781, 826, 1), - (12782, 826, 1), - (12783, 826, 1), - (12784, 826, 1), - (12798, 278, 5), - (12799, 278, 5), - (12800, 278, 5), - (12831, 128, 1), - (12834, 128, 1), - (12835, 128, 1), - (12840, 3817, 1), - (12841, 3817, 1), - (12849, 8303, 1), - (12860, 23, 3), - (12863, 23, 3), - (12865, 1155, 1), - (12866, 639, 1), - (12867, 6106, 6), - (12871, 452, 3), - (12872, 452, 3), - (12874, 451, 1), - (12876, 7003, 1), - (12877, 7003, 1), - (12878, 7003, 1), - (12881, 172, 1), - (12886, 304, 5), - (12887, 303, 5), - (12888, 305, 5), - (12889, 501, 1), - (12890, 507, 1), - (12892, 509, 3), - (12894, 1122, 1), - (12899, 57, 1), - (12900, 57, 1), - (12902, 1380, 1), - (12903, 1380, 1), - (12907, 1381, 1), - (12908, 1381, 1), - (12912, 1382, 1), - (12913, 1382, 1), - (12934, 173, 3), - (12956, 784, 1), - (12957, 786, 1), - (12958, 787, 1), - (12959, 785, 1), - (12964, 596, 1), - (12965, 597, 1), - (12968, 1041, 1), - (12969, 1041, 1), - (12970, 1041, 1), - (12977, 1041, 1), - (12978, 1041, 1), - (12979, 1041, 1), - (12980, 1041, 1), - (12981, 1041, 1), - (12992, 707, 4), - (12993, 707, 4), - (12994, 707, 4), - (13001, 9504, 1), - (13002, 9504, 1), - (13003, 9504, 1), - (13004, 153, 9), - (13005, 171, 1), - (13006, 171, 1), - (13007, 171, 1), - (13008, 859, 1), - (13009, 3730, 1), - (13010, 47, 1), - (13011, 47, 1), - (13012, 47, 1), - (13013, 446, 1), - (13014, 446, 1), - (13015, 446, 1), - (13017, 3815, 10), - (13018, 3815, 10), - (13019, 3815, 10), - (13023, 309, 6), - (13055, 8400, 1), - (13067, 643, 1), - (13072, 3514, 1), - (13073, 3514, 1), - (13074, 310, 6), - (13075, 310, 6), - (13076, 310, 6), - (13077, 311, 3), - (13078, 311, 3), - (13090, 20, 1), - (13092, 82, 1), - (13093, 82, 1), - (13094, 82, 1), - (13104, 87, 1), - (13105, 87, 1), - (13106, 87, 1), - (13130, 1685, 1), - (13140, 391, 9), - (13141, 391, 9), - (13142, 391, 9), - (13143, 500, 1), - (13144, 500, 1), - (13145, 500, 1), - (13146, 494, 1), - (13147, 494, 1), - (13148, 494, 1), - (13155, 705, 1), - (13166, 822, 1), - (13167, 822, 1), - (13168, 822, 1), - (13170, 128, 3), - (13190, 187, 5), - (13191, 187, 5), - (13192, 187, 5), - (13196, 3837, 3), - (13197, 3837, 3), - (13198, 3837, 3), - (13203, 199, 3), - (13204, 8261, 1), - (13205, 8261, 1), - (13206, 8261, 1), - (13213, 439, 3), - (13214, 439, 3), - (13215, 439, 3), - (13216, 439, 3), - (13217, 439, 3), - (13222, 3514, 1), - (13223, 3514, 1), - (13241, 173, 8), - (13244, 46, 1), - (13247, 409, 3), - (13253, 58, 1), - (13254, 58, 1), - (13255, 58, 1), - (13256, 224, 3), - (13257, 224, 3), - (13258, 224, 3), - (13262, 102, 1), - (13263, 102, 1), - (13264, 102, 1), - (13271, 1685, 1), - (13272, 1685, 1), - (13295, 20, 1), - (13308, 26, 3), - (13326, 310, 6), - (13326, 1685, 1), - (13332, 30, 6), - (13363, 1685, 1), - (13383, 1685, 1), - (13385, 1685, 1), - (13388, 1685, 1), - (13389, 1685, 1), - (13396, 1685, 1), - (13396, 3815, 10), - (13401, 1685, 1), - (13404, 259, 6), - (13404, 1685, 1), - (13410, 1685, 1), - (13413, 1685, 1), - (13415, 1092, 1), - (13415, 1685, 1), - (13416, 626, 1), - (13416, 1685, 1), - (13419, 1685, 1), - (13425, 1685, 1), - (13444, 1685, 1), - (13447, 1685, 1), - (13449, 1685, 1), - (13449, 11073, 1), - (13454, 1685, 1), - (13463, 458, 1), - (13463, 1685, 1), - (13466, 1685, 1), - (13467, 1685, 1), - (13468, 1685, 1), - (13472, 1685, 1), - (13474, 444, 1), - (13474, 1685, 1), - (13477, 1685, 1), - (13483, 1685, 1), - (13484, 1685, 1), - (13485, 1685, 1), - (13490, 1685, 1), - (13492, 199, 3), - (13492, 1685, 1), - (13493, 1685, 1), - (13496, 187, 5), - (13496, 1685, 1), - (13499, 30, 1), - (13499, 1685, 1), - (13502, 259, 3), - (13502, 1685, 1), - (13505, 1685, 1), - (13508, 1685, 1), - (13511, 1685, 1), - (13511, 3837, 3), - (13514, 1685, 1), - (13517, 941, 1), - (13517, 1685, 1), - (13520, 1685, 1), - (13521, 1685, 1), - (13524, 1685, 1), - (13527, 1685, 1), - (13528, 1685, 1), - (13529, 1685, 1), - (13530, 1685, 1), - (13533, 1685, 1), - (13542, 184, 3), - (13542, 1685, 1), - (13545, 1685, 1), - (13546, 1685, 1), - (13549, 1685, 1), - (13556, 1685, 1), - (13562, 872, 1), - (13562, 1685, 1), - (13565, 1685, 1), - (13565, 3804, 1), - (13568, 876, 1), - (13568, 1685, 1), - (13571, 1685, 1), - (13575, 1685, 1), - (13578, 1685, 1), - (13584, 1685, 1), - (13585, 1685, 1), - (13585, 3826, 1), - (13586, 1685, 1), - (13589, 30, 3), - (13589, 1685, 1), - (13590, 30, 3), - (13590, 1685, 1), - (13592, 702, 1), - (13592, 1685, 1), - (13595, 1685, 1), - (13595, 6001, 11), - (13598, 1685, 1), - (13601, 1685, 1), - (13604, 1685, 1), - (13607, 1685, 1), - (13610, 1685, 1), - (13613, 1685, 1), - (13616, 1685, 1), - (13617, 1685, 1), - (13618, 1685, 1), - (13619, 1685, 1), - (13621, 278, 5), - (13621, 1685, 1), - (13624, 1685, 1), - (13627, 1685, 1), - (13628, 1685, 1), - (13630, 1685, 1), - (13633, 1685, 1), - (13646, 1668, 1), - (13646, 1685, 1), - (13650, 1685, 1), - (13653, 1685, 1), - (13656, 1685, 1), - (13663, 1685, 1), - (13667, 500, 1), - (13667, 1685, 1), - (13670, 1685, 1), - (13673, 1158, 1), - (13674, 7754, 1), - (13675, 278, 5), - (13675, 1685, 1), - (13678, 1685, 1), - (13682, 1685, 1), - (13683, 1685, 1), - (13684, 1685, 1), - (13685, 1685, 1), - (13686, 1685, 1), - (13687, 1685, 1), - (13688, 1685, 1), - (13689, 751, 1), - (13689, 1685, 1), - (13692, 1685, 1), - (13693, 1685, 1), - (13695, 1685, 1), - (13698, 784, 1), - (13698, 1685, 1), - (13701, 785, 1), - (13701, 1685, 1), - (13704, 787, 1), - (13704, 1685, 1), - (13707, 58, 1), - (13707, 1685, 1), - (13710, 1685, 1), - (13713, 1685, 1), - (13718, 1685, 1), - (13720, 1685, 1), - (13723, 58, 1), - (13723, 1685, 1), - (13726, 1685, 1), - (13727, 25, 3), - (13727, 1685, 1), - (13734, 217, 1), - (13734, 1685, 1), - (13753, 534, 1), - (13753, 1685, 1), - (13758, 602, 1), - (13758, 1685, 1), - (13763, 1685, 1), - (13764, 535, 1), - (13764, 1685, 1), - (13767, 1685, 1), - (13770, 1685, 1), - (13771, 1685, 1), - (13773, 310, 3), - (13773, 1685, 1), - (13774, 310, 3), - (13774, 1685, 1), - (13775, 310, 3), - (13775, 1685, 1), - (13779, 1685, 1), - (13782, 439, 3), - (13782, 1685, 1), - (13785, 1685, 1), - (13789, 1685, 1), - (13790, 1685, 1), - (13792, 1685, 1), - (13795, 1685, 1), - (13798, 1685, 1), - (13804, 1685, 1), - (13807, 1685, 1), - (13810, 1685, 1), - (13813, 1685, 1), - (13816, 1685, 1), - (13819, 1685, 1), - (13820, 1685, 1), - (13823, 1685, 1), - (13826, 1685, 1), - (13829, 1685, 1), - (13832, 1685, 1), - (13835, 1685, 1), - (13838, 1685, 1), - (13841, 1685, 1), - (13845, 1685, 1), - (13872, 1685, 1), - (13873, 961, 1), - (13873, 1685, 1), - (13878, 609, 1), - (13878, 1685, 1), - (13881, 387, 1), - (13881, 1685, 1), - (13889, 1012, 1), - (13889, 1685, 1), - (13899, 1685, 1), - (13905, 1685, 1), - (13908, 1685, 1), - (13911, 1685, 1), - (13914, 1685, 1), - (13917, 606, 1), - (13917, 1685, 1), - (13920, 125, 1), - (13920, 1685, 1), - (13933, 142, 20), - (13943, 142, 20), - (13953, 142, 20), - (13963, 142, 20), - (13973, 142, 20), - (13983, 142, 20), - (13993, 142, 20), - (14003, 1685, 1), - (14006, 30, 6), - (14006, 1685, 1), - (14009, 1685, 1), - (14010, 1685, 1), - (14011, 1685, 1), - (14011, 10394, 1), - (14016, 1685, 1), - (14016, 6001, 17), - (14018, 1684, 1), - (14019, 1685, 1), - (14026, 1685, 1), - (14029, 1685, 1), - (14032, 1685, 1), - (14037, 804, 1), - (14037, 1685, 1), - (14040, 300, 1), - (14040, 1685, 1), - (14043, 1685, 1), - (14046, 87, 1), - (14046, 1685, 1), - (14051, 1685, 1), - (14052, 1685, 1), - (14053, 1685, 1), - (14054, 1685, 1), - (14055, 1685, 1), - (14056, 1685, 1), - (14059, 1685, 1), - (14062, 821, 1), - (14062, 1685, 1), - (14065, 1685, 1), - (14065, 3215, 1), - (14068, 1685, 1), - (14068, 3216, 1), - (14071, 1685, 1), - (14076, 1685, 1), - (14080, 1685, 1), - (14081, 1685, 1), - (14082, 1685, 1), - (14085, 741, 1), - (14085, 1685, 1), - (14088, 769, 1), - (14088, 1685, 1), - (14091, 701, 1), - (14091, 1685, 1), - (14094, 1685, 1), - (14097, 1685, 1), - (14100, 1685, 1), - (14101, 1685, 1), - (14111, 1685, 1), - (14112, 1685, 1), - (14115, 872, 1), - (14115, 1685, 1), - (14129, 1685, 1), - (14130, 1685, 1), - (14132, 1685, 1), - (14132, 2234, 1), - (14135, 1685, 1), - (14138, 1685, 1), - (14139, 1685, 1), - (14140, 1685, 1), - (14141, 1685, 1), - (14144, 1685, 1), - (14144, 3515, 1), - (14148, 1685, 1), - (14151, 1685, 1), - (14154, 276, 3), - (14154, 1685, 1), - (14157, 1685, 1), - (14160, 1685, 1), - (14160, 7001, 1), - (14163, 1685, 1), - (14163, 7001, 1), - (14166, 945, 1), - (14166, 1685, 1), - (14169, 1685, 1), - (14173, 1685, 1), - (14176, 1685, 1), - (14176, 8261, 1), - (14179, 359, 1), - (14179, 1685, 1), - (14180, 1685, 1), - (14181, 1685, 1), - (14181, 3837, 12), - (14186, 809, 5), - (14186, 1685, 1), - (14189, 1685, 1), - (14192, 1685, 1), - (14196, 465, 3), - (14196, 1685, 1), - (14199, 499, 1), - (14199, 1685, 1), - (14200, 1685, 1), - (14203, 1685, 1), - (14206, 1685, 1), - (14207, 1685, 1), - (14208, 1685, 1), - (14208, 7689, 1), - (14209, 1685, 1), - (14210, 1685, 1), - (14213, 1065, 1), - (14213, 1685, 1), - (14218, 1685, 1), - (14221, 1685, 1), - (14222, 224, 3), - (14222, 1685, 1), - (14223, 47, 1), - (14223, 1685, 1), - (14224, 1685, 1), - (14225, 177, 1), - (14225, 1685, 1), - (14229, 135, 1), - (14231, 1685, 1), - (14232, 1685, 1), - (14233, 1685, 1), - (14234, 1685, 1), - (14237, 1685, 1), - (14238, 1041, 1), - (14238, 1685, 1), - (14241, 386, 1), - (14241, 1685, 1), - (14244, 1685, 1), - (14249, 1685, 1), - (14254, 386, 1), - (14254, 1685, 1), - (14256, 1685, 1), - (14259, 384, 1), - (14259, 1685, 1), - (14265, 939, 1), - (14265, 1685, 1), - (14272, 1685, 1), - (14273, 1685, 1), - (14274, 1685, 1), - (14275, 1685, 1), - (14278, 985, 1), - (14278, 1685, 1), - (14280, 57, 1), - (14280, 1685, 1), - (14281, 291, 1), - (14281, 1685, 1), - (14282, 1685, 1), - (14282, 3812, 1), - (14283, 1685, 1), - (14286, 753, 1), - (14286, 1685, 1), - (14289, 1685, 1), - (14292, 207, 1), - (14292, 1685, 1), - (14295, 1685, 1), - (14295, 3816, 1), - (14304, 1685, 1), - (14304, 8341, 1), - (14307, 1685, 1), - (14308, 431, 1), - (14308, 1685, 1), - (14311, 430, 1), - (14311, 1685, 1), - (14314, 901, 1), - (14314, 1685, 1), - (14318, 1685, 1), - (14318, 7703, 1), - (14321, 1685, 1), - (14322, 1685, 1), - (14323, 1685, 1), - (14324, 1685, 1), - (14328, 1154, 1), - (14328, 1685, 1), - (14331, 515, 1), - (14331, 1685, 1), - (14338, 308, 3), - (14338, 1685, 1), - (14341, 748, 1), - (14341, 1685, 1), - (14346, 1685, 1), - (14349, 215, 6), - (14352, 175, 3), - (14352, 1685, 1), - (14355, 1685, 1), - (14358, 1685, 1), - (14359, 1685, 1), - (14360, 1685, 1), - (14361, 23, 3), - (14364, 173, 1), - (14364, 1685, 1), - (14372, 1685, 1), - (14690, 756, 1), - (14733, 786, 1), - (15100, 467, 1), - (15105, 131, 1), - (15113, 130, 1), - (15120, 800, 1), - (15132, 660, 1), - (15135, 660, 1), - (15141, 30, 3), - (15147, 701, 13), - (15154, 659, 1), - (15158, 657, 1), - (15159, 770, 1), - (15162, 659, 1), - (15168, 657, 1), - (15174, 9400, 1), - (15179, 7755, 1), - (15182, 9403, 1), - (15204, 390, 1), - (15207, 323, 1), - (15210, 1041, 1), - (15220, 622, 1), - (15223, 624, 1), - (15226, 621, 1), - (15229, 623, 1), - (15253, 462, 1), - (15258, 184, 1), - (15270, 7003, 1), - (15280, 778, 1), - (15295, 2234, 1), - (15314, 36, 1), - (15317, 35, 1), - (15320, 558, 1), - (15341, 19, 3), - (15342, 8500, 1), - (15344, 38, 1), - (15348, 9504, 1), - (15356, 149, 1), - (15358, 151, 1), - (15359, 50, 1), - (15363, 447, 3), - (15371, 3729, 1), - (15377, 638, 1), - (15389, 935, 1), - (15396, 23, 3), - (15397, 494, 3), - (15403, 8604, 1), - (15406, 3817, 1), - (15414, 241, 1), - (15421, 245, 3), - (15424, 247, 1), - (15424, 982, 6), - (15466, 3551, 1), - (15469, 1120, 1), - (15472, 521, 1), - (15478, 578, 1), - (15481, 398, 24), - (15482, 261, 1), - (15485, 495, 9), - (15486, 534, 3), - (15526, 3702, 1), - (15549, 244, 1), - (15552, 3710, 1), - (15571, 351, 1), - (15579, 826, 1), - (15591, 2899, 1), - (15598, 759, 1), - (15598, 1150, 1), - (15598, 1151, 1), - (15598, 1152, 1), - (15605, 639, 1), - (15606, 160, 4), - (15622, 23, 3), - (15632, 789, 1), - (15639, 749, 1), - (15640, 822, 2), - (15746, 804, 1), - (15778, 87, 1), - (15833, 2045, 1), - (15836, 463, 1), - (15839, 19, 9), - (15855, 153, 9), - (15891, 988, 1), - (15893, 987, 1), - (15895, 986, 1), - (15961, 3701, 1), - (16062, 263, 1), - (16071, 2209, 3), - (16087, 53, 1), - (16094, 43, 1), - (16103, 7703, 1), - (16105, 684, 1), - (16106, 684, 1), - (16107, 684, 1), - (16117, 309, 6), - (16124, 3711, 1), - (16128, 3711, 1), - (16131, 73, 1), - (16137, 10394, 1), - (16140, 489, 1), - (16156, 137, 1), - (16159, 2045, 1), - (16163, 260, 1), - (16163, 7747, 1), - (16164, 358, 3), - (16176, 337, 1), - (16180, 584, 1), - (16185, 9202, 1), - (16185, 9203, 1), - (16189, 823, 3), - (16203, 403, 1), - (16211, 152, 1), - (16218, 403, 1), - (16221, 393, 1), - (16225, 219, 1), - (16238, 443, 1), - (16246, 245, 3), - (16249, 17, 3), - (16257, 470, 20), - (16266, 790, 1), - (16287, 669, 1), - (16297, 553, 1), - (16300, 668, 1), - (16303, 3506, 1), - (16306, 777, 1), - (16336, 1257, 1), - (16339, 773, 1), - (16342, 1257, 1), - (16371, 60, 1), - (16380, 2061, 1), - (16386, 2064, 1), - (16392, 2202, 1), - (16489, 23, 3), - (16604, 180, 3), - (16644, 747, 1), - (16666, 742, 1), - (16730, 82, 3), - (16745, 706, 1), - (17206, 601, 1), - (17209, 111, 1), - (17212, 10367, 1), - (17218, 744, 1), - (17235, 3826, 1), - (17280, 8205, 1), - (17281, 359, 1), - (17288, 41, 1), - (17289, 1062, 1), - (17307, 2047, 1), - (17317, 1270, 1), - (17334, 1041, 1), - (17336, 148, 1), - (17339, 760, 1), - (17342, 148, 1), - (17350, 170, 3), - (17361, 405, 1), - (17361, 426, 1), - (17364, 935, 4), - (17375, 1239, 1), - (17391, 98, 1), - (17409, 120, 1), - (17414, 673, 1), - (17436, 372, 1), - (17439, 372, 1), - (17441, 309, 3), - (17476, 462, 3), - (17492, 840, 1), - (17495, 9702, 1), - (17515, 3841, 1), - (17517, 441, 1), - (17522, 764, 1), - (17533, 677, 1), - (17549, 8700, 1); +-- +-- Dumping data for table `aa_rank_prereqs` +-- + +LOCK TABLES `aa_rank_prereqs` WRITE; +/*!40000 ALTER TABLE `aa_rank_prereqs` DISABLE KEYS */; +INSERT INTO `aa_rank_prereqs` VALUES (129,19,3),(131,19,3),(136,19,3),(141,23,3),(142,23,3),(143,23,3),(146,224,3),(162,224,3),(190,30,3),(191,30,3),(192,30,3),(195,31,3),(230,17,3),(231,17,3),(232,17,3),(255,309,3),(256,309,3),(257,309,3),(260,31,3),(261,31,3),(262,31,3),(263,17,3),(264,17,3),(265,17,3),(267,23,3),(268,23,3),(269,23,3),(446,26,3),(447,26,3),(448,26,3),(462,39,1),(463,39,1),(464,39,1),(468,41,1),(469,41,1),(470,41,1),(471,57,1),(472,57,1),(473,57,1),(474,50,1),(475,50,1),(476,50,1),(477,43,1),(478,43,1),(479,43,1),(480,117,1),(481,117,1),(482,117,1),(483,58,1),(484,58,1),(485,58,1),(489,110,1),(490,110,1),(491,110,1),(492,109,1),(493,109,1),(494,109,1),(495,98,1),(496,98,1),(497,98,1),(498,102,1),(499,102,1),(500,102,1),(501,107,1),(502,107,1),(503,107,1),(531,19,3),(532,19,3),(534,6001,11),(535,6001,11),(536,6001,11),(537,112,3),(538,112,3),(539,17,3),(540,17,3),(541,17,3),(542,309,3),(543,309,3),(544,309,3),(567,45,1),(574,125,1),(575,125,1),(576,125,1),(583,73,1),(584,73,1),(585,73,1),(586,120,1),(587,120,1),(588,120,1),(589,87,1),(590,87,1),(591,87,1),(592,30,1),(593,6001,11),(594,6001,11),(595,6001,11),(596,6000,11),(597,6000,11),(598,6000,11),(637,23,3),(638,23,3),(639,23,3),(640,23,3),(641,23,3),(642,23,3),(643,55,1),(644,82,1),(702,30,1),(703,30,1),(704,30,1),(705,30,1),(706,30,1),(715,6001,11),(716,6001,11),(717,6001,11),(754,153,3),(755,153,3),(756,153,3),(770,23,3),(771,23,3),(772,23,3),(773,217,1),(774,217,1),(775,217,1),(782,35,1),(783,35,1),(784,35,1),(806,81,1),(849,180,3),(850,180,3),(851,180,3),(886,102,1),(887,102,1),(893,87,1),(894,87,1),(924,23,3),(925,23,3),(931,23,1),(932,23,1),(933,23,1),(975,102,1),(1018,227,3),(1041,30,6),(1042,30,6),(1043,30,6),(1044,310,6),(1045,310,6),(1046,310,6),(1047,311,3),(1048,311,3),(1049,311,3),(1050,309,6),(1051,309,6),(1052,309,6),(1102,30,1),(1103,30,1),(1104,30,1),(1105,30,1),(1106,30,1),(1107,23,3),(1108,23,3),(1109,23,3),(1110,187,5),(1111,187,5),(1112,187,5),(1122,176,2),(1126,58,1),(1127,58,1),(1128,58,1),(1129,125,1),(1130,125,1),(1150,189,3),(1151,189,3),(1152,189,3),(1163,309,3),(1164,309,3),(1165,309,3),(1203,19,3),(1204,19,3),(1205,19,3),(1210,114,6),(1211,114,6),(1212,114,6),(1213,215,6),(1214,215,6),(1215,215,6),(1242,173,3),(1243,173,3),(1244,173,3),(1251,61,1),(1252,64,1),(1253,62,1),(1254,63,1),(1274,175,3),(1275,175,3),(1276,175,3),(1278,6001,11),(1279,6001,11),(1280,6001,11),(1323,47,1),(1337,308,3),(1338,308,3),(1339,308,3),(1414,451,1),(1415,451,1),(1416,451,1),(1417,451,1),(1418,451,1),(1420,17,3),(1421,17,3),(1422,17,3),(1423,17,3),(1424,17,3),(1425,374,3),(1426,374,3),(1427,374,3),(1428,374,3),(1429,374,3),(1435,20,3),(1436,20,3),(1437,20,3),(1458,375,3),(1459,255,5),(1460,255,5),(1461,255,5),(1471,362,1),(1472,362,1),(1473,362,1),(1474,362,1),(1475,362,1),(1483,114,6),(1484,114,6),(1485,114,6),(1486,19,7),(1487,19,7),(1488,19,7),(1489,19,7),(1490,19,7),(1494,80,1),(1495,185,6),(1496,185,6),(1497,185,6),(1501,46,1),(1502,46,1),(1503,46,1),(1504,60,1),(1505,60,1),(1506,60,1),(1511,175,3),(1512,175,3),(1513,175,3),(1514,259,6),(1515,259,6),(1516,259,6),(1524,30,3),(1525,30,3),(1526,30,3),(1543,439,3),(1544,439,3),(1545,439,3),(1546,420,1),(1547,420,1),(1548,420,1),(1552,13,5),(1553,13,5),(1554,13,5),(1555,359,3),(1556,359,3),(1557,359,3),(1558,46,1),(1559,46,1),(1560,46,1),(1572,263,1),(1573,263,1),(1574,263,1),(1575,263,1),(1576,263,1),(1577,58,1),(1578,58,1),(1579,58,1),(1583,300,6),(1584,300,6),(1585,300,6),(1586,300,6),(1587,300,6),(1591,222,3),(1601,82,1),(1602,82,1),(1603,82,1),(1608,82,3),(1609,82,3),(1610,82,3),(1611,181,2),(1612,181,2),(1613,181,2),(1614,181,2),(1615,181,2),(1627,13,5),(1628,13,5),(1629,13,5),(1638,224,3),(1639,565,1),(1640,793,1),(1641,121,3),(1642,121,3),(1643,77,1),(1644,85,1),(1645,77,1),(1646,85,1),(1656,153,1),(1657,153,1),(1659,285,1),(1660,285,1),(1667,570,1),(2400,38,1),(2401,38,1),(2402,38,1),(3676,35,1),(4666,435,3),(4667,435,3),(4668,435,3),(4669,435,3),(4670,435,3),(4688,497,5),(4689,497,5),(4690,497,5),(4691,497,5),(4692,497,5),(4707,30,6),(4708,30,6),(4709,30,6),(4710,310,6),(4711,310,6),(4712,310,6),(4713,311,3),(4714,311,3),(4715,311,3),(4716,309,6),(4717,309,6),(4718,309,6),(4749,23,3),(4750,23,3),(4751,23,3),(4752,114,6),(4753,114,6),(4754,114,6),(4755,215,6),(4756,215,6),(4757,215,6),(4761,526,3),(4762,526,3),(4763,526,3),(4773,20,3),(4795,309,3),(4796,309,3),(4797,309,3),(4829,420,1),(4830,420,1),(4831,420,1),(4844,435,3),(4845,435,3),(4846,435,3),(4847,435,3),(4848,435,3),(4861,68,1),(4862,68,1),(4863,68,1),(4864,175,3),(4865,175,3),(4866,175,3),(4887,413,3),(4888,413,3),(4889,413,3),(4890,57,1),(4894,409,3),(4895,409,3),(4896,409,3),(4903,784,1),(4906,785,1),(4909,786,1),(4912,787,1),(4915,794,1),(4916,794,1),(4917,794,1),(4921,117,1),(4922,117,1),(4923,117,1),(4924,740,3),(4925,740,3),(4926,740,3),(4931,173,8),(4932,173,8),(4933,173,8),(4951,439,3),(4952,439,3),(4953,439,3),(4975,30,1),(4976,30,1),(4977,30,1),(4978,30,1),(4979,30,1),(4986,82,1),(4987,82,1),(4988,82,1),(4989,82,3),(4990,82,3),(4991,82,3),(5010,35,1),(5011,35,1),(5012,35,1),(5038,30,3),(5039,30,3),(5040,30,3),(5041,6001,11),(5042,6001,11),(5043,6001,11),(5061,45,1),(5069,224,3),(5070,19,3),(5071,19,3),(5072,19,3),(5080,255,5),(5081,255,5),(5082,255,5),(5098,73,2),(5118,396,1),(5119,396,1),(5120,396,1),(5127,261,3),(5128,261,3),(5129,261,3),(5133,23,3),(5134,23,3),(5135,23,3),(5136,496,5),(5137,496,5),(5138,496,5),(5139,496,5),(5140,496,5),(5251,447,3),(5252,447,3),(5253,447,3),(5264,278,5),(5265,278,5),(5266,278,5),(5267,278,5),(5268,278,5),(5270,87,1),(5271,87,1),(5272,87,1),(5286,23,3),(5287,23,3),(5288,23,3),(5311,185,6),(5312,185,6),(5313,185,6),(5330,1685,1),(5333,1685,1),(5336,1685,1),(5339,1685,1),(5342,1685,1),(5347,1685,1),(5348,1685,1),(5350,707,4),(5350,1685,1),(5353,1685,1),(5356,1685,1),(5357,1685,1),(5360,1685,1),(5363,447,3),(5363,1685,1),(5366,1685,1),(5369,1685,1),(5513,58,1),(5514,58,1),(5515,58,1),(5529,19,7),(5530,19,7),(5531,19,7),(5532,19,7),(5533,19,7),(5542,30,6),(5543,30,6),(5544,30,6),(5545,310,6),(5546,310,6),(5547,310,6),(5548,311,3),(5549,311,3),(5550,311,3),(5551,309,6),(5552,309,6),(5553,309,6),(5571,23,3),(5572,23,3),(5573,23,3),(5574,114,6),(5575,114,6),(5576,114,6),(5577,215,6),(5578,215,6),(5579,215,6),(5595,309,3),(5596,309,3),(5597,309,3),(5607,794,1),(5608,794,1),(5609,794,1),(5617,23,3),(5618,23,3),(5619,23,3),(5702,30,1),(5703,30,1),(5704,30,1),(5705,30,1),(5706,30,1),(5759,374,3),(5760,374,3),(5761,374,3),(5762,374,3),(5763,374,3),(5791,19,3),(5792,19,3),(5793,19,3),(5797,396,1),(5798,396,1),(5799,396,1),(5803,255,5),(5804,255,5),(5805,255,5),(5806,30,3),(5807,30,3),(5808,30,3),(5825,45,1),(5826,185,6),(5827,185,6),(5828,185,6),(5854,217,1),(5855,217,1),(5856,217,1),(5857,173,3),(5858,173,3),(5859,173,3),(5869,57,1),(5871,57,1),(5872,57,1),(5880,60,1),(5881,60,1),(5882,60,1),(5886,58,1),(5887,58,1),(5888,58,1),(5892,784,1),(5893,785,1),(5894,786,1),(5895,787,1),(5939,278,5),(5940,278,5),(5941,278,5),(5942,278,5),(5943,278,5),(5944,740,3),(5945,740,3),(5946,740,3),(5947,175,3),(5948,175,3),(5949,175,3),(5950,175,3),(5951,175,3),(5952,175,3),(5954,68,1),(5955,68,1),(5956,68,1),(5969,6001,11),(5970,6001,11),(5971,6001,11),(5972,6001,11),(5973,6000,11),(5984,702,1),(6017,82,1),(6018,82,1),(6019,82,1),(6026,826,1),(6027,826,1),(6028,826,1),(6042,439,3),(6043,439,3),(6044,439,3),(6054,173,8),(6055,173,8),(6056,173,8),(6063,87,1),(6064,87,1),(6065,87,1),(6088,392,1),(6089,392,1),(6090,392,1),(6092,447,3),(6093,447,3),(6094,447,3),(6102,224,3),(6106,308,3),(6107,308,3),(6108,308,3),(6109,308,3),(6110,308,3),(6111,308,3),(6130,120,1),(6131,120,1),(6132,120,1),(6136,300,6),(6158,308,3),(6159,308,3),(6160,308,3),(6209,245,3),(6210,245,3),(6211,245,3),(6228,404,1),(6229,404,1),(6230,404,1),(6231,404,1),(6233,43,1),(6234,43,1),(6235,43,1),(6260,98,1),(6261,98,1),(6262,98,1),(6272,672,1),(6273,672,1),(6274,672,1),(6275,790,1),(6276,790,1),(6277,790,1),(6302,3710,1),(6303,3710,1),(6304,3710,1),(6319,107,1),(6320,107,1),(6321,107,1),(6333,125,1),(6337,553,1),(6338,553,1),(6339,553,1),(6340,777,1),(6341,777,1),(6342,777,1),(6346,494,3),(6347,494,3),(6348,494,3),(6349,500,3),(6350,500,3),(6351,500,3),(6352,409,3),(6353,409,3),(6354,409,3),(6380,128,3),(6381,128,3),(6382,128,3),(6400,187,5),(6401,187,5),(6402,187,5),(6403,23,3),(6404,23,3),(6405,23,3),(6439,41,1),(6440,41,1),(6441,420,1),(6442,362,1),(6443,362,1),(6445,176,1),(6446,176,1),(6447,176,1),(6478,3800,1),(6479,3800,1),(6480,3800,1),(6481,36,1),(6482,36,1),(6483,36,1),(6484,558,1),(6485,558,1),(6486,558,1),(6499,611,1),(6500,526,3),(6501,526,3),(6502,526,3),(6503,172,1),(6504,172,1),(6505,172,1),(6506,172,1),(6514,404,1),(6515,404,1),(6516,404,1),(6517,20,1),(6528,107,1),(6630,278,5),(6631,278,5),(6632,278,5),(6633,278,5),(6634,278,5),(6636,358,3),(6637,358,3),(6638,358,3),(6668,672,3),(6669,672,3),(6670,672,3),(6697,857,1),(6698,857,1),(6699,857,1),(6700,857,1),(6701,857,1),(6703,171,1),(6704,171,1),(6705,171,1),(6712,177,1),(6713,177,1),(6714,177,1),(6715,177,1),(6716,177,1),(6755,184,3),(6756,184,3),(6757,184,3),(6819,524,1),(6820,524,1),(6821,524,1),(6823,320,1),(6824,320,1),(6825,320,1),(6826,320,1),(6827,320,1),(6870,544,1),(6871,544,1),(6872,544,1),(6873,3837,3),(6874,3837,3),(6875,3837,3),(6876,259,3),(6877,259,3),(6878,259,3),(6900,465,3),(6901,465,3),(6902,465,3),(6903,465,3),(6904,465,3),(6908,499,1),(6909,499,1),(6910,499,1),(6930,611,1),(6935,465,3),(6936,465,3),(6937,465,3),(6941,962,1),(6942,962,1),(6943,962,1),(6944,962,1),(6945,962,1),(6977,3817,1),(6978,3817,1),(6979,3817,1),(6980,128,1),(6981,128,1),(6982,128,1),(6983,245,3),(6988,985,1),(6989,985,1),(6990,985,1),(7005,789,1),(7006,789,1),(7007,789,1),(7033,804,1),(7034,804,1),(7035,804,1),(7036,3646,1),(7037,3646,1),(7038,3646,1),(7050,26,3),(7051,26,3),(7052,26,3),(7053,26,3),(7054,26,3),(7055,26,3),(7063,26,3),(7064,26,3),(7065,26,3),(7100,254,3),(7101,254,3),(7102,254,3),(7103,286,1),(7104,286,1),(7105,286,1),(7116,110,1),(7117,110,1),(7118,110,1),(7122,435,3),(7123,435,3),(7124,435,3),(7125,435,3),(7126,435,3),(7128,109,1),(7129,109,1),(7130,109,1),(7134,439,3),(7135,439,3),(7136,439,3),(7137,672,1),(7138,672,1),(7139,672,1),(7184,1685,1),(7199,175,3),(7200,175,3),(7201,175,3),(7204,278,5),(7205,278,5),(7206,278,5),(7207,278,5),(7208,278,5),(7215,68,1),(7216,68,1),(7232,114,6),(7233,114,6),(7234,114,6),(7246,794,1),(7247,794,1),(7248,794,1),(7253,784,1),(7254,785,1),(7255,786,1),(7256,787,1),(7260,60,1),(7261,60,1),(7262,60,1),(7263,58,1),(7264,58,1),(7265,58,1),(7266,125,1),(7276,217,1),(7277,217,1),(7278,217,1),(7285,173,3),(7286,173,3),(7287,173,3),(7288,409,3),(7289,409,3),(7290,409,3),(7291,173,8),(7292,173,8),(7293,173,8),(7301,19,3),(7302,19,3),(7303,19,3),(7310,255,5),(7311,255,5),(7312,255,5),(7316,41,1),(7317,41,1),(7323,254,3),(7324,254,3),(7325,254,3),(7326,286,1),(7327,286,1),(7328,286,1),(7329,6001,11),(7330,6001,11),(7331,6001,11),(7335,702,1),(7359,82,1),(7360,82,1),(7361,82,1),(7378,82,3),(7379,82,3),(7380,82,3),(7381,82,3),(7382,82,3),(7383,82,3),(7390,87,1),(7391,87,1),(7392,87,1),(7407,31,3),(7414,185,6),(7415,185,6),(7416,185,6),(7433,30,1),(7434,30,1),(7435,30,1),(7436,30,1),(7437,30,1),(7445,187,5),(7446,187,5),(7447,187,5),(7448,553,1),(7449,553,1),(7450,553,1),(7451,777,1),(7452,777,1),(7453,777,1),(7466,224,3),(7472,447,3),(7473,447,3),(7474,447,3),(7478,245,3),(7497,128,3),(7498,128,3),(7499,128,3),(7554,19,7),(7555,19,7),(7556,19,7),(7557,19,7),(7558,19,7),(7562,30,6),(7563,30,6),(7564,30,6),(7581,215,6),(7582,215,6),(7583,215,6),(7615,494,3),(7616,494,3),(7617,494,3),(7618,500,3),(7619,500,3),(7620,500,3),(7621,20,1),(7622,26,3),(7623,26,3),(7624,26,3),(7631,309,3),(7632,309,3),(7633,309,3),(7650,310,6),(7651,310,6),(7652,310,6),(7653,311,3),(7654,311,3),(7655,311,3),(7656,309,6),(7657,309,6),(7658,309,6),(7659,153,3),(7660,153,3),(7661,153,3),(7664,170,3),(7665,170,3),(7666,170,3),(7667,170,3),(7668,170,3),(7682,68,1),(7686,435,3),(7687,435,3),(7688,435,3),(7691,224,3),(7695,862,3),(7696,862,3),(7697,862,3),(7700,310,3),(7701,310,3),(7702,310,3),(7704,3707,1),(7705,3707,1),(7706,3707,1),(7707,87,1),(7708,87,1),(7709,87,1),(7710,702,1),(7711,702,1),(7712,3826,1),(7715,901,1),(7716,901,1),(7717,901,1),(7718,125,1),(7722,19,7),(7723,19,7),(7724,19,7),(7725,19,7),(7726,19,7),(7733,195,3),(7743,184,1),(7744,184,1),(7745,184,1),(7748,13,5),(7749,13,5),(7750,13,5),(7751,2234,1),(7752,2234,1),(7753,2234,1),(7754,85,1),(7757,9403,1),(7758,9403,1),(7759,9403,1),(7760,824,1),(7761,824,1),(7762,824,1),(7765,7689,1),(7766,7689,1),(7767,7689,1),(7768,7689,1),(7770,19,3),(7771,19,3),(7772,19,3),(7773,19,3),(7774,19,3),(7775,19,3),(7822,1154,1),(7823,1154,1),(7824,1154,1),(7825,1154,1),(7826,1154,1),(7827,1404,3),(7832,60,1),(7833,60,1),(7834,60,1),(7835,60,1),(7836,60,1),(7842,19,7),(7843,19,7),(7844,19,7),(7940,558,1),(7941,558,1),(7942,558,1),(7943,39,1),(7944,41,1),(7951,19,3),(7952,19,3),(7953,19,3),(7983,520,1),(7984,520,1),(7985,520,1),(7986,705,1),(7987,705,1),(7988,705,1),(7989,1092,1),(7990,1092,1),(7991,1092,1),(7992,1092,1),(7993,39,1),(7994,39,1),(7995,39,1),(8031,791,1),(8032,791,1),(8033,791,1),(8035,521,1),(8036,521,1),(8037,521,1),(8069,160,4),(8070,160,4),(8071,160,4),(8076,565,1),(8077,565,1),(8078,565,1),(8079,565,1),(8080,565,1),(8081,565,1),(8082,208,1),(8083,208,1),(8084,208,1),(8195,3707,1),(8196,3707,1),(8197,3707,1),(8198,210,1),(8199,210,1),(8200,210,1),(8204,153,1),(8205,153,1),(8206,153,1),(8207,285,1),(8208,285,1),(8209,285,1),(8220,3812,1),(8224,516,3),(8225,516,3),(8226,516,3),(8260,1211,1),(8263,142,20),(8264,142,20),(8265,142,20),(8266,142,20),(8267,142,20),(8268,142,20),(8269,142,20),(8270,142,20),(8271,142,20),(8272,142,20),(8273,142,20),(8274,142,20),(8275,142,20),(8276,142,20),(8277,142,20),(8278,142,20),(8279,142,20),(8280,142,20),(8281,142,20),(8282,142,20),(8283,142,20),(8284,142,20),(8285,142,20),(8286,142,20),(8287,142,20),(8288,142,20),(8289,142,20),(8290,142,20),(8291,142,20),(8292,142,20),(8293,142,20),(8294,142,20),(8295,142,20),(8296,142,20),(8297,142,20),(8303,309,6),(8309,31,3),(8310,31,3),(8311,31,3),(8312,110,1),(8317,8205,1),(8318,8205,1),(8319,199,1),(8320,199,1),(8321,199,1),(8332,861,1),(8333,861,1),(8334,861,1),(8335,1041,1),(8336,1041,1),(8337,1041,1),(8338,1041,1),(8339,1041,1),(8344,215,6),(8345,215,6),(8346,215,6),(8347,616,1),(8348,616,1),(8349,616,1),(8351,142,20),(8352,142,20),(8353,142,20),(8354,142,20),(8355,142,20),(8356,142,20),(8357,142,20),(8358,142,20),(8359,142,20),(8360,142,20),(8361,142,20),(8362,142,20),(8363,142,20),(8364,142,20),(8365,142,20),(8366,142,20),(8367,142,20),(8368,142,20),(8369,142,20),(8370,142,20),(8371,142,20),(8372,142,20),(8373,142,20),(8374,142,20),(8375,142,20),(8376,142,20),(8377,142,20),(8378,142,20),(8379,142,20),(8380,142,20),(8381,142,20),(8382,142,20),(8383,142,20),(8384,142,20),(8385,142,20),(8386,142,20),(8387,142,20),(8388,142,20),(8389,142,20),(8390,142,20),(8391,142,20),(8392,142,20),(8393,142,20),(8394,142,20),(8395,142,20),(8396,142,20),(8397,142,20),(8398,142,20),(8399,142,20),(8400,142,20),(8401,142,20),(8402,142,20),(8403,142,20),(8404,142,20),(8405,142,20),(8406,142,20),(8407,142,20),(8408,142,20),(8409,142,20),(8410,142,20),(8411,142,20),(8412,142,20),(8413,142,20),(8414,142,20),(8415,142,20),(8416,142,20),(8417,142,20),(8418,142,20),(8419,142,20),(8420,142,20),(8421,516,3),(8427,254,3),(8428,254,3),(8429,254,3),(9103,1350,3),(9104,1350,3),(9105,1350,3),(9106,1351,3),(9107,1351,3),(9108,1351,3),(9112,1390,3),(9113,1390,3),(9114,1390,3),(9115,1391,3),(9116,1391,3),(9117,1391,3),(9121,1370,3),(9122,1370,3),(9123,1370,3),(9124,1371,3),(9125,1371,3),(9126,1371,3),(9130,1380,3),(9131,1380,3),(9132,1380,3),(9133,1381,3),(9134,1381,3),(9135,1381,3),(9139,1470,3),(9140,1470,3),(9141,1470,3),(9142,1471,3),(9143,1471,3),(9144,1471,3),(9148,1480,3),(9149,1480,3),(9150,1480,3),(9151,1481,3),(9152,1481,3),(9153,1481,3),(9157,1490,3),(9158,1490,3),(9159,1490,3),(9160,1491,3),(9161,1491,3),(9162,1491,3),(9166,1460,3),(9167,1460,3),(9168,1460,3),(9169,1461,3),(9170,1461,3),(9171,1461,3),(9175,1450,3),(9176,1450,3),(9177,1450,3),(9178,1451,3),(9179,1451,3),(9180,1451,3),(9184,1440,3),(9185,1440,3),(9186,1440,3),(9187,1441,3),(9188,1441,3),(9189,1441,3),(9193,1420,3),(9194,1420,3),(9195,1420,3),(9196,1421,3),(9197,1421,3),(9198,1421,3),(9202,1430,3),(9203,1430,3),(9204,1430,3),(9205,1431,3),(9206,1431,3),(9207,1431,3),(9211,1400,3),(9212,1400,3),(9213,1400,3),(9214,1401,3),(9215,1401,3),(9216,1401,3),(9220,1360,3),(9221,1360,3),(9222,1360,3),(9223,1361,3),(9224,1361,3),(9225,1361,3),(9229,1500,3),(9230,1500,3),(9231,1500,3),(9232,1501,3),(9233,1501,3),(9234,1501,3),(9238,1410,3),(9239,1410,3),(9240,1410,3),(9241,1411,3),(9242,1411,3),(9243,1411,3),(9300,1300,3),(9301,1300,3),(9302,1300,3),(9303,1300,6),(9304,1300,6),(9305,1300,6),(9306,1300,9),(9307,1300,9),(9308,1300,9),(9309,1313,3),(9310,1313,3),(9311,1313,3),(9312,1313,6),(9313,1313,6),(9314,1313,6),(9315,1313,9),(9316,1313,9),(9317,1313,9),(9318,1302,3),(9319,1302,3),(9320,1302,3),(9321,1302,6),(9322,1302,6),(9323,1302,6),(9324,1302,9),(9325,1302,9),(9326,1302,9),(9327,1303,3),(9328,1303,3),(9329,1303,3),(9330,1303,6),(9331,1303,6),(9332,1303,6),(9333,1303,9),(9334,1303,9),(9335,1303,9),(9336,1301,3),(9337,1301,3),(9338,1301,3),(9339,1301,6),(9340,1301,6),(9341,1301,6),(9342,1301,9),(9343,1301,9),(9344,1301,9),(9345,1312,3),(9346,1312,3),(9347,1312,3),(9348,1312,6),(9349,1312,6),(9350,1312,6),(9351,1312,9),(9352,1312,9),(9353,1312,9),(9354,1315,3),(9355,1315,3),(9356,1315,3),(9357,1315,6),(9358,1315,6),(9359,1315,6),(9360,1315,9),(9361,1315,9),(9362,1315,9),(9363,1310,3),(9364,1310,3),(9365,1310,3),(9366,1310,6),(9367,1310,6),(9368,1310,6),(9369,1310,9),(9370,1310,9),(9371,1310,9),(9372,1311,3),(9373,1311,3),(9374,1311,3),(9375,1311,6),(9376,1311,6),(9377,1311,6),(9378,1311,9),(9379,1311,9),(9380,1311,9),(9381,1309,3),(9382,1309,3),(9383,1309,3),(9384,1309,6),(9385,1309,6),(9386,1309,6),(9387,1309,9),(9388,1309,9),(9389,1309,9),(9390,1308,3),(9391,1308,3),(9392,1308,3),(9393,1308,6),(9394,1308,6),(9395,1308,6),(9396,1308,9),(9397,1308,9),(9398,1308,9),(9399,1307,3),(9400,1307,3),(9401,1307,3),(9402,1307,6),(9403,1307,6),(9404,1307,6),(9405,1307,9),(9406,1307,9),(9407,1307,9),(9408,1304,3),(9409,1304,3),(9410,1304,3),(9411,1304,6),(9412,1304,6),(9413,1304,6),(9414,1304,9),(9415,1304,9),(9416,1304,9),(9417,1305,3),(9418,1305,3),(9419,1305,3),(9420,1305,6),(9421,1305,6),(9422,1305,6),(9423,1305,9),(9424,1305,9),(9425,1305,9),(9426,1306,3),(9427,1306,3),(9428,1306,3),(9429,1306,6),(9430,1306,6),(9431,1306,6),(9432,1306,9),(9433,1306,9),(9434,1306,9),(9435,1314,3),(9436,1314,3),(9437,1314,3),(9438,1314,6),(9439,1314,6),(9440,1314,6),(9441,1314,9),(9442,1314,9),(9443,1314,9),(9500,72,1),(10016,19,3),(10017,19,3),(10018,19,3),(10030,558,1),(10031,558,1),(10032,558,1),(10038,19,3),(10039,19,3),(10040,19,3),(10041,358,3),(10042,358,3),(10043,358,3),(10047,6001,11),(10048,6001,11),(10049,6001,11),(10064,82,3),(10065,82,3),(10066,82,3),(10067,82,3),(10068,82,3),(10069,82,3),(10070,278,5),(10071,278,5),(10072,278,5),(10073,278,5),(10074,278,5),(10093,185,6),(10105,170,3),(10106,170,3),(10107,170,3),(10108,170,3),(10109,170,3),(10110,520,1),(10111,520,1),(10112,520,1),(10130,544,1),(10131,544,1),(10132,544,1),(10133,3837,3),(10134,3837,3),(10135,3837,3),(10136,259,3),(10137,259,3),(10138,259,3),(10150,187,5),(10151,187,5),(10152,187,5),(10153,553,1),(10154,553,1),(10155,553,1),(10165,439,3),(10166,439,3),(10167,439,3),(10176,171,1),(10177,171,1),(10178,171,1),(10182,177,1),(10183,177,1),(10184,177,1),(10185,177,1),(10186,177,1),(10197,447,3),(10198,447,3),(10199,447,3),(10203,524,1),(10204,524,1),(10205,524,1),(10206,320,1),(10207,320,1),(10209,175,3),(10210,175,3),(10211,175,3),(10213,278,5),(10214,278,5),(10215,278,5),(10216,278,5),(10217,278,5),(10249,208,1),(10250,208,1),(10251,208,1),(10255,784,1),(10256,785,1),(10257,786,1),(10258,787,1),(10262,58,1),(10263,58,1),(10264,58,1),(10271,173,3),(10272,173,3),(10273,173,3),(10274,173,8),(10275,173,8),(10276,173,8),(10282,791,1),(10283,791,1),(10284,791,1),(10285,521,1),(10286,521,1),(10287,521,1),(10308,128,3),(10309,128,3),(10310,128,3),(10329,3701,1),(10330,199,3),(10332,943,3),(10336,941,1),(10337,941,1),(10338,941,1),(10354,6001,17),(10389,841,1),(10390,841,1),(10391,841,1),(10396,705,4),(10397,1092,4),(10398,3701,1),(10399,3701,1),(10413,207,1),(10414,207,1),(10415,207,1),(10416,207,1),(10417,207,1),(10426,185,18),(10427,519,15),(10428,173,8),(10429,173,8),(10430,173,8),(10431,791,1),(10432,791,1),(10433,791,1),(10434,792,1),(10435,792,1),(10436,792,1),(10450,19,9),(10451,19,9),(10452,19,9),(10456,3800,1),(10457,3800,1),(10458,3800,1),(10462,396,1),(10463,396,1),(10464,391,9),(10465,391,9),(10466,391,9),(10468,19,9),(10469,19,9),(10470,558,1),(10471,558,1),(10472,558,1),(10473,26,3),(10474,26,3),(10475,26,3),(10476,26,3),(10477,26,3),(10510,705,1),(10511,185,3),(10512,185,3),(10513,185,3),(10514,519,3),(10515,519,3),(10516,519,3),(10519,3213,1),(10522,3732,1),(10527,1400,1),(10532,1401,1),(10537,1402,1),(10548,605,13),(10554,263,1),(10555,263,1),(10556,263,1),(10557,1120,1),(10558,1120,1),(10559,1120,1),(10560,1120,1),(10561,3551,1),(10562,3551,1),(10563,3551,1),(10564,217,1),(10565,217,1),(10566,217,1),(10576,109,1),(10579,3646,1),(10580,3646,1),(10588,601,1),(10589,601,1),(10590,601,1),(10591,601,1),(10592,601,1),(10610,265,5),(10611,265,5),(10612,265,5),(10621,180,3),(10622,180,3),(10623,30,3),(10624,30,3),(10625,30,3),(10626,702,1),(10646,3826,1),(10657,276,3),(10658,276,3),(10659,276,3),(10666,98,1),(10667,98,1),(10668,98,1),(10670,19,9),(10708,6001,11),(10709,6001,11),(10710,6001,11),(10711,30,6),(10712,30,6),(10713,30,6),(10714,873,1),(10715,873,1),(10717,184,1),(10718,184,1),(10719,872,1),(10720,872,1),(10721,872,1),(10722,778,1),(10723,778,1),(10724,778,1),(10725,778,1),(10726,778,1),(10727,2235,1),(10728,2235,1),(10730,870,1),(10731,870,1),(10733,219,1),(10734,219,1),(10735,219,1),(10750,286,1),(10751,286,1),(10752,7108,1),(10753,286,1),(10789,10424,1),(10790,705,4),(10791,1092,4),(10800,462,3),(10801,462,3),(10802,462,3),(10903,125,1),(10904,125,1),(10905,125,1),(10909,7007,1),(10910,7007,1),(10911,7007,1),(10915,823,3),(10916,823,3),(10917,823,3),(10951,447,3),(10952,447,3),(10953,447,3),(10954,662,3),(10955,662,3),(10956,662,3),(11011,3710,1),(11012,3710,1),(11013,3710,1),(11014,3899,1),(11015,3899,1),(11016,3899,1),(11020,3899,1),(11050,452,3),(11051,452,3),(11052,452,3),(11053,500,3),(11054,500,3),(11059,452,3),(11060,452,3),(11077,986,1),(11078,988,1),(11079,987,1),(11088,505,1),(11089,505,1),(11090,505,1),(11091,505,1),(12422,1202,1),(12432,23,3),(12433,23,3),(12434,23,3),(12435,23,3),(12436,23,3),(12437,23,3),(12475,7003,1),(12476,7003,1),(12477,7003,1),(12478,3705,9),(12479,3705,9),(12480,3705,9),(12523,114,6),(12526,215,6),(12527,215,6),(12528,215,6),(12529,358,3),(12530,358,3),(12531,358,3),(12553,23,3),(12554,23,3),(12555,23,3),(12556,23,3),(12557,23,3),(12558,23,3),(12582,9400,1),(12583,9400,1),(12584,9400,1),(12587,9403,1),(12588,9403,1),(12589,9403,1),(12600,3514,1),(12606,13,5),(12610,310,3),(12626,1410,3),(12629,1411,3),(12632,1412,3),(12635,428,2),(12639,519,3),(12642,185,3),(12645,519,1),(12646,185,1),(12664,3728,1),(12673,420,1),(12677,17,3),(12679,276,3),(12680,276,3),(12681,276,3),(12697,30,6),(12698,30,6),(12699,30,6),(12713,8202,1),(12714,8202,1),(12715,8202,1),(12716,3702,1),(12717,3702,1),(12718,3702,1),(12719,3702,1),(12720,3506,1),(12721,3506,1),(12722,3506,1),(12723,3506,1),(12727,359,3),(12728,359,3),(12729,359,3),(12730,941,1),(12731,941,1),(12732,941,1),(12733,943,3),(12734,259,3),(12735,259,3),(12736,259,3),(12737,3701,1),(12738,3701,1),(12739,3701,1),(12749,30,1),(12750,30,1),(12751,30,1),(12757,68,1),(12758,68,1),(12759,68,1),(12760,175,3),(12761,175,3),(12762,175,3),(12773,1580,1),(12774,1580,1),(12775,1580,1),(12776,1580,1),(12777,1580,1),(12779,826,1),(12780,826,1),(12781,826,1),(12782,826,1),(12783,826,1),(12784,826,1),(12798,278,5),(12799,278,5),(12800,278,5),(12831,128,1),(12834,128,1),(12835,128,1),(12840,3817,1),(12841,3817,1),(12849,8303,1),(12860,23,3),(12863,23,3),(12865,1155,1),(12866,639,1),(12867,6106,6),(12871,452,3),(12872,452,3),(12874,451,1),(12876,7003,1),(12877,7003,1),(12878,7003,1),(12881,172,1),(12886,304,5),(12887,303,5),(12888,305,5),(12889,501,1),(12890,507,1),(12892,509,3),(12894,1122,1),(12899,57,1),(12900,57,1),(12902,1380,1),(12903,1380,1),(12907,1381,1),(12908,1381,1),(12912,1382,1),(12913,1382,1),(12934,173,3),(12956,784,1),(12957,786,1),(12958,787,1),(12959,785,1),(12964,596,1),(12965,597,1),(12968,1041,1),(12969,1041,1),(12970,1041,1),(12977,1041,1),(12978,1041,1),(12979,1041,1),(12980,1041,1),(12981,1041,1),(12992,707,4),(12993,707,4),(12994,707,4),(13001,9504,1),(13002,9504,1),(13003,9504,1),(13004,153,9),(13005,171,1),(13006,171,1),(13007,171,1),(13008,859,1),(13009,3730,1),(13010,47,1),(13011,47,1),(13012,47,1),(13013,446,1),(13014,446,1),(13015,446,1),(13017,3815,10),(13018,3815,10),(13019,3815,10),(13023,309,6),(13055,8400,1),(13067,643,1),(13072,3514,1),(13073,3514,1),(13074,310,6),(13075,310,6),(13076,310,6),(13077,311,3),(13078,311,3),(13090,20,1),(13092,82,1),(13093,82,1),(13094,82,1),(13104,87,1),(13105,87,1),(13106,87,1),(13130,1685,1),(13140,391,9),(13141,391,9),(13142,391,9),(13143,500,1),(13144,500,1),(13145,500,1),(13146,494,1),(13147,494,1),(13148,494,1),(13155,705,1),(13166,822,1),(13167,822,1),(13168,822,1),(13170,128,3),(13190,187,5),(13191,187,5),(13192,187,5),(13196,3837,3),(13197,3837,3),(13198,3837,3),(13203,199,3),(13204,8261,1),(13205,8261,1),(13206,8261,1),(13213,439,3),(13214,439,3),(13215,439,3),(13216,439,3),(13217,439,3),(13222,3514,1),(13223,3514,1),(13241,173,8),(13244,46,1),(13247,409,3),(13253,58,1),(13254,58,1),(13255,58,1),(13256,224,3),(13257,224,3),(13258,224,3),(13262,102,1),(13263,102,1),(13264,102,1),(13271,1685,1),(13272,1685,1),(13295,20,1),(13308,26,3),(13326,310,6),(13326,1685,1),(13332,30,6),(13363,1685,1),(13383,1685,1),(13385,1685,1),(13388,1685,1),(13389,1685,1),(13396,1685,1),(13396,3815,10),(13401,1685,1),(13404,259,6),(13404,1685,1),(13410,1685,1),(13413,1685,1),(13415,1092,1),(13415,1685,1),(13416,626,1),(13416,1685,1),(13419,1685,1),(13425,1685,1),(13444,1685,1),(13447,1685,1),(13449,1685,1),(13449,11073,1),(13454,1685,1),(13463,458,1),(13463,1685,1),(13466,1685,1),(13467,1685,1),(13468,1685,1),(13472,1685,1),(13474,444,1),(13474,1685,1),(13477,1685,1),(13483,1685,1),(13484,1685,1),(13485,1685,1),(13490,1685,1),(13492,199,3),(13492,1685,1),(13493,1685,1),(13496,187,5),(13496,1685,1),(13499,30,1),(13499,1685,1),(13502,259,3),(13502,1685,1),(13505,1685,1),(13508,1685,1),(13511,1685,1),(13511,3837,3),(13514,1685,1),(13517,941,1),(13517,1685,1),(13520,1685,1),(13521,1685,1),(13524,1685,1),(13527,1685,1),(13528,1685,1),(13529,1685,1),(13530,1685,1),(13533,1685,1),(13542,184,3),(13542,1685,1),(13545,1685,1),(13546,1685,1),(13549,1685,1),(13556,1685,1),(13562,872,1),(13562,1685,1),(13565,1685,1),(13565,3804,1),(13568,876,1),(13568,1685,1),(13571,1685,1),(13575,1685,1),(13578,1685,1),(13584,1685,1),(13585,1685,1),(13585,3826,1),(13586,1685,1),(13589,30,3),(13589,1685,1),(13590,30,3),(13590,1685,1),(13592,702,1),(13592,1685,1),(13595,1685,1),(13595,6001,11),(13598,1685,1),(13601,1685,1),(13604,1685,1),(13607,1685,1),(13610,1685,1),(13613,1685,1),(13616,1685,1),(13617,1685,1),(13618,1685,1),(13619,1685,1),(13621,278,5),(13621,1685,1),(13624,1685,1),(13627,1685,1),(13628,1685,1),(13630,1685,1),(13633,1685,1),(13646,1668,1),(13646,1685,1),(13650,1685,1),(13653,1685,1),(13656,1685,1),(13663,1685,1),(13667,500,1),(13667,1685,1),(13670,1685,1),(13673,1158,1),(13674,7754,1),(13675,278,5),(13675,1685,1),(13678,1685,1),(13682,1685,1),(13683,1685,1),(13684,1685,1),(13685,1685,1),(13686,1685,1),(13687,1685,1),(13688,1685,1),(13689,751,1),(13689,1685,1),(13692,1685,1),(13693,1685,1),(13695,1685,1),(13698,784,1),(13698,1685,1),(13701,785,1),(13701,1685,1),(13704,787,1),(13704,1685,1),(13707,58,1),(13707,1685,1),(13710,1685,1),(13713,1685,1),(13718,1685,1),(13720,1685,1),(13723,58,1),(13723,1685,1),(13726,1685,1),(13727,25,3),(13727,1685,1),(13734,217,1),(13734,1685,1),(13753,534,1),(13753,1685,1),(13758,602,1),(13758,1685,1),(13763,1685,1),(13764,535,1),(13764,1685,1),(13767,1685,1),(13770,1685,1),(13771,1685,1),(13773,310,3),(13773,1685,1),(13774,310,3),(13774,1685,1),(13775,310,3),(13775,1685,1),(13779,1685,1),(13782,439,3),(13782,1685,1),(13785,1685,1),(13789,1685,1),(13790,1685,1),(13792,1685,1),(13795,1685,1),(13798,1685,1),(13804,1685,1),(13807,1685,1),(13810,1685,1),(13813,1685,1),(13816,1685,1),(13819,1685,1),(13820,1685,1),(13823,1685,1),(13826,1685,1),(13829,1685,1),(13832,1685,1),(13835,1685,1),(13838,1685,1),(13841,1685,1),(13845,1685,1),(13872,1685,1),(13873,961,1),(13873,1685,1),(13878,609,1),(13878,1685,1),(13881,387,1),(13881,1685,1),(13889,1012,1),(13889,1685,1),(13899,1685,1),(13905,1685,1),(13908,1685,1),(13911,1685,1),(13914,1685,1),(13917,606,1),(13917,1685,1),(13920,125,1),(13920,1685,1),(13933,142,20),(13943,142,20),(13953,142,20),(13963,142,20),(13973,142,20),(13983,142,20),(13993,142,20),(14003,1685,1),(14006,30,6),(14006,1685,1),(14009,1685,1),(14010,1685,1),(14011,1685,1),(14011,10394,1),(14016,1685,1),(14016,6001,17),(14018,1684,1),(14019,1685,1),(14026,1685,1),(14029,1685,1),(14032,1685,1),(14037,804,1),(14037,1685,1),(14040,300,1),(14040,1685,1),(14043,1685,1),(14046,87,1),(14046,1685,1),(14051,1685,1),(14052,1685,1),(14053,1685,1),(14054,1685,1),(14055,1685,1),(14056,1685,1),(14059,1685,1),(14062,821,1),(14062,1685,1),(14065,1685,1),(14065,3215,1),(14068,1685,1),(14068,3216,1),(14071,1685,1),(14076,1685,1),(14080,1685,1),(14081,1685,1),(14082,1685,1),(14085,741,1),(14085,1685,1),(14088,769,1),(14088,1685,1),(14091,701,1),(14091,1685,1),(14094,1685,1),(14097,1685,1),(14100,1685,1),(14101,1685,1),(14111,1685,1),(14112,1685,1),(14115,872,1),(14115,1685,1),(14129,1685,1),(14130,1685,1),(14132,1685,1),(14132,2234,1),(14135,1685,1),(14138,1685,1),(14139,1685,1),(14140,1685,1),(14141,1685,1),(14144,1685,1),(14144,3515,1),(14148,1685,1),(14151,1685,1),(14154,276,3),(14154,1685,1),(14157,1685,1),(14160,1685,1),(14160,7001,1),(14163,1685,1),(14163,7001,1),(14166,945,1),(14166,1685,1),(14169,1685,1),(14173,1685,1),(14176,1685,1),(14176,8261,1),(14179,359,1),(14179,1685,1),(14180,1685,1),(14181,1685,1),(14181,3837,12),(14186,809,5),(14186,1685,1),(14189,1685,1),(14192,1685,1),(14196,465,3),(14196,1685,1),(14199,499,1),(14199,1685,1),(14200,1685,1),(14203,1685,1),(14206,1685,1),(14207,1685,1),(14208,1685,1),(14208,7689,1),(14209,1685,1),(14210,1685,1),(14213,1065,1),(14213,1685,1),(14218,1685,1),(14221,1685,1),(14222,224,3),(14222,1685,1),(14223,47,1),(14223,1685,1),(14224,1685,1),(14225,177,1),(14225,1685,1),(14229,135,1),(14231,1685,1),(14232,1685,1),(14233,1685,1),(14234,1685,1),(14237,1685,1),(14238,1041,1),(14238,1685,1),(14241,386,1),(14241,1685,1),(14244,1685,1),(14249,1685,1),(14254,386,1),(14254,1685,1),(14256,1685,1),(14259,384,1),(14259,1685,1),(14265,939,1),(14265,1685,1),(14272,1685,1),(14273,1685,1),(14274,1685,1),(14275,1685,1),(14278,985,1),(14278,1685,1),(14280,57,1),(14280,1685,1),(14281,291,1),(14281,1685,1),(14282,1685,1),(14282,3812,1),(14283,1685,1),(14286,753,1),(14286,1685,1),(14289,1685,1),(14292,207,1),(14292,1685,1),(14295,1685,1),(14295,3816,1),(14304,1685,1),(14304,8341,1),(14307,1685,1),(14308,431,1),(14308,1685,1),(14311,430,1),(14311,1685,1),(14314,901,1),(14314,1685,1),(14318,1685,1),(14318,7703,1),(14321,1685,1),(14322,1685,1),(14323,1685,1),(14324,1685,1),(14328,1154,1),(14328,1685,1),(14331,515,1),(14331,1685,1),(14338,308,3),(14338,1685,1),(14341,748,1),(14341,1685,1),(14346,1685,1),(14349,215,6),(14352,175,3),(14352,1685,1),(14355,1685,1),(14358,1685,1),(14359,1685,1),(14360,1685,1),(14361,23,3),(14364,173,1),(14364,1685,1),(14372,1685,1),(14690,756,1),(14733,786,1),(15100,467,1),(15105,131,1),(15113,130,1),(15120,800,1),(15132,660,1),(15135,660,1),(15141,30,3),(15147,701,13),(15154,659,1),(15158,657,1),(15159,770,1),(15162,659,1),(15168,657,1),(15174,9400,1),(15179,7755,1),(15182,9403,1),(15204,390,1),(15207,323,1),(15210,1041,1),(15220,622,1),(15223,624,1),(15226,621,1),(15229,623,1),(15253,462,1),(15258,184,1),(15270,7003,1),(15280,778,1),(15295,2234,1),(15314,36,1),(15317,35,1),(15320,558,1),(15341,19,3),(15342,8500,1),(15344,38,1),(15348,9504,1),(15356,149,1),(15358,151,1),(15359,50,1),(15363,447,3),(15371,3729,1),(15377,638,1),(15389,935,1),(15396,23,3),(15397,494,3),(15403,8604,1),(15406,3817,1),(15414,241,1),(15421,245,3),(15424,247,1),(15424,982,6),(15466,3551,1),(15469,1120,1),(15472,521,1),(15478,578,1),(15481,398,24),(15482,261,1),(15485,495,9),(15486,534,3),(15526,3702,1),(15549,244,1),(15552,3710,1),(15571,351,1),(15579,826,1),(15591,2899,1),(15598,759,1),(15598,1150,1),(15598,1151,1),(15598,1152,1),(15605,639,1),(15606,160,4),(15622,23,3),(15632,789,1),(15639,749,1),(15640,822,2),(15746,804,1),(15778,87,1),(15833,2045,1),(15836,463,1),(15839,19,9),(15855,153,9),(15891,988,1),(15893,987,1),(15895,986,1),(15961,3701,1),(16062,263,1),(16071,2209,3),(16087,53,1),(16094,43,1),(16103,7703,1),(16105,684,1),(16106,684,1),(16107,684,1),(16117,309,6),(16124,3711,1),(16128,3711,1),(16131,73,1),(16137,10394,1),(16140,489,1),(16156,137,1),(16159,2045,1),(16163,260,1),(16163,7747,1),(16164,358,3),(16176,337,1),(16180,584,1),(16185,9202,1),(16185,9203,1),(16189,823,3),(16203,403,1),(16211,152,1),(16218,403,1),(16221,393,1),(16225,219,1),(16238,443,1),(16246,245,3),(16249,17,3),(16257,470,20),(16266,790,1),(16287,669,1),(16297,553,1),(16300,668,1),(16303,3506,1),(16306,777,1),(16336,1257,1),(16339,773,1),(16342,1257,1),(16371,60,1),(16380,2061,1),(16386,2064,1),(16392,2202,1),(16489,23,3),(16604,180,3),(16644,747,1),(16666,742,1),(16730,82,3),(16745,706,1),(17206,601,1),(17209,111,1),(17212,10367,1),(17218,744,1),(17235,3826,1),(17280,8205,1),(17281,359,1),(17288,41,1),(17289,1062,1),(17307,2047,1),(17317,1270,1),(17334,1041,1),(17336,148,1),(17339,760,1),(17342,148,1),(17350,170,3),(17361,405,1),(17361,426,1),(17364,935,4),(17375,1239,1),(17391,98,1),(17409,120,1),(17414,673,1),(17436,372,1),(17439,372,1),(17441,309,3),(17476,462,3),(17492,840,1),(17495,9702,1),(17515,3841,1),(17517,441,1),(17522,764,1),(17533,677,1),(17549,8700,1); +/*!40000 ALTER TABLE `aa_rank_prereqs` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2023-01-20 11:40:16 diff --git a/world/adventure.cpp b/world/adventure.cpp index 2e5a58fc1..bc72d8cf4 100644 --- a/world/adventure.cpp +++ b/world/adventure.cpp @@ -383,8 +383,8 @@ void Adventure::MoveCorpsesToGraveyard() if(!results.Success()) for(auto row = results.begin(); row != results.end(); ++row) { - dbid_list.push_back(atoi(row[0])); - charid_list.push_back(atoi(row[1])); + dbid_list.push_back(Strings::ToInt(row[0])); + charid_list.push_back(Strings::ToInt(row[1])); } for (auto &elem : dbid_list) { diff --git a/world/adventure_manager.cpp b/world/adventure_manager.cpp index 2f894134f..3d8442e53 100644 --- a/world/adventure_manager.cpp +++ b/world/adventure_manager.cpp @@ -679,41 +679,41 @@ bool AdventureManager::LoadAdventureTemplates() for (auto row = results.begin(); row != results.end(); ++row) { auto adventure_template = new AdventureTemplate; - adventure_template->id = atoi(row[0]); + adventure_template->id = Strings::ToInt(row[0]); strcpy(adventure_template->zone, row[1]); - adventure_template->zone_version = atoi(row[2]); - adventure_template->is_hard = atoi(row[3]); - adventure_template->min_level = atoi(row[4]); - adventure_template->max_level = atoi(row[5]); - adventure_template->type = atoi(row[6]); - adventure_template->type_data = atoi(row[7]); - adventure_template->type_count = atoi(row[8]); - adventure_template->assa_x = atof(row[9]); - adventure_template->assa_y = atof(row[10]); - adventure_template->assa_z = atof(row[11]); - adventure_template->assa_h = atof(row[12]); + adventure_template->zone_version = Strings::ToInt(row[2]); + adventure_template->is_hard = Strings::ToInt(row[3]); + adventure_template->min_level = Strings::ToInt(row[4]); + adventure_template->max_level = Strings::ToInt(row[5]); + adventure_template->type = Strings::ToInt(row[6]); + adventure_template->type_data = Strings::ToInt(row[7]); + adventure_template->type_count = Strings::ToInt(row[8]); + adventure_template->assa_x = Strings::ToFloat(row[9]); + adventure_template->assa_y = Strings::ToFloat(row[10]); + adventure_template->assa_z = Strings::ToFloat(row[11]); + adventure_template->assa_h = Strings::ToFloat(row[12]); strn0cpy(adventure_template->text, row[13], sizeof(adventure_template->text)); - adventure_template->duration = atoi(row[14]); - adventure_template->zone_in_time = atoi(row[15]); - adventure_template->win_points = atoi(row[16]); - adventure_template->lose_points = atoi(row[17]); - adventure_template->theme = atoi(row[18]); - adventure_template->zone_in_zone_id = atoi(row[19]); - adventure_template->zone_in_x = atof(row[20]); - adventure_template->zone_in_y = atof(row[21]); - adventure_template->zone_in_object_id = atoi(row[22]); - adventure_template->dest_x = atof(row[23]); - adventure_template->dest_y = atof(row[24]); - adventure_template->dest_z = atof(row[25]); - adventure_template->dest_h = atof(row[26]); - adventure_template->graveyard_zone_id = atoi(row[27]); - adventure_template->graveyard_x = atof(row[28]); - adventure_template->graveyard_y = atof(row[29]); - adventure_template->graveyard_z = atof(row[30]); - adventure_template->graveyard_radius = atof(row[31]); + adventure_template->duration = Strings::ToInt(row[14]); + adventure_template->zone_in_time = Strings::ToInt(row[15]); + adventure_template->win_points = Strings::ToInt(row[16]); + adventure_template->lose_points = Strings::ToInt(row[17]); + adventure_template->theme = Strings::ToInt(row[18]); + adventure_template->zone_in_zone_id = Strings::ToInt(row[19]); + adventure_template->zone_in_x = Strings::ToFloat(row[20]); + adventure_template->zone_in_y = Strings::ToFloat(row[21]); + adventure_template->zone_in_object_id = Strings::ToInt(row[22]); + adventure_template->dest_x = Strings::ToFloat(row[23]); + adventure_template->dest_y = Strings::ToFloat(row[24]); + adventure_template->dest_z = Strings::ToFloat(row[25]); + adventure_template->dest_h = Strings::ToFloat(row[26]); + adventure_template->graveyard_zone_id = Strings::ToInt(row[27]); + adventure_template->graveyard_x = Strings::ToFloat(row[28]); + adventure_template->graveyard_y = Strings::ToFloat(row[29]); + adventure_template->graveyard_z = Strings::ToFloat(row[30]); + adventure_template->graveyard_radius = Strings::ToFloat(row[31]); adventure_templates[adventure_template->id] = adventure_template; } @@ -732,8 +732,8 @@ bool AdventureManager::LoadAdventureEntries() for (auto row = results.begin(); row != results.end(); ++row) { - int id = atoi(row[0]); - int template_id = atoi(row[1]); + int id = Strings::ToInt(row[0]); + int template_id = Strings::ToInt(row[1]); AdventureTemplate* tid = nullptr; auto t_iter = adventure_templates.find(template_id); @@ -1108,26 +1108,26 @@ void AdventureManager::LoadLeaderboardInfo() LeaderboardInfo lbi; lbi.name = row[0]; - lbi.wins = atoi(row[3]); - lbi.guk_wins = atoi(row[3]); - lbi.wins += atoi(row[4]); - lbi.mir_wins = atoi(row[4]); - lbi.wins += atoi(row[5]); - lbi.mmc_wins = atoi(row[5]); - lbi.wins += atoi(row[6]); - lbi.ruj_wins = atoi(row[6]); - lbi.wins += atoi(row[7]); - lbi.tak_wins = atoi(row[7]); - lbi.losses = atoi(row[8]); - lbi.guk_losses = atoi(row[8]); - lbi.losses += atoi(row[9]); - lbi.mir_losses = atoi(row[9]); - lbi.losses += atoi(row[10]); - lbi.mmc_losses = atoi(row[10]); - lbi.losses += atoi(row[11]); - lbi.ruj_losses = atoi(row[11]); - lbi.losses += atoi(row[12]); - lbi.tak_losses = atoi(row[12]); + lbi.wins = Strings::ToInt(row[3]); + lbi.guk_wins = Strings::ToInt(row[3]); + lbi.wins += Strings::ToInt(row[4]); + lbi.mir_wins = Strings::ToInt(row[4]); + lbi.wins += Strings::ToInt(row[5]); + lbi.mmc_wins = Strings::ToInt(row[5]); + lbi.wins += Strings::ToInt(row[6]); + lbi.ruj_wins = Strings::ToInt(row[6]); + lbi.wins += Strings::ToInt(row[7]); + lbi.tak_wins = Strings::ToInt(row[7]); + lbi.losses = Strings::ToInt(row[8]); + lbi.guk_losses = Strings::ToInt(row[8]); + lbi.losses += Strings::ToInt(row[9]); + lbi.mir_losses = Strings::ToInt(row[9]); + lbi.losses += Strings::ToInt(row[10]); + lbi.mmc_losses = Strings::ToInt(row[10]); + lbi.losses += Strings::ToInt(row[11]); + lbi.ruj_losses = Strings::ToInt(row[11]); + lbi.losses += Strings::ToInt(row[12]); + lbi.tak_losses = Strings::ToInt(row[12]); leaderboard_info_wins.push_back(lbi); leaderboard_info_percentage.push_back(lbi); diff --git a/world/cli/database_concurrency.cpp b/world/cli/database_concurrency.cpp new file mode 100644 index 000000000..bb20f4eba --- /dev/null +++ b/world/cli/database_concurrency.cpp @@ -0,0 +1,73 @@ +#include +#include "../../common/repositories/zone_repository.h" +#include "../../common/eqemu_config.h" +#include + +Database db; +Database db2; + +volatile sig_atomic_t stop; +void inthand(int signum) { + stop = 1; +} + +[[noreturn]] void DatabaseTest() +{ + while (true) { + LogInfo("DatabaseTest Query"); + db.QueryDatabase("SELECT 1"); + } +} + +[[noreturn]] void DatabaseTestSecondConnection() +{ + while (true) { + LogInfo("DatabaseTest Query"); + db2.QueryDatabase("SELECT 1"); + } +} + + +void WorldserverCLI::TestDatabaseConcurrency(int argc, char **argv, argh::parser &cmd, std::string &description) +{ + description = "Test command to test database concurrency"; + + if (cmd[{"-h", "--help"}]) { + return; + } + + signal(SIGINT, inthand); + + LogInfo("Database test"); + + auto mutex = new Mutex; + + auto c = EQEmuConfig::get(); + LogInfo("Connecting to MySQL"); + if (!db.Connect( + c->DatabaseHost.c_str(), + c->DatabaseUsername.c_str(), + c->DatabasePassword.c_str(), + c->DatabaseDB.c_str(), + c->DatabasePort + )) { + LogError("Cannot continue without a database connection"); + return; + } + + db.SetMutex(mutex); + + db2.SetMySQL(db); + + db2.SetMutex(mutex); + + std::thread(DatabaseTest).detach(); + std::thread(DatabaseTest).detach(); + std::thread(DatabaseTestSecondConnection).detach(); + + while (!stop) { + + } + + safe_delete(mutex); +} diff --git a/world/cli/database_set_account_status.cpp b/world/cli/database_set_account_status.cpp index 52e777bf4..39dbeeb28 100644 --- a/world/cli/database_set_account_status.cpp +++ b/world/cli/database_set_account_status.cpp @@ -19,6 +19,6 @@ void WorldserverCLI::DatabaseSetAccountStatus(int argc, char **argv, argh::parse database.SetAccountStatus( cmd(2).str(), - std::stoi(cmd(3).str()) + Strings::ToInt(cmd(3).str()) ); } diff --git a/world/cli/database_version.cpp b/world/cli/database_version.cpp index 639e7e1de..e3130b9dc 100644 --- a/world/cli/database_version.cpp +++ b/world/cli/database_version.cpp @@ -1,5 +1,6 @@ #include "../../common/version.h" #include "../../common/json/json.h" +#include "../../common/rulesys.h" void WorldserverCLI::DatabaseVersion(int argc, char **argv, argh::parser &cmd, std::string &description) { @@ -9,13 +10,13 @@ void WorldserverCLI::DatabaseVersion(int argc, char **argv, argh::parser &cmd, s return; } - Json::Value database_version; + Json::Value v; - database_version["database_version"] = CURRENT_BINARY_DATABASE_VERSION; - database_version["bots_database_version"] = CURRENT_BINARY_BOTS_DATABASE_VERSION; + v["database_version"] = CURRENT_BINARY_DATABASE_VERSION; + v["bots_database_version"] = RuleB(Bots, Enabled) ? CURRENT_BINARY_BOTS_DATABASE_VERSION : 0; std::stringstream payload; - payload << database_version; + payload << v; std::cout << payload.str() << std::endl; } diff --git a/world/cli/test.cpp b/world/cli/test.cpp index 39a923115..738741723 100644 --- a/world/cli/test.cpp +++ b/world/cli/test.cpp @@ -1,4 +1,6 @@ -#include "../../common/zone_store.h" +#include +#include +#include "../../common/events/player_events.h" void WorldserverCLI::TestCommand(int argc, char **argv, argh::parser &cmd, std::string &description) { @@ -8,14 +10,5 @@ void WorldserverCLI::TestCommand(int argc, char **argv, argh::parser &cmd, std:: return; } - zone_store.LoadZones(database); - - const char* zonename = ZoneName(0); - if (zonename == 0) { - LogInfo("Zone name is 0"); - } - if (zonename == nullptr) { - LogInfo("Zone name is nullptr"); - } - + } diff --git a/world/cli/test_string_benchmark.cpp b/world/cli/test_string_benchmark.cpp new file mode 100644 index 000000000..32d5e9020 --- /dev/null +++ b/world/cli/test_string_benchmark.cpp @@ -0,0 +1,114 @@ +#include +#include +#include "../../common/events/player_events.h" +#include "../../common/timer.h" + +void WorldserverCLI::TestStringBenchmarkCommand(int argc, char **argv, argh::parser &cmd, std::string &description) +{ + description = "Test command"; + + if (cmd[{"-h", "--help"}]) { + return; + } + + enum Type { + StringsToInt = 0, + StringsToBigInt, + StringsToUnsignedInt, + StringsToUnsignedBigInt, + StringsToFloat, + StringsIsNumber, + StringsIsFloat, + StdStoi, + StdAtoi, + StdStoll, + StdAtoll, + StdStoul, + StdStoull, + StdStof, + }; + + struct Benchmark { + std::string name; + Type type; + }; + + std::vector benches = { + Benchmark{.name = "Strings::ToInt", .type = StringsToInt}, + Benchmark{.name = "std::stoi", .type = StdStoi}, + Benchmark{.name = "std::atoi", .type = StdAtoi}, + Benchmark{.name = "Strings::ToBigInt", .type = StringsToBigInt}, + Benchmark{.name = "std::stoll", .type = StdStoll}, + Benchmark{.name = "std::atoll", .type = StdAtoll}, + Benchmark{.name = "Strings::ToUnsignedInt", .type = StringsToUnsignedInt}, + Benchmark{.name = "std::stoul", .type = StdStoul}, + Benchmark{.name = "Strings::ToUnsignedBigInt", .type = StringsToUnsignedBigInt}, + Benchmark{.name = "std::stoull", .type = StdStoull}, + Benchmark{.name = "Strings::ToFloat", .type = StringsToFloat}, + Benchmark{.name = "std::stof", .type = StdStof}, + Benchmark{.name = "Strings::IsNumber", .type = StringsIsNumber}, + Benchmark{.name = "Strings::IsFloat", .type = StringsIsFloat}, + }; + + BenchTimer benchmark; + + for (auto &b: benches) { + int iterations = 10000000; + std::string number = "1111753784"; + std::string float_number = "1111753784.2345623456345"; + int64 convert = 0; + uint64_t uconvert = 0; + float fconvert = 0; + bool check = false; + + for (int i = 0; i < iterations; i++) { + switch (b.type) { + case StringsToInt: + convert = Strings::ToInt(number, 0); + break; + case StdStoi: + convert = std::stoi(number); + break; + case StdAtoi: + convert = std::atoi(number.c_str()); + break; + case StringsToBigInt: + convert = Strings::ToBigInt(number, 0); + break; + case StdStoll: + convert = std::stoll(number); + break; + case StdAtoll: + convert = std::atoll(number.c_str()); + break; + case StringsToUnsignedInt: + uconvert = Strings::ToUnsignedInt(number, 0); + break; + case StringsToUnsignedBigInt: + uconvert = Strings::ToUnsignedBigInt(number, 0); + break; + case StringsToFloat: + fconvert = Strings::ToFloat(number, 0); + break; + case StringsIsNumber: + check = Strings::IsNumber(number); + break; + case StringsIsFloat: + check = Strings::IsFloat(float_number); + break; + case StdStoul: + uconvert = std::stoul(number); + break; + case StdStoull: + uconvert = std::stoull(number); + break; + case StdStof: + fconvert = std::stof(number); + break; + } + } + + LogInfo("{:<30} | [{}] time [{}]", b.name, Strings::Commify(iterations), benchmark.elapsed()); + benchmark.reset(); + } +} diff --git a/world/client.cpp b/world/client.cpp index 672a68012..5d60d727b 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -49,6 +49,8 @@ #include "sof_char_create_data.h" #include "../common/zone_store.h" #include "../common/repositories/account_repository.h" +#include "../common/repositories/player_event_logs_repository.h" +#include "../common/events/player_event_logs.h" #include #include @@ -451,7 +453,7 @@ bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app) is_player_zoning = (login_info->zoning == 1); - uint32 id = std::stoi(name); + uint32 id = Strings::ToInt(name); if (id == 0) { LogWarning("Receiving Login Info Packet from Client | account_id is 0 - disconnecting"); return false; @@ -806,7 +808,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { if (!strcasecmp(row[1], char_name)) { if (RuleB(World, EnableReturnHomeButton)) { int now = time(nullptr); - if ((now - atoi(row[3])) >= RuleI(World, MinOfflineTimeToReturnHome)) { + if ((now - Strings::ToInt(row[3])) >= RuleI(World, MinOfflineTimeToReturnHome)) { home_enabled = true; break; } @@ -818,7 +820,8 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { zone_id = database.MoveCharacterToBind(charid, 4); } else { LogInfo("[{}] is trying to go home before they're able.", char_name); - database.SetHackerFlag(GetAccountName(), char_name, "MQGoHome: player tried to go home before they were able."); + RecordPossibleHack("[MQGoHome] player tried to go home before they were able"); + eqs->Close(); return true; } @@ -831,7 +834,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { if (!strcasecmp(row[1], char_name)) { if ( RuleB(World, EnableTutorialButton) && - std::stoi(row[2]) <= RuleI(World, MaxLevelForTutorial) + Strings::ToInt(row[2]) <= RuleI(World, MaxLevelForTutorial) ) { tutorial_enabled = true; break; @@ -844,7 +847,8 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { database.MoveCharacterToZone(charid, zone_id); } else { LogInfo("[{}] is trying to go to the Tutorial but they are not allowed.", char_name); - database.SetHackerFlag(GetAccountName(), char_name, "MQTutorial: player tried to enter the tutorial without having tutorial enabled for this character."); + RecordPossibleHack("[MQTutorial] player tried to enter the tutorial without having tutorial enabled for this character"); + eqs->Close(); return true; } @@ -1010,10 +1014,11 @@ bool Client::HandlePacket(const EQApplicationPacket *app) { EmuOpcode opcode = app->GetOpcode(); + auto o = eqs->GetOpcodeManager(); LogPacketClientServer( "[{}] [{:#06x}] Size [{}] {}", OpcodeManager::EmuToName(app->GetOpcode()), - eqs->GetOpcodeManager()->EmuToEQ(app->GetOpcode()), + o->EmuToEQ(app->GetOpcode()) == 0 ? app->GetProtocolOpcode() : o->EmuToEQ(app->GetOpcode()), app->Size(), (LogSys.IsLogEnabled(Logs::Detail, Logs::PacketClientServer) ? DumpPacketToString(app) : "") ); @@ -1253,7 +1258,7 @@ bool Client::ChecksumVerificationCRCEQGame(uint64 checksum) std::string checksumvar; uint64_t checksumint; if (database.GetVariable("crc_eqgame", checksumvar)) { - checksumint = atoll(checksumvar.c_str()); + checksumint = Strings::ToBigInt(checksumvar.c_str()); } else { LogChecksumVerification("variable not set in variables table."); @@ -1276,7 +1281,7 @@ bool Client::ChecksumVerificationCRCSkillCaps(uint64 checksum) std::string checksumvar; uint64_t checksumint; if (database.GetVariable("crc_skillcaps", checksumvar)) { - checksumint = atoll(checksumvar.c_str()); + checksumint = Strings::ToBigInt(checksumvar.c_str()); } else { LogChecksumVerification("[checksum_crc2_skillcaps] variable not set in variables table."); @@ -1299,7 +1304,7 @@ bool Client::ChecksumVerificationCRCBaseData(uint64 checksum) std::string checksumvar; uint64_t checksumint; if (database.GetVariable("crc_basedata", checksumvar)) { - checksumint = atoll(checksumvar.c_str()); + checksumint = Strings::ToBigInt(checksumvar.c_str()); } else { LogChecksumVerification("variable not set in variables table."); @@ -1778,12 +1783,39 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) pp.binds[0].heading = pp.heading; } - LogInfo("Current location [{}] [{}] [{}] [{}] [{}] [{}]", - ZoneName(pp.zone_id), pp.zone_id, pp.x, pp.y, pp.z, pp.heading); - LogInfo("Bind location [{}] [{}] [{}] [{}] [{}]", - ZoneName(pp.binds[0].zone_id), pp.binds[0].zone_id, pp.binds[0].x, pp.binds[0].y, pp.binds[0].z); - LogInfo("Home location [{}] [{}] [{}] [{}] [{}]", - ZoneName(pp.binds[4].zone_id), pp.binds[4].zone_id, pp.binds[4].x, pp.binds[4].y, pp.binds[4].z); + if (GetZone(pp.zone_id)) { + LogInfo( + "Current location [{}] [{}] [{:.2f}] [{:.2f}] [{:.2f}] [{:.2f}]", + ZoneName(pp.zone_id), + pp.zone_id, + pp.x, + pp.y, + pp.z, + pp.heading + ); + } + + if (GetZone(pp.binds[0].zone_id)) { + LogInfo( + "Bind location [{}] [{}] [{:.2f}] [{:.2f}] [{:.2f}]", + ZoneName(pp.binds[0].zone_id), + pp.binds[0].zone_id, + pp.binds[0].x, + pp.binds[0].y, + pp.binds[0].z + ); + } + + if (GetZone(pp.binds[4].zone_id)) { + LogInfo( + "Home location [{}] [{}] [{:.2f}] [{:.2f}] [{:.2f}]", + ZoneName(pp.binds[4].zone_id), + pp.binds[4].zone_id, + pp.binds[4].x, + pp.binds[4].y, + pp.binds[4].z + ); + } /* Starting Items inventory */ content_db.SetStartingItems(&pp, &inv, pp.race, pp.class_, pp.deity, pp.zone_id, pp.name, GetAdmin()); @@ -2332,3 +2364,24 @@ bool Client::StoreCharacter( return true; } + +void Client::RecordPossibleHack(const std::string& message) +{ + if (player_event_logs.IsEventEnabled(PlayerEvent::POSSIBLE_HACK)) { + auto event = PlayerEvent::PossibleHackEvent{.message = message}; + std::stringstream ss; + { + cereal::JSONOutputArchiveSingleLine ar(ss); + event.serialize(ar); + } + + auto e = PlayerEventLogsRepository::NewEntity(); + e.character_id = charid; + e.account_id = GetCLE() ? GetAccountID() : 0; + e.event_type_id = PlayerEvent::POSSIBLE_HACK; + e.event_type_name = PlayerEvent::EventName[PlayerEvent::POSSIBLE_HACK]; + e.event_data = ss.str(); + e.created_at = std::time(nullptr); + PlayerEventLogsRepository::InsertOne(database, e); + } +} diff --git a/world/client.h b/world/client.h index 93aacb31d..975350a01 100644 --- a/world/client.h +++ b/world/client.h @@ -28,8 +28,6 @@ #include "../common/eq_packet_structs.h" #include "cliententry.h" -#define CLIENT_TIMEOUT 30000 - class EQApplicationPacket; class EQStreamInterface; @@ -101,9 +99,7 @@ private: ClientListEntry* cle; Timer connect; - bool firstlogin; bool seen_character_select; - bool realfirstlogin; bool HandlePacket(const EQApplicationPacket *app); bool HandleNameApprovalPacket(const EQApplicationPacket *app); @@ -121,6 +117,7 @@ private: EQStreamInterface* eqs; bool CanTradeFVNoDropItem(); + void RecordPossibleHack(const std::string& message); }; bool CheckCharCreateInfoSoF(CharCreate_Struct *cc); diff --git a/world/cliententry.cpp b/world/cliententry.cpp index 9609a2df7..f4270c4b5 100644 --- a/world/cliententry.cpp +++ b/world/cliententry.cpp @@ -120,8 +120,9 @@ ClientListEntry::~ClientListEntry() Camp(); // updates zoneserver's numplayers client_list.RemoveCLEReferances(this); } - for (auto &elem : tell_queue) - safe_delete_array(elem); + for (auto& elem: tell_queue) { + safe_delete_array(elem) + }; tell_queue.clear(); } @@ -131,13 +132,6 @@ void ClientListEntry::SetChar(uint32 iCharID, const char *iCharName) strn0cpy(pname, iCharName, sizeof(pname)); } -void ClientListEntry::SetOnline(ZoneServer *iZS, CLE_Status iOnline) -{ - if (iZS == Server()) { - SetOnline(iOnline); - } -} - void ClientListEntry::SetOnline(CLE_Status iOnline) { LogClientLogin( @@ -289,8 +283,9 @@ void ClientListEntry::ClearVars(bool iAll) pLFG = 0; gm = 0; pClientVersion = 0; - for (auto &elem : tell_queue) - safe_delete_array(elem); + for (auto& elem: tell_queue) { + safe_delete_array(elem) + }; tell_queue.clear(); } @@ -365,7 +360,7 @@ bool ClientListEntry::CheckAuth(uint32 loginserver_account_id, const char *key_p } std::string lsworldadmin; if (database.GetVariable("honorlsworldadmin", lsworldadmin)) { - if (atoi(lsworldadmin.c_str()) == 1 && pworldadmin != 0 && (padmin < pworldadmin || padmin == AccountStatus::Player)) { + if (Strings::ToInt(lsworldadmin.c_str()) == 1 && pworldadmin != 0 && (padmin < pworldadmin || padmin == AccountStatus::Player)) { padmin = pworldadmin; } } diff --git a/world/cliententry.h b/world/cliententry.h index f3ce31dea..38bbaad9b 100644 --- a/world/cliententry.h +++ b/world/cliententry.h @@ -68,9 +68,6 @@ public: void LSUpdate(ZoneServer* zoneserver); void LSZoneChange(ZoneToZone_Struct* ztz); bool CheckAuth(uint32 loginserver_account_id, const char* key_password); - bool CheckAuth(const char* iName, MD5& iMD5Password); - bool CheckAuth(uint32 id, const char* key, uint32 ip); - void SetOnline(ZoneServer* iZS, CLE_Status iOnline); void SetOnline(CLE_Status iOnline = CLE_Status::Online); void SetChar(uint32 iCharID, const char* iCharName); inline CLE_Status Online() { return pOnline; } @@ -149,7 +146,6 @@ private: // Account stuff uint32 paccountid; char paccountname[32]{}; - MD5 pMD5Pass; int16 padmin{}; // Character info diff --git a/world/clientlist.cpp b/world/clientlist.cpp index 8dcf6dd48..225069e9b 100644 --- a/world/clientlist.cpp +++ b/world/clientlist.cpp @@ -85,19 +85,6 @@ void ClientList::CLERemoveZSRef(ZoneServer* iZS) { } } -ClientListEntry* ClientList::GetCLE(uint32 iID) { - LinkedListIterator iterator(clientlist); - - iterator.Reset(); - while(iterator.MoreElements()) { - if (iterator.GetData()->GetID() == iID) { - return iterator.GetData(); - } - iterator.Advance(); - } - return 0; -} - //Check current CLE Entry IPs against incoming connection void ClientList::GetCLEIP(uint32 in_ip) { @@ -207,31 +194,6 @@ void ClientList::GetCLEIP(uint32 in_ip) { } } -uint32 ClientList::GetCLEIPCount(uint32 in_ip) { - ClientListEntry* cle = nullptr; - LinkedListIterator iterator(clientlist); - - int count = 0; - iterator.Reset(); - - while (iterator.MoreElements()) { - cle = iterator.GetData(); - if ( - cle->GetIP() == in_ip && - ( - cle->Admin() < RuleI(World, ExemptMaxClientsStatus) || - RuleI(World, ExemptMaxClientsStatus) < 0 - ) && - cle->Online() >= CLE_Status::Online - ) { // If the IP matches, and the connection admin status is below the exempt status, or exempt status is less than 0 (no-one is exempt) - count++; // Increment the occurences of this IP address - } - iterator.Advance(); - } - - return count; -} - void ClientList::DisconnectByIP(uint32 in_ip) { ClientListEntry* cle = nullptr; LinkedListIterator iterator(clientlist); @@ -296,19 +258,6 @@ ClientListEntry* ClientList::FindCLEByCharacterID(uint32 iCharID) { return nullptr; } -ClientListEntry* ClientList::FindCLEByLSID(uint32 iLSID) { - LinkedListIterator iterator(clientlist); - - iterator.Reset(); - while (iterator.MoreElements()) { - if (iterator.GetData()->LSID() == iLSID) { - return iterator.GetData(); - } - iterator.Advance(); - } - return nullptr; -} - void ClientList::SendCLEList(const int16& admin, const char* to, WorldTCPConnection* connection, const char* iName) { LinkedListIterator iterator(clientlist); int x = 0, y = 0; @@ -1224,20 +1173,6 @@ Client* ClientList::FindByAccountID(uint32 account_id) { return 0; } -Client* ClientList::FindByName(char* charname) { - LinkedListIterator iterator(list); - - iterator.Reset(); - while(iterator.MoreElements()) { - if (iterator.GetData()->GetCharName() == charname) { - Client* tmp = iterator.GetData(); - return tmp; - } - iterator.Advance(); - } - return 0; -} - Client* ClientList::Get(uint32 ip, uint16 port) { LinkedListIterator iterator(list); @@ -1315,29 +1250,6 @@ bool ClientList::SendPacket(const char* to, ServerPacket* pack) { return false; } -void ClientList::SendGuildPacket(uint32 guild_id, ServerPacket* pack) { - std::set zone_ids; - - LinkedListIterator iterator(clientlist); - - iterator.Reset(); - while(iterator.MoreElements()) { - if (iterator.GetData()->GuildID() == guild_id) { - zone_ids.insert(iterator.GetData()->zone()); - } - iterator.Advance(); - } - - //now we know all the zones, send it to each one... this is kinda a shitty way to do this - //since its basically O(n^2) - std::set::iterator cur, end; - cur = zone_ids.begin(); - end = zone_ids.end(); - for(; cur != end; cur++) { - zoneserver_list.SendPacket(*cur, pack); - } -} - void ClientList::UpdateClientGuild(uint32 char_id, uint32 guild_id) { LinkedListIterator iterator(clientlist); @@ -1351,21 +1263,6 @@ void ClientList::UpdateClientGuild(uint32 char_id, uint32 guild_id) { } } -void ClientList::RemoveCLEByLSID(uint32 iLSID) -{ - LinkedListIterator iterator(clientlist); - - iterator.Reset(); - while (iterator.MoreElements()) { - if (iterator.GetData()->LSAccountID() == iLSID) { - iterator.RemoveCurrent(); - } - else { - iterator.Advance(); - } - } -} - bool ClientList::IsAccountInGame(uint32 iLSID) { LinkedListIterator iterator(clientlist); iterator.Reset(); diff --git a/world/clientlist.h b/world/clientlist.h index 2ab6be60d..50ea5ab69 100644 --- a/world/clientlist.h +++ b/world/clientlist.h @@ -30,7 +30,6 @@ public: void Add(Client* client); Client* Get(uint32 ip, uint16 port); Client* FindByAccountID(uint32 account_id); - Client* FindByName(char* charname); void ZoneBootup(ZoneServer* zs); void RemoveCLEReferances(ClientListEntry* cle); @@ -47,7 +46,6 @@ public: void SendCLEList(const int16& admin, const char* to, WorldTCPConnection* connection, const char* iName = 0); bool SendPacket(const char* to, ServerPacket* pack); - void SendGuildPacket(uint32 guild_id, ServerPacket* pack); void ClientUpdate(ZoneServer* zoneserver, ServerClientList_Struct* scl); void CLERemoveZSRef(ZoneServer* iZS); @@ -55,16 +53,12 @@ public: ClientListEntry* FindCharacter(const char* name); ClientListEntry* FindCLEByAccountID(uint32 iAccID); ClientListEntry* FindCLEByCharacterID(uint32 iCharID); - ClientListEntry* FindCLEByLSID(uint32 iLSID); - ClientListEntry* GetCLE(uint32 iID); void GetCLEIP(uint32 in_ip); - uint32 GetCLEIPCount(uint32 iLSAccountID); void DisconnectByIP(uint32 in_ip); void CLCheckStale(); void CLEKeepAlive(uint32 numupdates, uint32* wid); void CLEAdd(uint32 iLSID, const char* iLoginServerName, const char* iLoginName, const char* iLoginKey, int16 iWorldAdmin = AccountStatus::Player, uint32 ip = 0, uint8 local=0); void UpdateClientGuild(uint32 char_id, uint32 guild_id); - void RemoveCLEByLSID(uint32 iLSID); bool IsAccountInGame(uint32 iLSID); int GetClientCount(); diff --git a/world/console.cpp b/world/console.cpp index d0d71afdb..a843dee67 100644 --- a/world/console.cpp +++ b/world/console.cpp @@ -166,14 +166,14 @@ void ConsoleWho( } else if (Strings::IsNumber(arg)) { if (whom.lvllow == 0xFFFF) { - whom.lvllow = atoi(arg.c_str()); + whom.lvllow = Strings::ToInt(arg.c_str()); whom.lvlhigh = whom.lvllow; } - else if (atoi(arg.c_str()) > int(whom.lvllow)) { - whom.lvlhigh = atoi(arg.c_str()); + else if (Strings::ToInt(arg.c_str()) > int(whom.lvllow)) { + whom.lvlhigh = Strings::ToInt(arg.c_str()); } else { - whom.lvllow = atoi(arg.c_str()); + whom.lvllow = Strings::ToInt(arg.c_str()); } } else { @@ -200,11 +200,11 @@ void ConsoleUptime( return; } - if (Strings::IsNumber(args[0]) && atoi(args[0].c_str()) > 0) { + if (Strings::IsNumber(args[0]) && Strings::ToInt(args[0].c_str()) > 0) { auto pack = new ServerPacket(ServerOP_Uptime, sizeof(ServerUptime_Struct)); ServerUptime_Struct *sus = (ServerUptime_Struct *) pack->pBuffer; snprintf(sus->adminname, sizeof(sus->adminname), "*%s", connection->UserName().c_str()); - sus->zoneserverid = atoi(args[0].c_str()); + sus->zoneserverid = Strings::ToInt(args[0].c_str()); ZoneServer *zs = zoneserver_list.FindByID(sus->zoneserverid); if (zs) { zs->SendPacket(pack); @@ -284,7 +284,7 @@ void ConsoleEmote( 0, 0, AccountStatus::Player, - atoi(args[1].c_str()), + Strings::ToInt(args[1].c_str()), Strings::Join(join_args, " ").c_str() ); } @@ -295,7 +295,7 @@ void ConsoleEmote( 0, 0, AccountStatus::Player, - atoi(args[1].c_str()), + Strings::ToInt(args[1].c_str()), Strings::Join(join_args, " ").c_str() ); } @@ -304,7 +304,7 @@ void ConsoleEmote( args[0].c_str(), 0, AccountStatus::Player, - atoi(args[1].c_str()), + Strings::ToInt(args[1].c_str()), Strings::Join(join_args, " ").c_str() ); } @@ -422,7 +422,7 @@ void ConsoleGuildSay( } auto from = args[0]; - auto guild_id = Strings::IsNumber(args[1]) ? std::stoul(args[1]) : 0; + auto guild_id = Strings::IsNumber(args[1]) ? Strings::ToUnsignedInt(args[1]) : 0; if (!guild_id) { return; } @@ -585,7 +585,7 @@ void ConsoleZoneShutdown( pack->opcode = ServerOP_ZoneShutdown; strcpy(s->adminname, tmpname); if (Strings::IsNumber(args[0])) { - s->ZoneServerID = atoi(args[0].c_str()); + s->ZoneServerID = Strings::ToInt(args[0].c_str()); } else { s->zoneid = ZoneID(args[0].c_str()); @@ -639,12 +639,12 @@ void ConsoleZoneBootup( if (args.size() > 2) { zoneserver_list.SOPZoneBootup( tmpname, - atoi(args[0].c_str()), + Strings::ToInt(args[0].c_str()), args[1].c_str(), (bool) (strcasecmp(args[1].c_str(), "static") == 0)); } else { - zoneserver_list.SOPZoneBootup(tmpname, atoi(args[0].c_str()), args[1].c_str(), false); + zoneserver_list.SOPZoneBootup(tmpname, Strings::ToInt(args[0].c_str()), args[1].c_str(), false); } } } @@ -751,10 +751,10 @@ void ConsoleFlag( connection->SendLine("Usage: flag [status] [accountname]"); } else { - if (atoi(args[0].c_str()) > connection->Admin()) { + if (Strings::ToInt(args[0].c_str()) > connection->Admin()) { connection->SendLine("You cannot set people's status to higher than your own"); } - else if (!database.SetAccountStatus(args[1].c_str(), atoi(args[0].c_str()))) { + else if (!database.SetAccountStatus(args[1].c_str(), Strings::ToInt(args[0].c_str()))) { connection->SendLine("Unable to flag account!"); } else { @@ -821,8 +821,8 @@ void ConsoleWorldShutdown( { if (args.size() == 2) { int32 time, interval; - if (Strings::IsNumber(args[0]) && Strings::IsNumber(args[1]) && ((time = atoi(args[0].c_str())) > 0) && - ((interval = atoi(args[1].c_str())) > 0)) { + if (Strings::IsNumber(args[0]) && Strings::IsNumber(args[1]) && ((time = Strings::ToInt(args[0].c_str())) > 0) && + ((interval = Strings::ToInt(args[1].c_str())) > 0)) { zoneserver_list.WorldShutDown(time, interval); } else { @@ -886,7 +886,7 @@ void ConsoleSignalCharByName( return; } - connection->SendLine(StringFormat("Signal Sent to %s with ID %i", (char *) args[0].c_str(), atoi(args[1].c_str()))); + connection->SendLine(StringFormat("Signal Sent to %s with ID %i", (char *) args[0].c_str(), Strings::ToInt(args[1].c_str()))); uint32 message_len = strlen((char *) args[0].c_str()) + 1; auto pack = new ServerPacket(ServerOP_CZSignal, sizeof(CZSignal_Struct) + message_len); CZSignal_Struct* CZS = (CZSignal_Struct*) pack->pBuffer; @@ -894,7 +894,7 @@ void ConsoleSignalCharByName( int update_identifier = 0; CZS->update_type = update_type; CZS->update_identifier = update_identifier; - CZS->signal_id = atoi(args[1].c_str()); + CZS->signal_id = Strings::ToInt(args[1].c_str()); strn0cpy(CZS->client_name, (char *) args[0].c_str(), 64); zoneserver_list.SendPacket(pack); safe_delete(pack); diff --git a/world/console.old.cpp b/world/console.old.cpp deleted file mode 100644 index 59c782512..000000000 --- a/world/console.old.cpp +++ /dev/null @@ -1,902 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#include "../common/global_define.h" -#include -#include -#include -#include -#include - - -#include "../common/version.h" -#include "console.h" -#include "zoneserver.h" -#include "worlddb.h" -#include "../common/packet_dump.h" -#include "../common/seperator.h" -#include "../common/eq_packet_structs.h" -#include "../common/eq_packet.h" -#include "login_server.h" -#include "login_server_list.h" -#include "../common/serverinfo.h" -#include "../common/md5.h" -#include "../common/opcodemgr.h" -#include "../common/rulesys.h" -#include "../common/ruletypes.h" -#include "../common/strings.h" -#include "world_config.h" -#include "zoneserver.h" -#include "zonelist.h" -#include "clientlist.h" -#include "launcher_list.h" -#include "ucs.h" -#include "queryserv.h" - -#ifdef _WINDOWS - #define snprintf _snprintf - #define strncasecmp _strnicmp - #define strcasecmp _stricmp -#endif - -extern ZSList zoneserver_list; -extern uint32 numzones; -extern LoginServerList loginserverlist; -extern ClientList client_list; -extern LauncherList launcher_list; -extern UCSConnection UCSLink; -extern QueryServConnection QSLink; -extern volatile bool RunLoops; - -ConsoleList console_list; -void CatchSignal(int sig_num); - -Console::Console(EmuTCPConnection* itcpc) -: WorldTCPConnection(), - timeout_timer(RuleI(Console, SessionTimeOut)), - prompt_timer(1) -{ - tcpc = itcpc; - tcpc->SetEcho(true); - state = 0; - paccountid = 0; - memset(paccountname, 0, sizeof(paccountname)); - admin = 0; - pAcceptMessages = false; -} - -Console::~Console() { - if (tcpc) - tcpc->Free(); -} - -void Console::Die() { - state = CONSOLE_STATE_CLOSED; - struct in_addr in; - in.s_addr = GetIP(); - LogInfo("Removing console from [{}]:[{}]",inet_ntoa(in),GetPort()); - tcpc->Disconnect(); -} - -bool Console::SendChannelMessage(const ServerChannelMessage_Struct* scm) { - if (!pAcceptMessages) - return false; - switch (scm->chan_num) { - if(RuleB(Chat, ServerWideAuction)){ - case 4: { - SendMessage(1, "%s auctions, '%s'", scm->from, scm->message); - break; - } - } - if(RuleB(Chat, ServerWideOOC)){ - case 5: { - SendMessage(1, "%s says ooc, '%s'", scm->from, scm->message); - break; - } - } - case 6: { - SendMessage(1, "%s BROADCASTS, '%s'", scm->from, scm->message); - break; - } - case 7: { - SendMessage(1, "[%s] tells you, '%s'", scm->from, scm->message); - auto pack = new ServerPacket(ServerOP_ChannelMessage, - sizeof(ServerChannelMessage_Struct) + strlen(scm->message) + 1); - memcpy(pack->pBuffer, scm, pack->size); - ServerChannelMessage_Struct* scm2 = (ServerChannelMessage_Struct*) pack->pBuffer; - strcpy(scm2->deliverto, scm2->from); - scm2->noreply = true; - client_list.SendPacket(scm->from, pack); - safe_delete(pack); - break; - } - case 11: { - SendMessage(1, "%s GMSAYS, '%s'", scm->from, scm->message); - break; - } - default: { - return false; - } - } - return true; -} - -bool Console::SendEmoteMessage(uint32 type, const char* message, ...) { - if (!message) - return false; - if (!pAcceptMessages) - return false; - va_list argptr; - char buffer[1024]; - - va_start(argptr, message); - vsnprintf(buffer, sizeof(buffer), message, argptr); - va_end(argptr); - - SendMessage(1, message); - return true; -} - -bool Console::SendEmoteMessageRaw(uint32 type, const char* message) { - if (!message) - return false; - if (!pAcceptMessages) - return false; - SendMessage(1, message); - return true; -} - -void Console::SendEmoteMessage(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message, ...) { - if (!message) - return; - if (to_guilddbid != 0 || to_minstatus > Admin()) - return; - va_list argptr; - char buffer[1024]; - - va_start(argptr, message); - vsnprintf(buffer, sizeof(buffer), message, argptr); - va_end(argptr); - - SendEmoteMessageRaw(to, to_guilddbid, to_minstatus, type, buffer); -} - -void Console::SendEmoteMessageRaw(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message) { - if (!message) - return; - if (to_guilddbid != 0 || to_minstatus > Admin()) - return; - SendMessage(1, message); -} - -void Console::SendMessage(uint8 newline, const char* message, ...) { - if (!message) - return; - char* buffer = 0; - uint32 bufsize = 1500; - if (message) - bufsize += strlen(message); - buffer = new char[bufsize]; - memset(buffer, 0, bufsize); - if (message != 0) { - va_list argptr; - - va_start(argptr, message); - vsnprintf(buffer, bufsize - 512, message, argptr); - va_end(argptr); - } - - if (newline) { - char outbuf[3]; - outbuf[0] = 13; - outbuf[1] = 10; - outbuf[2] = 0; - for (int i=0; i < newline; i++) - strcat(buffer, outbuf); - } - tcpc->Send((uchar*) buffer, strlen(buffer)); - safe_delete_array(buffer); -} - -bool Console::Process() { - if (state == CONSOLE_STATE_CLOSED) - return false; - - if (!tcpc->Connected()) { - struct in_addr in; - in.s_addr = GetIP(); - LogInfo("Removing console (!tcpc->Connected) from [{}]:[{}]",inet_ntoa(in),GetPort()); - return false; - } - //if we have not gotten the special markers after this timer, send login prompt - if(prompt_timer.Check()) { - struct in_addr in; - in.s_addr = GetIP(); - - std::string connecting_ip = inet_ntoa(in); - - SendMessage(2, StringFormat("Establishing connection from IP: %s Port: %d", inet_ntoa(in), GetPort()).c_str()); - - if (connecting_ip.find("127.0.0.1") != std::string::npos) { - SendMessage(2, StringFormat("Connecting established from local host, auto assuming admin").c_str()); - state = CONSOLE_STATE_CONNECTED; - tcpc->SetEcho(false); - admin = 255; - SendPrompt(); - } - else { - if (tcpc->GetMode() == EmuTCPConnection::modeConsole) - tcpc->Send((const uchar*) "Username: ", strlen("Username: ")); - } - - prompt_timer.Disable(); - - } - - if (timeout_timer.Check()) { - SendMessage(1, 0); - SendMessage(1, "Timeout, disconnecting..."); - struct in_addr in; - in.s_addr = GetIP(); - LogInfo("TCP connection timeout from [{}]:[{}]",inet_ntoa(in),GetPort()); - return false; - } - - if (tcpc->GetMode() == EmuTCPConnection::modePacket) { - struct in_addr in; - in.s_addr = GetIP(); - if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeZone) { - auto zs = new ZoneServer(tcpc); - LogInfo("New zoneserver #[{}] from [{}]:[{}]", zs->GetID(), inet_ntoa(in), GetPort()); - zoneserver_list.Add(zs); - numzones++; - tcpc = 0; - } else if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeLauncher) { - LogInfo("New launcher from [{}]:[{}]", inet_ntoa(in), GetPort()); - launcher_list.Add(tcpc); - tcpc = 0; - } - else if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeUCS) - { - LogInfo("New UCS Connection from [{}]:[{}]", inet_ntoa(in), GetPort()); - UCSLink.SetConnection(tcpc); - tcpc = 0; - } - else if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeQueryServ) - { - LogInfo("New QS Connection from [{}]:[{}]", inet_ntoa(in), GetPort()); - QSLink.SetConnection(tcpc); - tcpc = 0; - } - else { - LogInfo("Unsupported packet mode from [{}]:[{}]", inet_ntoa(in), GetPort()); - } - return false; - } - char* command = 0; - while ((command = tcpc->PopLine())) { - timeout_timer.Start(); - ProcessCommand(command); - delete command; - } - return true; -} - -void ConsoleList::Add(Console* con) { - list.Insert(con); -} - -void ConsoleList::Process() { - LinkedListIterator iterator(list); - iterator.Reset(); - - while(iterator.MoreElements()) { - if (!iterator.GetData()->Process()) - iterator.RemoveCurrent(); - else - iterator.Advance(); - } -} - -void ConsoleList::KillAll() { - LinkedListIterator iterator(list); - iterator.Reset(); - - while(iterator.MoreElements()) { - iterator.GetData()->Die(); - iterator.RemoveCurrent(); - } -} - -void ConsoleList::SendConsoleWho(WorldTCPConnection* connection, const char* to, int16 admin, char** output, uint32* outsize, uint32* outlen) { - LinkedListIterator iterator(list); - iterator.Reset(); - struct in_addr in; - int x = 0; - - while(iterator.MoreElements()) { - in.s_addr = iterator.GetData()->GetIP(); - if (admin >= iterator.GetData()->Admin()) - AppendAnyLenString(output, outsize, outlen, " Console: %s:%i AccID: %i AccName: %s", inet_ntoa(in), iterator.GetData()->GetPort(), iterator.GetData()->AccountID(), iterator.GetData()->AccountName()); - else - AppendAnyLenString(output, outsize, outlen, " Console: AccID: %i AccName: %s", iterator.GetData()->AccountID(), iterator.GetData()->AccountName()); - if (*outlen >= 3584) { - connection->SendEmoteMessageRaw(to, 0, 0, 10, *output); - safe_delete(*output); - *outsize = 0; - *outlen = 0; - } - else { - if (connection->IsConsole()) - AppendAnyLenString(output, outsize, outlen, "\r\n"); - else - AppendAnyLenString(output, outsize, outlen, "\n"); - } - x++; - iterator.Advance(); - } - AppendAnyLenString(output, outsize, outlen, "%i consoles connected", x); -} - -void ConsoleList::SendChannelMessage(const ServerChannelMessage_Struct* scm) { - LinkedListIterator iterator(list); - iterator.Reset(); - - while(iterator.MoreElements()) { - iterator.GetData()->SendChannelMessage(scm); - iterator.Advance(); - } -} - -void ConsoleList::SendEmoteMessage(uint32 type, const char* message, ...) { - va_list argptr; - char buffer[1024]; - - va_start(argptr, message); - vsnprintf(buffer, sizeof(buffer), message, argptr); - va_end(argptr); - - SendEmoteMessageRaw(type, buffer); -} - -void ConsoleList::SendEmoteMessageRaw(uint32 type, const char* message) { - LinkedListIterator iterator(list); - iterator.Reset(); - - while(iterator.MoreElements()) { - iterator.GetData()->SendEmoteMessageRaw(type, message); - iterator.Advance(); - } -} - -Console* ConsoleList::FindByAccountName(const char* accname) { - LinkedListIterator iterator(list); - iterator.Reset(); - - while(iterator.MoreElements()) { - if (strcasecmp(iterator.GetData()->AccountName(), accname) == 0) - return iterator.GetData(); - - iterator.Advance(); - } - return 0; -} - -void Console::ProcessCommand(const char* command) { - switch(state) - { - case CONSOLE_STATE_USERNAME: - { - if (strlen(command) >= 16) { - SendMessage(1, 0); - SendMessage(2, "Username buffer overflow."); - SendMessage(1, "Bye Bye."); - state = CONSOLE_STATE_CLOSED; - return; - } - strcpy(paccountname, command); - state = CONSOLE_STATE_PASSWORD; - SendMessage(0, "Password: "); - tcpc->SetEcho(false); - break; - } - case CONSOLE_STATE_PASSWORD: - { - if (strlen(command) >= 16) { - SendMessage(1, 0); - SendMessage(2, "Password buffer overflow."); - SendMessage(1, "Bye Bye."); - state = CONSOLE_STATE_CLOSED; - return; - } - paccountid = database.CheckLogin(paccountname ,command); - if (paccountid == 0) { - SendMessage(1, 0); - SendMessage(2, "Login failed."); - SendMessage(1, "Bye Bye."); - state = CONSOLE_STATE_CLOSED; - return; - } - database.GetAccountName(paccountid, paccountname); // fixes case and stuff - admin = database.CheckStatus(paccountid); - if (!(admin >= consoleLoginStatus)) { - SendMessage(1, 0); - SendMessage(2, "Access denied."); - SendMessage(1, "Bye Bye."); - state = CONSOLE_STATE_CLOSED; - return; - } - LogInfo("TCP console authenticated: Username=[{}], Admin=[{}]",paccountname,admin); - SendMessage(1, 0); - SendMessage(2, "Login accepted."); - state = CONSOLE_STATE_CONNECTED; - tcpc->SetEcho(true); - SendPrompt(); - break; - } - case CONSOLE_STATE_CONNECTED: { - Log(Logs::Detail, Logs::World_Server,"TCP command: %s: \"%s\"",paccountname ,command); - Seperator sep(command); - if (strcasecmp(sep.arg[0], "help") == 0 || strcmp(sep.arg[0], "?") == 0) { - SendMessage(1, " whoami"); - SendMessage(1, " who"); - SendMessage(1, " zonestatus"); - SendMessage(1, " uptime [zoneID#]"); - SendMessage(1, " emote [zonename or charname or world] [type] [message]"); - SendMessage(1, " echo [on/off]"); - SendMessage(1, " acceptmessages [on/off]"); - SendMessage(1, " tell [name] [message]"); - SendMessage(1, " broadcast [message]"); - SendMessage(1, " gmsay [message]"); - SendMessage(1, " ooc [message]"); - SendMessage(1, " auction [message]"); - if (admin >= consoleKickStatus) - SendMessage(1, " kick [charname]"); - if (admin >= consoleLockStatus) - SendMessage(1, " lock/unlock"); - if (admin >= consoleZoneStatus) { - SendMessage(1, " zoneshutdown [zonename or ZoneServerID]"); - SendMessage(1, " zonebootup [ZoneServerID] [zonename]"); - SendMessage(1, " zonelock [list|lock|unlock] [zonename]"); - } - if (admin >= consoleFlagStatus) - SendMessage(1, " flag [status] [accountname]"); - if (admin >= consolePassStatus) - SendMessage(1, " setpass [accountname] [newpass]"); - if (admin >= consoleWorldStatus) { - SendMessage(1, " version"); - SendMessage(1, " worldshutdown"); - } - if (admin >= AccountStatus::GMMgmt) { - SendMessage(1, " IPLookup [name]"); - } - if (admin >= AccountStatus::GMAdmin) { - SendMessage(1, " LSReconnect"); - SendMessage(1, " signalcharbyname charname ID"); - SendMessage(1, " reloadworld"); - } - } - else if (strcasecmp(sep.arg[0], "ping") == 0) { - // do nothing - } - else if (strcasecmp(sep.arg[0], "signalcharbyname") == 0) { - SendMessage(1, "Signal Sent to %s with ID %i", (char*) sep.arg[1], atoi(sep.arg[2])); - uint32 message_len = strlen((char*) sep.arg[1]) + 1; - auto pack = new ServerPacket(ServerOP_CZSignalClientByName, - sizeof(CZClientSignalByName_Struct) + message_len); - CZClientSignalByName_Struct* CZSC = (CZClientSignalByName_Struct*) pack->pBuffer; - strn0cpy(CZSC->Name, (char*) sep.arg[1], 64); - CZSC->data = atoi(sep.arg[2]); - zoneserver_list.SendPacket(pack); - safe_delete(pack); - } - else if (strcasecmp(sep.arg[0], "setpass") == 0 && admin >= consolePassStatus) { - if (sep.argnum != 2) - SendMessage(1, "Format: setpass accountname password"); - else { - - int16 tmpstatus = 0; - uint32 tmpid = database.GetAccountIDByName(sep.arg[1], &tmpstatus); - if (!tmpid) - SendMessage(1, "Error: Account not found"); - else if (tmpstatus > admin) - SendMessage(1, "Cannot change password: Account's status is higher than yours"); - else if (database.SetLocalPassword(tmpid, sep.arg[2])) - SendMessage(1, "Password changed."); - else - SendMessage(1, "Error changing password."); - } - } - else if (strcasecmp(sep.arg[0], "uptime") == 0) { - if (sep.IsNumber(1) && atoi(sep.arg[1]) > 0) { - auto pack = new ServerPacket(ServerOP_Uptime, sizeof(ServerUptime_Struct)); - ServerUptime_Struct* sus = (ServerUptime_Struct*) pack->pBuffer; - snprintf(sus->adminname, sizeof(sus->adminname), "*%s", GetName()); - sus->zoneserverid = atoi(sep.arg[1]); - ZoneServer* zs = zoneserver_list.FindByID(sus->zoneserverid); - if (zs) - zs->SendPacket(pack); - else - SendMessage(1, "Zoneserver not found."); - delete pack; - } - else { - ZSList::ShowUpTime(this); - } - } - else if (strcasecmp(sep.arg[0], "md5") == 0) { - uint8 md5[16]; - MD5::Generate((const uchar*) sep.argplus[1], strlen(sep.argplus[1]), md5); - SendMessage(1, "MD5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", md5[0], md5[1], md5[2], md5[3], md5[4], md5[5], md5[6], md5[7], md5[8], md5[9], md5[10], md5[11], md5[12], md5[13], md5[14], md5[15]); - } - else if (strcasecmp(sep.arg[0], "whoami") == 0) { - SendMessage(1, "You are logged in as '%s'", AccountName()); - SendMessage(1, "You are known as '*%s'", AccountName()); - SendMessage(1, "AccessLevel: %d", Admin()); - } - else if (strcasecmp(sep.arg[0], "echo") == 0) { - if (strcasecmp(sep.arg[1], "on") == 0) - tcpc->SetEcho(true); - else if (strcasecmp(sep.arg[1], "off") == 0) { - if (pAcceptMessages) - SendMessage(1, "Echo can not be turned off while acceptmessages is on"); - else - tcpc->SetEcho(false); - } - else - SendMessage(1, "Usage: echo [on/off]"); - } - else if (strcasecmp(sep.arg[0], "acceptmessages") == 0) { - if (strcasecmp(sep.arg[1], "on") == 0) - if (tcpc->GetEcho()) - SendMessage(1, "AcceptMessages can not be turned on while echo is on"); - else - pAcceptMessages = true; - else if (strcasecmp(sep.arg[1], "off") == 0) - pAcceptMessages = false; - else - SendMessage(1, "Usage: acceptmessages [on/off]"); - } - else if (strcasecmp(sep.arg[0], "tell") == 0) { - char tmpname[64]; - tmpname[0] = '*'; - strcpy(&tmpname[1], paccountname); - zoneserver_list.SendChannelMessage(tmpname, sep.arg[1], 7, 0, sep.argplus[2]); - } - else if (strcasecmp(sep.arg[0], "broadcast") == 0) { - char tmpname[64]; - tmpname[0] = '*'; - strcpy(&tmpname[1], paccountname); - zoneserver_list.SendChannelMessage(tmpname, 0, 6, 0, sep.argplus[1]); - } - else if (strcasecmp(sep.arg[0], "ooc") == 0) { - char tmpname[64]; - tmpname[0] = '*'; - strcpy(&tmpname[1], paccountname); - zoneserver_list.SendChannelMessage(tmpname, 0, 5, 0, sep.argplus[1]); - } - else if (strcasecmp(sep.arg[0], "auction") == 0) { - char tmpname[64]; - tmpname[0] = '*'; - strcpy(&tmpname[1], paccountname); - zoneserver_list.SendChannelMessage(tmpname, 0, 4, 0, sep.argplus[1]); - } - else if (strcasecmp(sep.arg[0], "gmsay") == 0 || strcasecmp(sep.arg[0], "pr") == 0) { - char tmpname[64]; - tmpname[0] = '*'; - strcpy(&tmpname[1], paccountname); - zoneserver_list.SendChannelMessage(tmpname, 0, 11, 0, sep.argplus[1]); - } - else if (strcasecmp(sep.arg[0], "emote") == 0) { - if (strcasecmp(sep.arg[1], "world") == 0) - zoneserver_list.SendEmoteMessageRaw(0, 0, 0, atoi(sep.arg[2]), sep.argplus[3]); - else { - ZoneServer* zs = zoneserver_list.FindByName(sep.arg[1]); - if (zs != 0) - zs->SendEmoteMessageRaw(0, 0, 0, atoi(sep.arg[2]), sep.argplus[3]); - else - zoneserver_list.SendEmoteMessageRaw(sep.arg[1], 0, 0, atoi(sep.arg[2]), sep.argplus[3]); - } - } - else if (strcasecmp(sep.arg[0], "movechar") == 0) { - if(sep.arg[1][0]==0 || sep.arg[2][0] == 0) - SendMessage(1, "Usage: movechar [charactername] [zonename]"); - else { - if (!ZoneID(sep.arg[2])) - SendMessage(1, "Error: Zone '%s' not found", sep.arg[2]); - else if (!database.CheckUsedName((char*) sep.arg[1])) { - if (!database.MoveCharacterToZone((char*) sep.arg[1], (char*) sep.arg[2])) - SendMessage(1, "Character Move Failed!"); - else - SendMessage(1, "Character has been moved."); - } - else - SendMessage(1, "Character Does Not Exist"); - } - } - else if (strcasecmp(sep.arg[0], "flag") == 0 && Admin() >= consoleFlagStatus) { -// SCORPIOUS2K - reversed parameter order for flag - if(sep.arg[2][0]==0 || !sep.IsNumber(1)) - SendMessage(1, "Usage: flag [status] [accountname]"); - else - { - if (atoi(sep.arg[1]) > Admin()) - SendMessage(1, "You cannot set people's status to higher than your own"); - else if (atoi(sep.arg[1]) < 0 && Admin() < consoleFlagStatus) - SendMessage(1, "You have too low of status to change flags"); - else if (!database.SetAccountStatus(sep.arg[2], atoi(sep.arg[1]))) - SendMessage(1, "Unable to flag account!"); - else - SendMessage(1, "Account Flaged"); - } - } - else if (strcasecmp(sep.arg[0], "kick") == 0 && admin >= consoleKickStatus) { - char tmpname[64]; - tmpname[0] = '*'; - strcpy(&tmpname[1], paccountname); - auto pack = new ServerPacket; - pack->opcode = ServerOP_KickPlayer; - pack->size = sizeof(ServerKickPlayer_Struct); - pack->pBuffer = new uchar[pack->size]; - ServerKickPlayer_Struct* skp = (ServerKickPlayer_Struct*) pack->pBuffer; - strcpy(skp->adminname, tmpname); - strcpy(skp->name, sep.arg[1]); - skp->adminrank = Admin(); - zoneserver_list.SendPacket(pack); - delete pack; - } - else if (strcasecmp(sep.arg[0], "who") == 0) { - auto whom = new Who_All_Struct; - memset(whom, 0, sizeof(Who_All_Struct)); - whom->lvllow = 0xFFFF; - whom->lvlhigh = 0xFFFF; - whom->wclass = 0xFFFF; - whom->wrace = 0xFFFF; - whom->gmlookup = 0xFFFF; - for (int i=1; i<=sep.argnum; i++) { - if (strcasecmp(sep.arg[i], "gm") == 0) - whom->gmlookup = 1; - else if (sep.IsNumber(i)) { - if (whom->lvllow == 0xFFFF) { - whom->lvllow = atoi(sep.arg[i]); - whom->lvlhigh = whom->lvllow; - } - else if (atoi(sep.arg[i]) > int(whom->lvllow)) - whom->lvlhigh = atoi(sep.arg[i]); - else - whom->lvllow = atoi(sep.arg[i]); - } - else - strn0cpy(whom->whom, sep.arg[i], sizeof(whom->whom)); - } - client_list.ConsoleSendWhoAll(0, admin, whom, this); - delete whom; - } - else if (strcasecmp(sep.arg[0], "zonestatus") == 0) { - zoneserver_list.SendZoneStatus(0, admin, this); - } - else if (strcasecmp(sep.arg[0], "exit") == 0 || strcasecmp(sep.arg[0], "quit") == 0) { - SendMessage(1, "Bye Bye."); - state = CONSOLE_STATE_CLOSED; - } - else if (strcasecmp(sep.arg[0], "zoneshutdown") == 0 && admin >= consoleZoneStatus) { - if (sep.arg[1][0] == 0) { - SendMessage(1, "Usage: zoneshutdown zoneshortname"); - } else { - char tmpname[64]; - tmpname[0] = '*'; - strcpy(&tmpname[1], paccountname); - - auto pack = new ServerPacket; - pack->size = sizeof(ServerZoneStateChange_struct); - pack->pBuffer = new uchar[pack->size]; - memset(pack->pBuffer, 0, sizeof(ServerZoneStateChange_struct)); - ServerZoneStateChange_struct* s = (ServerZoneStateChange_struct *) pack->pBuffer; - pack->opcode = ServerOP_ZoneShutdown; - strcpy(s->adminname, tmpname); - if (sep.arg[1][0] >= '0' && sep.arg[1][0] <= '9') - s->ZoneServerID = atoi(sep.arg[1]); - else - s->zoneid = ZoneID(sep.arg[1]); - - ZoneServer* zs = 0; - if (s->ZoneServerID != 0) - zs = zoneserver_list.FindByID(s->ZoneServerID); - else if (s->zoneid != 0) - zs = zoneserver_list.FindByName(ZoneName(s->zoneid)); - else - SendMessage(1, "Error: ZoneShutdown: neither ID nor name specified"); - - if (zs == 0) - SendMessage(1, "Error: ZoneShutdown: zoneserver not found"); - else - zs->SendPacket(pack); - - delete pack; - } - } - else if (strcasecmp(sep.arg[0], "zonebootup") == 0 && admin >= consoleZoneStatus) { - if (sep.arg[2][0] == 0 || !sep.IsNumber(1)) { - SendMessage(1, "Usage: zonebootup ZoneServerID# zoneshortname"); - } else { - char tmpname[64]; - tmpname[0] = '*'; - strcpy(&tmpname[1], paccountname); - - LogInfo("Console ZoneBootup: [{}], [{}], [{}]",tmpname,sep.arg[2],sep.arg[1]); - zoneserver_list.SOPZoneBootup(tmpname, atoi(sep.arg[1]), sep.arg[2], (bool) (strcasecmp(sep.arg[3], "static") == 0)); - } - } - else if (strcasecmp(sep.arg[0], "worldshutdown") == 0 && admin >= consoleWorldStatus) { - int32 time, interval; - if(sep.IsNumber(1) && sep.IsNumber(2) && ((time=atoi(sep.arg[1]))>0) && ((interval=atoi(sep.arg[2]))>0)) { - zoneserver_list.WorldShutDown(time, interval); - } - else if(strcasecmp(sep.arg[1], "now") == 0) { - zoneserver_list.WorldShutDown(0, 0); - } - else if(strcasecmp(sep.arg[1], "disable") == 0) { - SendEmoteMessage( - 0, - 0, - 0, - Chat::Yellow, - "[SYSTEM] World shutdown has been aborted." - ); - zoneserver_list.SendEmoteMessage( - 0, - 0, - 0, - Chat::Yellow, - "[SYSTEM] World shutdown has been aborted." - ); - zoneserver_list.shutdowntimer->Disable(); - zoneserver_list.reminder->Disable(); - } - else { - SendMessage(1, "Usage: worldshutdown [now] [disable] ([time] [interval])"); - //Go ahead and shut down since that's what this used to do when invoked this way. - zoneserver_list.WorldShutDown(0, 0); - } - } - else if (strcasecmp(sep.arg[0], "lock") == 0 && admin >= consoleLockStatus) { - WorldConfig::LockWorld(); - if (loginserverlist.Connected()) { - loginserverlist.SendStatus(); - SendMessage(1, "World locked."); - } - else { - SendMessage(1, "World locked, but login server not connected."); - } - } - else if (strcasecmp(sep.arg[0], "unlock") == 0 && admin >= consoleLockStatus) { - WorldConfig::UnlockWorld(); - if (loginserverlist.Connected()) { - loginserverlist.SendStatus(); - SendMessage(1, "World unlocked."); - } - else { - SendMessage(1, "World unlocked, but login server not connected."); - } - } - else if (strcasecmp(sep.arg[0], "version") == 0 && admin >= consoleWorldStatus) { - SendMessage(1, "Current version information."); - SendMessage(1, " %s", CURRENT_VERSION); - SendMessage(1, " Compiled on: %s at %s", COMPILE_DATE, COMPILE_TIME); - SendMessage(1, " Last modified on: %s", LAST_MODIFIED); - } - else if (strcasecmp(sep.arg[0], "serverinfo") == 0 && admin >= AccountStatus::GMMgmt) { - if (strcasecmp(sep.arg[1], "os") == 0) { - #ifdef _WINDOWS - GetOS(); - char intbuffer [sizeof(unsigned long)]; - SendMessage(1, "Operating system information."); - SendMessage(1, " %s", Ver_name); - SendMessage(1, " Build number: %s", ultoa(Ver_build, intbuffer, 10)); - SendMessage(1, " Minor version: %s", ultoa(Ver_min, intbuffer, 10)); - SendMessage(1, " Major version: %s", ultoa(Ver_maj, intbuffer, 10)); - SendMessage(1, " Platform Id: %s", ultoa(Ver_pid, intbuffer, 10)); - #else - char os_string[100]; - SendMessage(1, "Operating system information."); - SendMessage(1, " %s", GetOS(os_string)); - #endif - } - else { - SendMessage(1, "Usage: Serverinfo [type]"); - SendMessage(1, " OS - Operating system version information."); - } - } - else if (strcasecmp(sep.arg[0], "IPLookup") == 0 && admin >= AccountStatus::GMMgmt) { - client_list.SendCLEList(admin, 0, this, sep.argplus[1]); - } - else if (strcasecmp(sep.arg[0], "LSReconnect") == 0 && admin >= AccountStatus::GMAdmin) { - #ifdef _WINDOWS - _beginthread(AutoInitLoginServer, 0, nullptr); - #else - pthread_t thread; - pthread_create(&thread, nullptr, &AutoInitLoginServer, nullptr); - #endif - RunLoops = true; - SendMessage(1, " Login Server Reconnect manually restarted by Console"); - LogInfo("Login Server Reconnect manually restarted by Console"); - } - else if (strcasecmp(sep.arg[0], "zonelock") == 0 && admin >= consoleZoneStatus) { - if (strcasecmp(sep.arg[1], "list") == 0) { - zoneserver_list.ListLockedZones(0, this); - } - else if (strcasecmp(sep.arg[1], "lock") == 0 && admin >= AccountStatus::GMAdmin) { - uint16 tmp = ZoneID(sep.arg[2]); - if (tmp) { - if (zoneserver_list.SetLockedZone(tmp, true)) - zoneserver_list.SendEmoteMessage(0, 0, 80, 15, "Zone locked: %s", ZoneName(tmp)); - else - SendMessage(1, "Failed to change lock"); - } - else - SendMessage(1, "Usage: #zonelock lock [zonename]"); - } - else if (strcasecmp(sep.arg[1], "unlock") == 0 && admin >= AccountStatus::GMAdmin) { - uint16 tmp = ZoneID(sep.arg[2]); - if (tmp) { - if (zoneserver_list.SetLockedZone(tmp, false)) - zoneserver_list.SendEmoteMessage(0, 0, 80, 15, "Zone unlocked: %s", ZoneName(tmp)); - else - SendMessage(1, "Failed to change lock"); - } - else - SendMessage(1, "Usage: #zonelock unlock [zonename]"); - } - else { - SendMessage(1, "#zonelock sub-commands"); - SendMessage(1, " list"); - if (admin >= AccountStatus::GMAdmin) { - SendMessage(1, " lock [zonename]"); - SendMessage(1, " unlock [zonename]"); - } - } - } - else if (strcasecmp(sep.arg[0], "reloadworld") == 0 && admin > AccountStatus::GMAdmin) - { - SendEmoteMessage(0,0,0,15,"Reloading World..."); - auto pack = new ServerPacket(ServerOP_ReloadWorld, sizeof(ReloadWorld_Struct)); - ReloadWorld_Struct* RW = (ReloadWorld_Struct*) pack->pBuffer; - RW->global_repop = ReloadWorld::Repop; - zoneserver_list.SendPacket(pack); - safe_delete(pack); - } - else if (strcasecmp(sep.arg[0], "") == 0){ - /* Hit Enter with no command */ - } - else { - SendMessage(1, "Command unknown."); - } - if (state == CONSOLE_STATE_CONNECTED) - SendPrompt(); - break; - } - default: { - break; - } - } -} - -void Console::SendPrompt() { - if (tcpc->GetEcho()) - SendMessage(0, "%s> ", paccountname); -} - diff --git a/world/dynamic_zone_manager.cpp b/world/dynamic_zone_manager.cpp index 2bed2a97e..751246b2d 100644 --- a/world/dynamic_zone_manager.cpp +++ b/world/dynamic_zone_manager.cpp @@ -28,9 +28,9 @@ void DynamicZoneManager::PurgeExpiredDynamicZones() LogDynamicZones("Purging [{}] dynamic zone(s)", dz_ids.size()); DynamicZoneMembersRepository::DeleteWhere(database, - fmt::format("dynamic_zone_id IN ({})", fmt::join(dz_ids, ","))); + fmt::format("dynamic_zone_id IN ({})", Strings::Join(dz_ids, ","))); DynamicZonesRepository::DeleteWhere(database, - fmt::format("id IN ({})", fmt::join(dz_ids, ","))); + fmt::format("id IN ({})", Strings::Join(dz_ids, ","))); } } @@ -145,7 +145,7 @@ void DynamicZoneManager::Process() // need to look up expedition ids until lockouts are moved to dynamic zones std::vector expedition_ids; auto expeditions = ExpeditionsRepository::GetWhere(database, - fmt::format("dynamic_zone_id IN ({})", fmt::join(dynamic_zone_ids, ","))); + fmt::format("dynamic_zone_id IN ({})", Strings::Join(dynamic_zone_ids, ","))); if (!expeditions.empty()) { @@ -154,14 +154,14 @@ void DynamicZoneManager::Process() expedition_ids.emplace_back(expedition.id); } ExpeditionLockoutsRepository::DeleteWhere(database, - fmt::format("expedition_id IN ({})", fmt::join(expedition_ids, ","))); + fmt::format("expedition_id IN ({})", Strings::Join(expedition_ids, ","))); } ExpeditionsRepository::DeleteWhere(database, - fmt::format("dynamic_zone_id IN ({})", fmt::join(dynamic_zone_ids, ","))); + fmt::format("dynamic_zone_id IN ({})", Strings::Join(dynamic_zone_ids, ","))); DynamicZoneMembersRepository::RemoveAllMembers(database, dynamic_zone_ids); DynamicZonesRepository::DeleteWhere(database, - fmt::format("id IN ({})", fmt::join(dynamic_zone_ids, ","))); + fmt::format("id IN ({})", Strings::Join(dynamic_zone_ids, ","))); } } diff --git a/world/eqemu_api_world_data_service.cpp b/world/eqemu_api_world_data_service.cpp index de8e2ffba..c9e257a64 100644 --- a/world/eqemu_api_world_data_service.cpp +++ b/world/eqemu_api_world_data_service.cpp @@ -194,7 +194,7 @@ void EQEmuApiWorldDataService::reload(Json::Value &r, const std::vector(std::stoul(args[2])); + global_repop = static_cast(Strings::ToUnsignedInt(args[2])); if (global_repop > ReloadWorld::ForceRepop) { global_repop = ReloadWorld::ForceRepop; @@ -224,6 +224,13 @@ void EQEmuApiWorldDataService::reload(Json::Value &r, const std::vectorLoadRules(&database, RuleManager::Instance()->GetActiveRuleset(), true); + } } found_command = true; diff --git a/world/eql_config.cpp b/world/eql_config.cpp index d35429aae..037372a94 100644 --- a/world/eql_config.cpp +++ b/world/eql_config.cpp @@ -47,7 +47,7 @@ void EQLConfig::LoadSettings() { } else { auto row = results.begin(); - m_dynamics = atoi(row[0]); + m_dynamics = Strings::ToInt(row[0]); } query = StringFormat("SELECT zone, port FROM launcher_zones WHERE launcher = '%s'", namebuf); @@ -60,27 +60,12 @@ void EQLConfig::LoadSettings() { LauncherZone zs; for (auto row = results.begin(); row != results.end(); ++row) { zs.name = row[0]; - zs.port = atoi(row[1]); + zs.port = Strings::ToInt(row[1]); m_zones[zs.name] = zs; } } -EQLConfig *EQLConfig::CreateLauncher(const char *name, uint8 dynamic_count) { - - char namebuf[128]; - database.DoEscapeString(namebuf, name, strlen(name)&0x3F); //limit len to 64 - namebuf[127] = '\0'; - - std::string query = StringFormat("INSERT INTO launcher (name, dynamics) VALUES('%s', %d)", namebuf, dynamic_count); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - return nullptr; - } - - return new EQLConfig(name); -} - void EQLConfig::GetZones(std::vector &result) { std::map::iterator cur, end; cur = m_zones.begin(); @@ -90,64 +75,6 @@ void EQLConfig::GetZones(std::vector &result) { } } -std::vector EQLConfig::ListZones() { - LauncherLink *ll = launcher_list.Get(m_name.c_str()); - std::vector res; - if(ll == nullptr) { - //if the launcher isnt connected, use the list from the database. - std::map::iterator cur, end; - cur = m_zones.begin(); - end = m_zones.end(); - for(; cur != end; ++cur) { - res.push_back(cur->first); - } - } else { - //otherwise, use the zone list from the launcher link. - ll->GetZoneList(res); - } - return(res); -} - -void EQLConfig::DeleteLauncher() { - - launcher_list.Remove(m_name.c_str()); - - char namebuf[128]; - database.DoEscapeString(namebuf, m_name.c_str(), m_name.length()&0x3F); //limit len to 64 - namebuf[127] = '\0'; - - std::string query = StringFormat("DELETE FROM launcher WHERE name = '%s'", namebuf); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - return; - } - - query = StringFormat("DELETE FROM launcher_zones WHERE launcher = '%s'", namebuf); - results = database.QueryDatabase(query); - if (!results.Success()) { - return; - } -} - -bool EQLConfig::IsConnected() const { - LauncherLink *ll = launcher_list.Get(m_name.c_str()); - return(ll != nullptr); -} - -void EQLConfig::RestartZone(Const_char *zone_ref) { - LauncherLink *ll = launcher_list.Get(m_name.c_str()); - if(ll == nullptr) - return; - ll->RestartZone(zone_ref); -} - -void EQLConfig::StopZone(Const_char *zone_ref) { - LauncherLink *ll = launcher_list.Get(m_name.c_str()); - if(ll == nullptr) - return; - ll->StopZone(zone_ref); -} - void EQLConfig::StartZone(Const_char *zone_ref) { LauncherLink *ll = launcher_list.Get(m_name.c_str()); if(ll == nullptr) @@ -155,158 +82,6 @@ void EQLConfig::StartZone(Const_char *zone_ref) { ll->StartZone(zone_ref); } -bool EQLConfig::BootStaticZone(Const_char *short_name, uint16 port) { - //make sure the short name is valid. - if(ZoneID(short_name) == 0) - return false; - - //database update - char namebuf[128]; - database.DoEscapeString(namebuf, m_name.c_str(), m_name.length()&0x3F); //limit len to 64 - namebuf[127] = '\0'; - char zonebuf[32]; - database.DoEscapeString(zonebuf, short_name, strlen(short_name)&0xF); //limit len to 16 - zonebuf[31] = '\0'; - - std::string query = StringFormat("INSERT INTO launcher_zones (launcher, zone, port) " - "VALUES('%s', '%s', %d)", namebuf, zonebuf, port); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - return false; - } - - //update our internal state. - LauncherZone lz; - lz.name = short_name; - lz.port = port; - m_zones[lz.name] = lz; - - //if the launcher is connected, update it. - LauncherLink *ll = launcher_list.Get(m_name.c_str()); - if(ll != nullptr) { - ll->BootZone(short_name, port); - } - - return true; -} - -bool EQLConfig::ChangeStaticZone(Const_char *short_name, uint16 port) { - //make sure the short name is valid. - if(ZoneID(short_name) == 0) - return false; - - //check internal state - std::map::iterator res; - res = m_zones.find(short_name); - if(res == m_zones.end()) { - //not found. - LogError("Update for unknown zone {}", short_name); - return false; - } - - char namebuf[128]; - database.DoEscapeString(namebuf, m_name.c_str(), m_name.length()&0x3F); //limit len to 64 - namebuf[127] = '\0'; - char zonebuf[32]; - database.DoEscapeString(zonebuf, short_name, strlen(short_name)&0xF); //limit len to 16 - zonebuf[31] = '\0'; - - std::string query = StringFormat("UPDATE launcher_zones SET port=%d WHERE " - "launcher = '%s' AND zone = '%s'",port, namebuf, zonebuf); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - return false; - } - - //update internal state - res->second.port = port; - - //if the launcher is connected, update it. - LauncherLink *ll = launcher_list.Get(m_name.c_str()); - if(ll != nullptr) { - ll->RestartZone(short_name); - } - - return true; -} - -bool EQLConfig::DeleteStaticZone(Const_char *short_name) { - //check internal state - std::map::iterator res; - res = m_zones.find(short_name); - if(res == m_zones.end()) { - //not found. - LogError("Update for unknown zone {}", short_name); - return false; - } - - char namebuf[128]; - database.DoEscapeString(namebuf, m_name.c_str(), m_name.length()&0x3F); //limit len to 64 - namebuf[127] = '\0'; - char zonebuf[32]; - database.DoEscapeString(zonebuf, short_name, strlen(short_name)&0xF); //limit len to 16 - zonebuf[31] = '\0'; - - std::string query = StringFormat("DELETE FROM launcher_zones WHERE " - "launcher = '%s' AND zone = '%s'", namebuf, zonebuf); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - return false; - } - - //internal update. - m_zones.erase(res); - - //if the launcher is connected, update it. - LauncherLink *ll = launcher_list.Get(m_name.c_str()); - if(ll != nullptr) { - ll->StopZone(short_name); - } - - return true; -} - -bool EQLConfig::SetDynamicCount(int count) { - - char namebuf[128]; - database.DoEscapeString(namebuf, m_name.c_str(), m_name.length()&0x3F); //limit len to 64 - namebuf[127] = '\0'; - - std::string query = StringFormat("UPDATE launcher SET dynamics=%d WHERE name='%s'", count, namebuf); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - return false; - } - - //update in-memory version. - m_dynamics = count; - - //if the launcher is connected, update it. - LauncherLink *ll = launcher_list.Get(m_name.c_str()); - if(ll != nullptr) { - ll->BootDynamics(count); - } - - return false; -} - int EQLConfig::GetDynamicCount() const { return(m_dynamics); } - -std::map EQLConfig::GetZoneDetails(Const_char *zone_ref) { - std::map res; - - LauncherLink *ll = launcher_list.Get(m_name.c_str()); - if(ll == nullptr) { - res["name"] = zone_ref; - res["up"] = "0"; - res["starts"] = "0"; - res["port"] = "0"; - } else { - ll->GetZoneDetails(zone_ref, res); - } - - return(res); -} - diff --git a/world/eql_config.h b/world/eql_config.h index 2702abdbc..998816165 100644 --- a/world/eql_config.h +++ b/world/eql_config.h @@ -42,24 +42,8 @@ public: //BEGIN PERL EXPORT Const_char * GetName() const { return(m_name.c_str()); } - int GetStaticCount() const { return(m_zones.size()); } - bool IsConnected() const; //is this launcher connected to world - - void DeleteLauncher(); //kill this launcher and all its zones. - - void RestartZone(Const_char *zone_ref); - void StopZone(Const_char *zone_ref); void StartZone(Const_char *zone_ref); - - bool BootStaticZone(Const_char *short_name, uint16 port); - bool ChangeStaticZone(Const_char *short_name, uint16 port); - bool DeleteStaticZone(Const_char *short_name); - - bool SetDynamicCount(int count); int GetDynamicCount() const; - - std::vector ListZones(); //returns an array of zone refs - std::map GetZoneDetails(Const_char *zone_ref); //END PERL EXPORT protected: diff --git a/world/eqw.cpp b/world/eqw.cpp index 7c37f3e45..1a7e6c147 100644 --- a/world/eqw.cpp +++ b/world/eqw.cpp @@ -131,7 +131,7 @@ std::vector EQW::ListBootedZones() { std::map EQW::GetZoneDetails(Const_char *zone_ref) { std::map res; - ZoneServer *zs = zoneserver_list.FindByID(atoi(zone_ref)); + ZoneServer *zs = zoneserver_list.FindByID(Strings::ToInt(zone_ref)); if(zs == nullptr) { res["error"] = "Invalid zone."; return(res); @@ -316,7 +316,7 @@ int EQW::CountBugs() { return 0; auto row = results.begin(); - return atoi(row[0]); + return Strings::ToInt(row[0]); } std::vector EQW::ListBugs(uint32 offset) { diff --git a/world/expedition_database.cpp b/world/expedition_database.cpp index 670418a87..995be8c6e 100644 --- a/world/expedition_database.cpp +++ b/world/expedition_database.cpp @@ -50,11 +50,11 @@ void ExpeditionDatabase::PurgeExpiredExpeditions() auto results = database.QueryDatabase(query); if (results.Success()) { - std::vector expedition_ids; + std::vector expedition_ids; std::vector dynamic_zone_ids; for (auto row = results.begin(); row != results.end(); ++row) { - expedition_ids.emplace_back(static_cast(strtoul(row[0], nullptr, 10))); + expedition_ids.emplace_back(row[0]); dynamic_zone_ids.emplace_back(static_cast(strtoul(row[1], nullptr, 10))); } diff --git a/world/http_request.cpp b/world/http_request.cpp index af4b6c9b2..16be3c8dd 100644 --- a/world/http_request.cpp +++ b/world/http_request.cpp @@ -54,7 +54,7 @@ int HTTPRequest::getInt(const char *name, int default_value) const { res = m_values.find(name); if(res == m_values.end()) return(default_value); - return(atoi(res->second.c_str())); + return(Strings::ToInt(res->second.c_str())); } float HTTPRequest::getFloat(const char *name, float default_value) const { @@ -62,7 +62,7 @@ float HTTPRequest::getFloat(const char *name, float default_value) const { res = m_values.find(name); if(res == m_values.end()) return(default_value); - return(atof(res->second.c_str())); + return(Strings::ToFloat(res->second.c_str())); } void HTTPRequest::header(Const_char *name, Const_char *value) { diff --git a/world/launcher_link.cpp b/world/launcher_link.cpp index 0517d522f..ae856c8b8 100644 --- a/world/launcher_link.cpp +++ b/world/launcher_link.cpp @@ -37,7 +37,6 @@ extern LauncherList launcher_list; LauncherLink::LauncherLink(int id, std::shared_ptr c) : ID(id), tcpc(c), - authenticated(false), m_name(""), m_bootTimer(2000) { diff --git a/world/launcher_link.h b/world/launcher_link.h index 8b273d5d2..60d8540e9 100644 --- a/world/launcher_link.h +++ b/world/launcher_link.h @@ -45,7 +45,6 @@ public: inline uint16 GetPort() const { return tcpc->Handle() ? tcpc->Handle()->RemotePort() : 0; } inline std::string GetUUID() const { return tcpc->GetUUID(); } inline const char * GetName() const { return(m_name.c_str()); } - inline int CountZones() const { return(m_states.size()); } bool ContainsZone(const char *short_name) const; @@ -65,7 +64,6 @@ protected: const int ID; std::shared_ptr tcpc; std::unique_ptr m_process_timer; - bool authenticated; std::string m_name; Timer m_bootTimer; diff --git a/world/launcher_list.cpp b/world/launcher_list.cpp index b38b38589..f9923f345 100644 --- a/world/launcher_list.cpp +++ b/world/launcher_list.cpp @@ -86,17 +86,6 @@ LauncherLink *LauncherList::Get(const char *name) { return(res->second); } -LauncherLink *LauncherList::FindByZone(const char *short_name) { - std::map::iterator cur, end; - cur = m_launchers.begin(); - end = m_launchers.end(); - for (; cur != end; ++cur) { - if (cur->second->ContainsZone(short_name)) - return(cur->second); - } - return(nullptr); -} - void LauncherList::Add(std::shared_ptr conn) { auto it = new LauncherLink(nextID++, conn); LogInfo("Adding pending launcher [{}]", it->GetID()); @@ -129,15 +118,6 @@ int LauncherList::GetLauncherCount() { return(m_launchers.size()); } -void LauncherList::GetLauncherNameList(std::vector &res) { - std::map::iterator cur, end; - cur = m_configs.begin(); - end = m_configs.end(); - for (; cur != end; ++cur) { - res.push_back(cur->first); - } -} - void LauncherList::LoadList() { std::vector launchers; @@ -160,10 +140,6 @@ EQLConfig *LauncherList::GetConfig(const char *name) { return(res->second); } -void LauncherList::CreateLauncher(const char *name, uint8 dynamic_count) { - m_configs[name] = EQLConfig::CreateLauncher(name, dynamic_count); -} - void LauncherList::Remove(const char *name) { std::map::iterator resc; resc = m_configs.find(name); diff --git a/world/launcher_list.h b/world/launcher_list.h index 06156cd7e..f20dba0f4 100644 --- a/world/launcher_list.h +++ b/world/launcher_list.h @@ -37,17 +37,13 @@ public: void LoadList(); EQLConfig *GetConfig(const char *name); - void CreateLauncher(const char *name, uint8 dynamic_count); void Remove(const char *name); void Add(std::shared_ptr conn); void Remove(std::shared_ptr conn); LauncherLink *Get(const char *name); - LauncherLink *FindByZone(const char *short_name); int GetLauncherCount(); - void GetLauncherNameList(std::vector &list); - protected: std::map m_configs; //we own these objects std::map m_launchers; //we own these objects diff --git a/world/login_server_list.cpp b/world/login_server_list.cpp index 64081a3fe..efd9c1d91 100644 --- a/world/login_server_list.cpp +++ b/world/login_server_list.cpp @@ -55,14 +55,6 @@ void LoginServerList::Add(const char* iAddress, uint16 iPort, const char* Accoun m_list.push_back(std::unique_ptr(loginserver)); } -bool LoginServerList::SendInfo() { - for (auto &iter : m_list) { - (*iter).SendInfo(); - } - - return true; -} - bool LoginServerList::SendStatus() { for (auto &iter : m_list) { (*iter).SendStatus(); @@ -99,23 +91,3 @@ bool LoginServerList::Connected() { return false; } - -bool LoginServerList::AllConnected() { - for (auto &iter : m_list) { - if (!(*iter).Connected()) { - return false; - } - } - - return true; -} - -bool LoginServerList::CanUpdate() { - for (auto &iter : m_list) { - if ((*iter).CanUpdate()) { - return true; - } - } - - return false; -} diff --git a/world/login_server_list.h b/world/login_server_list.h index d1b29a8cf..d9a270e55 100644 --- a/world/login_server_list.h +++ b/world/login_server_list.h @@ -16,17 +16,11 @@ public: ~LoginServerList(); void Add(const char*, uint16, const char*, const char*, bool); - - bool SendInfo(); bool SendStatus(); - bool SendPacket(ServerPacket *pack); bool SendAccountUpdate(ServerPacket *pack); bool Connected(); - bool AllConnected(); - bool CanUpdate(); size_t GetServerCount() const { return m_list.size(); } - protected: std::list> m_list; }; diff --git a/world/main.cpp b/world/main.cpp index b27ab7684..a01c57ed1 100644 --- a/world/main.cpp +++ b/world/main.cpp @@ -18,8 +18,6 @@ * */ -#define PLATFORM_WORLD 1 - #include "../common/global_define.h" #include @@ -56,18 +54,8 @@ #include #else -#include "../common/unix.h" #include - -#if not defined (FREEBSD) && not defined (DARWIN) -union semun { - int val; - struct semid_ds *buf; - ushort *array; - struct seminfo *__buf; - void *__pad; -}; -#endif +#include #endif @@ -96,6 +84,7 @@ union semun { #include "shared_task_manager.h" #include "world_boot.h" #include "../common/path_manager.h" +#include "../common/events/player_event_logs.h" ZoneStore zone_store; @@ -118,6 +107,7 @@ EQEmuLogSys LogSys; WorldContentService content_service; WebInterfaceList web_interface; PathManager path; +PlayerEventLogs player_event_logs; void CatchSignal(int sig_num); @@ -128,6 +118,7 @@ inline void UpdateWindowTitle(std::string new_title) #endif } + /** * World process entrypoint * @@ -371,6 +362,9 @@ int main(int argc, char **argv) } ); + Timer player_event_process_timer(1000); + player_event_logs.SetDatabase(&database)->Init(); + auto loop_fn = [&](EQ::Timer* t) { Timer::SetCurrentTime(); @@ -418,6 +412,10 @@ int main(int argc, char **argv) client_list.Process(); + if (player_event_process_timer.Check()) { + player_event_logs.Process(); + } + if (PurgeInstanceTimer.Check()) { database.PurgeExpiredInstances(); database.PurgeAllDeletedDataBuckets(); @@ -467,6 +465,8 @@ int main(int argc, char **argv) LogInfo("Signaling HTTP service to stop"); LogSys.CloseFileLogs(); + WorldBoot::Shutdown(); + return 0; } diff --git a/world/main.h b/world/main.h index 06e918a5c..55c1fa8e9 100644 --- a/world/main.h +++ b/world/main.h @@ -32,56 +32,3 @@ void CatchSignal(int sig_num); -#define EQ_WORLD_PORT 9000 //mandated by the client -#define LOGIN_PORT 5997 - -class NetConnection -{ -public: - NetConnection() { - world_locked = false; - for (int i=0; i<5; i++) { - memset(loginaddress[i], 0, sizeof(loginaddress[i])); - loginport[i] = LOGIN_PORT; - } - memset(worldname, 0, sizeof(worldname)); - memset(worldshortname, 0, sizeof(worldshortname)); - memset(worldaccount, 0, sizeof(worldaccount)); - memset(worldpassword, 0, sizeof(worldpassword)); - memset(worldaddress, 0, sizeof(worldaddress)); - memset(chataddress, 0, sizeof(chataddress)); - DEFAULTSTATUS=0; - LoginServerInfo = 0;//ReadLoginINI(); - UpdateStats = false; - } - ~NetConnection() { } - - bool ReadLoginINI(); - bool LoginServerInfo; - bool UpdateStats; - char* GetLoginInfo(uint16* oPort); - inline char* GetLoginAddress(uint8 i) { return loginaddress[i]; } - inline uint16 GetLoginPort(uint8 i) { return loginport[i]; } - inline char* GetWorldName() { return worldname; } - inline char* GetWorldShortName() { return worldshortname; } - inline char* GetWorldAccount() { return worldaccount; } - inline char* GetWorldPassword() { return worldpassword; } - inline char* GetWorldAddress() { return worldaddress; } - inline uint8 GetDefaultStatus() { return DEFAULTSTATUS; } - inline char* GetChatAddress() { return chataddress; } - uint16 GetChatPort() { return chatport; } - bool world_locked; -private: - int listening_socket; - char loginaddress[5][255]; - uint16 loginport[5]; - uint16 chatport; - char worldname[201]; - char worldshortname[31]; - char worldaccount[31]; - char worldpassword[31]; - char worldaddress[255]; - char chataddress[255]; - uint8 DEFAULTSTATUS; - -}; diff --git a/world/queryserv.cpp b/world/queryserv.cpp index e3cf2a51f..8708b6c31 100644 --- a/world/queryserv.cpp +++ b/world/queryserv.cpp @@ -22,6 +22,7 @@ void QueryServConnection::AddConnection(std::shared_ptrOnMessage(ServerOP_QueryServGeneric, std::bind(&QueryServConnection::HandleGenericMessage, this, std::placeholders::_1, std::placeholders::_2)); connection->OnMessage(ServerOP_LFGuildUpdate, std::bind(&QueryServConnection::HandleLFGuildUpdateMessage, this, std::placeholders::_1, std::placeholders::_2)); m_streams.insert(std::make_pair(connection->GetUUID(), connection)); + m_keepalive = std::make_unique(1000, true, std::bind(&QueryServConnection::OnKeepAlive, this, std::placeholders::_1)); } void QueryServConnection::RemoveConnection(std::shared_ptr connection) @@ -51,4 +52,10 @@ bool QueryServConnection::SendPacket(ServerPacket* pack) } return true; -} \ No newline at end of file +} + +void QueryServConnection::OnKeepAlive(EQ::Timer *t) +{ + ServerPacket pack(ServerOP_KeepAlive, 0); + SendPacket(&pack); +} diff --git a/world/queryserv.h b/world/queryserv.h index f19520b7d..a02aab647 100644 --- a/world/queryserv.h +++ b/world/queryserv.h @@ -4,6 +4,7 @@ #include "../common/types.h" #include "../common/net/servertalk_server.h" #include "../common/servertalk.h" +#include "../common/event/timer.h" class QueryServConnection { @@ -14,8 +15,10 @@ public: void HandleGenericMessage(uint16_t opcode, EQ::Net::Packet &p); void HandleLFGuildUpdateMessage(uint16_t opcode, EQ::Net::Packet &p); bool SendPacket(ServerPacket* pack); + void OnKeepAlive(EQ::Timer *t); private: std::map> m_streams; + std::unique_ptr m_keepalive; }; #endif /*QueryServ_H_*/ diff --git a/world/shared_task_manager.cpp b/world/shared_task_manager.cpp index 1c539805a..50a3f5b1d 100644 --- a/world/shared_task_manager.cpp +++ b/world/shared_task_manager.cpp @@ -312,7 +312,7 @@ void SharedTaskManager::LoadSharedTaskState() shared_task_character_data = CharacterDataRepository::GetWhere( *m_database, - fmt::format("id IN ({})", fmt::join(character_ids, ",")) + fmt::format("id IN ({})", Strings::Join(character_ids, ",")) ); } @@ -1294,7 +1294,7 @@ std::vector SharedTaskManage OR (timer_group > 0 AND timer_type = {} AND timer_group = {})) AND expire_time > NOW() ORDER BY timer_type ASC LIMIT 1 ), - fmt::join(character_ids, ","), + Strings::Join(character_ids, ","), task.id, static_cast(TaskTimerType::Replay), task.replay_timer_group, @@ -1632,7 +1632,7 @@ void SharedTaskManager::AddReplayTimers(SharedTask *s) s->GetTaskData().id, s->GetTaskData().replay_timer_group, static_cast(TaskTimerType::Replay), - fmt::join(s->member_id_history, ",") + Strings::Join(s->member_id_history, ",") )); CharacterTaskTimersRepository::InsertMany(*m_database, task_timers); diff --git a/world/shared_task_world_messaging.cpp b/world/shared_task_world_messaging.cpp index a9f513592..01584c495 100644 --- a/world/shared_task_world_messaging.cpp +++ b/world/shared_task_world_messaging.cpp @@ -323,7 +323,7 @@ void SharedTaskWorldMessaging::HandleZoneMessage(ServerPacket *pack) } } - std::string player_list = fmt::format("{}", fmt::join(player_names, ", ")); + std::string player_list = fmt::format("{}", Strings::Join(player_names, ", ")); client_list.SendCharacterMessageID(buf->source_character_id, Chat::Yellow, TaskStr::MEMBERS_PRINT, {player_list}); } diff --git a/world/wguild_mgr.cpp b/world/wguild_mgr.cpp index 2768a4dd8..302dee616 100644 --- a/world/wguild_mgr.cpp +++ b/world/wguild_mgr.cpp @@ -101,7 +101,6 @@ void WorldGuildManager::ProcessZonePacket(ServerPacket *pack) { client_list.UpdateClientGuild(s->char_id, s->guild_id); //broadcast this update to any zone with a member in this guild. - //client_list.SendGuildPacket(s->guild_id, pack); //because im sick of this not working, sending it to all zones, just spends a bit more bandwidth. zoneserver_list.SendPacket(pack); diff --git a/world/wguild_mgr.h b/world/wguild_mgr.h index c992f3cf3..9bc22cb94 100644 --- a/world/wguild_mgr.h +++ b/world/wguild_mgr.h @@ -13,8 +13,6 @@ public: //called by zoneserver when it receives a guild message from zone. void ProcessZonePacket(ServerPacket *pack); - uint8 *MakeGuildMembers(uint32 guild_id, const char *prefix_name, uint32 &length); //make a guild member list packet, returns ownership of the buffer. - protected: virtual void SendGuildRefresh(uint32 guild_id, bool name, bool motd, bool rank, bool relation); virtual void SendCharRefresh(uint32 old_guild_id, uint32 guild_id, uint32 charid); diff --git a/world/world_boot.cpp b/world/world_boot.cpp index c53730be8..286d689eb 100644 --- a/world/world_boot.cpp +++ b/world/world_boot.cpp @@ -30,6 +30,8 @@ extern ZSList zoneserver_list; extern WorldConfig Config; +auto mutex = new Mutex; + void WorldBoot::GMSayHookCallBackProcessWorld(uint16 log_category, const char *func, std::string message) { // we don't want to loop up with chat messages @@ -136,9 +138,7 @@ bool WorldBoot::LoadDatabaseConnections() return false; } - /** - * Multi-tenancy: Content database - */ + // Multi-tenancy - content database if (!c->ContentDbHost.empty()) { if (!content_db.Connect( c->ContentDbHost.c_str(), @@ -153,7 +153,12 @@ bool WorldBoot::LoadDatabaseConnections() } } else { - content_db.SetMysql(database.getMySQL()); + content_db.SetMySQL(database); + // when database and content_db share the same underlying mysql connection + // it needs to be protected by a shared mutex otherwise we produce concurrency issues + // when database actions are occurring in different threads + database.SetMutex(mutex); + content_db.SetMutex(mutex); } return true; @@ -290,16 +295,16 @@ bool WorldBoot::DatabaseLoadRoutines(int argc, char **argv) } } - if (!ignore_db) { - LogInfo("Checking Database Conversions"); - database.CheckDatabaseConversions(); - } - // logging system init auto logging = LogSys.SetDatabase(&database) ->SetLogPath(path.GetLogPath()) ->LoadLogDatabaseSettings(); + if (!ignore_db) { + LogInfo("Checking Database Conversions"); + database.CheckDatabaseConversions(); + } + if (RuleB(Logging, WorldGMSayLogging)) { logging->SetGMSayHandler(&WorldBoot::GMSayHookCallBackProcessWorld); } @@ -652,3 +657,8 @@ void WorldBoot::CheckForPossibleConfigurationIssues() } } +void WorldBoot::Shutdown() +{ + safe_delete(mutex); +} + diff --git a/world/world_boot.h b/world/world_boot.h index 9e6f9b655..19af9bba7 100644 --- a/world/world_boot.h +++ b/world/world_boot.h @@ -15,6 +15,7 @@ public: static void RegisterLoginservers(); static bool DatabaseLoadRoutines(int argc, char **argv); static void CheckForPossibleConfigurationIssues(); + static void Shutdown(); }; diff --git a/world/world_config.h b/world/world_config.h index 73b618b74..ee28f4344 100644 --- a/world/world_config.h +++ b/world/world_config.h @@ -59,12 +59,6 @@ public: static void LockWorld() { if (_world_config) _world_config->Locked=true; } static void UnlockWorld() { if (_world_config) _world_config->Locked=false; } - static void DisableStats() { if (_world_config) _world_config->UpdateStats=false; } - static void EnableStats() { if (_world_config) _world_config->UpdateStats=true; } - - static void DisableLoginserver() { if (_world_config) _world_config->LoginDisabled=true; } - static void EnableLoginserver() { if (_world_config) _world_config->LoginDisabled=false; } - static void SetWorldAddress(std::string addr) { if (_world_config) _world_config->WorldAddress=addr; } static void SetLocalAddress(std::string addr) { if (_world_config) _world_config->LocalAddress=addr; } diff --git a/world/world_server_cli.cpp b/world/world_server_cli.cpp index 787c3b90e..58d022ed4 100644 --- a/world/world_server_cli.cpp +++ b/world/world_server_cli.cpp @@ -31,10 +31,13 @@ void WorldserverCLI::CommandHandler(int argc, char **argv) function_map["test:expansion"] = &WorldserverCLI::ExpansionTestCommand; function_map["test:repository"] = &WorldserverCLI::TestRepository; function_map["test:repository2"] = &WorldserverCLI::TestRepository2; + function_map["test:db-concurrency"] = &WorldserverCLI::TestDatabaseConcurrency; + function_map["test:string-benchmark"] = &WorldserverCLI::TestStringBenchmarkCommand; EQEmuCommand::HandleMenu(function_map, cmd, argc, argv); } +#include "cli/database_concurrency.cpp" #include "cli/copy_character.cpp" #include "cli/database_dump.cpp" #include "cli/database_get_schema.cpp" @@ -45,4 +48,5 @@ void WorldserverCLI::CommandHandler(int argc, char **argv) #include "cli/test_expansion.cpp" #include "cli/test_repository.cpp" #include "cli/test_repository_2.cpp" +#include "cli/test_string_benchmark.cpp" #include "cli/version.cpp" diff --git a/world/world_server_cli.h b/world/world_server_cli.h index 954c36cd1..154de6441 100644 --- a/world/world_server_cli.h +++ b/world/world_server_cli.h @@ -18,6 +18,8 @@ public: static void ExpansionTestCommand(int argc, char **argv, argh::parser &cmd, std::string &description); static void TestRepository(int argc, char **argv, argh::parser &cmd, std::string &description); static void TestRepository2(int argc, char **argv, argh::parser &cmd, std::string &description); + static void TestDatabaseConcurrency(int argc, char **argv, argh::parser &cmd, std::string &description); + static void TestStringBenchmarkCommand(int argc, char **argv, argh::parser &cmd, std::string &description); }; diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 70033d988..4cac30d86 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -120,22 +120,22 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, EQApplicationPacket **o inventory_profile.SetInventoryVersion(client_version); inventory_profile.SetGMInventory(true); // charsel can not interact with items..but, no harm in setting to full expansion support - uint32 character_id = (uint32) atoi(row[0]); + uint32 character_id = (uint32) Strings::ToInt(row[0]); uint8 has_home = 0; uint8 has_bind = 0; memset(&pp, 0, sizeof(PlayerProfile_Struct)); memset(p_character_select_entry_struct->Name, 0, sizeof(p_character_select_entry_struct->Name)); strcpy(p_character_select_entry_struct->Name, row[1]); - p_character_select_entry_struct->Class = (uint8) atoi(row[4]); - p_character_select_entry_struct->Race = (uint32) atoi(row[3]); - p_character_select_entry_struct->Level = (uint8) atoi(row[5]); + p_character_select_entry_struct->Class = (uint8) Strings::ToInt(row[4]); + p_character_select_entry_struct->Race = (uint32) Strings::ToInt(row[3]); + p_character_select_entry_struct->Level = (uint8) Strings::ToInt(row[5]); p_character_select_entry_struct->ShroudClass = p_character_select_entry_struct->Class; p_character_select_entry_struct->ShroudRace = p_character_select_entry_struct->Race; - p_character_select_entry_struct->Zone = (uint16) atoi(row[19]); + p_character_select_entry_struct->Zone = (uint16) Strings::ToInt(row[19]); p_character_select_entry_struct->Instance = 0; - p_character_select_entry_struct->Gender = (uint8) atoi(row[2]); - p_character_select_entry_struct->Face = (uint8) atoi(row[15]); + p_character_select_entry_struct->Gender = (uint8) Strings::ToInt(row[2]); + p_character_select_entry_struct->Face = (uint8) Strings::ToInt(row[15]); for (uint32 material_slot = 0; material_slot < EQ::textures::materialCount; material_slot++) { p_character_select_entry_struct->Equip[material_slot].Material = 0; @@ -148,28 +148,28 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, EQApplicationPacket **o p_character_select_entry_struct->Unknown15 = 0xFF; p_character_select_entry_struct->Unknown19 = 0xFF; - p_character_select_entry_struct->DrakkinTattoo = (uint32) atoi(row[17]); - p_character_select_entry_struct->DrakkinDetails = (uint32) atoi(row[18]); - p_character_select_entry_struct->Deity = (uint32) atoi(row[6]); + p_character_select_entry_struct->DrakkinTattoo = (uint32) Strings::ToInt(row[17]); + p_character_select_entry_struct->DrakkinDetails = (uint32) Strings::ToInt(row[18]); + p_character_select_entry_struct->Deity = (uint32) Strings::ToInt(row[6]); p_character_select_entry_struct->PrimaryIDFile = 0; // Processed Below p_character_select_entry_struct->SecondaryIDFile = 0; // Processed Below - p_character_select_entry_struct->HairColor = (uint8) atoi(row[9]); - p_character_select_entry_struct->BeardColor = (uint8) atoi(row[10]); - p_character_select_entry_struct->EyeColor1 = (uint8) atoi(row[11]); - p_character_select_entry_struct->EyeColor2 = (uint8) atoi(row[12]); - p_character_select_entry_struct->HairStyle = (uint8) atoi(row[13]); - p_character_select_entry_struct->Beard = (uint8) atoi(row[14]); + p_character_select_entry_struct->HairColor = (uint8) Strings::ToInt(row[9]); + p_character_select_entry_struct->BeardColor = (uint8) Strings::ToInt(row[10]); + p_character_select_entry_struct->EyeColor1 = (uint8) Strings::ToInt(row[11]); + p_character_select_entry_struct->EyeColor2 = (uint8) Strings::ToInt(row[12]); + p_character_select_entry_struct->HairStyle = (uint8) Strings::ToInt(row[13]); + p_character_select_entry_struct->Beard = (uint8) Strings::ToInt(row[14]); p_character_select_entry_struct->GoHome = 0; // Processed Below p_character_select_entry_struct->Tutorial = 0; // Processed Below - p_character_select_entry_struct->DrakkinHeritage = (uint32) atoi(row[16]); + p_character_select_entry_struct->DrakkinHeritage = (uint32) Strings::ToInt(row[16]); p_character_select_entry_struct->Unknown1 = 0; p_character_select_entry_struct->Enabled = 1; - p_character_select_entry_struct->LastLogin = (uint32) atoi(row[7]); // RoF2 value: 1212696584 + p_character_select_entry_struct->LastLogin = (uint32) Strings::ToInt(row[7]); // RoF2 value: 1212696584 p_character_select_entry_struct->Unknown2 = 0; if (RuleB(World, EnableReturnHomeButton)) { int now = time(nullptr); - if ((now - atoi(row[7])) >= RuleI(World, MinOfflineTimeToReturnHome)) + if ((now - Strings::ToInt(row[7])) >= RuleI(World, MinOfflineTimeToReturnHome)) p_character_select_entry_struct->GoHome = 1; } @@ -194,20 +194,20 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, EQApplicationPacket **o auto results_bind = database.QueryDatabase(character_list_query); auto bind_count = results_bind.RowCount(); for (auto row_b = results_bind.begin(); row_b != results_bind.end(); ++row_b) { - if (row_b[6] && atoi(row_b[6]) == 4) { + if (row_b[6] && Strings::ToInt(row_b[6]) == 4) { has_home = 1; // If our bind count is less than 5, we need to actually make use of this data so lets parse it if (bind_count < 5) { - pp.binds[4].zone_id = atoi(row_b[0]); - pp.binds[4].instance_id = atoi(row_b[1]); - pp.binds[4].x = atof(row_b[2]); - pp.binds[4].y = atof(row_b[3]); - pp.binds[4].z = atof(row_b[4]); - pp.binds[4].heading = atof(row_b[5]); + pp.binds[4].zone_id = Strings::ToInt(row_b[0]); + pp.binds[4].instance_id = Strings::ToInt(row_b[1]); + pp.binds[4].x = Strings::ToFloat(row_b[2]); + pp.binds[4].y = Strings::ToFloat(row_b[3]); + pp.binds[4].z = Strings::ToFloat(row_b[4]); + pp.binds[4].heading = Strings::ToFloat(row_b[5]); } } - if (row_b[6] && atoi(row_b[6]) == 0) + if (row_b[6] && Strings::ToInt(row_b[6]) == 0) has_bind = 1; } @@ -233,8 +233,8 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, EQApplicationPacket **o auto results_bind = content_db.QueryDatabase(character_list_query); for (auto row_d = results_bind.begin(); row_d != results_bind.end(); ++row_d) { /* If a bind_id is specified, make them start there */ - if (atoi(row_d[1]) != 0) { - pp.binds[4].zone_id = (uint32) atoi(row_d[1]); + if (Strings::ToInt(row_d[1]) != 0) { + pp.binds[4].zone_id = (uint32) Strings::ToInt(row_d[1]); auto z = GetZone(pp.binds[4].zone_id); if (z) { @@ -246,11 +246,11 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, EQApplicationPacket **o } /* Otherwise, use the zone and coordinates given */ else { - pp.binds[4].zone_id = (uint32) atoi(row_d[0]); - float x = atof(row_d[2]); - float y = atof(row_d[3]); - float z = atof(row_d[4]); - float heading = atof(row_d[5]); + pp.binds[4].zone_id = (uint32) Strings::ToInt(row_d[0]); + float x = Strings::ToFloat(row_d[2]); + float y = Strings::ToFloat(row_d[3]); + float z = Strings::ToFloat(row_d[4]); + float heading = Strings::ToFloat(row_d[5]); if (x == 0 && y == 0 && z == 0 && heading == 0) { auto zone = GetZone(pp.binds[4].zone_id); if (zone) { @@ -350,11 +350,11 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, EQApplicationPacket **o auto results_b = database.QueryDatabase(character_list_query); uint8 slot = 0; for (auto row_b = results_b.begin(); row_b != results_b.end(); ++row_b) { - slot = atoi(row_b[0]); - pp.item_tint.Slot[slot].Red = atoi(row_b[1]); - pp.item_tint.Slot[slot].Green = atoi(row_b[2]); - pp.item_tint.Slot[slot].Blue = atoi(row_b[3]); - pp.item_tint.Slot[slot].UseTint = atoi(row_b[4]); + slot = Strings::ToInt(row_b[0]); + pp.item_tint.Slot[slot].Red = Strings::ToInt(row_b[1]); + pp.item_tint.Slot[slot].Green = Strings::ToInt(row_b[2]); + pp.item_tint.Slot[slot].Blue = Strings::ToInt(row_b[3]); + pp.item_tint.Slot[slot].UseTint = Strings::ToInt(row_b[4]); } if (GetCharSelInventory(account_id, p_character_select_entry_struct->Name, &inventory_profile)) { @@ -380,7 +380,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, EQApplicationPacket **o p_character_select_entry_struct->Equip[matslot].Material = item_id_file; } else { if (strlen(item->IDFile) > 2) { - item_id_file = atoi(&item->IDFile[2]); + item_id_file = Strings::ToInt(&item->IDFile[2]); p_character_select_entry_struct->Equip[matslot].Material = item_id_file; } } @@ -439,12 +439,12 @@ int WorldDatabase::MoveCharacterToBind(int character_id, uint8 bind_number) int zone_id, instance_id; double x, y, z, heading; for (auto row = results.begin(); row != results.end(); ++row) { - zone_id = atoi(row[0]); - instance_id = atoi(row[1]); - x = atof(row[2]); - y = atof(row[3]); - z = atof(row[4]); - heading = atof(row[5]); + zone_id = Strings::ToInt(row[0]); + instance_id = Strings::ToInt(row[1]); + x = Strings::ToFloat(row[2]); + y = Strings::ToFloat(row[3]); + z = Strings::ToFloat(row[4]); + heading = Strings::ToFloat(row[5]); } query = fmt::format( @@ -596,16 +596,16 @@ bool WorldDatabase::GetStartZone( else { LogInfo("Found starting location in start_zones"); auto row = results.begin(); - pp->x = atof(row[0]); - pp->y = atof(row[1]); - pp->z = atof(row[2]); - pp->heading = atof(row[3]); - pp->zone_id = atoi(row[4]); - pp->binds[0].zone_id = atoi(row[5]); - pp->binds[0].x = atof(row[6]); - pp->binds[0].y = atof(row[7]); - pp->binds[0].z = atof(row[8]); - pp->binds[0].heading = atof(row[3]); + pp->x = Strings::ToFloat(row[0]); + pp->y = Strings::ToFloat(row[1]); + pp->z = Strings::ToFloat(row[2]); + pp->heading = Strings::ToFloat(row[3]); + pp->zone_id = Strings::ToInt(row[4]); + pp->binds[0].zone_id = Strings::ToInt(row[5]); + pp->binds[0].x = Strings::ToFloat(row[6]); + pp->binds[0].y = Strings::ToFloat(row[7]); + pp->binds[0].z = Strings::ToFloat(row[8]); + pp->binds[0].heading = Strings::ToFloat(row[3]); } if ( @@ -792,7 +792,7 @@ bool WorldDatabase::GetCharacterLevel(const char *name, int &level) return false; auto row = results.begin(); - level = atoi(row[0]); + level = Strings::ToInt(row[0]); return true; } @@ -808,21 +808,21 @@ bool WorldDatabase::LoadCharacterCreateAllocations() for (auto row = results.begin(); row != results.end(); ++row) { RaceClassAllocation allocate; - allocate.Index = atoi(row[0]); - allocate.BaseStats[0] = atoi(row[1]); - allocate.BaseStats[3] = atoi(row[2]); - allocate.BaseStats[1] = atoi(row[3]); - allocate.BaseStats[2] = atoi(row[4]); - allocate.BaseStats[4] = atoi(row[5]); - allocate.BaseStats[5] = atoi(row[6]); - allocate.BaseStats[6] = atoi(row[7]); - allocate.DefaultPointAllocation[0] = atoi(row[8]); - allocate.DefaultPointAllocation[3] = atoi(row[9]); - allocate.DefaultPointAllocation[1] = atoi(row[10]); - allocate.DefaultPointAllocation[2] = atoi(row[11]); - allocate.DefaultPointAllocation[4] = atoi(row[12]); - allocate.DefaultPointAllocation[5] = atoi(row[13]); - allocate.DefaultPointAllocation[6] = atoi(row[14]); + allocate.Index = Strings::ToInt(row[0]); + allocate.BaseStats[0] = Strings::ToInt(row[1]); + allocate.BaseStats[3] = Strings::ToInt(row[2]); + allocate.BaseStats[1] = Strings::ToInt(row[3]); + allocate.BaseStats[2] = Strings::ToInt(row[4]); + allocate.BaseStats[4] = Strings::ToInt(row[5]); + allocate.BaseStats[5] = Strings::ToInt(row[6]); + allocate.BaseStats[6] = Strings::ToInt(row[7]); + allocate.DefaultPointAllocation[0] = Strings::ToInt(row[8]); + allocate.DefaultPointAllocation[3] = Strings::ToInt(row[9]); + allocate.DefaultPointAllocation[1] = Strings::ToInt(row[10]); + allocate.DefaultPointAllocation[2] = Strings::ToInt(row[11]); + allocate.DefaultPointAllocation[4] = Strings::ToInt(row[12]); + allocate.DefaultPointAllocation[5] = Strings::ToInt(row[13]); + allocate.DefaultPointAllocation[6] = Strings::ToInt(row[14]); character_create_allocations.push_back(allocate); } @@ -841,12 +841,12 @@ bool WorldDatabase::LoadCharacterCreateCombos() for (auto row = results.begin(); row != results.end(); ++row) { RaceClassCombos combo; - combo.AllocationIndex = atoi(row[0]); - combo.Race = atoi(row[1]); - combo.Class = atoi(row[2]); - combo.Deity = atoi(row[3]); - combo.Zone = atoi(row[4]); - combo.ExpansionRequired = atoi(row[5]); + combo.AllocationIndex = Strings::ToInt(row[0]); + combo.Race = Strings::ToInt(row[1]); + combo.Class = Strings::ToInt(row[2]); + combo.Deity = Strings::ToInt(row[3]); + combo.Zone = Strings::ToInt(row[4]); + combo.ExpansionRequired = Strings::ToInt(row[5]); character_create_race_class_combos.push_back(combo); } @@ -901,7 +901,7 @@ bool WorldDatabase::GetCharSelInventory(uint32 account_id, char *name, EQ::Inven return false; for (auto row = results.begin(); row != results.end(); ++row) { - int16 slot_id = atoi(row[0]); + int16 slot_id = Strings::ToInt(row[0]); switch (slot_id) { case EQ::invslot::slotFace: @@ -916,22 +916,22 @@ bool WorldDatabase::GetCharSelInventory(uint32 account_id, char *name, EQ::Inven break; } - uint32 item_id = atoi(row[1]); - int8 charges = atoi(row[2]); - uint32 color = atoul(row[3]); + uint32 item_id = Strings::ToInt(row[1]); + int8 charges = Strings::ToInt(row[2]); + uint32 color = Strings::ToUnsignedInt(row[3]); uint32 aug[EQ::invaug::SOCKET_COUNT]; - aug[0] = (uint32)atoi(row[4]); - aug[1] = (uint32)atoi(row[5]); - aug[2] = (uint32)atoi(row[6]); - aug[3] = (uint32)atoi(row[7]); - aug[4] = (uint32)atoi(row[8]); - aug[5] = (uint32)atoi(row[9]); + aug[0] = (uint32)Strings::ToInt(row[4]); + aug[1] = (uint32)Strings::ToInt(row[5]); + aug[2] = (uint32)Strings::ToInt(row[6]); + aug[3] = (uint32)Strings::ToInt(row[7]); + aug[4] = (uint32)Strings::ToInt(row[8]); + aug[5] = (uint32)Strings::ToInt(row[9]); - bool instnodrop = ((row[10] && (uint16)atoi(row[10])) ? true : false); - uint32 ornament_icon = (uint32)atoul(row[12]); - uint32 ornament_idfile = (uint32)atoul(row[13]); - uint32 ornament_hero_model = (uint32)atoul(row[14]); + bool instnodrop = ((row[10] && (uint16)Strings::ToInt(row[10])) ? true : false); + uint32 ornament_icon = (uint32)Strings::ToUnsignedInt(row[12]); + uint32 ornament_idfile = (uint32)Strings::ToUnsignedInt(row[13]); + uint32 ornament_hero_model = (uint32)Strings::ToUnsignedInt(row[14]); const EQ::ItemData *item = content_db.GetItem(item_id); if (!item) diff --git a/world/worlddb.h b/world/worlddb.h index d5bfdf3f5..2b3d7ea07 100644 --- a/world/worlddb.h +++ b/world/worlddb.h @@ -40,12 +40,6 @@ public: bool LoadCharacterCreateAllocations(); bool LoadCharacterCreateCombos(); - bool StoreCharacter( - uint32 account_id, - PlayerProfile_Struct *p_player_profile_struct, - EQ::InventoryProfile *p_inventory_profile - ); - private: void SetTitaniumDefaultStartZone(PlayerProfile_Struct* in_pp, CharCreate_Struct* in_cc); void SetSoFDefaultStartZone(PlayerProfile_Struct* in_pp, CharCreate_Struct* in_cc); diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index 0edd6e88f..a23d0bec8 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -43,6 +43,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../common/shared_tasks.h" #include "shared_task_manager.h" #include "../common/content/world_content_service.h" +#include "../common/repositories/player_event_logs_repository.h" +#include "../common/events/player_event_logs.h" extern ClientList client_list; extern GroupLFPList LFPGroupList; @@ -72,7 +74,6 @@ ZoneServer::ZoneServer(std::shared_ptr in_c zone_os_process_id = 0; client_port = 0; is_booting_up = false; - is_authenticated = false; is_static_zone = false; zone_player_count = 0; @@ -141,20 +142,6 @@ bool ZoneServer::SetZone(uint32 in_zone_id, uint32 in_instance_id, bool in_is_st return true; } -void ZoneServer::LSShutDownUpdate(uint32 zone_id) { - if (WorldConfig::get()->UpdateStats) { - auto pack = new ServerPacket; - pack->opcode = ServerOP_LSZoneShutdown; - pack->size = sizeof(ZoneShutdown_Struct); - pack->pBuffer = new uchar[pack->size]; - memset(pack->pBuffer, 0, pack->size); - auto zsd = (ZoneShutdown_Struct*) pack->pBuffer; - zsd->zone = zone_id ? zone_id : GetPrevZoneID(); - zsd->zone_wid = GetID(); - loginserverlist.SendPacket(pack); - safe_delete(pack); - } -} void ZoneServer::LSBootUpdate(uint32 zone_id, uint32 instanceid, bool startup) { if (WorldConfig::get()->UpdateStats) { auto pack = new ServerPacket; @@ -369,6 +356,30 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { zoneserver_list.SendPacket(pack); break; } + case ServerOP_PlayerEvent: { + auto n = PlayerEvent::PlayerEventContainer{}; + auto s = (ServerSendPlayerEvent_Struct *) pack->pBuffer; + EQ::Util::MemoryStreamReader ss(s->cereal_data, s->cereal_size); + cereal::BinaryInputArchive archive(ss); + archive(n); + + // by default process events in world + // if set, process events in queryserver + // if you want to offload event recording to a dedicated QS instance + if (!RuleB(Logging, PlayerEventsQSProcess)) { + player_event_logs.AddToQueue(n.player_event_log); + } + else { + QSLink.SendPacket(pack); + } + + // if discord enabled for event, ship to UCS to process + if (player_event_logs.IsEventDiscordEnabled(n.player_event_log.event_type_id)) { + UCSLink.SendPacket(pack); + } + + break; + } case ServerOP_DetailsChange: { if (pack->size != sizeof(ServerRaidGeneralAction_Struct)) { break; @@ -1306,6 +1317,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { case ServerOP_ItemStatus: case ServerOP_KickPlayer: case ServerOP_KillPlayer: + case ServerOP_OOCMute: case ServerOP_OOZGroupMessage: case ServerOP_Petition: case ServerOP_RaidGroupSay: @@ -1356,6 +1368,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { zoneserver_list.SendPacket(pack); UCSLink.SendPacket(pack); LogSys.LoadLogDatabaseSettings(); + player_event_logs.ReloadSettings(); break; } case ServerOP_ReloadTasks: { diff --git a/world/zoneserver.h b/world/zoneserver.h index f7b5ea3ac..cc490bdd1 100644 --- a/world/zoneserver.h +++ b/world/zoneserver.h @@ -46,7 +46,6 @@ public: void IncomingClient(Client* client); void LSBootUpdate(uint32 zone_id, uint32 instance_id = 0, bool startup = false); void LSSleepUpdate(uint32 zone_id); - void LSShutDownUpdate(uint32 zone_id); uint32 GetPrevZoneID() { return zone_server_previous_zone_id; } void ChangeWID(uint32 iCharID, uint32 iWID); void SendGroupIDs(); @@ -74,7 +73,6 @@ public: std::string GetUUID() const { return tcpc->GetUUID(); } inline uint32 GetInstanceID() { return instance_id; } - inline void SetInstanceID(uint32 i) { instance_id = i; } inline uint32 GetZoneOSProcessID() { return zone_os_process_id; } @@ -88,7 +86,6 @@ private: uint16 client_port; bool is_booting_up; bool is_static_zone; - bool is_authenticated; uint32 zone_player_count; char compiled[25]; char zone_name[32]; diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index 90a3b350b..d5ad9a67e 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -11,6 +11,7 @@ SET(zone_sources beacon.cpp bonuses.cpp bot.cpp + bot_raid.cpp bot_command.cpp bot_database.cpp botspellsai.cpp @@ -97,9 +98,7 @@ SET(zone_sources mob_appearance.cpp mob_movement_manager.cpp mob_info.cpp - mod_functions.cpp npc.cpp - npc_ai.cpp npc_scale_manager.cpp object.cpp oriented_bounding_box.cpp @@ -237,7 +236,6 @@ SET(zone_headers mob.h mob_movement_manager.h npc.h - npc_ai.h npc_scale_manager.h object.h oriented_bounding_box.h @@ -256,7 +254,6 @@ SET(zone_headers quest_parser_collection.h raids.h raycast_mesh.h - skills.h shared_task_zone_messaging.h spawn2.cpp spawn2.h diff --git a/zone/aa.cpp b/zone/aa.cpp index f3ee4e0ee..66b5f7b0f 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -23,6 +23,7 @@ Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) #include "../common/races.h" #include "../common/spdat.h" #include "../common/strings.h" +#include "../common/events/player_event_logs.h" #include "aa.h" #include "client.h" #include "corpse.h" @@ -35,9 +36,11 @@ Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) #include "titles.h" #include "zonedb.h" #include "../common/zone_store.h" +#include "worldserver.h" #include "bot.h" +extern WorldServer worldserver; extern QueryServ* QServ; void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, uint32 duration_override, bool followme, bool sticktarg, uint16 *eye_id) { @@ -53,9 +56,11 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u // yep, even these need pet power! int act_power = 0; - if (IsClient()) { - act_power = CastToClient()->GetFocusEffect(focusPetPower, spell_id); - act_power = CastToClient()->mod_pet_power(act_power, spell_id); + if (IsOfClientBot()) { + act_power = GetFocusEffect(focusPetPower, spell_id); + if (IsClient()) { + act_power = CastToClient()->GetFocusEffect(focusPetPower, spell_id); + } } PetRecord record; @@ -297,15 +302,6 @@ void Mob::WakeTheDead(uint16 spell_id, Corpse *corpse_to_use, Mob *target, uint3 return; } - /* TODO: Does WTD use pet focus? - int act_power = 0; - - if (IsClient()) { - act_power = CastToClient()->GetFocusEffect(focusPetPower, spell_id); - act_power = CastToClient()->mod_pet_power(act_power, spell_id); - } - */ - SwarmPet_Struct pet; pet.count = 1; pet.duration = 1; @@ -827,7 +823,7 @@ void Client::InspectBuffs(Client* Inspector, int Rank) uint32 buff_count = GetMaxTotalSlots(); uint32 packet_index = 0; for (uint32 i = 0; i < buff_count; i++) { - if (buffs[i].spellid == SPELL_UNKNOWN) + if (!IsValidSpell(buffs[i].spellid)) continue; ib->spell_id[packet_index] = buffs[i].spellid; if (Rank > 1) @@ -1178,6 +1174,17 @@ void Client::FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost SendAlternateAdvancementPoints(); SendAlternateAdvancementStats(); + if (player_event_logs.IsEventEnabled(PlayerEvent::AA_PURCHASE)) { + auto e = PlayerEvent::AAPurchasedEvent{ + .aa_id = rank->id, + .aa_cost = cost, + .aa_previous_id = rank->prev_id, + .aa_next_id = rank->next_id + }; + + RecordPlayerEventLog(PlayerEvent::AA_PURCHASE, e); + } + if (rank->prev) { MessageString( Chat::Yellow, @@ -1223,15 +1230,17 @@ void Client::FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost } } - const auto export_string = fmt::format( - "{} {} {} {}", - cost, - rank->id, - rank->prev_id, - rank->next_id - ); + if (parse->PlayerHasQuestSub(EVENT_AA_BUY)) { + const auto& export_string = fmt::format( + "{} {} {} {}", + cost, + rank->id, + rank->prev_id, + rank->next_id + ); - parse->EventPlayer(EVENT_AA_BUY, this, export_string, 0); + parse->EventPlayer(EVENT_AA_BUY, this, export_string, 0); + } CalcBonuses(); @@ -1439,9 +1448,9 @@ bool ZoneDatabase::LoadAlternateAdvancement(Client *c) { int i = 0; for(auto row = results.begin(); row != results.end(); ++row) { - uint32 aa = atoi(row[0]); - uint32 value = atoi(row[1]); - uint32 charges = atoi(row[2]); + uint32 aa = Strings::ToInt(row[0]); + uint32 value = Strings::ToInt(row[1]); + uint32 charges = Strings::ToInt(row[2]); auto rank = zone->GetAlternateAdvancementRank(aa); if(!rank) { @@ -1766,20 +1775,20 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_mapid = atoi(row[0]); + ability->id = Strings::ToInt(row[0]); ability->name = row[1]; - ability->category = atoi(row[2]); + ability->category = Strings::ToInt(row[2]); //EQ client has classes left shifted by one bit for some odd reason - ability->classes = atoi(row[3]) << 1; - ability->races = atoi(row[4]); - ability->deities = atoi(row[5]); - ability->drakkin_heritage = atoi(row[6]); - ability->status = atoi(row[7]); - ability->type = atoi(row[8]); - ability->charges = atoi(row[9]); - ability->grant_only = atoi(row[10]) != 0 ? true : false; - ability->reset_on_death = atoi(row[11]) != 0 ? true : false; - ability->first_rank_id = atoi(row[12]); + ability->classes = Strings::ToInt(row[3]) << 1; + ability->races = Strings::ToInt(row[4]); + ability->deities = Strings::ToInt(row[5]); + ability->drakkin_heritage = Strings::ToInt(row[6]); + ability->status = Strings::ToInt(row[7]); + ability->type = Strings::ToInt(row[8]); + ability->charges = Strings::ToInt(row[9]); + ability->grant_only = Strings::ToInt(row[10]) != 0 ? true : false; + ability->reset_on_death = Strings::ToInt(row[11]) != 0 ? true : false; + ability->first_rank_id = Strings::ToInt(row[12]); ability->first = nullptr; abilities[ability->id] = std::unique_ptr(ability); @@ -1805,18 +1814,18 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_mapid = atoi(row[0]); - rank->upper_hotkey_sid = atoi(row[1]); - rank->lower_hotkey_sid = atoi(row[2]); - rank->title_sid = atoi(row[3]); - rank->desc_sid = atoi(row[4]); - rank->cost = atoi(row[5]); - rank->level_req = atoi(row[6]); - rank->spell = atoi(row[7]); - rank->spell_type = atoi(row[8]); - rank->recast_time = atoi(row[9]); - rank->next_id = atoi(row[10]); - rank->expansion = atoi(row[11]); + rank->id = Strings::ToInt(row[0]); + rank->upper_hotkey_sid = Strings::ToInt(row[1]); + rank->lower_hotkey_sid = Strings::ToInt(row[2]); + rank->title_sid = Strings::ToInt(row[3]); + rank->desc_sid = Strings::ToInt(row[4]); + rank->cost = Strings::ToInt(row[5]); + rank->level_req = Strings::ToInt(row[6]); + rank->spell = Strings::ToInt(row[7]); + rank->spell_type = Strings::ToInt(row[8]); + rank->recast_time = Strings::ToInt(row[9]); + rank->next_id = Strings::ToInt(row[10]); + rank->expansion = Strings::ToInt(row[11]); rank->base_ability = nullptr; rank->total_cost = 0; rank->prev_id = -1; @@ -1837,11 +1846,11 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_mapGetName()); - return mod_will_aggro(mob, this); + return true; } } else { if ( @@ -548,7 +548,7 @@ bool Mob::CheckWillAggro(Mob *mob) { ) { if(CheckLosFN(mob)) { LogAggro("Check aggro for [{}] target [{}]", GetName(), mob->GetName()); - return mod_will_aggro(mob, this); + return true; } } } @@ -1491,19 +1491,16 @@ bool Mob::PassCharismaCheck(Mob* caster, uint16 spell_id) { resist_check = ResistSpell(spells[spell_id].resist_type, spell_id, caster, false,0, false, true); //2: The mob makes a resistance check against the charm - if (resist_check == 100) + if (resist_check == 100) { return true; - - else - { - if (caster->IsClient()) - { + } else { + if (caster->IsOfClientBot()) { //3: At maxed ability, Total Domination has a 50% chance of preventing the charm break that otherwise would have occurred. int16 TotalDominationBonus = caster->aabonuses.CharmBreakChance + caster->spellbonuses.CharmBreakChance + caster->itembonuses.CharmBreakChance; - if (zone->random.Int(0, 99) < TotalDominationBonus) + if (zone->random.Int(0, 99) < TotalDominationBonus) { return true; - + } } } } diff --git a/zone/attack.cpp b/zone/attack.cpp index 5d6d2350b..2f408e612 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -25,6 +25,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../common/strings.h" #include "../common/data_verification.h" #include "../common/misc_functions.h" +#include "../common/events/player_event_logs.h" #include "queryserv.h" #include "quest_parser_collection.h" #include "string_ids.h" @@ -248,8 +249,9 @@ int Mob::compute_defense() { int defense = GetSkill(EQ::skills::SkillDefense) * 400 / 225; defense += (8000 * (GetAGI() - 40)) / 36000; - if (IsClient()) - defense += CastToClient()->GetHeroicAGI() / 10; + if (IsOfClientBot()) { + defense += GetHeroicAGI() * RuleR(Character, HeroicAgilityMultiplier) / 10; + } //516 SE_AC_Mitigation_Max_Percent auto ac_bonus = itembonuses.AC_Mitigation_Max_Percent + aabonuses.AC_Mitigation_Max_Percent + spellbonuses.AC_Mitigation_Max_Percent; @@ -317,8 +319,9 @@ bool Mob::CheckHitChance(Mob* other, DamageHitInfo &hit) Mob *defender = this; Log(Logs::Detail, Logs::Attack, "CheckHitChance(%s) attacked by %s", defender->GetName(), attacker->GetName()); - if (defender->IsClient() && defender->CastToClient()->IsSitting()) + if (defender->IsOfClientBotMerc() && defender->IsSitting()) { return true; + } auto avoidance = defender->GetTotalDefense(); if (avoidance == -1) // some sort of auto avoid disc @@ -871,22 +874,23 @@ int Mob::ACSum(bool skip_caps) int ac = 0; // this should be base AC whenever shrouds come around ac += itembonuses.AC; // items + food + tribute int shield_ac = 0; - if (HasShieldEquiped() && IsClient()) { - auto client = CastToClient(); - auto inst = client->GetInv().GetItem(EQ::invslot::slotSecondary); + if (HasShieldEquiped() && IsOfClientBot()) { + auto inst = (IsClient()) ? GetInv().GetItem(EQ::invslot::slotSecondary) : CastToBot()->GetBotItem(EQ::invslot::slotSecondary); if (inst) { - if (inst->GetItemRecommendedLevel(true) <= GetLevel()) + if (inst->GetItemRecommendedLevel(true) <= GetLevel()) { shield_ac = inst->GetItemArmorClass(true); - else - shield_ac = client->CalcRecommendedLevelBonus(GetLevel(), inst->GetItemRecommendedLevel(true), inst->GetItemArmorClass(true)); + } else { + shield_ac = CalcRecommendedLevelBonus(GetLevel(), inst->GetItemRecommendedLevel(true), inst->GetItemArmorClass(true)); + } } - shield_ac += client->GetHeroicSTR() / 10; + shield_ac += GetHeroicSTR() * RuleR(Character, HeroicStrengthMultiplier) / 10; } // EQ math ac = (ac * 4) / 3; // anti-twink - if (!skip_caps && IsClient() && GetLevel() < RuleI(Combat, LevelToStopACTwinkControl)) + if (!skip_caps && IsOfClientBot() && GetLevel() < RuleI(Combat, LevelToStopACTwinkControl)) { ac = std::min(ac, 25 + 6 * GetLevel()); + } ac = std::max(0, ac + GetClassRaceACBonus()); if (IsNPC()) { // This is the developer tweaked number @@ -915,7 +919,7 @@ int Mob::ACSum(bool skip_caps) if (ac < 0) ac = 0; - if (!skip_caps && (IsClient() || IsBot())) { + if (!skip_caps && IsOfClientBot()) { auto softcap = GetACSoftcap(); auto returns = GetSoftcapReturns(); int total_aclimitmod = aabonuses.CombatStability + itembonuses.CombatStability + spellbonuses.CombatStability; @@ -1001,8 +1005,9 @@ double Mob::RollD20(int offense, int mitigation) 1.6, 1.7, 1.8, 1.9, 2.0 }; - if (IsClient() && CastToClient()->IsSitting()) + if (IsOfClientBotMerc() && IsSitting()) { return mods[19]; + } auto atk_roll = zone->random.Roll0(offense + 5); auto def_roll = zone->random.Roll0(mitigation + 5); @@ -1446,12 +1451,15 @@ void Mob::DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts, boo } if (IsBot()) { - const auto export_string = fmt::format( - "{} {}", - hit.skill, - GetSkill(hit.skill) - ); - parse->EventBot(EVENT_USE_SKILL, CastToBot(), nullptr, export_string, 0); + if (parse->BotHasQuestSub(EVENT_USE_SKILL)) { + const auto& export_string = fmt::format( + "{} {}", + hit.skill, + GetSkill(hit.skill) + ); + + parse->EventBot(EVENT_USE_SKILL, CastToBot(), nullptr, export_string, 0); + } } } } @@ -1686,8 +1694,9 @@ void Client::Damage(Mob* other, int64 damage, uint16 spell_id, EQ::skills::Skill if (dead || IsCorpse()) return; - if (spell_id == 0) + if (!IsValidSpell(spell_id)) { spell_id = SPELL_UNKNOWN; + } // cut all PVP spell damage to 2/3 // Blasting ourselfs is considered PvP @@ -1711,8 +1720,9 @@ void Client::Damage(Mob* other, int64 damage, uint16 spell_id, EQ::skills::Skill if (damage > 0) { - if (spell_id == SPELL_UNKNOWN) + if (!IsValidSpell(spell_id)) { CheckIncreaseSkill(EQ::skills::SkillDefense, other, -15); + } } } @@ -1730,22 +1740,24 @@ bool Client::Death(Mob* killerMob, int64 damage, uint16 spell, EQ::skills::Skill spell = SPELL_UNKNOWN; } - auto export_string = fmt::format( - "{} {} {} {}", - killerMob ? killerMob->GetID() : 0, - damage, - spell, - static_cast(attack_skill) - ); + if (parse->PlayerHasQuestSub(EVENT_DEATH)) { + const auto& export_string = fmt::format( + "{} {} {} {}", + killerMob ? killerMob->GetID() : 0, + damage, + spell, + static_cast(attack_skill) + ); - if (parse->EventPlayer(EVENT_DEATH, this, export_string, 0) != 0) { - if (GetHP() < 0) { - SetHP(0); + if (parse->EventPlayer(EVENT_DEATH, this, export_string, 0) != 0) { + if (GetHP() < 0) { + SetHP(0); + } + return false; } - return false; } - if (killerMob && (killerMob->IsClient() || killerMob->IsBot()) && (spell != SPELL_UNKNOWN) && damage > 0) { + if (killerMob && killerMob->IsOfClientBot() && IsValidSpell(spell) && damage > 0) { char val1[20] = { 0 }; entity_list.MessageCloseString( @@ -1784,8 +1796,8 @@ bool Client::Death(Mob* killerMob, int64 damage, uint16 spell, EQ::skills::Skill d->killer_id = killerMob ? killerMob->GetID() : 0; d->corpseid = GetID(); d->bindzoneid = m_pp.binds[0].zone_id; - d->spell_id = spell == SPELL_UNKNOWN ? 0xffffffff : spell; - d->attack_skill = spell != SPELL_UNKNOWN ? 0xe7 : attack_skill; + d->spell_id = IsValidSpell(spell) ? spell : 0xffffffff; + d->attack_skill = IsValidSpell(spell) ? 0xe7 : attack_skill; d->damage = damage; app.priority = 6; entity_list.QueueClients(this, &app); @@ -1810,9 +1822,9 @@ bool Client::Death(Mob* killerMob, int64 damage, uint16 spell, EQ::skills::Skill if (killerMob) { if (killerMob->IsNPC()) { - parse->EventNPC(EVENT_SLAY, killerMob->CastToNPC(), this, "", 0); - - mod_client_death_npc(killerMob); + if (parse->HasQuestSub(killerMob->GetNPCTypeID(), EVENT_SLAY)) { + parse->EventNPC(EVENT_SLAY, killerMob->CastToNPC(), this, "", 0); + } auto emote_id = killerMob->GetEmoteID(); if (emote_id) { @@ -1821,7 +1833,10 @@ bool Client::Death(Mob* killerMob, int64 damage, uint16 spell, EQ::skills::Skill killerMob->TrySpellOnKill(killed_level, spell); } else if (killerMob->IsBot()) { - parse->EventBot(EVENT_SLAY, killerMob->CastToBot(), this, "", 0); + if (parse->BotHasQuestSub(EVENT_SLAY)) { + parse->EventBot(EVENT_SLAY, killerMob->CastToBot(), this, "", 0); + } + killerMob->TrySpellOnKill(killed_level, spell); } @@ -1840,9 +1855,6 @@ bool Client::Death(Mob* killerMob, int64 damage, uint16 spell, EQ::skills::Skill killerMob->CastToClient()->SetDueling(false); killerMob->CastToClient()->SetDuelTarget(0); entity_list.DuelMessage(killerMob, this, false); - - mod_client_death_duel(killerMob); - } else { //otherwise, we just died, end the duel. @@ -1913,7 +1925,7 @@ bool Client::Death(Mob* killerMob, int64 damage, uint16 spell, EQ::skills::Skill } } - if (spell != SPELL_UNKNOWN) { + if (IsValidSpell(spell)) { uint32 buff_count = GetMaxTotalSlots(); for (uint16 buffIt = 0; buffIt < buff_count; buffIt++) { if (buffs[buffIt].spellid == spell && buffs[buffIt].client) { @@ -1967,10 +1979,10 @@ bool Client::Death(Mob* killerMob, int64 damage, uint16 spell, EQ::skills::Skill database.GetVariable("ServerType", tmp); if (tmp[0] == '1' && tmp[1] == '\0' && killerMob && killerMob->IsClient()) { database.GetVariable("PvPreward", tmp); - auto reward = atoi(tmp.c_str()); + auto reward = Strings::ToInt(tmp.c_str()); if (reward == 3) { database.GetVariable("PvPitem", tmp); - auto pvp_item_id = atoi(tmp.c_str()); + auto pvp_item_id = Strings::ToInt(tmp.c_str()); const auto* item = database.GetItem(pvp_item_id); if (item) { new_corpse->SetPlayerKillItemID(pvp_item_id); @@ -2060,8 +2072,33 @@ bool Client::Death(Mob* killerMob, int64 damage, uint16 spell, EQ::skills::Skill QServ->PlayerLogEvent(Player_Log_Deaths, CharacterID(), event_desc); } - std::vector args = { new_corpse }; - parse->EventPlayer(EVENT_DEATH_COMPLETE, this, export_string, 0, &args); + if (player_event_logs.IsEventEnabled(PlayerEvent::DEATH)) { + auto e = PlayerEvent::DeathEvent{ + .killer_id = killerMob ? static_cast(killerMob->GetID()) : static_cast(0), + .killer_name = killerMob ? killerMob->GetCleanName() : "No Killer", + .damage = damage, + .spell_id = spell, + .spell_name = IsValidSpell(spell) ? spells[spell].name : "No Spell", + .skill_id = static_cast(attack_skill), + .skill_name = !EQ::skills::GetSkillName(attack_skill).empty() ? EQ::skills::GetSkillName(attack_skill) : "No Skill", + }; + + RecordPlayerEventLog(PlayerEvent::DEATH, e); + } + + if (parse->PlayerHasQuestSub(EVENT_DEATH_COMPLETE)) { + const auto& export_string = fmt::format( + "{} {} {} {}", + killerMob ? killerMob->GetID() : 0, + damage, + spell, + static_cast(attack_skill) + ); + + std::vector args = { new_corpse }; + + parse->EventPlayer(EVENT_DEATH_COMPLETE, this, export_string, 0, &args); + } return true; } //SYNC WITH: tune.cpp, mob.h TuneNPCAttack @@ -2220,8 +2257,6 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool otherlevel = otherlevel ? otherlevel : 1; mylevel = mylevel ? mylevel : 1; - //damage = mod_npc_damage(damage, skillinuse, Hand, weapon, other); - my_hit.base_damage = GetBaseDamage() + eleBane; my_hit.min_damage = GetMinDamage(); int32 hate = my_hit.base_damage + my_hit.min_damage; @@ -2300,8 +2335,11 @@ void NPC::Damage(Mob* other, int64 damage, uint16 spell_id, EQ::skills::SkillTyp //handle EVENT_ATTACK. Resets after we have not been attacked for 12 seconds if (attacked_timer.Check()) { - LogCombat("Triggering EVENT_ATTACK due to attack by [{}]", other ? other->GetName() : "nullptr"); - parse->EventNPC(EVENT_ATTACK, this, other, "", 0); + if (parse->HasQuestSub(GetNPCTypeID(), EVENT_ATTACK)) { + LogCombat("Triggering EVENT_ATTACK due to attack by [{}]", other ? other->GetName() : "nullptr"); + + parse->EventNPC(EVENT_ATTACK, this, other, "", 0); + } } attacked_timer.Start(CombatEventTimer_expire); @@ -2342,33 +2380,45 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy ((killer_mob) ? (killer_mob->GetName()) : ("[nullptr]")), damage, spell, attack_skill); Mob *oos = killer_mob ? killer_mob->GetOwnerOrSelf() : nullptr; - auto export_string = fmt::format( - "{} {} {} {}", - killer_mob ? killer_mob->GetID() : 0, - damage, - spell, - static_cast(attack_skill) - ); if (IsNPC()) { - if (parse->EventNPC(EVENT_DEATH, this, oos, export_string, 0) != 0) { - if (GetHP() < 0) { - SetHP(0); - } + if (parse->HasQuestSub(GetNPCTypeID(), EVENT_DEATH)) { + const auto& export_string = fmt::format( + "{} {} {} {}", + killer_mob ? killer_mob->GetID() : 0, + damage, + spell, + static_cast(attack_skill) + ); - return false; + if (parse->EventNPC(EVENT_DEATH, this, oos, export_string, 0) != 0) { + if (GetHP() < 0) { + SetHP(0); + } + + return false; + } } } else if (IsBot()) { - if (parse->EventBot(EVENT_DEATH, CastToBot(), oos, export_string, 0) != 0) { - if (GetHP() < 0) { - SetHP(0); - } + if (parse->BotHasQuestSub(EVENT_DEATH)) { + const auto& export_string = fmt::format( + "{} {} {} {}", + killer_mob ? killer_mob->GetID() : 0, + damage, + spell, + static_cast(attack_skill) + ); + if (parse->EventBot(EVENT_DEATH, CastToBot(), oos, export_string, 0) != 0) { + if (GetHP() < 0) { + SetHP(0); + } - return false; + return false; + } } } - if (killer_mob && (killer_mob->IsClient() || killer_mob->IsBot()) && (spell != SPELL_UNKNOWN) && damage > 0) { + if (killer_mob && killer_mob->IsOfClientBot() && IsValidSpell(spell) && damage > 0) { char val1[20] = { 0 }; entity_list.MessageCloseString( @@ -2490,7 +2540,6 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy Raid *kr = entity_list.GetRaidByClient(give_exp_client); int64 finalxp = give_exp_client->GetExperienceForKill(this); - finalxp = give_exp_client->mod_client_xp(finalxp, this); // handle task credit on behalf of the killer if (RuleB(TaskSystem, EnableTaskSystem)) { @@ -2513,13 +2562,15 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy for (int i = 0; i < MAX_RAID_MEMBERS; i++) { if (kr->members[i].member != nullptr && kr->members[i].member->IsClient()) { // If Group Member is Client Client *c = kr->members[i].member; - parse->EventNPC(EVENT_KILLED_MERIT, this, c, "killed", 0); + + c->RecordKilledNPCEvent(this); + if (parse->HasQuestSub(GetNPCTypeID(), EVENT_KILLED_MERIT)) { + parse->EventNPC(EVENT_KILLED_MERIT, this, c, "killed", 0); + } if (RuleB(NPC, EnableMeritBasedFaction)) c->SetFactionLevel(c->CharacterID(), GetNPCFactionID(), c->GetBaseClass(), c->GetBaseRace(), c->GetDeity()); - mod_npc_killed_merit(kr->members[i].member); - PlayerCount++; } } @@ -2560,13 +2611,16 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { if (kg->members[i] != nullptr && kg->members[i]->IsClient()) { // If Group Member is Client Client *c = kg->members[i]->CastToClient(); - parse->EventNPC(EVENT_KILLED_MERIT, this, c, "killed", 0); + + c->RecordKilledNPCEvent(this); + + if (parse->HasQuestSub(GetNPCTypeID(), EVENT_KILLED_MERIT)) { + parse->EventNPC(EVENT_KILLED_MERIT, this, c, "killed", 0); + } if (RuleB(NPC, EnableMeritBasedFaction)) c->SetFactionLevel(c->CharacterID(), GetNPCFactionID(), c->GetBaseClass(), c->GetBaseRace(), c->GetDeity()); - mod_npc_killed_merit(c); - PlayerCount++; } } @@ -2607,14 +2661,15 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy } /* Send the EVENT_KILLED_MERIT event */ - parse->EventNPC(EVENT_KILLED_MERIT, this, give_exp_client, "killed", 0); + give_exp_client->RecordKilledNPCEvent(this); + if (parse->HasQuestSub(GetNPCTypeID(), EVENT_KILLED_MERIT)) { + parse->EventNPC(EVENT_KILLED_MERIT, this, give_exp_client, "killed", 0); + } if (RuleB(NPC, EnableMeritBasedFaction)) give_exp_client->SetFactionLevel(give_exp_client->CharacterID(), GetNPCFactionID(), give_exp_client->GetBaseClass(), give_exp_client->GetBaseRace(), give_exp_client->GetDeity()); - mod_npc_killed_merit(give_exp_client); - // QueryServ Logging - Solo if (RuleB(QueryServ, PlayerLogNPCKills)) { auto pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, @@ -2750,8 +2805,6 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy // Parse quests even if we're killed by an NPC if (oos) { - mod_npc_killed(oos); - if (IsNPC()) { auto emote_id = GetEmoteID(); if (emote_id) { @@ -2760,7 +2813,10 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy } if (oos->IsNPC()) { - parse->EventNPC(EVENT_NPC_SLAY, oos->CastToNPC(), this, "", 0); + if (parse->HasQuestSub(oos->GetNPCTypeID(), EVENT_NPC_SLAY)) { + parse->EventNPC(EVENT_NPC_SLAY, oos->CastToNPC(), this, "", 0); + } + auto emote_id = oos->GetEmoteID(); if (emote_id) { oos->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledNPC, emote_id); @@ -2770,8 +2826,11 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy } } - if (killer_mob->IsBot()) { - parse->EventBot(EVENT_NPC_SLAY, killer_mob->CastToBot(), this, "", 0); + if (killer_mob && killer_mob->IsBot()) { + if (parse->BotHasQuestSub(EVENT_NPC_SLAY)) { + parse->EventBot(EVENT_NPC_SLAY, killer_mob->CastToBot(), this, "", 0); + } + killer_mob->TrySpellOnKill(killed_level, spell); } @@ -2783,13 +2842,36 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy entity_list.UpdateFindableNPCState(this, true); - std::vector args = { corpse }; - parse->EventNPC(EVENT_DEATH_COMPLETE, this, oos, export_string, 0, &args); - combat_record.Stop(); + m_combat_record.Stop(); + if (parse->HasQuestSub(GetNPCTypeID(), EVENT_DEATH_COMPLETE)) { + const auto& export_string = fmt::format( + "{} {} {} {}", + killer_mob ? killer_mob->GetID() : 0, + damage, + spell, + static_cast(attack_skill) + ); + + std::vector args = { corpse }; + + parse->EventNPC(EVENT_DEATH_COMPLETE, this, oos, export_string, 0, &args); + } /* Zone controller process EVENT_DEATH_ZONE (Death events) */ - args.push_back(this); - DispatchZoneControllerEvent(EVENT_DEATH_ZONE, oos, export_string, 0, &args); + + if (parse->HasQuestSub(ZONE_CONTROLLER_NPC_ID, EVENT_DEATH_ZONE)) { + const auto& export_string = fmt::format( + "{} {} {} {}", + killer_mob ? killer_mob->GetID() : 0, + damage, + spell, + static_cast(attack_skill) + ); + + std::vector args = { corpse, this }; + + DispatchZoneControllerEvent(EVENT_DEATH_ZONE, oos, export_string, 0, &args); + } return true; } @@ -2866,7 +2948,7 @@ void Mob::AddToHateList(Mob* other, int64 hate /*= 0*/, int64 damage /*= 0*/, bo if (GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && other->IsClient()) return; - if (spell_id != SPELL_UNKNOWN && NoDetrimentalSpellAggro(spell_id)) + if (IsValidSpell(spell_id) && NoDetrimentalSpellAggro(spell_id)) return; if (other == myowner) @@ -2998,8 +3080,12 @@ void Mob::AddToHateList(Mob* other, int64 hate /*= 0*/, int64 damage /*= 0*/, bo } if (!wasengaged) { - if (IsNPC() && other->IsClient() && other->CastToClient()) - parse->EventNPC(EVENT_AGGRO, CastToNPC(), other, "", 0); + if (IsNPC() && other->IsClient() && other->CastToClient()) { + if (parse->HasQuestSub(GetNPCTypeID(), EVENT_AGGRO)) { + parse->EventNPC(EVENT_AGGRO, CastToNPC(), other, "", 0); + } + } + AI_Event_Engaged(other, iYellForHelp); } } @@ -3026,8 +3112,9 @@ void Mob::DamageShield(Mob* attacker, bool spell_ds) { DS = spellbonuses.DamageShield; rev_ds = attacker->spellbonuses.ReverseDamageShield; - if (spellbonuses.DamageShieldSpellID != 0 && spellbonuses.DamageShieldSpellID != SPELL_UNKNOWN) + if (IsValidSpell(spellbonuses.DamageShieldSpellID)) { spellid = spellbonuses.DamageShieldSpellID; + } } else { DS = spellbonuses.SpellDamageShield + itembonuses.SpellDamageShield + aabonuses.SpellDamageShield; @@ -3096,8 +3183,9 @@ void Mob::DamageShield(Mob* attacker, bool spell_ds) { //if we've gotten to this point, we know we know "attacker" hit "this" (us) for damage & we aren't invulnerable uint16 rev_ds_spell_id = SPELL_UNKNOWN; - if (spellbonuses.ReverseDamageShieldSpellID != 0 && spellbonuses.ReverseDamageShieldSpellID != SPELL_UNKNOWN) + if (IsValidSpell(spellbonuses.ReverseDamageShieldSpellID)) { rev_ds_spell_id = spellbonuses.ReverseDamageShieldSpellID; + } if (rev_ds < 0) { LogCombat("Applying Reverse Damage Shield of value [{}] to [{}]", rev_ds, attacker->GetName()); @@ -3530,12 +3618,12 @@ int64 Mob::ReduceAllDamage(int64 damage) bool Mob::HasProcs() const { for (int i = 0; i < MAX_PROCS; i++) { - if (PermaProcs[i].spellID != SPELL_UNKNOWN || SpellProcs[i].spellID != SPELL_UNKNOWN) { + if (IsValidSpell(PermaProcs[i].spellID) || IsValidSpell(SpellProcs[i].spellID)) { return true; } } - if (IsClient() || IsBot()) { + if (IsOfClientBot()) { for (int i = 0; i < MAX_AA_PROCS; i += 4) { if (aabonuses.SpellProc[i]) { return true; @@ -3548,12 +3636,12 @@ bool Mob::HasProcs() const bool Mob::HasDefensiveProcs() const { for (int i = 0; i < MAX_PROCS; i++) { - if (DefensiveProcs[i].spellID != SPELL_UNKNOWN) { + if (IsValidSpell(DefensiveProcs[i].spellID)) { return true; } } - if (IsClient() || IsBot()) { + if (IsOfClientBot()) { for (int i = 0; i < MAX_AA_PROCS; i += 4) { if (aabonuses.DefensiveProc[i]) { return true; @@ -3584,12 +3672,12 @@ bool Mob::HasSkillProcSuccess() const bool Mob::HasRangedProcs() const { for (int i = 0; i < MAX_PROCS; i++){ - if (RangedProcs[i].spellID != SPELL_UNKNOWN) { + if (IsValidSpell(RangedProcs[i].spellID)) { return true; } } - if (IsClient() || IsBot()) { + if (IsOfClientBot()) { for (int i = 0; i < MAX_AA_PROCS; i += 4) { if (aabonuses.RangedProc[i]) { return true; @@ -3676,16 +3764,16 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons damage = DMG_INVULNERABLE; } - if (spell_id != SPELL_UNKNOWN || attacker == nullptr) + if (IsValidSpell(spell_id) || attacker == nullptr) avoidable = false; // only apply DS if physical damage (no spell damage) // damage shield calls this function with spell_id set, so its unavoidable - if (attacker && damage > 0 && spell_id == SPELL_UNKNOWN && skill_used != EQ::skills::SkillArchery && skill_used != EQ::skills::SkillThrowing) { + if (attacker && damage > 0 && !IsValidSpell(spell_id) && skill_used != EQ::skills::SkillArchery && skill_used != EQ::skills::SkillThrowing) { DamageShield(attacker); } - if (spell_id == SPELL_UNKNOWN && skill_used) { + if (!IsValidSpell(spell_id) && skill_used >= EQ::skills::Skill1HBlunt) { CheckNumHitsRemaining(NumHit::IncomingHitAttempts); if (attacker) @@ -3712,7 +3800,7 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons //if there is some damage being done and theres an attacker involved if (attacker) { // if spell is lifetap add hp to the caster - if (spell_id != SPELL_UNKNOWN && IsLifetapSpell(spell_id)) { + if (IsValidSpell(spell_id) && IsLifetapSpell(spell_id)) { int64 healed = damage; healed = RuleB(Spells, CompoundLifetapHeals) ? attacker->GetActSpellHealing(spell_id, healed) : healed; @@ -3741,11 +3829,11 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons } //end `if there is some damage being done and theres anattacker person involved` - Mob *pet = GetPet(); // pets that have GHold will never automatically add NPCs // pets that have Hold and no Focus will add NPCs if they're engaged // pets that have Hold and Focus will not add NPCs if ( + Mob* pet = GetPet(); pet && !pet->IsFamiliar() && !pet->GetSpecialAbility(IMMUNE_AGGRO) && @@ -3756,26 +3844,25 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons attacker != this && !attacker->IsCorpse() && !pet->IsGHeld() && - !attacker->IsTrap() + !attacker->IsTrap() && + !pet->IsHeld() ) { - if (!pet->IsHeld()) { - LogAggro("Sending pet [{}] into battle due to attack", pet->GetName()); - if (IsClient()) { - // if pet was sitting his new mode is follow - // following after the battle (live verified) - if (pet->GetPetOrder() == SPO_Sit) { - pet->SetPetOrder(SPO_Follow); - } - - // fix GUI sit button to be unpressed and stop sitting regen - CastToClient()->SetPetCommandState(PET_BUTTON_SIT, 0); - pet->SetAppearance(eaStanding); + LogAggro("Sending pet [{}] into battle due to attack", pet->GetName()); + if (IsClient()) { + // if pet was sitting his new mode is follow + // following after the battle (live verified) + if (pet->GetPetOrder() == SPO_Sit) { + pet->SetPetOrder(SPO_Follow); } - pet->AddToHateList(attacker, 1, 0, true, false, false, spell_id); - pet->SetTarget(attacker); - MessageString(Chat::NPCQuestSay, PET_ATTACKING, pet->GetCleanName(), attacker->GetCleanName()); + // fix GUI sit button to be unpressed and stop sitting regen + CastToClient()->SetPetCommandState(PET_BUTTON_SIT, 0); + pet->SetAppearance(eaStanding); } + + pet->AddToHateList(attacker, 1, 0, true, false, false, spell_id); + pet->SetTarget(attacker); + MessageString(Chat::NPCQuestSay, PET_ATTACKING, pet->GetCleanName(), attacker->GetCleanName()); } if (GetTempPetCount()) { @@ -3783,7 +3870,7 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons } //see if any runes want to reduce this damage - if (spell_id == SPELL_UNKNOWN) { + if (!IsValidSpell(spell_id)) { damage = ReduceDamage(damage); LogCombat("Melee Damage reduced to [{}]", damage); damage = ReduceAllDamage(damage); @@ -3796,9 +3883,18 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons else { int64 origdmg = damage; damage = AffectMagicalDamage(damage, spell_id, iBuffTic, attacker); - if (origdmg != damage && attacker && attacker->IsClient()) { - if (attacker->CastToClient()->GetFilter(FilterDamageShields) != FilterHide) - attacker->Message(Chat::Yellow, "The Spellshield absorbed %d of %d points of damage", origdmg - damage, origdmg); + if ( + origdmg != damage && + attacker && + attacker->IsClient() && + attacker->CastToClient()->GetFilter(FilterDamageShields) != FilterHide + ) { + attacker->Message( + Chat::Yellow, + "The Spellshield absorbed %d of %d points of damage", + origdmg - damage, + origdmg + ); } if (damage == 0 && attacker && origdmg != damage && IsClient()) { //Kayen: Probably need to add a filter for this - Not sure if this msg is correct but there should be a message for spell negate/runes. @@ -3820,6 +3916,100 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons //final damage has been determined. SetHP(int64(GetHP() - damage)); + const auto has_bot_given_event = parse->BotHasQuestSub(EVENT_DAMAGE_GIVEN); + + const auto has_bot_taken_event = parse->BotHasQuestSub(EVENT_DAMAGE_TAKEN); + + const auto has_npc_given_event = ( + ( + IsNPC() && + parse->HasQuestSub(CastToNPC()->GetNPCTypeID(), EVENT_DAMAGE_GIVEN) + ) || + ( + attacker && + attacker->IsNPC() && + parse->HasQuestSub(attacker->CastToNPC()->GetNPCTypeID(), EVENT_DAMAGE_GIVEN) + ) + ); + + const auto has_npc_taken_event = ( + ( + IsNPC() && + parse->HasQuestSub(CastToNPC()->GetNPCTypeID(), EVENT_DAMAGE_TAKEN) + ) || + ( + attacker && + attacker->IsNPC() && + parse->HasQuestSub(attacker->CastToNPC()->GetNPCTypeID(), EVENT_DAMAGE_TAKEN) + ) + ); + + const auto has_player_given_event = parse->PlayerHasQuestSub(EVENT_DAMAGE_GIVEN); + + const auto has_player_taken_event = parse->PlayerHasQuestSub(EVENT_DAMAGE_TAKEN); + + const auto has_given_event = ( + has_bot_given_event || + has_npc_given_event || + has_player_given_event + ); + + const auto has_taken_event = ( + has_bot_taken_event || + has_npc_taken_event || + has_player_taken_event + ); + + std::vector args; + + if (has_taken_event) { + const auto export_string = fmt::format( + "{} {} {} {} {} {} {} {} {}", + attacker ? attacker->GetID() : 0, + damage, + spell_id, + static_cast(skill_used), + FromDamageShield ? 1 : 0, + avoidable ? 1 : 0, + buffslot, + iBuffTic ? 1 : 0, + static_cast(special) + ); + + if (IsBot() && has_bot_taken_event) { + parse->EventBot(EVENT_DAMAGE_TAKEN, CastToBot(), attacker ? attacker : nullptr, export_string, 0); + } else if (IsClient() && has_player_taken_event) { + args.push_back(attacker ? attacker : nullptr); + parse->EventPlayer(EVENT_DAMAGE_TAKEN, CastToClient(), export_string, 0, &args); + } else if (IsNPC() && has_npc_taken_event) { + parse->EventNPC(EVENT_DAMAGE_TAKEN, CastToNPC(), attacker ? attacker : nullptr, export_string, 0); + } + } + + if (has_given_event && attacker) { + const auto export_string = fmt::format( + "{} {} {} {} {} {} {} {} {}", + GetID(), + damage, + spell_id, + static_cast(skill_used), + FromDamageShield ? 1 : 0, + avoidable ? 1 : 0, + buffslot, + iBuffTic ? 1 : 0, + static_cast(special) + ); + + if (attacker->IsBot() && has_bot_given_event) { + parse->EventBot(EVENT_DAMAGE_GIVEN, attacker->CastToBot(), this, export_string, 0); + } else if (attacker->IsClient() && has_player_given_event) { + args.push_back(this); + parse->EventPlayer(EVENT_DAMAGE_GIVEN, attacker->CastToClient(), export_string, 0, &args); + } else if (attacker->IsNPC() && has_npc_given_event) { + parse->EventNPC(EVENT_DAMAGE_GIVEN, attacker->CastToNPC(), this, export_string, 0); + } + } + if (HasDied()) { bool IsSaved = false; @@ -3865,10 +4055,11 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons if (attacker) { if (skill_used == EQ::skills::SkillBash) { can_stun = true; - if (attacker->IsClient()) + if (attacker->IsClient() || attacker->IsBot() || attacker->IsMerc()) { stunbash_chance = attacker->spellbonuses.StunBashChance + - attacker->itembonuses.StunBashChance + - attacker->aabonuses.StunBashChance; + attacker->itembonuses.StunBashChance + + attacker->aabonuses.StunBashChance; + } } else if (skill_used == EQ::skills::SkillKick && (attacker->GetLevel() > 55 || attacker->IsNPC()) && GetClass() == WARRIOR) { @@ -3877,7 +4068,7 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons bool is_immune_to_frontal_stun = false; - if (IsBot() || IsClient() || IsMerc()) { + if (IsOfClientBotMerc()) { if ( IsPlayerClass(GetClass()) && RuleI(Combat, FrontalStunImmunityClasses) & GetPlayerClassBit(GetClass()) @@ -3968,12 +4159,12 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons } } - if (spell_id != SPELL_UNKNOWN && !iBuffTic) { + if (IsValidSpell(spell_id) && !iBuffTic) { //see if root will break if (IsRooted() && !FromDamageShield) // neotoyko: only spells cancel root TryRootFadeByDamage(buffslot, attacker); } - else if (spell_id == SPELL_UNKNOWN) + else if (!IsValidSpell(spell_id)) { //increment chances of interrupting if (IsCasting()) { //shouldnt interrupt on regular spell damage @@ -3998,7 +4189,8 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons a->source = 0; else a->source = attacker->GetID(); - a->type = SkillDamageTypes[skill_used]; // was 0x1c + a->type = (EQ::ValueWithin(skill_used, EQ::skills::Skill1HBlunt, EQ::skills::Skill2HPiercing)) ? + SkillDamageTypes[skill_used] : SkillDamageTypes[EQ::skills::SkillHandtoHand]; // was 0x1c a->damage = damage; a->spellid = spell_id; if (special == eSpecialAttacks::AERampage) @@ -4012,10 +4204,11 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons (IsClient() || zone->random.Roll(RuleI(Combat, MeleePushChance)))) { a->force = EQ::skills::GetSkillMeleePushForce(skill_used); if (IsNPC()) { - if (attacker->IsNPC()) + if (attacker && attacker->IsNPC()) { a->force = 0.0f; // 2013 change that disabled NPC vs NPC push - else + } else { a->force *= 0.10f; // force against NPCs is divided by 10 I guess? ex bash is 0.3, parsed 0.03 against an NPC + } if (ForcedMovement == 0 && a->force != 0.0f && position_update_melee_push_timer.Check()) { m_Delta.x += a->force * g_Math.FastSin(a->hit_heading); m_Delta.y += a->force * g_Math.FastCos(a->hit_heading); @@ -4027,22 +4220,23 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons //Note: if players can become pets, they will not receive damage messages of their own //this was done to simplify the code here (since we can only effectively skip one mob on queue) eqFilterType filter; - Mob *skip = attacker; + Mob* skip = attacker; if (attacker && attacker->GetOwnerID()) { //attacker is a pet, let pet owners see their pet's damage Mob* owner = attacker->GetOwner(); if (owner && owner->IsClient()) { - if (((spell_id != SPELL_UNKNOWN) || (FromDamageShield)) && damage>0) { + if ((IsValidSpell(spell_id) || (FromDamageShield)) && damage > 0) { //special crap for spell damage, looks hackish to me char val1[20] = { 0 }; owner->MessageString(Chat::NonMelee, OTHER_HIT_NONMELEE, GetCleanName(), ConvertArray(damage, val1)); } else { if (damage > 0) { - if (spell_id != SPELL_UNKNOWN) + if (IsValidSpell(spell_id)) { filter = iBuffTic ? FilterDOT : FilterSpellDamage; - else + } else { filter = FilterPetHits; + } } else if (damage == -5) filter = FilterNone; //cant filter invulnerable @@ -4053,13 +4247,14 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons owner->CastToClient()->QueuePacket(outapp, true, CLIENT_CONNECTED, filter); } } + skip = owner; } else { //attacker is not a pet, send to the attacker //if the attacker is a client, try them with the correct filter if (attacker && (attacker->IsClient() || attacker->IsBot())) { - if ((spell_id != SPELL_UNKNOWN || FromDamageShield) && damage > 0) { + if ((IsValidSpell(spell_id) || FromDamageShield) && damage > 0) { //special crap for spell damage, looks hackish to me char val1[20] = { 0 }; if (FromDamageShield) { @@ -4084,10 +4279,12 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons // Only try to queue these packets to a client else if (attacker && (attacker->IsClient())) { if (damage > 0) { - if (spell_id != SPELL_UNKNOWN) + if (IsValidSpell(spell_id)) { filter = iBuffTic ? FilterDOT : FilterSpellDamage; - else - filter = FilterNone; //cant filter our own hits + } + else { + filter = FilterNone; //cant filter our own hits + } } else if (damage == -5) filter = FilterNone; //cant filter invulnerable @@ -4102,10 +4299,12 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons //send damage to all clients around except the specified skip mob (attacker or the attacker's owner) and ourself if (damage > 0) { - if (spell_id != SPELL_UNKNOWN) + if (IsValidSpell(spell_id)) { filter = iBuffTic ? FilterDOT : FilterSpellDamage; - else + } + else { filter = FilterOthersHit; + } } else if (damage == -5) filter = FilterNone; //cant filter invulnerable @@ -4166,7 +4365,7 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons else { //else, it is a buff tic... // So we can see our dot dmg like live shows it. - if (spell_id != SPELL_UNKNOWN && damage > 0 && attacker && attacker != this && !attacker->IsCorpse()) { + if (IsValidSpell(spell_id) && damage > 0 && attacker && attacker != this && !attacker->IsCorpse()) { //might filter on (attack_skill>200 && attack_skill<250), but I dont think we need it if (attacker->IsClient()) { attacker->FilteredMessageString(attacker, Chat::DotDamage, @@ -4195,11 +4394,11 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons spells[spell_id].name /* Message4 */ ); } - } //end packet sending + } -} +} //end packet sending -void Mob::HealDamage(uint64 amount, Mob *caster, uint16 spell_id) +void Mob::HealDamage(uint64 amount, Mob* caster, uint16 spell_id) { int64 maxhp = GetMaxHP(); int64 curhp = GetHP(); @@ -4213,16 +4412,17 @@ void Mob::HealDamage(uint64 amount, Mob *caster, uint16 spell_id) if (acthealed > 100) { if (caster) { if (IsBuffSpell(spell_id)) { // hots - // message to caster - if (caster->IsClient() && caster == this) { - if (caster->CastToClient()->ClientVersionBit() & EQ::versions::maskSoFAndLater) + // message to caster + if ((caster->IsClient() && caster == this)) { + if (caster->CastToClient()->ClientVersionBit() & EQ::versions::maskSoFAndLater) { FilteredMessageString(caster, Chat::NonMelee, FilterHealOverTime, HOT_HEAL_SELF, itoa(acthealed), spells[spell_id].name); + } else FilteredMessageString(caster, Chat::NonMelee, FilterHealOverTime, YOU_HEALED, GetCleanName(), itoa(acthealed)); } - else if (caster->IsClient() && caster != this) { + else if ((caster->IsClient() && caster != this)) { if (caster->CastToClient()->ClientVersionBit() & EQ::versions::maskSoFAndLater) caster->FilteredMessageString(caster, Chat::NonMelee, FilterHealOverTime, HOT_HEAL_OTHER, GetCleanName(), itoa(acthealed), @@ -4231,6 +4431,7 @@ void Mob::HealDamage(uint64 amount, Mob *caster, uint16 spell_id) caster->FilteredMessageString(caster, Chat::NonMelee, FilterHealOverTime, YOU_HEAL, GetCleanName(), itoa(acthealed)); } + // message to target if (IsClient() && caster != this) { if (CastToClient()->ClientVersionBit() & EQ::versions::maskSoFAndLater) @@ -4245,7 +4446,7 @@ void Mob::HealDamage(uint64 amount, Mob *caster, uint16 spell_id) else { // normal heals FilteredMessageString(caster, Chat::NonMelee, FilterSpellDamage, YOU_HEALED, caster->GetCleanName(), itoa(acthealed)); - if (caster != this) + caster->FilteredMessageString(caster, Chat::NonMelee, FilterSpellDamage, YOU_HEAL, GetCleanName(), itoa(acthealed)); } @@ -4256,10 +4457,12 @@ void Mob::HealDamage(uint64 amount, Mob *caster, uint16 spell_id) } if (curhp < maxhp) { - if ((curhp + amount) > maxhp) + if ((curhp + amount) > maxhp) { curhp = maxhp; - else + } + else { curhp += amount; + } SetHP(curhp); SendHPUpdate(); @@ -4358,7 +4561,7 @@ void Mob::TryDefensiveProc(Mob *on, uint16 hand) { } //AA Procs - if (IsClient() || IsBot()){ + if (IsOfClientBot()) { for (int i = 0; i < MAX_AA_PROCS; i += 4) { int32 aa_rank_id = aabonuses.DefensiveProc[i + +SBIndex::COMBAT_PROC_ORIGIN_ID]; int32 aa_spell_id = aabonuses.DefensiveProc[i + SBIndex::COMBAT_PROC_SPELL_ID]; @@ -4559,7 +4762,7 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon, // Not ranged if (!rangedattk) { // Perma procs (Not used for AA, they are handled below) - if (PermaProcs[i].spellID != SPELL_UNKNOWN) { + if (IsValidSpell(PermaProcs[i].spellID)) { if (zone->random.Roll(PermaProcs[i].chance)) { // TODO: Do these get spell bonus? LogCombat("Permanent proc [{}] procing spell [{}] ([{}] percent chance)", i, PermaProcs[i].spellID, PermaProcs[i].chance); ExecWeaponProc(nullptr, PermaProcs[i].spellID, on); @@ -4570,7 +4773,7 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon, } // Spell procs (buffs) - if (SpellProcs[i].spellID != SPELL_UNKNOWN) { + if (IsValidSpell(SpellProcs[i].spellID)) { if (SpellProcs[i].base_spellID == POISON_PROC) { poison_slot=i; continue; // Process the poison proc last per @mackal @@ -4595,7 +4798,7 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon, } else if (rangedattk) { // ranged only // ranged spell procs (buffs) - if (RangedProcs[i].spellID != SPELL_UNKNOWN) { + if (IsValidSpell(RangedProcs[i].spellID)) { passed_skill_limit_check = PassLimitToSkill(skillinuse, RangedProcs[i].base_spellID, ProcType::RANGED_PROC); @@ -4616,7 +4819,7 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon, } //AA Melee and Ranged Procs - if (IsClient() || IsBot()) { + if (IsOfClientBot()) { for (int i = 0; i < MAX_AA_PROCS; i += 4) { int32 aa_rank_id = 0; @@ -5066,8 +5269,9 @@ void Mob::ApplyMeleeDamageMods(uint16 skill, int64 &damage, Mob *defender, Extra dmgbonusmod += opts->melee_damage_bonus_flat; if (defender) { - if (defender->IsClient() && defender->GetClass() == WARRIOR) + if (defender->IsOfClientBotMerc() && defender->GetClass() == WARRIOR) { dmgbonusmod -= 5; + } // 168 defensive dmgbonusmod += (defender->spellbonuses.MeleeMitigationEffect + defender->itembonuses.MeleeMitigationEffect + @@ -5387,7 +5591,7 @@ void Mob::TrySkillProc(Mob *on, EQ::skills::SkillType skill, uint16 ReuseTime, b } } - if (IsClient() && aabonuses.LimitToSkill[skill]) { + if (IsOfClientBot() && aabonuses.LimitToSkill[skill]) { CanProc = true; uint32 effect_id = 0; @@ -5701,16 +5905,16 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac TryCriticalHit(defender, hit, opts); hit.damage_done += hit.min_damage; - if (IsClient()) { + if (IsOfClientBot()) { int extra = 0; switch (hit.skill) { - case EQ::skills::SkillThrowing: - case EQ::skills::SkillArchery: - extra = CastToClient()->GetHeroicDEX() / 10; - break; - default: - extra = CastToClient()->GetHeroicSTR() / 10; - break; + case EQ::skills::SkillThrowing: + case EQ::skills::SkillArchery: + extra = GetHeroicDEX() * RuleR(Character, HeroicDexterityMultiplier) / 10; + break; + default: + extra = GetHeroicSTR() * RuleR(Character, HeroicStrengthMultiplier) / 10; + break; } hit.damage_done += extra; } @@ -6216,6 +6420,11 @@ int64 Mob::GetHPRegen() const return hp_regen; } +int64 Mob::GetHPRegenPerSecond() const +{ + return hp_regen_per_second; +} + int64 Mob::GetManaRegen() const { return mana_regen; diff --git a/zone/aura.cpp b/zone/aura.cpp index 7f41d1b3a..4fd97dbf6 100644 --- a/zone/aura.cpp +++ b/zone/aura.cpp @@ -946,17 +946,17 @@ bool ZoneDatabase::GetAuraEntry(uint16 spell_id, AuraRecord &record) auto row = results.begin(); - record.npc_type = atoi(row[0]); + record.npc_type = Strings::ToInt(row[0]); strn0cpy(record.name, row[1], 64); - record.spell_id = atoi(row[2]); - record.distance = atoi(row[3]); + record.spell_id = Strings::ToInt(row[2]); + record.distance = Strings::ToInt(row[3]); record.distance *= record.distance; // so we can avoid sqrt - record.aura_type = atoi(row[4]); - record.spawn_type = atoi(row[5]); - record.movement = atoi(row[6]); - record.duration = atoi(row[7]) * 1000; // DB is in seconds - record.icon = atoi(row[8]); - record.cast_time = atoi(row[9]) * 1000; // DB is in seconds + record.aura_type = Strings::ToInt(row[4]); + record.spawn_type = Strings::ToInt(row[5]); + record.movement = Strings::ToInt(row[6]); + record.duration = Strings::ToInt(row[7]) * 1000; // DB is in seconds + record.icon = Strings::ToInt(row[8]); + record.cast_time = Strings::ToInt(row[9]) * 1000; // DB is in seconds return true; } diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index a6664f55b..9ee25918e 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -128,7 +128,7 @@ void Client::CalcBonuses() consume_food_timer.SetTimer(timer); } -int Client::CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat) +int Mob::CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat) { if( (reclevel > 0) && (level < reclevel) ) { @@ -520,12 +520,15 @@ void Client::AddItemBonuses(const EQ::ItemInstance *inst, StatBonuses *newbon, b } } - if (item->ExtraDmgSkill != 0 && item->ExtraDmgSkill <= EQ::skills::HIGHEST_SKILL) { - if ((newbon->SkillDamageAmount[item->ExtraDmgSkill] + item->ExtraDmgAmt) > - RuleI(Character, ItemExtraDmgCap)) + if (item->ExtraDmgAmt != 0 && item->ExtraDmgSkill <= EQ::skills::HIGHEST_SKILL) { + if ( + RuleI(Character, ItemExtraDmgCap) >= 0 && + (newbon->SkillDamageAmount[item->ExtraDmgSkill] + item->ExtraDmgAmt) > RuleI(Character, ItemExtraDmgCap) + ) { newbon->SkillDamageAmount[item->ExtraDmgSkill] = RuleI(Character, ItemExtraDmgCap); - else + } else { newbon->SkillDamageAmount[item->ExtraDmgSkill] += item->ExtraDmgAmt; + } } } @@ -1858,12 +1861,13 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon) newbon->AssistRange = -1; int buff_count = GetMaxTotalSlots(); - for(i = 0; i < buff_count; i++) { - if(buffs[i].spellid != SPELL_UNKNOWN){ + for (i = 0; i < buff_count; i++) { + if (IsValidSpell(buffs[i].spellid)) { ApplySpellsBonuses(buffs[i].spellid, buffs[i].casterlevel, newbon, buffs[i].casterid, 0, buffs[i].ticsremaining, i, buffs[i].instrument_mod); - if (buffs[i].hit_number > 0) + if (buffs[i].hit_number > 0) { Numhits(true); + } } } @@ -1874,7 +1878,7 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon) //Disables a specific spell effect bonus completely, can also be limited to negate only item, AA or spell bonuses. if (spellbonuses.NegateEffects){ for(i = 0; i < buff_count; i++) { - if( (buffs[i].spellid != SPELL_UNKNOWN) && (IsEffectInSpell(buffs[i].spellid, SE_NegateSpellEffect)) ) + if(IsValidSpell(buffs[i].spellid) && (IsEffectInSpell(buffs[i].spellid, SE_NegateSpellEffect)) ) NegateSpellEffectBonuses(buffs[i].spellid); } } @@ -4009,7 +4013,10 @@ bool Client::CalcItemScale(uint32 slot_x, uint32 slot_y) { if(inst->IsScaling()) { uint16 oldexp = inst->GetExp(); - parse->EventItem(EVENT_SCALE_CALC, this, inst, nullptr, "", 0); + + if (parse->ItemHasQuestSub(inst, EVENT_SCALE_CALC)) { + parse->EventItem(EVENT_SCALE_CALC, this, inst, nullptr, "", 0); + } if (inst->GetExp() != oldexp) { // if the scaling factor changed, rescale the item and update the client inst->ScaleItem(); @@ -4028,7 +4035,10 @@ bool Client::CalcItemScale(uint32 slot_x, uint32 slot_y) { if(a_inst->IsScaling()) { uint16 oldexp = a_inst->GetExp(); - parse->EventItem(EVENT_SCALE_CALC, this, a_inst, nullptr, "", 0); + + if (parse->ItemHasQuestSub(a_inst, EVENT_SCALE_CALC)) { + parse->EventItem(EVENT_SCALE_CALC, this, a_inst, nullptr, "", 0); + } if (a_inst->GetExp() != oldexp) { @@ -4096,9 +4106,14 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { { uint16 oldexp = inst->GetExp(); - parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, inst, nullptr, "", 0); + if (parse->ItemHasQuestSub(inst, EVENT_ITEM_ENTER_ZONE)) { + parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, inst, nullptr, "", 0); + } + if (i <= EQ::invslot::EQUIPMENT_END) { - parse->EventItem(EVENT_EQUIP_ITEM, this, inst, nullptr, "", i); + if (parse->ItemHasQuestSub(inst, EVENT_EQUIP_ITEM)) { + parse->EventItem(EVENT_EQUIP_ITEM, this, inst, nullptr, "", i); + } } if (inst->GetExp() != oldexp) { // if the scaling factor changed, rescale the item and update the client @@ -4108,10 +4123,14 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { } } else { if (i <= EQ::invslot::EQUIPMENT_END) { - parse->EventItem(EVENT_EQUIP_ITEM, this, inst, nullptr, "", i); + if (parse->ItemHasQuestSub(inst, EVENT_EQUIP_ITEM)) { + parse->EventItem(EVENT_EQUIP_ITEM, this, inst, nullptr, "", i); + } } - parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, inst, nullptr, "", 0); + if (parse->ItemHasQuestSub(inst, EVENT_ITEM_ENTER_ZONE)) { + parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, inst, nullptr, "", 0); + } } //iterate all augments @@ -4125,7 +4144,9 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { { uint16 oldexp = a_inst->GetExp(); - parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, a_inst, nullptr, "", 0); + if (parse->ItemHasQuestSub(a_inst, EVENT_ITEM_ENTER_ZONE)) { + parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, a_inst, nullptr, "", 0); + } if (a_inst->GetExp() != oldexp) { @@ -4134,7 +4155,9 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { update_slot = true; } } else { - parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, a_inst, nullptr, "", 0); + if (parse->ItemHasQuestSub(a_inst, EVENT_ITEM_ENTER_ZONE)) { + parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, a_inst, nullptr, "", 0); + } } } diff --git a/zone/bot.cpp b/zone/bot.cpp index e7684358c..0744ce94e 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -18,6 +18,7 @@ #include "bot.h" #include "object.h" +#include "raids.h" #include "doors.h" #include "quest_parser_collection.h" #include "lua_parser.h" @@ -27,16 +28,17 @@ #include "../common/data_verification.h" extern volatile bool is_zone_loaded; +extern bool Critical; // This constructor is used during the bot create command Bot::Bot(NPCType *npcTypeData, Client* botOwner) : NPC(npcTypeData, nullptr, glm::vec4(), Ground, false), rest_timer(1), ping_timer(1) { GiveNPCTypeData(npcTypeData); - if(botOwner) { + if (botOwner) { SetBotOwner(botOwner); _botOwnerCharacterID = botOwner->CharacterID(); } else { - SetBotOwner(0); + SetBotOwner(nullptr); _botOwnerCharacterID = 0; } @@ -68,16 +70,17 @@ Bot::Bot(NPCType *npcTypeData, Client* botOwner) : NPC(npcTypeData, nullptr, glm RestRegenHP = 0; RestRegenMana = 0; RestRegenEndurance = 0; - m_enforce_spell_settings = 0; - m_bot_archery_setting = 0; + m_enforce_spell_settings = false; + m_bot_archery_setting = false; m_expansion_bitmask = -1; + m_bot_caster_range = 0; SetBotID(0); SetBotSpellID(0); SetSpawnStatus(false); SetBotCharmer(false); SetPetChooser(false); SetRangerAutoWeaponSelect(false); - SetTaunting(GetClass() == WARRIOR); + SetTaunting(GetClass() == WARRIOR || GetClass() == PALADIN || GetClass() == SHADOWKNIGHT); SetDefaultBotStance(); SetAltOutOfCombatBehavior(GetClass() == BARD); // will need to be updated if more classes make use of this flag @@ -86,8 +89,6 @@ Bot::Bot(NPCType *npcTypeData, Client* botOwner) : NPC(npcTypeData, nullptr, glm m_alt_combat_hate_timer.Start(250); m_auto_defend_timer.Disable(); - //m_combat_jitter_timer.Disable(); - //SetCombatJitterFlag(false); SetGuardFlag(false); SetHoldFlag(false); SetAttackFlag(false); @@ -129,7 +130,7 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to GiveNPCTypeData(npcTypeData); _botOwnerCharacterID = botOwnerCharacterID; - if(_botOwnerCharacterID > 0) + if (_botOwnerCharacterID > 0) SetBotOwner(entity_list.GetClientByCharID(_botOwnerCharacterID)); auto bot_owner = GetBotOwner(); @@ -198,8 +199,6 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to m_alt_combat_hate_timer.Start(250); m_auto_defend_timer.Disable(); - //m_combat_jitter_timer.Disable(); - //SetCombatJitterFlag(false); SetGuardFlag(false); SetHoldFlag(false); SetAttackFlag(false); @@ -226,8 +225,8 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to std::string error_message; EquipBot(&error_message); - if(!error_message.empty()) { - if(bot_owner) + if (!error_message.empty()) { + if (bot_owner) bot_owner->Message(Chat::White, error_message.c_str()); error_message.clear(); } @@ -251,12 +250,13 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to LoadAAs(); - // copied from client CompleteConnect() handler - watch for problems - // (may have to move to post-spawn location if certain buffs still don't process correctly) - if (database.botdb.LoadBuffs(this) && bot_owner) { - + if (!database.botdb.LoadBuffs(this)) { + if (bot_owner) { + bot_owner->Message(Chat::White, "&s for '%s'", BotDatabase::fail::LoadBuffs(), GetCleanName()); + } + } else { //reapply some buffs - uint32 buff_count = GetMaxTotalSlots(); + uint32 buff_count = GetMaxBuffSlots(); for (uint32 j1 = 0; j1 < buff_count; j1++) { if (!IsValidSpell(buffs[j1].spellid)) { continue; @@ -264,11 +264,8 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to const SPDat_Spell_Struct& spell = spells[buffs[j1].spellid]; - int NimbusEffect = GetNimbusEffect(buffs[j1].spellid); - if (NimbusEffect) { - if (!IsNimbusEffectActive(NimbusEffect)) { - SendSpellEffect(NimbusEffect, 500, 0, 1, 3000, true); - } + if (int NimbusEffect = GetNimbusEffect(buffs[j1].spellid); NimbusEffect && !IsNimbusEffectActive(NimbusEffect)) { + SendSpellEffect(NimbusEffect, 500, 0, 1, 3000, true); } for (int x1 = 0; x1 < EFFECT_COUNT; x1++) { @@ -326,11 +323,6 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to } break; } - //case SE_SummonHorse: { - // SummonHorse(buffs[j1].spellid); - // //hasmount = true; //this was false, is that the correct thing? - // break; - //} case SE_Silence: { Silence(true); @@ -357,12 +349,8 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to { if (!zone->CanLevitate()) { - //if (!GetGM()) - //{ SendAppearancePacket(AT_Levitate, 0); BuffFadeByEffect(SE_Levitate); - //Message(Chat::White, "You can't levitate in this zone."); - //} } else { SendAppearancePacket(AT_Levitate, 2); @@ -400,18 +388,15 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to } } } - else { - bot_owner->Message(Chat::White, "&s for '%s'", BotDatabase::fail::LoadBuffs(), GetCleanName()); - } CalcBotStats(false); hp_regen = CalcHPRegen(); mana_regen = CalcManaRegen(); end_regen = CalcEnduranceRegen(); - if(current_hp > max_hp) + if (current_hp > max_hp) current_hp = max_hp; - if(current_hp <= 0) { + if (current_hp <= 0) { if (RuleB(Spells, BuffsFadeOnDeath)) { BuffFadeNonPersistDeath(); } @@ -437,21 +422,31 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to } } - if(current_mana > max_mana) + if (current_mana > max_mana) { current_mana = max_mana; + } cur_end = max_end; + + // Safety Check to confirm we have a valid group + if (HasGroup() && !GetGroup()->IsGroupMember(GetBotOwner())) { + Bot::RemoveBotFromGroup(this, GetGroup()); + } + + // Safety Check to confirm we have a valid raid + if (HasRaid() && !GetRaid()->IsRaidMember(GetBotOwner()->CastToClient())) { + Bot::RemoveBotFromRaid(this); + } + } Bot::~Bot() { AI_Stop(); LeaveHealRotationMemberPool(); - if(HasGroup()) - Bot::RemoveBotFromGroup(this, GetGroup()); - - if(HasPet()) + if (HasPet()) { GetPet()->Depop(); + } entity_list.RemoveBot(GetID()); } @@ -465,14 +460,14 @@ void Bot::SetBotSpellID(uint32 newSpellID) { npc_spells_id = newSpellID; } -void Bot::SetSurname(std::string bot_surname) { +void Bot::SetSurname(std::string_view bot_surname) { _surname = bot_surname.substr(0, 31); if (spawned) { auto outapp = new EQApplicationPacket(OP_GMLastName, sizeof(GMLastName_Struct)); - GMLastName_Struct* gmn = (GMLastName_Struct*)outapp->pBuffer; + auto gmn = (GMLastName_Struct*)outapp->pBuffer; strcpy(gmn->name, GetCleanName()); strcpy(gmn->gmname, GetCleanName()); @@ -487,14 +482,14 @@ void Bot::SetSurname(std::string bot_surname) { } } -void Bot::SetTitle(std::string bot_title) { +void Bot::SetTitle(std::string_view bot_title) { _title = bot_title.substr(0, 31); if (spawned) { auto outapp = new EQApplicationPacket(OP_SetTitleReply, sizeof(SetTitleReply_Struct)); - SetTitleReply_Struct* strs = (SetTitleReply_Struct*)outapp->pBuffer; + auto strs = (SetTitleReply_Struct*)outapp->pBuffer; strs->is_suffix = 0; strn0cpy(strs->title, _title.c_str(), sizeof(strs->title)); @@ -505,14 +500,14 @@ void Bot::SetTitle(std::string bot_title) { } } -void Bot::SetSuffix(std::string bot_suffix) { +void Bot::SetSuffix(std::string_view bot_suffix) { _suffix = bot_suffix.substr(0, 31); if (spawned) { auto outapp = new EQApplicationPacket(OP_SetTitleReply, sizeof(SetTitleReply_Struct)); - SetTitleReply_Struct* strs = (SetTitleReply_Struct*)outapp->pBuffer; + auto strs = (SetTitleReply_Struct*)outapp->pBuffer; strs->is_suffix = 1; strn0cpy(strs->title, _suffix.c_str(), sizeof(strs->title)); @@ -539,8 +534,8 @@ uint32 Bot::GetBotArcheryRange() { } void Bot::ChangeBotArcherWeapons(bool isArcher) { - if((GetClass()==WARRIOR) || (GetClass()==PALADIN) || (GetClass()==RANGER) || (GetClass()==SHADOWKNIGHT) || (GetClass()==ROGUE)) { - if(!isArcher) { + if ((GetClass()==WARRIOR) || (GetClass()==PALADIN) || (GetClass()==RANGER) || (GetClass()==SHADOWKNIGHT) || (GetClass()==ROGUE)) { + if (!isArcher) { BotAddEquipItem(EQ::invslot::slotPrimary, GetBotItemBySlot(EQ::invslot::slotPrimary)); BotAddEquipItem(EQ::invslot::slotSecondary, GetBotItemBySlot(EQ::invslot::slotSecondary)); SetAttackTimer(); @@ -559,7 +554,7 @@ void Bot::ChangeBotArcherWeapons(bool isArcher) { } void Bot::Sit() { - if(IsMoving()) { + if (IsMoving()) { moved = false; StopNavigation(); } @@ -571,9 +566,9 @@ void Bot::Stand() { SetAppearance(eaStanding); } -bool Bot::IsSitting() { +bool Bot::IsSitting() const { bool result = false; - if(GetAppearance() == eaSitting && !IsMoving()) + if (GetAppearance() == eaSitting && !IsMoving()) result = true; return result; @@ -581,7 +576,7 @@ bool Bot::IsSitting() { bool Bot::IsStanding() { bool result = false; - if(GetAppearance() == eaStanding) + if (GetAppearance() == eaStanding) result = true; return result; @@ -589,8 +584,8 @@ bool Bot::IsStanding() { NPCType *Bot::FillNPCTypeStruct( uint32 botSpellsID, - std::string botName, - std::string botLastName, + const std::string& botName, + const std::string& botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, @@ -639,19 +634,7 @@ NPCType *Bot::FillNPCTypeStruct( n->bodytype = 1; n->deity = EQ::deity::DeityAgnostic; n->level = botLevel; - //n->npc_id = 0; - //n->texture = 0; - //n->helmtexture = 0; - //n->herosforgemodel = 0; - //n->loottable_id = 0; n->npc_spells_id = botSpellsID; - //n->npc_spells_effects_id = 0; - //n->npc_faction_id = 0; - //n->merchanttype = 0; - //n->alt_currency_type = 0; - //n->adventure_template = 0; - //n->trap_template = 0; - //n->light = 0; n->AC = ac; n->Mana = mana; n->ATK = attack; @@ -668,7 +651,6 @@ NPCType *Bot::FillNPCTypeStruct( n->PR = pr; n->DR = dr; n->Corrup = corrup; - //n->PhR = 0; n->haircolor = hairColor; n->beardcolor = beardColor; n->eyecolor1 = eyeColor; @@ -679,63 +661,12 @@ NPCType *Bot::FillNPCTypeStruct( n->drakkin_heritage = drakkinHeritage; n->drakkin_tattoo = drakkinTattoo; n->drakkin_details = drakkinDetails; - //n->armor_tint = { 0 }; - //n->min_dmg = 0; - //n->max_dmg = 0; - //n->charm_ac = 0; - //n->charm_min_dmg = 0; - //n->charm_max_dmg = 0; - //n->charm_attack_delay = 0; - //n->charm_accuracy_rating = 0; - //n->charm_avoidance_rating = 0; - //n->charm_atk = 0; - //n->attack_count = 0; - //*n->special_abilities = { 0 }; - //n->d_melee_texture1 = 0; - //n->d_melee_texture2 = 0; - //*n->ammo_idfile = { 0 }; - //n->prim_melee_type = 0; - //n->sec_melee_type = 0; - //n->ranged_type = 0; n->hp_regen = 1; n->mana_regen = 1; - //n->aggroradius = 0; - //n->assistradius = 0; - //n->see_invis = 0; - //n->see_invis_undead = false; - //n->see_hide = false; - //n->see_improved_hide = false; - //n->qglobal = false; - //n->npc_aggro = false; - //n->spawn_limit = 0; - //n->mount_color = 0; - //n->attack_speed = 0.0f; - //n->attack_delay = 0; - //n->accuracy_rating = 0; - //n->avoidance_rating = 0; - //n->findable = false; n->trackable = true; - //n->slow_mitigation = 0; n->maxlevel = botLevel; - //n->scalerate = 0; - //n->private_corpse = false; - //n->unique_spawn_by_name = false; - //n->underwater = false; - //n->emoteid = 0; - //n->spellscale = 0.0f; - //n->healscale = 0.0f; - //n->no_target_hotkey = false; - //n->raid_target = false; - //n->armtexture = 0; - //n->bracertexture = 0; - //n->handtexture = 0; - //n->legtexture = 0; - //n->feettexture = 0; - //n->ignore_despawn = false; n->show_name = true; - //n->untargetable = false; n->skip_global_loot = true; - //n->rare_spawn = false; n->stuck_behavior = Ground; n->skip_auto_scale = true; @@ -743,8 +674,8 @@ NPCType *Bot::FillNPCTypeStruct( } NPCType *Bot::CreateDefaultNPCTypeStructForBot( - std::string botName, - std::string botLastName, + const std::string& botName, + const std::string& botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, @@ -755,8 +686,6 @@ NPCType *Bot::CreateDefaultNPCTypeStructForBot( strn0cpy(n->name, botName.c_str(), sizeof(n->name)); strn0cpy(n->lastname, botLastName.c_str(), sizeof(n->lastname)); - //n->current_hp = 0; - //n->max_hp = 0; n->size = 6.0f; n->runspeed = 0.7f; n->gender = gender; @@ -765,21 +694,7 @@ NPCType *Bot::CreateDefaultNPCTypeStructForBot( n->bodytype = 1; n->deity = EQ::deity::DeityAgnostic; n->level = botLevel; - //n->npc_id = 0; - //n->texture = 0; - //n->helmtexture = 0; - //n->herosforgemodel = 0; - //n->loottable_id = 0; - //n->npc_spells_id = 0; - //n->npc_spells_effects_id = 0; - //n->npc_faction_id = 0; - //n->merchanttype = 0; - //n->alt_currency_type = 0; - //n->adventure_template = 0; - //n->trap_template = 0; - //n->light = 0; n->AC = 12; - //n->Mana = 0; n->ATK = 75; n->STR = 75; n->STA = 75; @@ -794,74 +709,12 @@ NPCType *Bot::CreateDefaultNPCTypeStructForBot( n->PR = 15; n->DR = 15; n->Corrup = 15; - //n->PhR = 0; - //n->haircolor = 0; - //n->beardcolor = 0; - //n->eyecolor1 = 0; - //n->eyecolor2 = 0; - //n->hairstyle = 0; - //n->luclinface = 0; - //n->beard = 0; - //n->drakkin_heritage = 0; - //n->drakkin_tattoo = 0; - //n->drakkin_details = 0; - //n->armor_tint = { 0 }; - //n->min_dmg = 0; - //n->max_dmg = 0; - //n->charm_ac = 0; - //n->charm_min_dmg = 0; - //n->charm_max_dmg = 0; - //n->charm_attack_delay = 0; - //n->charm_accuracy_rating = 0; - //n->charm_avoidance_rating = 0; - //n->charm_atk = 0; - //n->attack_count = 0; - //*n->special_abilities = { 0 }; - //n->d_melee_texture1 = 0; - //n->d_melee_texture2 = 0; - //*n->ammo_idfile = { 0 }; - //n->prim_melee_type = 0; - //n->sec_melee_type = 0; - //n->ranged_type = 0; n->hp_regen = 1; n->mana_regen = 1; - //n->aggroradius = 0; - //n->assistradius = 0; - //n->see_invis = 0; - //n->see_invis_undead = false; - //n->see_hide = false; - //n->see_improved_hide = false; - //n->qglobal = false; - //n->npc_aggro = false; - //n->spawn_limit = 0; - //n->mount_color = 0; - //n->attack_speed = 0.0f; - //n->attack_delay = 0; - //n->accuracy_rating = 0; - //n->avoidance_rating = 0; - //n->findable = false; n->trackable = true; - //n->slow_mitigation = 0; n->maxlevel = botLevel; - //n->scalerate = 0; - //n->private_corpse = false; - //n->unique_spawn_by_name = false; - //n->underwater = false; - //n->emoteid = 0; - //n->spellscale = 0.0f; - //n->healscale = 0.0f; - //n->no_target_hotkey = false; - //n->raid_target = false; - //n->armtexture = 0; - //n->bracertexture = 0; - //n->handtexture = 0; - //n->legtexture = 0; - //n->feettexture = 0; - //n->ignore_despawn = false; n->show_name = true; - //n->untargetable = false; n->skip_global_loot = true; - //n->rare_spawn = false; n->stuck_behavior = Ground; return n; @@ -1219,9 +1072,8 @@ void Bot::GenerateAppearance() { iBeardColor = zone->random.Int(0, 3); } else if (GetGender()) { iHair = zone->random.Int(0, 2); - if (GetRace() == DWARF) { // Dwarven Females can have a beard - if(zone->random.Int(1, 100) < 50) - iFace += 10; + if (GetRace() == DWARF && zone->random.Int(1, 100) < 50) { + iFace += 10; } } else { iHair = zone->random.Int(0, 3); @@ -1236,11 +1088,11 @@ void Bot::GenerateAppearance() { iHairColor = zone->random.Int(0, 19); } - uint8 iEyeColor1 = (uint8)zone->random.Int(0, 9); + auto iEyeColor1 = (uint8)zone->random.Int(0, 9); uint8 iEyeColor2 = 0; if (GetRace() == DRAKKIN) { iEyeColor1 = iEyeColor2 = (uint8)zone->random.Int(0, 11); - } else if(zone->random.Int(1, 100) > 96) { + } else if (zone->random.Int(1, 100) > 96) { iEyeColor2 = zone->random.Int(0, 9); } else { iEyeColor2 = iEyeColor1; @@ -1266,393 +1118,37 @@ void Bot::GenerateAppearance() { drakkin_details = iDetails; } -int32 Bot::acmod() { - int agility = GetAGI(); - int level = GetLevel(); - if(agility < 1 || level < 1) - return 0; - - if(agility <= 74) { - if(agility == 1) - return -24; - else if(agility <= 3) - return -23; - else if(agility == 4) - return -22; - else if(agility <= 6) - return -21; - else if(agility <= 8) - return -20; - else if(agility == 9) - return -19; - else if(agility <= 11) - return -18; - else if(agility == 12) - return -17; - else if(agility <= 14) - return -16; - else if(agility <= 16) - return -15; - else if(agility == 17) - return -14; - else if(agility <= 19) - return -13; - else if(agility == 20) - return -12; - else if(agility <= 22) - return -11; - else if(agility <= 24) - return -10; - else if(agility == 25) - return -9; - else if(agility <= 27) - return -8; - else if(agility == 28) - return -7; - else if(agility <= 30) - return -6; - else if(agility <= 32) - return -5; - else if(agility == 33) - return -4; - else if(agility <= 35) - return -3; - else if(agility == 36) - return -2; - else if(agility <= 38) - return -1; - else if(agility <= 65) - return 0; - else if(agility <= 70) - return 1; - else if(agility <= 74) - return 5; - } else if(agility <= 137) { - if(agility == 75) { - if(level <= 6) - return 9; - else if(level <= 19) - return 23; - else if(level <= 39) - return 33; - else - return 39; - } else if(agility >= 76 && agility <= 79) { - if(level <= 6) - return 10; - else if(level <= 19) - return 23; - else if(level <= 39) - return 33; - else - return 40; - } else if(agility == 80) { - if(level <= 6) - return 11; - else if(level <= 19) - return 24; - else if(level <= 39) - return 34; - else - return 41; - } else if(agility >= 81 && agility <= 85) { - if(level <= 6) - return 12; - else if(level <= 19) - return 25; - else if(level <= 39) - return 35; - else - return 42; - } else if(agility >= 86 && agility <= 90) { - if(level <= 6) - return 12; - else if(level <= 19) - return 26; - else if(level <= 39) - return 36; - else - return 42; - } else if(agility >= 91 && agility <= 95) { - if(level <= 6) - return 13; - else if(level <= 19) - return 26; - else if(level <= 39) - return 36; - else - return 43; - } else if(agility >= 96 && agility <= 99) { - if(level <= 6) - return 14; - else if(level <= 19) - return 27; - else if(level <= 39) - return 37; - else - return 44; - } else if(agility == 100 && level >= 7) { - if(level <= 19) - return 28; - else if (level <= 39) - return 38; - else - return 45; - } - else if(level <= 6) - return 15; - //level is >6 - else if(agility >= 101 && agility <= 105) { - if(level <= 19) - return 29; - else if(level <= 39) - return 39;// not verified - else - return 45; - } else if(agility >= 106 && agility <= 110) { - if(level <= 19) - return 29; - else if(level <= 39) - return 39;// not verified - else - return 46; - } else if(agility >= 111 && agility <= 115) { - if(level <= 19) - return 30; - else if(level <= 39) - return 40;// not verified - else - return 47; - } else if(agility >= 116 && agility <= 119) { - if(level <= 19) - return 31; - else if(level <= 39) - return 41; - else - return 47; - } - else if(level <= 19) - return 32; - //level is > 19 - else if(agility == 120) { - if(level <= 39) - return 42; - else - return 48; - } else if(agility <= 125) { - if(level <= 39) - return 42; - else - return 49; - } else if(agility <= 135) { - if(level <= 39) - return 42; - else - return 50; - } else { - if(level <= 39) - return 42; - else - return 51; - } - } else if(agility <= 300) { - if(level <= 6) { - if(agility <= 139) - return 21; - else if(agility == 140) - return 22; - else if(agility <= 145) - return 23; - else if(agility <= 150) - return 23; - else if(agility <= 155) - return 24; - else if(agility <= 159) - return 25; - else if(agility == 160) - return 26; - else if(agility <= 165) - return 26; - else if(agility <= 170) - return 27; - else if(agility <= 175) - return 28; - else if(agility <= 179) - return 28; - else if(agility == 180) - return 29; - else if(agility <= 185) - return 30; - else if(agility <= 190) - return 31; - else if(agility <= 195) - return 31; - else if(agility <= 199) - return 32; - else if(agility <= 219) - return 33; - else if(agility <= 239) - return 34; - else - return 35; - } else if(level <= 19) { - if(agility <= 139) - return 34; - else if(agility == 140) - return 35; - else if(agility <= 145) - return 36; - else if(agility <= 150) - return 37; - else if(agility <= 155) - return 37; - else if(agility <= 159) - return 38; - else if(agility == 160) - return 39; - else if(agility <= 165) - return 40; - else if(agility <= 170) - return 40; - else if(agility <= 175) - return 41; - else if(agility <= 179) - return 42; - else if(agility == 180) - return 43; - else if(agility <= 185) - return 43; - else if(agility <= 190) - return 44; - else if(agility <= 195) - return 45; - else if(agility <= 199) - return 45; - else if(agility <= 219) - return 46; - else if(agility <= 239) - return 47; - else - return 48; - } else if(level <= 39) { - if(agility <= 139) - return 44; - else if(agility == 140) - return 45; - else if(agility <= 145) - return 46; - else if(agility <= 150) - return 47; - else if(agility <= 155) - return 47; - else if(agility <= 159) - return 48; - else if(agility == 160) - return 49; - else if(agility <= 165) - return 50; - else if(agility <= 170) - return 50; - else if(agility <= 175) - return 51; - else if(agility <= 179) - return 52; - else if(agility == 180) - return 53; - else if(agility <= 185) - return 53; - else if(agility <= 190) - return 54; - else if(agility <= 195) - return 55; - else if(agility <= 199) - return 55; - else if(agility <= 219) - return 56; - else if(agility <= 239) - return 57; - else - return 58; - } else { //lvl >= 40 - if(agility <= 139) - return 51; - else if(agility == 140) - return 52; - else if(agility <= 145) - return 53; - else if(agility <= 150) - return 53; - else if(agility <= 155) - return 54; - else if(agility <= 159) - return 55; - else if(agility == 160) - return 56; - else if(agility <= 165) - return 56; - else if(agility <= 170) - return 57; - else if(agility <= 175) - return 58; - else if(agility <= 179) - return 58; - else if(agility == 180) - return 59; - else if(agility <= 185) - return 60; - else if(agility <= 190) - return 61; - else if(agility <= 195) - return 61; - else if(agility <= 199) - return 62; - else if(agility <= 219) - return 63; - else if(agility <= 239) - return 64; - else - return 65; - } - } - else - return (65 + ((agility - 300) / 21)); - - LogError("Agility [{}] Level [{}]",agility,level); - return 0; -} - uint16 Bot::GetPrimarySkillValue() { EQ::skills::SkillType skill = EQ::skills::HIGHEST_SKILL; //because nullptr == 0, which is 1H Slashing, & we want it to return 0 from GetSkill - bool equiped = m_inv.GetItem(EQ::invslot::slotPrimary); - if(!equiped) + if (bool equiped = m_inv.GetItem(EQ::invslot::slotPrimary); !equiped) { skill = EQ::skills::SkillHandtoHand; - else { + } else { uint8 type = m_inv.GetItem(EQ::invslot::slotPrimary)->GetItem()->ItemType; //is this the best way to do this? - switch(type) { - case EQ::item::ItemType1HSlash: - skill = EQ::skills::Skill1HSlashing; - break; - case EQ::item::ItemType2HSlash: - skill = EQ::skills::Skill2HSlashing; - break; - case EQ::item::ItemType1HPiercing: - skill = EQ::skills::Skill1HPiercing; - break; - case EQ::item::ItemType1HBlunt: - skill = EQ::skills::Skill1HBlunt; - break; - case EQ::item::ItemType2HBlunt: - skill = EQ::skills::Skill2HBlunt; - break; - case EQ::item::ItemType2HPiercing: - skill = EQ::skills::Skill2HPiercing; - break; - case EQ::item::ItemTypeMartial: - skill = EQ::skills::SkillHandtoHand; - break; - default: - skill = EQ::skills::SkillHandtoHand; - break; + switch (type) { + case EQ::item::ItemType1HSlash: + skill = EQ::skills::Skill1HSlashing; + break; + case EQ::item::ItemType2HSlash: + skill = EQ::skills::Skill2HSlashing; + break; + case EQ::item::ItemType1HPiercing: + skill = EQ::skills::Skill1HPiercing; + break; + case EQ::item::ItemType1HBlunt: + skill = EQ::skills::Skill1HBlunt; + break; + case EQ::item::ItemType2HBlunt: + skill = EQ::skills::Skill2HBlunt; + break; + case EQ::item::ItemType2HPiercing: + skill = EQ::skills::Skill2HPiercing; + break; + case EQ::item::ItemTypeMartial: + skill = EQ::skills::SkillHandtoHand; + break; + default: + skill = EQ::skills::SkillHandtoHand; + break; } } @@ -1666,7 +1162,7 @@ uint16 Bot::MaxSkill(EQ::skills::SkillType skillid, uint16 class_, uint16 level) uint32 Bot::GetTotalATK() { uint32 AttackRating = 0; uint32 WornCap = itembonuses.ATK; - if(IsBot()) { + if (IsBot()) { AttackRating = ((WornCap * 1.342) + (GetSkill(EQ::skills::SkillOffense) * 1.345) + ((GetSTR() - 66) * 0.9) + (GetPrimarySkillValue() * 2.69)); AttackRating += aabonuses.ATK + GroupLeadershipAAOffenseEnhancement(); if (AttackRating < 10) @@ -1681,7 +1177,7 @@ uint32 Bot::GetTotalATK() { uint32 Bot::GetATKRating() { uint32 AttackRating = 0; - if(IsBot()) { + if (IsBot()) { AttackRating = (GetSkill(EQ::skills::SkillOffense) * 1.345) + ((GetSTR() - 66) * 0.9) + (GetPrimarySkillValue() * 2.69); if (AttackRating < 10) AttackRating = 10; @@ -1697,26 +1193,26 @@ int32 Bot::GenerateBaseHitPoints() { int32 NormalSTA = GetSTA(); if (GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->ClientVersion() >= EQ::versions::ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) { float SoDPost255; - if(((NormalSTA - 255) / 2) > 0) + if (((NormalSTA - 255) / 2) > 0) SoDPost255 = ((NormalSTA - 255) / 2); else SoDPost255 = 0; int hp_factor = GetClassHPFactor(); - if(level < 41) + if (level < 41) new_base_hp = (5 + (GetLevel() * hp_factor / 12) + ((NormalSTA - SoDPost255) * GetLevel() * hp_factor / 3600)); - else if(level < 81) + else if (level < 81) new_base_hp = (5 + (40 * hp_factor / 12) + ((GetLevel() - 40) * hp_factor / 6) + ((NormalSTA - SoDPost255) * hp_factor / 90) + ((NormalSTA - SoDPost255) * (GetLevel() - 40) * hp_factor / 1800)); else new_base_hp = (5 + (80 * hp_factor / 8) + ((GetLevel() - 80) * hp_factor / 10) + ((NormalSTA - SoDPost255) * hp_factor / 90) + ((NormalSTA - SoDPost255) * hp_factor / 45)); } else { - if(((NormalSTA - 255) / 2) > 0) + if (((NormalSTA - 255) / 2) > 0) Post255 = ((NormalSTA - 255) / 2); else Post255 = 0; - new_base_hp = (5) + (GetLevel() * lm / 10) + (((NormalSTA - Post255) * GetLevel() * lm / 3000)) + ((Post255 * 1) * lm / 6000); + new_base_hp = 5 + (GetLevel() * lm / 10) + ((NormalSTA - Post255) * GetLevel() * lm / 3000) + ((Post255 * 1) * lm / 6000); } base_hp = new_base_hp; return new_base_hp; @@ -1733,7 +1229,7 @@ void Bot::LoadAAs() { AA::Ability *ability = (*iter).second.get(); //skip expendables - if(!ability->first || ability->charges > 0) { + if (!ability->first || ability->charges > 0) { ++iter; continue; } @@ -1749,7 +1245,7 @@ void Bot::LoadAAs() { } while(current) { - if(!CanUseAlternateAdvancementRank(current)) { + if (!CanUseAlternateAdvancementRank(current)) { current = nullptr; } else { current = current->next; @@ -1757,7 +1253,7 @@ void Bot::LoadAAs() { } } - if(points > 0) { + if (points > 0) { SetAA(id, points); } @@ -1774,8 +1270,7 @@ bool Bot::IsValidRaceClassCombo(uint16 bot_race, uint8 bot_class) { bool is_valid = false; auto classes = database.botdb.GetRaceClassBitmask(bot_race); - auto bot_class_bitmask = GetPlayerClassBit(bot_class); - if (classes & bot_class_bitmask) { + if (auto bot_class_bitmask = GetPlayerClassBit(bot_class); classes & bot_class_bitmask) { is_valid = true; } return is_valid; @@ -1811,7 +1306,7 @@ bool Bot::Save() std::string error_message; - if(!GetBotID()) { // New bot record + if (!GetBotID()) { // New bot record uint32 bot_id = 0; if (!database.botdb.SaveNewBot(this, bot_id) || !bot_id) { bot_owner->Message(Chat::White, "%s '%s'", BotDatabase::fail::SaveNewBot(), GetCleanName()); @@ -1879,8 +1374,13 @@ bool Bot::DeleteBot() return false; } - if (GetGroup()) + if (GetGroup()) { RemoveBotFromGroup(this, GetGroup()); + } + + if (GetRaid()) { + RemoveBotFromRaid(this); + } std::string error_message; @@ -2049,18 +1549,21 @@ bool Bot::LoadPet() bool Bot::SavePet() { - if (!GetPet() || GetPet()->IsFamiliar()) // dead? + if (!GetPet() || GetPet()->IsFamiliar()) { // dead? return true; + } NPC *pet_inst = GetPet()->CastToNPC(); - if (!pet_inst->GetPetSpellID() || !IsValidSpell(pet_inst->GetPetSpellID())) + if (!pet_inst->GetPetSpellID() || !IsValidSpell(pet_inst->GetPetSpellID())) { return false; + } auto bot_owner = GetBotOwner(); - if (!bot_owner) + if (!bot_owner) { return false; + } - char* pet_name = new char[64]; + auto pet_name = new char[64]; SpellBuff_Struct pet_buffs[PET_BUFF_COUNT]; uint32 pet_items[EQ::invslot::EQUIPMENT_COUNT]; @@ -2071,7 +1574,7 @@ bool Bot::SavePet() pet_inst->GetPetState(pet_buffs, pet_items, pet_name); std::string pet_name_str = pet_name; - safe_delete_array(pet_name); + safe_delete_array(pet_name) std::string error_message; @@ -2132,9 +1635,8 @@ bool Bot::Process() if (GetDepop()) { - _botOwner = 0; + _botOwner = nullptr; _botOwnerCharacterID = 0; - _previousTarget = 0; return false; } @@ -2155,10 +1657,8 @@ bool Bot::Process() if (tic_timer.Check()) { // 6 seconds, or whatever the rule is set to has passed, send this position to everyone to avoid ghosting - if (!IsEngaged()) { - if (!rest_timer.Enabled()) { - rest_timer.Start(RuleI(Character, RestRegenTimeToActivate) * 1000); - } + if (!IsEngaged() && !rest_timer.Enabled()) { + rest_timer.Start(RuleI(Character, RestRegenTimeToActivate) * 1000); } BuffProcess(); @@ -2221,7 +1721,6 @@ bool Bot::Process() return true; } - // Bot AI AI_Process(); return true; @@ -2255,25 +1754,22 @@ void Bot::AI_Bot_Init() AIautocastspell_timer.reset(nullptr); casting_spell_AIindex = static_cast(AIBot_spells.size()); - roambox_max_x = 0; - roambox_max_y = 0; - roambox_min_x = 0; - roambox_min_y = 0; - roambox_distance = 0; - roambox_destination_x = 0; - roambox_destination_y = 0; - roambox_destination_z = 0; - roambox_min_delay = 2500; - roambox_delay = 2500; + m_roambox.max_x = 0; + m_roambox.max_y = 0; + m_roambox.min_x = 0; + m_roambox.min_y = 0; + m_roambox.distance = 0; + m_roambox.dest_x = 0; + m_roambox.dest_y = 0; + m_roambox.dest_z = 0; + m_roambox.delay = 2500; + m_roambox.min_delay = 2500; } void Bot::SpellProcess() { - if(spellend_timer.Check(false)) { + if (spellend_timer.Check(false)) { NPC::SpellProcess(); - if(GetClass() == BARD) { - if (casting_spell_id != 0) - casting_spell_id = 0; - } + if (GetClass() == BARD && casting_spell_id != 0) casting_spell_id = 0; } } @@ -2298,49 +1794,48 @@ void Bot::BotMeditate(bool isSitting) { void Bot::BotRangedAttack(Mob* other) { //make sure the attack and ranged timers are up //if the ranged timer is disabled, then they have no ranged weapon and shouldent be attacking anyhow - if((attack_timer.Enabled() && !attack_timer.Check(false)) || (ranged_timer.Enabled() && !ranged_timer.Check())) { + if ((attack_timer.Enabled() && !attack_timer.Check(false)) || (ranged_timer.Enabled() && !ranged_timer.Check())) { LogCombatDetail("Bot Archery attack canceled. Timer not up. Attack [{}] ranged [{}]", attack_timer.GetRemainingTime(), ranged_timer.GetRemainingTime()); Message(0, "Error: Timer not up. Attack %d, ranged %d", attack_timer.GetRemainingTime(), ranged_timer.GetRemainingTime()); return; } - EQ::ItemInstance* rangedItem = GetBotItem(EQ::invslot::slotRange); + const auto rangedItem = GetBotItem(EQ::invslot::slotRange); const EQ::ItemData* RangeWeapon = nullptr; - if(rangedItem) + if (rangedItem) RangeWeapon = rangedItem->GetItem(); - EQ::ItemInstance* ammoItem = GetBotItem(EQ::invslot::slotAmmo); + const auto ammoItem = GetBotItem(EQ::invslot::slotAmmo); const EQ::ItemData* Ammo = nullptr; - if(ammoItem) + if (ammoItem) Ammo = ammoItem->GetItem(); - if(!RangeWeapon || !Ammo) + if (!RangeWeapon || !Ammo) return; LogCombatDetail("Shooting [{}] with bow [{}] ([{}]) and arrow [{}] ([{}])", other->GetCleanName(), RangeWeapon->Name, RangeWeapon->ID, Ammo->Name, Ammo->ID); - if(!IsAttackAllowed(other) || IsCasting() || DivineAura() || IsStunned() || IsMezzed() || (GetAppearance() == eaDead)) + if (!IsAttackAllowed(other) || IsCasting() || DivineAura() || IsStunned() || IsMezzed() || (GetAppearance() == eaDead)) return; SendItemAnimation(other, Ammo, EQ::skills::SkillArchery); - //DoArcheryAttackDmg(GetTarget(), rangedItem, ammoItem); DoArcheryAttackDmg(other, rangedItem, ammoItem); // watch //break invis when you attack - if(invisible) { + if (invisible) { LogCombatDetail("Removing invisibility due to melee attack"); BuffFadeByEffect(SE_Invisibility); BuffFadeByEffect(SE_Invisibility2); invisible = false; } - if(invisible_undead) { + if (invisible_undead) { LogCombatDetail("Removing invisibility vs. undead due to melee attack"); BuffFadeByEffect(SE_InvisVsUndead); BuffFadeByEffect(SE_InvisVsUndead2); invisible_undead = false; } - if(invisible_animals) { + if (invisible_animals) { LogCombatDetail("Removing invisibility vs. animals due to melee attack"); BuffFadeByEffect(SE_InvisVsAnimals); invisible_animals = false; @@ -2352,8 +1847,8 @@ void Bot::BotRangedAttack(Mob* other) { if (hidden || improved_hidden) { hidden = false; improved_hidden = false; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); - SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer; + auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); + auto sa_out = (SpawnAppearance_Struct*)outapp->pBuffer; sa_out->spawn_id = GetID(); sa_out->type = 0x03; sa_out->parameter = 0; @@ -2383,40 +1878,22 @@ bool Bot::CheckBotDoubleAttack(bool tripleAttack) { //A reasonable forumla would then be TA = 20% * chance //AA's can also give triple attack skill over cap. (ie Burst of Power) NOTE: Skill ID in spell data is 76 (Triple Attack) //Kayen: Need to decide if we can implement triple attack skill before working in over the cap effect. - if(tripleAttack) { + if (tripleAttack) { // Only some Double Attack classes get Triple Attack [This is already checked in client_processes.cpp] int32 triple_bonus = (spellbonuses.TripleAttackChance + itembonuses.TripleAttackChance); chance *= 0.2f; //Baseline chance is 20% of your double attack chance. chance *= (float(100.0f + triple_bonus) / 100.0f); //Apply modifiers. } - if((zone->random.Real(0, 1) < chance)) + if (zone->random.Real(0, 1) < chance) return true; return false; } -bool Bot::CanDoSpecialAttack(Mob *other) { - //Make sure everything is valid before doing any attacks. - if (!other) { - SetTarget(nullptr); - return false; - } - - if(!GetTarget()) - SetTarget(other); - - if ((other == nullptr || ((GetAppearance() == eaDead) || (other->IsClient() && other->CastToClient()->IsDead())) || HasDied() || (!IsAttackAllowed(other))) || other->GetInvul() || other->GetSpecialAbility(IMMUNE_MELEE)) - return false; - - return true; -} - -void Bot::SetTarget(Mob* mob) { - if(mob != this) { - if(mob != GetTarget()) - _previousTarget = GetTarget(); - +void Bot::SetTarget(Mob *mob) +{ + if (mob != this) { NPC::SetTarget(mob); } } @@ -2447,15 +1924,27 @@ void Bot::SetHoldMode() { // AI Processing for the Bot object constexpr float MAX_CASTER_DISTANCE[PLAYER_CLASS_COUNT] = { - 0, (34 * 34), (24 * 24), (28 * 28), (26 * 26), (42 * 42), 0, (30 * 30), 0, (38 * 38), (54 * 54), (48 * 48), (52 * 52), (50 * 50), (32 * 32), 0 -// W C P R S D M B R S N W M E B B -// A L A N H R N R O H E I A N S E -// R R L G D U K D G M C Z G C T R + 0, + (34 * 34), + (24 * 24), + (28 * 28), + (26 * 26), + (42 * 42), + 0, + (30 * 30), + 0, + (38 * 38), + (54 * 54), + (48 * 48), + (52 * 52), + (50 * 50), + (32 * 32), + 0 }; void Bot::AI_Process() { -#define TEST_COMBATANTS() if (!GetTarget() || GetAppearance() == eaDead) { return; } + #define PULLING_BOT (GetPullingFlag() || GetReturningFlag()) #define NOT_PULLING_BOT (!GetPullingFlag() && !GetReturningFlag()) #define GUARDING (GetGuardFlag()) @@ -2466,285 +1955,71 @@ void Bot::AI_Process() #define NOT_PASSIVE (GetBotStance() != EQ::constants::stancePassive) Client* bot_owner = (GetBotOwner() && GetBotOwner()->IsClient() ? GetBotOwner()->CastToClient() : nullptr); - Group* bot_group = GetGroup(); + auto raid = entity_list.GetRaidByBotName(GetName()); + uint32 r_group = RAID_GROUPLESS; + if (raid) { + raid->VerifyRaid(); + r_group = raid->GetGroup(GetName()); -//#pragma region PRIMARY AI SKIP CHECKS + if (mana_timer.Check(false)) { + raid->SendHPManaEndPacketsFrom(this); + } + + if (send_hp_update_timer.Check(false)) { + raid->SendHPManaEndPacketsFrom(this); + } + } + + auto bot_group = GetGroup(); // Primary reasons for not processing AI - if (!bot_owner || !bot_group || !IsAIControlled()) { + if (!IsAIProcessValid(bot_owner, bot_group, raid)) { return; } - if (bot_owner->IsDead()) { + auto leash_owner = SetLeashOwner(bot_owner, bot_group, raid, r_group); - SetTarget(nullptr); - SetBotOwner(nullptr); - - return; - } - - // We also need a leash owner and follow mob (subset of primary AI criteria) - Client* leash_owner = (bot_group->GetLeader() && bot_group->GetLeader()->IsClient() ? bot_group->GetLeader()->CastToClient() : bot_owner); if (!leash_owner) { return; } -//#pragma endregion + SetFollowID(leash_owner->GetID()); - Mob* follow_mob = entity_list.GetMob(GetFollowID()); - if (!follow_mob) { + auto follow_mob = SetFollowMob(leash_owner); - follow_mob = leash_owner; - SetFollowID(leash_owner->GetID()); - } - - // Berserk updates should occur if primary AI criteria are met - if (GetClass() == WARRIOR || GetClass() == BERSERKER) { - - if (!berserk && GetHP() > 0 && GetHPRatio() < 30.0f) { - - entity_list.MessageCloseString(this, false, 200, 0, BERSERK_START, GetName()); - berserk = true; - } - - if (berserk && GetHPRatio() >= 30.0f) { - - entity_list.MessageCloseString(this, false, 200, 0, BERSERK_END, GetName()); - berserk = false; - } - } - -//#pragma region SECONDARY AI SKIP CHECKS + SetBerserkState(); // Secondary reasons for not processing AI - if (GetPauseAI() || IsStunned() || IsMezzed() || (GetAppearance() == eaDead)) { - - if (IsCasting()) { - InterruptSpell(); - } - - if (IsMyHealRotationSet() || (AmICastingForHealRotation() && m_member_of_heal_rotation->CastingMember() == this)) { - - AdvanceHealRotation(false); - m_member_of_heal_rotation->SetMemberIsCasting(this, false); - } - + if (CheckIfIncapacitated()) { return; } -//#pragma endregion - float fm_distance = DistanceSquared(m_Position, follow_mob->GetPosition()); float lo_distance = DistanceSquared(m_Position, leash_owner->GetPosition()); float leash_distance = RuleR(Bots, LeashDistance); -//#pragma region CURRENTLY CASTING CHECKS +// CURRENTLY CASTING CHECKS - if (IsCasting()) { - - if (IsHealRotationMember() && - m_member_of_heal_rotation->CastingOverride() && - m_member_of_heal_rotation->CastingTarget() != nullptr && - m_member_of_heal_rotation->CastingReady() && - m_member_of_heal_rotation->CastingMember() == this && - !m_member_of_heal_rotation->MemberIsCasting(this)) - { - InterruptSpell(); - } - else if (AmICastingForHealRotation() && m_member_of_heal_rotation->CastingMember() == this) { - - AdvanceHealRotation(false); - return; - } - else if (GetClass() != BARD) { - - if (IsEngaged()) { - return; - } - - if ( - (NOT_GUARDING && fm_distance > GetFollowDistance()) || // Cancel out-of-combat casting if movement to follow mob is required - (GUARDING && DistanceSquared(GetPosition(), GetGuardPoint()) > GetFollowDistance()) // Cancel out-of-combat casting if movement to guard point is required - ) { - InterruptSpell(); - } - - return; - } - } - else if (IsHealRotationMember()) { - m_member_of_heal_rotation->SetMemberIsCasting(this, false); - } - -//#pragma endregion - - // Can't move if rooted... - if (IsRooted() && IsMoving()) { - - StopMoving(); + if (CheckIfCasting(fm_distance)) { return; } -//#pragma region HEAL ROTATION CASTING CHECKS +// HEAL ROTATION CASTING CHECKS - if (IsMyHealRotationSet()) { - - if (AIHealRotation(HealRotationTarget(), UseHealRotationFastHeals())) { - - m_member_of_heal_rotation->SetMemberIsCasting(this); - m_member_of_heal_rotation->UpdateTargetHealingStats(HealRotationTarget()); - AdvanceHealRotation(); - } - else { - - m_member_of_heal_rotation->SetMemberIsCasting(this, false); - AdvanceHealRotation(false); - } - } - -//#pragma endregion + HealRotationChecks(); bool bo_alt_combat = (RuleB(Bots, AllowOwnerOptionAltCombat) && bot_owner->GetBotOption(Client::booAltCombat)); -//#pragma region ATTACK FLAG - if (GetAttackFlag()) { // Push owner's target onto our hate list - - if (GetPet() && PULLING_BOT) { - GetPet()->SetPetOrder(m_previous_pet_order); - } - - SetAttackFlag(false); - SetAttackingFlag(false); - SetPullFlag(false); - SetPullingFlag(false); - SetReturningFlag(false); - bot_owner->SetBotPulling(false); - - if (NOT_HOLDING && NOT_PASSIVE) { - - auto attack_target = bot_owner->GetTarget(); - if (attack_target) { - - InterruptSpell(); - WipeHateList(); - AddToHateList(attack_target, 1); - SetTarget(attack_target); - SetAttackingFlag(); - if (HasPet() && (GetClass() != ENCHANTER || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 2)) { - - GetPet()->WipeHateList(); - GetPet()->AddToHateList(attack_target, 1); - GetPet()->SetTarget(attack_target); - } - } - } + SetOwnerTarget(bot_owner); } - -//#pragma endregion - -//#pragma region PULL FLAG - else if (GetPullFlag()) { // Push owner's target onto our hate list and set flags so other bots do not aggro - - SetAttackFlag(false); - SetAttackingFlag(false); - SetPullFlag(false); - SetPullingFlag(false); - SetReturningFlag(false); - bot_owner->SetBotPulling(false); - - if (NOT_HOLDING && NOT_PASSIVE) { - - auto pull_target = bot_owner->GetTarget(); - if (pull_target) { - - BotGroupSay( - this, - fmt::format( - "Pulling {}.", - pull_target->GetCleanName() - ).c_str() - ); - InterruptSpell(); - WipeHateList(); - AddToHateList(pull_target, 1); - SetTarget(pull_target); - SetPullingFlag(); - bot_owner->SetBotPulling(); - if (HasPet() && (GetClass() != ENCHANTER || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 1)) { - - GetPet()->WipeHateList(); - GetPet()->SetTarget(nullptr); - m_previous_pet_order = GetPet()->GetPetOrder(); - GetPet()->SetPetOrder(SPO_Guard); - } - } - } + BotPullerProcess(bot_owner, raid); } -//#pragma endregion +//ALT COMBAT (ACQUIRE HATE) -//#pragma region ALT COMBAT (ACQUIRE HATE) - - else if (bo_alt_combat && m_alt_combat_hate_timer.Check(false)) { // 'Alt Combat' gives some more 'control' options on how bots process aggro - - // Empty hate list - let's find some aggro - if (!IsEngaged() && NOT_HOLDING && NOT_PASSIVE && (!bot_owner->GetBotPulling() || NOT_PULLING_BOT)) { - - Mob* lo_target = leash_owner->GetTarget(); - if (lo_target && - lo_target->IsNPC() && - !lo_target->IsMezzed() && - ((bot_owner->GetBotOption(Client::booAutoDefend) && lo_target->GetHateAmount(leash_owner)) || leash_owner->AutoAttackEnabled()) && - lo_distance <= leash_distance && - DistanceSquared(m_Position, lo_target->GetPosition()) <= leash_distance && - (CheckLosFN(lo_target) || leash_owner->CheckLosFN(lo_target)) && - IsAttackAllowed(lo_target)) - { - AddToHateList(lo_target, 1); - if (HasPet() && (GetClass() != ENCHANTER || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 2)) { - - GetPet()->AddToHateList(lo_target, 1); - GetPet()->SetTarget(lo_target); - } - } - else { - - for (int counter = 0; counter < bot_group->GroupCount(); counter++) { - - Mob* bg_member = bot_group->members[counter]; - if (!bg_member) { - continue; - } - - Mob* bgm_target = bg_member->GetTarget(); - if (!bgm_target || !bgm_target->IsNPC()) { - continue; - } - - if (!bgm_target->IsMezzed() && - ((bot_owner->GetBotOption(Client::booAutoDefend) && bgm_target->GetHateAmount(bg_member)) || leash_owner->AutoAttackEnabled()) && - lo_distance <= leash_distance && - DistanceSquared(m_Position, bgm_target->GetPosition()) <= leash_distance && - (CheckLosFN(bgm_target) || leash_owner->CheckLosFN(bgm_target)) && - IsAttackAllowed(bgm_target)) - { - AddToHateList(bgm_target, 1); - if (HasPet() && (GetClass() != ENCHANTER || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 2)) { - - GetPet()->AddToHateList(bgm_target, 1); - GetPet()->SetTarget(bgm_target); - } - - break; - } - } - } - } - } - -//#pragma endregion + SetBotTarget(bot_owner, raid, bot_group, leash_owner, lo_distance, leash_distance, bo_alt_combat); glm::vec3 Goal(0, 0, 0); @@ -2755,242 +2030,51 @@ void Bot::AI_Process() rest_timer.Disable(); } -//#pragma region PULLING FLAG (TARGET VALIDATION) +// PULLING FLAG (TARGET VALIDATION) if (GetPullingFlag()) { - - if (!GetTarget()) { - - WipeHateList(); - SetTarget(nullptr); - SetPullingFlag(false); - SetReturningFlag(false); - bot_owner->SetBotPulling(false); - if (GetPet()) { - GetPet()->SetPetOrder(m_previous_pet_order); - } - + if (!PullingFlagChecks(bot_owner)) { return; } - else if (GetTarget()->GetHateList().size()) { - - WipeHateList(); - SetTarget(nullptr); - SetPullingFlag(false); - SetReturningFlag(); - - return; - } - else { - // Default action is to aggress towards enemy - } } -//#pragma endregion - -//#pragma region RETURNING FLAG +// RETURNING FLAG else if (GetReturningFlag()) { - - // Need to make it back to group before clearing return flag - if (fm_distance <= GetFollowDistance()) { - - // Once we're back, clear blocking flags so everyone else can join in - SetReturningFlag(false); - bot_owner->SetBotPulling(false); - if (GetPet()) { - GetPet()->SetPetOrder(m_previous_pet_order); - } - } - - // Need to keep puller out of combat until they reach their 'return to' destination - if (HasTargetReflection()) { - - SetTarget(nullptr); - WipeHateList(); - + if (!ReturningFlagChecks(bot_owner, fm_distance)) { return; } } -//#pragma endregion - -//#pragma region ALT COMBAT (ACQUIRE TARGET) +// ALT COMBAT (ACQUIRE TARGET) else if (bo_alt_combat && m_alt_combat_hate_timer.Check()) { // Find a mob from hate list to target - - // Group roles can be expounded upon in the future - auto assist_mob = entity_list.GetMob(bot_group->GetMainAssistName()); - bool find_target = true; - - if (assist_mob) { - if (assist_mob->GetTarget()) { - if (assist_mob != this) { - if (GetTarget() != assist_mob->GetTarget()) { - SetTarget(assist_mob->GetTarget()); - } - - if ( - HasPet() && - ( - GetClass() != ENCHANTER || - GetPet()->GetPetType() != petAnimation || - GetAA(aaAnimationEmpathy) >= 2 - ) - ) { - // This artificially inflates pet's target aggro..but, less expensive than checking hate each AI process - GetPet()->AddToHateList(assist_mob->GetTarget(), 1); - GetPet()->SetTarget(assist_mob->GetTarget()); - } - } - - find_target = false; - } else if (assist_mob != this) { - if (GetTarget()) { - SetTarget(nullptr); - } - - if ( - HasPet() && - ( - GetClass() != ENCHANTER || - GetPet()->GetPetType() != petAnimation || - GetAA(aaAnimationEmpathy) >= 1 - ) - ) { - GetPet()->WipeHateList(); - GetPet()->SetTarget(nullptr); - } - - find_target = false; - } - } - - if (find_target) { - if (IsRooted()) { - auto closest = hate_list.GetClosestEntOnHateList(this, true); - if (closest) { - SetTarget(closest); - } - } else { - // This will keep bots on target for now..but, future updates will allow for rooting/stunning - auto escaping = hate_list.GetEscapingEntOnHateList(leash_owner, leash_distance); - if (escaping) { - SetTarget(escaping); - } - - if (!GetTarget()) { - auto most_hate = hate_list.GetEntWithMostHateOnList(this, nullptr, true); - if (most_hate) { - SetTarget(most_hate); - } - } - } - } + AcquireBotTarget(bot_group, nullptr, leash_owner, leash_distance); } -//#pragma endregion +// DEFAULT (ACQUIRE TARGET) -//#pragma region DEFAULT (ACQUIRE TARGET) - - else { - - // Default behavior doesn't have a means of acquiring a target from the bot's hate list.. - // ..that action occurs through commands or out-of-combat checks - // (Use current target, if already in combat) - } - -//#pragma endregion - -//#pragma region VERIFY TARGET AND STANCE - - Mob* tar = GetTarget(); // We should have a target..if not, we're awaiting new orders - if (!tar || PASSIVE) { - if (GetTarget()) { - SetTarget(nullptr); - } - - WipeHateList(); - SetAttackFlag(false); - SetAttackingFlag(false); - if (PULLING_BOT) { - - // 'Flags' should only be set on the bot that is pulling - SetPullingFlag(false); - SetReturningFlag(false); - bot_owner->SetBotPulling(false); - if (GetPet()) { - GetPet()->SetPetOrder(m_previous_pet_order); - } - } - - if (GetArchetype() == ARCHETYPE_CASTER) { - BotMeditate(true); - } +// VERIFY TARGET AND STANCE + auto tar = GetBotTarget(bot_owner); + if (!tar) { return; } -//#pragma endregion - -//#pragma region ATTACKING FLAG (HATE VALIDATION) +// ATTACKING FLAG (HATE VALIDATION) if (GetAttackingFlag() && tar->CheckAggro(this)) { SetAttackingFlag(false); } -//#pragma endregion - float tar_distance = DistanceSquared(m_Position, tar->GetPosition()); -//#pragma region TARGET VALIDATION - - // DOUBLE-CHECK THIS CRITERIA - - // Verify that our target has attackable criteria - if (HOLDING || - !tar->IsNPC() || - tar->IsMezzed() || - lo_distance > leash_distance || - tar_distance > leash_distance || - (!GetAttackingFlag() && !CheckLosFN(tar) && !leash_owner->CheckLosFN(tar)) || // This is suppose to keep bots from attacking things behind walls - !IsAttackAllowed(tar) || - (bo_alt_combat && - (!GetAttackingFlag() && NOT_PULLING_BOT && !leash_owner->AutoAttackEnabled() && !tar->GetHateAmount(this) && !tar->GetHateAmount(leash_owner)) - ) - ) - { - // Normally, we wouldn't want to do this without class checks..but, too many issues can arise if we let enchanter animation pets run rampant - if (HasPet()) { - - GetPet()->RemoveFromHateList(tar); - GetPet()->SetTarget(nullptr); - } - - RemoveFromHateList(tar); - SetTarget(nullptr); - - SetAttackFlag(false); - SetAttackingFlag(false); - if (PULLING_BOT) { - - SetPullingFlag(false); - SetReturningFlag(false); - bot_owner->SetBotPulling(false); - if (GetPet()) { - GetPet()->SetPetOrder(m_previous_pet_order); - } - } - - if (IsMoving()) { - StopMoving(); - } +// TARGET VALIDATION + if (!IsValidTarget(bot_owner, leash_owner, lo_distance, leash_distance, bo_alt_combat, tar, tar_distance)) { return; } -//#pragma endregion - // This causes conflicts with default pet handler (bounces between targets) if (NOT_PULLING_BOT && HasPet() && (GetClass() != ENCHANTER || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 2)) { @@ -3006,7 +2090,7 @@ void Bot::AI_Process() SendAddPlayerState(PlayerState::Aggressive); } -//#pragma region PULLING FLAG (ACTIONABLE RANGE) +// PULLING FLAG (ACTIONABLE RANGE) if (GetPullingFlag()) { @@ -3020,327 +2104,31 @@ void Bot::AI_Process() } } -//#pragma endregion +// COMBAT RANGE CALCS -//#pragma region COMBAT RANGE CALCS + bool atCombatRange; + const EQ::ItemInstance* p_item; + const EQ::ItemInstance* s_item; + CheckCombatRange(tar, tar_distance, atCombatRange, p_item, s_item); - bool atCombatRange = false; - - const auto* p_item = GetBotItem(EQ::invslot::slotPrimary); - const auto* s_item = GetBotItem(EQ::invslot::slotSecondary); - - bool behind_mob = false; - bool backstab_weapon = false; - if (GetClass() == ROGUE) { - - behind_mob = BehindMob(tar, GetX(), GetY()); // Can be separated for other future use - backstab_weapon = p_item && p_item->GetItemBackstabDamage(); - } - - // Calculate melee distances - float melee_distance_max = 0.0f; - float melee_distance = 0.0f; - { - float size_mod = GetSize(); - float other_size_mod = tar->GetSize(); - - if (GetRace() == RT_DRAGON || GetRace() == RT_WURM || GetRace() == RT_DRAGON_7) { // For races with a fixed size - size_mod = 60.0f; - } - else if (size_mod < 6.0f) { - size_mod = 8.0f; - } - - if (tar->GetRace() == RT_DRAGON || tar->GetRace() == RT_WURM || tar->GetRace() == RT_DRAGON_7) { // For races with a fixed size - other_size_mod = 60.0f; - } - else if (other_size_mod < 6.0f) { - other_size_mod = 8.0f; - } - - if (other_size_mod > size_mod) { - size_mod = other_size_mod; - } - - if (size_mod > 29.0f) { - size_mod *= size_mod; - } - else if (size_mod > 19.0f) { - size_mod *= (size_mod * 2.0f); - } - else { - size_mod *= (size_mod * 4.0f); - } - - // Prevention of ridiculously sized hit boxes - if (size_mod > 10000.0f) { - size_mod = (size_mod / 7.0f); - } - - melee_distance_max = size_mod; - - switch (GetClass()) { - case WARRIOR: - case PALADIN: - case SHADOWKNIGHT: - if (p_item && p_item->GetItem()->IsType2HWeapon()) { - melee_distance = melee_distance_max * 0.45f; - } - else if ((s_item && s_item->GetItem()->IsTypeShield()) || (!p_item && !s_item)) { - melee_distance = melee_distance_max * 0.35f; - } - else { - melee_distance = melee_distance_max * 0.40f; - } - - break; - case NECROMANCER: - case WIZARD: - case MAGICIAN: - case ENCHANTER: - if (p_item && p_item->GetItem()->IsType2HWeapon()) { - melee_distance = melee_distance_max * 0.95f; - } - else { - melee_distance = melee_distance_max * 0.75f; - } - - break; - case ROGUE: - if (behind_mob && backstab_weapon) { - if (p_item->GetItem()->IsType2HWeapon()) { // 'p_item' tested in 'backstab_weapon' check above - melee_distance = melee_distance_max * 0.30f; - } - else { - melee_distance = melee_distance_max * 0.25f; - } - - break; - } - // Fall-through - default: - if (p_item && p_item->GetItem()->IsType2HWeapon()) { - melee_distance = melee_distance_max * 0.70f; - } - else { - melee_distance = melee_distance_max * 0.50f; - } - - break; - } - } - float melee_distance_min = melee_distance / 2.0f; - - // Calculate caster distances - float caster_distance_max = 0.0f; - float caster_distance_min = 0.0f; - float caster_distance = 0.0f; - { - if (GetLevel() >= GetStopMeleeLevel() && GetClass() >= WARRIOR && GetClass() <= BERSERKER) { - caster_distance_max = MAX_CASTER_DISTANCE[(GetClass() - 1)]; - } - - if (caster_distance_max) { - - caster_distance_min = melee_distance_max; - if (caster_distance_max <= caster_distance_min) { - caster_distance_max = caster_distance_min * 1.25f; - } - - caster_distance = ((caster_distance_max + caster_distance_min) / 2); - } - } - - bool atArcheryRange = IsArcheryRange(tar); - - if (GetRangerAutoWeaponSelect()) { - - bool changeWeapons = false; - - if (atArcheryRange && !IsBotArcher()) { - - SetBotArcherySetting(true); - changeWeapons = true; - } - else if (!atArcheryRange && IsBotArcher()) { - - SetBotArcherySetting(false); - changeWeapons = true; - } - - if (changeWeapons) { - ChangeBotArcherWeapons(IsBotArcher()); - } - } - - if (IsBotArcher() && atArcheryRange) { - atCombatRange = true; - } - else if (caster_distance_max && tar_distance <= caster_distance_max) { - atCombatRange = true; - } - else if (tar_distance <= melee_distance) { - atCombatRange = true; - } - -//#pragma endregion - -//#pragma region ENGAGED AT COMBAT RANGE +// ENGAGED AT COMBAT RANGE // We can fight if (atCombatRange) { - //if (IsMoving() || GetCombatJitterFlag()) { // StopMoving() needs to be called so that the jitter timer can be reset if (IsMoving()) { - - // Since we're using a pseudo-shadowstep for jitter, disregard the combat jitter flag - //if (!GetCombatJitterFlag()) { - StopMoving(CalculateHeadingToTarget(tar->GetX(), tar->GetY())); - //} - + StopMoving(CalculateHeadingToTarget(tar->GetX(), tar->GetY())); return; } - // Combat 'jitter' code - // Note: Combat Jitter is disabled until a working movement solution can be found if (AI_movement_timer->Check() && (!spellend_timer.Enabled() || GetClass() == BARD)) { - if (!IsRooted()) { - - if (HasTargetReflection()) { - - if (!tar->IsFeared() && !tar->IsStunned()) { - - if (GetClass() == ROGUE) { - - if (m_evade_timer.Check(false)) { // Attempt to evade - - int timer_duration = (HideReuseTime - GetSkillReuseTime(EQ::skills::SkillHide)) * 1000; - if (timer_duration < 0) { - timer_duration = 0; - } - - m_evade_timer.Start(timer_duration); - if (zone->random.Int(0, 260) < (int)GetSkill(EQ::skills::SkillHide)) { - RogueEvade(tar); - } - - return; - } - } - - //if (tar->IsRooted()) { // Move caster/rogue back from rooted mob - out of combat range, if necessary - - // if (GetArchetype() == ARCHETYPE_CASTER || GetClass() == ROGUE) { - - // if (tar_distance <= melee_distance_max) { - - // if (PlotPositionAroundTarget(this, Goal.x, Goal.y, Goal.z)) { - // //if (PlotPositionBehindMeFacingTarget(tar, Goal.x, Goal.y, Goal.z)) { - - // Teleport(Goal); - // //WalkTo(Goal.x, Goal.y, Goal.z); - // SetCombatJitterFlag(); - - // return; - // } - // } - // } - //} - } - } - //else { - - // if (caster_distance_min && tar_distance < caster_distance_min && !tar->IsFeared()) { // Caster back-off adjustment - - // if (PlotPositionAroundTarget(this, Goal.x, Goal.y, Goal.z)) { - // //if (PlotPositionBehindMeFacingTarget(tar, Goal.x, Goal.y, Goal.z)) { - - // if (DistanceSquared(Goal, tar->GetPosition()) <= caster_distance_max) { - - // Teleport(Goal); - // //WalkTo(Goal.x, Goal.y, Goal.z); - // SetCombatJitterFlag(); - - // return; - // } - // } - // } - // else if (tar_distance < melee_distance_min) { // Melee back-off adjustment - - // if (PlotPositionAroundTarget(this, Goal.x, Goal.y, Goal.z)) { - // //if (PlotPositionBehindMeFacingTarget(tar, Goal.x, Goal.y, Goal.z)) { - - // if (DistanceSquared(Goal, tar->GetPosition()) <= melee_distance_max) { - - // Teleport(Goal); - // //WalkTo(Goal.x, Goal.y, Goal.z); - // SetCombatJitterFlag(); - - // return; - // } - // } - // } - // else if (backstab_weapon && !behind_mob) { // Move the rogue to behind the mob - - // if (PlotPositionAroundTarget(tar, Goal.x, Goal.y, Goal.z)) { - // //if (PlotPositionOnArcBehindTarget(tar, Goal.x, Goal.y, Goal.z, melee_distance)) { - - // float distance_squared = DistanceSquared(Goal, tar->GetPosition()); - // if (/*distance_squared >= melee_distance_min && */distance_squared <= melee_distance_max) { - - // Teleport(Goal); - // //RunTo(Goal.x, Goal.y, Goal.z); - // SetCombatJitterFlag(); - - // return; - // } - // } - // } - // else if (m_combat_jitter_timer.Check()) { - - // if (!caster_distance && PlotPositionAroundTarget(tar, Goal.x, Goal.y, Goal.z)) { - // //if (!caster_distance && PlotPositionOnArcInFrontOfTarget(tar, Goal.x, Goal.y, Goal.z, melee_distance)) { - - // float distance_squared = DistanceSquared(Goal, tar->GetPosition()); - // if (/*distance_squared >= melee_distance_min && */distance_squared <= melee_distance_max) { - - // Teleport(Goal); - // //WalkTo(Goal.x, Goal.y, Goal.z); - // SetCombatJitterFlag(); - - // return; - // } - // } - // else if (caster_distance && PlotPositionAroundTarget(tar, Goal.x, Goal.y, Goal.z)) { - // //else if (caster_distance && PlotPositionOnArcInFrontOfTarget(tar, Goal.x, Goal.y, Goal.z, caster_distance)) { - - // float distance_squared = DistanceSquared(Goal, tar->GetPosition()); - // if (/*distance_squared >= caster_distance_min && */distance_squared <= caster_distance_max) { - - // Teleport(Goal); - // //WalkTo(Goal.x, Goal.y, Goal.z); - // SetCombatJitterFlag(); - - // return; - // } - // } - // } - - // if (!IsFacingMob(tar)) { - - // FaceTarget(tar); - // return; - // } - //} + if (TryEvade(tar)) { + return; } - else { - if (!IsSitting() && !IsFacingMob(tar)) { - - FaceTarget(tar); - return; - } + if (TryFacingTarget(tar)) { + return; } } @@ -3349,139 +2137,24 @@ void Bot::AI_Process() } // Up to this point, GetTarget() has been safe to dereference since the initial - // TEST_COMBATANTS() call. Due to the chance of the target dying and our pointer + // if (!GetTarget() || GetAppearance() == eaDead) { return false; } call. Due to the chance of the target dying and our pointer // being nullified, we need to test it before dereferencing to avoid crashes - if (IsBotArcher() && ranged_timer.Check(false)) { // Can shoot mezzed, stunned and dead!? - - TEST_COMBATANTS(); - if (GetTarget()->GetHPRatio() <= 99.0f) { - BotRangedAttack(tar); - } + if (IsBotArcher() && TryRangedAttack(tar)) { + return; } - else if (!IsBotArcher() && GetLevel() < GetStopMeleeLevel()) { - // We can't fight if we don't have a target, are stun/mezzed or dead.. - // Stop attacking if the target is enraged - TEST_COMBATANTS(); - if (tar->IsEnraged() && !BehindMob(tar, GetX(), GetY())) { + if (!IsBotArcher() && GetLevel() < GetStopMeleeLevel()) { + if (!TryClassAttacks(tar)) { return; } - // First, special attack per class (kick, backstab etc..) - TEST_COMBATANTS(); - DoClassAttacks(tar); - - TEST_COMBATANTS(); - if (attack_timer.Check()) { // Process primary weapon attacks - - Attack(tar, EQ::invslot::slotPrimary); - - TEST_COMBATANTS(); - TriggerDefensiveProcs(tar, EQ::invslot::slotPrimary, false); - - TEST_COMBATANTS(); - TryCombatProcs(p_item, tar, EQ::invslot::slotPrimary); - - // bool tripleSuccess = false; - - TEST_COMBATANTS(); - if (CanThisClassDoubleAttack()) { - - if (CheckBotDoubleAttack()) { - Attack(tar, EQ::invslot::slotPrimary, true); - } - - TEST_COMBATANTS(); - if (GetSpecialAbility(SPECATK_TRIPLE) && CheckBotDoubleAttack(true)) { - // tripleSuccess = true; - Attack(tar, EQ::invslot::slotPrimary, true); - } - - TEST_COMBATANTS(); - // quad attack, does this belong here?? - if (GetSpecialAbility(SPECATK_QUAD) && CheckBotDoubleAttack(true)) { - Attack(tar, EQ::invslot::slotPrimary, true); - } - } - - TEST_COMBATANTS(); - // Live AA - Flurry, Rapid Strikes ect (Flurry does not require Triple Attack). - int32 flurrychance = (aabonuses.FlurryChance + spellbonuses.FlurryChance + itembonuses.FlurryChance); - if (flurrychance) { - - if (zone->random.Int(0, 100) < flurrychance) { - - MessageString(Chat::NPCFlurry, YOU_FLURRY); - Attack(tar, EQ::invslot::slotPrimary, false); - - TEST_COMBATANTS(); - Attack(tar, EQ::invslot::slotPrimary, false); - } - } - - TEST_COMBATANTS(); - auto ExtraAttackChanceBonus = - (spellbonuses.ExtraAttackChance[0] + itembonuses.ExtraAttackChance[0] + - aabonuses.ExtraAttackChance[0]); - if (ExtraAttackChanceBonus) { - - if (p_item && p_item->GetItem()->IsType2HWeapon()) { - - if (zone->random.Int(0, 100) < ExtraAttackChanceBonus) { - Attack(tar, EQ::invslot::slotPrimary, false); - } - } - } + if (!TryPrimaryWeaponAttacks(tar, p_item)) { + return; } - TEST_COMBATANTS(); - if (attack_dw_timer.Check() && CanThisClassDualWield()) { // Process secondary weapon attacks - - const EQ::ItemData* s_itemdata = nullptr; - // Can only dual wield without a weapon if you're a monk - if (s_item || (GetClass() == MONK)) { - - if (s_item) { - s_itemdata = s_item->GetItem(); - } - - int weapon_type = 0; // No weapon type. - bool use_fist = true; - if (s_itemdata) { - - weapon_type = s_itemdata->ItemType; - use_fist = false; - } - - if (use_fist || !s_itemdata->IsType2HWeapon()) { - - float DualWieldProbability = 0.0f; - - int32 Ambidexterity = (aabonuses.Ambidexterity + spellbonuses.Ambidexterity + itembonuses.Ambidexterity); - DualWieldProbability = ((GetSkill(EQ::skills::SkillDualWield) + GetLevel() + Ambidexterity) / 400.0f); // 78.0 max - - int32 DWBonus = (spellbonuses.DualWieldChance + itembonuses.DualWieldChance); - DualWieldProbability += (DualWieldProbability * float(DWBonus) / 100.0f); - - float random = zone->random.Real(0, 1); - if (random < DualWieldProbability) { // Max 78% of DW - - Attack(tar, EQ::invslot::slotSecondary); // Single attack with offhand - - TEST_COMBATANTS(); - TryCombatProcs(s_item, tar, EQ::invslot::slotSecondary); - - TEST_COMBATANTS(); - if (CanThisClassDoubleAttack() && CheckBotDoubleAttack()) { - - if (tar->GetHP() > -10) { - Attack(tar, EQ::invslot::slotSecondary); // Single attack with offhand - } - } - } - } - } + if (!TrySecondaryWeaponAttacks(tar, s_item)) { + return; } } @@ -3490,68 +2163,15 @@ void Bot::AI_Process() } } -//#pragma endregion +// ENGAGED NOT AT COMBAT RANGE -//#pragma region ENGAGED NOT AT COMBAT RANGE + else if (!TryPursueTarget(leash_distance, Goal)) { + return; + } - else { // To far away to fight (GetTarget() validity can be iffy below this point - including outer scopes) - - // This code actually gets processed when we are too far away from target and have not engaged yet, too - if (/*!GetCombatJitterFlag() && */AI_movement_timer->Check() && (!spellend_timer.Enabled() || GetClass() == BARD)) { // Pursue processing - - if (GetTarget() && !IsRooted()) { - - LogAIDetail("Pursuing [{}] while engaged", GetTarget()->GetCleanName()); - Goal = GetTarget()->GetPosition(); - if (DistanceSquared(m_Position, Goal) <= leash_distance) { - RunTo(Goal.x, Goal.y, Goal.z); - } - else { - - WipeHateList(); - SetTarget(nullptr); - if (HasPet() && (GetClass() != ENCHANTER || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 2)) { - - GetPet()->WipeHateList(); - GetPet()->SetTarget(nullptr); - } - } - - return; - } - else { - - if (IsMoving()) { - StopMoving(); - } - return; - } - } - - if (GetTarget() && GetTarget()->IsFeared() && !spellend_timer.Enabled() && AI_think_timer->Check()) { - - if (!IsFacingMob(GetTarget())) { - FaceTarget(GetTarget()); - } - - // This is a mob that is fleeing either because it has been feared or is low on hitpoints - AI_PursueCastCheck(); // This appears to always return true..can't trust for success/fail - - return; - } - } // End not in combat range - -//#pragma endregion - - if (!IsMoving() && !spellend_timer.Enabled()) { // This may actually need work... - - if (GetTarget() && AI_EngagedCastCheck()) { - BotMeditate(false); - } - else if (GetArchetype() == ARCHETYPE_CASTER) { - BotMeditate(true); - } +// End not in combat range + if (TryMeditate()) { return; } } @@ -3565,60 +2185,12 @@ void Bot::AI_Process() SetReturningFlag(false); } -//#pragma region AUTO DEFEND +// AUTO DEFEND - // This is as close as I could get without modifying the aggro mechanics and making it an expensive process... - // 'class Client' doesn't make use of hate_list... - if (RuleB(Bots, AllowOwnerOptionAutoDefend) && bot_owner->GetBotOption(Client::booAutoDefend)) { - - if (!m_auto_defend_timer.Enabled()) { - - m_auto_defend_timer.Start(zone->random.Int(250, 1250)); // random timer to simulate 'awareness' (cuts down on scanning overhead) - return; - } - - if (m_auto_defend_timer.Check() && bot_owner->GetAggroCount()) { - - if (NOT_HOLDING && NOT_PASSIVE) { - - auto xhaters = bot_owner->GetXTargetAutoMgr(); - if (xhaters && !xhaters->empty()) { - - for (auto hater_iter : xhaters->get_list()) { - - if (!hater_iter.spawn_id) { - continue; - } - - if (bot_owner->GetBotPulling() && bot_owner->GetTarget() && hater_iter.spawn_id == bot_owner->GetTarget()->GetID()) { - continue; - } - - auto hater = entity_list.GetMob(hater_iter.spawn_id); - if (hater && !hater->IsMezzed() && DistanceSquared(hater->GetPosition(), bot_owner->GetPosition()) <= leash_distance) { - - // This is roughly equivilent to npc attacking a client pet owner - AddToHateList(hater, 1); - SetTarget(hater); - SetAttackingFlag(); - if (HasPet() && (GetClass() != ENCHANTER || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 2)) { - - GetPet()->AddToHateList(hater, 1); - GetPet()->SetTarget(hater); - } - - m_auto_defend_timer.Disable(); - - return; - } - } - } - } - } + if (TryAutoDefend(bot_owner, leash_distance) ) { + return; } -//#pragma endregion - SetTarget(nullptr); if (HasPet() && (GetClass() != ENCHANTER || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 1)) { @@ -3631,309 +2203,1031 @@ void Bot::AI_Process() SendRemovePlayerState(PlayerState::Aggressive); } -//#pragma region OK TO IDLE +// OK TO IDLE // Ok to idle - if ((NOT_GUARDING && fm_distance <= GetFollowDistance()) || (GUARDING && DistanceSquared(GetPosition(), GetGuardPoint()) <= GetFollowDistance())) { - - if (!IsMoving() && AI_think_timer->Check() && !spellend_timer.Enabled()) { - - if (NOT_PASSIVE) { - - if (!AI_IdleCastCheck() && !IsCasting() && GetClass() != BARD) { - BotMeditate(true); - } - } - else { - - if (GetClass() != BARD) { - BotMeditate(true); - } - } - - return; - } - } - - // Non-engaged movement checks - if (AI_movement_timer->Check() && (!IsCasting() || GetClass() == BARD)) { - - if (GUARDING) { - Goal = GetGuardPoint(); - } - else { - Goal = follow_mob->GetPosition(); - } - float destination_distance = DistanceSquared(GetPosition(), Goal); - - if ((!bot_owner->GetBotPulling() || PULLING_BOT) && (destination_distance > GetFollowDistance())) { - - if (!IsRooted()) { - - if (rest_timer.Enabled()) { - rest_timer.Disable(); - } - - bool running = true; - - if (destination_distance < GetFollowDistance() + BOT_FOLLOW_DISTANCE_WALK) { - running = false; - } - - if (running) { - RunTo(Goal.x, Goal.y, Goal.z); - } - else { - WalkTo(Goal.x, Goal.y, Goal.z); - } - - return; - } - } - else { - - if (IsMoving()) { - - StopMoving(); - return; - } - } - } - - // Basically, bard bots get a chance to cast idle spells while moving - if (GetClass() == BARD && IsMoving() && NOT_PASSIVE) { - - if (!spellend_timer.Enabled() && AI_think_timer->Check()) { - - AI_IdleCastCheck(); - return; - } - } - -//#pragma endregion - - } - -#undef TEST_COMBATANTS -#undef PULLING_BOT -#undef NOT_PULLING_BOT -#undef GUARDING -#undef NOT_GUARDING -#undef HOLDING -#undef NOT_HOLDING -#undef PASSIVE -#undef NOT_PASSIVE -} - -// AI Processing for a Bot object's pet -void Bot::PetAIProcess() { - if( !HasPet() || !GetPet() || !GetPet()->IsNPC()) - return; - - Mob* BotOwner = GetBotOwner(); - NPC* botPet = GetPet()->CastToNPC(); - if(!botPet->GetOwner() || !botPet->GetID() || !botPet->GetOwnerID()) { - Kill(); - return; - } - - if (!botPet->IsAIControlled() || botPet->GetAttackTimer().Check(false) || botPet->IsCasting() || !botPet->GetOwner()->IsBot()) - return; - - if (IsEngaged()) { - if (botPet->IsRooted()) - botPet->SetTarget(hate_list.GetClosestEntOnHateList(botPet)); - else - botPet->SetTarget(hate_list.GetEntWithMostHateOnList(botPet)); - - // Let's check if we have a los with our target. - // If we don't, our hate_list is wiped. - // It causes some cpu stress but without it, it was causing the bot/pet to aggro behind wall, floor etc... - if(!botPet->CheckLosFN(botPet->GetTarget()) || botPet->GetTarget()->IsMezzed() || !botPet->IsAttackAllowed(GetTarget())) { - botPet->WipeHateList(); - botPet->SetTarget(botPet->GetOwner()); + if (TryIdleChecks(fm_distance)) { return; } + if (TryNonCombatMovementChecks(bot_owner, follow_mob, Goal)) { + return; + } + if (TryBardMovementCasts()) { + return; + } + } +} - botPet->FaceTarget(botPet->GetTarget()); - bool is_combat_range = botPet->CombatRange(botPet->GetTarget()); - // Ok, we're engaged, each class type has a special AI - // Only melee class will go to melee. Casters and healers will stay behind, following the leader by default. - // I should probably make the casters staying in place so they can cast.. +bool Bot::TryBardMovementCasts() {// Basically, bard bots get a chance to cast idle spells while moving - // Ok, we 're a melee or any other class lvl<12. Yes, because after it becomes hard to go in melee for casters.. even for bots.. - if(is_combat_range) { - botPet->GetAIMovementTimer()->Check(); - if(botPet->IsMoving()) { - botPet->SetHeading(botPet->GetTarget()->GetHeading()); - if(moved) { - moved = false; - botPet->SetRunAnimSpeed(0); + if (GetClass() == BARD && IsMoving() && NOT_PASSIVE && !spellend_timer.Enabled() && AI_think_timer->Check()) { + + AI_IdleCastCheck(); + return true; + } + return false; +} + +bool Bot::TryNonCombatMovementChecks(Client* bot_owner, const Mob* follow_mob, glm::vec3& Goal) {// Non-engaged movement checks + + if (AI_movement_timer->Check() && (!IsCasting() || GetClass() == BARD)) { + if (GUARDING) { + Goal = GetGuardPoint(); + } + else { + Goal = follow_mob->GetPosition(); + } + float destination_distance = DistanceSquared(GetPosition(), Goal); + + if ((!bot_owner->GetBotPulling() || PULLING_BOT) && (destination_distance > GetFollowDistance())) { + + if (!IsRooted()) { + + if (rest_timer.Enabled()) { + rest_timer.Disable(); } + + bool running = true; + + if (destination_distance < GetFollowDistance() + BOT_FOLLOW_DISTANCE_WALK) { + running = false; + } + + if (running) { + RunTo(Goal.x, Goal.y, Goal.z); + } + else { + WalkTo(Goal.x, Goal.y, Goal.z); + } + + return true; + } + } + else { + + if (IsMoving()) { + + StopMoving(); + return true; + } + } + } + return false; +} + +bool Bot::TryIdleChecks(float fm_distance) { + + if ( + ( + (NOT_GUARDING && fm_distance <= GetFollowDistance()) || + (GUARDING && DistanceSquared(GetPosition(), GetGuardPoint()) <= GetFollowDistance())) && + !IsMoving() && + AI_think_timer->Check() && + !spellend_timer.Enabled() + ) { + + if (NOT_PASSIVE) { + + if (!AI_IdleCastCheck() && !IsCasting() && GetClass() != BARD) { + BotMeditate(true); } - if(!botPet->IsMoving()) { - float newX = 0; - float newY = 0; - float newZ = 0; - bool petHasAggro = false; - if(botPet->GetTarget() && botPet->GetTarget()->GetHateTop() && botPet->GetTarget()->GetHateTop() == botPet) - petHasAggro = true; - - if(botPet->GetClass() == ROGUE && !petHasAggro && !botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY())) { - // Move the rogue to behind the mob - if(botPet->PlotPositionAroundTarget(botPet->GetTarget(), newX, newY, newZ)) { - botPet->RunTo(newX, newY, newZ); - return; - } - } - else if(GetTarget() == botPet->GetTarget() && !petHasAggro && !botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY())) { - // If the bot owner and the bot are fighting the same mob, then move the pet to the rear arc of the mob - if(botPet->PlotPositionAroundTarget(botPet->GetTarget(), newX, newY, newZ)) { - botPet->RunTo(newX, newY, newZ); - return; - } - } - else if(DistanceSquaredNoZ(botPet->GetPosition(), botPet->GetTarget()->GetPosition()) < botPet->GetTarget()->GetSize()) { - // Let's try to adjust our melee range so we don't appear to be bunched up - bool isBehindMob = false; - bool moveBehindMob = false; - if(botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY())) - isBehindMob = true; - - if (!isBehindMob && !petHasAggro) - moveBehindMob = true; - - if(botPet->PlotPositionAroundTarget(botPet->GetTarget(), newX, newY, newZ, moveBehindMob)) { - botPet->RunTo(newX, newY, newZ); - return; - } - } - } - - // we can't fight if we don't have a target, are stun/mezzed or dead.. - if(botPet->GetTarget() && !botPet->IsStunned() && !botPet->IsMezzed() && (botPet->GetAppearance() != eaDead)) { - // check the delay on the attack - if(botPet->GetAttackTimer().Check()) { - // Stop attacking while we are on a front arc and the target is enraged - if(!botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY()) && botPet->GetTarget()->IsEnraged()) - return; - - if (botPet->Attack(GetTarget(), EQ::invslot::slotPrimary)) // try the main hand - if (botPet->GetTarget()) { - // We're a pet so we re able to dual attack - int32 RandRoll = zone->random.Int(0, 99); - if (botPet->CanThisClassDoubleAttack() && (RandRoll < (botPet->GetLevel() + NPCDualAttackModifier))) { - if (botPet->Attack(botPet->GetTarget(), EQ::invslot::slotPrimary)) {} - } - } - - if (botPet->GetOwner()->IsBot()) { - int aa_chance = 0; - int aa_skill = 0; - // Magician AA - aa_skill += botPet->GetOwner()->GetAA(aaElementalAlacrity); - // Necromancer AA - aa_skill += botPet->GetOwner()->GetAA(aaQuickeningofDeath); - // Beastlord AA - aa_skill += botPet->GetOwner()->GetAA(aaWardersAlacrity); - if(aa_skill >= 1) - aa_chance += ((aa_skill > 5 ? 5 : aa_skill) * 4); - - if(aa_skill >= 6) - aa_chance += ((aa_skill - 5 > 3 ? 3 : aa_skill - 5) * 7); - - if(aa_skill >= 9) - aa_chance += ((aa_skill - 8 > 3 ? 3 : aa_skill - 8) * 3); - - if(aa_skill >= 12) - aa_chance += ((aa_skill - 11) * 1); - - - //aa_chance += botPet->GetOwner()->GetAA(aaCompanionsAlacrity) * 3; - - if (zone->random.Int(1, 100) < aa_chance) - Flurry(nullptr); - } - - // Ok now, let's check pet's offhand. - if (botPet->GetAttackDWTimer().Check() && botPet->GetOwnerID() && botPet->GetOwner() && ((botPet->GetOwner()->GetClass() == MAGICIAN) || (botPet->GetOwner()->GetClass() == NECROMANCER) || (botPet->GetOwner()->GetClass() == SHADOWKNIGHT) || (botPet->GetOwner()->GetClass() == BEASTLORD))) { - if(botPet->GetOwner()->GetLevel() >= 24) { - float DualWieldProbability = ((botPet->GetSkill(EQ::skills::SkillDualWield) + botPet->GetLevel()) / 400.0f); - DualWieldProbability -= zone->random.Real(0, 1); - if(DualWieldProbability < 0) { - botPet->Attack(botPet->GetTarget(), EQ::invslot::slotSecondary); - if (botPet->CanThisClassDoubleAttack()) { - int32 RandRoll = zone->random.Int(0, 99); - if (RandRoll < (botPet->GetLevel() + 20)) - botPet->Attack(botPet->GetTarget(), EQ::invslot::slotSecondary); - } - } - } - } - if(!botPet->GetOwner()) - return; - - // Special attack - botPet->DoClassAttacks(botPet->GetTarget()); - } - // See if the pet can cast any spell - botPet->AI_EngagedCastCheck(); - } } else { - // Now, if we cannot reach our target - if (!botPet->HateSummon()) { - if(botPet->GetTarget() && botPet->AI_PursueCastCheck()) {} - else if (botPet->GetTarget() && botPet->GetAIMovementTimer()->Check()) { - botPet->SetRunAnimSpeed(0); - if(!botPet->IsRooted()) { - LogAIDetail("Pursuing [{}] while engaged", botPet->GetTarget()->GetCleanName()); - botPet->RunTo(botPet->GetTarget()->GetX(), botPet->GetTarget()->GetY(), botPet->GetTarget()->GetZ()); - return; - } else { - botPet->SetHeading(botPet->GetTarget()->GetHeading()); - if(moved) { - moved = false; - StopNavigation(); - botPet->StopNavigation(); + if (GetClass() != BARD) { + BotMeditate(true); + } + + } + return true; + } + return false; +} + +// This is as close as I could get without modifying the aggro mechanics and making it an expensive process... +// 'class Client' doesn't make use of hate_list +bool Bot::TryAutoDefend(Client* bot_owner, float leash_distance) { + + if (RuleB(Bots, AllowOwnerOptionAutoDefend) && bot_owner->GetBotOption(Client::booAutoDefend)) { + + if (!m_auto_defend_timer.Enabled()) { + + m_auto_defend_timer.Start(zone->random.Int(250, 1250)); // random timer to simulate 'awareness' (cuts down on scanning overhead) + return true; + } + + if ( + m_auto_defend_timer.Check() && + bot_owner->GetAggroCount() && + NOT_HOLDING && + NOT_PASSIVE + ) { + auto xhaters = bot_owner->GetXTargetAutoMgr(); + + if (xhaters && !xhaters->empty()) { + for (auto hater_iter : xhaters->get_list()) { + if (!hater_iter.spawn_id) { + continue; + } + + if (bot_owner->GetBotPulling() && bot_owner->GetTarget() && hater_iter.spawn_id == bot_owner->GetTarget()->GetID()) { + continue; + } + + auto hater = entity_list.GetMob(hater_iter.spawn_id); + if (hater && !hater->IsMezzed() && DistanceSquared(hater->GetPosition(), bot_owner->GetPosition()) <= leash_distance) { + // This is roughly equivilent to npc attacking a client pet owner + AddToHateList(hater, 1); + SetTarget(hater); + SetAttackingFlag(); + + if (HasPet() && (GetClass() != ENCHANTER || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 2)) { + GetPet()->AddToHateList(hater, 1); + GetPet()->SetTarget(hater); } + + m_auto_defend_timer.Disable(); + + return true; } } } } - } else { - // Ok if we're not engaged, what's happening.. - if(botPet->GetTarget() != botPet->GetOwner()) - botPet->SetTarget(botPet->GetOwner()); + } + return false; +} - if(!IsMoving()) - botPet->AI_IdleCastCheck(); +bool Bot::TryMeditate() { - if(botPet->GetAIMovementTimer()->Check()) { - switch(pStandingPetOrder) { - case SPO_Follow: { - float dist = DistanceSquared(botPet->GetPosition(), botPet->GetTarget()->GetPosition()); - botPet->SetRunAnimSpeed(0); - if(dist > 184) { - botPet->RunTo(botPet->GetTarget()->GetX(), botPet->GetTarget()->GetY(), botPet->GetTarget()->GetZ()); - return; - } else { - botPet->SetHeading(botPet->GetTarget()->GetHeading()); - if(moved) { - moved = false; - StopNavigation(); - botPet->StopNavigation(); - } - } - break; + if (!IsMoving() && !spellend_timer.Enabled()) { + if (GetTarget() && AI_EngagedCastCheck()) { + BotMeditate(false); + } else if (GetArchetype() == ARCHETYPE_CASTER) { + BotMeditate(true); + } + + if (!(GetPlayerState() & static_cast(PlayerState::Aggressive))) { + SendAddPlayerState(PlayerState::Aggressive); + } + return true; + } + return false; +} + +// This code actually gets processed when we are too far away from target and have not engaged yet +bool Bot::TryPursueTarget(float leash_distance, glm::vec3& Goal) { + + if (AI_movement_timer->Check() && (!spellend_timer.Enabled() || GetClass() == BARD)) { + if (GetTarget() && !IsRooted()) { + LogAIDetail("Pursuing [{}] while engaged", GetTarget()->GetCleanName()); + Goal = GetTarget()->GetPosition(); + if (DistanceSquared(m_Position, Goal) <= leash_distance) { + RunTo(Goal.x, Goal.y, Goal.z); + + } else { + WipeHateList(); + SetTarget(nullptr); + + if (HasPet() && (GetClass() != ENCHANTER || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 2)) { + GetPet()->WipeHateList(); + GetPet()->SetTarget(nullptr); } - case SPO_Sit: - botPet->SetAppearance(eaSitting); - break; - case SPO_Guard: - botPet->NextGuardPosition(); - break; } + return true; + + } else { + if (IsMoving()) { + StopMoving(); + } + + return false; + } + } + + if (GetTarget() && GetTarget()->IsFeared() && !spellend_timer.Enabled() && AI_think_timer->Check()) { + if (!IsFacingMob(GetTarget())) { + FaceTarget(GetTarget()); + } + + // This is a mob that is fleeing either because it has been feared or is low on hitpoints + AI_PursueCastCheck(); + + return true; + } + return false; +} + +bool Bot::TrySecondaryWeaponAttacks(Mob* tar, const EQ::ItemInstance* s_item) { + + if (!GetTarget() || GetAppearance() == eaDead) { return false; } + if (attack_dw_timer.Check() && CanThisClassDualWield()) { + const EQ::ItemData* s_itemdata = nullptr; + + // Can only dual wield without a weapon if you're a monk + if (s_item || (GetClass() == MONK)) { + + if (s_item) { + s_itemdata = s_item->GetItem(); + } + + bool use_fist = true; + if (s_itemdata) { + use_fist = false; + } + + if (use_fist || !s_itemdata->IsType2HWeapon()) { + + float DualWieldProbability = 0.0f; + + int32 Ambidexterity = (aabonuses.Ambidexterity + spellbonuses.Ambidexterity + itembonuses.Ambidexterity); + DualWieldProbability = ((GetSkill(EQ::skills::SkillDualWield) + GetLevel() + Ambidexterity) / 400.0f); // 78.0 max chance + + int32 DWBonus = (spellbonuses.DualWieldChance + itembonuses.DualWieldChance); + DualWieldProbability += (DualWieldProbability * float(DWBonus) / 100.0f); + + float random = zone->random.Real(0, 1); + if (random < DualWieldProbability) { // Max 78% for DW chance + Attack(tar, EQ::invslot::slotSecondary); // Single attack with offhand + + if (!GetTarget() || GetAppearance() == eaDead) { return false; } + TryCombatProcs(s_item, tar, EQ::invslot::slotSecondary); + + if (!GetTarget() || GetAppearance() == eaDead) { return false; } + if (CanThisClassDoubleAttack() && CheckBotDoubleAttack() && tar->GetHP() > -10) { + Attack(tar, EQ::invslot::slotSecondary); // Single attack with offhand + } + } + } + } + } + return true; +} + +bool Bot::TryPrimaryWeaponAttacks(Mob* tar, const EQ::ItemInstance* p_item) { + + if (!GetTarget() || GetAppearance() == eaDead) { return false; } + if (attack_timer.Check()) { // Process primary weapon attacks + + Attack(tar, EQ::invslot::slotPrimary); + + if (!GetTarget() || GetAppearance() == eaDead) { return false; } + TriggerDefensiveProcs(tar, EQ::invslot::slotPrimary, false); + + if (!GetTarget() || GetAppearance() == eaDead) { return false; } + TryCombatProcs(p_item, tar, EQ::invslot::slotPrimary); + + if (!GetTarget() || GetAppearance() == eaDead) { return false; } + if (CanThisClassDoubleAttack()) { + + if (CheckBotDoubleAttack()) { + Attack(tar, EQ::invslot::slotPrimary, true); + } + + if (!GetTarget() || GetAppearance() == eaDead) { return false; } + if (GetSpecialAbility(SPECATK_TRIPLE) && CheckBotDoubleAttack(true)) { + + Attack(tar, EQ::invslot::slotPrimary, true); + } + + if (!GetTarget() || GetAppearance() == eaDead) { return false; } + // quad attack, does this belong here?? + if (GetSpecialAbility(SPECATK_QUAD) && CheckBotDoubleAttack(true)) { + Attack(tar, EQ::invslot::slotPrimary, true); + } + } + + if (!GetTarget() || GetAppearance() == eaDead) { return false; } + // Live AA - Flurry, Rapid Strikes ect (Flurry does not require Triple Attack). + if (int32 flurrychance = (aabonuses.FlurryChance + spellbonuses.FlurryChance + itembonuses.FlurryChance)) { + + if (zone->random.Int(0, 100) < flurrychance) { + + MessageString(Chat::NPCFlurry, YOU_FLURRY); + Attack(tar, EQ::invslot::slotPrimary, false); + + if (!GetTarget() || GetAppearance() == eaDead) { return false; } + Attack(tar, EQ::invslot::slotPrimary, false); + } + } + + if (!GetTarget() || GetAppearance() == eaDead) { return false; } + auto ExtraAttackChanceBonus = + (spellbonuses.ExtraAttackChance[0] + itembonuses.ExtraAttackChance[0] + + aabonuses.ExtraAttackChance[0]); + + if ( + ExtraAttackChanceBonus && + p_item && + p_item->GetItem()->IsType2HWeapon() && + zone->random.Int(0, 100) < ExtraAttackChanceBonus + ) { + Attack(tar, EQ::invslot::slotPrimary, false); + } + } + return true; +} + +// We can't fight if we don't have a target, are stun/mezzed or dead.. +bool Bot::TryClassAttacks(Mob* tar) { + +// Stop attacking if the target is enraged + if (!GetTarget() || GetAppearance() == eaDead) { return false; } + if (tar->IsEnraged() && !BehindMob(tar, GetX(), GetY())) { + return false; + } + + // First, special attack per class (kick, backstab etc..) + DoClassAttacks(tar); + return true; +} + +bool Bot::TryRangedAttack(Mob* tar) { + + if (IsBotArcher() && ranged_timer.Check(false)) { + + if (!GetTarget() || GetAppearance() == eaDead) { return false; } + if (GetTarget()->GetHPRatio() <= 99.0f) { + BotRangedAttack(tar); + } + return true; + } + return false; +} + +bool Bot::TryFacingTarget(Mob* tar) { + + if (!IsSitting() && !IsFacingMob(tar)) { + FaceTarget(tar); + return true; + } + return false; +} + + +bool Bot::TryEvade(Mob* tar) { + + if ( + !IsRooted() && + HasTargetReflection() && + !tar->IsFeared() && + !tar->IsStunned() && + GetClass() == ROGUE && + m_evade_timer.Check(false) + ) { + int timer_duration = (HideReuseTime - GetSkillReuseTime(EQ::skills::SkillHide)) * 1000; + + if (timer_duration < 0) { + timer_duration = 0; + } + + m_evade_timer.Start(timer_duration); + if (zone->random.Int(0, 260) < (int) GetSkill(EQ::skills::SkillHide)) { + RogueEvade(tar); + } + return true; + } + + return false; +} + +void Bot::CheckCombatRange(Mob* tar, float tar_distance, bool& atCombatRange, const EQ::ItemInstance*& p_item, const EQ::ItemInstance*& s_item) { + + atCombatRange= false; + p_item= GetBotItem(EQ::invslot::slotPrimary); + s_item= GetBotItem(EQ::invslot::slotSecondary); + bool behind_mob = false; + bool backstab_weapon = false; + if (GetClass() == ROGUE) { + + behind_mob = BehindMob(tar, GetX(), GetY()); // Can be separated for other future use + backstab_weapon = p_item && p_item->GetItemBackstabDamage(); + } + + // Calculate melee distances + float melee_distance_max = 0.0f; + float melee_distance = 0.0f; + + CalcMeleeDistances(tar, p_item, s_item, behind_mob, backstab_weapon, melee_distance_max, melee_distance); + + float caster_distance_max = GetBotCasterMaxRange(melee_distance_max); + + bool atArcheryRange = IsArcheryRange(tar); + + SetRangerCombatWeapon(atArcheryRange); + + bool stop_melee_level = GetLevel() >= GetStopMeleeLevel(); + if (IsBotArcher() && atArcheryRange) { + atCombatRange = true; + } + else if (caster_distance_max && tar_distance <= caster_distance_max && stop_melee_level) { + atCombatRange = true; + } + else if (tar_distance <= melee_distance) { + atCombatRange = true; + } +} + +void Bot::SetRangerCombatWeapon(bool atArcheryRange) { + + if (GetRangerAutoWeaponSelect()) { + bool changeWeapons = false; + + if (atArcheryRange && !IsBotArcher()) { + SetBotArcherySetting(true); + changeWeapons = true; + } + + else if (!atArcheryRange && IsBotArcher()) { + SetBotArcherySetting(false); + changeWeapons = true; + } + + if (changeWeapons) { + ChangeBotArcherWeapons(IsBotArcher()); + } + } +} + +void Bot::CalcMeleeDistances(const Mob* tar, const EQ::ItemInstance* const& p_item, const EQ::ItemInstance* const& s_item, bool behind_mob, bool backstab_weapon, float& melee_distance_max, float& melee_distance) const { + + float size_mod = GetSize(); + float other_size_mod = tar->GetSize(); + + // For races with a fixed size + if (GetRace() == RT_DRAGON || GetRace() == RT_WURM || GetRace() == RT_DRAGON_7) { + // size_mod = 60.0f; + } + + else if (size_mod < 6.0f) { + size_mod = 8.0f; + } + + // For races with a fixed size + if (tar->GetRace() == RT_DRAGON || tar->GetRace() == RT_WURM || tar->GetRace() == RT_DRAGON_7) { + other_size_mod = 60.0f; + } + + else if (other_size_mod < 6.0f) { + other_size_mod = 8.0f; + } + + if (other_size_mod > size_mod) { + size_mod = other_size_mod; + } + + if (size_mod > 29.0f) { + size_mod *= size_mod; + } + + else if (size_mod > 19.0f) { + size_mod *= (size_mod * 2.0f); + } + + else { + size_mod *= (size_mod * 4.0f); + } + + // Prevention of ridiculously sized hit boxes + if (size_mod > 10000.0f) { + size_mod = (size_mod / 7.0f); + } + + melee_distance_max = size_mod; + + switch (GetClass()) { + case WARRIOR: + case PALADIN: + case SHADOWKNIGHT: + if (p_item && p_item->GetItem()->IsType2HWeapon()) { + melee_distance = melee_distance_max * 0.45f; + } + else if ((s_item && s_item->GetItem()->IsTypeShield()) || (!p_item && !s_item)) { + melee_distance = melee_distance_max * 0.35f; + } + else { + melee_distance = melee_distance_max * 0.40f; + } + break; + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + if (p_item && p_item->GetItem()->IsType2HWeapon()) { + melee_distance = melee_distance_max * 0.95f; + } + else { + melee_distance = melee_distance_max * 0.75f; + } + break; + case ROGUE: + if (behind_mob && backstab_weapon) { + if (p_item->GetItem()->IsType2HWeapon()) { + melee_distance = melee_distance_max * 0.30f; + } + else { + melee_distance = melee_distance_max * 0.25f; + } + break; + } + // Fall-through + default: + if (p_item && p_item->GetItem()->IsType2HWeapon()) { + melee_distance = melee_distance_max * 0.70f; + } + else { + melee_distance = melee_distance_max * 0.50f; + } + + break; + } +} + +bool Bot::IsValidTarget(Client* bot_owner, Client* leash_owner, float lo_distance, float leash_distance, bool bo_alt_combat, Mob* tar, float tar_distance) { + + if (HOLDING || + !tar->IsNPC() || + tar->IsMezzed() || + lo_distance > leash_distance || + tar_distance > leash_distance || + (!GetAttackingFlag() && !CheckLosFN(tar) && !leash_owner->CheckLosFN(tar)) || // This is suppose to keep bots from attacking things behind walls + !IsAttackAllowed(tar) || + (bo_alt_combat && + (!GetAttackingFlag() && NOT_PULLING_BOT && !leash_owner->AutoAttackEnabled() && !tar->GetHateAmount(this) && !tar->GetHateAmount(leash_owner)) + ) + ) + { + // Normally, we wouldn't want to do this without class checks..but, too many issues can arise if we let enchanter animation pets run rampant + if (HasPet()) { + GetPet()->RemoveFromHateList(tar); + GetPet()->SetTarget(nullptr); + } + + RemoveFromHateList(tar); + SetTarget(nullptr); + + SetAttackFlag(false); + SetAttackingFlag(false); + + if (PULLING_BOT) { + SetPullingFlag(false); + SetReturningFlag(false); + bot_owner->SetBotPulling(false); + if (GetPet()) { + GetPet()->SetPetOrder(m_previous_pet_order); + } + } + + if (IsMoving()) { + StopMoving(); + } + + return false; + } + return true; +} + +Mob* Bot::GetBotTarget(Client* bot_owner) { + + Mob* tar = GetTarget(); + if (!tar || PASSIVE) { + if (GetTarget()) { + SetTarget(nullptr); + } + + WipeHateList(); + SetAttackFlag(false); + SetAttackingFlag(false); + if (PULLING_BOT) { + + // 'Flags' should only be set on the bot that is pulling + SetPullingFlag(false); + SetReturningFlag(false); + bot_owner->SetBotPulling(false); + if (GetPet()) { + GetPet()->SetPetOrder(m_previous_pet_order); + } + } + + if (GetArchetype() == ARCHETYPE_CASTER) { + BotMeditate(true); + } + } + return tar; +} + +void Bot::AcquireBotTarget(Group* bot_group, Raid* raid, Client* leash_owner, float leash_distance) {// Group roles can be expounded upon in the future + Mob* assist_mob = nullptr; + bool find_target = true; + + if (bot_group) { + assist_mob = entity_list.GetMob(bot_group->GetMainAssistName()); + } + else if (raid) { + assist_mob = raid->GetRaidMainAssistOneByName(GetName()); + } + + if (assist_mob) { + if (assist_mob->GetTarget()) { + if (assist_mob != this) { + if (GetTarget() != assist_mob->GetTarget()) { + SetTarget(assist_mob->GetTarget()); + } + + if ( + HasPet() && + ( + GetClass() != ENCHANTER || + GetPet()->GetPetType() != petAnimation || + GetAA(aaAnimationEmpathy) >= 2 + ) + ) { + // This artificially inflates pet's target aggro..but, less expensive than checking hate each AI process + GetPet()->AddToHateList(assist_mob->GetTarget(), 1); + GetPet()->SetTarget(assist_mob->GetTarget()); + } + } + + find_target = false; + } else if (assist_mob != this) { + if (GetTarget()) { + SetTarget(nullptr); + } + + if ( + HasPet() && + ( + GetClass() != ENCHANTER || + GetPet()->GetPetType() != petAnimation || + GetAA(aaAnimationEmpathy) >= 1 + ) + ) { + GetPet()->WipeHateList(); + GetPet()->SetTarget(nullptr); + } + + find_target = false; + } + } + + if (find_target) { + if (IsRooted()) { + auto closest = hate_list.GetClosestEntOnHateList(this, true); + if (closest) { + SetTarget(closest); + } + } else { + // This will keep bots on target for now..but, future updates will allow for rooting/stunning + if (auto escaping = hate_list.GetEscapingEntOnHateList(leash_owner, leash_distance)) { + SetTarget(escaping); + } + + if (!GetTarget()) { + auto most_hate = hate_list.GetEntWithMostHateOnList(this, nullptr, true); + if (most_hate) { + SetTarget(most_hate); + } + } + } + } +} + +bool Bot::ReturningFlagChecks(Client* bot_owner, float fm_distance) {// Need to make it back to group before clearing return flag + + if (fm_distance <= GetFollowDistance()) { + + // Once we're back, clear blocking flags so everyone else can join in + SetReturningFlag(false); + bot_owner->SetBotPulling(false); + + if (GetPet()) { + GetPet()->SetPetOrder(m_previous_pet_order); + } + } + + // Need to keep puller out of combat until they reach their 'return to' destination + if (HasTargetReflection()) { + + SetTarget(nullptr); + WipeHateList(); + return false; + } + return true; +} + +bool Bot::PullingFlagChecks(Client* bot_owner) { + + if (!GetTarget()) { + + WipeHateList(); + SetTarget(nullptr); + SetPullingFlag(false); + SetReturningFlag(false); + bot_owner->SetBotPulling(false); + + if (GetPet()) { + GetPet()->SetPetOrder(m_previous_pet_order); + } + + return false; + } + else if (GetTarget()->GetHateList().size()) { + + WipeHateList(); + SetTarget(nullptr); + SetPullingFlag(false); + SetReturningFlag(); + + if (HasPet() && + (GetClass() != ENCHANTER || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 1)) { + + GetPet()->WipeHateList(); + GetPet()->SetTarget(nullptr); + } + + if (GetPlayerState() & static_cast(PlayerState::Aggressive)) { + SendRemovePlayerState(PlayerState::Aggressive); + } + } + + return true; +} + +void Bot::SetBotTarget(Client* bot_owner, Raid* raid, Group* bot_group, Client* leash_owner, float lo_distance, float leash_distance, bool bo_alt_combat) { + + if (bo_alt_combat && m_alt_combat_hate_timer.Check(false)) { + // Empty hate list - let's find some aggro + if (!IsEngaged() && NOT_HOLDING && NOT_PASSIVE && (!bot_owner->GetBotPulling() || NOT_PULLING_BOT)) { + SetLeashOwnerTarget(leash_owner, bot_owner, lo_distance, leash_distance); + } + + else if (bot_group) { + for (const auto& bg_member: bot_group->members) { + if (!bg_member) { + continue; + } + + auto bgm_target = bg_member->GetTarget(); + if (!bgm_target || !bgm_target->IsNPC()) { + continue; + } + SetBotGroupTarget(bot_owner, leash_owner, lo_distance, leash_distance, bg_member, bgm_target); + } + } + else if (raid) { + for (const auto& raid_member : raid->members) { + if (!raid_member.member) { + continue; + } + + auto rm_target = raid_member.member->GetTarget(); + if (!rm_target || !rm_target->IsNPC()) { + continue; + } + SetBotGroupTarget(bot_owner, leash_owner, lo_distance, leash_distance, raid_member.member, rm_target); + } + } + } +} + +void Bot::HealRotationChecks() { + + if (IsMyHealRotationSet()) { + if (AIHealRotation(HealRotationTarget(), UseHealRotationFastHeals())) { + m_member_of_heal_rotation->SetMemberIsCasting(this); + m_member_of_heal_rotation->UpdateTargetHealingStats(HealRotationTarget()); + AdvanceHealRotation(); + } + else { + m_member_of_heal_rotation->SetMemberIsCasting(this, false); + AdvanceHealRotation(false); + } + } +} + +bool Bot::IsAIProcessValid(const Client* bot_owner, const Group* bot_group, const Raid* raid) { + + if (!bot_owner || !bot_group && !raid || !IsAIControlled()) { + return false; + } + + if (bot_owner->IsDead()) { + SetTarget(nullptr); + SetBotOwner(nullptr); + return false; + } + return true; +} + +bool Bot::CheckIfCasting(float fm_distance) { + + if (IsCasting()) { + if (IsHealRotationMember() && + m_member_of_heal_rotation->CastingOverride() && + m_member_of_heal_rotation->CastingTarget() != nullptr && + m_member_of_heal_rotation->CastingReady() && + m_member_of_heal_rotation->CastingMember() == this && + !m_member_of_heal_rotation->MemberIsCasting(this)) + { + InterruptSpell(); + } + else if (AmICastingForHealRotation() && m_member_of_heal_rotation->CastingMember() == this) { + + AdvanceHealRotation(false); + return true; + } + else if (GetClass() != BARD) { + + if (IsEngaged()) { + return true; + } + + if ( + (NOT_GUARDING && fm_distance > GetFollowDistance()) || // Cancel out-of-combat casting if movement to follow mob is required + (GUARDING && DistanceSquared(GetPosition(), GetGuardPoint()) > GetFollowDistance()) // Cancel out-of-combat casting if movement to guard point is required + ) { + InterruptSpell(); + } + + return true; + } + } + else if (IsHealRotationMember()) { + m_member_of_heal_rotation->SetMemberIsCasting(this, false); + } + return false; +} + +bool Bot::CheckIfIncapacitated() { + + if (GetPauseAI() || IsStunned() || IsMezzed() || (GetAppearance() == eaDead)) { + + if (IsCasting()) { + InterruptSpell(); + } + + if (IsMyHealRotationSet() || (AmICastingForHealRotation() && m_member_of_heal_rotation->CastingMember() == this)) { + AdvanceHealRotation(false); + m_member_of_heal_rotation->SetMemberIsCasting(this, false); + } + return true; + } + + if (IsRooted() && IsMoving()) { + StopMoving(); + return true; + } + + return false; +} + +void Bot::SetBerserkState() {// Berserk updates should occur if primary AI criteria are met + if (GetClass() == WARRIOR || GetClass() == BERSERKER) { + + if (!berserk && GetHP() > 0 && GetHPRatio() < 30.0f) { + entity_list.MessageCloseString(this, false, 200, 0, BERSERK_START, GetName()); + berserk = true; + } + + if (berserk && GetHPRatio() >= 30.0f) { + entity_list.MessageCloseString(this, false, 200, 0, BERSERK_END, GetName()); + berserk = false; + } + } +} + +Mob* Bot::SetFollowMob(Client* leash_owner) { + Mob* follow_mob = entity_list.GetMob(GetFollowID()); + if (!follow_mob) { + + follow_mob = leash_owner; + SetFollowID(leash_owner->GetID()); + } + return follow_mob; +} + +Client* Bot::SetLeashOwner(Client* bot_owner, Group* bot_group, Raid* raid, uint32 r_group) const { + + Client* leash_owner = nullptr; + if (raid && r_group < MAX_RAID_GROUPS && raid->GetGroupLeader(r_group)) { + leash_owner = + raid->GetGroupLeader(r_group) && + raid->GetGroupLeader(r_group)->IsClient() ? + raid->GetGroupLeader(r_group)->CastToClient() : bot_owner; + + } else if (bot_group) { + bot_group->VerifyGroup(); + leash_owner = (bot_group->GetLeader() && bot_group->GetLeader()->IsClient() ? bot_group->GetLeader()->CastToClient() : bot_owner); + + } else { + leash_owner = bot_owner; + } + return leash_owner; +} + +void Bot::SetLeashOwnerTarget(Client* leash_owner, Client* bot_owner, float lo_distance, float leash_distance) { + + Mob* lo_target = leash_owner->GetTarget(); + if (lo_target && + lo_target->IsNPC() && + !lo_target->IsMezzed() && + ((bot_owner->GetBotOption(Client::booAutoDefend) && lo_target->GetHateAmount(leash_owner)) || leash_owner->AutoAttackEnabled()) && + lo_distance <= leash_distance && + DistanceSquared(m_Position, lo_target->GetPosition()) <= leash_distance && + (CheckLosFN(lo_target) || leash_owner->CheckLosFN(lo_target)) && + IsAttackAllowed(lo_target)) + { + AddToHateList(lo_target, 1); + if (HasPet() && (GetClass() != ENCHANTER || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 2)) { + GetPet()->AddToHateList(lo_target, 1); + GetPet()->SetTarget(lo_target); + } + } +} + +void Bot::SetOwnerTarget(Client* bot_owner) { + if (GetPet() && PULLING_BOT) { + GetPet()->SetPetOrder(m_previous_pet_order); + } + + SetAttackFlag(false); + SetAttackingFlag(false); + SetPullFlag(false); + SetPullingFlag(false); + SetReturningFlag(false); + bot_owner->SetBotPulling(false); + + if (NOT_HOLDING && NOT_PASSIVE) { + + auto attack_target = bot_owner->GetTarget(); + if (attack_target) { + + InterruptSpell(); + WipeHateList(); + AddToHateList(attack_target, 1); + SetTarget(attack_target); + SetAttackingFlag(); + if (HasPet() && (GetClass() != ENCHANTER || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 2)) { + + GetPet()->WipeHateList(); + GetPet()->AddToHateList(attack_target, 1); + GetPet()->SetTarget(attack_target); + } + } + } +} + +void Bot::BotPullerProcess(Client* bot_owner, Raid* raid) { + SetAttackFlag(false); + SetAttackingFlag(false); + SetPullFlag(false); + SetPullingFlag(false); + SetReturningFlag(false); + bot_owner->SetBotPulling(false); + + if (NOT_HOLDING && NOT_PASSIVE) { + auto pull_target = bot_owner->GetTarget(); + if (pull_target) { + if (raid) { + const auto msg = fmt::format("Pulling {} to the group..", pull_target->GetCleanName()); + raid->RaidSay(msg.c_str(), GetCleanName(), 0, 100); + } else { + BotGroupSay( + this, + fmt::format( + "Pulling {}.", + pull_target->GetCleanName() + ).c_str() + ); + } + + InterruptSpell(); + WipeHateList(); + AddToHateList(pull_target, 1); + SetTarget(pull_target); + SetPullingFlag(); + bot_owner->SetBotPulling(); + if (HasPet() && (GetClass() != ENCHANTER || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 1)) { + + GetPet()->WipeHateList(); + GetPet()->SetTarget(nullptr); + m_previous_pet_order = GetPet()->GetPetOrder(); + GetPet()->SetPetOrder(SPO_Guard); + } + } + } +} + +void Bot::SetBotGroupTarget(const Client* bot_owner, Client* leash_owner, float lo_distance, float leash_distance, Mob* const& bg_member, Mob* bgm_target) { + if (!bgm_target->IsMezzed() && + ((bot_owner->GetBotOption(Client::booAutoDefend) && bgm_target->GetHateAmount(bg_member)) || leash_owner->AutoAttackEnabled()) && + lo_distance <= leash_distance && + DistanceSquared(m_Position, bgm_target->GetPosition()) <= leash_distance && + (CheckLosFN(bgm_target) || leash_owner->CheckLosFN(bgm_target)) && + IsAttackAllowed(bgm_target)) + { + AddToHateList(bgm_target, 1); + if (HasPet() && (GetClass() != ENCHANTER || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 2)) { + GetPet()->AddToHateList(bgm_target, 1); + GetPet()->SetTarget(bgm_target); } } } @@ -3941,15 +3235,13 @@ void Bot::PetAIProcess() { void Bot::Depop() { WipeHateList(); entity_list.RemoveFromHateLists(this); - if(HasGroup()) - Bot::RemoveBotFromGroup(this, GetGroup()); - if(HasPet()) + if (HasPet()) GetPet()->Depop(); - _botOwner = 0; + _botOwner = nullptr; _botOwnerCharacterID = 0; - _previousTarget = 0; + NPC::Depop(false); } @@ -4032,6 +3324,11 @@ bool Bot::Spawn(Client* botCharacterOwner) { } } + if (Raid* raid = entity_list.GetRaidByBotName(GetName())) + { + raid->VerifyRaid(); + SetRaidGrouped(true); + } return true; } @@ -4096,35 +3393,33 @@ uint32 Bot::GetBotItemBySlot(uint16 slot_id) return item_id; } - if (!database.botdb.LoadItemBySlot(GetBotID(), slot_id, item_id)) { - if (GetBotOwner() && GetBotOwner()->IsClient()) { - GetBotOwner()->CastToClient()->Message( - Chat::White, - fmt::format( - "Failed to load slot ID {} for {}.", - slot_id, - GetCleanName() - ).c_str() - ); - } + if (!database.botdb.LoadItemBySlot(GetBotID(), slot_id, item_id) && GetBotOwner() && GetBotOwner()->IsClient()) { + GetBotOwner()->CastToClient()->Message( + Chat::White, + fmt::format( + "Failed to load slot ID {} for {}.", + slot_id, + GetCleanName() + ).c_str() + ); } return item_id; } void Bot::SetLevel(uint8 in_level, bool command) { - if(in_level > 0) + if (in_level > 0) Mob::SetLevel(in_level, command); } void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { - if(ns) { + if (ns) { Mob::FillSpawnStruct(ns, ForWho); ns->spawn.afk = 0; ns->spawn.lfg = 0; ns->spawn.anon = 0; ns->spawn.gm = 0; - if(IsInAGuild()) + if (IsInAGuild()) ns->spawn.guildID = GuildID(); else ns->spawn.guildID = 0xFFFFFFFF; // 0xFFFFFFFF = NO GUILD, 0 = Unknown Guild @@ -4145,13 +3440,11 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { strcpy(ns->spawn.suffix, GetSuffix().c_str()); const EQ::ItemData* item = nullptr; const EQ::ItemInstance* inst = nullptr; - uint32 spawnedbotid = 0; - spawnedbotid = GetBotID(); for (int i = EQ::textures::textureBegin; i < EQ::textures::weaponPrimary; i++) { inst = GetBotItem(i); if (inst) { item = inst->GetItem(); - if (item != 0) { + if (item != nullptr) { ns->spawn.equipment.Slot[i].Material = item->Material; ns->spawn.equipment.Slot[i].EliteModel = item->EliteMaterial; ns->spawn.equipment.Slot[i].HerosForgeModel = item->HerosForgeModel; @@ -4167,22 +3460,25 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { } inst = GetBotItem(EQ::invslot::slotPrimary); - if(inst) { + if (inst) { item = inst->GetItem(); + if(item) { if(strlen(item->IDFile) > 2) - ns->spawn.equipment.Primary.Material = atoi(&item->IDFile[2]); + ns->spawn.equipment.Primary.Material = Strings::ToInt(&item->IDFile[2]); + ns->spawn.equipment_tint.Primary.Color = GetEquipmentColor(EQ::textures::weaponPrimary); } } inst = GetBotItem(EQ::invslot::slotSecondary); - if(inst) { + if (inst) { item = inst->GetItem(); + if(item) { if(strlen(item->IDFile) > 2) - ns->spawn.equipment.Secondary.Material = atoi(&item->IDFile[2]); + ns->spawn.equipment.Secondary.Material = Strings::ToInt(&item->IDFile[2]); ns->spawn.equipment_tint.Secondary.Color = GetEquipmentColor(EQ::textures::weaponSecondary); } @@ -4251,9 +3547,12 @@ void Bot::LoadAndSpawnAllZonedBots(Client* bot_owner) { } auto spawned_bot_count_class = bot_class_spawned_count[b->GetClass() - 1]; - auto bot_spawn_limit_class = bot_class_spawn_limits[b->GetClass() - 1]; - if (bot_spawn_limit_class >= 0 && spawned_bot_count_class >= bot_spawn_limit_class) { + if ( + auto bot_spawn_limit_class = bot_class_spawn_limits[b->GetClass() - 1]; + bot_spawn_limit_class >= 0 && + spawned_bot_count_class >= bot_spawn_limit_class + ) { database.SetGroupID(b->GetCleanName(), 0, b->GetBotID()); g->UpdatePlayer(bot_owner); continue; @@ -4295,12 +3594,12 @@ void Bot::LoadAndSpawnAllZonedBots(Client* bot_owner) { // Returns TRUE if there is atleast 1 bot in the specified group bool Bot::GroupHasBot(Group* group) { bool Result = false; - if(group) { - for(int Counter = 0; Counter < MAX_GROUP_MEMBERS; Counter++) { + if (group) { + for (int Counter = 0; Counter < MAX_GROUP_MEMBERS; Counter++) { if (group->members[Counter] == nullptr) continue; - if(group->members[Counter]->IsBot()) { + if (group->members[Counter]->IsBot()) { Result = true; break; } @@ -4323,15 +3622,15 @@ uint32 Bot::SpawnedBotCount(const uint32 owner_id, uint8 class_id) { void Bot::LevelBotWithClient(Client* client, uint8 level, bool sendlvlapp) { // This essentially performs a '#bot update,' with appearance packets, based on the current methods. // This should not be called outside of Client::SetEXP() due to it's lack of rule checks. - if(client) { + if (client) { std::list blist = entity_list.GetBotsByBotOwnerCharacterID(client->CharacterID()); - for(std::list::iterator biter = blist.begin(); biter != blist.end(); ++biter) { + for (auto biter = blist.begin(); biter != blist.end(); ++biter) { Bot* bot = *biter; - if(bot && (bot->GetLevel() != client->GetLevel())) { + if (bot && (bot->GetLevel() != client->GetLevel())) { bot->SetPetChooser(false); // not sure what this does, but was in bot 'update' code bot->CalcBotStats(client->GetBotOption(Client::booStatsUpdate)); - if(sendlvlapp) + if (sendlvlapp) bot->SendLevelAppearance(); // modified from Client::SetLevel() bot->SendAppearancePacket(AT_WhoLevel, level, true, true); // who level change @@ -4343,8 +3642,8 @@ void Bot::LevelBotWithClient(Client* client, uint8 level, bool sendlvlapp) { } void Bot::SendBotArcheryWearChange(uint8 material_slot, uint32 material, uint32 color) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); - WearChange_Struct* wc = (WearChange_Struct*)outapp->pBuffer; + auto outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); + auto wc = (WearChange_Struct*)outapp->pBuffer; wc->spawn_id = GetID(); wc->material = material; @@ -4370,9 +3669,8 @@ void Bot::BotAddEquipItem(uint16 slot_id, uint32 item_id) { // this is being called before bot is assigned an entity id.. // ..causing packets to be sent out to zone with an id of '0' if (item_id) { - uint8 material_from_slot = EQ::InventoryProfile::CalcMaterialFromSlot(slot_id); - if (material_from_slot != EQ::textures::materialInvalid) { + if (uint8 material_from_slot = EQ::InventoryProfile::CalcMaterialFromSlot(slot_id); material_from_slot != EQ::textures::materialInvalid) { equipment[slot_id] = item_id; // npc has more than just material slots. Valid material should mean valid inventory index if (GetID()) { // temp hack fix SendWearChange(material_from_slot); @@ -4380,10 +3678,8 @@ void Bot::BotAddEquipItem(uint16 slot_id, uint32 item_id) { } UpdateEquipmentLight(); - if (UpdateActiveLight()) { - if (GetID()) { // temp hack fix - SendAppearancePacket(AT_Light, GetActiveLightType()); - } + if (UpdateActiveLight() && GetID()) { // temp hack fix + SendAppearancePacket(AT_Light, GetActiveLightType()); } } } @@ -4493,23 +3789,19 @@ uint32 Bot::CountBotItem(uint32 item_id) { return item_count; } -bool Bot::HasBotItem(uint32 item_id) { - bool has_item = false; - EQ::ItemInstance *inst = nullptr; +int16 Bot::HasBotItem(uint32 item_id) { + EQ::ItemInstance const *inst = nullptr; for (uint16 slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) { inst = GetBotItem(slot_id); if (!inst || !inst->GetItem()) { continue; } - if (inst->GetID() == item_id) { - has_item = true; - break; + return slot_id; } } - - return has_item; + return INVALID_INDEX; } void Bot::RemoveBotItem(uint32 item_id) { @@ -4547,45 +3839,47 @@ void Bot::RemoveBotItem(uint32 item_id) { bool Bot::RemoveBotFromGroup(Bot* bot, Group* group) { bool Result = false; - if(bot && group) { - if(bot->HasGroup()) { - if(!group->IsLeader(bot)) { - bot->SetFollowID(0); - if(group->DelMember(bot)) - database.SetGroupID(bot->GetCleanName(), 0, bot->GetBotID()); - } else { - for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(!group->members[i]) - continue; - - group->members[i]->SetFollowID(0); - } - group->DisbandGroup(); + if (bot && group && bot->HasGroup()) { + if (!group->IsLeader(bot)) { + bot->SetFollowID(0); + if (group->DelMember(bot)) { database.SetGroupID(bot->GetCleanName(), 0, bot->GetBotID()); + if (group->GroupCount() < 1) { + group->DisbandGroup(); + } } - Result = true; + } else { + for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (!group->members[i]) { + continue; + } + + group->members[i]->SetFollowID(0); + } + group->DisbandGroup(); + database.SetGroupID(bot->GetCleanName(), 0, bot->GetBotID()); } + Result = true; } return Result; } bool Bot::AddBotToGroup(Bot* bot, Group* group) { bool Result = false; - if(bot && group) { - if(!bot->HasGroup()) { - // Add bot to this group - if(group->AddMember(bot)) { - if(group->GetLeader()) { - bot->SetFollowID(group->GetLeader()->GetID()); - // Need to send this only once when a group is formed with a bot so the client knows it is also the group leader - if(group->GroupCount() == 2 && group->GetLeader()->IsClient()) { - group->UpdateGroupAAs(); - Mob *TempLeader = group->GetLeader(); - group->SendUpdate(groupActUpdate, TempLeader); - } + if (bot && group) { + // Add bot to this group + if (group->AddMember(bot)) { + if (group->GetLeader()) { + bot->SetFollowID(group->GetLeader()->GetID()); + // Need to send this only once when a group is formed with a bot so the client knows it is also the group leader + if (group->GroupCount() == 2 && group->GetLeader()->IsClient()) { + group->UpdateGroupAAs(); + Mob *TempLeader = group->GetLeader(); + group->SendUpdate(groupActUpdate, TempLeader); } - Result = true; } + group->VerifyGroup(); + Result = true; } } return Result; @@ -4631,17 +3925,17 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* struct ClientTrade { ItemInstance* trade_item_instance; int16 from_client_slot; - int16 to_bot_slot; + int16 to_bot_slot = invslot::SLOT_INVALID; - ClientTrade(ItemInstance* item, int16 from) : trade_item_instance(item), from_client_slot(from), to_bot_slot(invslot::SLOT_INVALID) { } + ClientTrade(ItemInstance* item, int16 from) : trade_item_instance(item), from_client_slot(from) { } }; struct ClientReturn { - const ItemInstance* return_item_instance; + ItemInstance* return_item_instance; int16 from_bot_slot; - int16 to_client_slot; + int16 to_client_slot = invslot::SLOT_INVALID; - ClientReturn(const ItemInstance* item, int16 from) : return_item_instance(item), from_bot_slot(from), to_client_slot(invslot::SLOT_INVALID) { } + ClientReturn(ItemInstance* item, int16 from) : return_item_instance(item), from_bot_slot(from) { } }; static const int16 bot_equip_order[invslot::EQUIPMENT_COUNT] = { @@ -4758,6 +4052,33 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* } } + for (int m = EQ::invaug::SOCKET_BEGIN; m <= EQ::invaug::SOCKET_END; ++m) { + const auto augment = trade_instance->GetAugment(m); + if (!augment) { + continue; + } + + if (!CheckLoreConflict(augment->GetItem())) { + continue; + } + + linker.SetLinkType(EQ::saylink::SayLinkItemInst); + linker.SetItemInst(augment); + + item_link = linker.GenerateLink(); + + client->Message( + Chat::Yellow, + fmt::format( + "{} already has {}, the trade has been cancelled!", + GetCleanName(), + item_link + ).c_str() + ); + client->ResetTrade(); + return; + } + if (CheckLoreConflict(trade_instance->GetItem())) { if (trade_event_exists) { event_trade.push_back(ClientTrade(trade_instance, trade_index)); @@ -4859,6 +4180,10 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* continue; } + if (trade_instance->GetItem()->ItemType == EQ::item::ItemTypeAugmentation) { + continue; + } + //if (stage_loop == stageStackable) { // // TODO: implement // continue; @@ -4890,7 +4215,7 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* if (trade_instance->GetItem()->IsType2HWeapon()) { if (!melee_secondary) { melee_2h_weapon = true; - auto equipped_secondary_weapon = m_inv[invslot::slotSecondary]; + auto equipped_secondary_weapon = GetBotItem(invslot::slotSecondary); if (equipped_secondary_weapon) { client_return.push_back(ClientReturn(equipped_secondary_weapon, invslot::slotSecondary)); } @@ -4906,7 +4231,7 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* !trade_instance->IsWeapon() ) { melee_secondary = true; - auto equipped_primary_weapon = m_inv[invslot::slotPrimary]; + auto equipped_primary_weapon = GetBotItem(invslot::slotPrimary); if (equipped_primary_weapon && equipped_primary_weapon->GetItem()->IsType2HWeapon()) { client_return.push_back(ClientReturn(equipped_primary_weapon, invslot::slotPrimary)); } @@ -4921,7 +4246,7 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* trade_iterator.to_bot_slot = index; if (m_inv[index]) { - client_return.push_back(ClientReturn(m_inv[index], index)); + client_return.push_back(ClientReturn(GetBotItem(index), index)); } break; @@ -5055,9 +4380,8 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* client->DeleteItemInInventory(return_iterator.from_bot_slot); } else { // successful trade returns auto return_instance = m_inv.PopItem(return_iterator.from_bot_slot); - //if (*return_instance != *return_iterator.return_item_instance) { + // // TODO: add logging - //} if (!database.botdb.DeleteItemBySlot(GetBotID(), return_iterator.from_bot_slot)) { OwnerMessage( @@ -5070,6 +4394,25 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* BotRemoveEquipItem(return_iterator.from_bot_slot); + if (parse->BotHasQuestSub(EVENT_UNEQUIP_ITEM_BOT)) { + const auto& export_string = fmt::format( + "{} {}", + return_iterator.return_item_instance->IsStackable() ? return_iterator.return_item_instance->GetCharges() : 1, + return_iterator.from_bot_slot + ); + + std::vector args = { return_iterator.return_item_instance }; + + parse->EventBot( + EVENT_UNEQUIP_ITEM_BOT, + this, + nullptr, + export_string, + return_iterator.return_item_instance->GetID(), + &args + ); + } + if (return_instance) { EQ::SayLinkEngine linker; linker.SetLinkType(EQ::saylink::SayLinkItemInst); @@ -5118,6 +4461,26 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* m_inv.PutItem(trade_iterator.to_bot_slot, *trade_iterator.trade_item_instance); BotAddEquipItem(trade_iterator.to_bot_slot, (trade_iterator.trade_item_instance ? trade_iterator.trade_item_instance->GetID() : 0)); + + if (parse->BotHasQuestSub(EVENT_EQUIP_ITEM_BOT)) { + const auto& export_string = fmt::format( + "{} {}", + trade_iterator.trade_item_instance->IsStackable() ? trade_iterator.trade_item_instance->GetCharges() : 1, + trade_iterator.to_bot_slot + ); + + std::vector args = { trade_iterator.trade_item_instance }; + + parse->EventBot( + EVENT_EQUIP_ITEM_BOT, + this, + nullptr, + export_string, + trade_iterator.trade_item_instance->GetID(), + &args + ); + } + trade_iterator.trade_item_instance = nullptr; // actual deletion occurs in client delete below client->DeleteItemInInventory(trade_iterator.from_client_slot, 0, (trade_iterator.from_client_slot == EQ::invslot::slotCursor)); @@ -5145,7 +4508,7 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* // Accept Items from Cursor to support bot command ^inventorygive if (begin_slot_id == invslot::slotCursor && end_slot_id == invslot::slotCursor) { EQ::ItemInstance* insts[1] = { 0 }; - EQ::InventoryProfile& user_inv = client->GetInv(); + user_inv = client->GetInv(); insts[0] = user_inv.GetItem(invslot::slotCursor); client->DeleteItemInInventory(invslot::slotCursor); @@ -5153,13 +4516,16 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* std::vector items(insts, insts + std::size(insts)); // Check if EVENT_TRADE accepts any items - std::vector item_list(items.begin(), items.end()); - parse->EventBot(EVENT_TRADE, this, client, "", 0, &item_list); + if (parse->BotHasQuestSub(EVENT_TRADE)) { + std::vector item_list(items.begin(), items.end()); + parse->EventBot(EVENT_TRADE, this, client, "", 0, &item_list); + } + CalcBotStats(false); } else { EQ::ItemInstance* insts[8] = { 0 }; - EQ::InventoryProfile& user_inv = client->GetInv(); + user_inv = client->GetInv(); for (int i = EQ::invslot::TRADE_BEGIN; i <= EQ::invslot::TRADE_END; ++i) { insts[i - EQ::invslot::TRADE_BEGIN] = user_inv.GetItem(i); client->DeleteItemInInventory(i); @@ -5169,15 +4535,18 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* std::vector items(insts, insts + std::size(insts)); // Check if EVENT_TRADE accepts any items - std::vector item_list(items.begin(), items.end()); - parse->EventBot(EVENT_TRADE, this, client, "", 0, &item_list); + if (parse->BotHasQuestSub(EVENT_TRADE)) { + std::vector item_list(items.begin(), items.end()); + parse->EventBot(EVENT_TRADE, this, client, "", 0, &item_list); + } + CalcBotStats(false); } } } bool Bot::Death(Mob *killerMob, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill) { - if(!NPC::Death(killerMob, damage, spell_id, attack_skill)) + if (!NPC::Death(killerMob, damage, spell_id, attack_skill)) return false; Save(); @@ -5192,26 +4561,26 @@ bool Bot::Death(Mob *killerMob, int64 damage, uint16 spell_id, EQ::skills::Skill Mob *give_exp = hate_list.GetDamageTopOnHateList(this); Client *give_exp_client = nullptr; - if(give_exp && give_exp->IsClient()) + if (give_exp && give_exp->IsClient()) give_exp_client = give_exp->CastToClient(); bool IsLdonTreasure = (GetClass() == LDON_TREASURE); - if(entity_list.GetCorpseByID(GetID())) + if (entity_list.GetCorpseByID(GetID())) entity_list.GetCorpseByID(GetID())->Depop(); Group *g = GetGroup(); - if(g) { - for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(g->members[i]) { - if(g->members[i] == this) { + if (g) { + for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (g->members[i]) { + if (g->members[i] == this) { // If the leader dies, make the next bot the leader // and reset all bots followid - if(g->IsLeader(g->members[i])) { - if(g->members[i + 1]) { + if (g->IsLeader(g->members[i])) { + if (g->members[i + 1]) { g->SetLeader(g->members[i + 1]); g->members[i + 1]->SetFollowID(g->members[i]->GetFollowID()); - for(int j = 0; j < MAX_GROUP_MEMBERS; j++) { - if(g->members[j] && (g->members[j] != g->members[i + 1])) + for (int j = 0; j < MAX_GROUP_MEMBERS; j++) { + if (g->members[j] && (g->members[j] != g->members[i + 1])) g->members[j]->SetFollowID(g->members[i + 1]->GetID()); } } @@ -5227,8 +4596,8 @@ bool Bot::Death(Mob *killerMob, int64 damage, uint16 spell_id, EQ::skills::Skill // if group members exist below this one, move // them all up one slot in the group list int j = (i + 1); - for(; j < MAX_GROUP_MEMBERS; j++) { - if(g->members[j]) { + for (; j < MAX_GROUP_MEMBERS; j++) { + if (g->members[j]) { g->members[j-1] = g->members[j]; strcpy(g->membername[j-1], g->members[j]->GetCleanName()); g->membername[j][0] = '\0'; @@ -5242,9 +4611,9 @@ bool Bot::Death(Mob *killerMob, int64 damage, uint16 spell_id, EQ::skills::Skill GroupJoin_Struct* gu = (GroupJoin_Struct*)outapp->pBuffer; gu->action = groupActLeave; strcpy(gu->membername, GetCleanName()); - if(g) { - for(int k = 0; k < MAX_GROUP_MEMBERS; k++) { - if(g->members[k] && g->members[k]->IsClient()) + if (g) { + for (int k = 0; k < MAX_GROUP_MEMBERS; k++) { + if (g->members[k] && g->members[k]->IsClient()) g->members[k]->CastToClient()->QueuePacket(outapp); } } @@ -5260,33 +4629,53 @@ bool Bot::Death(Mob *killerMob, int64 damage, uint16 spell_id, EQ::skills::Skill my_owner->CastToClient()->SetBotPulling(false); } - const auto export_string = fmt::format( - "{} {} {} {}", - killerMob ? killerMob->GetID() : 0, - damage, - spell_id, - static_cast(attack_skill) - ); +Raid* raid = entity_list.GetRaidByBotName(GetName()); - parse->EventBot(EVENT_DEATH_COMPLETE, this, killerMob, export_string, 0); + if (raid) + { + + for (int x = 0; x < MAX_RAID_MEMBERS; x++) + { + if (strcmp(raid->members[x].membername, GetName()) == 0) + { + raid->members[x].member = nullptr; + } + } + } + + if (parse->BotHasQuestSub(EVENT_DEATH_COMPLETE)) { + const auto& export_string = fmt::format( + "{} {} {} {}", + killerMob ? killerMob->GetID() : 0, + damage, + spell_id, + static_cast(attack_skill) + ); + + parse->EventBot(EVENT_DEATH_COMPLETE, this, killerMob, export_string, 0); + } entity_list.RemoveBot(GetID()); - return true; + +return true; } void Bot::Damage(Mob *from, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, eSpecialAttacks special) { - if(spell_id == 0) + if (spell_id == 0) spell_id = SPELL_UNKNOWN; //handle EVENT_ATTACK. Resets after we have not been attacked for 12 seconds - if(attacked_timer.Check()) { - LogCombat("Triggering EVENT_ATTACK due to attack by [{}]", from->GetName()); - parse->EventBot(EVENT_ATTACK, this, from, "", 0); + if (attacked_timer.Check()) { + if (parse->BotHasQuestSub(EVENT_ATTACK)) { + LogCombat("Triggering EVENT_ATTACK due to attack by [{}]", from->GetName()); + + parse->EventBot(EVENT_ATTACK, this, from, "", 0); + } } attacked_timer.Start(CombatEventTimer_expire); // if spell is lifetap add hp to the caster - if (spell_id != SPELL_UNKNOWN && IsLifetapSpell(spell_id)) { + if (IsValidSpell(spell_id) && IsLifetapSpell(spell_id)) { int64 healed = GetActSpellHealing(spell_id, damage); LogCombatDetail("Applying lifetap heal of [{}] to [{}]", healed, GetCleanName()); HealDamage(healed); @@ -5294,22 +4683,22 @@ void Bot::Damage(Mob *from, int64 damage, uint16 spell_id, EQ::skills::SkillType } CommonDamage(from, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic, special); - if(GetHP() < 0) { - if(IsCasting()) + if (GetHP() < 0) { + if (IsCasting()) InterruptSpell(); SetAppearance(eaDead); } SendHPUpdate(); - if(this == from) + if (this == from) return; // Aggro the bot's group members - if(IsGrouped()) { + if (IsGrouped()) { Group *g = GetGroup(); - if(g) { - for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(g->members[i] && g->members[i]->IsBot() && from && !g->members[i]->CheckAggro(from) && g->members[i]->IsAttackAllowed(from)) + if (g) { + for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (g->members[i] && g->members[i]->IsBot() && from && !g->members[i]->CheckAggro(from) && g->members[i]->IsAttackAllowed(from)) g->members[i]->AddToHateList(from, 1); } } @@ -5362,17 +4751,17 @@ int Bot::GetHandToHandDamage(void) { } static uint8 mnk_dmg[] = {99, - 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, // 1-10 - 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, // 11-20 - 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, // 21-30 + 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, // 1-10 + 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, // 11-20 + 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, // 21-30 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, // 31-40 12, 12, 12, 12, 13, 13, 13, 13, 13, 14, // 41-50 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, // 51-60 - 14, 14}; // 61-62 + 14, 14}; // 61-62 static uint8 bst_dmg[] = {99, - 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, // 1-10 - 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, // 11-20 - 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, // 21-30 + 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, // 1-10 + 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, // 11-20 + 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, // 21-30 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, // 31-40 10, 11, 11, 11, 11, 11, 11, 12, 12}; // 41-49 if (GetClass() == MONK) { @@ -5420,13 +4809,13 @@ void Bot::DoRiposte(Mob* defender) { defender->Attack(this, EQ::invslot::slotPrimary, true); int32 DoubleRipChance = (defender->GetAABonuses().GiveDoubleRiposte[0] + defender->GetSpellBonuses().GiveDoubleRiposte[0] + defender->GetItemBonuses().GiveDoubleRiposte[0]); - if(DoubleRipChance && (DoubleRipChance >= zone->random.Int(0, 100))) { + if (DoubleRipChance && (DoubleRipChance >= zone->random.Int(0, 100))) { LogCombatDetail("Preforming a double riposte ([{}] percent chance)", DoubleRipChance); defender->Attack(this, EQ::invslot::slotPrimary, true); } DoubleRipChance = defender->GetAABonuses().GiveDoubleRiposte[1]; - if(DoubleRipChance && (DoubleRipChance >= zone->random.Int(0, 100))) { + if (DoubleRipChance && (DoubleRipChance >= zone->random.Int(0, 100))) { if (defender->GetClass() == MONK) defender->MonkSpecialAttack(this, defender->GetAABonuses().GiveDoubleRiposte[2]); else if (defender->IsBot()) @@ -5522,16 +4911,16 @@ int Bot::GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target) void Bot::DoSpecialAttackDamage(Mob *who, EQ::skills::SkillType skill, int32 max_damage, int32 min_damage, int32 hate_override, int ReuseTime, bool HitChance) { int32 hate = max_damage; - if(hate_override > -1) + if (hate_override > -1) hate = hate_override; if (skill == EQ::skills::SkillBash) { const EQ::ItemInstance* inst = GetBotItem(EQ::invslot::slotSecondary); const EQ::ItemData* botweapon = nullptr; - if(inst) + if (inst) botweapon = inst->GetItem(); - if(botweapon) { + if (botweapon) { if (botweapon->ItemType == EQ::item::ItemTypeShield) hate += botweapon->AC; @@ -5558,22 +4947,12 @@ void Bot::DoSpecialAttackDamage(Mob *who, EQ::skills::SkillType skill, int32 max who->Damage(this, my_hit.damage_done, SPELL_UNKNOWN, skill, false); - if(!GetTarget() || HasDied()) + if (!GetTarget() || HasDied()) return; if (my_hit.damage_done > 0) CheckNumHitsRemaining(NumHit::OutgoingHitSuccess); - //[AA Dragon Punch] value[0] = 100 for 25%, chance value[1] = skill - //if(aabonuses.SpecialAttackKBProc[0] && aabonuses.SpecialAttackKBProc[1] == skill){ - // int kb_chance = 25; - // kb_chance += (kb_chance * (100 - aabonuses.SpecialAttackKBProc[0]) / 100); - - // if (zone->random.Int(0, 99) < kb_chance) - // SpellFinished(904, who, 10, 0, -1, spells[904].ResistDiff); - // //who->Stun(100); Kayen: This effect does not stun on live, it only moves the NPC. - //} - if (HasSkillProcs()) TrySkillProc(who, skill, (ReuseTime * 1000)); @@ -5582,14 +4961,14 @@ void Bot::DoSpecialAttackDamage(Mob *who, EQ::skills::SkillType skill, int32 max } void Bot::TryBackstab(Mob *other, int ReuseTime) { - if(!other) + if (!other) return; bool bIsBehind = false; bool bCanFrontalBS = false; const EQ::ItemInstance* inst = GetBotItem(EQ::invslot::slotPrimary); const EQ::ItemData* botpiercer = nullptr; - if(inst) + if (inst) botpiercer = inst->GetItem(); if (!botpiercer || (botpiercer->ItemType != EQ::item::ItemType1HPiercing)) { @@ -5608,15 +4987,15 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) { if (bIsBehind || bCanFrontalBS) { int chance = (10 + (GetDEX() / 10) + (itembonuses.HeroicDEX / 10)); - if(level >= 60 && other->GetLevel() <= 45 && !other->CastToNPC()->IsEngaged() && other->GetHP()<= 32000 && other->IsNPC() && zone->random.Real(0, 99) < chance) { + if (level >= 60 && other->GetLevel() <= 45 && !other->CastToNPC()->IsEngaged() && other->GetHP()<= 32000 && other->IsNPC() && zone->random.Real(0, 99) < chance) { entity_list.MessageCloseString(this, false, 200, Chat::MeleeCrit, ASSASSINATES, GetName()); RogueAssassinate(other); } else { RogueBackstab(other); if (level > 54) { float DoubleAttackProbability = ((GetSkill(EQ::skills::SkillDoubleAttack) + GetLevel()) / 500.0f); - if(zone->random.Real(0, 1) < DoubleAttackProbability) { - if(other->GetHP() > 0) + if (zone->random.Real(0, 1) < DoubleAttackProbability) { + if (other->GetHP() > 0) RogueBackstab(other,false,ReuseTime); if (tripleChance && other->GetHP() > 0 && tripleChance > zone->random.Int(0, 100)) @@ -5624,7 +5003,7 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) { } } } - } else if(aabonuses.FrontalBackstabMinDmg || itembonuses.FrontalBackstabMinDmg || spellbonuses.FrontalBackstabMinDmg) { + } else if (aabonuses.FrontalBackstabMinDmg || itembonuses.FrontalBackstabMinDmg || spellbonuses.FrontalBackstabMinDmg) { m_specialattacks = eSpecialAttacks::ChaoticStab; RogueBackstab(other, true); m_specialattacks = eSpecialAttacks::None; @@ -5657,8 +5036,8 @@ void Bot::RogueBackstab(Mob *other, bool min_damage, int ReuseTime) void Bot::RogueAssassinate(Mob* other) { EQ::ItemInstance* botweaponInst = GetBotItem(EQ::invslot::slotPrimary); - if(botweaponInst) { - if(GetWeaponDamage(other, botweaponInst)) + if (botweaponInst) { + if (GetWeaponDamage(other, botweaponInst)) other->Damage(this, 32000, SPELL_UNKNOWN, EQ::skills::SkillBackstab); else other->Damage(this, -5, SPELL_UNKNOWN, EQ::skills::SkillBackstab); @@ -5668,7 +5047,7 @@ void Bot::RogueAssassinate(Mob* other) { } void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { - if(!target || spellend_timer.Enabled() || IsFeared() || IsStunned() || IsMezzed() || DivineAura() || GetHP() < 0 || !IsAttackAllowed(target)) + if (!target || spellend_timer.Enabled() || IsFeared() || IsStunned() || IsMezzed() || DivineAura() || GetHP() < 0 || !IsAttackAllowed(target)) return; bool taunt_time = taunt_timer.Check(); @@ -5705,7 +5084,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { break; } case PALADIN: { - if(GetHPRatio() < 20) { + if (GetHPRatio() < 20) { CastSpell(SPELL_LAY_ON_HANDS, GetID()); knightattack_timer.Start(LayOnHandsReuseTime * 1000); } @@ -5721,8 +5100,8 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { } } - if(taunting && target && target->IsNPC() && taunt_time) { - if(GetTarget() && GetTarget()->GetHateTop() && GetTarget()->GetHateTop() != this) { + if (taunting && target && target->IsNPC() && taunt_time) { + if (GetTarget() && GetTarget()->GetHateTop() && GetTarget()->GetHateTop() != this) { BotGroupSay( this, fmt::format( @@ -5788,7 +5167,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { break; } default: - break;; + break; } } @@ -5808,7 +5187,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { if ((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) || (m_inv.GetItem(EQ::invslot::slotSecondary) && m_inv.GetItem(EQ::invslot::slotSecondary)->GetItem()->ItemType == EQ::item::ItemTypeShield) || (m_inv.GetItem(EQ::invslot::slotPrimary) && m_inv.GetItem(EQ::invslot::slotPrimary)->GetItem()->IsType2HWeapon() && GetAA(aa2HandBash) >= 1)) canBash = true; - if(!canBash || zone->random.Int(0, 100) > 25) + if (!canBash || zone->random.Int(0, 100) > 25) skill_to_use = EQ::skills::SkillKick; else skill_to_use = EQ::skills::SkillBash; @@ -5851,7 +5230,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { break; } - if(skill_to_use == -1) + if (skill_to_use == -1) return; int64 dmg = GetBaseSkillDamage(static_cast(skill_to_use), GetTarget()); @@ -5884,7 +5263,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { } if (skill_to_use == EQ::skills::SkillKick) { - if(target != this) { + if (target != this) { DoAnim(animKick); if (GetWeaponDamage(target, GetBotItem(EQ::invslot::slotFeet)) <= 0) dmg = DMG_INVULNERABLE; @@ -5970,7 +5349,7 @@ void Bot::AI_Stop() { } FACTION_VALUE Bot::GetReverseFactionCon(Mob* iOther) { - if(iOther->IsBot()) + if (iOther->IsBot()) return FACTION_ALLY; return NPC::GetReverseFactionCon(iOther); @@ -5978,7 +5357,7 @@ FACTION_VALUE Bot::GetReverseFactionCon(Mob* iOther) { Mob* Bot::GetOwnerOrSelf() { Mob* Result = nullptr; - if(GetBotOwner()) + if (GetBotOwner()) Result = GetBotOwner(); else Result = this; @@ -5989,7 +5368,7 @@ Mob* Bot::GetOwnerOrSelf() { Mob* Bot::GetOwner() { Mob* Result = nullptr; Result = GetBotOwner(); - if(!Result) + if (!Result) SetBotOwner(0); return Result; @@ -5997,42 +5376,42 @@ Mob* Bot::GetOwner() { bool Bot::IsBotAttackAllowed(Mob* attacker, Mob* target, bool& hasRuleDefined) { bool Result = false; - if(attacker && target) { - if(attacker == target) { + if (attacker && target) { + if (attacker == target) { hasRuleDefined = true; Result = false; - } else if(attacker->IsClient() && target->IsBot() && attacker->CastToClient()->GetPVP() && target->CastToBot()->GetBotOwner()->CastToClient()->GetPVP()) { + } else if (attacker->IsClient() && target->IsBot() && attacker->CastToClient()->GetPVP() && target->CastToBot()->GetBotOwner()->CastToClient()->GetPVP()) { hasRuleDefined = true; Result = true; - } else if(attacker->IsClient() && target->IsBot()) { + } else if (attacker->IsClient() && target->IsBot()) { hasRuleDefined = true; Result = false; - } else if(attacker->IsBot() && target->IsNPC()) { + } else if (attacker->IsBot() && target->IsNPC()) { hasRuleDefined = true; Result = true; - } else if(attacker->IsBot() && !target->IsNPC()) { + } else if (attacker->IsBot() && !target->IsNPC()) { hasRuleDefined = true; Result = false; - } else if(attacker->IsPet() && attacker->IsFamiliar()) { + } else if (attacker->IsPet() && attacker->IsFamiliar()) { hasRuleDefined = true; Result = false; - } else if(attacker->IsBot() && attacker->CastToBot()->GetBotOwner() && attacker->CastToBot()->GetBotOwner()->CastToClient()->GetPVP()) { - if(target->IsBot() && target->GetOwner() && target->GetOwner()->CastToClient()->GetPVP()) { + } else if (attacker->IsBot() && attacker->CastToBot()->GetBotOwner() && attacker->CastToBot()->GetBotOwner()->CastToClient()->GetPVP()) { + if (target->IsBot() && target->GetOwner() && target->GetOwner()->CastToClient()->GetPVP()) { hasRuleDefined = true; - if(target->GetOwner() == attacker->GetOwner()) + if (target->GetOwner() == attacker->GetOwner()) Result = false; else Result = true; - } else if(target->IsClient() && target->CastToClient()->GetPVP()) { + } else if (target->IsClient() && target->CastToClient()->GetPVP()) { hasRuleDefined = true; - if(target == attacker->GetOwner()) + if (target == attacker->GetOwner()) Result = false; else Result = true; - } else if(target->IsNPC()) { + } else if (target->IsNPC()) { hasRuleDefined = true; Result = true; - } else if(!target->IsNPC()) { + } else if (!target->IsNPC()) { hasRuleDefined = true; Result = false; } @@ -6063,23 +5442,22 @@ void Bot::BotOrderCampAll(Client* c, uint8 class_id) { const auto& l = entity_list.GetBotsByBotOwnerCharacterID(c->CharacterID()); for (const auto& b : l) { if (!class_id || b->GetClass() == class_id) { - b->Camp(); + b->Camp(true); } } } } void Bot::ProcessBotOwnerRefDelete(Mob* botOwner) { - if(botOwner) { - if(botOwner->IsClient()) { - std::list BotList = entity_list.GetBotsByBotOwnerCharacterID(botOwner->CastToClient()->CharacterID()); - if(!BotList.empty()) { - for(std::list::iterator botListItr = BotList.begin(); botListItr != BotList.end(); ++botListItr) { - Bot* tempBot = *botListItr; - if(tempBot) { - tempBot->SetTarget(0); - tempBot->SetBotOwner(0); - } + if (botOwner && botOwner->IsClient()) { + std::list BotList = entity_list.GetBotsByBotOwnerCharacterID(botOwner->CastToClient()->CharacterID()); + if (!BotList.empty()) { + for (std::list::iterator botListItr = BotList.begin(); botListItr != BotList.end(); ++botListItr) { + Bot* tempBot = *botListItr; + if (tempBot) { + tempBot->SetTarget(nullptr); + tempBot->SetBotOwner(nullptr); + tempBot->Zone(); } } } @@ -6089,8 +5467,11 @@ void Bot::ProcessBotOwnerRefDelete(Mob* botOwner) { int64 Bot::CalcMaxMana() { switch(GetCasterClass()) { case 'I': + max_mana = (GenerateBaseManaPoints() + itembonuses.Mana + spellbonuses.Mana + GroupLeadershipAAManaEnhancement()); + max_mana += (GetHeroicINT() * 10); case 'W': { max_mana = (GenerateBaseManaPoints() + itembonuses.Mana + spellbonuses.Mana + GroupLeadershipAAManaEnhancement()); + max_mana += (GetHeroicWIS() * 10); break; } case 'N': { @@ -6104,9 +5485,9 @@ int64 Bot::CalcMaxMana() { } } - if(current_mana > max_mana) + if (current_mana > max_mana) current_mana = max_mana; - else if(max_mana < 0) + else if (max_mana < 0) max_mana = 0; return max_mana; @@ -6174,7 +5555,7 @@ int32 Bot::GetActSpellDuration(uint16 spell_id, int32 duration) { int64 tic_inc = 0; tic_inc = GetFocusEffect(focusSpellDurByTic, spell_id); - if(IsBeneficialSpell(spell_id)) { + if (IsBeneficialSpell(spell_id)) { switch (GetAA(aaSpellCastingReinforcement)) { case 1: increase += 5; @@ -6194,7 +5575,7 @@ int32 Bot::GetActSpellDuration(uint16 spell_id, int32 duration) { increase += 20; } - if(IsMezSpell(spell_id)) + if (IsMezSpell(spell_id)) tic_inc += GetAA(aaMesmerizationMastery); return (((duration * increase) / 100) + tic_inc); @@ -6203,13 +5584,13 @@ int32 Bot::GetActSpellDuration(uint16 spell_id, int32 duration) { float Bot::GetAOERange(uint16 spell_id) { float range; range = spells[spell_id].aoe_range; - if(range == 0) + if (range == 0) range = spells[spell_id].range; - if(range == 0) + if (range == 0) range = 10; - if(IsBardSong(spell_id) && IsBeneficialSpell(spell_id)) { + if (IsBardSong(spell_id) && IsBeneficialSpell(spell_id)) { float song_bonus = (aabonuses.SongRange + spellbonuses.SongRange + itembonuses.SongRange); range += (range * song_bonus / 100.0f); } @@ -6220,13 +5601,13 @@ float Bot::GetAOERange(uint16 spell_id) { bool Bot::SpellEffect(Mob* caster, uint16 spell_id, float partial) { bool Result = false; Result = Mob::SpellEffect(caster, spell_id, partial); - if(IsGrouped()) { + if (IsGrouped()) { Group *g = GetGroup(); - if(g) { + if (g) { EQApplicationPacket hp_app; CreateHPPacket(&hp_app); - for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(g->members[i] && g->members[i]->IsClient()) + for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (g->members[i] && g->members[i]->IsClient()) g->members[i]->CastToClient()->QueuePacket(&hp_app); } } @@ -6327,7 +5708,17 @@ bool Bot::CastSpell( return Result; } -bool Bot::SpellOnTarget(uint16 spell_id, Mob* spelltar) { +bool Bot::SpellOnTarget( + uint16 spell_id, + Mob *spelltar, + int reflect_effectiveness, + bool use_resist_adjust, + int16 resist_adjust, + bool isproc, + int level_override, + int duration_override, + bool disable_buff_overwrite +) { if (!IsValidSpell(spell_id)) { return false; } @@ -6357,21 +5748,21 @@ bool Bot::SpellOnTarget(uint16 spell_id, Mob* spelltar) { bool Bot::IsImmuneToSpell(uint16 spell_id, Mob *caster) { bool Result = false; - if(!caster) + if (!caster) return false; - if(!IsSacrificeSpell(spell_id) && !(zone->GetZoneID() == 202) && !(this == caster)) { + if (!IsSacrificeSpell(spell_id) && zone->GetZoneID() != Zones::POKNOWLEDGE && this != caster) { Result = Mob::IsImmuneToSpell(spell_id, caster); - if(!Result) { - if(caster->IsBot()) { - if(spells[spell_id].target_type == ST_Undead) { - if((GetBodyType() != BT_SummonedUndead) && (GetBodyType() != BT_Undead) && (GetBodyType() != BT_Vampire)) { + if (!Result) { + if (caster->IsBot()) { + if (spells[spell_id].target_type == ST_Undead) { + if ((GetBodyType() != BT_SummonedUndead) && (GetBodyType() != BT_Undead) && (GetBodyType() != BT_Vampire)) { LogSpellsDetail("Bot's target is not an undead"); return true; } } - if(spells[spell_id].target_type == ST_Summoned) { - if((GetBodyType() != BT_SummonedUndead) && (GetBodyType() != BT_Summoned) && (GetBodyType() != BT_Summoned2) && (GetBodyType() != BT_Summoned3)) { + if (spells[spell_id].target_type == ST_Summoned) { + if ((GetBodyType() != BT_SummonedUndead) && (GetBodyType() != BT_Summoned) && (GetBodyType() != BT_Summoned2) && (GetBodyType() != BT_Summoned3)) { LogSpellsDetail("Bot's target is not a summoned creature"); return true; } @@ -6388,8 +5779,8 @@ bool Bot::IsImmuneToSpell(uint16 spell_id, Mob *caster) { bool Bot::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, EQ::spells::CastingSlot slot) { bool Result = false; SpellTargetType targetType = spells[spell_id].target_type; - if(targetType == ST_GroupClientAndPet) { - if((spell_id == 1768 && zone->GetZoneID() == 202) || (!IsDetrimentalSpell(spell_id))) { + if (targetType == ST_GroupClientAndPet) { + if ((spell_id == 1768 && zone->GetZoneID() == 202) || (!IsDetrimentalSpell(spell_id))) { CastAction = SingleTarget; return true; } @@ -6400,12 +5791,12 @@ bool Bot::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce bool Bot::DoCastSpell(uint16 spell_id, uint16 target_id, EQ::spells::CastingSlot slot, int32 cast_time, int32 mana_cost, uint32* oSpellWillFinish, uint32 item_slot, uint32 aa_id) { bool Result = false; - if(GetClass() == BARD) + if (GetClass() == BARD) cast_time = 0; Result = Mob::DoCastSpell(spell_id, target_id, slot, cast_time, mana_cost, oSpellWillFinish, item_slot, aa_id); - if(oSpellWillFinish) { + if (oSpellWillFinish) { const SPDat_Spell_Struct &spell = spells[spell_id]; *oSpellWillFinish = Timer::GetCurrentTime() + ((spell.recast_time > 20000) ? 10000 : spell.recast_time); } @@ -6423,18 +5814,18 @@ int32 Bot::GenerateBaseManaPoints() { case 'I': WisInt = INT; if (GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->ClientVersion() >= EQ::versions::ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) { - if(WisInt > 100) { + if (WisInt > 100) { ConvertedWisInt = (((WisInt - 100) * 5 / 2) + 100); - if(WisInt > 201) + if (WisInt > 201) ConvertedWisInt -= ((WisInt - 201) * 5 / 4); } else ConvertedWisInt = WisInt; - if(GetLevel() < 41) { + if (GetLevel() < 41) { wisint_mana = (GetLevel() * 75 * ConvertedWisInt / 1000); base_mana = (GetLevel() * 15); - } else if(GetLevel() < 81) { + } else if (GetLevel() < 81) { wisint_mana = ((3 * ConvertedWisInt) + ((GetLevel() - 40) * 15 * ConvertedWisInt / 100)); base_mana = (600 + ((GetLevel() - 40) * 30)); } else { @@ -6443,13 +5834,13 @@ int32 Bot::GenerateBaseManaPoints() { } bot_mana = (base_mana + wisint_mana); } else { - if(((WisInt - 199) / 2) > 0) + if (((WisInt - 199) / 2) > 0) MindLesserFactor = ((WisInt - 199) / 2); else MindLesserFactor = 0; MindFactor = WisInt - MindLesserFactor; - if(WisInt > 100) + if (WisInt > 100) bot_mana = (((5 * (MindFactor + 20)) / 2) * 3 * GetLevel() / 40); else bot_mana = (((5 * (MindFactor + 200)) / 2) * 3 * GetLevel() / 100); @@ -6458,17 +5849,17 @@ int32 Bot::GenerateBaseManaPoints() { case 'W': WisInt = WIS; if (GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->ClientVersion() >= EQ::versions::ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) { - if(WisInt > 100) { + if (WisInt > 100) { ConvertedWisInt = (((WisInt - 100) * 5 / 2) + 100); - if(WisInt > 201) + if (WisInt > 201) ConvertedWisInt -= ((WisInt - 201) * 5 / 4); } else ConvertedWisInt = WisInt; - if(GetLevel() < 41) { + if (GetLevel() < 41) { wisint_mana = (GetLevel() * 75 * ConvertedWisInt / 1000); base_mana = (GetLevel() * 15); - } else if(GetLevel() < 81) { + } else if (GetLevel() < 81) { wisint_mana = ((3 * ConvertedWisInt) + ((GetLevel() - 40) * 15 * ConvertedWisInt / 100)); base_mana = (600 + ((GetLevel() - 40) * 30)); } else { @@ -6477,13 +5868,13 @@ int32 Bot::GenerateBaseManaPoints() { } bot_mana = (base_mana + wisint_mana); } else { - if(((WisInt - 199) / 2) > 0) + if (((WisInt - 199) / 2) > 0) MindLesserFactor = ((WisInt - 199) / 2); else MindLesserFactor = 0; MindFactor = (WisInt - MindLesserFactor); - if(WisInt > 100) + if (WisInt > 100) bot_mana = (((5 * (MindFactor + 20)) / 2) * 3 * GetLevel() / 40); else bot_mana = (((5 * (MindFactor + 200)) / 2) * 3 * GetLevel() / 100); @@ -6498,13 +5889,13 @@ int32 Bot::GenerateBaseManaPoints() { } void Bot::GenerateSpecialAttacks() { - if(((GetClass() == MONK) || (GetClass() == WARRIOR) || (GetClass() == RANGER) || (GetClass() == BERSERKER)) && (GetLevel() >= 60)) + if (((GetClass() == MONK) || (GetClass() == WARRIOR) || (GetClass() == RANGER) || (GetClass() == BERSERKER)) && (GetLevel() >= 60)) SetSpecialAbility(SPECATK_TRIPLE, 1); } bool Bot::DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, EQ::spells::CastingSlot slot, bool& stopLogic) { - if(GetClass() == BARD) { - if(!ApplyBardPulse(bardsong, this, bardsong_slot)) + if (GetClass() == BARD) { + if (!ApplyBardPulse(bardsong, this, bardsong_slot)) InterruptSpell(SONG_ENDS_ABRUPTLY, 0x121, bardsong); stopLogic = true; @@ -6513,59 +5904,68 @@ bool Bot::DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, EQ::spells: } bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQ::spells::CastingSlot slot, bool& stopLogic) { - if(spellTarget) { - if(IsGrouped() && (spellTarget->IsBot() || spellTarget->IsClient()) && RuleB(Bots, GroupBuffing)) { - bool noGroupSpell = false; - uint16 thespell = spell_id; - for (int i = 0; i < AIBot_spells.size(); i++) { - int j = BotGetSpells(i); - int spelltype = BotGetSpellType(i); - bool spellequal = (j == thespell); - bool spelltypeequal = ((spelltype == 2) || (spelltype == 16) || (spelltype == 32)); - bool spelltypetargetequal = ((spelltype == 8) && (spells[thespell].target_type == ST_Self)); - bool spelltypeclassequal = ((spelltype == 1024) && (GetClass() == SHAMAN)); - bool slotequal = (slot == EQ::spells::CastingSlot::Item); - if(spellequal || slotequal) { - if((spelltypeequal || spelltypetargetequal) || spelltypeclassequal || slotequal) { - if(((spells[thespell].effect_id[0] == 0) && (spells[thespell].base_value[0] < 0)) && - (spellTarget->GetHP() < ((spells[thespell].base_value[0] * (-1)) + 100))) { - LogSpells("GroupBuffing failure"); - return false; - } - SpellOnTarget(thespell, spellTarget); - noGroupSpell = true; - stopLogic = true; + if ( + spellTarget && + IsGrouped() && + ( + spellTarget->IsBot() || + spellTarget->IsClient() + ) && + RuleB(Bots, GroupBuffing) + ) { + bool noGroupSpell = false; + uint16 thespell = spell_id; + for (int i = 0; i < AIBot_spells.size(); i++) { + int j = BotGetSpells(i); + int spelltype = BotGetSpellType(i); + bool spellequal = (j == thespell); + bool spelltypeequal = ((spelltype == 2) || (spelltype == 16) || (spelltype == 32)); + bool spelltypetargetequal = ((spelltype == 8) && (spells[thespell].target_type == ST_Self)); + bool spelltypeclassequal = ((spelltype == 1024) && (GetClass() == SHAMAN)); + bool slotequal = (slot == EQ::spells::CastingSlot::Item); + if (spellequal || slotequal) { + if ((spelltypeequal || spelltypetargetequal) || spelltypeclassequal || slotequal) { + if (((spells[thespell].effect_id[0] == 0) && (spells[thespell].base_value[0] < 0)) && + (spellTarget->GetHP() < ((spells[thespell].base_value[0] * (-1)) + 100))) { + LogSpells("GroupBuffing failure"); + return false; } + + SpellOnTarget(thespell, spellTarget); + noGroupSpell = true; + stopLogic = true; } } - - if(!noGroupSpell) { - Group *g = GetGroup(); - if(g) { - for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(g->members[i]) { - if((g->members[i]->GetClass() == NECROMANCER) && (IsEffectInSpell(thespell, SE_AbsorbMagicAtt) || IsEffectInSpell(thespell, SE_Rune))) { - } - else - SpellOnTarget(thespell, g->members[i]); - - if(g->members[i] && g->members[i]->GetPetID()) - SpellOnTarget(thespell, g->members[i]->GetPet()); - } - } - SetMana(GetMana() - (GetActSpellCost(thespell, spells[thespell].mana) * (g->GroupCount() - 1))); - } - } - stopLogic = true; } + + if (!noGroupSpell) { + Group *g = GetGroup(); + if (g) { + for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (g->members[i]) { + if ((g->members[i]->GetClass() == NECROMANCER) && (IsEffectInSpell(thespell, SE_AbsorbMagicAtt) || IsEffectInSpell(thespell, SE_Rune))) { + } + else + SpellOnTarget(thespell, g->members[i]); + + if (g->members[i] && g->members[i]->GetPetID()) + SpellOnTarget(thespell, g->members[i]->GetPet()); + } + } + SetMana(GetMana() - (GetActSpellCost(thespell, spells[thespell].mana) * (g->GroupCount() - 1))); + } + } + stopLogic = true; } return true; } bool Bot::DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, EQ::spells::CastingSlot slot, bool& stopLogic) { bool isMainGroupMGB = false; - if(isMainGroupMGB && (GetClass() != BARD)) { + Raid* raid = entity_list.GetRaidByBotName(GetName()); + + if (isMainGroupMGB && (GetClass() != BARD)) { BotGroupSay( this, fmt::format( @@ -6575,13 +5975,26 @@ bool Bot::DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, EQ::spel ); SpellOnTarget(spell_id, this); entity_list.AESpell(this, this, spell_id, true); - } else { + } + else if (raid) + { + std::vector raid_group_members = raid->GetRaidGroupMembers(raid->GetGroup(GetName())); + for (auto iter = raid_group_members.begin(); iter != raid_group_members.end(); ++iter) { + if (iter->member) { + SpellOnTarget(spell_id, iter->member); + if (iter->member && iter->member->GetPetID()) + SpellOnTarget(spell_id, iter->member ->GetPet()); + } + } + } + else + { Group *g = GetGroup(); - if(g) { - for(int i = 0; i < MAX_GROUP_MEMBERS; ++i) { - if(g->members[i]) { + if (g) { + for (int i = 0; i < MAX_GROUP_MEMBERS; ++i) { + if (g->members[i]) { SpellOnTarget(spell_id, g->members[i]); - if(g->members[i] && g->members[i]->GetPetID()) + if (g->members[i] && g->members[i]->GetPetID()) SpellOnTarget(spell_id, g->members[i]->GetPet()); } } @@ -6624,7 +6037,6 @@ void Bot::CalcBonuses() { } int64 Bot::CalcHPRegenCap() { - int level = GetLevel(); int64 hpregen_cap = 0; hpregen_cap = (RuleI(Character, ItemHealthRegenCap) + itembonuses.HeroicSTA / 25); hpregen_cap += (aabonuses.ItemHPRegenCap + spellbonuses.ItemHPRegenCap + itembonuses.ItemHPRegenCap); @@ -6635,10 +6047,10 @@ int64 Bot::CalcManaRegenCap() { int64 cap = RuleI(Character, ItemManaRegenCap) + aabonuses.ItemManaRegenCap; switch(GetCasterClass()) { case 'I': - cap += (itembonuses.HeroicINT / 25); + cap += itembonuses.HeroicINT * RuleR(Character, HeroicIntelligenceMultiplier) / 25; break; case 'W': - cap += (itembonuses.HeroicWIS / 25); + cap += itembonuses.HeroicWIS * RuleR(Character, HeroicWisdomMultiplier) / 25; break; } return (cap * RuleI(Character, ManaRegenMultiplier) / 100); @@ -6662,7 +6074,7 @@ int32 Bot::GetMaxStat() { int32 Bot::GetMaxResist() { int level = GetLevel(); int32 base = 500; - if(level > 60) + if (level > 60) base += ((level - 60) * 5); return base; @@ -6722,15 +6134,15 @@ int32 Bot::GetMaxCorrup() { int32 Bot::CalcSTR() { int32 val = (STR + itembonuses.STR + spellbonuses.STR); int32 mod = aabonuses.STR; - if(val > 255 && GetLevel() <= 60) + if (val > 255 && GetLevel() <= 60) val = 255; STR = (val + mod); - if(STR < 1) + if (STR < 1) STR = 1; int m = GetMaxSTR(); - if(STR > m) + if (STR > m) STR = m; return STR; @@ -6739,15 +6151,15 @@ int32 Bot::CalcSTR() { int32 Bot::CalcSTA() { int32 val = (STA + itembonuses.STA + spellbonuses.STA); int32 mod = aabonuses.STA; - if(val > 255 && GetLevel() <= 60) + if (val > 255 && GetLevel() <= 60) val = 255; STA = (val + mod); - if(STA < 1) + if (STA < 1) STA = 1; int m = GetMaxSTA(); - if(STA > m) + if (STA > m) STA = m; return STA; @@ -6756,15 +6168,15 @@ int32 Bot::CalcSTA() { int32 Bot::CalcAGI() { int32 val = (AGI + itembonuses.AGI + spellbonuses.AGI); int32 mod = aabonuses.AGI; - if(val > 255 && GetLevel() <= 60) + if (val > 255 && GetLevel() <= 60) val = 255; AGI = (val + mod); - if(AGI < 1) + if (AGI < 1) AGI = 1; int m = GetMaxAGI(); - if(AGI > m) + if (AGI > m) AGI = m; return AGI; @@ -6773,15 +6185,15 @@ int32 Bot::CalcAGI() { int32 Bot::CalcDEX() { int32 val = (DEX + itembonuses.DEX + spellbonuses.DEX); int32 mod = aabonuses.DEX; - if(val > 255 && GetLevel() <= 60) + if (val > 255 && GetLevel() <= 60) val = 255; DEX = (val + mod); - if(DEX < 1) + if (DEX < 1) DEX = 1; int m = GetMaxDEX(); - if(DEX > m) + if (DEX > m) DEX = m; return DEX; @@ -6790,16 +6202,16 @@ int32 Bot::CalcDEX() { int32 Bot::CalcINT() { int32 val = (INT + itembonuses.INT + spellbonuses.INT); int32 mod = aabonuses.INT; - if(val > 255 && GetLevel() <= 60) + if (val > 255 && GetLevel() <= 60) val = 255; INT = (val + mod); - if(INT < 1) + if (INT < 1) INT = 1; int m = GetMaxINT(); - if(INT > m) + if (INT > m) INT = m; return INT; @@ -6808,16 +6220,16 @@ int32 Bot::CalcINT() { int32 Bot::CalcWIS() { int32 val = (WIS + itembonuses.WIS + spellbonuses.WIS); int32 mod = aabonuses.WIS; - if(val > 255 && GetLevel() <= 60) + if (val > 255 && GetLevel() <= 60) val = 255; WIS = (val + mod); - if(WIS < 1) + if (WIS < 1) WIS = 1; int m = GetMaxWIS(); - if(WIS > m) + if (WIS > m) WIS = m; return WIS; @@ -6826,16 +6238,16 @@ int32 Bot::CalcWIS() { int32 Bot::CalcCHA() { int32 val = (CHA + itembonuses.CHA + spellbonuses.CHA); int32 mod = aabonuses.CHA; - if(val > 255 && GetLevel() <= 60) + if (val > 255 && GetLevel() <= 60) val = 255; CHA = (val + mod); - if(CHA < 1) + if (CHA < 1) CHA = 1; int m = GetMaxCHA(); - if(CHA > m) + if (CHA > m) CHA = m; return CHA; @@ -6843,13 +6255,13 @@ int32 Bot::CalcCHA() { int32 Bot::CalcMR() { MR += (itembonuses.MR + spellbonuses.MR + aabonuses.MR); - if(GetClass() == WARRIOR) + if (GetClass() == WARRIOR) MR += (GetLevel() / 2); - if(MR < 1) + if (MR < 1) MR = 1; - if(MR > GetMaxMR()) + if (MR > GetMaxMR()) MR = GetMaxMR(); return MR; @@ -6857,19 +6269,19 @@ int32 Bot::CalcMR() { int32 Bot::CalcFR() { int c = GetClass(); - if(c == RANGER) { + if (c == RANGER) { FR += 4; int l = GetLevel(); - if(l > 49) + if (l > 49) FR += (l - 49); } FR += (itembonuses.FR + spellbonuses.FR + aabonuses.FR); - if(FR < 1) + if (FR < 1) FR = 1; - if(FR > GetMaxFR()) + if (FR > GetMaxFR()) FR = GetMaxFR(); return FR; @@ -6877,23 +6289,23 @@ int32 Bot::CalcFR() { int32 Bot::CalcDR() { int c = GetClass(); - if(c == PALADIN) { + if (c == PALADIN) { DR += 8; int l = GetLevel(); - if(l > 49) + if (l > 49) DR += (l - 49); - } else if(c == SHADOWKNIGHT) { + } else if (c == SHADOWKNIGHT) { DR += 4; int l = GetLevel(); - if(l > 49) + if (l > 49) DR += (l - 49); } DR += (itembonuses.DR + spellbonuses.DR + aabonuses.DR); - if(DR < 1) + if (DR < 1) DR = 1; - if(DR > GetMaxDR()) + if (DR > GetMaxDR()) DR = GetMaxDR(); return DR; @@ -6901,24 +6313,24 @@ int32 Bot::CalcDR() { int32 Bot::CalcPR() { int c = GetClass(); - if(c == ROGUE) { + if (c == ROGUE) { PR += 8; int l = GetLevel(); - if(l > 49) + if (l > 49) PR += (l - 49); - } else if(c == SHADOWKNIGHT) { + } else if (c == SHADOWKNIGHT) { PR += 4; int l = GetLevel(); - if(l > 49) + if (l > 49) PR += (l - 49); } PR += (itembonuses.PR + spellbonuses.PR + aabonuses.PR); - if(PR < 1) + if (PR < 1) PR = 1; - if(PR > GetMaxPR()) + if (PR > GetMaxPR()) PR = GetMaxPR(); return PR; @@ -6926,19 +6338,19 @@ int32 Bot::CalcPR() { int32 Bot::CalcCR() { int c = GetClass(); - if(c == RANGER) { + if (c == RANGER) { CR += 4; int l = GetLevel(); - if(l > 49) + if (l > 49) CR += (l - 49); } CR += (itembonuses.CR + spellbonuses.CR + aabonuses.CR); - if(CR < 1) + if (CR < 1) CR = 1; - if(CR > GetMaxCR()) + if (CR > GetMaxCR()) CR = GetMaxCR(); return CR; @@ -6946,7 +6358,7 @@ int32 Bot::CalcCR() { int32 Bot::CalcCorrup() { Corrup = (Corrup + itembonuses.Corrup + spellbonuses.Corrup + aabonuses.Corrup); - if(Corrup > GetMaxCorrup()) + if (Corrup > GetMaxCorrup()) Corrup = GetMaxCorrup(); return Corrup; @@ -6958,18 +6370,18 @@ int32 Bot::CalcATK() { } void Bot::CalcRestState() { - if(!RuleB(Character, RestRegenEnabled)) + if (!RuleB(Character, RestRegenEnabled)) return; RestRegenHP = RestRegenMana = RestRegenEndurance = 0; - if(IsEngaged() || !IsSitting() || !rest_timer.Check(false)) + if (IsEngaged() || !IsSitting() || !rest_timer.Check(false)) return; uint32 buff_count = GetMaxTotalSlots(); for (unsigned int j = 0; j < buff_count; j++) { - if(buffs[j].spellid != SPELL_UNKNOWN) { - if(IsDetrimentalSpell(buffs[j].spellid) && (buffs[j].ticsremaining > 0)) - if(!DetrimentalSpellAllowsRest(buffs[j].spellid)) + if (IsValidSpell(buffs[j].spellid)) { + if (IsDetrimentalSpell(buffs[j].spellid) && (buffs[j].ticsremaining > 0)) + if (!DetrimentalSpellAllowsRest(buffs[j].spellid)) return; } } @@ -7030,7 +6442,9 @@ int32 Bot::LevelRegen() { int64 Bot::CalcHPRegen() { int32 regen = (LevelRegen() + itembonuses.HPRegen + spellbonuses.HPRegen); + regen += GetHeroicSTA() * RuleR(Character, HeroicStaminaMultiplier) / 20; regen += (aabonuses.HPRegen + GroupLeadershipAAHealthRegeneration()); + regen = ((regen * RuleI(Character, HPRegenMultiplier)) / 100); return regen; } @@ -7041,7 +6455,7 @@ int64 Bot::CalcManaRegen() { int32 regen = 0; if (IsSitting()) { BuffFadeBySitModifier(); - if(botclass != WARRIOR && botclass != MONK && botclass != ROGUE && botclass != BERSERKER) { + if (botclass != WARRIOR && botclass != MONK && botclass != ROGUE && botclass != BERSERKER) { regen = ((((GetSkill(EQ::skills::SkillMeditate) / 10) + (level - (level / 4))) / 4) + 4); regen += (spellbonuses.ManaRegen + itembonuses.ManaRegen); } else @@ -7050,16 +6464,17 @@ int64 Bot::CalcManaRegen() { regen = (2 + spellbonuses.ManaRegen + itembonuses.ManaRegen); if(GetCasterClass() == 'I') - regen += (itembonuses.HeroicINT / 25); + regen += itembonuses.HeroicINT * RuleR(Character, HeroicIntelligenceMultiplier) / 25; else if(GetCasterClass() == 'W') - regen += (itembonuses.HeroicWIS / 25); + regen += itembonuses.HeroicWIS * RuleR(Character, HeroicWisdomMultiplier) / 25; + else regen = 0; regen += aabonuses.ManaRegen; regen = ((regen * RuleI(Character, ManaRegenMultiplier)) / 100); float mana_regen_rate = RuleR(Bots, ManaRegen); - if(mana_regen_rate < 0.0f) + if (mana_regen_rate < 0.0f) mana_regen_rate = 0.0f; regen = (regen * mana_regen_rate); @@ -7101,6 +6516,7 @@ int64 Bot::CalcMaxHP() { int32 bot_hp = 0; uint32 nd = 10000; bot_hp += (GenerateBaseHitPoints() + itembonuses.HP); + bot_hp += GetHeroicSTA() * RuleR(Character, HeroicStaminaMultiplier) * 10; nd += aabonuses.MaxHP; bot_hp = ((float)bot_hp * (float)nd / (float)10000); bot_hp += (spellbonuses.HP + aabonuses.HP); @@ -7111,7 +6527,7 @@ int64 Bot::CalcMaxHP() { current_hp = max_hp; int hp_perc_cap = spellbonuses.HPPercCap[0]; - if(hp_perc_cap) { + if (hp_perc_cap) { int curHP_cap = ((max_hp * hp_perc_cap) / 100); if (current_hp > curHP_cap || (spellbonuses.HPPercCap[1] && current_hp > spellbonuses.HPPercCap[1])) current_hp = curHP_cap; @@ -7128,7 +6544,7 @@ int64 Bot::CalcMaxEndurance() { cur_end = max_end; int end_perc_cap = spellbonuses.EndPercCap[0]; - if(end_perc_cap) { + if (end_perc_cap) { int curEnd_cap = ((max_end * end_perc_cap) / 100); if (cur_end > curEnd_cap || (spellbonuses.EndPercCap[1] && cur_end > spellbonuses.EndPercCap[1])) cur_end = curEnd_cap; @@ -7140,35 +6556,43 @@ int64 Bot::CalcMaxEndurance() { int64 Bot::CalcBaseEndurance() { int32 base_end = 0; int32 base_endurance = 0; - int32 ConvertedStats = 0; + int32 converted_stats = 0; int32 sta_end = 0; - int Stats = 0; + int stats = 0; if (GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->ClientVersion() >= EQ::versions::ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) { - int HeroicStats = 0; - Stats = ((GetSTR() + GetSTA() + GetDEX() + GetAGI()) / 4); - HeroicStats = ((GetHeroicSTR() + GetHeroicSTA() + GetHeroicDEX() + GetHeroicAGI()) / 4); - if (Stats > 100) { - ConvertedStats = (((Stats - 100) * 5 / 2) + 100); - if (Stats > 201) - ConvertedStats -= ((Stats - 201) * 5 / 4); - } else - ConvertedStats = Stats; + double heroic_stats = 0; + stats = ((GetSTR() + GetSTA() + GetDEX() + GetAGI()) / 4); + double heroic_str = GetHeroicSTR() * RuleR(Character, HeroicStrengthMultiplier); + double heroic_sta = GetHeroicSTA() * RuleR(Character, HeroicStaminaMultiplier); + double heroic_dex = GetHeroicDEX() * RuleR(Character, HeroicDexterityMultiplier); + double heroic_agi = GetHeroicAGI() * RuleR(Character, HeroicAgilityMultiplier); + heroic_stats = (heroic_str + heroic_sta + heroic_dex + heroic_agi) / 4; + + if (stats > 100) { + converted_stats = (((stats - 100) * 5 / 2) + 100); + if (stats > 201) { + converted_stats -= ((stats - 201) * 5 / 4); + } + } else { + converted_stats = stats; + } if (GetLevel() < 41) { - sta_end = (GetLevel() * 75 * ConvertedStats / 1000); + sta_end = (GetLevel() * 75 * converted_stats / 1000); base_endurance = (GetLevel() * 15); } else if (GetLevel() < 81) { - sta_end = ((3 * ConvertedStats) + ((GetLevel() - 40) * 15 * ConvertedStats / 100)); + sta_end = ((3 * converted_stats) + ((GetLevel() - 40) * 15 * converted_stats / 100)); base_endurance = (600 + ((GetLevel() - 40) * 30)); } else { - sta_end = (9 * ConvertedStats); + sta_end = (9 * converted_stats); base_endurance = (1800 + ((GetLevel() - 80) * 18)); } - base_end = (base_endurance + sta_end + (HeroicStats * 10)); + base_end = (base_endurance + sta_end + (heroic_stats * 10)); } else { - Stats = (GetSTR()+GetSTA()+GetDEX()+GetAGI()); - int LevelBase = (GetLevel() * 15); - int at_most_800 = Stats; + + stats = (GetSTR() + GetSTA() + GetDEX() + GetAGI()); + int level_base = (GetLevel() * 15); + int at_most_800 = stats; if(at_most_800 > 800) at_most_800 = 800; @@ -7177,16 +6601,17 @@ int64 Bot::CalcBaseEndurance() { int Bonus800plus = 0; int HalfBonus800plus = 0; int BonusUpto800 = int(at_most_800 / 4) ; - if(Stats > 400) { + + if(stats > 400) { Bonus400to800 = int((at_most_800 - 400) / 4); HalfBonus400to800 = int(std::max((at_most_800 - 400), 0) / 8); - if(Stats > 800) { - Bonus800plus = (int((Stats - 800) / 8) * 2); - HalfBonus800plus = int((Stats - 800) / 16); + if(stats > 800) { + Bonus800plus = (int((stats - 800) / 8) * 2); + HalfBonus800plus = int((stats - 800) / 16); } } int bonus_sum = (BonusUpto800 + Bonus400to800 + HalfBonus400to800 + Bonus800plus + HalfBonus800plus); - base_end = LevelBase; + base_end = level_base; base_end += ((bonus_sum * 3 * GetLevel()) / 40); } return base_end; @@ -7204,9 +6629,9 @@ int64 Bot::CalcEnduranceRegenCap() { } void Bot::SetEndurance(int32 newEnd) { - if(newEnd < 0) + if (newEnd < 0) newEnd = 0; - else if(newEnd > GetMaxEndurance()) + else if (newEnd > GetMaxEndurance()) newEnd = GetMaxEndurance(); cur_end = newEnd; @@ -7218,17 +6643,17 @@ void Bot::DoEnduranceUpkeep() { uint32 buffs_i; uint32 buff_count = GetMaxTotalSlots(); for (buffs_i = 0; buffs_i < buff_count; buffs_i++) { - if (buffs[buffs_i].spellid != SPELL_UNKNOWN) { + if (IsValidSpell(buffs[buffs_i].spellid)) { int upkeep = spells[buffs[buffs_i].spellid].endurance_upkeep; - if(upkeep > 0) { - if(cost_redux > 0) { - if(upkeep <= cost_redux) + if (upkeep > 0) { + if (cost_redux > 0) { + if (upkeep <= cost_redux) continue; upkeep -= cost_redux; } - if((upkeep+upkeep_sum) > GetEndurance()) + if ((upkeep+upkeep_sum) > GetEndurance()) BuffFadeBySlot(buffs_i); else upkeep_sum += upkeep; @@ -7236,17 +6661,24 @@ void Bot::DoEnduranceUpkeep() { } } - if(upkeep_sum != 0) + if (upkeep_sum != 0) SetEndurance(GetEndurance() - upkeep_sum); } void Bot::Camp(bool save_to_database) { - Sit(); - if (GetGroup()) { - RemoveBotFromGroup(this, GetGroup()); + if (IsEngaged() || GetBotOwner()->IsEngaged()) { + GetBotOwner()->Message( + Chat::White, + fmt::format( + "You cannot camp your bots while in combat" + ).c_str() + ); + return; } + Sit(); + LeaveHealRotationMemberPool(); if (save_to_database) { @@ -7257,8 +6689,13 @@ void Bot::Camp(bool save_to_database) { } void Bot::Zone() { - if(HasGroup()) + Raid* raid = entity_list.GetRaidByBotName(GetName()); + if (raid) { + raid->MemberZoned(CastToClient()); + } + else if (HasGroup()) { GetGroup()->MemberZoned(this); + } Save(); Depop(); @@ -7266,12 +6703,12 @@ void Bot::Zone() { bool Bot::IsArcheryRange(Mob *target) { bool result = false; - if(target) { + if (target) { float range = (GetBotArcheryRange() + 5.0); range *= range; float targetDistance = DistanceSquaredNoZ(m_Position, target->GetPosition()); float minRuleDistance = (RuleI(Combat, MinRangedAttackDist) * RuleI(Combat, MinRangedAttackDist)); - if((targetDistance > range) || (targetDistance < minRuleDistance)) + if ((targetDistance > range) || (targetDistance < minRuleDistance)) result = false; else result = true; @@ -7424,34 +6861,13 @@ void Bot::UpdateGroupCastingRoles(const Group* group, bool disband) doter->CastToBot()->SetGroupDoter(); } -//void Bot::UpdateRaidCastingRoles(const Raid* raid, bool disband = false) { } - -bool Bot::CanHeal() { - bool result = false; - - if(!AI_HasSpells()) - return false; - - BotSpell botSpell; - botSpell.SpellId = 0; - botSpell.SpellIndex = 0; - botSpell.ManaCost = 0; - - botSpell = GetFirstBotSpellBySpellType(this, SpellType_Heal); - - if(botSpell.SpellId != 0) - result = true; - - return result; -} - -Bot* Bot::GetBotByBotClientOwnerAndBotName(Client* c, std::string botName) { +Bot* Bot::GetBotByBotClientOwnerAndBotName(Client* c, const std::string& botName) { Bot* Result = nullptr; - if(c) { + if (c) { std::list BotList = entity_list.GetBotsByBotOwnerCharacterID(c->CharacterID()); - if(!BotList.empty()) { - for(std::list::iterator botListItr = BotList.begin(); botListItr != BotList.end(); ++botListItr) { - if(std::string((*botListItr)->GetCleanName()) == botName) { + if (!BotList.empty()) { + for (auto botListItr = BotList.begin(); botListItr != BotList.end(); ++botListItr) { + if (std::string((*botListItr)->GetCleanName()) == botName) { Result = (*botListItr); break; } @@ -7461,14 +6877,14 @@ Bot* Bot::GetBotByBotClientOwnerAndBotName(Client* c, std::string botName) { return Result; } -void Bot::ProcessBotGroupInvite(Client* c, std::string botName) { - if(c) { +void Bot::ProcessBotGroupInvite(Client* c, std::string const& botName) { + if (c) { Bot* invitedBot = GetBotByBotClientOwnerAndBotName(c, botName); - if(invitedBot && !invitedBot->HasGroup()) { - if(!c->IsGrouped()) { - Group *g = new Group(c); - if(AddBotToGroup(invitedBot, g)) { + if (invitedBot && !invitedBot->HasGroup() && !invitedBot->HasRaid()) { + if (!c->IsGrouped()) { + auto g = new Group(c); + if (AddBotToGroup(invitedBot, g)) { entity_list.AddGroup(g); database.SetGroupLeaderName(g->GetID(), c->GetName()); g->SaveGroupLeaderAA(); @@ -7481,16 +6897,24 @@ void Bot::ProcessBotGroupInvite(Client* c, std::string botName) { AddBotToGroup(invitedBot, c->GetGroup()); database.SetGroupID(invitedBot->GetCleanName(), c->GetGroup()->GetID(), invitedBot->GetBotID()); } + if (c->HasRaid() && c->HasGroup()) { + Raid* raid = entity_list.GetRaidByClient(c); + if (raid) { + raid->AddBot(invitedBot, raid->GetGroup(c), false, false, false); + } + } + } else if (invitedBot->HasGroup()) { + c->MessageString(Chat::LightGray, TARGET_ALREADY_IN_GROUP, invitedBot->GetCleanName()); } } } // Processes a group disband request from a Client for a Bot. -void Bot::ProcessBotGroupDisband(Client* c, std::string botName) { - if(c) { +void Bot::ProcessBotGroupDisband(Client* c, const std::string& botName) { + if (c) { Bot* tempBot = nullptr; - if(botName.empty()) + if (botName.empty()) tempBot = GetFirstBotInGroup(c->GetGroup()); else tempBot = GetBotByBotClientOwnerAndBotName(c, botName); @@ -7499,22 +6923,41 @@ void Bot::ProcessBotGroupDisband(Client* c, std::string botName) { } } +// Processes a raid disband request from a Client for a Bot. +void Bot::RemoveBotFromRaid(Bot* bot) { + + Raid* bot_raid = entity_list.GetRaidByBotName(bot->GetName()); + if (bot_raid) { + uint32 gid = bot_raid->GetGroup(bot->GetName()); + bot_raid->SendRaidGroupRemove(bot->GetName(), gid); + bot_raid->RemoveMember(bot->GetName()); + bot_raid->GroupUpdate(gid); + if (!bot_raid->RaidCount()) { + bot_raid->DisbandRaid(); + } + } +} + // Handles all client zone change event void Bot::ProcessClientZoneChange(Client* botOwner) { - if(botOwner) { + if (botOwner) { std::list BotList = entity_list.GetBotsByBotOwnerCharacterID(botOwner->CharacterID()); - for(std::list::iterator itr = BotList.begin(); itr != BotList.end(); ++itr) { + for (std::list::iterator itr = BotList.begin(); itr != BotList.end(); ++itr) { Bot* tempBot = *itr; - if(tempBot) { - if(tempBot->HasGroup()) { + if (tempBot) { + Raid* raid = entity_list.GetRaidByBotName(tempBot->GetName()); + if (raid) { + tempBot->Zone(); + } + else if (tempBot->HasGroup()) { Group* g = tempBot->GetGroup(); - if(g && g->IsGroupMember(botOwner)) { - if(botOwner && botOwner->IsClient()) { + if (g && g->IsGroupMember(botOwner)) { + if (botOwner && botOwner->IsClient()) { // Modified to not only zone bots if you're the leader. // Also zone bots of the non-leader when they change zone. - if(tempBot->GetBotOwnerCharacterID() == botOwner->CharacterID() && g->IsGroupMember(botOwner)) + if (tempBot->GetBotOwnerCharacterID() == botOwner->CharacterID() && g->IsGroupMember(botOwner)) tempBot->Zone(); else tempBot->Camp(); @@ -7534,13 +6977,13 @@ void Bot::ProcessClientZoneChange(Client* botOwner) { Bot* Bot::GetFirstBotInGroup(Group* group) { Bot* Result = nullptr; - if(group) { - for(int Counter = 0; Counter < MAX_GROUP_MEMBERS; Counter++) { + if (group) { + for (int Counter = 0; Counter < MAX_GROUP_MEMBERS; Counter++) { if (group->members[Counter] == nullptr) { continue; } - if(group->members[Counter]->IsBot()) { + if (group->members[Counter]->IsBot()) { Result = group->members[Counter]->CastToBot(); break; } @@ -7552,7 +6995,7 @@ Bot* Bot::GetFirstBotInGroup(Group* group) { // Processes a client request to inspect a bot's equipment. void Bot::ProcessBotInspectionRequest(Bot* inspectedBot, Client* client) { - if(inspectedBot && client) { + if (inspectedBot && client) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_InspectAnswer, sizeof(InspectResponse_Struct)); InspectResponse_Struct* insr = (InspectResponse_Struct*) outapp->pBuffer; insr->TargetID = inspectedBot->GetNPCTypeID(); @@ -7564,9 +7007,9 @@ void Bot::ProcessBotInspectionRequest(Bot* inspectedBot, Client* client) { for (int16 L = EQ::invslot::EQUIPMENT_BEGIN; L <= EQ::invslot::EQUIPMENT_END; L++) { inst = inspectedBot->GetBotItem(L); - if(inst) { + if (inst) { item = inst->GetItem(); - if(item) { + if (item) { strcpy(insr->itemnames[L], item->Name); insr->itemicons[L] = item->Icon; } @@ -7594,19 +7037,19 @@ void Bot::CalcItemBonuses(StatBonuses* newbon) for (int i = EQ::invslot::BONUS_BEGIN; i <= EQ::invslot::BONUS_STAT_END; ++i) { const EQ::ItemInstance* item = GetBotItem(i); - if(item) { + if (item) { AddItemBonuses(item, newbon); } } // Caps - if(newbon->HPRegen > CalcHPRegenCap()) + if (newbon->HPRegen > CalcHPRegenCap()) newbon->HPRegen = CalcHPRegenCap(); - if(newbon->ManaRegen > CalcManaRegenCap()) + if (newbon->ManaRegen > CalcManaRegenCap()) newbon->ManaRegen = CalcManaRegenCap(); - if(newbon->EnduranceRegen > CalcEnduranceRegenCap()) + if (newbon->EnduranceRegen > CalcEnduranceRegenCap()) newbon->EnduranceRegen = CalcEnduranceRegenCap(); } @@ -7616,26 +7059,26 @@ void Bot::AddItemBonuses(const EQ::ItemInstance *inst, StatBonuses* newbon, bool return; } - if(inst->GetAugmentType()==0 && isAug == true) + if (inst->GetAugmentType()==0 && isAug) { return; } const EQ::ItemData *item = inst->GetItem(); - if(!isTribute && !inst->IsEquipable(GetBaseRace(),GetClass())) + if (!isTribute && !inst->IsEquipable(GetBaseRace(),GetClass())) { if (item->ItemType != EQ::item::ItemTypeFood && item->ItemType != EQ::item::ItemTypeDrink) return; } - if(GetLevel() < inst->GetItemRequiredLevel(true)) + if (GetLevel() < inst->GetItemRequiredLevel(true)) { return; } auto rec_level = isAug ? rec_override : inst->GetItemRecommendedLevel(true); - if(GetLevel() >= rec_level) + if (GetLevel() >= rec_level) { newbon->AC += item->AC; newbon->HP += item->HP; @@ -7740,94 +7183,94 @@ void Bot::AddItemBonuses(const EQ::ItemInstance *inst, StatBonuses* newbon, bool } //FatherNitwit: New style haste, shields, and regens - if(newbon->haste < (int32)item->Haste) { + if (newbon->haste < (int32)item->Haste) { newbon->haste = item->Haste; } - if(item->Regen > 0) + if (item->Regen > 0) newbon->HPRegen += item->Regen; - if(item->ManaRegen > 0) + if (item->ManaRegen > 0) newbon->ManaRegen += item->ManaRegen; - if(item->EnduranceRegen > 0) + if (item->EnduranceRegen > 0) newbon->EnduranceRegen += item->EnduranceRegen; - if(item->DamageShield > 0) { - if((newbon->DamageShield + item->DamageShield) > RuleI(Character, ItemDamageShieldCap)) + if (item->DamageShield > 0) { + if ((newbon->DamageShield + item->DamageShield) > RuleI(Character, ItemDamageShieldCap)) newbon->DamageShield = RuleI(Character, ItemDamageShieldCap); else newbon->DamageShield += item->DamageShield; } - if(item->SpellShield > 0) { - if((newbon->SpellShield + item->SpellShield) > RuleI(Character, ItemSpellShieldingCap)) + if (item->SpellShield > 0) { + if ((newbon->SpellShield + item->SpellShield) > RuleI(Character, ItemSpellShieldingCap)) newbon->SpellShield = RuleI(Character, ItemSpellShieldingCap); else newbon->SpellShield += item->SpellShield; } - if(item->Shielding > 0) { - if((newbon->MeleeMitigation + item->Shielding) > RuleI(Character, ItemShieldingCap)) + if (item->Shielding > 0) { + if ((newbon->MeleeMitigation + item->Shielding) > RuleI(Character, ItemShieldingCap)) newbon->MeleeMitigation = RuleI(Character, ItemShieldingCap); else newbon->MeleeMitigation += item->Shielding; } - if(item->StunResist > 0) { - if((newbon->StunResist + item->StunResist) > RuleI(Character, ItemStunResistCap)) + if (item->StunResist > 0) { + if ((newbon->StunResist + item->StunResist) > RuleI(Character, ItemStunResistCap)) newbon->StunResist = RuleI(Character, ItemStunResistCap); else newbon->StunResist += item->StunResist; } - if(item->StrikeThrough > 0) { - if((newbon->StrikeThrough + item->StrikeThrough) > RuleI(Character, ItemStrikethroughCap)) + if (item->StrikeThrough > 0) { + if ((newbon->StrikeThrough + item->StrikeThrough) > RuleI(Character, ItemStrikethroughCap)) newbon->StrikeThrough = RuleI(Character, ItemStrikethroughCap); else newbon->StrikeThrough += item->StrikeThrough; } - if(item->Avoidance > 0) { - if((newbon->AvoidMeleeChance + item->Avoidance) > RuleI(Character, ItemAvoidanceCap)) + if (item->Avoidance > 0) { + if ((newbon->AvoidMeleeChance + item->Avoidance) > RuleI(Character, ItemAvoidanceCap)) newbon->AvoidMeleeChance = RuleI(Character, ItemAvoidanceCap); else newbon->AvoidMeleeChance += item->Avoidance; } - if(item->Accuracy > 0) { - if((newbon->HitChance + item->Accuracy) > RuleI(Character, ItemAccuracyCap)) + if (item->Accuracy > 0) { + if ((newbon->HitChance + item->Accuracy) > RuleI(Character, ItemAccuracyCap)) newbon->HitChance = RuleI(Character, ItemAccuracyCap); else newbon->HitChance += item->Accuracy; } - if(item->CombatEffects > 0) { - if((newbon->ProcChance + item->CombatEffects) > RuleI(Character, ItemCombatEffectsCap)) + if (item->CombatEffects > 0) { + if ((newbon->ProcChance + item->CombatEffects) > RuleI(Character, ItemCombatEffectsCap)) newbon->ProcChance = RuleI(Character, ItemCombatEffectsCap); else newbon->ProcChance += item->CombatEffects; } - if(item->DotShielding > 0) { - if((newbon->DoTShielding + item->DotShielding) > RuleI(Character, ItemDoTShieldingCap)) + if (item->DotShielding > 0) { + if ((newbon->DoTShielding + item->DotShielding) > RuleI(Character, ItemDoTShieldingCap)) newbon->DoTShielding = RuleI(Character, ItemDoTShieldingCap); else newbon->DoTShielding += item->DotShielding; } - if(item->HealAmt > 0) { - if((newbon->HealAmt + item->HealAmt) > RuleI(Character, ItemHealAmtCap)) + if (item->HealAmt > 0) { + if ((newbon->HealAmt + item->HealAmt) > RuleI(Character, ItemHealAmtCap)) newbon->HealAmt = RuleI(Character, ItemHealAmtCap); else newbon->HealAmt += item->HealAmt; } - if(item->SpellDmg > 0) { - if((newbon->SpellDmg + item->SpellDmg) > RuleI(Character, ItemSpellDmgCap)) + if (item->SpellDmg > 0) { + if ((newbon->SpellDmg + item->SpellDmg) > RuleI(Character, ItemSpellDmgCap)) newbon->SpellDmg = RuleI(Character, ItemSpellDmgCap); else newbon->SpellDmg += item->SpellDmg; } - if(item->Clairvoyance > 0) { - if((newbon->Clairvoyance + item->Clairvoyance) > RuleI(Character, ItemClairvoyanceCap)) + if (item->Clairvoyance > 0) { + if ((newbon->Clairvoyance + item->Clairvoyance) > RuleI(Character, ItemClairvoyanceCap)) newbon->Clairvoyance = RuleI(Character, ItemClairvoyanceCap); else newbon->Clairvoyance += item->Clairvoyance; } - if(item->DSMitigation > 0) { - if((newbon->DSMitigation + item->DSMitigation) > RuleI(Character, ItemDSMitigationCap)) + if (item->DSMitigation > 0) { + if ((newbon->DSMitigation + item->DSMitigation) > RuleI(Character, ItemDSMitigationCap)) newbon->DSMitigation = RuleI(Character, ItemDSMitigationCap); else newbon->DSMitigation += item->DSMitigation; @@ -7844,45 +7287,45 @@ void Bot::AddItemBonuses(const EQ::ItemInstance *inst, StatBonuses* newbon, bool { case EQ::item::ItemTypeAllInstrumentTypes: // (e.g. Singing Short Sword) { - if(item->BardValue > newbon->singingMod) + if (item->BardValue > newbon->singingMod) newbon->singingMod = item->BardValue; - if(item->BardValue > newbon->brassMod) + if (item->BardValue > newbon->brassMod) newbon->brassMod = item->BardValue; - if(item->BardValue > newbon->stringedMod) + if (item->BardValue > newbon->stringedMod) newbon->stringedMod = item->BardValue; - if(item->BardValue > newbon->percussionMod) + if (item->BardValue > newbon->percussionMod) newbon->percussionMod = item->BardValue; - if(item->BardValue > newbon->windMod) + if (item->BardValue > newbon->windMod) newbon->windMod = item->BardValue; break; } case EQ::item::ItemTypeSinging: { - if(item->BardValue > newbon->singingMod) + if (item->BardValue > newbon->singingMod) newbon->singingMod = item->BardValue; break; } case EQ::item::ItemTypeWindInstrument: { - if(item->BardValue > newbon->windMod) + if (item->BardValue > newbon->windMod) newbon->windMod = item->BardValue; break; } case EQ::item::ItemTypeStringedInstrument: { - if(item->BardValue > newbon->stringedMod) + if (item->BardValue > newbon->stringedMod) newbon->stringedMod = item->BardValue; break; } case EQ::item::ItemTypeBrassInstrument: { - if(item->BardValue > newbon->brassMod) + if (item->BardValue > newbon->brassMod) newbon->brassMod = item->BardValue; break; } case EQ::item::ItemTypePercussionInstrument: { - if(item->BardValue > newbon->percussionMod) + if (item->BardValue > newbon->percussionMod) newbon->percussionMod = item->BardValue; break; } @@ -7896,11 +7339,15 @@ void Bot::AddItemBonuses(const EQ::ItemInstance *inst, StatBonuses* newbon, bool } } - if (item->ExtraDmgSkill != 0 && item->ExtraDmgSkill <= EQ::skills::HIGHEST_SKILL) { - if((newbon->SkillDamageAmount[item->ExtraDmgSkill] + item->ExtraDmgAmt) > RuleI(Character, ItemExtraDmgCap)) + if (item->ExtraDmgAmt != 0 && item->ExtraDmgSkill <= EQ::skills::HIGHEST_SKILL) { + if ( + RuleI(Character, ItemExtraDmgCap) >= 0 && + (newbon->SkillDamageAmount[item->ExtraDmgSkill] + item->ExtraDmgAmt) > RuleI(Character, ItemExtraDmgCap) + ) { newbon->SkillDamageAmount[item->ExtraDmgSkill] = RuleI(Character, ItemExtraDmgCap); - else + } else { newbon->SkillDamageAmount[item->ExtraDmgSkill] += item->ExtraDmgAmt; + } } if (!isAug) @@ -7913,11 +7360,11 @@ void Bot::AddItemBonuses(const EQ::ItemInstance *inst, StatBonuses* newbon, bool int Bot::CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat) { - if( (reclevel > 0) && (level < reclevel) ) + if ( (reclevel > 0) && (level < reclevel) ) { int32 statmod = (level * 10000 / reclevel) * basestat; - if( statmod < 0 ) + if ( statmod < 0 ) { statmod -= 5000; return (statmod/10000); @@ -7934,21 +7381,21 @@ int Bot::CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat) // This method is intended to call all necessary methods to do all bot stat calculations, including spell buffs, equipment, AA bonsues, etc. void Bot::CalcBotStats(bool showtext) { - if(!GetBotOwner()) + if (!GetBotOwner()) return; - if(showtext) { + if (showtext) { GetBotOwner()->Message(Chat::Yellow, "Updating %s...", GetCleanName()); } // this code is annoying since many classes change their name and illusions change the race id - /*if(!IsValidRaceClassCombo()) { + /*if (!IsValidRaceClassCombo()) { GetBotOwner()->Message(Chat::Yellow, "A %s - %s bot was detected. Is this Race/Class combination allowed?.", GetRaceIDName(GetRace()), GetClassIDName(GetClass(), GetLevel())); GetBotOwner()->Message(Chat::Yellow, "Previous Bots Code releases did not check Race/Class combinations during create."); GetBotOwner()->Message(Chat::Yellow, "Unless you are experiencing heavy lag, you should delete and remake this bot."); }*/ - if(GetBotOwner()->GetLevel() != GetLevel()) + if (GetBotOwner()->GetLevel() != GetLevel()) SetLevel(GetBotOwner()->GetLevel()); for (int sindex = 0; sindex <= EQ::skills::HIGHEST_SKILL; ++sindex) { @@ -7964,29 +7411,29 @@ void Bot::CalcBotStats(bool showtext) { LoadAAs(); GenerateSpecialAttacks(); - if(showtext) { + if (showtext) { GetBotOwner()->Message(Chat::Yellow, "Base stats:"); GetBotOwner()->Message(Chat::Yellow, "Level: %i HP: %i AC: %i Mana: %i STR: %i STA: %i DEX: %i AGI: %i INT: %i WIS: %i CHA: %i", GetLevel(), base_hp, AC, max_mana, STR, STA, DEX, AGI, INT, WIS, CHA); GetBotOwner()->Message(Chat::Yellow, "Resists-- Magic: %i, Poison: %i, Fire: %i, Cold: %i, Disease: %i, Corruption: %i.",MR,PR,FR,CR,DR,Corrup); // Test Code - if(GetClass() == BARD) + if (GetClass() == BARD) GetBotOwner()->Message(Chat::Yellow, "Bard Skills-- Brass: %i, Percussion: %i, Singing: %i, Stringed: %i, Wind: %i", GetSkill(EQ::skills::SkillBrassInstruments), GetSkill(EQ::skills::SkillPercussionInstruments), GetSkill(EQ::skills::SkillSinging), GetSkill(EQ::skills::SkillStringedInstruments), GetSkill(EQ::skills::SkillWindInstruments)); } - //if(Save()) + //if (Save()) // GetBotOwner()->CastToClient()->Message(Chat::White, "%s saved.", GetCleanName()); //else // GetBotOwner()->CastToClient()->Message(Chat::White, "%s save failed!", GetCleanName()); CalcBonuses(); - if(showtext) { + if (showtext) { GetBotOwner()->Message(Chat::Yellow, "%s has been updated.", GetCleanName()); GetBotOwner()->Message(Chat::Yellow, "Level: %i HP: %i AC: %i Mana: %i STR: %i STA: %i DEX: %i AGI: %i INT: %i WIS: %i CHA: %i", GetLevel(), max_hp, GetAC(), max_mana, GetSTR(), GetSTA(), GetDEX(), GetAGI(), GetINT(), GetWIS(), GetCHA()); GetBotOwner()->Message(Chat::Yellow, "Resists-- Magic: %i, Poison: %i, Fire: %i, Cold: %i, Disease: %i, Corruption: %i.",GetMR(),GetPR(),GetFR(),GetCR(),GetDR(),GetCorrup()); // Test Code - if(GetClass() == BARD) { + if (GetClass() == BARD) { GetBotOwner()->Message(Chat::Yellow, "Bard Skills-- Brass: %i, Percussion: %i, Singing: %i, Stringed: %i, Wind: %i", GetSkill(EQ::skills::SkillBrassInstruments) + GetBrassMod(), GetSkill(EQ::skills::SkillPercussionInstruments) + GetPercMod(), @@ -8010,13 +7457,15 @@ bool Bot::CheckLoreConflict(const EQ::ItemData* item) { } bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, float iRange, uint32 iSpellTypes) { - if((iSpellTypes & SPELL_TYPES_DETRIMENTAL) != 0) { + + if ((iSpellTypes & SPELL_TYPES_DETRIMENTAL) != 0) { LogError("[EntityList::Bot_AICheckCloseBeneficialSpells] detrimental spells requested"); return false; } - if(!caster || !caster->AI_HasSpells()) + if (!caster || !caster->AI_HasSpells()) { return false; + } if (iChance < 100) { uint8 tmp = zone->random.Int(1, 100); @@ -8026,33 +7475,72 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl uint8 botCasterClass = caster->GetClass(); - if( iSpellTypes == SpellType_Heal ) { - if( botCasterClass == CLERIC || botCasterClass == DRUID || botCasterClass == SHAMAN) { - if(caster->HasGroup()) { + if (iSpellTypes == SpellType_Heal) { + if ( botCasterClass == CLERIC || botCasterClass == DRUID || botCasterClass == SHAMAN) { + if (caster->HasGroup()) { Group *g = caster->GetGroup(); - if(g) { - for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(g->members[i] && !g->members[i]->qglobal) { - if(g->members[i]->IsClient() && g->members[i]->GetHPRatio() < 90) { - if(caster->AICastSpell(g->members[i], 100, SpellType_Heal)) + if (g) { + for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (g->members[i] && !g->members[i]->qglobal) { + if (g->members[i]->IsClient() && g->members[i]->GetHPRatio() < 90) { + if (caster->AICastSpell(g->members[i], 100, SpellType_Heal)) return true; - } else if((g->members[i]->GetClass() == WARRIOR || g->members[i]->GetClass() == PALADIN || g->members[i]->GetClass() == SHADOWKNIGHT) && g->members[i]->GetHPRatio() < 95) { - if(caster->AICastSpell(g->members[i], 100, SpellType_Heal)) + } else if ((g->members[i]->GetClass() == WARRIOR || g->members[i]->GetClass() == PALADIN || g->members[i]->GetClass() == SHADOWKNIGHT) && g->members[i]->GetHPRatio() < 95) { + if (caster->AICastSpell(g->members[i], 100, SpellType_Heal)) return true; - } else if(g->members[i]->GetClass() == ENCHANTER && g->members[i]->GetHPRatio() < 80) { - if(caster->AICastSpell(g->members[i], 100, SpellType_Heal)) + } else if (g->members[i]->GetClass() == ENCHANTER && g->members[i]->GetHPRatio() < 80) { + if (caster->AICastSpell(g->members[i], 100, SpellType_Heal)) return true; - } else if(g->members[i]->GetHPRatio() < 70) { - if(caster->AICastSpell(g->members[i], 100, SpellType_Heal)) + } else if (g->members[i]->GetHPRatio() < 70) { + if (caster->AICastSpell(g->members[i], 100, SpellType_Heal)) return true; } } - if(g->members[i] && !g->members[i]->qglobal && g->members[i]->HasPet() && g->members[i]->GetPet()->GetHPRatio() < 50) { - if(g->members[i]->GetPet()->GetOwner() != caster && caster->IsEngaged() && g->members[i]->IsCasting() && g->members[i]->GetClass() != ENCHANTER ) + if (g->members[i] && !g->members[i]->qglobal && g->members[i]->HasPet() && g->members[i]->GetPet()->GetHPRatio() < 50) { + if (g->members[i]->GetPet()->GetOwner() != caster && caster->IsEngaged() && g->members[i]->IsCasting() && g->members[i]->GetClass() != ENCHANTER ) continue; - if(caster->AICastSpell(g->members[i]->GetPet(), 100, SpellType_Heal)) + if (caster->AICastSpell(g->members[i]->GetPet(), 100, SpellType_Heal)) + return true; + } + } + } + } + else if (caster->IsRaidGrouped()) + { + //added raid check + Raid* raid = entity_list.GetRaidByBotName(caster->GetName()); + uint32 gid = raid->GetGroup(caster->GetName()); + if (gid < MAX_RAID_GROUPS) { + std::vector raid_group_members = raid->GetRaidGroupMembers(gid); + for (std::vector::iterator iter = raid_group_members.begin(); iter != raid_group_members.end(); ++iter) { + //for (auto& iter : raid->GetRaidGroupMembers(g)) { + if (iter->member && !iter->member->qglobal) { + if (iter->member->IsClient() && iter->member->GetHPRatio() < 90) { + if (caster->AICastSpell(iter->member, 100, SpellType_Heal)) + return true; + } + else if ((iter->member->GetClass() == WARRIOR || iter->member->GetClass() == PALADIN || iter->member->GetClass() == SHADOWKNIGHT) && iter->member->GetHPRatio() < 95) { + if (caster->AICastSpell(iter->member, 100, SpellType_Heal)) + return true; + } + else if (iter->member->GetClass() == ENCHANTER && iter->member->GetHPRatio() < 80) { + if (caster->AICastSpell(iter->member, 100, SpellType_Heal)) + return true; + } + else if (iter->member->GetHPRatio() < 70) { + if (caster->AICastSpell(iter->member, 100, SpellType_Heal)) + return true; + } + + } + + if (iter->member && !iter->member->qglobal && iter->member->HasPet() && iter->member->GetPet()->GetHPRatio() < 50) { + if (iter->member->GetPet()->GetOwner() != caster && caster->IsEngaged() && iter->member->IsCasting() && iter->member->GetClass() != ENCHANTER) + continue; + + if (caster->AICastSpell(iter->member->GetPet(), 100, SpellType_Heal)) return true; } } @@ -8060,52 +7548,88 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl } } - if( botCasterClass == PALADIN || botCasterClass == BEASTLORD || botCasterClass == RANGER) { - if(caster->HasGroup()) { - Group *g = caster->GetGroup(); - float hpRatioToHeal = 25.0f; - switch(caster->GetBotStance()) { - case EQ::constants::stanceReactive: - case EQ::constants::stanceBalanced: - hpRatioToHeal = 50.0f; - break; - case EQ::constants::stanceBurn: - case EQ::constants::stanceBurnAE: - hpRatioToHeal = 20.0f; - break; - case EQ::constants::stanceAggressive: - case EQ::constants::stanceEfficient: - default: - hpRatioToHeal = 25.0f; - break; - } + if ((botCasterClass == PALADIN || botCasterClass == BEASTLORD || botCasterClass == RANGER) && (caster->HasGroup() || caster->IsRaidGrouped())) { + float hpRatioToHeal = 25.0f; + switch(caster->GetBotStance()) { + case EQ::constants::stanceReactive: + case EQ::constants::stanceBalanced: + hpRatioToHeal = 50.0f; + break; + case EQ::constants::stanceBurn: + case EQ::constants::stanceBurnAE: + hpRatioToHeal = 20.0f; + break; + case EQ::constants::stanceAggressive: + case EQ::constants::stanceEfficient: + default: + hpRatioToHeal = 25.0f; + break; + } + Group* g = caster->GetGroup(); + uint32 gid = RAID_GROUPLESS; + Raid* raid = entity_list.GetRaidByBotName(caster->GetName()); + if (raid) { + gid = raid->GetGroup(caster->GetName()); + } - if(g) { - for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(g->members[i] && !g->members[i]->qglobal) { - if(g->members[i]->IsClient() && g->members[i]->GetHPRatio() < hpRatioToHeal) { - if(caster->AICastSpell(g->members[i], 100, SpellType_Heal)) - return true; - } else if((g->members[i]->GetClass() == WARRIOR || g->members[i]->GetClass() == PALADIN || g->members[i]->GetClass() == SHADOWKNIGHT) && g->members[i]->GetHPRatio() < hpRatioToHeal) { - if(caster->AICastSpell(g->members[i], 100, SpellType_Heal)) - return true; - } else if(g->members[i]->GetClass() == ENCHANTER && g->members[i]->GetHPRatio() < hpRatioToHeal) { - if(caster->AICastSpell(g->members[i], 100, SpellType_Heal)) - return true; - } else if(g->members[i]->GetHPRatio() < hpRatioToHeal/2) { - if(caster->AICastSpell(g->members[i], 100, SpellType_Heal)) - return true; - } - } - - if(g->members[i] && !g->members[i]->qglobal && g->members[i]->HasPet() && g->members[i]->GetPet()->GetHPRatio() < 25) { - if(g->members[i]->GetPet()->GetOwner() != caster && caster->IsEngaged() && g->members[i]->IsCasting() && g->members[i]->GetClass() != ENCHANTER ) - continue; - - if(caster->AICastSpell(g->members[i]->GetPet(), 100, SpellType_Heal)) + if (g) { + for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (g->members[i] && !g->members[i]->qglobal) { + if (g->members[i]->IsClient() && g->members[i]->GetHPRatio() < hpRatioToHeal) { + if (caster->AICastSpell(g->members[i], 100, SpellType_Heal)) + return true; + } else if ((g->members[i]->GetClass() == WARRIOR || g->members[i]->GetClass() == PALADIN || g->members[i]->GetClass() == SHADOWKNIGHT) && g->members[i]->GetHPRatio() < hpRatioToHeal) { + if (caster->AICastSpell(g->members[i], 100, SpellType_Heal)) + return true; + } else if (g->members[i]->GetClass() == ENCHANTER && g->members[i]->GetHPRatio() < hpRatioToHeal) { + if (caster->AICastSpell(g->members[i], 100, SpellType_Heal)) + return true; + } else if (g->members[i]->GetHPRatio() < hpRatioToHeal/2) { + if (caster->AICastSpell(g->members[i], 100, SpellType_Heal)) return true; } } + + if (g->members[i] && !g->members[i]->qglobal && g->members[i]->HasPet() && g->members[i]->GetPet()->GetHPRatio() < 25) { + if (g->members[i]->GetPet()->GetOwner() != caster && caster->IsEngaged() && g->members[i]->IsCasting() && g->members[i]->GetClass() != ENCHANTER ) + continue; + + if (caster->AICastSpell(g->members[i]->GetPet(), 100, SpellType_Heal)) + return true; + } + } + } + else if (gid < MAX_RAID_GROUPS) + { + std::vector raid_group_members = raid->GetRaidGroupMembers(gid); + for (std::vector::iterator iter = raid_group_members.begin(); iter != raid_group_members.end(); ++iter) { + //for (auto& iter : raid->GetRaidGroupMembers(gid)) { + if (iter->member && !iter->member->qglobal) { + if (iter->member->IsClient() && iter->member->GetHPRatio() < hpRatioToHeal) { + if (caster->AICastSpell(iter->member, 100, SpellType_Heal)) + return true; + } + else if ((iter->member->GetClass() == WARRIOR || iter->member->GetClass() == PALADIN || iter->member->GetClass() == SHADOWKNIGHT) && iter->member->GetHPRatio() < hpRatioToHeal) { + if (caster->AICastSpell(iter->member, 100, SpellType_Heal)) + return true; + } + else if (iter->member->GetClass() == ENCHANTER && iter->member->GetHPRatio() < hpRatioToHeal) { + if (caster->AICastSpell(iter->member, 100, SpellType_Heal)) + return true; + } + else if (iter->member->GetHPRatio() < hpRatioToHeal / 2) { + if (caster->AICastSpell(iter->member, 100, SpellType_Heal)) + return true; + } + } + + if (iter->member && !iter->member->qglobal && iter->member->HasPet() && iter->member->GetPet()->GetHPRatio() < 25) { + if (iter->member->GetPet()->GetOwner() != caster && caster->IsEngaged() && iter->member->IsCasting() && iter->member->GetClass() != ENCHANTER) + continue; + + if (caster->AICastSpell(iter->member->GetPet(), 100, SpellType_Heal)) + return true; + } } } } @@ -8114,18 +7638,31 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl if (iSpellTypes == SpellType_Buff) { uint8 chanceToCast = caster->IsEngaged() ? caster->GetChanceToCastBySpellType(SpellType_Buff) : 100; if (botCasterClass == BARD) { - if(caster->AICastSpell(caster, chanceToCast, SpellType_Buff)) + if (caster->AICastSpell(caster, chanceToCast, SpellType_Buff)) { return true; - else + } else return false; } + if (caster->IsRaidGrouped()) { + Raid* raid = entity_list.GetRaidByBotName(caster->GetName()); + uint32 g = raid->GetGroup(caster->GetName()); + if (g < MAX_RAID_GROUPS) { + std::vector raid_group_members = raid->GetRaidGroupMembers(g); + for (std::vector::iterator iter = raid_group_members.begin(); iter != raid_group_members.end(); ++iter) { + if (iter->member) { + if (caster->AICastSpell(iter->member, chanceToCast, SpellType_Buff) || caster->AICastSpell(iter->member->GetPet(), chanceToCast, SpellType_Buff)) + return true; + } + } + } + } if (caster->HasGroup()) { Group *g = caster->GetGroup(); - if(g) { - for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(g->members[i]) { - if(caster->AICastSpell(g->members[i], chanceToCast, SpellType_Buff) || caster->AICastSpell(g->members[i]->GetPet(), chanceToCast, SpellType_Buff)) + if (g) { + for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (g->members[i]) { + if (caster->AICastSpell(g->members[i], chanceToCast, SpellType_Buff) || caster->AICastSpell(g->members[i]->GetPet(), chanceToCast, SpellType_Buff)) return true; } } @@ -8133,20 +7670,41 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl } } - if( iSpellTypes == SpellType_Cure) { - if(caster->HasGroup()) { + if ( iSpellTypes == SpellType_Cure) { + if (caster->HasGroup()) { Group *g = caster->GetGroup(); - if(g) { - for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(g->members[i] && caster->GetNeedsCured(g->members[i])) { - if(caster->AICastSpell(g->members[i], caster->GetChanceToCastBySpellType(SpellType_Cure), SpellType_Cure)) + if (g) { + for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (g->members[i] && caster->GetNeedsCured(g->members[i])) { + if (caster->AICastSpell(g->members[i], caster->GetChanceToCastBySpellType(SpellType_Cure), SpellType_Cure)) return true; - else if(botCasterClass == BARD) + else if (botCasterClass == BARD) return false; } - if(g->members[i] && g->members[i]->GetPet() && caster->GetNeedsCured(g->members[i]->GetPet())) { - if(caster->AICastSpell(g->members[i]->GetPet(), (int)caster->GetChanceToCastBySpellType(SpellType_Cure)/4, SpellType_Cure)) + if (g->members[i] && g->members[i]->GetPet() && caster->GetNeedsCured(g->members[i]->GetPet())) { + if (caster->AICastSpell(g->members[i]->GetPet(), (int)caster->GetChanceToCastBySpellType(SpellType_Cure)/4, SpellType_Cure)) + return true; + } + } + } + } + else if (caster->IsRaidGrouped()) + { + Raid* raid = entity_list.GetRaidByBotName(caster->GetName()); + uint32 gid = raid->GetGroup(caster->GetName()); + if (gid < MAX_RAID_GROUPS) { + std::vector raid_group_members = raid->GetRaidGroupMembers(gid); + for (std::vector::iterator iter = raid_group_members.begin(); iter != raid_group_members.end(); ++iter) { + if (iter->member && caster->GetNeedsCured(iter->member)) { + if (caster->AICastSpell(iter->member, caster->GetChanceToCastBySpellType(SpellType_Cure), SpellType_Cure)) + return true; + else if (botCasterClass == BARD) + return false; + } + + if (iter->member && iter->member->GetPet() && caster->GetNeedsCured(iter->member->GetPet())) { + if (caster->AICastSpell(iter->member->GetPet(), (int)caster->GetChanceToCastBySpellType(SpellType_Cure) / 4, SpellType_Cure)) return true; } } @@ -8169,14 +7727,44 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl } } } + else if (caster->IsRaidGrouped()) + { + Raid* raid = entity_list.GetRaidByBotName(caster->GetName()); + uint32 gid = raid->GetGroup(caster->GetName()); + if (gid < MAX_RAID_GROUPS) { + std::vector raid_group_members = raid->GetRaidGroupMembers(gid); + for (std::vector::iterator iter = raid_group_members.begin(); iter != raid_group_members.end(); ++iter) { + if (iter->member && caster->GetNeedsHateRedux(iter->member)) { + if (caster->AICastSpell(iter->member, caster->GetChanceToCastBySpellType(SpellType_HateRedux), SpellType_HateRedux)) + return true; + } + } + } + } + } if (iSpellTypes == SpellType_PreCombatBuff) { if (botCasterClass == BARD || caster->IsEngaged()) return false; - if (caster->HasGroup()) { - Group *g = caster->GetGroup(); + //added raid check + if (caster->IsRaidGrouped()) { + Raid* raid = entity_list.GetRaidByBotName(caster->GetName()); + uint32 g = raid->GetGroup(caster->GetName()); + if (g < MAX_RAID_GROUPS) { + std::vector raid_group_members = raid->GetRaidGroupMembers(g); + for (std::vector::iterator iter = raid_group_members.begin(); iter != raid_group_members.end(); ++iter) { + if (iter->member && + (caster->AICastSpell(iter->member, iChance, SpellType_PreCombatBuff) || + caster->AICastSpell(iter->member->GetPet(), iChance, SpellType_PreCombatBuff)) + ) { + return true; + } + } + } + } else if (caster->HasGroup()) { + const auto g = caster->GetGroup(); if (g) { for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { if (g->members[i]) { @@ -8218,14 +7806,13 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl Mob* EntityList::GetMobByBotID(uint32 botID) { Mob* Result = nullptr; - if(botID > 0) { - auto it = mob_list.begin(); - for (auto it = mob_list.begin(); it != mob_list.end(); ++it) { - if(!it->second) + if (botID > 0) { + for (const auto& m: mob_list) { + if (!m.second) continue; - if(it->second->IsBot() && it->second->CastToBot()->GetBotID() == botID) { - Result = it->second; + if (m.second->IsBot() && m.second->CastToBot()->GetBotID() == botID) { + Result = m.second; break; } } @@ -8235,10 +7822,10 @@ Mob* EntityList::GetMobByBotID(uint32 botID) { Bot* EntityList::GetBotByBotID(uint32 botID) { Bot* Result = nullptr; - if(botID > 0) { - for(std::list::iterator botListItr = bot_list.begin(); botListItr != bot_list.end(); ++botListItr) { + if (botID > 0) { + for (std::list::iterator botListItr = bot_list.begin(); botListItr != bot_list.end(); ++botListItr) { Bot* tempBot = *botListItr; - if(tempBot && tempBot->GetBotID() == botID) { + if (tempBot && tempBot->GetBotID() == botID) { Result = tempBot; break; } @@ -8247,12 +7834,12 @@ Bot* EntityList::GetBotByBotID(uint32 botID) { return Result; } -Bot* EntityList::GetBotByBotName(std::string botName) { +Bot* EntityList::GetBotByBotName(std::string_view botName) { Bot* Result = nullptr; - if(!botName.empty()) { - for(std::list::iterator botListItr = bot_list.begin(); botListItr != bot_list.end(); ++botListItr) { + if (!botName.empty()) { + for (std::list::iterator botListItr = bot_list.begin(); botListItr != bot_list.end(); ++botListItr) { Bot* tempBot = *botListItr; - if(tempBot && std::string(tempBot->GetName()) == botName) { + if (tempBot && std::string(tempBot->GetName()) == botName) { Result = tempBot; break; } @@ -8294,7 +7881,11 @@ void EntityList::AddBot(Bot *new_bot, bool send_spawn_packet, bool dont_queue) { new_bot->SetID(GetFreeID()); bot_list.push_back(new_bot); mob_list.insert(std::pair(new_bot->GetID(), new_bot)); - parse->EventBot(EVENT_SPAWN, new_bot, nullptr, "", 0); + + if (parse->BotHasQuestSub(EVENT_SPAWN)) { + parse->EventBot(EVENT_SPAWN, new_bot, nullptr, "", 0); + } + new_bot->SetSpawned(); if (send_spawn_packet) { if (dont_queue) { @@ -8312,16 +7903,18 @@ void EntityList::AddBot(Bot *new_bot, bool send_spawn_packet, bool dont_queue) { } } - new_bot->DispatchZoneControllerEvent(EVENT_SPAWN_ZONE, new_bot, "", 0, nullptr); + if (parse->HasQuestSub(ZONE_CONTROLLER_NPC_ID, EVENT_SPAWN_ZONE)) { + new_bot->DispatchZoneControllerEvent(EVENT_SPAWN_ZONE, new_bot, "", 0, nullptr); + } } } std::list EntityList::GetBotsByBotOwnerCharacterID(uint32 botOwnerCharacterID) { std::list Result; - if(botOwnerCharacterID > 0) { - for(std::list::iterator botListItr = bot_list.begin(); botListItr != bot_list.end(); ++botListItr) { + if (botOwnerCharacterID > 0) { + for (std::list::iterator botListItr = bot_list.begin(); botListItr != bot_list.end(); ++botListItr) { Bot* tempBot = *botListItr; - if(tempBot && tempBot->GetBotOwnerCharacterID() == botOwnerCharacterID) + if (tempBot && tempBot->GetBotOwnerCharacterID() == botOwnerCharacterID) Result.push_back(tempBot); } } @@ -8330,10 +7923,10 @@ std::list EntityList::GetBotsByBotOwnerCharacterID(uint32 botOwnerCharacte bool EntityList::RemoveBot(uint16 entityID) { bool Result = false; - if(entityID > 0) { - for(std::list::iterator botListItr = bot_list.begin(); botListItr != bot_list.end(); ++botListItr) { + if (entityID > 0) { + for (std::list::iterator botListItr = bot_list.begin(); botListItr != bot_list.end(); ++botListItr) { Bot* tempBot = *botListItr; - if(tempBot && tempBot->GetID() == entityID) { + if (tempBot && tempBot->GetID() == entityID) { bot_list.erase(botListItr); Result = true; break; @@ -8350,11 +7943,11 @@ void EntityList::ShowSpawnWindow(Client* client, int Distance, bool NamedOnly) { int CurrentCon = 0; Mob* curMob = nullptr; uint32 array_counter = 0; - auto it = mob_list.begin(); - for (auto it = mob_list.begin(); it != mob_list.end(); ++it) { - curMob = it->second; + + for (const auto& m : mob_list) { + curMob = m.second; if (curMob && DistanceNoZ(curMob->GetPosition(), client->GetPosition()) <= Distance) { - if(curMob->IsTrackable()) { + if (curMob->IsTrackable()) { Mob* cur_entity = curMob; int Extras = (cur_entity->IsBot() || cur_entity->IsPet() || cur_entity->IsFamiliar() || cur_entity->IsClient()); const char *const MyArray[] = { @@ -8392,7 +7985,7 @@ void EntityList::ShowSpawnWindow(Client* client, int Distance, bool NamedOnly) { for ( MyArraySize = 0; true; MyArraySize++) { if (!(*(MyArray[MyArraySize]))) break; - }; + } if (NamedOnly) { bool ContinueFlag = false; const char *CurEntityName = cur_entity->GetName(); @@ -8400,15 +7993,15 @@ void EntityList::ShowSpawnWindow(Client* client, int Distance, bool NamedOnly) { if (!strncasecmp(CurEntityName, MyArray[Index], strlen(MyArray[Index])) || (Extras)) { ContinueFlag = true; break; - }; - }; + } + } if (ContinueFlag) continue; - }; + } CurrentCon = client->GetLevelCon(cur_entity->GetLevel()); - if(CurrentCon != LastCon) { - if(LastCon != -1) + if (CurrentCon != LastCon) { + if (LastCon != -1) WindowText += ""; LastCon = CurrentCon; @@ -8441,7 +8034,7 @@ void EntityList::ShowSpawnWindow(Client* client, int Distance, bool NamedOnly) { } WindowText += cur_entity->GetCleanName(); WindowText += "
"; - if(strlen(WindowText.c_str()) > 4000) { + if (strlen(WindowText.c_str()) > 4000) { WindowText += "

List truncated... too many mobs to display"; break; } @@ -8486,38 +8079,41 @@ void EntityList::ScanCloseClientMobs(std::unordered_map& close_mob LogAIScanCloseDetail("Close Client Mob List Size [{}] for mob [{}]", close_mobs.size(), scanning_mob->GetCleanName()); } -uint8 Bot::GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets) { - uint8 needHealed = 0; - Group *g = nullptr; - if(HasGroup()) { - g = GetGroup(); - if(g) { - for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(g->members[i] && !g->members[i]->qglobal) { - if(g->members[i]->GetHPRatio() <= hpr) - needHealed++; +uint8 Bot::GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets, Raid* raid) { - if(includePets) { - if(g->members[i]->GetPet() && g->members[i]->GetPet()->GetHPRatio() <= hpr) - needHealed++; + uint8 need_healed = 0; + if (HasGroup()) { + + auto group_members = GetGroup(); + if (group_members) { + + for (auto member : group_members->members) { + if (member && !member->qglobal) { + + if (member->GetHPRatio() <= hpr) { + need_healed++; + } + + if (includePets && member->GetPet() && member->GetPet()->GetHPRatio() <= hpr) { + need_healed++; } } } } } - return needHealed; + return GetNumberNeedingHealedInRaidGroup(need_healed, hpr, includePets, raid); } int Bot::GetRawACNoShield(int &shield_ac) { int ac = itembonuses.AC + spellbonuses.AC; shield_ac = 0; EQ::ItemInstance* inst = GetBotItem(EQ::invslot::slotSecondary); - if(inst) { + if (inst) { if (inst->GetItem()->ItemType == EQ::item::ItemTypeShield) { ac -= inst->GetItem()->AC; shield_ac = inst->GetItem()->AC; for (uint8 i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) { - if(inst->GetAugment(i)) { + if (inst->GetAugment(i)) { ac -= inst->GetAugment(i)->GetItem()->AC; shield_ac += inst->GetAugment(i)->GetItem()->AC; } @@ -8533,7 +8129,7 @@ uint32 Bot::CalcCurrentWeight() { uint32 Total = 0; for (int i = EQ::invslot::EQUIPMENT_BEGIN; i <= EQ::invslot::EQUIPMENT_END; ++i) { inst = GetBotItem(i); - if(inst) { + if (inst) { TempItem = inst->GetItem(); if (TempItem) Total += TempItem->Weight; @@ -8550,7 +8146,7 @@ uint32 Bot::CalcCurrentWeight() { int Bot::GroupLeadershipAAHealthEnhancement() { Group *g = GetGroup(); - if(!g || (g->GroupCount() < 3)) + if (!g || (g->GroupCount() < 3)) return 0; switch(g->GetLeadershipAA(groupAAHealthEnhancement)) { @@ -8568,7 +8164,7 @@ int Bot::GroupLeadershipAAHealthEnhancement() { int Bot::GroupLeadershipAAManaEnhancement() { Group *g = GetGroup(); - if(!g || (g->GroupCount() < 3)) + if (!g || (g->GroupCount() < 3)) return 0; switch(g->GetLeadershipAA(groupAAManaEnhancement)) { @@ -8586,7 +8182,7 @@ int Bot::GroupLeadershipAAManaEnhancement() { int Bot::GroupLeadershipAAHealthRegeneration() { Group *g = GetGroup(); - if(!g || (g->GroupCount() < 3)) + if (!g || (g->GroupCount() < 3)) return 0; switch(g->GetLeadershipAA(groupAAHealthRegeneration)) { @@ -8606,7 +8202,7 @@ int Bot::GroupLeadershipAAHealthRegeneration() { int Bot::GroupLeadershipAAOffenseEnhancement() { Group *g = GetGroup(); - if(!g || (g->GroupCount() < 3)) + if (!g || (g->GroupCount() < 3)) return 0; switch(g->GetLeadershipAA(groupAAOffenseEnhancement)) { @@ -8628,16 +8224,16 @@ int Bot::GroupLeadershipAAOffenseEnhancement() { bool Bot::GetNeedsCured(Mob *tar) { bool needCured = false; - if(tar) { - if(tar->FindType(SE_PoisonCounter) || tar->FindType(SE_DiseaseCounter) || tar->FindType(SE_CurseCounter) || tar->FindType(SE_CorruptionCounter)) { + if (tar) { + if (tar->FindType(SE_PoisonCounter) || tar->FindType(SE_DiseaseCounter) || tar->FindType(SE_CurseCounter) || tar->FindType(SE_CorruptionCounter)) { uint32 buff_count = tar->GetMaxTotalSlots(); int buffsWithCounters = 0; needCured = true; for (unsigned int j = 0; j < buff_count; j++) { - if(tar->GetBuffs()[j].spellid != SPELL_UNKNOWN) { - if(CalculateCounters(tar->GetBuffs()[j].spellid) > 0) { + if (IsValidSpell(tar->GetBuffs()[j].spellid)) { + if (CalculateCounters(tar->GetBuffs()[j].spellid) > 0) { buffsWithCounters++; - if(buffsWithCounters == 1 && (tar->GetBuffs()[j].ticsremaining < 2 || (int32)((tar->GetBuffs()[j].ticsremaining * 6) / tar->GetBuffs()[j].counters) < 2)) { + if (buffsWithCounters == 1 && (tar->GetBuffs()[j].ticsremaining < 2 || (int32)((tar->GetBuffs()[j].ticsremaining * 6) / tar->GetBuffs()[j].counters) < 2)) { needCured = false; break; } @@ -8688,15 +8284,15 @@ bool Bot::GetNeedsHateRedux(Mob *tar) { bool Bot::HasOrMayGetAggro() { bool mayGetAggro = false; - if(GetTarget() && GetTarget()->GetHateTop()) { + if (GetTarget() && GetTarget()->GetHateTop()) { Mob *topHate = GetTarget()->GetHateTop(); - if(topHate == this) + if (topHate == this) mayGetAggro = true; else { uint32 myHateAmt = GetTarget()->GetHateAmount(this); uint32 topHateAmt = GetTarget()->GetHateAmount(topHate); - if(myHateAmt > 0 && topHateAmt > 0 && (uint8)((myHateAmt / topHateAmt) * 100) > 90) + if (myHateAmt > 0 && topHateAmt > 0 && (uint8)((myHateAmt / topHateAmt) * 100) > 90) mayGetAggro = true; } } @@ -8708,7 +8304,6 @@ void Bot::SetDefaultBotStance() { if (GetClass() == WARRIOR) defaultStance = EQ::constants::stanceAggressive; - _baseBotStance = EQ::constants::stancePassive; _botStance = defaultStance; } @@ -8718,34 +8313,34 @@ void Bot::BotGroupSay(Mob *speaker, const char *msg, ...) { va_start(ap, msg); vsnprintf(buf, 1000, msg, ap); va_end(ap); - if(speaker->HasGroup()) { + if (speaker->HasGroup()) { Group *g = speaker->GetGroup(); - if(g) + if (g) g->GroupMessage(speaker->CastToMob(), 0, 100, buf); } else speaker->Say("%s", buf); } bool Bot::UseDiscipline(uint32 spell_id, uint32 target) { - if(!IsValidSpell(spell_id)) { + if (!IsValidSpell(spell_id)) { BotGroupSay(this, "Not a valid spell."); return false; } const SPDat_Spell_Struct &spell = spells[spell_id]; uint8 level_to_use = spell.classes[GetClass() - 1]; - if(level_to_use == 255 || level_to_use > GetLevel()) { + if (level_to_use == 255 || level_to_use > GetLevel()) { return false; } - if(GetEndurance() > spell.endurance_cost) + if (GetEndurance() > spell.endurance_cost) SetEndurance(GetEndurance() - spell.endurance_cost); else return false; - if(spell.recast_time > 0) { - if(CheckDisciplineRecastTimers(this, spells[spell_id].timer_id)) { - if(spells[spell_id].timer_id > 0 && spells[spell_id].timer_id < MAX_DISCIPLINE_TIMERS) + if (spell.recast_time > 0) { + if (CheckDisciplineRecastTimers(this, spells[spell_id].timer_id)) { + if (spells[spell_id].timer_id > 0 && spells[spell_id].timer_id < MAX_DISCIPLINE_TIMERS) SetDisciplineRecastTimer(spells[spell_id].timer_id, spell.recast_time); } else { uint32 remaining_time = (GetDisciplineRemainingTime(this, spells[spell_id].timer_id) / 1000); @@ -8761,7 +8356,7 @@ bool Bot::UseDiscipline(uint32 spell_id, uint32 target) { } } - if(IsCasting()) + if (IsCasting()) InterruptSpell(); CastSpell(spell_id, target, EQ::spells::CastingSlot::Discipline); @@ -8988,23 +8583,7 @@ std::string Bot::CreateSayLink(Client* c, const char* message, const char* name) return saylink; } -void Bot::StopMoving() -{ - //SetCombatJitterFlag(false); - //m_combat_jitter_timer.Start(zone->random.Int(BOT_COMBAT_JITTER_INTERVAL_MIN, BOT_COMBAT_JITTER_INTERVAL_MAX)); - - Mob::StopMoving(); -} - -void Bot::StopMoving(float new_heading) -{ - //SetCombatJitterFlag(false); - //m_combat_jitter_timer.Start(zone->random.Int(BOT_COMBAT_JITTER_INTERVAL_MIN, BOT_COMBAT_JITTER_INTERVAL_MAX)); - - Mob::StopMoving(new_heading); -} - -void Bot::SpawnBotGroupByName(Client* c, std::string botgroup_name, uint32 leader_id) +void Bot::SpawnBotGroupByName(Client* c, const std::string& botgroup_name, uint32 leader_id) { auto leader = Bot::LoadBot(leader_id); if (!leader) { @@ -9153,17 +8732,21 @@ void Bot::SpawnBotGroupByName(Client* c, std::string botgroup_name, uint32 leade void Bot::Signal(int signal_id) { - const auto export_string = fmt::format("{}", signal_id); - parse->EventBot(EVENT_SIGNAL, this, nullptr, export_string, 0); + if (parse->BotHasQuestSub(EVENT_SIGNAL)) { + parse->EventBot(EVENT_SIGNAL, this, nullptr, std::to_string(signal_id), 0); + } } void Bot::SendPayload(int payload_id, std::string payload_value) { - const auto export_string = fmt::format("{} {}", payload_id, payload_value); - parse->EventBot(EVENT_PAYLOAD, this, nullptr, export_string, 0); + if (parse->BotHasQuestSub(EVENT_PAYLOAD)) { + const auto& export_string = fmt::format("{} {}", payload_id, payload_value); + + parse->EventBot(EVENT_PAYLOAD, this, nullptr, export_string, 0); + } } -void Bot::OwnerMessage(std::string message) +void Bot::OwnerMessage(const std::string& message) { if (!GetBotOwner() || !GetBotOwner()->IsClient()) { return; @@ -9234,7 +8817,7 @@ bool Bot::GetBotDataBuckets() return true; } -bool Bot::CheckDataBucket(std::string bucket_name, std::string bucket_value, uint8 bucket_comparison) +bool Bot::CheckDataBucket(const std::string& bucket_name, const std::string& bucket_value, uint8 bucket_comparison) { if (!bucket_name.empty() && !bucket_value.empty()) { auto full_name = fmt::format( @@ -9404,7 +8987,7 @@ void Bot::ListBotSpells(uint8 min_level) auto spell_count = 0; auto spell_number = 1; - for (const auto& s : (AIBot_spells.size() > AIBot_spells_enforced.size()) ? AIBot_spells : AIBot_spells_enforced) { + for (const auto& s : (GetBotEnforceSpellSetting()) ? AIBot_spells_enforced : AIBot_spells) { auto b = bot_spell_settings.find(s.spellid); if (b == bot_spell_settings.end() && s.minlevel >= min_level) { bot_owner->Message( @@ -9588,7 +9171,7 @@ std::vector Bot::GetApplySpellList( if (apply_type == ApplySpellType::Raid && IsRaidGrouped()) { auto* r = GetRaid(); - auto group_id = r->GetGroup(this->GetCleanName()); + auto group_id = r->GetGroup(GetCleanName()); if (r && EQ::ValueWithin(group_id, 0, (MAX_RAID_GROUPS - 1))) { for (auto i = 0; i < MAX_RAID_MEMBERS; i++) { auto* m = r->members[i].member; @@ -9744,4 +9327,58 @@ void Bot::SendSpellAnim(uint16 target_id, uint16 spell_id) entity_list.QueueCloseClients(this, &app, false, RuleI(Range, SpellParticles)); } +float Bot::GetBotCasterMaxRange(float melee_distance_max) {// Calculate caster distances + float caster_distance_max = 0.0f; + float caster_distance_min = 0.0f; + float caster_distance = 0.0f; + + caster_distance_max = GetBotCasterRange() * GetBotCasterRange(); + if (!GetBotCasterRange() && GetLevel() >= GetStopMeleeLevel() && GetClass() >= WARRIOR && GetClass() <= BERSERKER) { + caster_distance_max = MAX_CASTER_DISTANCE[GetClass() - 1]; + } + if (caster_distance_max) { + caster_distance_min = melee_distance_max; + if (caster_distance_max <= caster_distance_min) { + caster_distance_max = caster_distance_min * 1.25f; + } + } + return caster_distance_max; +} + +bool Bot::CheckSpawnConditions(Client* c) { + + if (c->GetFeigned()) { + c->Message(Chat::White, "You cannot spawn a bot-group while feigned."); + return false; + } + + auto* owner_group = c->GetGroup(); + if (owner_group) { + std::list member_list; + owner_group->GetClientList(member_list); + member_list.remove(nullptr); + + for (auto member_iter : member_list) { + if (member_iter->IsEngaged() || member_iter->GetAggroCount() > 0) { + c->Message(Chat::White, "You cannot spawn bots while your group is engaged,"); + return false; + } + } + } else { + if (c->GetAggroCount() > 0) { + c->Message(Chat::White, "You cannot spawn bots while you are engaged,"); + return false; + } + } + + Raid* raid = entity_list.GetRaidByClient(c); + if (raid && raid->IsEngaged()) { + c->Message(Chat::White, "You cannot spawn bots while your raid is engaged."); + return false; + } + + return true; +} + + uint8 Bot::spell_casting_chances[SPELL_TYPE_COUNT][PLAYER_CLASS_COUNT][EQ::constants::STANCE_TYPE_COUNT][cntHSND] = { 0 }; diff --git a/zone/bot.h b/zone/bot.h index 3dffea1a1..f383304ce 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -33,6 +33,7 @@ #include "../common/global_define.h" #include "guild_mgr.h" #include "worldserver.h" +#include "raids.h" #include @@ -42,9 +43,6 @@ constexpr uint32 BOT_FOLLOW_DISTANCE_WALK = 1000; // as DSq value (~31.623 units constexpr uint32 BOT_KEEP_ALIVE_INTERVAL = 5000; // 5 seconds -//constexpr uint32 BOT_COMBAT_JITTER_INTERVAL_MIN = 5000; // 5 seconds -//constexpr uint32 BOT_COMBAT_JITTER_INTERVAL_MAX = 20000; // 20 seconds - extern WorldServer worldserver; constexpr int BotAISpellRange = 100; // TODO: Write a method that calcs what the bot's spell range is based on spell, equipment, AA, whatever and replace this @@ -53,8 +51,6 @@ constexpr int MaxDisciplineTimer = 10; constexpr int DisciplineReuseStart = MaxSpellTimer + 1; constexpr int MaxTimer = MaxSpellTimer + MaxDisciplineTimer; - - // nHSND negative Healer/Slower/Nuker/Doter // pH positive Healer // pS positive Slower @@ -103,12 +99,6 @@ public: BotTradeClientNoDropNoTrade }; - enum BotRoleType { - BotRoleMainAssist, - BotRoleGroupHealer, - BotRoleRaidHealer - }; - enum SpellTypeIndex : uint32 { spellTypeIndexNuke, spellTypeIndexHeal, @@ -147,13 +137,13 @@ public: void Damage(Mob* from, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None) override; - bool HasRaid() override { return (GetRaid() ? true : false); } - bool HasGroup() override { return (GetGroup() ? true : false); } - Raid* GetRaid() override { return entity_list.GetRaidByMob(this); } - Group* GetGroup() override { return entity_list.GetGroupByMob(this); } + bool HasRaid() final { return GetRaid() != nullptr; } + bool HasGroup() final { return GetGroup() != nullptr; } + Raid* GetRaid() final { return entity_list.GetRaidByBot(this); } + Group* GetGroup() final { return entity_list.GetGroupByMob(this); } // Common, but informal "interfaces" with Client object - uint32 CharacterID() { return GetBotID(); } // Just returns the Bot Id + uint32 CharacterID() const { return GetBotID(); } inline bool IsInAGuild() const { return (_guildId != GUILD_NONE && _guildId != 0); } inline bool IsInGuild(uint32 in_gid) const { return (in_gid == _guildId && IsInAGuild()); } inline uint32 GuildID() const { return _guildId; } @@ -179,20 +169,19 @@ public: int GetHandToHandDamage(void) override; bool TryFinishingBlow(Mob *defender, int64 &damage) override; void DoRiposte(Mob* defender) override; - inline int32 GetATK() const override { return ATK + itembonuses.ATK + spellbonuses.ATK + ((GetSTR() + GetSkill(EQ::skills::SkillOffense)) * 9 / 10); } + inline int32 GetATK() { return ATK + itembonuses.ATK + spellbonuses.ATK + ((GetSTR() + GetSkill(EQ::skills::SkillOffense)) * 9 / 10); } inline int32 GetATKBonus() const override { return itembonuses.ATK + spellbonuses.ATK; } uint32 GetTotalATK(); uint32 GetATKRating(); uint16 GetPrimarySkillValue(); uint16 MaxSkill(EQ::skills::SkillType skillid, uint16 class_, uint16 level) const; - inline uint16 MaxSkill(EQ::skills::SkillType skillid) const { return MaxSkill(skillid, GetClass(), GetLevel()); } + inline uint16 MaxSkill(EQ::skills::SkillType skillid) { return MaxSkill(skillid, GetClass(), GetLevel()); } int GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target = nullptr) override; void DoSpecialAttackDamage(Mob *who, EQ::skills::SkillType skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool HitChance = false); void TryBackstab(Mob *other,int ReuseTime = 10) override; void RogueBackstab(Mob* other, bool min_damage = false, int ReuseTime = 10) override; void RogueAssassinate(Mob* other) override; void DoClassAttacks(Mob *target, bool IsRiposte=false); - bool CanDoSpecialAttack(Mob *other); void CalcBonuses() override; void CalcItemBonuses(StatBonuses* newbon); void AddItemBonuses(const EQ::ItemInstance *inst, StatBonuses* newbon, bool isAug = false, bool isTribute = false, int rec_override = 0); @@ -203,7 +192,7 @@ public: bool IsNPC() const override { return false; } Mob* GetOwner() override; Mob* GetOwnerOrSelf() override; - inline bool HasOwner() override { return (GetBotOwner() ? true : false); } + inline bool HasOwner() override { return GetBotOwner() != nullptr; } int64 CalcMaxMana() override; void SetAttackTimer() override; uint64 GetClassHPFactor(); @@ -219,38 +208,37 @@ public: void ChangeBotArcherWeapons(bool isArcher); void Sit(); void Stand(); - bool IsSitting(); + bool IsSitting() const override; bool IsStanding(); - int GetWalkspeed() const override { return (int)((float)_GetWalkSpeed() * 1.785714285f); } // 1.25 / 0.7 = 1.7857142857142857142857142857143 - int GetRunspeed() const override { return (int)((float)_GetRunSpeed() * 1.785714285f); } + int GetWalkspeed() { return (int)((float)_GetWalkSpeed() * 1.785714285f); } // 1.25 / 0.7 = 1.7857142857142857142857142857143 + int GetRunspeed() { return (int)((float)_GetRunSpeed() * 1.785714285f); } void WalkTo(float x, float y, float z) override; void RunTo(float x, float y, float z) override; - void StopMoving() override; - void StopMoving(float new_heading) override; - //bool GetCombatJitterFlag() { return m_combat_jitter_flag; } - bool GetGuardFlag() { return m_guard_flag; } + + bool GetGuardFlag() const { return m_guard_flag; } void SetGuardFlag(bool flag = true) { m_guard_flag = flag; } - bool GetHoldFlag() { return m_hold_flag; } + bool GetHoldFlag() const { return m_hold_flag; } void SetHoldFlag(bool flag = true) { m_hold_flag = flag; } - bool GetAttackFlag() { return m_attack_flag; } + bool GetAttackFlag() const { return m_attack_flag; } void SetAttackFlag(bool flag = true) { m_attack_flag = flag; } - bool GetAttackingFlag() { return m_attacking_flag; } - bool GetPullFlag() { return m_pull_flag; } + bool GetAttackingFlag() const { return m_attacking_flag; } + bool GetPullFlag() const { return m_pull_flag; } void SetPullFlag(bool flag = true) { m_pull_flag = flag; } - bool GetPullingFlag() { return m_pulling_flag; } - bool GetReturningFlag() { return m_returning_flag; } + bool GetPullingFlag() const { return m_pulling_flag; } + bool GetReturningFlag() const { return m_returning_flag; } bool UseDiscipline(uint32 spell_id, uint32 target); - uint8 GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets); + uint8 GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets, Raid* raid); + uint8 GetNumberNeedingHealedInRaidGroup(uint8& need_healed, uint8 hpr, bool includePets, Raid* raid); bool GetNeedsCured(Mob *tar); bool GetNeedsHateRedux(Mob *tar); bool HasOrMayGetAggro(); void SetDefaultBotStance(); - void SetSurname(std::string bot_surname); - void SetTitle(std::string bot_title); - void SetSuffix(std::string bot_suffix); - std::string GetSurname() { return _surname; } - std::string GetTitle() { return _title; } - std::string GetSuffix() { return _suffix; } + void SetSurname(std::string_view bot_surname); + void SetTitle(std::string_view bot_title); + void SetSuffix(std::string_view bot_suffix); + std::string GetSurname() const { return _surname; } + std::string GetTitle() const { return _title; } + std::string GetSuffix() const { return _suffix; } inline virtual int32 GetMaxStat(); inline virtual int32 GetMaxResist(); inline virtual int32 GetMaxSTR(); @@ -288,19 +276,18 @@ public: uint32 CalcCurrentWeight(); int GroupLeadershipAAHealthEnhancement(); int GroupLeadershipAAManaEnhancement(); - int GroupLeadershipAAHealthRegeneration(); + int GroupLeadershipAAHealthRegeneration(); int GroupLeadershipAAOffenseEnhancement(); void CalcRestState(); - int64 CalcMaxEndurance(); //This calculates the maximum endurance we can have - int64 CalcBaseEndurance(); //Calculates Base End - int64 CalcEnduranceRegen(); //Calculates endurance regen used in DoEnduranceRegen() - int64 GetEndurance() const {return cur_end;} //This gets our current endurance - int64 GetMaxEndurance() const {return max_end;} //This gets our endurance from the last CalcMaxEndurance() call - int64 CalcEnduranceRegenCap(); - inline uint8 GetEndurancePercent() { return (uint8)((float)cur_end / (float)max_end * 100.0f); } - void SetEndurance(int32 newEnd); //This sets the current endurance to the new value - void DoEnduranceRegen(); //This Regenerates endurance - void DoEnduranceUpkeep(); //does the endurance upkeep + int64 CalcMaxEndurance(); + int64 CalcBaseEndurance(); + int64 CalcEnduranceRegen(); + int64 GetEndurance() const override {return cur_end;} + int64 GetMaxEndurance() const override {return max_end;} + int64 CalcEnduranceRegenCap(); + inline uint8 GetEndurancePercent() override { return (uint8)((float)cur_end / (float)max_end * 100.0f); } + void SetEndurance(int32 newEnd) override; + void DoEnduranceUpkeep(); bool AI_AddBotSpells(uint32 bot_spell_id); void AddSpellToBotList( @@ -336,26 +323,29 @@ public: ); void AI_Bot_Event_SpellCastFinished(bool iCastSucceeded, uint16 slot); + // AI Methods bool AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes); bool AI_EngagedCastCheck() override; bool AI_PursueCastCheck() override; bool AI_IdleCastCheck() override; bool AIHealRotation(Mob* tar, bool useFastHeals); - bool GetPauseAI() { return _pauseAI; } + bool GetPauseAI() const { return _pauseAI; } void SetPauseAI(bool pause_flag) { _pauseAI = pause_flag; } - uint8 GetStopMeleeLevel() { return _stopMeleeLevel; } + uint8 GetStopMeleeLevel() const { return _stopMeleeLevel; } void SetStopMeleeLevel(uint8 level); void SetGuardMode(); void SetHoldMode(); + uint32 GetBotCasterRange() const { return m_bot_caster_range; } + bool IsValidSpellRange(uint16 spell_id, Mob const* tar); // Bot AI Methods void AI_Bot_Init(); void AI_Bot_Start(uint32 iMoveDelay = 0); // Mob AI Virtual Override Methods - void AI_Process() override; - void AI_Stop() override; + void AI_Process() final; + void AI_Stop() final; // Mob Spell Virtual Override Methods void SpellProcess() override; @@ -365,53 +355,79 @@ public: void DoBuffTic(const Buffs_Struct &buff, int slot, Mob* caster = nullptr) override; virtual bool CastSpell(uint16 spell_id, uint16 target_id, EQ::spells::CastingSlot slot = EQ::spells::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, int16 *resist_adjust = nullptr, uint32 aa_id = 0); - virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar); + bool SpellOnTarget( + uint16 spell_id, + Mob* spelltar, + int reflect_effectiveness = 0, + bool use_resist_adjust = false, + int16 resist_adjust = 0, + bool isproc = false, + int level_override = -1, + int duration_override = 0, + bool disable_buff_overwrite = false + ) final; bool IsImmuneToSpell(uint16 spell_id, Mob *caster) override; virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, EQ::spells::CastingSlot slot); virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, EQ::spells::CastingSlot slot = EQ::spells::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1, - uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, uint32 aa_id = 0); + uint32* oSpellWillFinish = nullptr, uint32 item_slot = 0xFFFFFFFF, uint32 aa_id = 0); inline int64 GetFocusEffect(focusType type, uint16 spell_id, Mob *caster = nullptr, bool from_buff_tic = false) override { return Mob::GetFocusEffect(type, spell_id, caster, from_buff_tic); } inline bool Attack(Mob* other, int Hand = EQ::invslot::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) override { return Mob::Attack(other, Hand, FromRiposte, IsStrikethrough, IsFromSpell, opts); } + [[nodiscard]] int GetMaxBuffSlots() const final { return EQ::spells::LONG_BUFFS; } + [[nodiscard]] int GetMaxSongSlots() const final { return EQ::spells::SHORT_BUFFS; } + [[nodiscard]] int GetMaxDiscSlots() const final { return EQ::spells::DISC_BUFFS; } + [[nodiscard]] int GetMaxTotalSlots() const final { return EQ::spells::TOTAL_BUFFS; } + bool GetBotOwnerDataBuckets(); bool GetBotDataBuckets(); - bool CheckDataBucket(std::string bucket_name, std::string bucket_value, uint8 bucket_comparison); + bool CheckDataBucket(const std::string& bucket_name, const std::string& bucket_value, uint8 bucket_comparison); // Bot Equipment & Inventory Class Methods void BotTradeAddItem(const EQ::ItemInstance* inst, uint16 slot_id, std::string* error_message, bool save_to_database = true); void EquipBot(std::string* error_message); bool CheckLoreConflict(const EQ::ItemData* item); - void UpdateEquipmentLight() override { m_Light.Type[EQ::lightsource::LightEquipment] = m_inv.FindBrightestLightType(); m_Light.Level[EQ::lightsource::LightEquipment] = EQ::lightsource::TypeToLevel(m_Light.Type[EQ::lightsource::LightEquipment]); } - inline EQ::InventoryProfile& GetInv() { return m_inv; } + void UpdateEquipmentLight() override + { + m_Light.Type[EQ::lightsource::LightEquipment] = m_inv.FindBrightestLightType(); + m_Light.Level[EQ::lightsource::LightEquipment] = EQ::lightsource::TypeToLevel(m_Light.Type[EQ::lightsource::LightEquipment]); + } + + inline EQ::InventoryProfile& GetInv() override { return m_inv; } // Static Class Methods - //static void DestroyBotRaidObjects(Client* client); // Can be removed after bot raids are dumped static Bot* LoadBot(uint32 botID); static uint32 SpawnedBotCount(const uint32 owner_id, uint8 class_id = NO_CLASS); static void LevelBotWithClient(Client* client, uint8 level, bool sendlvlapp); - //static bool SetBotOwnerCharacterID(uint32 botID, uint32 botOwnerCharacterID, std::string* error_message); + static bool IsBotAttackAllowed(Mob* attacker, Mob* target, bool& hasRuleDefined); - static Bot* GetBotByBotClientOwnerAndBotName(Client* c, std::string botName); - static void ProcessBotGroupInvite(Client* c, std::string botName); - static void ProcessBotGroupDisband(Client* c, std::string botName); + static Bot* GetBotByBotClientOwnerAndBotName(Client* c, const std::string& botName); + static void ProcessBotGroupInvite(Client* c, std::string const& botName); + static void ProcessBotGroupDisband(Client* c, const std::string& botName); static void BotOrderCampAll(Client* c, uint8 class_id = NO_CLASS); static void ProcessBotInspectionRequest(Bot* inspectedBot, Client* client); static void LoadAndSpawnAllZonedBots(Client* bot_owner); static bool GroupHasBot(Group* group); static Bot* GetFirstBotInGroup(Group* group); static void ProcessClientZoneChange(Client* botOwner); - static void ProcessBotOwnerRefDelete(Mob* botOwner); // Removes a Client* reference when the Client object is destroyed - static void ProcessGuildInvite(Client* guildOfficer, Bot* botToGuild); // Processes a client's request to guild a bot - static bool ProcessGuildRemoval(Client* guildOfficer, std::string botName); // Processes a client's request to deguild a bot + static void ProcessBotOwnerRefDelete(Mob* botOwner); // Removes a Client* reference when the Client object is destroyed static int32 GetSpellRecastTimer(Bot *caster, int timer_index); static bool CheckSpellRecastTimers(Bot *caster, int SpellIndex); static int32 GetDisciplineRecastTimer(Bot *caster, int timer_index); static bool CheckDisciplineRecastTimers(Bot *caster, int timer_index); static uint32 GetDisciplineRemainingTime(Bot *caster, int timer_index); + //Raid methods + static void ProcessRaidInvite(Mob* invitee, Client* invitor, bool group_invite = false); + static void RemoveBotFromRaid(Bot* bot); + inline void SetDirtyAutoHaters() { m_dirtyautohaters = true; } + static void CreateBotRaid(Mob* invitee, Client* invitor, bool group_invite, Raid* raid); + static void + ProcessBotGroupAdd(Group* group, Raid* raid, Client* client = nullptr, bool new_raid = false, bool initial = false); + + static std::list GetBotSpellsForSpellEffect(Bot* botCaster, int spellEffect); static std::list GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster, int spellEffect, SpellTargetType targetType); static std::list GetBotSpellsBySpellType(Bot* botCaster, uint32 spellType); @@ -441,8 +457,8 @@ public: static BotSpell GetBestBotSpellForResistDebuff(Bot* botCaster, Mob* target); static NPCType *CreateDefaultNPCTypeStructForBot( - std::string botName, - std::string botLastName, + const std::string& botName, + const std::string& botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, @@ -456,8 +472,8 @@ public: // "GET" Class Methods uint32 GetBotID() const { return _botID; } - uint32 GetBotOwnerCharacterID() { return _botOwnerCharacterID; } - uint32 GetBotSpellID() { return npc_spells_id; } + uint32 GetBotOwnerCharacterID() const { return _botOwnerCharacterID; } + uint32 GetBotSpellID() const { return npc_spells_id; } Mob* GetBotOwner() { return this->_botOwner; } uint32 GetBotArcheryRange(); EQ::ItemInstance* GetBotItem(uint16 slot_id); @@ -467,24 +483,20 @@ public: bool IsBotArcher() { return m_bot_archery_setting; } bool IsBotCharmer() { return _botCharmer; } bool IsBot() const override { return true; } + bool IsOfClientBot() const override { return true; } + bool IsOfClientBotMerc() const override { return true; } + bool GetRangerAutoWeaponSelect() { return _rangerAutoWeaponSelect; } - BotRoleType GetBotRole() { return _botRole; } EQ::constants::StanceType GetBotStance() { return _botStance; } uint8 GetChanceToCastBySpellType(uint32 spellType); bool GetBotEnforceSpellSetting() { return m_enforce_spell_settings; } - - bool IsGroupHealer() { return m_CastingRoles.GroupHealer; } - bool IsGroupSlower() { return m_CastingRoles.GroupSlower; } - bool IsGroupNuker() { return m_CastingRoles.GroupNuker; } - bool IsGroupDoter() { return m_CastingRoles.GroupDoter; } + float GetBotCasterMaxRange(float melee_distance_max); + bool IsGroupHealer() const { return m_CastingRoles.GroupHealer; } + bool IsGroupSlower() const { return m_CastingRoles.GroupSlower; } + bool IsGroupNuker() const { return m_CastingRoles.GroupNuker; } + bool IsGroupDoter() const { return m_CastingRoles.GroupDoter; } static void UpdateGroupCastingRoles(const Group* group, bool disband = false); - //bool IsRaidHealer() { return m_CastingRoles.RaidHealer; } - //bool IsRaidSlower() { return m_CastingRoles.RaidSlower; } - //bool IsRaidNuker() { return m_CastingRoles.RaidNuker; } - //bool IsRaidDoter() { return m_CastingRoles.RaidDoter; } - //static void UpdateRaidCastingRoles(const Raid* raid, bool disband = false); - bool IsBotCaster() { return IsCasterClass(GetClass()); } bool IsBotHybrid() { return IsHybridClass(GetClass()); } bool IsBotINTCaster() { return IsINTCasterClass(GetClass()); } @@ -493,7 +505,6 @@ public: bool IsBotFighter() { return IsFighterClass(GetClass()); } bool IsBotNonSpellFighter() { return IsNonSpellFighterClass(GetClass()); } uint8 GetBotClass() { return GetClass(); } - bool CanHeal(); int GetRawACNoShield(int &shield_ac); // new heal rotation code @@ -519,8 +530,8 @@ public: std::shared_ptr* MemberOfHealRotation() { return &m_member_of_heal_rotation; } - bool GetAltOutOfCombatBehavior() { return _altoutofcombatbehavior;} - bool GetShowHelm() { return _showhelm; } + bool GetAltOutOfCombatBehavior() const { return _altoutofcombatbehavior;} + bool GetShowHelm() const { return _showhelm; } inline int32 GetSTR() const override { return STR; } inline int32 GetSTA() const override { return STA; } inline int32 GetDEX() const override { return DEX; } @@ -596,15 +607,14 @@ public: void SetBotCharmer(bool c) { _botCharmer = c; } void SetPetChooser(bool p) { _petChooser = p; } void SetBotOwner(Mob* botOwner) { this->_botOwner = botOwner; } - // void SetBotOwnerCharacterID(uint32 botOwnerCharacterID) { _botOwnerCharacterID = botOwnerCharacterID; } void SetRangerAutoWeaponSelect(bool enable) { GetClass() == RANGER ? _rangerAutoWeaponSelect = enable : _rangerAutoWeaponSelect = false; } - void SetBotRole(BotRoleType botRole) { _botRole = botRole; } void SetBotStance(EQ::constants::StanceType botStance) { if (botStance >= EQ::constants::stancePassive && botStance <= EQ::constants::stanceBurnAE) _botStance = botStance; else _botStance = EQ::constants::stancePassive; } + void SetBotCasterRange(uint32 bot_caster_range) { m_bot_caster_range = bot_caster_range; } void SetSpellRecastTimer(int timer_index, int32 recast_delay); void SetDisciplineRecastTimer(int timer_index, int32 recast_delay); void SetAltOutOfCombatBehavior(bool behavior_flag) { _altoutofcombatbehavior = behavior_flag;} @@ -637,7 +647,7 @@ public: void SetBotEnforceSpellSetting(bool enforcespellsettings, bool save = false); bool GetBotEnforceSpellSetting() const { return m_enforce_spell_settings; } - static void SpawnBotGroupByName(Client* c, std::string botgroup_name, uint32 leader_id); + static void SpawnBotGroupByName(Client* c, const std::string& botgroup_name, uint32 leader_id); std::string CreateSayLink(Client* botOwner, const char* message, const char* name); @@ -650,8 +660,8 @@ public: // Publicized private functions static NPCType *FillNPCTypeStruct( uint32 botSpellsID, - std::string botName, - std::string botLastName, + const std::string& botName, + const std::string& botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, @@ -702,50 +712,123 @@ public: uint32 CountBotItem(uint32 item_id); std::map GetBotItemSlots(); uint32 GetBotItemBySlot(uint16 slot_id); - bool HasBotItem(uint32 item_id); + int16 HasBotItem(uint32 item_id); void RemoveBotItem(uint32 item_id); uint32 GetTotalPlayTime(); // New accessors for BotDatabase access bool DeleteBot(); uint32* GetTimers() { return timers; } - uint32 GetLastZoneID() { return _lastZoneId; } - int32 GetBaseAC() { return _baseAC; } - int32 GetBaseATK() { return _baseATK; } - int32 GetBaseSTR() { return _baseSTR; } - int32 GetBaseSTA() { return _baseSTA; } - int32 GetBaseCHA() { return _baseCHA; } - int32 GetBaseDEX() { return _baseDEX; } - int32 GetBaseINT() { return _baseINT; } - int32 GetBaseAGI() { return _baseAGI; } - int32 GetBaseWIS() { return _baseWIS; } - int32 GetBaseFR() { return _baseFR; } - int32 GetBaseCR() { return _baseCR; } - int32 GetBaseMR() { return _baseMR; } - int32 GetBasePR() { return _basePR; } - int32 GetBaseDR() { return _baseDR; } - int32 GetBaseCorrup() { return _baseCorrup; } + uint32 GetLastZoneID() const { return _lastZoneId; } + int32 GetBaseAC() const { return _baseAC; } + int32 GetBaseATK() const { return _baseATK; } + int32 GetBaseSTR() const { return _baseSTR; } + int32 GetBaseSTA() const { return _baseSTA; } + int32 GetBaseCHA() const { return _baseCHA; } + int32 GetBaseDEX() const { return _baseDEX; } + int32 GetBaseINT() const { return _baseINT; } + int32 GetBaseAGI() const { return _baseAGI; } + int32 GetBaseWIS() const { return _baseWIS; } + int32 GetBaseFR() const { return _baseFR; } + int32 GetBaseCR() const { return _baseCR; } + int32 GetBaseMR() const { return _baseMR; } + int32 GetBasePR() const { return _basePR; } + int32 GetBaseDR() const { return _baseDR; } + int32 GetBaseCorrup() const { return _baseCorrup; } void Signal(int signal_id); void SendPayload(int payload_id, std::string payload_value = std::string()); - void OwnerMessage(std::string message); + void OwnerMessage(const std::string& message); + + //Raid additions + Raid* p_raid_instance; + + static uint8 spell_casting_chances[SPELL_TYPE_COUNT][PLAYER_CLASS_COUNT][EQ::constants::STANCE_TYPE_COUNT][cntHSND]; + + bool BotCastMez(Mob* tar, uint8 botLevel, bool checked_los, BotSpell& botSpell, Raid* raid); + bool BotCastHeal(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpell, Raid* raid); + bool BotCastRoot(Mob* tar, uint8 botLevel, uint32 iSpellTypes, BotSpell& botSpell, const bool& checked_los); + bool BotCastBuff(Mob* tar, uint8 botLevel, uint8 botClass); + bool BotCastEscape(Mob*& tar, uint8 botClass, BotSpell& botSpell, uint32 iSpellTypes); + bool BotCastNuke(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpell, const bool& checked_los); + bool BotCastDispel(Mob* tar, BotSpell& botSpell, uint32 iSpellTypes, const bool& checked_los); + bool BotCastPet(Mob* tar, uint8 botClass, BotSpell& botSpell); + bool BotCastCombatBuff(Mob* tar, uint8 botLevel, uint8 botClass); + bool BotCastLifetap(Mob* tar, uint8 botLevel, BotSpell& botSpell, const bool& checked_los, uint32 iSpellTypes); + bool BotCastSnare(Mob* tar, uint8 botLevel, BotSpell& botSpell, const bool& checked_los, uint32 iSpellTypes); + bool BotCastDOT(Mob* tar, uint8 botLevel, const BotSpell& botSpell, const bool& checked_los); + bool BotCastSlow(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpell, const bool& checked_los, Raid* raid); + bool BotCastDebuff(Mob* tar, uint8 botLevel, BotSpell& botSpell, bool checked_los); + bool BotCastCure(Mob* tar, uint8 botClass, BotSpell& botSpell, Raid* raid); + bool BotCastHateReduction(Mob* tar, uint8 botLevel, const BotSpell& botSpell); + bool BotCastCombatSong(Mob* tar, uint8 botLevel); + bool BotCastSong(Mob* tar, uint8 botLevel); + + bool CheckIfIncapacitated(); + bool IsAIProcessValid(const Client* bot_owner, const Group* bot_group, const Raid* raid); + + Client* SetLeashOwner(Client* bot_owner, Group* bot_group, Raid* raid, uint32 r_group) const; + Mob* SetFollowMob(Client* leash_owner); + + Mob* GetBotTarget(Client* bot_owner); + void AcquireBotTarget(Group* bot_group, Raid* raid, Client* leash_owner, float leash_distance); + void SetBotTarget(Client* bot_owner, Raid* raid, Group* bot_group, Client* leash_owner, float lo_distance, float leash_distance, bool bo_alt_combat); + void SetLeashOwnerTarget(Client* leash_owner, Client* bot_owner, float lo_distance, float leash_distance); + void SetOwnerTarget(Client* bot_owner); + void SetBotGroupTarget(const Client* bot_owner, Client* leash_owner, float lo_distance, float leash_distance, Mob* const& bg_member, Mob* bgm_target); + bool IsValidTarget(Client* bot_owner, Client* leash_owner, float lo_distance, float leash_distance, bool bo_alt_combat, Mob* tar, float tar_distance); + + bool PullingFlagChecks(Client* bot_owner); + bool ReturningFlagChecks(Client* bot_owner, float fm_distance); + void BotPullerProcess(Client* bot_owner, Raid* raid); + + + // Movement Methods + void CalcMeleeDistances( + const Mob* tar, + const EQ::ItemInstance* const& p_item, + const EQ::ItemInstance* const& s_item, + bool behind_mob, + bool backstab_weapon, + float& melee_distance_max, + float& melee_distance + ) const; + + // Combat Checks + void SetBerserkState(); + bool CheckIfCasting(float fm_distance); + void HealRotationChecks(); + void CheckCombatRange(Mob* tar, float tar_distance, bool& atCombatRange, const EQ::ItemInstance*& p_item, const EQ::ItemInstance*& s_item); + + // Try Combat Methods + bool TryEvade(Mob* tar); + bool TryFacingTarget(Mob* tar); + bool TryRangedAttack(Mob* tar); + bool TryClassAttacks(Mob* tar); + bool TryPrimaryWeaponAttacks(Mob* tar, const EQ::ItemInstance* p_item); + bool TrySecondaryWeaponAttacks(Mob* tar, const EQ::ItemInstance* s_item); + bool TryPursueTarget(float leash_distance, glm::vec3& Goal); + bool TryMeditate(); + bool TryAutoDefend(Client* bot_owner, float leash_distance); + bool TryIdleChecks(float fm_distance); + bool TryNonCombatMovementChecks(Client* bot_owner, const Mob* follow_mob, glm::vec3& Goal); + bool TryBardMovementCasts(); + void SetRangerCombatWeapon(bool atArcheryRange); + + // Public "Refactor" Methods + static bool CheckSpawnConditions(Client* c); protected: - void PetAIProcess(); void BotMeditate(bool isSitting); bool CheckBotDoubleAttack(bool Triple = false); void PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* client); - bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0) override; + bool AIDoSpellCast(int32 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = nullptr) override; BotCastingRoles& GetCastingRoles() { return m_CastingRoles; } void SetGroupHealer(bool flag = true) { m_CastingRoles.GroupHealer = flag; } void SetGroupSlower(bool flag = true) { m_CastingRoles.GroupSlower = flag; } void SetGroupNuker(bool flag = true) { m_CastingRoles.GroupNuker = flag; } void SetGroupDoter(bool flag = true) { m_CastingRoles.GroupDoter = flag; } - //void SetRaidHealer(bool flag = true) { m_CastingRoles.RaidHealer = flag; } - //void SetRaidSlower(bool flag = true) { m_CastingRoles.RaidSlower = flag; } - //void SetRaidNuker(bool flag = true) { m_CastingRoles.RaidNuker = flag; } - //void SetRaidDoter(bool flag = true) { m_CastingRoles.RaidDoter = flag; } std::deque bot_signal_q; std::vector AIBot_spells; @@ -757,7 +840,6 @@ private: uint32 _botOwnerCharacterID; bool _spawnStatus; Mob* _botOwner; - bool _botOrderAttack; bool m_bot_archery_setting; bool _botCharmer; bool _petChooser; @@ -766,7 +848,6 @@ private: EQ::InventoryProfile m_inv; double _lastTotalPlayTime; time_t _startTotalPlayTime; - Mob* _previousTarget; uint32 _guildId; uint8 _guildRank; std::string _guildName; @@ -775,9 +856,7 @@ private: std::string _suffix; uint32 _lastZoneId; bool _rangerAutoWeaponSelect; - BotRoleType _botRole; EQ::constants::StanceType _botStance; - EQ::constants::StanceType _baseBotStance; unsigned int RestRegenHP; unsigned int RestRegenMana; unsigned int RestRegenEndurance; @@ -792,8 +871,7 @@ private: Timer m_evade_timer; // can be moved to pTimers at some point Timer m_alt_combat_hate_timer; Timer m_auto_defend_timer; - //Timer m_combat_jitter_timer; - //bool m_combat_jitter_flag; + bool m_dirtyautohaters; bool m_guard_flag; bool m_hold_flag; bool m_attack_flag; @@ -802,7 +880,7 @@ private: bool m_pulling_flag; bool m_returning_flag; eStandingPetOrder m_previous_pet_order; - + uint32 m_bot_caster_range; BotCastingRoles m_CastingRoles; std::map bot_data_buckets; std::map bot_owner_data_buckets; @@ -811,7 +889,6 @@ private: std::shared_ptr m_member_of_heal_rotation; - std::map botAAs; InspectMessage_Struct _botInspectMessage; bool _altoutofcombatbehavior; bool _showhelm; @@ -841,15 +918,12 @@ private: // Class Methods void LoadAAs(); - int32 acmod(); void GenerateBaseStats(); void GenerateAppearance(); - void GenerateArmorClass(); int32 GenerateBaseHitPoints(); int32 GenerateBaseManaPoints(); void GenerateSpecialAttacks(); void SetBotID(uint32 botID); - //void SetCombatJitterFlag(bool flag = true) { m_combat_jitter_flag = flag; } void SetAttackingFlag(bool flag = true) { m_attacking_flag = flag; } void SetPullingFlag(bool flag = true) { m_pulling_flag = flag; } void SetReturningFlag(bool flag = true) { m_returning_flag = flag; } @@ -862,9 +936,6 @@ private: bool LoadPet(); // Load and spawn bot pet if there is one bool SavePet(); // Save and depop bot pet if there is one bool DeletePet(); - - public: - static uint8 spell_casting_chances[SPELL_TYPE_COUNT][PLAYER_CLASS_COUNT][EQ::constants::STANCE_TYPE_COUNT][cntHSND]; }; bool IsSpellInBotList(DBbotspells_Struct* spell_list, uint16 iSpellID); diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index b85d4f1e4..f0c4827ce 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -122,82 +122,94 @@ public: } for (int spell_id = 2; spell_id < SPDAT_RECORDS; ++spell_id) { - if (spells[spell_id].player_1[0] == '\0') + if (!IsValidSpell(spell_id)) { continue; - if (spells[spell_id].target_type != ST_Target && spells[spell_id].cast_restriction != 0) // watch + } + + if (spells[spell_id].player_1[0] == '\0') { continue; + } + + if ( + spells[spell_id].target_type != ST_Target && + spells[spell_id].cast_restriction != 0 + ) { + continue; + } auto target_type = BCEnum::TT_None; switch (spells[spell_id].target_type) { - case ST_GroupTeleport: - target_type = BCEnum::TT_GroupV1; - break; - case ST_AECaster: - // Disabled until bot code works correctly - //target_type = BCEnum::TT_AECaster; - break; - case ST_AEBard: - // Disabled until bot code works correctly - //target_type = BCEnum::TT_AEBard; - break; - case ST_Target: - switch (spells[spell_id].cast_restriction) { - case 0: - target_type = BCEnum::TT_Single; + case ST_GroupTeleport: + target_type = BCEnum::TT_GroupV1; break; - case 104: + case ST_AECaster: + // Disabled until bot code works correctly + //target_type = BCEnum::TT_AECaster; + break; + case ST_AEBard: + // Disabled until bot code works correctly + //target_type = BCEnum::TT_AEBard; + break; + case ST_Target: + switch (spells[spell_id].cast_restriction) { + case 0: + target_type = BCEnum::TT_Single; + break; + case 104: + target_type = BCEnum::TT_Animal; + break; + case 105: + target_type = BCEnum::TT_Plant; + break; + case 118: + target_type = BCEnum::TT_Summoned; + break; + case 120: + target_type = BCEnum::TT_Undead; + break; + default: + break; + } + break; + case ST_Self: + target_type = BCEnum::TT_Self; + break; + case ST_AETarget: + // Disabled until bot code works correctly + //target_type = BCEnum::TT_AETarget; + break; + case ST_Animal: target_type = BCEnum::TT_Animal; break; - case 105: - target_type = BCEnum::TT_Plant; + case ST_Undead: + target_type = BCEnum::TT_Undead; break; - case 118: + case ST_Summoned: target_type = BCEnum::TT_Summoned; break; - case 120: - target_type = BCEnum::TT_Undead; + case ST_Corpse: + target_type = BCEnum::TT_Corpse; + break; + case ST_Plant: + target_type = BCEnum::TT_Plant; + break; + case ST_Group: + target_type = BCEnum::TT_GroupV2; break; default: break; - } - break; - case ST_Self: - target_type = BCEnum::TT_Self; - break; - case ST_AETarget: - // Disabled until bot code works correctly - //target_type = BCEnum::TT_AETarget; - break; - case ST_Animal: - target_type = BCEnum::TT_Animal; - break; - case ST_Undead: - target_type = BCEnum::TT_Undead; - break; - case ST_Summoned: - target_type = BCEnum::TT_Summoned; - break; - case ST_Corpse: - target_type = BCEnum::TT_Corpse; - break; - case ST_Plant: - target_type = BCEnum::TT_Plant; - break; - case ST_Group: - target_type = BCEnum::TT_GroupV2; - break; - default: - break; } if (target_type == BCEnum::TT_None) continue; - uint8 class_levels[16] = { 0 }; + uint8 class_levels[16] = {0}; bool player_spell = false; for (int class_type = WARRIOR; class_type <= BERSERKER; ++class_type) { int class_index = CLASSIDTOINDEX(class_type); - if (spells[spell_id].classes[class_index] == 0 || spells[spell_id].classes[class_index] > HARD_LEVEL_CAP) + if (spells[spell_id].classes[class_index] == 0 || + spells[spell_id].classes[class_index] > HARD_LEVEL_CAP) { continue; + } class_levels[class_index] = spells[spell_id].classes[class_index]; player_spell = true; @@ -208,124 +220,122 @@ public: STBaseEntry* entry_prototype = nullptr; while (true) { switch (spells[spell_id].effect_id[EFFECTIDTOINDEX(1)]) { - case SE_BindAffinity: - entry_prototype = new STBaseEntry(BCEnum::SpT_BindAffinity); - break; - case SE_Charm: - if (spells[spell_id].spell_affect_index != 12) + case SE_BindAffinity: + entry_prototype = new STBaseEntry(BCEnum::SpT_BindAffinity); break; - entry_prototype = new STCharmEntry(); - if (spells[spell_id].resist_difficulty <= -1000) - entry_prototype->SafeCastToCharm()->dire = true; - break; - case SE_Teleport: - entry_prototype = new STDepartEntry; - entry_prototype->SafeCastToDepart()->single = !BCSpells::IsGroupType(target_type); - break; - case SE_Succor: - if (!strcmp(spells[spell_id].teleport_zone, "same")) { - entry_prototype = new STEscapeEntry; - } - else { + case SE_Charm: + if (spells[spell_id].spell_affect_index != 12) + break; + entry_prototype = new STCharmEntry(); + if (spells[spell_id].resist_difficulty <= -1000) + entry_prototype->SafeCastToCharm()->dire = true; + break; + case SE_Teleport: entry_prototype = new STDepartEntry; entry_prototype->SafeCastToDepart()->single = !BCSpells::IsGroupType(target_type); - } - break; - case SE_Translocate: - if (spells[spell_id].teleport_zone[0] == '\0') { - entry_prototype = new STSendHomeEntry(); - entry_prototype->SafeCastToSendHome()->group = BCSpells::IsGroupType(target_type); - } - else { - entry_prototype = new STDepartEntry; - entry_prototype->SafeCastToDepart()->single = !BCSpells::IsGroupType(target_type); - } - break; - case SE_ModelSize: - if (spells[spell_id].base_value[EFFECTIDTOINDEX(1)] > 100) { - entry_prototype = new STSizeEntry; - entry_prototype->SafeCastToSize()->size_type = BCEnum::SzT_Enlarge; - } - else if (spells[spell_id].base_value[EFFECTIDTOINDEX(1)] > 0 && spells[spell_id].base_value[EFFECTIDTOINDEX(1)] < 100) { - entry_prototype = new STSizeEntry; - entry_prototype->SafeCastToSize()->size_type = BCEnum::SzT_Reduce; - } - break; - case SE_Identify: - entry_prototype = new STBaseEntry(BCEnum::SpT_Identify); - break; - case SE_Invisibility: - if (spells[spell_id].spell_affect_index != 9) break; - entry_prototype = new STInvisibilityEntry; - entry_prototype->SafeCastToInvisibility()->invis_type = BCEnum::IT_Living; - break; - case SE_SeeInvis: - if (spells[spell_id].spell_affect_index != 5) + case SE_Succor: + if (!strcmp(spells[spell_id].teleport_zone, "same")) { + entry_prototype = new STEscapeEntry; + } else { + entry_prototype = new STDepartEntry; + entry_prototype->SafeCastToDepart()->single = !BCSpells::IsGroupType(target_type); + } break; - entry_prototype = new STInvisibilityEntry; - entry_prototype->SafeCastToInvisibility()->invis_type = BCEnum::IT_See; - break; - case SE_InvisVsUndead: - if (spells[spell_id].spell_affect_index != 9) + case SE_Translocate: + if (spells[spell_id].teleport_zone[0] == '\0') { + entry_prototype = new STSendHomeEntry(); + entry_prototype->SafeCastToSendHome()->group = BCSpells::IsGroupType(target_type); + } else { + entry_prototype = new STDepartEntry; + entry_prototype->SafeCastToDepart()->single = !BCSpells::IsGroupType(target_type); + } break; - entry_prototype = new STInvisibilityEntry; - entry_prototype->SafeCastToInvisibility()->invis_type = BCEnum::IT_Undead; - break; - case SE_InvisVsAnimals: - if (spells[spell_id].spell_affect_index != 9) + case SE_ModelSize: + if (spells[spell_id].base_value[EFFECTIDTOINDEX(1)] > 100) { + entry_prototype = new STSizeEntry; + entry_prototype->SafeCastToSize()->size_type = BCEnum::SzT_Enlarge; + } else if (spells[spell_id].base_value[EFFECTIDTOINDEX(1)] > 0 && + spells[spell_id].base_value[EFFECTIDTOINDEX(1)] < 100) { + entry_prototype = new STSizeEntry; + entry_prototype->SafeCastToSize()->size_type = BCEnum::SzT_Reduce; + } break; - entry_prototype = new STInvisibilityEntry; - entry_prototype->SafeCastToInvisibility()->invis_type = BCEnum::IT_Animal; - break; - case SE_Mez: - if (spells[spell_id].spell_affect_index != 12) + case SE_Identify: + entry_prototype = new STBaseEntry(BCEnum::SpT_Identify); break; - entry_prototype = new STBaseEntry(BCEnum::SpT_Mesmerize); - break; - case SE_Revive: - if (spells[spell_id].spell_affect_index != 1) + case SE_Invisibility: + if (spells[spell_id].spell_affect_index != 9) + break; + entry_prototype = new STInvisibilityEntry; + entry_prototype->SafeCastToInvisibility()->invis_type = BCEnum::IT_Living; break; - entry_prototype = new STResurrectEntry(); - entry_prototype->SafeCastToResurrect()->aoe = BCSpells::IsCasterCentered(target_type); - break; - case SE_Rune: - if (spells[spell_id].spell_affect_index != 2) + case SE_SeeInvis: + if (spells[spell_id].spell_affect_index != 5) + break; + entry_prototype = new STInvisibilityEntry; + entry_prototype->SafeCastToInvisibility()->invis_type = BCEnum::IT_See; + break; + case SE_InvisVsUndead: + if (spells[spell_id].spell_affect_index != 9) + break; + entry_prototype = new STInvisibilityEntry; + entry_prototype->SafeCastToInvisibility()->invis_type = BCEnum::IT_Undead; + break; + case SE_InvisVsAnimals: + if (spells[spell_id].spell_affect_index != 9) + break; + entry_prototype = new STInvisibilityEntry; + entry_prototype->SafeCastToInvisibility()->invis_type = BCEnum::IT_Animal; + break; + case SE_Mez: + if (spells[spell_id].spell_affect_index != 12) + break; + entry_prototype = new STBaseEntry(BCEnum::SpT_Mesmerize); + break; + case SE_Revive: + if (spells[spell_id].spell_affect_index != 1) + break; + entry_prototype = new STResurrectEntry(); + entry_prototype->SafeCastToResurrect()->aoe = BCSpells::IsCasterCentered(target_type); + break; + case SE_Rune: + if (spells[spell_id].spell_affect_index != 2) + break; + entry_prototype = new STBaseEntry(BCEnum::SpT_Rune); + break; + case SE_SummonCorpse: + entry_prototype = new STBaseEntry(BCEnum::SpT_SummonCorpse); + break; + case SE_WaterBreathing: + entry_prototype = new STBaseEntry(BCEnum::SpT_WaterBreathing); + break; + default: break; - entry_prototype = new STBaseEntry(BCEnum::SpT_Rune); - break; - case SE_SummonCorpse: - entry_prototype = new STBaseEntry(BCEnum::SpT_SummonCorpse); - break; - case SE_WaterBreathing: - entry_prototype = new STBaseEntry(BCEnum::SpT_WaterBreathing); - break; - default: - break; } if (entry_prototype) break; switch (spells[spell_id].effect_id[EFFECTIDTOINDEX(2)]) { - case SE_Succor: - entry_prototype = new STEscapeEntry; - std::string is_lesser = spells[spell_id].name; - if (is_lesser.find("Lesser") != std::string::npos) - entry_prototype->SafeCastToEscape()->lesser = true; - break; + case SE_Succor: + entry_prototype = new STEscapeEntry; + std::string is_lesser = spells[spell_id].name; + if (is_lesser.find("Lesser") != std::string::npos) + entry_prototype->SafeCastToEscape()->lesser = true; + break; } if (entry_prototype) break; switch (spells[spell_id].effect_id[EFFECTIDTOINDEX(3)]) { - case SE_Lull: - entry_prototype = new STBaseEntry(BCEnum::SpT_Lull); - break; - case SE_Levitate: // needs more criteria - entry_prototype = new STBaseEntry(BCEnum::SpT_Levitation); - break; - default: - break; + case SE_Lull: + entry_prototype = new STBaseEntry(BCEnum::SpT_Lull); + break; + case SE_Levitate: // needs more criteria + entry_prototype = new STBaseEntry(BCEnum::SpT_Levitation); + break; + default: + break; } if (entry_prototype) break; @@ -333,7 +343,8 @@ public: while (spells[spell_id].type_description_id == 27) { if (!spells[spell_id].good_effect) break; - if (spells[spell_id].skill != EQ::skills::SkillOffense && spells[spell_id].skill != EQ::skills::SkillDefense) + if (spells[spell_id].skill != EQ::skills::SkillOffense && + spells[spell_id].skill != EQ::skills::SkillDefense) break; entry_prototype = new STStanceEntry(); @@ -348,98 +359,111 @@ public: break; switch (spells[spell_id].spell_affect_index) { - case 1: { - bool valid_spell = false; - entry_prototype = new STCureEntry; + case 1: { + bool valid_spell = false; + entry_prototype = new STCureEntry; - for (int i = EffectIDFirst; i <= EffectIDLast; ++i) { - int effect_index = EFFECTIDTOINDEX(i); - if (spells[spell_id].effect_id[effect_index] != SE_Blind && spells[spell_id].base_value[effect_index] >= 0) - continue; - else if (spells[spell_id].effect_id[effect_index] == SE_Blind && !spells[spell_id].good_effect) - continue; + for (int i = EffectIDFirst; i <= EffectIDLast; ++i) { + int effect_index = EFFECTIDTOINDEX(i); + if (spells[spell_id].effect_id[effect_index] != SE_Blind && + spells[spell_id].base_value[effect_index] >= 0) + continue; + else if (spells[spell_id].effect_id[effect_index] == SE_Blind && + !spells[spell_id].good_effect) + continue; - switch (spells[spell_id].effect_id[effect_index]) { - case SE_Blind: - entry_prototype->SafeCastToCure()->cure_value[AILMENTIDTOINDEX(BCEnum::AT_Blindness)] += spells[spell_id].base_value[effect_index]; - break; - case SE_DiseaseCounter: - entry_prototype->SafeCastToCure()->cure_value[AILMENTIDTOINDEX(BCEnum::AT_Disease)] += spells[spell_id].base_value[effect_index]; - break; - case SE_PoisonCounter: - entry_prototype->SafeCastToCure()->cure_value[AILMENTIDTOINDEX(BCEnum::AT_Poison)] += spells[spell_id].base_value[effect_index]; - break; - case SE_CurseCounter: - entry_prototype->SafeCastToCure()->cure_value[AILMENTIDTOINDEX(BCEnum::AT_Curse)] += spells[spell_id].base_value[effect_index]; - break; - case SE_CorruptionCounter: - entry_prototype->SafeCastToCure()->cure_value[AILMENTIDTOINDEX(BCEnum::AT_Corruption)] += spells[spell_id].base_value[effect_index]; - break; - default: - continue; + switch (spells[spell_id].effect_id[effect_index]) { + case SE_Blind: + entry_prototype->SafeCastToCure()->cure_value[AILMENTIDTOINDEX( + BCEnum::AT_Blindness)] += spells[spell_id].base_value[effect_index]; + break; + case SE_DiseaseCounter: + entry_prototype->SafeCastToCure()->cure_value[AILMENTIDTOINDEX( + BCEnum::AT_Disease)] += spells[spell_id].base_value[effect_index]; + break; + case SE_PoisonCounter: + entry_prototype->SafeCastToCure()->cure_value[AILMENTIDTOINDEX( + BCEnum::AT_Poison)] += spells[spell_id].base_value[effect_index]; + break; + case SE_CurseCounter: + entry_prototype->SafeCastToCure()->cure_value[AILMENTIDTOINDEX( + BCEnum::AT_Curse)] += spells[spell_id].base_value[effect_index]; + break; + case SE_CorruptionCounter: + entry_prototype->SafeCastToCure()->cure_value[AILMENTIDTOINDEX( + BCEnum::AT_Corruption)] += spells[spell_id].base_value[effect_index]; + break; + default: + continue; + } + entry_prototype->SafeCastToCure()->cure_total += spells[spell_id].base_value[effect_index]; + valid_spell = true; } - entry_prototype->SafeCastToCure()->cure_total += spells[spell_id].base_value[effect_index]; - valid_spell = true; - } - if (!valid_spell) { - safe_delete(entry_prototype); - entry_prototype = nullptr; - } - - break; - } - case 2: { - bool valid_spell = false; - entry_prototype = new STResistanceEntry; - - for (int i = EffectIDFirst; i <= EffectIDLast; ++i) { - int effect_index = EFFECTIDTOINDEX(i); - if (spells[spell_id].base_value[effect_index] <= 0) - continue; - - switch (spells[spell_id].effect_id[effect_index]) { - case SE_ResistFire: - entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX(BCEnum::RT_Fire)] += spells[spell_id].base_value[effect_index]; - break; - case SE_ResistCold: - entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX(BCEnum::RT_Cold)] += spells[spell_id].base_value[effect_index]; - break; - case SE_ResistPoison: - entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX(BCEnum::RT_Poison)] += spells[spell_id].base_value[effect_index]; - break; - case SE_ResistDisease: - entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX(BCEnum::RT_Disease)] += spells[spell_id].base_value[effect_index]; - break; - case SE_ResistMagic: - entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX(BCEnum::RT_Magic)] += spells[spell_id].base_value[effect_index]; - break; - case SE_ResistCorruption: - entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX(BCEnum::RT_Corruption)] += spells[spell_id].base_value[effect_index]; - break; - default: - continue; + if (!valid_spell) { + safe_delete(entry_prototype); + entry_prototype = nullptr; } - entry_prototype->SafeCastToResistance()->resist_total += spells[spell_id].base_value[effect_index]; - valid_spell = true; - } - if (!valid_spell) { - safe_delete(entry_prototype); - entry_prototype = nullptr; - } - break; - } - case 7: - case 10: - if (spells[spell_id].effect_description_id != 65) break; - if (IsEffectInSpell(spell_id, SE_NegateIfCombat)) + } + case 2: { + bool valid_spell = false; + entry_prototype = new STResistanceEntry; + + for (int i = EffectIDFirst; i <= EffectIDLast; ++i) { + int effect_index = EFFECTIDTOINDEX(i); + if (spells[spell_id].base_value[effect_index] <= 0) + continue; + + switch (spells[spell_id].effect_id[effect_index]) { + case SE_ResistFire: + entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX( + BCEnum::RT_Fire)] += spells[spell_id].base_value[effect_index]; + break; + case SE_ResistCold: + entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX( + BCEnum::RT_Cold)] += spells[spell_id].base_value[effect_index]; + break; + case SE_ResistPoison: + entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX( + BCEnum::RT_Poison)] += spells[spell_id].base_value[effect_index]; + break; + case SE_ResistDisease: + entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX( + BCEnum::RT_Disease)] += spells[spell_id].base_value[effect_index]; + break; + case SE_ResistMagic: + entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX( + BCEnum::RT_Magic)] += spells[spell_id].base_value[effect_index]; + break; + case SE_ResistCorruption: + entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX( + BCEnum::RT_Corruption)] += spells[spell_id].base_value[effect_index]; + break; + default: + continue; + } + entry_prototype->SafeCastToResistance()->resist_total += spells[spell_id].base_value[effect_index]; + valid_spell = true; + } + if (!valid_spell) { + safe_delete(entry_prototype); + entry_prototype = nullptr; + } + + break; + } + case 7: + case 10: + if (spells[spell_id].effect_description_id != 65) + break; + if (IsEffectInSpell(spell_id, SE_NegateIfCombat)) + break; + entry_prototype = new STMovementSpeedEntry(); + entry_prototype->SafeCastToMovementSpeed()->group = BCSpells::IsGroupType(target_type); + break; + default: break; - entry_prototype = new STMovementSpeedEntry(); - entry_prototype->SafeCastToMovementSpeed()->group = BCSpells::IsGroupType(target_type); - break; - default: - break; } if (entry_prototype) break; @@ -449,7 +473,8 @@ public: if (!entry_prototype) continue; - if (target_type == BCEnum::TT_Self && (entry_prototype->BCST() != BCEnum::SpT_Stance && entry_prototype->BCST() != BCEnum::SpT_SummonCorpse)) { + if (target_type == BCEnum::TT_Self && (entry_prototype->BCST() != BCEnum::SpT_Stance && + entry_prototype->BCST() != BCEnum::SpT_SummonCorpse)) { #ifdef BCSTSPELLDUMP LogError("DELETING entry_prototype (primary clause) - name: [{}], target_type: [{}], BCST: [{}]", spells[spell_id].name, BCEnum::TargetTypeEnumToString(target_type).c_str(), BCEnum::SpellTypeEnumToString(entry_prototype->BCST()).c_str()); @@ -479,53 +504,53 @@ public: STBaseEntry* spell_entry = nullptr; switch (entry_prototype->BCST()) { - case BCEnum::SpT_Charm: - if (entry_prototype->IsCharm()) - spell_entry = new STCharmEntry(entry_prototype->SafeCastToCharm()); - break; - case BCEnum::SpT_Cure: - if (entry_prototype->IsCure()) - spell_entry = new STCureEntry(entry_prototype->SafeCastToCure()); - break; - case BCEnum::SpT_Depart: - if (entry_prototype->IsDepart()) - spell_entry = new STDepartEntry(entry_prototype->SafeCastToDepart()); - break; - case BCEnum::SpT_Escape: - if (entry_prototype->IsEscape()) - spell_entry = new STEscapeEntry(entry_prototype->SafeCastToEscape()); - break; - case BCEnum::SpT_Invisibility: - if (entry_prototype->IsInvisibility()) - spell_entry = new STInvisibilityEntry(entry_prototype->SafeCastToInvisibility()); - break; - case BCEnum::SpT_MovementSpeed: - if (entry_prototype->IsMovementSpeed()) - spell_entry = new STMovementSpeedEntry(entry_prototype->SafeCastToMovementSpeed()); - break; - case BCEnum::SpT_Resistance: - if (entry_prototype->IsResistance()) - spell_entry = new STResistanceEntry(entry_prototype->SafeCastToResistance()); - break; - case BCEnum::SpT_Resurrect: - if (entry_prototype->IsResurrect()) - spell_entry = new STResurrectEntry(entry_prototype->SafeCastToResurrect()); - break; - case BCEnum::SpT_SendHome: - if (entry_prototype->IsSendHome()) - spell_entry = new STSendHomeEntry(entry_prototype->SafeCastToSendHome()); - break; - case BCEnum::SpT_Size: - if (entry_prototype->IsSize()) - spell_entry = new STSizeEntry(entry_prototype->SafeCastToSize()); - break; - case BCEnum::SpT_Stance: - if (entry_prototype->IsStance()) - spell_entry = new STStanceEntry(entry_prototype->SafeCastToStance()); - break; - default: - spell_entry = new STBaseEntry(entry_prototype); - break; + case BCEnum::SpT_Charm: + if (entry_prototype->IsCharm()) + spell_entry = new STCharmEntry(entry_prototype->SafeCastToCharm()); + break; + case BCEnum::SpT_Cure: + if (entry_prototype->IsCure()) + spell_entry = new STCureEntry(entry_prototype->SafeCastToCure()); + break; + case BCEnum::SpT_Depart: + if (entry_prototype->IsDepart()) + spell_entry = new STDepartEntry(entry_prototype->SafeCastToDepart()); + break; + case BCEnum::SpT_Escape: + if (entry_prototype->IsEscape()) + spell_entry = new STEscapeEntry(entry_prototype->SafeCastToEscape()); + break; + case BCEnum::SpT_Invisibility: + if (entry_prototype->IsInvisibility()) + spell_entry = new STInvisibilityEntry(entry_prototype->SafeCastToInvisibility()); + break; + case BCEnum::SpT_MovementSpeed: + if (entry_prototype->IsMovementSpeed()) + spell_entry = new STMovementSpeedEntry(entry_prototype->SafeCastToMovementSpeed()); + break; + case BCEnum::SpT_Resistance: + if (entry_prototype->IsResistance()) + spell_entry = new STResistanceEntry(entry_prototype->SafeCastToResistance()); + break; + case BCEnum::SpT_Resurrect: + if (entry_prototype->IsResurrect()) + spell_entry = new STResurrectEntry(entry_prototype->SafeCastToResurrect()); + break; + case BCEnum::SpT_SendHome: + if (entry_prototype->IsSendHome()) + spell_entry = new STSendHomeEntry(entry_prototype->SafeCastToSendHome()); + break; + case BCEnum::SpT_Size: + if (entry_prototype->IsSize()) + spell_entry = new STSizeEntry(entry_prototype->SafeCastToSize()); + break; + case BCEnum::SpT_Stance: + if (entry_prototype->IsStance()) + spell_entry = new STStanceEntry(entry_prototype->SafeCastToStance()); + break; + default: + spell_entry = new STBaseEntry(entry_prototype); + break; } assert(spell_entry); @@ -535,7 +560,8 @@ public: bot_command_spells[spell_entry->BCST()].push_back(spell_entry); - if (bot_levels.find(class_type) == bot_levels.end() || bot_levels[class_type] > class_levels[class_index]) + if (bot_levels.find(class_type) == bot_levels.end() || + bot_levels[class_type] > class_levels[class_index]) bot_levels[class_type] = class_levels[class_index]; } @@ -551,15 +577,15 @@ public: #ifdef BCSTSPELLDUMP spell_dump(); #endif - } static void Unload() { for (auto map_iter : bot_command_spells) { if (map_iter.second.empty()) continue; - for (auto list_iter : map_iter.second) - safe_delete(list_iter); + for (auto list_iter: map_iter.second) { + safe_delete(list_iter); + } map_iter.second.clear(); } bot_command_spells.clear(); @@ -569,24 +595,23 @@ public: static bool IsCasterCentered(BCEnum::TType target_type) { switch (target_type) { - case BCEnum::TT_AECaster: - case BCEnum::TT_AEBard: - return true; - default: - return false; + case BCEnum::TT_AECaster: + case BCEnum::TT_AEBard: + return true; + default: + return false; } } static bool IsGroupType(BCEnum::TType target_type) { switch (target_type) { - case BCEnum::TT_GroupV1: - case BCEnum::TT_GroupV2: - return true; - default: - return false; + case BCEnum::TT_GroupV1: + case BCEnum::TT_GroupV2: + return true; + default: + return false; } } - private: static void remove_inactive() { if (bot_command_spells.empty()) @@ -610,8 +635,10 @@ private: } }); - for (auto del_iter : *removed_spells_list) + for (auto del_iter: *removed_spells_list) + { safe_delete(del_iter); + } removed_spells_list->clear(); if (RuleI(Bots, CommandSpellRank) == 1) { @@ -635,8 +662,9 @@ private: return false; }); - for (auto del_iter : *removed_spells_list) + for (auto del_iter: *removed_spells_list) { safe_delete(del_iter); + } removed_spells_list->clear(); } @@ -659,8 +687,9 @@ private: return false; }); - for (auto del_iter : *removed_spells_list) + for (auto del_iter: *removed_spells_list) { safe_delete(del_iter); + } removed_spells_list->clear(); } @@ -686,8 +715,9 @@ private: return false; }); - for (auto del_iter : *removed_spells_list) + for (auto del_iter: *removed_spells_list) { safe_delete(del_iter); + } removed_spells_list->clear(); } @@ -1245,6 +1275,8 @@ int bot_command_count; // how many bot commands we have // init has been performed to point at the real function int (*bot_command_dispatch)(Client *,char const *) = bot_command_not_avail; + + std::map bot_command_list; std::map bot_command_aliases; @@ -1356,6 +1388,7 @@ int bot_command_init(void) bot_command_add("bottitle", "Sets a bots title", AccountStatus::Player, bot_subcommand_bot_title) || bot_command_add("botupdate", "Updates a bot to reflect any level changes that you have experienced", AccountStatus::Player, bot_subcommand_bot_update) || bot_command_add("botwoad", "Changes the Barbarian woad of a bot", AccountStatus::Player, bot_subcommand_bot_woad) || + bot_command_add("casterrange", "Controls the range casters will try to stay away from a mob (if too far, they will skip spells that are out-of-range)", AccountStatus::Player, bot_command_caster_range) || bot_command_add("charm", "Attempts to have a bot charm your target", AccountStatus::Player, bot_command_charm) || bot_command_add("circle", "Orders a Druid bot to open a magical doorway to a specified destination", AccountStatus::Player, bot_subcommand_circle) || bot_command_add("cure", "Orders a bot to remove any ailments", AccountStatus::Player, bot_command_cure) || @@ -1614,8 +1647,6 @@ int bot_command_real_dispatch(Client *c, const char *message) { Seperator sep(message, ' ', 10, 100, true); // "three word argument" should be considered 1 arg - bot_command_log_command(c, message); - std::string cstr(sep.arg[0]+1); if(bot_command_list.count(cstr) != 1) { @@ -1649,77 +1680,6 @@ int bot_command_real_dispatch(Client *c, const char *message) } -void bot_command_log_command(Client *c, const char *message) -{ -int admin = c->Admin(); - - bool continueevents = false; - switch (zone->loglevelvar){ //catch failsafe - case 9: { // log only LeadGM - if ( - admin >= AccountStatus::GMLeadAdmin && - admin < AccountStatus::GMMgmt - ) { - continueevents = true; - } - break; - } - case 8: { // log only GM - if ( - admin >= AccountStatus::GMAdmin && - admin < AccountStatus::GMLeadAdmin - ) { - continueevents = true; - } - break; - } - case 1: { - if (admin >= AccountStatus::GMMgmt) { - continueevents = true; - } - break; - } - case 2: { - if (admin >= AccountStatus::GMLeadAdmin) { - continueevents = true; - } - break; - } - case 3: { - if (admin >= AccountStatus::GMAdmin) { - continueevents = true; - } - break; - } - case 4: { - if (admin >= AccountStatus::QuestTroupe) { - continueevents = true; - } - break; - } - case 5: { - if (admin >= AccountStatus::ApprenticeGuide) { - continueevents = true; - } - break; - } - case 6: { - if (admin >= AccountStatus::Steward) { - continueevents = true; - } - break; - } - case 7: { - continueevents = true; - break; - } - } - - if (continueevents) - database.logevents(c->AccountName(), c->AccountID(), admin,c->GetName(), c->GetTarget()?c->GetTarget()->GetName():"None", "BotCommand", message, 1); -} - - /* * helper functions by use */ @@ -1988,7 +1948,7 @@ namespace MyBots if (!clear_list) UniquifySBL(sbl); } -}; +} namespace ActionableTarget { @@ -2182,7 +2142,7 @@ namespace ActionableTarget return target[target_type]; } }; -}; +} namespace ActionableBots { @@ -2523,7 +2483,7 @@ namespace ActionableBots ActionableBots::Filter_ByHighestSkill(bot_owner, sbl, EQ::skills::SkillPickLock, pick_lock_value); } -}; +} /* @@ -2879,7 +2839,7 @@ void bot_command_bind_affinity(Client *c, const Seperator *sep) void bot_command_bot(Client *c, const Seperator *sep) { - /* VS2012 code - begin */ + std::list subcommand_list; subcommand_list.push_back("botappearance"); subcommand_list.push_back("botcamp"); @@ -2900,14 +2860,6 @@ void bot_command_bot(Client *c, const Seperator *sep) subcommand_list.push_back("bottogglearcher"); subcommand_list.push_back("bottogglehelm"); subcommand_list.push_back("botupdate"); - /* VS2012 code - end */ - - /* VS2013 code - const std::list subcommand_list = { - "botappearance", "botcamp", "botclone", "botcreate", "botdelete", "botdetails", "botdyearmor", "botinspectmessage", "botfollowdistance", - "botlist", "botoutofcombat", "botreport", "botspawn", "botstance", "botsummon", "bottogglearcher", "bottogglehelm", "botupdate" - }; - */ if (helper_command_alias_fail(c, "bot_command_bot", sep->arg[0], "bot")) return; @@ -3241,7 +3193,14 @@ void bot_command_find_aliases(Client *c, const Seperator *sep) if (strcasecmp(find_iter->second.c_str(), alias_iter.second.c_str()) || c->Admin() < command_iter->second->access) continue; - c->Message(Chat::White, "%c%s", BOT_COMMAND_CHAR, alias_iter.first.c_str()); + c->Message( + Chat::White, + fmt::format( + "^{}", + alias_iter.first + ).c_str() + ); + ++bot_command_aliases_shown; } c->Message(Chat::White, "%d bot command alias%s listed.", bot_command_aliases_shown, bot_command_aliases_shown != 1 ? "es" : ""); @@ -3407,7 +3366,7 @@ void bot_command_guard(Client *c, const Seperator *sep) void bot_command_heal_rotation(Client *c, const Seperator *sep) { - /* VS2012 code - begin */ + std::list subcommand_list; subcommand_list.push_back("healrotationadaptivetargeting"); subcommand_list.push_back("healrotationaddmember"); @@ -3429,16 +3388,6 @@ void bot_command_heal_rotation(Client *c, const Seperator *sep) subcommand_list.push_back("healrotationsethot"); subcommand_list.push_back("healrotationstart"); subcommand_list.push_back("healrotationstop"); - /* VS2012 code - end */ - - /* VS2013 code - const std::list subcommand_list = { - "healrotationadaptivetargeting", "healrotationaddmember", "healrotationaddtarget", "healrotationadjustcritical", "healrotationadjustsafe", - "healrotationcastoverride", "healrotationchangeinterval", "healrotationclearhot", "healrotationcleartargets", "healrotationcreate", - "healrotationdelete", "healrotationfastheals", "healrotationlist", "healrotationremovemember", "healrotationremovetarget", "healrotationsave", - "healrotationresetlimits", "healrotationsethot", "healrotationstart", "healrotationstop" - }; - */ if (helper_command_alias_fail(c, "bot_command_heal_rotation", sep->arg[0], "healrotation")) return; @@ -3475,7 +3424,15 @@ void bot_command_help(Client *c, const Seperator *sep) if (c->Admin() < command_iter.second->access) continue; - c->Message(Chat::White, "%c%s - %s", BOT_COMMAND_CHAR, command_iter.first.c_str(), command_iter.second->desc == nullptr ? "[no description]" : command_iter.second->desc); + c->Message( + Chat::White, + fmt::format( + "^{} - {}", + command_iter.first, + command_iter.second->desc ? command_iter.second->desc : "No Description" + ).c_str() + ); + ++bot_commands_shown; } if (parse->PlayerHasQuestSub(EVENT_BOT_COMMAND)) { @@ -3587,17 +3544,12 @@ void bot_command_identify(Client *c, const Seperator *sep) void bot_command_inventory(Client *c, const Seperator *sep) { - /* VS2012 code - begin */ + std::list subcommand_list; subcommand_list.push_back("inventorygive"); subcommand_list.push_back("inventorylist"); subcommand_list.push_back("inventoryremove"); subcommand_list.push_back("inventorywindow"); - /* VS2012 code - end */ - - /* VS2013 code - const std::list subcommand_list = { "inventorygive", "inventorylist", "inventoryremove", "inventorywindow" }; - */ if (helper_command_alias_fail(c, "bot_command_inventory", sep->arg[0], "inventory")) return; @@ -3716,8 +3668,14 @@ void bot_command_item_use(Client* c, const Seperator* sep) continue; } - msg = StringFormat("%cinventorygive byname %s", BOT_COMMAND_CHAR, bot_iter->GetCleanName()); - text_link = bot_iter->CreateSayLink(c, msg.c_str(), bot_iter->GetCleanName()); + text_link = bot_iter->CreateSayLink( + c, + fmt::format( + "^inventorygive byname {}", + bot_iter->GetCleanName() + ).c_str(), + bot_iter->GetCleanName() + ); for (auto slot_iter : equipable_slot_list) { // needs more failure criteria - this should cover the bulk for now @@ -4056,7 +4014,7 @@ void bot_command_owner_option(Client *c, const Seperator *sep) database.botdb.SaveOwnerOption(c->CharacterID(), Client::booDeathMarquee, c->GetBotOption(Client::booDeathMarquee)); - c->Message(Chat::White, "Bot 'death marquee' is now %s.", (c->GetBotOption(Client::booDeathMarquee) == true ? "enabled" : "disabled")); + c->Message(Chat::White, "Bot 'death marquee' is now %s.", (c->GetBotOption(Client::booDeathMarquee) ? "enabled" : "disabled")); } else if (!owner_option.compare("statsupdate")) { @@ -4072,7 +4030,7 @@ void bot_command_owner_option(Client *c, const Seperator *sep) database.botdb.SaveOwnerOption(c->CharacterID(), Client::booStatsUpdate, c->GetBotOption(Client::booStatsUpdate)); - c->Message(Chat::White, "Bot 'stats update' is now %s.", (c->GetBotOption(Client::booStatsUpdate) == true ? "enabled" : "disabled")); + c->Message(Chat::White, "Bot 'stats update' is now %s.", (c->GetBotOption(Client::booStatsUpdate) ? "enabled" : "disabled")); } else if (!owner_option.compare("spawnmessage")) { @@ -4158,7 +4116,7 @@ void bot_command_owner_option(Client *c, const Seperator *sep) database.botdb.SaveOwnerOption(c->CharacterID(), Client::booAltCombat, c->GetBotOption(Client::booAltCombat)); - c->Message(Chat::White, "Bot 'alt combat' is now %s.", (c->GetBotOption(Client::booAltCombat) == true ? "enabled" : "disabled")); + c->Message(Chat::White, "Bot 'alt combat' is now %s.", (c->GetBotOption(Client::booAltCombat) ? "enabled" : "disabled")); } else { c->Message(Chat::White, "Bot owner option 'altcombat' is not allowed on this server."); @@ -4180,7 +4138,7 @@ void bot_command_owner_option(Client *c, const Seperator *sep) database.botdb.SaveOwnerOption(c->CharacterID(), Client::booAutoDefend, c->GetBotOption(Client::booAutoDefend)); - c->Message(Chat::White, "Bot 'auto defend' is now %s.", (c->GetBotOption(Client::booAutoDefend) == true ? "enabled" : "disabled")); + c->Message(Chat::White, "Bot 'auto defend' is now %s.", (c->GetBotOption(Client::booAutoDefend) ? "enabled" : "disabled")); } else { c->Message(Chat::White, "Bot owner option 'autodefend' is not allowed on this server."); @@ -4200,7 +4158,7 @@ void bot_command_owner_option(Client *c, const Seperator *sep) database.botdb.SaveOwnerOption(c->CharacterID(), Client::booBuffCounter, c->GetBotOption(Client::booBuffCounter)); - c->Message(Chat::White, "Bot 'buff counter' is now %s.", (c->GetBotOption(Client::booBuffCounter) == true ? "enabled" : "disabled")); + c->Message(Chat::White, "Bot 'buff counter' is now %s.", (c->GetBotOption(Client::booBuffCounter) ? "enabled" : "disabled")); } else if (!owner_option.compare("monkwumessage")) { @@ -4216,7 +4174,11 @@ void bot_command_owner_option(Client *c, const Seperator *sep) database.botdb.SaveOwnerOption(c->CharacterID(), Client::booMonkWuMessage, c->GetBotOption(Client::booMonkWuMessage)); - c->Message(Chat::White, "Bot 'monk wu message' is now %s.", (c->GetBotOption(Client::booMonkWuMessage) == true ? "enabled" : "disabled")); + c->Message( + Chat::White, + "Bot 'monk wu message' is now %s.", + (c->GetBotOption(Client::booMonkWuMessage) ? "enabled" : "disabled") + ); } else if (!owner_option.compare("current")) { @@ -4255,16 +4217,11 @@ void bot_command_owner_option(Client *c, const Seperator *sep) void bot_command_pet(Client *c, const Seperator *sep) { - /* VS2012 code - begin */ + std::list subcommand_list; subcommand_list.push_back("petgetlost"); subcommand_list.push_back("petremove"); subcommand_list.push_back("petsettype"); - /* VS2012 code - end */ - - /* VS2013 code - const std::list subcommand_list = { "petgetlost", "petremove", "petsettype" }; - */ if (helper_command_alias_fail(c, "bot_command_pet", sep->arg[0], "pet")) return; @@ -4358,7 +4315,7 @@ void bot_command_precombat(Client* c, const Seperator* sep) c->SetBotPrecombat(!c->GetBotPrecombat()); } - c->Message(Chat::White, "Precombat flag is now %s.", (c->GetBotPrecombat() == true ? "set" : "clear")); + c->Message(Chat::White, "Precombat flag is now %s.", (c->GetBotPrecombat() ? "set" : "clear")); } // TODO: Rework to allow owner specificed criteria for puller @@ -5055,7 +5012,7 @@ void bot_command_water_breathing(Client *c, const Seperator *sep) */ void bot_subcommand_bot_appearance(Client *c, const Seperator *sep) { - /* VS2012 code - begin */ + std::list subcommand_list; subcommand_list.push_back("botbeardcolor"); subcommand_list.push_back("botbeardstyle"); @@ -5067,14 +5024,6 @@ void bot_subcommand_bot_appearance(Client *c, const Seperator *sep) subcommand_list.push_back("botheritage"); subcommand_list.push_back("bottattoo"); subcommand_list.push_back("botwoad"); - /* VS2012 code - end */ - - /* VS2013 code - const std::list subcommand_list = { - "botbeardcolor", "botbeardstyle", "botdetails", "boteyes", "botface", - "bothaircolor", "bothairstyle", "botheritage", "bottattoo", "botwoad" - }; - */ if (helper_command_alias_fail(c, "bot_subcommand_bot_appearance", sep->arg[0], "botappearance")) return; @@ -5103,7 +5052,7 @@ void bot_subcommand_bot_beard_color(Client *c, const Seperator *sep) return; } - uint8 uvalue = atoi(sep->arg[1]); + uint8 uvalue = Strings::ToInt(sep->arg[1]); auto fail_type = BCEnum::AFT_None; if (my_bot->GetGender() != MALE && my_bot->GetRace() != DWARF) @@ -5140,7 +5089,7 @@ void bot_subcommand_bot_beard_style(Client *c, const Seperator *sep) return; } - uint8 uvalue = atoi(sep->arg[1]); + uint8 uvalue = Strings::ToInt(sep->arg[1]); auto fail_type = BCEnum::AFT_None; if (my_bot->GetGender() != MALE && my_bot->GetRace() != DWARF) @@ -5364,40 +5313,54 @@ void bot_subcommand_bot_clone(Client *c, const Seperator *sep) void bot_command_view_combos(Client *c, const Seperator *sep) { - const std::string class_substrs[17] = { "", - "%u (WAR)", "%u (CLR)", "%u (PAL)", "%u (RNG)", - "%u (SHD)", "%u (DRU)", "%u (MNK)", "%u (BRD)", - "%u (ROG)", "%u (SHM)", "%u (NEC)", "%u (WIZ)", - "%u (MAG)", "%u (ENC)", "%u (BST)", "%u (BER)" + const std::string class_substrs[17] = { + "", + "WAR", "CLR", "PAL", "RNG", + "SHD", "DRU", "MNK", "BRD", + "ROG", "SHM", "NEC", "WIZ", + "MAG", "ENC", "BST", "BER" }; - const std::string race_substrs[17] = { "", - "%u (HUM)", "%u (BAR)", "%u (ERU)", "%u (ELF)", - "%u (HIE)", "%u (DEF)", "%u (HEF)", "%u (DWF)", - "%u (TRL)", "%u (OGR)", "%u (HFL)", "%u (GNM)", - "%u (IKS)", "%u (VAH)", "%u (FRG)", "%u (DRK)" + const std::string race_substrs[17] = { + "", + "HUM", "BAR", "ERU", "ELF", + "HIE", "DEF", "HEF", "DWF", + "TRL", "OGR", "HFL", "GNM", + "IKS", "VAH", "FRG", "DRK" }; - const uint16 race_values[17] = { 0, - HUMAN, BARBARIAN, ERUDITE, WOOD_ELF, - HIGH_ELF, DARK_ELF, HALF_ELF, DWARF, - TROLL, OGRE, HALFLING, GNOME, - IKSAR, VAHSHIR, FROGLOK, DRAKKIN + const uint16 race_values[17] = { + RACE_DOUG_0, + RACE_HUMAN_1, RACE_BARBARIAN_2, RACE_ERUDITE_3, RACE_WOOD_ELF_4, + RACE_HIGH_ELF_5, RACE_DARK_ELF_6, RACE_HALF_ELF_7, RACE_DWARF_8, + RACE_TROLL_9, RACE_OGRE_10, RACE_HALFLING_11, RACE_GNOME_12, + RACE_IKSAR_128, RACE_VAH_SHIR_130, RACE_FROGLOK_330, RACE_DRAKKIN_522 }; - if (helper_command_alias_fail(c, "bot_command_view_combos", sep->arg[0], "viewcombos")) + + if (helper_command_alias_fail(c, "bot_command_view_combos", sep->arg[0], "viewcombos")) { return; + } + if (helper_is_help_or_usage(sep->arg[1])) { - std::string window_title = "Bot Races"; std::string window_text; std::string message_separator = " "; - c->Message(Chat::White, "Usage: %s [bot_race]", sep->arg[0]); - window_text.append("Races:"); + c->Message(Chat::White, fmt::format("Usage: {} [Race]", sep->arg[0]).c_str()); + + window_text.append(""); + for (int race_id = 0; race_id <= 15; ++race_id) { window_text.append(message_separator); - window_text.append(StringFormat(race_substrs[race_id + 1].c_str(), race_values[race_id + 1])); + window_text.append( + fmt::format( + "{} ({})", + race_substrs[race_id + 1], + race_values[race_id + 1] + ) + ); + message_separator = ", "; } - c->SendPopupToClient(window_title.c_str(), window_text.c_str()); + c->SendPopupToClient("Bot Races", window_text.c_str()); return; } @@ -5405,53 +5368,92 @@ void bot_command_view_combos(Client *c, const Seperator *sep) c->Message(Chat::White, "Invalid Race!"); return; } - uint16 bot_race = atoi(sep->arg[1]); - auto classes_bitmask = database.botdb.GetRaceClassBitmask(bot_race); - auto race_name = GetRaceIDName(bot_race); - std::string window_title = "Bot Classes"; + + const uint16 bot_race = static_cast(Strings::ToUnsignedInt(sep->arg[1])); + const std::string race_name = GetRaceIDName(bot_race); + + if (!Mob::IsPlayerRace(bot_race)) { + c->Message( + Chat::White, + fmt::format( + "{} ({}) is not a race bots can use.", + race_name, + bot_race + ).c_str() + ); + return; + } + + const auto classes_bitmask = database.botdb.GetRaceClassBitmask(bot_race); + std::string window_text; std::string message_separator = " "; - c->Message(Chat::White, "%s can be these classes.", race_name); - window_text.append("Classes:"); + + window_text.append(""); + + const int object_max = 4; + auto object_count = 0; + for (int class_id = 0; class_id <= 15; ++class_id) { if (classes_bitmask & GetPlayerClassBit(class_id)) { window_text.append(message_separator); - window_text.append(StringFormat(class_substrs[class_id].c_str(), class_id)); + + if (object_count >= object_max) { + window_text.append(DialogueWindow::Break()); + object_count = 0; + } + + window_text.append( + fmt::format( + "{} ({})", + class_substrs[class_id], + class_id + ) + ); + + ++object_count; message_separator = ", "; } } - c->SendPopupToClient(window_title.c_str(), window_text.c_str()); - return; + + c->SendPopupToClient( + fmt::format( + "Bot Classes for {} ({})", + race_name, + bot_race + ).c_str(), + window_text.c_str() + ); } void bot_subcommand_bot_create(Client *c, const Seperator *sep) { const std::string class_substrs[17] = { "", - "{} (WAR)", "{} (CLR)", "{} (PAL)", "{} (RNG)", - "{} (SHD)", "{} (DRU)", "{} (MNK)", "{} (BRD)", - "{} (ROG)", "{} (SHM)", "{} (NEC)", "{} (WIZ)", - "{} (MAG)", "{} (ENC)", "{} (BST)", "{} (BER)" + "WAR", "CLR", "PAL", "RNG", + "SHD", "DRU", "MNK", "BRD", + "ROG", "SHM", "NEC", "WIZ", + "MAG", "ENC", "BST", "BER" }; const std::string race_substrs[17] = { "", - "{} (HUM)", "{} (BAR)", "{} (ERU)", "{} (ELF)", - "{} (HIE)", "{} (DEF)", "{} (HEF)", "{} (DWF)", - "{} (TRL)", "{} (OGR)", "{} (HFL)", "{} (GNM)", - "{} (IKS)", "{} (VAH)", "{} (FRG)", "{} (DRK)" + "HUM", "BAR", "ERU", "ELF", + "HIE", "DEF", "HEF", "DWF", + "TRL", "OGR", "HFL", "GNM", + "IKS", "VAH", "FRG", "DRK" }; const uint16 race_values[17] = { - 0, - HUMAN, BARBARIAN, ERUDITE, WOOD_ELF, - HIGH_ELF, DARK_ELF, HALF_ELF, DWARF, - TROLL, OGRE, HALFLING, GNOME, - IKSAR, VAHSHIR, FROGLOK, DRAKKIN + RACE_DOUG_0, + RACE_HUMAN_1, RACE_BARBARIAN_2, RACE_ERUDITE_3, RACE_WOOD_ELF_4, + RACE_HIGH_ELF_5, RACE_DARK_ELF_6, RACE_HALF_ELF_7, RACE_DWARF_8, + RACE_TROLL_9, RACE_OGRE_10, RACE_HALFLING_11, RACE_GNOME_12, + RACE_IKSAR_128, RACE_VAH_SHIR_130, RACE_FROGLOK_330, RACE_DRAKKIN_522 }; const std::string gender_substrs[2] = { - "{} (M)", "{} (F)", + "Male", "Female", }; if (helper_command_alias_fail(c, "bot_subcommand_bot_create", sep->arg[0], "botcreate")) { @@ -5462,7 +5464,7 @@ void bot_subcommand_bot_create(Client *c, const Seperator *sep) c->Message( Chat::White, fmt::format( - "Usage: {} [bot_name] [bot_class] [bot_race] [bot_gender]", + "Usage: {} [Name] [Class] [Race] [Gender]", sep->arg[0] ).c_str() ); @@ -5470,22 +5472,27 @@ void bot_subcommand_bot_create(Client *c, const Seperator *sep) std::string window_text; std::string message_separator; int object_count = 0; - const int object_max = 5; + const int object_max = 4; - window_text.append("Classes:"); + window_text.append( + fmt::format( + "Classes{}", + DialogueWindow::Break() + ) + ); message_separator = " "; - object_count = 1; + object_count = 0; for (int i = 0; i <= 15; ++i) { window_text.append(message_separator); if (object_count >= object_max) { - window_text.append("
"); + window_text.append(DialogueWindow::Break()); object_count = 0; } window_text.append( - fmt::format("{} {}", + fmt::format("{} ({})", class_substrs[i + 1], (i + 1) ) @@ -5495,22 +5502,27 @@ void bot_subcommand_bot_create(Client *c, const Seperator *sep) message_separator = ", "; } - window_text.append("

"); + window_text.append(DialogueWindow::Break(2)); - window_text.append("Races:"); + window_text.append( + fmt::format( + "Races{}", + DialogueWindow::Break() + ) + ); message_separator = " "; - object_count = 1; + object_count = 0; for (int i = 0; i <= 15; ++i) { window_text.append(message_separator); if (object_count >= object_max) { - window_text.append("
"); + window_text.append(DialogueWindow::Break()); object_count = 0; } window_text.append( - fmt::format("{}, {}", + fmt::format("{} ({})", race_substrs[i + 1], race_values[i + 1] ) @@ -5520,16 +5532,21 @@ void bot_subcommand_bot_create(Client *c, const Seperator *sep) message_separator = ", "; } - window_text.append("

"); + window_text.append(DialogueWindow::Break(2)); - window_text.append("Genders:"); + window_text.append( + fmt::format( + "Genders{}", + DialogueWindow::Break() + ) + ); message_separator = " "; for (int i = 0; i <= 1; ++i) { window_text.append(message_separator); window_text.append( - fmt::format("{}, {}", + fmt::format("{} ({})", gender_substrs[i], i ) @@ -5538,13 +5555,12 @@ void bot_subcommand_bot_create(Client *c, const Seperator *sep) message_separator = ", "; } - c->SendPopupToClient("Bot Create Options", window_text.c_str()); + c->SendPopupToClient("Bot Creation Options", window_text.c_str()); return; } - auto arguments = sep->argnum; - + const auto arguments = sep->argnum; if (!arguments || sep->IsNumber(1)) { c->Message(Chat::White, "You must name your bot!"); return; @@ -5557,29 +5573,32 @@ void bot_subcommand_bot_create(Client *c, const Seperator *sep) return; } - auto bot_class = static_cast(std::stoul(sep->arg[2])); + auto bot_class = static_cast(Strings::ToUnsignedInt(sep->arg[2])); if (arguments < 3 || !sep->IsNumber(3)) { c->Message(Chat::White, "Invalid race!"); return; } - auto bot_race = static_cast(std::stoul(sep->arg[3])); + auto bot_race = static_cast(Strings::ToUnsignedInt(sep->arg[3])); if (arguments < 4) { c->Message(Chat::White, "Invalid gender!"); return; } - auto bot_gender = 0; + auto bot_gender = MALE; if (sep->IsNumber(4)) { - bot_gender = static_cast(std::stoul(sep->arg[4])); + bot_gender = static_cast(Strings::ToUnsignedInt(sep->arg[4])); + if (bot_gender == NEUTER) { + bot_gender = MALE; + } } else { if (!strcasecmp(sep->arg[4], "m") || !strcasecmp(sep->arg[4], "male")) { - bot_gender = 0; + bot_gender = MALE; } else if (!strcasecmp(sep->arg[4], "f") || !strcasecmp(sep->arg[4], "female")) { - bot_gender = 1; + bot_gender = FEMALE; } } @@ -5639,7 +5658,7 @@ void bot_subcommand_bot_details(Client *c, const Seperator *sep) return; } - uint32 uvalue = atoi(sep->arg[1]); + uint32 uvalue = Strings::ToInt(sep->arg[1]); auto fail_type = BCEnum::AFT_None; if (my_bot->GetRace() != DRAKKIN) @@ -5674,7 +5693,7 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep) return; } - if (helper_is_help_or_usage(sep->arg[1])) { + if (helper_is_help_or_usage(sep->arg[1]) || !sep->arg[1] || (sep->arg[1] && !Strings::IsNumber(sep->arg[1]))) { c->Message( Chat::White, fmt::format( @@ -5692,7 +5711,7 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep) bool dye_all = (sep->arg[1][0] == '*'); if (!dye_all) { - material_slot = std::stoi(sep->arg[1]); + material_slot = Strings::ToInt(sep->arg[1]); slot_id = EQ::InventoryProfile::CalcSlotFromMaterial(material_slot); if (!sep->IsNumber(1) || slot_id == INVALID_INDEX || material_slot > EQ::textures::LastTintableTexture) { @@ -5707,7 +5726,7 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep) return; } - uint32 red_value = std::stoul(sep->arg[2]); + uint32 red_value = Strings::ToUnsignedInt(sep->arg[2]); if (red_value > 255) { red_value = 255; } @@ -5717,7 +5736,7 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep) return; } - uint32 green_value = std::stoul(sep->arg[3]); + uint32 green_value = Strings::ToUnsignedInt(sep->arg[3]); if (green_value > 255) { green_value = 255; } @@ -5727,7 +5746,7 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep) return; } - uint32 blue_value = std::stoul(sep->arg[4]); + uint32 blue_value = Strings::ToUnsignedInt(sep->arg[4]); if (blue_value > 255) { blue_value = 255; } @@ -5807,7 +5826,7 @@ void bot_subcommand_bot_eyes(Client *c, const Seperator *sep) return; } - uint8 uvalue = atoi(sep->arg[1]); + uint8 uvalue = Strings::ToInt(sep->arg[1]); //uint8 eye_bias = 0; //std::string arg2 = sep->arg[2]; @@ -5861,7 +5880,7 @@ void bot_subcommand_bot_face(Client *c, const Seperator *sep) return; } - uint8 uvalue = atoi(sep->arg[1]); + uint8 uvalue = Strings::ToInt(sep->arg[1]); auto fail_type = BCEnum::AFT_None; if (!PlayerAppearance::IsValidFace(my_bot->GetRace(), my_bot->GetGender(), uvalue)) { @@ -5901,7 +5920,7 @@ void bot_subcommand_bot_follow_distance(Client *c, const Seperator *sep) return; } - bfd = atoi(sep->arg[2]); + bfd = Strings::ToInt(sep->arg[2]); if (bfd < 1) bfd = 1; if (bfd > BOT_FOLLOW_DISTANCE_DEFAULT_MAX) @@ -5967,7 +5986,7 @@ void bot_subcommand_bot_hair_color(Client *c, const Seperator *sep) return; } - uint8 uvalue = atoi(sep->arg[1]); + uint8 uvalue = Strings::ToInt(sep->arg[1]); auto fail_type = BCEnum::AFT_None; if (!PlayerAppearance::IsValidHairColor(my_bot->GetRace(), my_bot->GetGender(), uvalue)) @@ -6002,7 +6021,7 @@ void bot_subcommand_bot_hairstyle(Client *c, const Seperator *sep) return; } - uint8 uvalue = atoi(sep->arg[1]); + uint8 uvalue = Strings::ToInt(sep->arg[1]); auto fail_type = BCEnum::AFT_None; if (!PlayerAppearance::IsValidHair(my_bot->GetRace(), my_bot->GetGender(), uvalue)) @@ -6039,7 +6058,7 @@ void bot_subcommand_bot_heritage(Client *c, const Seperator *sep) return; } - uint32 uvalue = atoi(sep->arg[1]); + uint32 uvalue = Strings::ToInt(sep->arg[1]); auto fail_type = BCEnum::AFT_None; if (my_bot->GetRace() != DRAKKIN) @@ -6176,13 +6195,13 @@ void bot_subcommand_bot_list(Client *c, const Seperator *sep) if (!strcasecmp(sep->arg[i], "class")) { filter_mask |= MaskClass; - filter_value[FilterClass] = atoi(sep->arg[i + 1]); + filter_value[FilterClass] = Strings::ToInt(sep->arg[i + 1]); continue; } if (!strcasecmp(sep->arg[i], "race")) { filter_mask |= MaskRace; - filter_value[FilterRace] = atoi(sep->arg[i + 1]); + filter_value[FilterRace] = Strings::ToInt(sep->arg[i + 1]); continue; } @@ -6510,8 +6529,7 @@ void bot_subcommand_bot_spawn(Client *c, const Seperator *sep) return; } - if (c->GetFeigned()) { - c->Message(Chat::White, "You cannot spawn a bot while feigned."); + if (!Bot::CheckSpawnConditions(c)) { return; } @@ -6625,39 +6643,6 @@ void bot_subcommand_bot_spawn(Client *c, const Seperator *sep) return; } - // this probably needs work... - if (c->GetGroup()) { - std::list group_list; - c->GetGroup()->GetMemberList(group_list); - for (auto member_iter : group_list) { - if (!member_iter) { - continue; - } - - if (member_iter->qglobal) { // what is this?? really should have had a message to describe failure... (can't spawn bots if you are assigned to a task/instance?) - return; - } - - if ( - !member_iter->qglobal && - member_iter->GetAppearance() != eaDead && - ( - member_iter->IsEngaged() || - ( - member_iter->IsClient() && - member_iter->CastToClient()->GetAggroCount() - ) - ) - ) { - c->Message(Chat::White, "You cannot summon bots while you are engaged."); - return; - } - } - } else if (c->GetAggroCount()) { - c->Message(Chat::White, "You cannot spawn bots while you are engaged."); - return; - } - auto my_bot = Bot::LoadBot(bot_id); if (!my_bot) { c->Message( @@ -6743,7 +6728,7 @@ void bot_subcommand_bot_stance(Client *c, const Seperator *sep) if (!strcasecmp(sep->arg[1], "current")) current_flag = true; else if (sep->IsNumber(1)) { - bst = (EQ::constants::StanceType)atoi(sep->arg[1]); + bst = (EQ::constants::StanceType)Strings::ToInt(sep->arg[1]); if (bst < EQ::constants::stanceUnknown || bst > EQ::constants::stanceBurnAE) bst = EQ::constants::stanceUnknown; } @@ -6802,7 +6787,7 @@ void bot_subcommand_bot_stop_melee_level(Client *c, const Seperator *sep) uint8 sml = RuleI(Bots, CasterStopMeleeLevel); if (sep->IsNumber(1)) { - sml = atoi(sep->arg[1]); + sml = Strings::ToInt(sep->arg[1]); } else if (!strcasecmp(sep->arg[1], "sync")) { sml = my_bot->GetLevel(); @@ -6908,7 +6893,7 @@ void bot_subcommand_bot_tattoo(Client *c, const Seperator *sep) return; } - uint32 uvalue = atoi(sep->arg[1]); + uint32 uvalue = Strings::ToInt(sep->arg[1]); auto fail_type = BCEnum::AFT_None; if (my_bot->GetRace() != DRAKKIN) @@ -7152,7 +7137,7 @@ void bot_subcommand_bot_woad(Client *c, const Seperator *sep) return; } - uint8 uvalue = atoi(sep->arg[1]); + uint8 uvalue = Strings::ToInt(sep->arg[1]); auto fail_type = BCEnum::AFT_None; if (my_bot->GetRace() != BARBARIAN) { @@ -7192,7 +7177,13 @@ void bot_subcommand_botgroup_add_member(Client *c, const Seperator *sep) std::list sbl; MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[1]); if (sbl.empty()) { - c->Message(Chat::White, "You must name a new member as a bot that you own to use this command."); + c->Message( + Chat::White, + fmt::format( + "Usage: () {} [member_name]", + sep->arg[0] + ).c_str() + ); return; } @@ -7720,7 +7711,7 @@ void bot_subcommand_botgroup_list(Client *c, const Seperator *sep) return; } - std::list> botgroups_list; + std::list> botgroups_list; if (!database.botdb.LoadBotGroupsListByOwnerID(c->CharacterID(), botgroups_list)) { c->Message(Chat::White, "Failed to load bot-group."); return; @@ -7733,17 +7724,17 @@ void bot_subcommand_botgroup_list(Client *c, const Seperator *sep) uint32 botgroup_count = 0; - for (auto botgroups_iter : botgroups_list) { + for (const auto& [group_name, group_leader_id] : botgroups_list) { c->Message( Chat::White, fmt::format( "Bot-group {} | Name: {} | Leader: {}{} | {}", (botgroup_count + 1), - botgroups_iter.first, - botgroups_iter.second, - database.botdb.IsBotGroupAutoSpawn(botgroups_iter.first) ? " (Auto Spawn)" : "", + group_name, + database.botdb.GetBotNameByID(group_leader_id), + database.botdb.IsBotGroupAutoSpawn(group_name) ? " (Auto Spawn)" : "", Saylink::Silent( - fmt::format("^botgroupload {}", botgroups_iter.first), + fmt::format("^botgroupload {}", group_name), "Load" ) ).c_str() @@ -7796,30 +7787,10 @@ void bot_subcommand_botgroup_load(Client *c, const Seperator *sep) return; } - if (c->GetFeigned()) { - c->Message(Chat::White, "You cannot spawn a bot-group while feigned."); + if (!Bot::CheckSpawnConditions(c)) { return; } - auto* owner_group = c->GetGroup(); - if (owner_group) { - std::list member_list; - owner_group->GetClientList(member_list); - member_list.remove(nullptr); - - for (auto member_iter : member_list) { - if (member_iter->IsEngaged() || member_iter->GetAggroCount() > 0) { - c->Message(Chat::White, "You cannot spawn bots while your group is engaged,"); - return; - } - } - } else { - if (c->GetAggroCount() > 0) { - c->Message(Chat::White, "You cannot spawn bots while you are engaged,"); - return; - } - } - uint32 botgroup_id = 0; if (!database.botdb.LoadBotGroupIDForLoadBotGroup(c->CharacterID(), botgroup_name, botgroup_id) || !botgroup_id) { c->Message( @@ -8214,7 +8185,7 @@ void bot_subcommand_heal_rotation_adjust_critical(Client *c, const Seperator *se uint8 armor_type_value = 255; if (sep->IsNumber(1)) - armor_type_value = atoi(armor_type_arg.c_str()); + armor_type_value = Strings::ToInt(armor_type_arg.c_str()); if (armor_type_value > ARMOR_TYPE_LAST) { c->Message(Chat::White, "You must specify a valid [armor_type: %u-%u] to use this command", ARMOR_TYPE_FIRST, ARMOR_TYPE_LAST); @@ -8243,7 +8214,7 @@ void bot_subcommand_heal_rotation_adjust_critical(Client *c, const Seperator *se float critical_ratio = CRITICAL_HP_RATIO_BASE; if (sep->IsNumber(2)) - critical_ratio = atof(critical_arg.c_str()); + critical_ratio = Strings::ToFloat(critical_arg.c_str()); else if (!critical_arg.compare("+")) critical_ratio = (*current_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(armor_type_value) + HP_RATIO_DELTA; else if (!critical_arg.compare("-")) @@ -8280,7 +8251,7 @@ void bot_subcommand_heal_rotation_adjust_safe(Client *c, const Seperator *sep) uint8 armor_type_value = 255; if (sep->IsNumber(1)) - armor_type_value = atoi(armor_type_arg.c_str()); + armor_type_value = Strings::ToInt(armor_type_arg.c_str()); if (armor_type_value > ARMOR_TYPE_LAST) { c->Message(Chat::White, "You must specify a valid [armor_type: %u-%u] to use this command", ARMOR_TYPE_FIRST, ARMOR_TYPE_LAST); @@ -8309,7 +8280,7 @@ void bot_subcommand_heal_rotation_adjust_safe(Client *c, const Seperator *sep) float safe_ratio = SAFE_HP_RATIO_BASE; if (sep->IsNumber(2)) - safe_ratio = atof(safe_arg.c_str()); + safe_ratio = Strings::ToFloat(safe_arg.c_str()); else if (!safe_arg.compare("+")) safe_ratio = (*current_member->MemberOfHealRotation())->ArmorTypeSafeHPRatio(armor_type_value) + HP_RATIO_DELTA; else if (!safe_arg.compare("-")) @@ -8423,7 +8394,7 @@ void bot_subcommand_heal_rotation_change_interval(Client *c, const Seperator *se uint32 hr_change_interval_s = CASTING_CYCLE_DEFAULT_INTERVAL_S; if (!change_interval_arg.empty()) { - hr_change_interval_s = atoi(change_interval_arg.c_str()); + hr_change_interval_s = Strings::ToInt(change_interval_arg.c_str()); } else { hr_change_interval_s = (*current_member->MemberOfHealRotation())->IntervalS(); @@ -8571,14 +8542,14 @@ void bot_subcommand_heal_rotation_create(Client *c, const Seperator *sep) hr_adaptive_targeting = true; if (!fast_heals_arg.compare("on")) hr_fast_heals = true; - hr_interval_s = atoi(interval_arg.c_str()); + hr_interval_s = Strings::ToInt(interval_arg.c_str()); } else if (!casting_override_arg.compare("off")) { if (!adaptive_targeting_arg.compare("on")) hr_adaptive_targeting = true; if (!fast_heals_arg.compare("on")) hr_fast_heals = true; - hr_interval_s = atoi(interval_arg.c_str()); + hr_interval_s = Strings::ToInt(interval_arg.c_str()); } if (hr_interval_s < CASTING_CYCLE_MINIMUM_INTERVAL_S || hr_interval_s > CASTING_CYCLE_MAXIMUM_INTERVAL_S) @@ -9301,13 +9272,13 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) return; } - auto slot_id = static_cast(std::stoul(sep->arg[1])); + auto slot_id = static_cast(Strings::ToUnsignedInt(sep->arg[1])); if (slot_id > EQ::invslot::EQUIPMENT_END || slot_id < EQ::invslot::EQUIPMENT_BEGIN) { c->Message(Chat::White, "Valid slots are 0 to 22."); return; } - const auto* inst = my_bot->GetBotItem(slot_id); + auto* inst = my_bot->GetBotItem(slot_id); if (!inst) { std::string slot_message = "is"; switch (slot_id) { @@ -9391,6 +9362,18 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) slot_id ) ); + + if (parse->BotHasQuestSub(EVENT_UNEQUIP_ITEM_BOT)) { + const auto& export_string = fmt::format( + "{} {}", + inst->IsStackable() ? inst->GetCharges() : 1, + slot_id + ); + + std::vector args = { inst }; + + parse->EventBot(EVENT_UNEQUIP_ITEM_BOT, my_bot, nullptr, export_string, inst->GetID(), &args); + } } } @@ -9910,17 +9893,18 @@ uint32 helper_bot_create(Client *bot_owner, std::string bot_name, uint8 bot_clas ); bot_id = my_bot->GetBotID(); + if (parse->PlayerHasQuestSub(EVENT_BOT_CREATE)) { + const auto& export_string = fmt::format( + "{} {} {} {} {}", + bot_name, + bot_id, + bot_race, + bot_class, + bot_gender + ); - const auto export_string = fmt::format( - "{} {} {} {} {}", - bot_name, - bot_id, - bot_race, - bot_class, - bot_gender - ); - - parse->EventPlayer(EVENT_BOT_CREATE, bot_owner, export_string, 0); + parse->EventPlayer(EVENT_BOT_CREATE, bot_owner, export_string, 0); + } safe_delete(my_bot); @@ -10052,7 +10036,7 @@ bool helper_cast_standard_spell(Bot* casting_bot, Mob* target_mob, int spell_id, bool helper_command_disabled(Client* bot_owner, bool rule_value, const char* command) { - if (rule_value == false) { + if (rule_value) { bot_owner->Message(Chat::White, "Bot command %s is not enabled on this server.", command); return true; } @@ -10116,8 +10100,7 @@ void helper_command_depart_list(Client* bot_owner, Bot* druid_bot, Bot* wizard_b } msg = fmt::format( - "{}circle {}{}", - std::to_string(BOT_COMMAND_CHAR), + "^circle {}{}", spells[local_entry->spell_id].teleport_zone, single_flag ? " single" : "" ); @@ -10152,8 +10135,7 @@ void helper_command_depart_list(Client* bot_owner, Bot* druid_bot, Bot* wizard_b } msg = fmt::format( - "{}portal {}{}", - std::to_string(BOT_COMMAND_CHAR), + "^portal {}{}", spells[local_entry->spell_id].teleport_zone, single_flag ? " single" : "" ); @@ -10218,7 +10200,15 @@ void helper_send_available_subcommands(Client *bot_owner, const char* command_si if (bot_owner->Admin() < find_iter->second->access) continue; - bot_owner->Message(Chat::White, "%c%s - %s", BOT_COMMAND_CHAR, subcommand_iter, ((find_iter != bot_command_list.end()) ? (find_iter->second->desc) : ("[no description]"))); + bot_owner->Message( + Chat::White, + fmt::format( + "^{} - {}", + subcommand_iter, + find_iter != bot_command_list.end() ? find_iter->second->desc : "No Description" + ).c_str() + ); + ++bot_subcommands_shown; } @@ -10280,7 +10270,7 @@ void bot_command_spell_list(Client* c, const Seperator *sep) uint8 min_level = 0; if (sep->IsNumber(1)) { - min_level = static_cast(std::stoul(sep->arg[1])); + min_level = static_cast(Strings::ToUnsignedInt(sep->arg[1])); } my_bot->ListBotSpells(min_level); @@ -10327,7 +10317,7 @@ void bot_command_spell_settings_add(Client *c, const Seperator *sep) return; } - auto spell_id = static_cast(std::stoul(sep->arg[1])); + auto spell_id = static_cast(Strings::ToUnsignedInt(sep->arg[1])); if (!IsValidSpell(spell_id)) { c->Message( @@ -10354,9 +10344,9 @@ void bot_command_spell_settings_add(Client *c, const Seperator *sep) return; } - auto priority = static_cast(std::stoi(sep->arg[2])); - auto min_hp = static_cast(EQ::Clamp(std::stoi(sep->arg[3]), -1, 99)); - auto max_hp = static_cast(EQ::Clamp(std::stoi(sep->arg[4]), -1, 100)); + auto priority = static_cast(Strings::ToInt(sep->arg[2])); + auto min_hp = static_cast(EQ::Clamp(Strings::ToInt(sep->arg[3]), -1, 99)); + auto max_hp = static_cast(EQ::Clamp(Strings::ToInt(sep->arg[4]), -1, 100)); BotSpellSetting bs; @@ -10442,7 +10432,7 @@ void bot_command_spell_settings_delete(Client *c, const Seperator *sep) return; } - auto spell_id = static_cast(std::stoul(sep->arg[1])); + auto spell_id = static_cast(Strings::ToUnsignedInt(sep->arg[1])); if (!IsValidSpell(spell_id)) { c->Message( @@ -10550,7 +10540,7 @@ void bot_command_spell_settings_toggle(Client *c, const Seperator *sep) return; } - auto spell_id = static_cast(std::stoul(sep->arg[1])); + auto spell_id = static_cast(Strings::ToUnsignedInt(sep->arg[1])); if (!IsValidSpell(spell_id)) { c->Message( Chat::White, @@ -10564,7 +10554,7 @@ void bot_command_spell_settings_toggle(Client *c, const Seperator *sep) bool toggle = ( sep->IsNumber(2) ? - (std::stoi(sep->arg[2]) ? true : false) : + Strings::ToInt(sep->arg[2]) != 0 : atobool(sep->arg[2]) ); @@ -10655,7 +10645,7 @@ void bot_command_spell_settings_update(Client *c, const Seperator *sep) return; } - auto spell_id = static_cast(std::stoul(sep->arg[1])); + auto spell_id = static_cast(Strings::ToUnsignedInt(sep->arg[1])); if (!IsValidSpell(spell_id)) { c->Message( @@ -10668,9 +10658,9 @@ void bot_command_spell_settings_update(Client *c, const Seperator *sep) return; } - auto priority = static_cast(std::stoi(sep->arg[2])); - auto min_hp = static_cast(EQ::Clamp(std::stoi(sep->arg[3]), -1, 99)); - auto max_hp = static_cast(EQ::Clamp(std::stoi(sep->arg[4]), -1, 100)); + auto priority = static_cast(Strings::ToInt(sep->arg[2])); + auto min_hp = static_cast(EQ::Clamp(Strings::ToInt(sep->arg[3]), -1, 99)); + auto max_hp = static_cast(EQ::Clamp(Strings::ToInt(sep->arg[4]), -1, 100)); BotSpellSetting bs; @@ -10745,7 +10735,7 @@ void bot_spell_info_dialogue_window(Client* c, const Seperator *sep) return; } - auto spell_id = static_cast(std::stoul(sep->arg[1])); + auto spell_id = static_cast(Strings::ToUnsignedInt(sep->arg[1])); auto min_level = spells[spell_id].classes; auto class_level = min_level[my_bot->GetBotClass() - 1]; @@ -10822,3 +10812,53 @@ void bot_command_enforce_spell_list(Client* c, const Seperator *sep) ).c_str() ); } + +void bot_command_caster_range(Client* c, const Seperator* sep) +{ + if (helper_command_alias_fail(c, "bot_command_caster_range", sep->arg[0], "casterrange")) { + return; + } + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(Chat::White, "usage: %s [current | value: 0 - 300].", sep->arg[0]); + c->Message(Chat::White, "note: Can only be used for Casters or Hybrids."); + c->Message(Chat::White, "note: Use [current] to check the current setting."); + c->Message(Chat::White, "note: Set the value to the minimum distance you want your bot to try to remain from its target."); + c->Message(Chat::White, "note: If they are too far for a spell, it will be skipped."); + return; + } + + auto my_bot = ActionableBots::AsTarget_ByBot(c); + if (!my_bot) { + c->Message(Chat::White, "You must a bot that you own to use this command."); + return; + } + if (!IsCasterClass(my_bot->GetClass()) && !IsHybridClass(my_bot->GetClass())) { + c->Message(Chat::White, "You must a caster or hybrid class to use this command."); + return; + } + + uint32 crange = 0; + if (sep->IsNumber(1)) { + crange = atoi(sep->arg[1]); + if (crange >= 0 && crange <= 300) { + my_bot->SetBotCasterRange(crange); + if (!database.botdb.SaveBotCasterRange(c->CharacterID(), my_bot->GetBotID(), crange)) { + c->Message(Chat::White, "%s for '%s'", BotDatabase::fail::SaveBotCasterRange(), my_bot->GetCleanName()); + return; + } + else { + c->Message(Chat::White, "Successfully set Caster Range for %s to %u.", my_bot->GetCleanName(), crange); + } + } + else { + c->Message(Chat::White, "You must enter a value within the range of 0 - 300."); + return; + } + } + else if (!strcasecmp(sep->arg[1], "current")) { + c->Message(Chat::White, "My current range is %u.", my_bot->GetBotCasterRange()); + } + else { + c->Message(Chat::White, "Incorrect argument, use help for a list of options."); + } +} diff --git a/zone/bot_command.h b/zone/bot_command.h index 270631ebd..723597df7 100644 --- a/zone/bot_command.h +++ b/zone/bot_command.h @@ -543,7 +543,6 @@ void bot_command_deinit(void); int bot_command_add(std::string bot_command_name, const char *desc, int access, BotCmdFuncPtr function); int bot_command_not_avail(Client *c, const char *message); int bot_command_real_dispatch(Client *c, char const *message); -void bot_command_log_command(Client *c, const char *message); // Bot Commands void bot_command_actionable(Client *c, const Seperator *sep); @@ -554,6 +553,7 @@ void bot_command_attack(Client *c, const Seperator *sep); void bot_command_bind_affinity(Client *c, const Seperator *sep); void bot_command_bot(Client *c, const Seperator *sep); void bot_command_botgroup(Client *c, const Seperator *sep); +void bot_command_caster_range(Client* c, const Seperator* sep); void bot_command_charm(Client *c, const Seperator *sep); void bot_command_cure(Client *c, const Seperator *sep); void bot_command_defensive(Client *c, const Seperator *sep); @@ -639,7 +639,6 @@ void bot_subcommand_botgroup_list(Client *c, const Seperator *sep); void bot_subcommand_botgroup_load(Client *c, const Seperator *sep); void bot_subcommand_botgroup_remove_member(Client *c, const Seperator *sep); void bot_subcommand_circle(Client *c, const Seperator *sep); -void bot_subcommand_evacuate(Client *c, const Seperator *sep); void bot_subcommand_heal_rotation_adaptive_targeting(Client *c, const Seperator *sep); void bot_subcommand_heal_rotation_add_member(Client *c, const Seperator *sep); void bot_subcommand_heal_rotation_add_target(Client *c, const Seperator *sep); @@ -668,7 +667,6 @@ void bot_subcommand_pet_get_lost(Client *c, const Seperator *sep); void bot_subcommand_pet_remove(Client *c, const Seperator *sep); void bot_subcommand_pet_set_type(Client *c, const Seperator *sep); void bot_subcommand_portal(Client *c, const Seperator *sep); -void bot_subcommand_succor(Client *c, const Seperator *sep); // bot command helpers diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index 600daab42..a12e4e6dd 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -43,7 +43,7 @@ bool BotDatabase::LoadBotCommandSettings(std::map= Bot::SPELL_TYPE_COUNT) continue; - uint8 class_index = atoi(row[1]); + uint8 class_index = Strings::ToInt(row[1]); if (class_index < WARRIOR || class_index > BERSERKER) continue; --class_index; - uint8 stance_index = atoi(row[2]); + uint8 stance_index = Strings::ToInt(row[2]); if (stance_index >= EQ::constants::STANCE_TYPE_COUNT) continue; for (uint8 conditional_index = nHSND; conditional_index < cntHSND; ++conditional_index) { - uint8 value = atoi(row[3 + conditional_index]); + uint8 value = Strings::ToInt(row[3 + conditional_index]); if (!value) continue; if (value > 100) @@ -173,13 +173,23 @@ bool BotDatabase::QueryNameAvailablity(const std::string& bot_name, bool& availa query = fmt::format( "SELECT b.bot_id FROM bot_data b " - "INNER JOIN character_data c ON b.`name` = c.`name` " - "WHERE b.`name` LIKE '{0}' OR c.`name` LIKE '{0}' " + "WHERE b.`name` LIKE '{}' " "LIMIT 1", bot_name ); auto results = database.QueryDatabase(query); + + if (!results.RowCount()) { + query = fmt::format( + "SELECT c.id FROM character_data c " + "WHERE c.`name` LIKE '{}' " + "LIMIT 1", + bot_name + ); + results = database.QueryDatabase(query); + } + if (!results.Success()) { return false; } @@ -213,7 +223,7 @@ bool BotDatabase::QueryBotCount(const uint32 owner_id, int class_id, uint32& bot } auto row = results.begin(); - bot_count = std::stoul(row[0]); + bot_count = Strings::ToUnsignedInt(row[0]); if (EQ::ValueWithin(class_id, WARRIOR, BERSERKER)) { query = fmt::format( @@ -231,7 +241,7 @@ bool BotDatabase::QueryBotCount(const uint32 owner_id, int class_id, uint32& bot } auto row = results.begin(); - bot_class_count = std::stoul(row[0]); + bot_class_count = Strings::ToUnsignedInt(row[0]); } return true; @@ -259,7 +269,7 @@ bool BotDatabase::LoadBotsList(const uint32 owner_id, std::list(std::stoul(row[1])); + bot_id = Strings::ToUnsignedInt(row[0]); + bot_class_id = static_cast(Strings::ToUnsignedInt(row[1])); return true; } @@ -475,6 +485,8 @@ bool BotDatabase::LoadBot(const uint32 bot_id, Bot*& loaded_bot) loaded_bot->SetBotEnforceSpellSetting((l.enforce_spell_settings ? true : false)); loaded_bot->SetBotArcherySetting((l.archery_setting ? true : false)); + + loaded_bot->SetBotCasterRange(l.caster_range); } return true; @@ -535,6 +547,7 @@ bool BotDatabase::SaveNewBot(Bot* bot_inst, uint32& bot_id) e.expansion_bitmask = bot_inst->GetExpansionBitmask(); e.enforce_spell_settings = bot_inst->GetBotEnforceSpellSetting(); e.archery_setting = bot_inst->IsBotArcher() ? 1 : 0; + e.caster_range = bot_inst->GetBotCasterRange(); auto b = BotDataRepository::InsertOne(database, e); if (!b.bot_id) { @@ -629,10 +642,11 @@ bool BotDatabase::DeleteBot(const uint32 bot_id) bool BotDatabase::LoadBuffs(Bot* bot_inst) { - if (!bot_inst) + if (!bot_inst) { return false; + } - query = StringFormat( + query = fmt::format( "SELECT" " `spell_id`," " `caster_level`," @@ -653,45 +667,58 @@ bool BotDatabase::LoadBuffs(Bot* bot_inst) " `extra_di_chance`," " `instrument_mod`" " FROM `bot_buffs`" - " WHERE `bot_id` = '%u'", + " WHERE `bot_id` = {}", bot_inst->GetBotID() ); auto results = database.QueryDatabase(query); - if (!results.Success()) + + if (!results.Success()) { return false; - if (!results.RowCount()) + } + + if (!results.RowCount()) { return true; + } Buffs_Struct* bot_buffs = bot_inst->GetBuffs(); - if (!bot_buffs) + + if (!bot_buffs) { return false; + } + + uint32 max_slots = bot_inst->GetMaxBuffSlots(); + for (int index = 0; index < max_slots; index++) { + bot_buffs[index].spellid = SPELL_UNKNOWN; + } int buff_count = 0; for (auto row = results.begin(); row != results.end() && buff_count < BUFF_COUNT; ++row) { - bot_buffs[buff_count].spellid = atoi(row[0]); - bot_buffs[buff_count].casterlevel = atoi(row[1]); + bot_buffs[buff_count].spellid = Strings::ToUnsignedInt(row[0]); + bot_buffs[buff_count].casterlevel = Strings::ToUnsignedInt(row[1]); //row[2] (duration_formula) can probably be removed - bot_buffs[buff_count].ticsremaining = atoi(row[3]); + bot_buffs[buff_count].ticsremaining = Strings::ToInt(row[3]); - if (CalculatePoisonCounters(bot_buffs[buff_count].spellid) > 0) - bot_buffs[buff_count].counters = atoi(row[4]); - else if (CalculateDiseaseCounters(bot_buffs[buff_count].spellid) > 0) - bot_buffs[buff_count].counters = atoi(row[5]); - else if (CalculateCurseCounters(bot_buffs[buff_count].spellid) > 0) - bot_buffs[buff_count].counters = atoi(row[6]); - else if (CalculateCorruptionCounters(bot_buffs[buff_count].spellid) > 0) - bot_buffs[buff_count].counters = atoi(row[7]); + bot_buffs[buff_count].counters = 0; + if (CalculatePoisonCounters(bot_buffs[buff_count].spellid) > 0) { + bot_buffs[buff_count].counters = Strings::ToUnsignedInt(row[4]); + } else if (CalculateDiseaseCounters(bot_buffs[buff_count].spellid) > 0) { + bot_buffs[buff_count].counters = Strings::ToUnsignedInt(row[5]); + } else if (CalculateCurseCounters(bot_buffs[buff_count].spellid) > 0) { + bot_buffs[buff_count].counters = Strings::ToUnsignedInt(row[6]); + } else if (CalculateCorruptionCounters(bot_buffs[buff_count].spellid) > 0) { + bot_buffs[buff_count].counters = Strings::ToUnsignedInt(row[7]); + } - bot_buffs[buff_count].hit_number = atoi(row[8]); - bot_buffs[buff_count].melee_rune = atoi(row[9]); - bot_buffs[buff_count].magic_rune = atoi(row[10]); - bot_buffs[buff_count].dot_rune = atoi(row[11]); - bot_buffs[buff_count].persistant_buff = ((atoi(row[12])) ? (true) : (false)); - bot_buffs[buff_count].caston_x = atoi(row[13]); - bot_buffs[buff_count].caston_y = atoi(row[14]); - bot_buffs[buff_count].caston_z = atoi(row[15]); - bot_buffs[buff_count].ExtraDIChance = atoi(row[16]); - bot_buffs[buff_count].instrument_mod = atoi(row[17]); + bot_buffs[buff_count].hit_number = Strings::ToUnsignedInt(row[8]); + bot_buffs[buff_count].melee_rune = Strings::ToUnsignedInt(row[9]); + bot_buffs[buff_count].magic_rune = Strings::ToUnsignedInt(row[10]); + bot_buffs[buff_count].dot_rune = Strings::ToUnsignedInt(row[11]); + bot_buffs[buff_count].persistant_buff = (Strings::ToBool(row[12])) != 0; + bot_buffs[buff_count].caston_x = Strings::ToInt(row[13]); + bot_buffs[buff_count].caston_y = Strings::ToInt(row[14]); + bot_buffs[buff_count].caston_z = Strings::ToInt(row[15]); + bot_buffs[buff_count].ExtraDIChance = Strings::ToInt(row[16]); + bot_buffs[buff_count].instrument_mod = Strings::ToUnsignedInt(row[17]); bot_buffs[buff_count].casterid = 0; ++buff_count; } @@ -812,7 +839,7 @@ bool BotDatabase::LoadStance(const uint32 bot_id, int& bot_stance) return true; auto row = results.begin(); - bot_stance = atoi(row[0]); + bot_stance = Strings::ToInt(row[0]); return true; } @@ -832,7 +859,7 @@ bool BotDatabase::LoadStance(Bot* bot_inst, bool& stance_flag) return true; auto row = results.begin(); - bot_inst->SetBotStance((EQ::constants::StanceType)atoi(row[0])); + bot_inst->SetBotStance((EQ::constants::StanceType)Strings::ToInt(row[0])); stance_flag = true; return true; @@ -925,9 +952,9 @@ bool BotDatabase::LoadTimers(Bot* bot_inst) uint32 timer_value = 0; uint32 max_value = 0; for (auto row = results.begin(); row != results.end(); ++row) { - timer_id = atoi(row[0]) - 1; - timer_value = atoi(row[1]); - max_value = atoi(row[2]); + timer_id = Strings::ToInt(row[0]) - 1; + timer_value = Strings::ToInt(row[1]); + max_value = Strings::ToInt(row[2]); if (timer_id >= 0 && timer_id < MaxTimer && timer_value < (Timer::GetCurrentTime() + max_value)) bot_timers[timer_id] = timer_value; @@ -952,7 +979,10 @@ bool BotDatabase::SaveTimers(Bot* bot_inst) if (bot_timers[timer_index] <= Timer::GetCurrentTime()) continue; - query = StringFormat("INSERT INTO `bot_timers` (`bot_id`, `timer_id`, `timer_value`) VALUES ('%u', '%u', '%u')", bot_inst->GetBotID(), (timer_index + 1), bot_timers[timer_index]); + query = fmt::format( + "REPLACE INTO `bot_timers` (`bot_id`, `timer_id`, `timer_value`) VALUES ('{}', '{}', '{}')", + bot_inst->GetBotID(), (timer_index + 1), bot_timers[timer_index] + ); auto results = database.QueryDatabase(query); if (!results.Success()) { DeleteTimers(bot_inst->GetBotID()); @@ -990,7 +1020,7 @@ bool BotDatabase::QueryInventoryCount(const uint32 bot_id, uint32& item_count) return true; auto row = results.begin(); - item_count = atoi(row[0]); + item_count = Strings::ToInt(row[0]); return true; } @@ -1029,22 +1059,22 @@ bool BotDatabase::LoadItems(const uint32 bot_id, EQ::InventoryProfile& inventory return true; for (auto row = results.begin(); row != results.end(); ++row) { - int16 slot_id = atoi(row[0]); + int16 slot_id = Strings::ToInt(row[0]); if (slot_id < EQ::invslot::EQUIPMENT_BEGIN || slot_id > EQ::invslot::EQUIPMENT_END) continue; - uint32 item_id = atoi(row[1]); - uint16 item_charges = (uint16)atoi(row[2]); + uint32 item_id = Strings::ToInt(row[1]); + uint16 item_charges = (uint16)Strings::ToInt(row[2]); EQ::ItemInstance* item_inst = database.CreateItem( item_id, item_charges, - (uint32)atoul(row[9]), - (uint32)atoul(row[10]), - (uint32)atoul(row[11]), - (uint32)atoul(row[12]), - (uint32)atoul(row[13]), - (uint32)atoul(row[14]) + (uint32)Strings::ToUnsignedInt(row[9]), + (uint32)Strings::ToUnsignedInt(row[10]), + (uint32)Strings::ToUnsignedInt(row[11]), + (uint32)Strings::ToUnsignedInt(row[12]), + (uint32)Strings::ToUnsignedInt(row[13]), + (uint32)Strings::ToUnsignedInt(row[14]) ); if (!item_inst) { LogError("Warning: bot_id [{}] has an invalid item_id [{}] in inventory slot [{}]", bot_id, item_id, slot_id); @@ -1058,12 +1088,12 @@ bool BotDatabase::LoadItems(const uint32 bot_id, EQ::InventoryProfile& inventory else item_inst->SetCharges(item_charges); - uint32 item_color = atoul(row[3]); + uint32 item_color = Strings::ToUnsignedInt(row[3]); if (item_color > 0) item_inst->SetColor(item_color); if (item_inst->GetItem()->Attuneable) { - if (atoi(row[4])) + if (Strings::ToInt(row[4])) item_inst->SetAttuned(true); else if (slot_id >= EQ::invslot::EQUIPMENT_BEGIN && slot_id <= EQ::invslot::EQUIPMENT_END) item_inst->SetAttuned(true); @@ -1095,9 +1125,9 @@ bool BotDatabase::LoadItems(const uint32 bot_id, EQ::InventoryProfile& inventory } } - item_inst->SetOrnamentIcon((uint32)atoul(row[6])); - item_inst->SetOrnamentationIDFile((uint32)atoul(row[7])); - item_inst->SetOrnamentHeroModel((uint32)atoul(row[8])); + item_inst->SetOrnamentIcon((uint32)Strings::ToUnsignedInt(row[6])); + item_inst->SetOrnamentationIDFile((uint32)Strings::ToUnsignedInt(row[7])); + item_inst->SetOrnamentHeroModel((uint32)Strings::ToUnsignedInt(row[8])); if (inventory_inst.PutItem(slot_id, *item_inst) == INVALID_INDEX) LogError("Warning: Invalid slot_id for item in inventory: bot_id = [{}], item_id = [{}], slot_id = [{}]", bot_id, item_id, slot_id); @@ -1144,7 +1174,7 @@ bool BotDatabase::LoadItemBySlot(const uint32 bot_id, const uint32 slot_id, uint return true; auto row = results.begin(); - item_id = atoi(row[0]); + item_id = Strings::ToInt(row[0]); return true; } @@ -1285,7 +1315,7 @@ bool BotDatabase::LoadEquipmentColor(const uint32 bot_id, const uint8 material_s return true; auto row = results.begin(); - rgb = atoul(row[0]); + rgb = Strings::ToUnsignedInt(row[0]); return true; } @@ -1336,7 +1366,7 @@ bool BotDatabase::LoadPetIndex(const uint32 bot_id, uint32& pet_index) return true; auto row = results.begin(); - pet_index = atoi(row[0]); + pet_index = Strings::ToInt(row[0]); return true; } @@ -1354,7 +1384,7 @@ bool BotDatabase::LoadPetSpellID(const uint32 bot_id, uint32& pet_spell_id) return true; auto row = results.begin(); - pet_spell_id = atoi(row[0]); + pet_spell_id = Strings::ToInt(row[0]); return true; } @@ -1378,10 +1408,10 @@ bool BotDatabase::LoadPetStats(const uint32 bot_id, std::string& pet_name, uint3 return true; auto row = results.begin(); - pet_spell_id = atoi(row[0]); + pet_spell_id = Strings::ToInt(row[0]); pet_name = row[1]; - pet_mana = atoi(row[2]); - pet_hp = atoi(row[3]); + pet_mana = Strings::ToInt(row[2]); + pet_hp = Strings::ToInt(row[3]); return true; } @@ -1467,9 +1497,9 @@ bool BotDatabase::LoadPetBuffs(const uint32 bot_id, SpellBuff_Struct* pet_buffs) int buff_index = 0; for (auto row = results.begin(); row != results.end() && buff_index < PET_BUFF_COUNT; ++row) { - pet_buffs[buff_index].spellid = atoi(row[0]); - pet_buffs[buff_index].level = atoi(row[1]); - pet_buffs[buff_index].duration = atoi(row[2]); + pet_buffs[buff_index].spellid = Strings::ToInt(row[0]); + pet_buffs[buff_index].level = Strings::ToInt(row[1]); + pet_buffs[buff_index].duration = Strings::ToInt(row[2]); // Work around for loading the counters and setting them back to max. Need entry in DB for saved counters if (CalculatePoisonCounters(pet_buffs[buff_index].spellid) > 0) @@ -1504,8 +1534,9 @@ bool BotDatabase::SavePetBuffs(const uint32 bot_id, const SpellBuff_Struct* pet_ return true; for (int buff_index = 0; buff_index < PET_BUFF_COUNT; ++buff_index) { - if (!pet_buffs[buff_index].spellid || pet_buffs[buff_index].spellid == SPELL_UNKNOWN) + if (!IsValidSpell(pet_buffs[buff_index].spellid)) { continue; + } query = StringFormat( "INSERT INTO `bot_pet_buffs` (" @@ -1574,7 +1605,7 @@ bool BotDatabase::LoadPetItems(const uint32 bot_id, uint32* pet_items) int item_index = EQ::invslot::EQUIPMENT_BEGIN; for (auto row = results.begin(); row != results.end() && (item_index >= EQ::invslot::EQUIPMENT_BEGIN && item_index <= EQ::invslot::EQUIPMENT_END); ++row) { - pet_items[item_index] = atoi(row[0]); + pet_items[item_index] = Strings::ToInt(row[0]); ++item_index; } @@ -2114,7 +2145,7 @@ bool BotDatabase::LoadOwnerOptions(Client *owner) for (auto row : results) { - owner->SetBotOption(static_cast(atoul(row[0])), (atoul(row[1]) != 0)); + owner->SetBotOption(static_cast(Strings::ToUnsignedInt(row[0])), (Strings::ToUnsignedInt(row[1]) != 0)); } return true; @@ -2236,7 +2267,7 @@ bool BotDatabase::LoadBotGroupIDByBotGroupName(const std::string& group_name, ui } auto row = results.begin(); - botgroup_id = std::stoul(row[0]); + botgroup_id = Strings::ToUnsignedInt(row[0]); return true; } @@ -2262,7 +2293,7 @@ bool BotDatabase::LoadBotGroupIDByLeaderID(const uint32 leader_id, uint32& botgr } auto row = results.begin(); - botgroup_id = std::stoul(row[0]); + botgroup_id = Strings::ToUnsignedInt(row[0]); return true; } @@ -2288,7 +2319,7 @@ bool BotDatabase::LoadBotGroupIDByMemberID(const uint32 member_id, uint32& botgr } auto row = results.begin(); - botgroup_id = std::stoul(row[0]); + botgroup_id = Strings::ToUnsignedInt(row[0]); return true; } @@ -2314,7 +2345,7 @@ bool BotDatabase::LoadLeaderIDByBotGroupName(const std::string& group_name, uint } auto row = results.begin(); - leader_id = std::stoul(row[0]); + leader_id = Strings::ToUnsignedInt(row[0]); return true; } @@ -2340,7 +2371,7 @@ bool BotDatabase::LoadLeaderIDByBotGroupID(const uint32 group_id, uint32& leader } auto row = results.begin(); - leader_id = std::stoul(row[0]); + leader_id = Strings::ToUnsignedInt(row[0]); return true; } @@ -2348,7 +2379,7 @@ bool BotDatabase::LoadLeaderIDByBotGroupID(const uint32 group_id, uint32& leader bool BotDatabase::LoadBotGroupNameByBotGroupID(const uint32 group_id, std::string& botgroup_name) { if (!group_id) { - false; + return false; } query = fmt::format( @@ -2536,18 +2567,18 @@ bool BotDatabase::RemoveMemberFromBotGroup(const uint32 member_id) return true; } -bool BotDatabase::LoadBotGroupIDForLoadBotGroup(const uint32 owner_id, const std::string& group_name, uint32& botgroup_id) +bool BotDatabase::LoadBotGroupIDForLoadBotGroup(const uint32 owner_id, std::string_view group_name, uint32& botgroup_id) { if (!owner_id || group_name.empty()) { return false; } query = fmt::format( - "SELECT groups_index, group_name FROM " + "SELECT bg.groups_index, group_name FROM " "bot_groups bg INNER JOIN bot_group_members bgm " "ON bg.groups_index = bgm.groups_index " "WHERE bgm.bot_id IN " - "(SELECT bot_id FROM bot_data WHERE WHERE owner_id = {})", + "(SELECT bot_id FROM bot_data WHERE owner_id = {})", owner_id ); @@ -2562,7 +2593,7 @@ bool BotDatabase::LoadBotGroupIDForLoadBotGroup(const uint32 owner_id, const std for (auto row : results) { if (!group_name.compare(row[1])) { - botgroup_id = std::stoul(row[0]); + botgroup_id = Strings::ToUnsignedInt(row[0]); break; } } @@ -2600,13 +2631,13 @@ bool BotDatabase::LoadBotGroup(const std::string& group_name, std::map>& botgroups_list) +bool BotDatabase::LoadBotGroupsListByOwnerID(const uint32 owner_id, std::list>& botgroups_list) { if (!owner_id) { return false; @@ -2614,11 +2645,11 @@ bool BotDatabase::LoadBotGroupsListByOwnerID(const uint32 owner_id, std::list(row[0], row[1])); + botgroups_list.push_back(std::pair(row[0], Strings::ToUnsignedInt(row[1]))); } return true; @@ -2704,7 +2735,7 @@ bool BotDatabase::LoadAutoSpawnBotGroupsByOwnerID(const uint32 owner_id, std::li for (auto row : results) { group_list.push_back( - std::pair(std::stoul(row[0]), row[1]) + std::pair(Strings::ToUnsignedInt(row[0]), row[1]) ); } @@ -2736,7 +2767,7 @@ bool BotDatabase::LoadGroupedBotsByGroupID(const uint32 owner_id, const uint32 g } for (auto row : results) { - group_list.push_back(std::stoul(row[0])); + group_list.push_back(Strings::ToUnsignedInt(row[0])); } return true; @@ -2757,7 +2788,7 @@ bool BotDatabase::LoadHealRotationIDByBotID(const uint32 bot_id, uint32& hr_inde return true; auto row = results.begin(); - hr_index = atoi(row[0]); + hr_index = Strings::ToInt(row[0]); return true; } @@ -2804,20 +2835,20 @@ bool BotDatabase::LoadHealRotation(Bot* hr_member, std::list& member_lis return true; auto row = results.begin(); - (*hr_member->MemberOfHealRotation())->SetIntervalS((uint32)atoi(row[0])); - (*hr_member->MemberOfHealRotation())->SetFastHeals((bool)atoi(row[1])); - (*hr_member->MemberOfHealRotation())->SetAdaptiveTargeting((bool)atoi(row[2])); - (*hr_member->MemberOfHealRotation())->SetCastingOverride((bool)atoi(row[3])); - (*hr_member->MemberOfHealRotation())->SetArmorTypeSafeHPRatio(ARMOR_TYPE_UNKNOWN, atof(row[4])); - (*hr_member->MemberOfHealRotation())->SetArmorTypeSafeHPRatio(ARMOR_TYPE_CLOTH, atof(row[5])); - (*hr_member->MemberOfHealRotation())->SetArmorTypeSafeHPRatio(ARMOR_TYPE_LEATHER, atof(row[6])); - (*hr_member->MemberOfHealRotation())->SetArmorTypeSafeHPRatio(ARMOR_TYPE_CHAIN, atof(row[7])); - (*hr_member->MemberOfHealRotation())->SetArmorTypeSafeHPRatio(ARMOR_TYPE_PLATE, atof(row[8])); - (*hr_member->MemberOfHealRotation())->SetArmorTypeCriticalHPRatio(ARMOR_TYPE_UNKNOWN, atof(row[9])); - (*hr_member->MemberOfHealRotation())->SetArmorTypeCriticalHPRatio(ARMOR_TYPE_CLOTH, atof(row[10])); - (*hr_member->MemberOfHealRotation())->SetArmorTypeCriticalHPRatio(ARMOR_TYPE_LEATHER, atof(row[11])); - (*hr_member->MemberOfHealRotation())->SetArmorTypeCriticalHPRatio(ARMOR_TYPE_CHAIN, atof(row[12])); - (*hr_member->MemberOfHealRotation())->SetArmorTypeCriticalHPRatio(ARMOR_TYPE_PLATE, atof(row[13])); + (*hr_member->MemberOfHealRotation())->SetIntervalS((uint32)Strings::ToInt(row[0])); + (*hr_member->MemberOfHealRotation())->SetFastHeals((bool)Strings::ToInt(row[1])); + (*hr_member->MemberOfHealRotation())->SetAdaptiveTargeting((bool)Strings::ToInt(row[2])); + (*hr_member->MemberOfHealRotation())->SetCastingOverride((bool)Strings::ToInt(row[3])); + (*hr_member->MemberOfHealRotation())->SetArmorTypeSafeHPRatio(ARMOR_TYPE_UNKNOWN, Strings::ToFloat(row[4])); + (*hr_member->MemberOfHealRotation())->SetArmorTypeSafeHPRatio(ARMOR_TYPE_CLOTH, Strings::ToFloat(row[5])); + (*hr_member->MemberOfHealRotation())->SetArmorTypeSafeHPRatio(ARMOR_TYPE_LEATHER, Strings::ToFloat(row[6])); + (*hr_member->MemberOfHealRotation())->SetArmorTypeSafeHPRatio(ARMOR_TYPE_CHAIN, Strings::ToFloat(row[7])); + (*hr_member->MemberOfHealRotation())->SetArmorTypeSafeHPRatio(ARMOR_TYPE_PLATE, Strings::ToFloat(row[8])); + (*hr_member->MemberOfHealRotation())->SetArmorTypeCriticalHPRatio(ARMOR_TYPE_UNKNOWN, Strings::ToFloat(row[9])); + (*hr_member->MemberOfHealRotation())->SetArmorTypeCriticalHPRatio(ARMOR_TYPE_CLOTH, Strings::ToFloat(row[10])); + (*hr_member->MemberOfHealRotation())->SetArmorTypeCriticalHPRatio(ARMOR_TYPE_LEATHER, Strings::ToFloat(row[11])); + (*hr_member->MemberOfHealRotation())->SetArmorTypeCriticalHPRatio(ARMOR_TYPE_CHAIN, Strings::ToFloat(row[12])); + (*hr_member->MemberOfHealRotation())->SetArmorTypeCriticalHPRatio(ARMOR_TYPE_PLATE, Strings::ToFloat(row[13])); load_flag = true; @@ -2844,7 +2875,7 @@ bool BotDatabase::LoadHealRotationMembers(const uint32 hr_index, std::list type, const std::pair flag); + bool SaveBotCasterRange(const uint32 owner_id, const uint32 bot_id, const uint32 bot_caster_range_value); + /* Bot bot-group functions */ bool QueryBotGroupExistence(const std::string& botgroup_name); @@ -164,10 +166,10 @@ public: bool AddMemberToBotGroup(const uint32 leader_id, const uint32 member_id); bool RemoveMemberFromBotGroup(const uint32 member_id); - bool LoadBotGroupIDForLoadBotGroup(const uint32 owner_id, const std::string& botgroup_name, uint32& botgroup_id); + bool LoadBotGroupIDForLoadBotGroup(const uint32 owner_id, std::string_view botgroup_name, uint32& botgroup_id); bool LoadBotGroup(const std::string& botgroup_name, std::map>& member_list); - bool LoadBotGroupsListByOwnerID(const uint32 owner_id, std::list>& botgroups_list); + bool LoadBotGroupsListByOwnerID(const uint32 owner_id, std::list>& botgroups_list); /* Bot group functions */ @@ -190,6 +192,7 @@ public: /* Bot miscellaneous functions */ uint8 GetSpellCastingChance(uint8 spell_type_index, uint8 class_index, uint8 stance_index, uint8 conditional_index); + std::string GetBotNameByID(const uint32 bot_id); uint16 GetRaceClassBitmask(uint16 bot_race); @@ -249,6 +252,7 @@ public: static const char* SaveFollowDistance(); static const char* SaveAllFollowDistances(); static const char* SaveStopMeleeLevel(); + static const char* SaveBotCasterRange(); /* fail::Bot bot-group functions */ static const char* QueryBotGroupExistence(); @@ -280,6 +284,7 @@ public: static const char* DeleteAllHealRotations(); /* fail::Bot miscellaneous functions */ + static const char* GetBotNameByID(); }; private: diff --git a/zone/bot_raid.cpp b/zone/bot_raid.cpp new file mode 100644 index 000000000..22edf3f76 --- /dev/null +++ b/zone/bot_raid.cpp @@ -0,0 +1,287 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "bot.h" +#include "object.h" +#include "raids.h" +#include "doors.h" +#include "quest_parser_collection.h" +#include "../common/data_verification.h" + +extern volatile bool is_zone_loaded; +extern bool Critical; + +std::vector Raid::GetRaidGroupMembers(uint32 gid) +{ + std::vector raid_group_members; + raid_group_members.clear(); + + for (int i = 0; i < MAX_RAID_MEMBERS; ++i) + { + if (members[i].member && members[i].GroupNumber == gid) + { + raid_group_members.push_back(members[i]); + } + } + return raid_group_members; +} + +// Returns Bot members that are in the raid +// passing in owner will return all Bots that have the same owner. +std::vector Raid::GetRaidBotMembers(uint32 owner) +{ + std::vector raid_members_bots; + raid_members_bots.clear(); + + for (int i = 0; i < MAX_RAID_MEMBERS; i++) { + if ( + members[i].member && + members[i].member->IsBot() + ) { + auto b_member = members[i].member->CastToBot(); + if (owner && b_member->GetBotOwnerCharacterID() == owner) { + raid_members_bots.emplace_back(b_member); + } else if (!owner) { + raid_members_bots.emplace_back(b_member); + } + } + } + + return raid_members_bots; +} + +// Returns Bot members that are in the group specified +// passing in owner will return only Bots that have the same owner. +std::vector Raid::GetRaidGroupBotMembers(uint32 gid) +{ + std::vector raid_members_bots; + raid_members_bots.clear(); + + for (int i = 0; i < MAX_RAID_MEMBERS; i++) { + if ( + members[i].member && + members[i].member->IsBot() && + members[i].GroupNumber == gid + ) { + auto b_member = members[i].member->CastToBot(); + raid_members_bots.emplace_back(b_member); + raid_members_bots.emplace_back(b_member); + } + } + + return raid_members_bots; +} + +void Raid::HandleBotGroupDisband(uint32 owner, uint32 gid) +{ + auto raid_members_bots = gid != RAID_GROUPLESS ? GetRaidGroupBotMembers(gid) : GetRaidBotMembers(owner); + + // If any of the bots are a group leader then re-create the botgroup on disband, dropping any clients + for (auto& bot_iter: raid_members_bots) { + + // Remove the entire BOT group in this case + if ( + bot_iter && + gid != RAID_GROUPLESS && + IsRaidMember(bot_iter->GetName()) && + IsGroupLeader(bot_iter->GetName()) + ) { + auto r_group_members = GetRaidGroupMembers(GetGroup(bot_iter->GetName())); + auto group_inst = new Group(bot_iter); + entity_list.AddGroup(group_inst); + database.SetGroupID(bot_iter->GetCleanName(), group_inst->GetID(), bot_iter->GetBotID()); + database.SetGroupLeaderName(group_inst->GetID(), bot_iter->GetName()); + + for (auto member_iter: r_group_members) { + if (member_iter.member->IsBot()) { + auto b_member = member_iter.member->CastToBot(); + if (strcmp(b_member->GetName(), bot_iter->GetName()) == 0) { + bot_iter->SetFollowID(owner); + } else { + Bot::AddBotToGroup(b_member, group_inst); + } + Bot::RemoveBotFromRaid(b_member); + } + } + } else { + Bot::RemoveBotFromRaid(bot_iter); + } + } +} + +uint8 Bot::GetNumberNeedingHealedInRaidGroup(uint8& need_healed, uint8 hpr, bool includePets, Raid* raid) { + + if (raid) { + uint32 r_group = raid->GetGroup(GetName()); + auto raid_group_members = raid->GetRaidGroupMembers(r_group); + + for (auto& m: raid_group_members) { + if (m.member && !m.member->qglobal) { + if (m.member->GetHPRatio() <= hpr) { + need_healed++; + } + + if (includePets) { + if (m.member->GetPet() && m.member->GetPet()->GetHPRatio() <= hpr) { + need_healed++; + } + } + } + } + } + return need_healed; +} + +void Bot::ProcessRaidInvite(Mob* invitee, Client* invitor, bool group_invite) { + + if (!invitee || !invitor) { + return; + } + + if (invitee->IsBot() && + invitor->HasRaid() && + invitee->GetOwner()->HasRaid() && + invitor->GetRaid()->IsRaidMember(invitee->GetOwner()->GetName()) + ) { + // If the Bot Owner is in our raid we need to be able to invite their Bots + } + else if (invitee->IsBot() && (invitee->CastToBot()->GetBotOwnerCharacterID() != invitor->CharacterID())) { + invitor->Message( + Chat::Red, + fmt::format( + "{} is not your Bot. You can only invite your own Bots, or Bots that belong to a Raid member.", + invitee->GetCleanName() + ).c_str() + ); + return; + } + + Raid* raid = entity_list.GetRaidByClient(invitor); + + Bot::CreateBotRaid(invitee, invitor, group_invite, raid); +} + +void Bot::CreateBotRaid(Mob* invitee, Client* invitor, bool group_invite, Raid* raid) { + + Group* g_invitee = invitee->GetGroup(); + Group* g_invitor = invitor->GetGroup(); + + if (g_invitee && invitor->IsClient()) { + if (!g_invitee->IsLeader(invitee)) { + invitor->Message( + Chat::Red, + fmt::format( + "You can only invite group leaders or ungrouped bots. Try {} instead.", + g_invitee->GetLeader()->GetCleanName() + ).c_str() + ); + return; + } + } + + bool new_raid = false; + if (!raid) { + new_raid = true; + raid = new Raid(invitor); + entity_list.AddRaid(raid); + raid->SetRaidDetails(); + } + + // Add Invitor to new raid + if (new_raid) { + if (g_invitor) { + ProcessBotGroupAdd(g_invitor, raid, nullptr, true, true); + } else { + raid->SendRaidCreate(invitor); + raid->AddMember(invitor, 0xFFFFFFFF, true, false, true); + raid->SendMakeLeaderPacketTo(invitor->GetName(), invitor); + if (raid->IsLocked()) { + raid->SendRaidLockTo(invitor); + } + } + } + + // Add Bot Group or Client Bot Group to raid + if (g_invitee) { + ProcessBotGroupAdd(g_invitee, raid); + + // Add individual client to raid + } else if (invitee->IsClient()) { + ProcessBotGroupAdd(g_invitee, raid, invitee->CastToClient()); + + // Add individual bot to raid + } else { + auto gid = raid->GetGroup(invitor->GetName()); + auto b = invitee->CastToBot(); + + // gives us a choice to either invite directly into the clients Raid Group, or just into the Raid + if (group_invite && raid->GroupCount(gid) < MAX_GROUP_MEMBERS) { + raid->AddBot(b, gid); + } else { + raid->AddBot(b); + } + + if (new_raid) { + invitee->SetFollowID(invitor->GetID()); + } + } +} + +void Bot::ProcessBotGroupAdd(Group* group, Raid* raid, Client* client, bool new_raid, bool initial) { + + uint32 raid_free_group_id = raid->GetFreeGroup(); + if (group) { + for (int x = 0; x < MAX_GROUP_MEMBERS; x++) { + if (group->members[x]) { + Client* c = nullptr; + Bot* b = nullptr; + + if (group->members[x] && group->members[x]->IsBot()) { + b = group->members[x]->CastToBot(); + raid->AddBot(b, raid_free_group_id, false, x == 0, false); + } else if (group->members[x] && group->members[x]->IsClient()) { + c = group->members[x]->CastToClient(); + raid->SendRaidCreate(c); + raid->AddMember( + c, + raid_free_group_id, + new_raid, + x == 0, + false + ); + raid->SendMakeLeaderPacketTo(raid->leadername, c); + raid->SendBulkRaid(c); + } + } + } + group->JoinRaidXTarget(raid, initial); + group->DisbandGroup(true); + } else if (client) { + raid->SendRaidCreate(client); + raid->AddMember(client, RAID_GROUPLESS, false, false, true); + raid->SendMakeLeaderPacketTo(raid->leadername, client); + raid->SendBulkRaid(client); + if (raid->IsLocked()) { + raid->SendRaidLockTo(client); + } + } + + raid->GroupUpdate(raid_free_group_id); +} + + diff --git a/zone/perlparser.h b/zone/bot_raid.h similarity index 57% rename from zone/perlparser.h rename to zone/bot_raid.h index 686018543..994b87e1b 100644 --- a/zone/perlparser.h +++ b/zone/bot_raid.h @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.org) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,31 +16,26 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -//extends the perl parser to use C methods -//instead of the command queue. - -#ifndef PERLPARSER_H -#define PERLPARSER_H - -#ifdef EMBPERL -#ifdef EMBPERL_XS - -#include "embparser.h" - -class PerlXSParser : public PerlembParser { -public: - PerlXSParser(); -// ~PerlXSParser(); - - virtual void SendCommands(const char * pkgprefix, const char *event, uint32 object_id, Mob* other, Mob* mob, ItemInst* iteminst, const SPDat_Spell_Struct *spell); -protected: - void map_funs(); - - SV *_empty_sv; -}; +#ifndef BOT_RAID_H +#define BOT_RAID_H -#endif //EMBPERL_XS -#endif //EMBPERL +#include "bot_structs.h" +#include "mob.h" +#include "client.h" +#include "pets.h" +#include "heal_rotation.h" +#include "groups.h" +#include "corpse.h" +#include "zonedb.h" +#include "../common/zone_store.h" +#include "string_ids.h" +#include "../common/misc_functions.h" +#include "../common/global_define.h" +#include "guild_mgr.h" +#include "worldserver.h" +#include "raids.h" -#endif //PERLPARSER_H +#include + +#endif // BOT_RAID_H diff --git a/zone/bot_structs.h b/zone/bot_structs.h index 3328c637d..5264c4ef9 100644 --- a/zone/bot_structs.h +++ b/zone/bot_structs.h @@ -34,22 +34,6 @@ struct BotsAvailableList { uint32 Owner_ID; }; -struct BotGroup { - uint32 BotGroupID; - uint32 BotID; -}; - -struct BotGroupList { - std::string BotGroupName; - std::string BotGroupLeaderName; -}; - -struct SpawnedBotsList { - char BotName[64]; - char ZoneName[64]; - uint32 BotLeaderCharID; -}; - struct BotSpell { uint16 SpellId; int SpellIndex; @@ -71,12 +55,6 @@ struct BotCastingRoles { //bool RaidDoter; }; -struct BotAA { - uint32 aa_id; - uint8 req_level; - uint8 total_levels; -}; - struct BotSpellSetting { int16 priority; uint8 min_level; diff --git a/zone/botspellsai.cpp b/zone/botspellsai.cpp index 570ba072f..f5158fe35 100644 --- a/zone/botspellsai.cpp +++ b/zone/botspellsai.cpp @@ -22,16 +22,11 @@ #include "../common/repositories/bot_spells_entries_repository.h" #include "../common/repositories/npc_spells_repository.h" -#if EQDEBUG >= 12 - #define BotAI_DEBUG_Spells 25 -#elif EQDEBUG >= 9 - #define BotAI_DEBUG_Spells 10 -#else - #define BotAI_DEBUG_Spells -1 -#endif - bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { + // Bot AI + Raid* raid = entity_list.GetRaidByBotName(GetName()); + if (!tar) { return false; } @@ -40,19 +35,12 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { return false; } - if (iChance < 100) { - if (zone->random.Int(0, 100) > iChance) { - return false; - } + if (iChance < 100 && zone->random.Int(0, 100) > iChance) { + return false; } - if (tar->GetAppearance() == eaDead) { - if ((tar->IsClient() && tar->CastToClient()->GetFeigned()) || tar->IsBot()) { - // do nothing - } - else { - return false; - } + if (tar->GetAppearance() == eaDead && ((tar->IsClient() && !tar->CastToClient()->GetFeigned()) || tar->IsBot())) { + return false; } uint8 botClass = GetClass(); @@ -60,1117 +48,1225 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { bool checked_los = false; //we do not check LOS until we are absolutely sure we need to, and we only do it once. - bool castedSpell = false; - BotSpell botSpell; botSpell.SpellId = 0; botSpell.SpellIndex = 0; botSpell.ManaCost = 0; switch (iSpellTypes) { - case SpellType_Mez: { - if (tar->GetBodyType() != BT_Giant) { - if (!checked_los) { - if (!CheckLosFN(tar)) { - break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - } - checked_los = true; - } - - //TODO - //Check if single target or AoE mez is best - //if (TARGETS ON MT IS => 3 THEN botSpell = AoEMez) - //if (TARGETS ON MT IS <= 2 THEN botSpell = BestMez) - - botSpell = GetBestBotSpellForMez(this); - - if (botSpell.SpellId == 0) { - break; - } - - Mob* addMob = GetFirstIncomingMobToMez(this, botSpell); - - if (!addMob) { - //Say("!addMob."); - break; - } - - if (!(!addMob->IsImmuneToSpell(botSpell.SpellId, this) && addMob->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0)) { - break; - } - castedSpell = AIDoSpellCast(botSpell.SpellIndex, addMob, botSpell.ManaCost); - - if (castedSpell) { - BotGroupSay( - this, - fmt::format( - "Attempting to mesmerize {} with {}.", - addMob->GetCleanName(), - spells[botSpell.SpellId].name - ).c_str() - ); - } - } - break; - } - case SpellType_Heal: { - if (tar->DontHealMeBefore() < Timer::GetCurrentTime()) { - uint8 hpr = (uint8)tar->GetHPRatio(); - bool hasAggro = false; - bool isPrimaryHealer = false; - - if (HasGroup()) { - isPrimaryHealer = IsGroupHealer(); - } - - if (hpr < 95 || (tar->IsClient() && (hpr < 95)) || (botClass == BARD)) { - if (tar->GetClass() == NECROMANCER) { - // Give necromancers a chance to go lifetap something or cleric can spend too much mana on a necro - if (hpr >= 40) { - break; - } - } - - if (tar->GetClass() == SHAMAN) { - // Give shaman the chance to canni without wasting the cleric's mana - if (hpr >= 80) { - break; - } - } - - // Evaluate the situation - if ((IsEngaged()) && ((botClass == CLERIC) || (botClass == DRUID) || (botClass == SHAMAN) || (botClass == PALADIN))) { - if (tar->GetTarget() && tar->GetTarget()->GetHateTop() && tar->GetTarget()->GetHateTop() == tar) { - hasAggro = true; - } - - if (hpr < 35) { - botSpell = GetBestBotSpellForFastHeal(this); - } - else if (hpr >= 35 && hpr < 70) { - if (GetNumberNeedingHealedInGroup(60, false) >= 3) { - botSpell = GetBestBotSpellForGroupHeal(this); - } - if (botSpell.SpellId == 0) { - botSpell = GetBestBotSpellForPercentageHeal(this); - } - } - else if (hpr >= 70 && hpr < 95) { - if (GetNumberNeedingHealedInGroup(80, false) >= 3) { - botSpell = GetBestBotSpellForGroupHealOverTime(this); - } - if (hasAggro) { - botSpell = GetBestBotSpellForPercentageHeal(this); - } - } - else { - if (!tar->FindType(SE_HealOverTime)) { - botSpell = GetBestBotSpellForHealOverTime(this); - } - } - } - else if ((botClass == CLERIC) || (botClass == DRUID) || (botClass == SHAMAN) || (botClass == PALADIN)) { - if (GetNumberNeedingHealedInGroup(40, true) >= 2) { - botSpell = GetBestBotSpellForGroupCompleteHeal(this); - - if (botSpell.SpellId == 0) { - botSpell = GetBestBotSpellForGroupHeal(this); - } - if (botSpell.SpellId == 0) { - botSpell = GetBestBotSpellForGroupHealOverTime(this); - } - if (hpr < 40) { - if (botSpell.SpellId == 0) { - botSpell = GetBestBotSpellForPercentageHeal(this); - } - } - } - else if (GetNumberNeedingHealedInGroup(60, true) >= 2) { - botSpell = GetBestBotSpellForGroupHeal(this); - - if (botSpell.SpellId == 0) { - botSpell = GetBestBotSpellForGroupHealOverTime(this); - } - if (hpr < 40) { - if (botSpell.SpellId == 0) { - botSpell = GetBestBotSpellForPercentageHeal(this); - } - } - } - else if (hpr < 40) { - botSpell = GetBestBotSpellForPercentageHeal(this); - } - else if (hpr >= 40 && hpr < 75) { - botSpell = GetBestBotSpellForRegularSingleTargetHeal(this); - } - else { - if (hpr < 90 && !tar->FindType(SE_HealOverTime)) { - botSpell = GetBestBotSpellForHealOverTime(this); - } - } - } - else { - float hpRatioToCast = 0.0f; - - switch(GetBotStance()) { - case EQ::constants::stanceEfficient: - case EQ::constants::stanceAggressive: - hpRatioToCast = isPrimaryHealer?90.0f:50.0f; - break; - case EQ::constants::stanceBalanced: - hpRatioToCast = isPrimaryHealer?95.0f:75.0f; - break; - case EQ::constants::stanceReactive: - hpRatioToCast = isPrimaryHealer?100.0f:90.0f; - break; - case EQ::constants::stanceBurn: - case EQ::constants::stanceBurnAE: - hpRatioToCast = isPrimaryHealer?75.0f:25.0f; - break; - default: - hpRatioToCast = isPrimaryHealer?100.0f:0.0f; - break; - } - - //If we're at specified mana % or below, don't heal as hybrid - if (tar->GetHPRatio() <= hpRatioToCast) { - botSpell = GetBestBotSpellForRegularSingleTargetHeal(this); - } - } - - if (botSpell.SpellId == 0) { - botSpell = GetBestBotSpellForRegularSingleTargetHeal(this); - } - if (botSpell.SpellId == 0) { - botSpell = GetFirstBotSpellForSingleTargetHeal(this); - } - if (botSpell.SpellId == 0 && botClass == BARD) { - botSpell = GetFirstBotSpellBySpellType(this, SpellType_Heal); - } - - // If there is still no spell id, then there isn't going to be one so we are done - if (botSpell.SpellId == 0) { - break; - } - // Can we cast this spell on this target? - if (!(spells[botSpell.SpellId].target_type==ST_GroupTeleport || spells[botSpell.SpellId].target_type == ST_Target || tar == this) - && !(tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0)) { - break; - } - - uint32 TempDontHealMeBeforeTime = tar->DontHealMeBefore(); - - castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost, &TempDontHealMeBeforeTime); - - if (castedSpell) { - /*if (TempDontHealMeBeforeTime != tar->DontHealMeBefore()) - tar->SetDontHealMeBefore(TempDontHealMeBeforeTime); - - // For non-HoT heals, do a 4 second delay - // TODO: Replace this code with logic that calculates the delay based on number of clerics in rotation - // and ignores heals for anyone except the main tank - if (!IsHealOverTimeSpell(botSpell.SpellId)) { - if (IsCompleteHealSpell(botSpell.SpellId)) { - // Complete Heal 4 second rotation - tar->SetDontHealMeBefore(Timer::GetCurrentTime() + 4000); - } - else { - tar->SetDontHealMeBefore(Timer::GetCurrentTime() + 1000); - } - }*/ - if (botClass != BARD) { - if (IsGroupSpell(botSpell.SpellId)) { - if (HasGroup()) { - Group *g = GetGroup(); - - if (g) { - BotGroupSay( - this, - fmt::format( - "Casting {}.", - spells[botSpell.SpellId].name - ).c_str() - ); - - for( int i = 0; imembers[i] && !g->members[i]->qglobal) { - g->members[i]->SetDontHealMeBefore(Timer::GetCurrentTime() + 1000); - } - } - } - } - } else { - if (tar != this) { //we don't need spam of bots healing themselves - BotGroupSay( - this, - fmt::format( - "Casting {} on {}.", - spells[botSpell.SpellId].name, - tar->GetCleanName() - ).c_str() - ); - } - - tar->SetDontHealMeBefore(Timer::GetCurrentTime() + 2000); - } - } - } - } - } - break; - } - case SpellType_Root: { - if (!tar->IsRooted() && tar->DontRootMeBefore() < Timer::GetCurrentTime()) { - if (!checked_los) { - if (!CheckLosFN(tar)) { - break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - } - checked_los = true; - } - - // TODO: If there is a ranger in the group then don't allow root spells - - botSpell = GetFirstBotSpellBySpellType(this, iSpellTypes); - - if (botSpell.SpellId == 0) { - break; - } - if (tar->CanBuffStack(botSpell.SpellId, botLevel, true) == 0) { - break; - } - uint32 TempDontRootMeBefore = tar->DontRootMeBefore(); - - castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost, &TempDontRootMeBefore); - - if (TempDontRootMeBefore != tar->DontRootMeBefore()) { - tar->SetDontRootMeBefore(TempDontRootMeBefore); - } - } - break; - } - case SpellType_Buff: { - if (tar->DontBuffMeBefore() < Timer::GetCurrentTime()) { - std::list buffSpellList = GetBotSpellsBySpellType(this, SpellType_Buff); - - for(std::list::iterator itr = buffSpellList.begin(); itr != buffSpellList.end(); ++itr) { - BotSpell selectedBotSpell = *itr; - - if (selectedBotSpell.SpellId == 0) { - continue; - } - // no buffs with illusions.. use #bot command to cast illusions - if (IsEffectInSpell(selectedBotSpell.SpellId, SE_Illusion) && tar != this) { - continue; - } - //no teleport spells use #bot command to cast teleports - if (IsEffectInSpell(selectedBotSpell.SpellId, SE_Teleport) || IsEffectInSpell(selectedBotSpell.SpellId, SE_Succor)) { - continue; - } - // can not cast buffs for your own pet only on another pet that isn't yours - if ((spells[selectedBotSpell.SpellId].target_type == ST_Pet) && (tar != GetPet())) { - continue; - } - // Validate target - // TODO: Add ST_TargetsTarget support for Buffing. - if ( - !( - ( - spells[selectedBotSpell.SpellId].target_type == ST_Target || - spells[selectedBotSpell.SpellId].target_type == ST_Pet || - (tar == this && spells[selectedBotSpell.SpellId].target_type != ST_TargetsTarget) || - spells[selectedBotSpell.SpellId].target_type == ST_Group || - spells[selectedBotSpell.SpellId].target_type == ST_GroupTeleport || - (botClass == BARD && spells[selectedBotSpell.SpellId].target_type == ST_AEBard) - ) && - !tar->IsImmuneToSpell(selectedBotSpell.SpellId, this) && - tar->CanBuffStack(selectedBotSpell.SpellId, botLevel, true) >= 0 - ) - ) { - continue; - } - - // Put the zone levitate and movement check here since bots are able to bypass the client casting check - if ((IsEffectInSpell(selectedBotSpell.SpellId, SE_Levitate) && !zone->CanLevitate()) - || (IsEffectInSpell(selectedBotSpell.SpellId, SE_MovementSpeed) && !zone->CanCastOutdoor())) { - if (botClass != BARD || !IsSpellUsableThisZoneType(selectedBotSpell.SpellId, zone->GetZoneType())) { - continue; - } - } - - switch (tar->GetArchetype()) - { - case ARCHETYPE_CASTER: - //TODO: probably more caster specific spell effects in here - if (IsEffectInSpell(selectedBotSpell.SpellId, SE_AttackSpeed) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ATK) || - IsEffectInSpell(selectedBotSpell.SpellId, SE_STR) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ReverseDS)) - { - continue; - } - break; - case ARCHETYPE_MELEE: - if (IsEffectInSpell(selectedBotSpell.SpellId, SE_IncreaseSpellHaste) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ManaPool) || - IsEffectInSpell(selectedBotSpell.SpellId, SE_CastingLevel) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ManaRegen_v2) || - IsEffectInSpell(selectedBotSpell.SpellId, SE_CurrentMana)) - { - continue; - } - break; - case ARCHETYPE_HYBRID: - //Hybrids get all buffs - default: - break; - } - - if (botClass == ENCHANTER && IsEffectInSpell(selectedBotSpell.SpellId, SE_Rune)) - { - float manaRatioToCast = 75.0f; - - switch(GetBotStance()) { - case EQ::constants::stanceEfficient: - manaRatioToCast = 90.0f; - break; - case EQ::constants::stanceBalanced: - case EQ::constants::stanceAggressive: - manaRatioToCast = 75.0f; - break; - case EQ::constants::stanceReactive: - case EQ::constants::stanceBurn: - case EQ::constants::stanceBurnAE: - manaRatioToCast = 50.0f; - break; - default: - manaRatioToCast = 75.0f; - break; - } - - //If we're at specified mana % or below, don't rune as enchanter - if (GetManaRatio() <= manaRatioToCast) { - break; - } - } - - if (CheckSpellRecastTimers(this, itr->SpellIndex)) - { - - uint32 TempDontBuffMeBefore = tar->DontBuffMeBefore(); - - castedSpell = AIDoSpellCast(selectedBotSpell.SpellIndex, tar, selectedBotSpell.ManaCost, &TempDontBuffMeBefore); - - if (TempDontBuffMeBefore != tar->DontBuffMeBefore()) - tar->SetDontBuffMeBefore(TempDontBuffMeBefore); - } - - if (castedSpell) { - break; - } - } - } - break; - } - case SpellType_Escape: { - uint8 hpr = (uint8)GetHPRatio(); - bool mayGetAggro = false; - -#ifdef IPC - if (hpr <= 5 || (IsNPC() && CastToNPC()->IsInteractive() && tar != this) ) -#else - if (hpr > 15 && ((botClass == WIZARD) || (botClass == ENCHANTER) || (botClass == RANGER))) - mayGetAggro = HasOrMayGetAggro(); //classes have hate reducing spells - - if (hpr <= 15 || mayGetAggro) -#endif - { - botSpell = GetFirstBotSpellBySpellType(this, iSpellTypes); - - if (botSpell.SpellId == 0) { - break; - } - if (IsInvulnerabilitySpell(botSpell.SpellId)) { - tar = this; //target self for invul type spells - } - castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); - } - break; - } - case SpellType_Nuke: { - if ((tar->GetHPRatio() <= 95.0f) || ((botClass == BARD) || (botClass == SHAMAN) || (botClass == ENCHANTER) || (botClass == PALADIN) || (botClass == SHADOWKNIGHT) || (botClass == WARRIOR))) - { - if (!checked_los) { - if (!CheckLosFN(tar)) - break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - - checked_los = true; - } - - if (botClass == CLERIC || botClass == ENCHANTER) - { - float manaRatioToCast = 75.0f; - - switch(GetBotStance()) { - case EQ::constants::stanceEfficient: - manaRatioToCast = 90.0f; - break; - case EQ::constants::stanceBalanced: - manaRatioToCast = 75.0f; - break; - case EQ::constants::stanceReactive: - case EQ::constants::stanceAggressive: - manaRatioToCast = 50.0f; - break; - case EQ::constants::stanceBurn: - case EQ::constants::stanceBurnAE: - manaRatioToCast = 25.0f; - break; - default: - manaRatioToCast = 50.0f; - break; - } - - //If we're at specified mana % or below, don't nuke as cleric or enchanter - if (GetManaRatio() <= manaRatioToCast) - break; - } - - if (botClass == MAGICIAN || botClass == SHADOWKNIGHT || botClass == NECROMANCER || botClass == PALADIN || botClass == RANGER || botClass == DRUID || botClass == CLERIC) { - if (tar->GetBodyType() == BT_Undead || tar->GetBodyType() == BT_SummonedUndead || tar->GetBodyType() == BT_Vampire) - botSpell = GetBestBotSpellForNukeByTargetType(this, ST_Undead); - else if (tar->GetBodyType() == BT_Summoned || tar->GetBodyType() == BT_Summoned2 || tar->GetBodyType() == BT_Summoned3) - botSpell = GetBestBotSpellForNukeByTargetType(this, ST_Summoned); - } - - if (botClass == PALADIN || botClass == DRUID || botClass == CLERIC || botClass == ENCHANTER || botClass == WIZARD) { - if (botSpell.SpellId == 0) { - uint8 stunChance = (tar->IsCasting() ? 30: 15); - - if (botClass == PALADIN) - stunChance = 50; - - if (!tar->GetSpecialAbility(UNSTUNABLE) && !tar->IsStunned() && (zone->random.Int(1, 100) <= stunChance)) { - botSpell = GetBestBotSpellForStunByTargetType(this, ST_Target); - } - } - } - - if (botClass == WIZARD && botSpell.SpellId == 0) { - botSpell = GetBestBotWizardNukeSpellByTargetResists(this, tar); - } - - if (botSpell.SpellId == 0) { - botSpell = GetBestBotSpellForNukeByTargetType(this, ST_Target); - } - if (botSpell.SpellId == 0) { - break; - } - if (!(!tar->IsImmuneToSpell(botSpell.SpellId, this) && (tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0))) { - break; - } - if (IsFearSpell(botSpell.SpellId)) { - // don't let fear cast if the npc isn't snared or rooted - if (tar->GetSnaredAmount() == -1) { - if (!tar->IsRooted()) { - break; - } - } - } - - castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); - } - break; - } - case SpellType_Dispel: { - if (tar->GetHPRatio() > 95.0f) { - if (!checked_los) { - if (!CheckLosFN(tar)) { - break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - } - checked_los = true; - } - - botSpell = GetFirstBotSpellBySpellType(this, iSpellTypes); - - if (botSpell.SpellId == 0) { - break; - } - // TODO: Check target to see if there is anything to dispel - - if (tar->CountDispellableBuffs() > 0) { - castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); - } - } - break; - } - case SpellType_Pet: { - //keep mobs from recasting pets when they have them. - if (!IsPet() && !GetPetID() && !IsBotCharmer()) { - if (botClass == WIZARD) { - auto buffs_max = GetMaxBuffSlots(); - auto my_buffs = GetBuffs(); - 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)) { - MakePet(my_buffs[index].spellid, spells[my_buffs[index].spellid].teleport_zone); - familiar_buff_slot = index; - break; - } - } - } - if (GetPetID()) - break; - - if (familiar_buff_slot >= 0) { - BuffFadeBySlot(familiar_buff_slot); - break; - } - - botSpell = GetFirstBotSpellBySpellType(this, SpellType_Pet); - } - else if (botClass == MAGICIAN) { - botSpell = GetBestBotMagicianPetSpell(this); - } - else { - botSpell = GetFirstBotSpellBySpellType(this, SpellType_Pet); - } - - if (botSpell.SpellId == 0) - break; - - castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); - } - break; - } - case SpellType_InCombatBuff: { - // Allow all classes to use InCombatBuffs - if (tar->DontBuffMeBefore() < Timer::GetCurrentTime()) { - std::list buffSpellList = GetBotSpellsBySpellType(this, SpellType_InCombatBuff); - - for (std::list::iterator itr = buffSpellList.begin(); itr != buffSpellList.end(); ++itr) { - BotSpell selectedBotSpell = *itr; - - if (selectedBotSpell.SpellId == 0) { - continue; - } - // no buffs with illusions.. use #bot command to cast illusions - if (IsEffectInSpell(selectedBotSpell.SpellId, SE_Illusion) && tar != this) { - continue; - } - //no teleport spells use #bot command to cast teleports - if (IsEffectInSpell(selectedBotSpell.SpellId, SE_Teleport) || IsEffectInSpell(selectedBotSpell.SpellId, SE_Succor)) { - continue; - } - // can not cast buffs for your own pet only on another pet that isn't yours - if ((spells[selectedBotSpell.SpellId].target_type == ST_Pet) && (tar != GetPet())) { - continue; - } - - //Conversion Spells - if (IsSelfConversionSpell(selectedBotSpell.SpellId)) { - if (GetManaRatio() > 90.0f || GetHPRatio() < 50.0f || GetHPRatio() < (GetManaRatio() + 10.0f)) { - break; //don't cast if low hp, lots of mana, or if mana is higher than hps - } - } - - // Validate target - // TODO: Add ST_TargetsTarget support for Buffing. - if ( - !( - ( - spells[selectedBotSpell.SpellId].target_type == ST_Target || - spells[selectedBotSpell.SpellId].target_type == ST_Pet || - (tar == this && spells[selectedBotSpell.SpellId].target_type != ST_TargetsTarget) || - spells[selectedBotSpell.SpellId].target_type == ST_Group || - spells[selectedBotSpell.SpellId].target_type == ST_GroupTeleport || - (botClass == BARD && spells[selectedBotSpell.SpellId].target_type == ST_AEBard) - ) && - !tar->IsImmuneToSpell(selectedBotSpell.SpellId, this) && - tar->CanBuffStack(selectedBotSpell.SpellId, botLevel, true) >= 0 - ) - ) { - continue; - } - - // Put the zone levitate and movement check here since bots are able to bypass the client casting check - if ( - (IsEffectInSpell(selectedBotSpell.SpellId, SE_Levitate) && !zone->CanLevitate()) || - (IsEffectInSpell(selectedBotSpell.SpellId, SE_MovementSpeed) && !zone->CanCastOutdoor()) - ) { - if (botClass != BARD || !IsSpellUsableThisZoneType(selectedBotSpell.SpellId, zone->GetZoneType())) { - continue; - } - } - - if (!IsGroupSpell(selectedBotSpell.SpellId)) { - //Only check archetype if spell is not a group spell - switch (tar->GetArchetype()) { - case ARCHETYPE_CASTER: - //TODO: probably more caster specific spell effects in here - if ( - ( - IsEffectInSpell(selectedBotSpell.SpellId, SE_AttackSpeed) || - IsEffectInSpell(selectedBotSpell.SpellId, SE_ATK) || - IsEffectInSpell(selectedBotSpell.SpellId, SE_STR) || - IsEffectInSpell(selectedBotSpell.SpellId, SE_ReverseDS) || - IsEffectInSpell(selectedBotSpell.SpellId, SE_DamageShield) - ) && - spells[selectedBotSpell.SpellId].target_type != ST_Self - ) { - continue; - } - break; - case ARCHETYPE_MELEE: - if ( - ( - IsEffectInSpell(selectedBotSpell.SpellId, SE_IncreaseSpellHaste) || - IsEffectInSpell(selectedBotSpell.SpellId, SE_ManaPool) || - IsEffectInSpell(selectedBotSpell.SpellId, SE_CastingLevel) || - IsEffectInSpell(selectedBotSpell.SpellId, SE_ManaRegen_v2) || - IsEffectInSpell(selectedBotSpell.SpellId, SE_CurrentMana) - ) && - spells[selectedBotSpell.SpellId].target_type != ST_Self - ) { - continue; - } - break; - case ARCHETYPE_HYBRID: - //Hybrids get all buffs - default: - break; - } - } - // TODO: Add TriggerSpell Support for Exchanter Runes - if (botClass == ENCHANTER && IsEffectInSpell(selectedBotSpell.SpellId, SE_Rune)) { - float manaRatioToCast = 75.0f; - - switch(GetBotStance()) { - case EQ::constants::stanceEfficient: - manaRatioToCast = 90.0f; - break; - case EQ::constants::stanceBalanced: - case EQ::constants::stanceAggressive: - manaRatioToCast = 75.0f; - break; - case EQ::constants::stanceReactive: - case EQ::constants::stanceBurn: - case EQ::constants::stanceBurnAE: - manaRatioToCast = 50.0f; - break; - default: - manaRatioToCast = 75.0f; - break; - } - - //If we're at specified mana % or below, don't rune as enchanter - if (GetManaRatio() <= manaRatioToCast) { - break; - } - } - - if (CheckSpellRecastTimers(this, itr->SpellIndex)) { - uint32 TempDontBuffMeBefore = tar->DontBuffMeBefore(); - castedSpell = AIDoSpellCast(selectedBotSpell.SpellIndex, tar, selectedBotSpell.ManaCost, &TempDontBuffMeBefore); - - if (TempDontBuffMeBefore != tar->DontBuffMeBefore()) - tar->SetDontBuffMeBefore(TempDontBuffMeBefore); - } - - if (castedSpell) { - break; - } - } - } - break; - } - case SpellType_Lifetap: { - if (GetHPRatio() < 90.0f) { - if (!checked_los) { - if (!CheckLosFN(tar)) - break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - - checked_los = true; - } - - botSpell = GetFirstBotSpellBySpellType(this, iSpellTypes); - - if (botSpell.SpellId == 0) - break; - - if (!(!tar->IsImmuneToSpell(botSpell.SpellId, this) && (tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0))) - break; - - castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); - } - break; - } - case SpellType_Snare: { - if (tar->DontSnareMeBefore() < Timer::GetCurrentTime()) { - if (!checked_los) { - if (!CheckLosFN(tar)) - break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - - checked_los = true; - } - - botSpell = GetFirstBotSpellBySpellType(this, iSpellTypes); - - if (botSpell.SpellId == 0) - break; - - if (!(!tar->IsImmuneToSpell(botSpell.SpellId, this) && tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0)) - break; - - uint32 TempDontSnareMeBefore = tar->DontSnareMeBefore(); - - castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost, &TempDontSnareMeBefore); - - if (TempDontSnareMeBefore != tar->DontSnareMeBefore()) - tar->SetDontSnareMeBefore(TempDontSnareMeBefore); - } - break; - } - case SpellType_DOT: { - if ((tar->GetHPRatio() <= 98.0f) && (tar->DontDotMeBefore() < Timer::GetCurrentTime()) && (tar->GetHPRatio() > 15.0f)) { - if (!checked_los) { - if (!CheckLosFN(tar)) - break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - - checked_los = true; - } - - if (GetClass() == BARD) { - std::list dotList = GetPrioritizedBotSpellsBySpellType(this, SpellType_DOT); - - const int maxDotSelect = 5; - int dotSelectCounter = 0; - - for (std::list::iterator itr = dotList.begin(); itr != dotList.end(); ++itr) { - BotSpell selectedBotSpell = *itr; - - if (selectedBotSpell.SpellId == 0) - continue; - - if (CheckSpellRecastTimers(this, itr->SpellIndex)) - { - - if (!(!tar->IsImmuneToSpell(selectedBotSpell.SpellId, this) && tar->CanBuffStack(selectedBotSpell.SpellId, botLevel, true) >= 0)) - continue; - - uint32 TempDontDotMeBefore = tar->DontDotMeBefore(); - - castedSpell = AIDoSpellCast(selectedBotSpell.SpellIndex, tar, selectedBotSpell.ManaCost, &TempDontDotMeBefore); - - if (TempDontDotMeBefore != tar->DontDotMeBefore()) - tar->SetDontDotMeBefore(TempDontDotMeBefore); - } - - dotSelectCounter++; - - if ((dotSelectCounter == maxDotSelect) || castedSpell) - break; - } - } - else { - std::list dotList = GetBotSpellsBySpellType(this, SpellType_DOT); - - const int maxDotSelect = 5; - int dotSelectCounter = 0; - - for (std::list::iterator itr = dotList.begin(); itr != dotList.end(); ++itr) { - BotSpell selectedBotSpell = *itr; - - if (selectedBotSpell.SpellId == 0) - continue; - - if (CheckSpellRecastTimers(this, itr->SpellIndex)) - { - - if (!(!tar->IsImmuneToSpell(selectedBotSpell.SpellId, this) && tar->CanBuffStack(selectedBotSpell.SpellId, botLevel, true) >= 0)) - continue; - - uint32 TempDontDotMeBefore = tar->DontDotMeBefore(); - - castedSpell = AIDoSpellCast(selectedBotSpell.SpellIndex, tar, selectedBotSpell.ManaCost, &TempDontDotMeBefore); - - if (TempDontDotMeBefore != tar->DontDotMeBefore()) - tar->SetDontDotMeBefore(TempDontDotMeBefore); - } - - dotSelectCounter++; - - if ((dotSelectCounter == maxDotSelect) || castedSpell) - break; - } - } - } - break; - } - case SpellType_Slow: { - if (tar->GetHPRatio() <= 99.0f) { - - if (!checked_los) { - if (!CheckLosFN(tar)) - break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - - checked_los = true; - } - - switch (botClass) { - case BARD: { - // probably needs attackable check - std::list botSongList = GetPrioritizedBotSpellsBySpellType(this, SpellType_Slow); - for (auto iter : botSongList) { - if (!iter.SpellId) - continue; - if (!CheckSpellRecastTimers(this, iter.SpellIndex)) - continue; - if (spells[iter.SpellId].zone_type != -1 && zone->GetZoneType() != -1 && spells[iter.SpellId].zone_type != zone->GetZoneType()) // is this bit or index? - continue; - if (spells[iter.SpellId].target_type != ST_Target) - continue; - if (tar->CanBuffStack(iter.SpellId, botLevel, true) < 0) - continue; - - castedSpell = AIDoSpellCast(iter.SpellIndex, tar, iter.ManaCost); - if (castedSpell) - break; - } - - break; - } - case ENCHANTER: { - botSpell = GetBestBotSpellForMagicBasedSlow(this); - break; - } - case SHAMAN: - case BEASTLORD: { - botSpell = GetBestBotSpellForDiseaseBasedSlow(this); - - if (botSpell.SpellId == 0 || ((tar->GetMR() - 50) < (tar->GetDR() + spells[botSpell.SpellId].resist_difficulty))) - botSpell = GetBestBotSpellForMagicBasedSlow(this); - break; - } - } - - if (botSpell.SpellId == 0) - break; - - if (!(!tar->IsImmuneToSpell(botSpell.SpellId, this) && tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0)) - break; - - castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); - - if (castedSpell && GetClass() != BARD) { - BotGroupSay( - this, - fmt::format( - "Attempting to slow {} with {}.", - tar->GetCleanName(), - spells[botSpell.SpellId].name - ).c_str() - ); - } - } - break; - } - case SpellType_Debuff: { - if ((tar->GetHPRatio() <= 99.0f) && (tar->GetHPRatio() > 20.0f)) - { - if (!checked_los) { - if (!CheckLosFN(tar)) - break; //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - - checked_los = true; - } - - botSpell = GetBestBotSpellForResistDebuff(this, tar); - - if (botSpell.SpellId == 0) - botSpell = GetDebuffBotSpell(this, tar); - - if (botSpell.SpellId == 0) - break; - - if (!(!tar->IsImmuneToSpell(botSpell.SpellId, this) && (tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0))) - break; - - castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); - } - break; - } - case SpellType_Cure: { - if (GetNeedsCured(tar) && (tar->DontCureMeBefore() < Timer::GetCurrentTime()) && !(GetNumberNeedingHealedInGroup(25, false) > 0) && !(GetNumberNeedingHealedInGroup(40, false) > 2)) - { - botSpell = GetBestBotSpellForCure(this, tar); - - if (botSpell.SpellId == 0) - break; - - uint32 TempDontCureMeBeforeTime = tar->DontCureMeBefore(); - - castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost, &TempDontCureMeBeforeTime); - - if (castedSpell) { - if (botClass != BARD) { - if (IsGroupSpell(botSpell.SpellId)) { - Group *g; - - if (HasGroup()) { - Group *g = GetGroup(); - - if (g) { - for ( int i = 0; imembers[i] && !g->members[i]->qglobal) { - if (TempDontCureMeBeforeTime != tar->DontCureMeBefore()) - g->members[i]->SetDontCureMeBefore(Timer::GetCurrentTime() + 4000); - } - } - } - } - } - else { - if (TempDontCureMeBeforeTime != tar->DontCureMeBefore()) { - tar->SetDontCureMeBefore(Timer::GetCurrentTime() + 4000); - } - } - } - } - } - break; - } + case SpellType_Mez: + return BotCastMez(tar, botLevel, checked_los, botSpell, raid); + case SpellType_Heal: + return BotCastHeal(tar, botLevel, botClass, botSpell, raid); + case SpellType_Root: + return BotCastRoot(tar, botLevel, iSpellTypes, botSpell, checked_los); + case SpellType_Buff: + return BotCastBuff(tar, botLevel, botClass); + case SpellType_Escape: + return BotCastEscape(tar, botClass, botSpell, iSpellTypes); + case SpellType_Nuke: + return BotCastNuke(tar, botLevel, botClass, botSpell, checked_los); + case SpellType_Dispel: + return BotCastDispel(tar, botSpell, iSpellTypes, checked_los); + case SpellType_Pet: + return BotCastPet(tar, botClass, botSpell); + case SpellType_InCombatBuff: + return BotCastCombatBuff(tar, botLevel, botClass); + case SpellType_Lifetap: + return BotCastLifetap(tar, botLevel, botSpell, checked_los, iSpellTypes); + case SpellType_Snare: + return BotCastSnare(tar, botLevel, botSpell, checked_los, iSpellTypes); + case SpellType_DOT: + return BotCastDOT(tar, botLevel, botSpell, checked_los); + case SpellType_Slow: + return BotCastSlow(tar, botLevel, botClass, botSpell, checked_los, raid); + case SpellType_Debuff: + return BotCastDebuff(tar, botLevel, botSpell, checked_los); + case SpellType_Cure: + return BotCastCure(tar, botClass, botSpell, raid); case SpellType_Resurrect: - break; - case SpellType_HateRedux: { - // assumed group member at this point - if (GetClass() == BARD) { - std::list botSongList = GetPrioritizedBotSpellsBySpellType(this, SpellType_HateRedux); - for (auto iter : botSongList) { - if (!iter.SpellId) - continue; - if (!CheckSpellRecastTimers(this, iter.SpellIndex)) - continue; - if (spells[iter.SpellId].zone_type != -1 && zone->GetZoneType() != -1 && spells[iter.SpellId].zone_type != zone->GetZoneType()) // is this bit or index? - continue; - if (spells[iter.SpellId].target_type != ST_Target) - continue; - if (tar->CanBuffStack(iter.SpellId, botLevel, true) < 0) - continue; - - castedSpell = AIDoSpellCast(iter.SpellIndex, tar, iter.ManaCost); - if (castedSpell) { - BotGroupSay( - this, - fmt::format( - "Attempting to reduce hate on {} with {}.", - tar->GetCleanName(), - spells[iter.SpellId].name - ).c_str() - ); - break; - } - } - } - - break; - } - case SpellType_InCombatBuffSong: { - if (tar != this) { // In-Combat songs can be cast Out-of-Combat in preparation for battle - break; - } - std::list botSongList = GetPrioritizedBotSpellsBySpellType(this, SpellType_InCombatBuffSong); - for (auto iter : botSongList) { - if (!iter.SpellId) - continue; - if (!CheckSpellRecastTimers(this, iter.SpellIndex)) - continue; - if (spells[iter.SpellId].zone_type != -1 && zone->GetZoneType() != -1 && spells[iter.SpellId].zone_type != zone->GetZoneType()) // is this bit or index? - continue; - switch (spells[iter.SpellId].target_type) { - case ST_AEBard: - case ST_AECaster: - case ST_GroupTeleport: - case ST_Group: - case ST_Self: - break; - default: - continue; - } - if (tar->CanBuffStack(iter.SpellId, botLevel, true) < 0) - continue; - - castedSpell = AIDoSpellCast(iter.SpellIndex, tar, iter.ManaCost); - if (castedSpell) - break; - } - - break; - } - case SpellType_OutOfCombatBuffSong: { - if (GetClass() != BARD || tar != this || IsEngaged()) // Out-of-Combat songs can not be cast in combat - break; - - std::list botSongList = GetPrioritizedBotSpellsBySpellType(this, SpellType_OutOfCombatBuffSong); - for (auto iter : botSongList) { - if (!iter.SpellId) - continue; - if (!CheckSpellRecastTimers(this, iter.SpellIndex)) - continue; - if (spells[iter.SpellId].zone_type != -1 && zone->GetZoneType() != -1 && spells[iter.SpellId].zone_type != zone->GetZoneType()) // is this bit or index? - continue; - switch (spells[iter.SpellId].target_type) { - case ST_AEBard: - case ST_AECaster: - case ST_GroupTeleport: - case ST_Group: - case ST_Self: - break; - default: - continue; - } - if (tar->CanBuffStack(iter.SpellId, botLevel, true) < 0) - continue; - - castedSpell = AIDoSpellCast(iter.SpellIndex, tar, iter.ManaCost); - if (castedSpell) - break; - } - - break; - } - case SpellType_PreCombatBuff: { - break; - } - case SpellType_PreCombatBuffSong: { - break; - } + return false; + case SpellType_HateRedux: + return BotCastHateReduction(tar, botLevel, botSpell); + case SpellType_InCombatBuffSong: + return BotCastCombatSong(tar, botLevel); + case SpellType_OutOfCombatBuffSong: + return BotCastSong(tar, botLevel); + case SpellType_PreCombatBuff: + return false; + case SpellType_PreCombatBuffSong: + return false; default: + return false; + } + + return false; +} + +bool Bot::BotCastSong(Mob* tar, uint8 botLevel) { + bool casted_spell = false; + if (GetClass() != BARD || tar != this || IsEngaged()) // Out-of-Combat songs can not be cast in combat + return casted_spell; + + for (auto botSongList = GetPrioritizedBotSpellsBySpellType(this, SpellType_OutOfCombatBuffSong); + auto iter : botSongList) { + if (!iter.SpellId) + continue; + if (!CheckSpellRecastTimers(this, iter.SpellIndex)) + continue; + if (!IsSpellUsableThisZoneType(iter.SpellId, zone->GetZoneType())) + continue; + switch (spells[iter.SpellId].target_type) { + case ST_AEBard: + case ST_AECaster: + case ST_GroupTeleport: + case ST_Group: + case ST_Self: + break; + default: + continue; + } + if (tar->CanBuffStack(iter.SpellId, botLevel, true) < 0) + continue; + + casted_spell = AIDoSpellCast(iter.SpellIndex, tar, iter.ManaCost); + if (casted_spell) break; } - return castedSpell; + return casted_spell; } -bool Bot::AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore) { +bool Bot::BotCastCombatSong(Mob* tar, uint8 botLevel) { + bool casted_spell = false; + if (tar != this) { // In-Combat songs can be cast Out-of-Combat in preparation for battle + return casted_spell; + } + for (auto botSongList = GetPrioritizedBotSpellsBySpellType(this, SpellType_InCombatBuffSong); + auto iter : botSongList) { + if (!iter.SpellId) + continue; + if (!CheckSpellRecastTimers(this, iter.SpellIndex)) + continue; + if (!IsSpellUsableThisZoneType(iter.SpellId, zone->GetZoneType())) + continue; + switch (spells[iter.SpellId].target_type) { + case ST_AEBard: + case ST_AECaster: + case ST_GroupTeleport: + case ST_Group: + case ST_Self: + break; + default: + continue; + } + if (tar->CanBuffStack(iter.SpellId, botLevel, true) < 0) + continue; + + casted_spell = AIDoSpellCast(iter.SpellIndex, tar, iter.ManaCost); + if (casted_spell) + break; + } + + return casted_spell; +} + +bool Bot::BotCastHateReduction(Mob* tar, uint8 botLevel, const BotSpell& botSpell) { + bool casted_spell = false; + if (GetClass() == BARD) { + std::list botSongList = GetPrioritizedBotSpellsBySpellType(this, SpellType_HateRedux); + for (auto iter : botSongList) { + if (!iter.SpellId) + continue; + if (!CheckSpellRecastTimers(this, iter.SpellIndex)) + continue; + if (!IsSpellUsableThisZoneType(iter.SpellId, zone->GetZoneType())) + continue; + if (spells[iter.SpellId].target_type != ST_Target) + continue; + if (tar->CanBuffStack(iter.SpellId, botLevel, true) < 0) + continue; + + if (IsValidSpellRange(botSpell.SpellId, tar)) { + casted_spell = AIDoSpellCast(iter.SpellIndex, tar, iter.ManaCost); + } + if (casted_spell) { + BotGroupSay( + this, + fmt::format( + "Attempting to reduce hate on {} with {}.", + tar->GetCleanName(), + spells[iter.SpellId].name + ).c_str() + ); + } + } + } + + return casted_spell; +} + +bool Bot::BotCastCure(Mob* tar, uint8 botClass, BotSpell& botSpell, Raid* raid) { + bool casted_spell = false; + if ( + GetNeedsCured(tar) && + (tar->DontCureMeBefore() < Timer::GetCurrentTime()) && + GetNumberNeedingHealedInGroup(25, false, raid) <= 0 && + GetNumberNeedingHealedInGroup(40, false, raid) <= 2 + ) { + botSpell = GetBestBotSpellForCure(this, tar); + + if (!IsValidSpell(botSpell.SpellId)) { + return casted_spell; + } + + uint32 TempDontCureMeBeforeTime = tar->DontCureMeBefore(); + + casted_spell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost, &TempDontCureMeBeforeTime); + + if (casted_spell && botClass != BARD) { + if (IsGroupSpell(botSpell.SpellId)) { + if (HasGroup()) { + Group const* group = GetGroup(); + if (group) { + for (auto member : group->members) { + if ( + member && + !member->qglobal && + TempDontCureMeBeforeTime != tar->DontCureMeBefore() + ) { + member->SetDontCureMeBefore(Timer::GetCurrentTime() + 4000); + } + } + } + } else if (IsRaidGrouped()) { + uint32 r_group = raid->GetGroup(GetName()); + if (r_group) { + std::vector raid_group_members = raid->GetRaidGroupMembers(r_group); + for (auto iter: raid_group_members) { + if ( + iter.member && + !iter.member->qglobal && + TempDontCureMeBeforeTime != tar->DontCureMeBefore() + ) { + iter.member->SetDontCureMeBefore(Timer::GetCurrentTime() + 4000); + } + } + } + } + } else if (TempDontCureMeBeforeTime != tar->DontCureMeBefore()) { + tar->SetDontCureMeBefore(Timer::GetCurrentTime() + 4000); + } + } + } + return casted_spell; +} + +bool Bot::BotCastDebuff(Mob* tar, uint8 botLevel, BotSpell& botSpell, bool checked_los) { + bool casted_spell = false; + if ((tar->GetHPRatio() <= 99.0f) && (tar->GetHPRatio() > 20.0f)) + { + if (!checked_los && !CheckLosFN(tar)) { + return casted_spell; + } + + botSpell = GetBestBotSpellForResistDebuff(this, tar); + + if (!IsValidSpell(botSpell.SpellId)) { + botSpell = GetDebuffBotSpell(this, tar); + } + + if (!IsValidSpell(botSpell.SpellId)) { + return casted_spell; + } + + if (! + ( + !tar->IsImmuneToSpell(botSpell.SpellId, this) && + (tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0) + ) + ) { + return casted_spell; + } + + if (IsValidSpellRange(botSpell.SpellId, tar)) { + casted_spell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); + } + } + return casted_spell; +} + +bool Bot::BotCastSlow(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpell, const bool& checked_los, Raid* raid) { + bool casted_spell = false; + if (tar->GetHPRatio() <= 99.0f) { + + if (!checked_los && !CheckLosFN(tar)) { + return casted_spell; + } + + switch (botClass) { + case BARD: { + // probably needs attackable check + for ( + auto botSongList = GetPrioritizedBotSpellsBySpellType(this, SpellType_Slow); + auto iter : botSongList + ) { + + if (!iter.SpellId) { + continue; + } + + if (!CheckSpellRecastTimers(this, iter.SpellIndex)) { + continue; + } + + if (!IsSpellUsableThisZoneType(iter.SpellId, zone->GetZoneType())) { + continue; + } + + if (spells[iter.SpellId].target_type != ST_Target) { + continue; + } + + if (tar->CanBuffStack(iter.SpellId, botLevel, true) < 0) { + continue; + } + + if (IsValidSpellRange(botSpell.SpellId, tar)) { + casted_spell = AIDoSpellCast(iter.SpellIndex, tar, iter.ManaCost); + } + + if (casted_spell) { + return casted_spell; + } + } + + break; + } + case ENCHANTER: { + botSpell = GetBestBotSpellForMagicBasedSlow(this); + break; + } + case SHAMAN: + case BEASTLORD: { + botSpell = GetBestBotSpellForDiseaseBasedSlow(this); + + if (botSpell.SpellId == 0 || ((tar->GetMR() - 50) < (tar->GetDR() + spells[botSpell.SpellId].resist_difficulty))) + botSpell = GetBestBotSpellForMagicBasedSlow(this); + break; + } + } + + if (!IsValidSpell(botSpell.SpellId)) { + return casted_spell; + } + + if (!(!tar->IsImmuneToSpell(botSpell.SpellId, this) && tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0)) { + return casted_spell; + } + if (IsValidSpellRange(botSpell.SpellId, tar)) { + casted_spell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); + } + + if (casted_spell && GetClass() != BARD) { + if (raid) { + const auto msg = fmt::format("Attempting to slow {}.", tar->GetCleanName()); + raid->RaidSay(msg.c_str(), GetCleanName(), 0, 100); + } else { + BotGroupSay( + this, + fmt::format( + "Attempting to slow {} with {}.", + tar->GetCleanName(), + spells[botSpell.SpellId].name + ).c_str() + ); + } + } + } + return casted_spell; +} + +bool Bot::BotCastDOT(Mob* tar, uint8 botLevel, const BotSpell& botSpell, const bool& checked_los) { + bool casted_spell = false; + + if ((tar->GetHPRatio() <= 98.0f) && (tar->DontDotMeBefore() < Timer::GetCurrentTime()) && (tar->GetHPRatio() > 15.0f)) { + if (!checked_los && !CheckLosFN(tar)) { + return casted_spell; + } + + if (GetClass() == BARD) { + std::list dotList = GetPrioritizedBotSpellsBySpellType(this, SpellType_DOT); + + const int maxDotSelect = 5; + int dotSelectCounter = 0; + + for (const auto& s : dotList) { + + if (!IsValidSpell(s.SpellId)) { + continue; + } + + if (CheckSpellRecastTimers(this, s.SpellIndex)) + { + + if (!(!tar->IsImmuneToSpell(s.SpellId, this) && tar->CanBuffStack(s.SpellId, botLevel, true) >= 0)) { + continue; + } + + uint32 TempDontDotMeBefore = tar->DontDotMeBefore(); + + casted_spell = AIDoSpellCast(s.SpellIndex, tar, s.ManaCost, &TempDontDotMeBefore); + + if (TempDontDotMeBefore != tar->DontDotMeBefore()) { + tar->SetDontDotMeBefore(TempDontDotMeBefore); + } + } + + dotSelectCounter++; + + if ((dotSelectCounter == maxDotSelect) || casted_spell) { + break; + } + } + } + else { + std::list dotList = GetBotSpellsBySpellType(this, SpellType_DOT); + + const int maxDotSelect = 5; + int dotSelectCounter = 0; + + for (const auto& s : dotList) { + + if (!IsValidSpell(s.SpellId)) { + continue; + } + + if (CheckSpellRecastTimers(this, s.SpellIndex)) { + + if (!(!tar->IsImmuneToSpell(s.SpellId, this) && + tar->CanBuffStack(s.SpellId, botLevel, true) >= 0)) { + continue; + } + + uint32 TempDontDotMeBefore = tar->DontDotMeBefore(); + + if (IsValidSpellRange(botSpell.SpellId, tar)) { + casted_spell = AIDoSpellCast(s.SpellIndex, tar, s.ManaCost, &TempDontDotMeBefore); + } + + if (TempDontDotMeBefore != tar->DontDotMeBefore()) { + tar->SetDontDotMeBefore(TempDontDotMeBefore); + } + } + + dotSelectCounter++; + + if ((dotSelectCounter == maxDotSelect) || casted_spell) { + return casted_spell; + } + } + } + } + return casted_spell; +} + +bool Bot::BotCastSnare(Mob* tar, uint8 botLevel, BotSpell& botSpell, const bool& checked_los, uint32 iSpellTypes) { + bool casted_spell = false; + if (tar->DontSnareMeBefore() < Timer::GetCurrentTime()) { + if (!checked_los && !CheckLosFN(tar)) { + return casted_spell; + } + + + botSpell = GetFirstBotSpellBySpellType(this, iSpellTypes); + + if (!IsValidSpell(botSpell.SpellId)) { + return casted_spell; + } + + if (!(!tar->IsImmuneToSpell(botSpell.SpellId, this) && tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0)) { + return casted_spell; + } + + uint32 TempDontSnareMeBefore = tar->DontSnareMeBefore(); + + if (IsValidSpellRange(botSpell.SpellId, tar)) { + casted_spell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost, &TempDontSnareMeBefore); + } + + if (TempDontSnareMeBefore != tar->DontSnareMeBefore()) { + tar->SetDontSnareMeBefore(TempDontSnareMeBefore); + } + } + return casted_spell; +} + +bool Bot::BotCastLifetap(Mob* tar, uint8 botLevel, BotSpell& botSpell, const bool& checked_los, uint32 iSpellTypes) { + bool casted_spell = false; + if (GetHPRatio() < 90.0f) { + if (!checked_los && !CheckLosFN(tar)) { + return casted_spell; + } + + + botSpell = GetFirstBotSpellBySpellType(this, iSpellTypes); + + if (!IsValidSpell(botSpell.SpellId)) { + return casted_spell; + } + + if (!(!tar->IsImmuneToSpell(botSpell.SpellId, this) && (tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0))) { + return casted_spell; + } + + if (IsValidSpellRange(botSpell.SpellId, tar)) { + casted_spell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); + } + } + return casted_spell; +} + +bool Bot::BotCastCombatBuff(Mob* tar, uint8 botLevel, uint8 botClass) { + + bool casted_spell = false; + if (tar->DontBuffMeBefore() < Timer::GetCurrentTime()) { + std::list buffSpellList = GetBotSpellsBySpellType(this, SpellType_InCombatBuff); + + for (const auto& s : buffSpellList) { + + if (!IsValidSpell(s.SpellId)) { + continue; + } + // no buffs with illusions.. use #bot command to cast illusions + if (IsEffectInSpell(s.SpellId, SE_Illusion) && tar != this) { + continue; + } + //no teleport spells use #bot command to cast teleports + if (IsEffectInSpell(s.SpellId, SE_Teleport) || IsEffectInSpell(s.SpellId, SE_Succor)) { + continue; + } + // can not cast buffs for your own pet only on another pet that isn't yours + if ((spells[s.SpellId].target_type == ST_Pet) && (tar != GetPet())) { + continue; + } + + //Conversion Spells + if ( + IsSelfConversionSpell(s.SpellId) && + ( + GetManaRatio() > 90.0f || + GetHPRatio() < 50.0f || + GetHPRatio() < (GetManaRatio() + 10.0f) + ) + ) { + break; //don't cast if low hp, lots of mana, or if mana is higher than hps + } + + // Validate target + // TODO: Add ST_TargetsTarget support for Buffing. + if ( + !( + ( + spells[s.SpellId].target_type == ST_Target || + spells[s.SpellId].target_type == ST_Pet || + (tar == this && spells[s.SpellId].target_type != ST_TargetsTarget) || + spells[s.SpellId].target_type == ST_Group || + spells[s.SpellId].target_type == ST_GroupTeleport || + (botClass == BARD && spells[s.SpellId].target_type == ST_AEBard) + ) && + !tar->IsImmuneToSpell(s.SpellId, this) && + tar->CanBuffStack(s.SpellId, botLevel, true) >= 0 + ) + ) { + continue; + } + + // Put the zone levitate and movement check here since bots are able to bypass the client casting check + if ( + ((IsEffectInSpell(s.SpellId, SE_Levitate) && !zone->CanLevitate()) || + (IsEffectInSpell(s.SpellId, SE_MovementSpeed) && !zone->CanCastOutdoor())) && + (botClass != BARD || !IsSpellUsableThisZoneType(s.SpellId, zone->GetZoneType())) + ) { + continue; + } + + if (!IsGroupSpell(s.SpellId)) { + //Only check archetype if spell is not a group spell + //Hybrids get all buffs + switch (tar->GetArchetype()) { + case ARCHETYPE_CASTER: + //TODO: probably more caster specific spell effects in here + if ( + ( + IsEffectInSpell(s.SpellId, SE_AttackSpeed) || + IsEffectInSpell(s.SpellId, SE_ATK) || + IsEffectInSpell(s.SpellId, SE_STR) || + IsEffectInSpell(s.SpellId, SE_ReverseDS) || + IsEffectInSpell(s.SpellId, SE_DamageShield) + ) && + spells[s.SpellId].target_type != ST_Self + ) { + continue; + } + break; + case ARCHETYPE_MELEE: + if ( + ( + IsEffectInSpell(s.SpellId, SE_IncreaseSpellHaste) || + IsEffectInSpell(s.SpellId, SE_ManaPool) || + IsEffectInSpell(s.SpellId, SE_CastingLevel) || + IsEffectInSpell(s.SpellId, SE_ManaRegen_v2) || + IsEffectInSpell(s.SpellId, SE_CurrentMana) + ) && + spells[s.SpellId].target_type != ST_Self + ) { + continue; + } + break; + default: + break; + } + } + // TODO: Add TriggerSpell Support for Exchanter Runes + if (botClass == ENCHANTER && IsEffectInSpell(s.SpellId, SE_Rune)) { + float manaRatioToCast = 75.0f; + + switch(GetBotStance()) { + case EQ::constants::stanceEfficient: + manaRatioToCast = 90.0f; + break; + case EQ::constants::stanceBalanced: + case EQ::constants::stanceAggressive: + manaRatioToCast = 75.0f; + break; + case EQ::constants::stanceReactive: + case EQ::constants::stanceBurn: + case EQ::constants::stanceBurnAE: + manaRatioToCast = 50.0f; + break; + default: + manaRatioToCast = 75.0f; + break; + } + + //If we're at specified mana % or below, don't rune as enchanter + if (GetManaRatio() <= manaRatioToCast) { + break; + } + } + + if (CheckSpellRecastTimers(this, s.SpellIndex)) { + uint32 TempDontBuffMeBefore = tar->DontBuffMeBefore(); + casted_spell = AIDoSpellCast(s.SpellIndex, tar, s.ManaCost, &TempDontBuffMeBefore); + if (TempDontBuffMeBefore != tar->DontBuffMeBefore()) { + tar->SetDontBuffMeBefore(TempDontBuffMeBefore); + } + } + + if (casted_spell) { + return casted_spell; + } + } + } + return casted_spell; +} + +bool Bot::BotCastPet(Mob* tar, uint8 botClass, BotSpell& botSpell) { + bool casted_spell = false; + if (!IsPet() && !GetPetID() && !IsBotCharmer()) { + if (botClass == WIZARD) { + auto buffs_max = GetMaxBuffSlots(); + auto my_buffs = GetBuffs(); + 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)) { + MakePet(my_buffs[index].spellid, spells[my_buffs[index].spellid].teleport_zone); + familiar_buff_slot = index; + break; + } + } + } + if (GetPetID()) { + return casted_spell; + } + if (familiar_buff_slot >= 0) { + BuffFadeBySlot(familiar_buff_slot); + return casted_spell; + } + + botSpell = GetFirstBotSpellBySpellType(this, SpellType_Pet); + } + else if (botClass == MAGICIAN) { + botSpell = GetBestBotMagicianPetSpell(this); + } + else { + botSpell = GetFirstBotSpellBySpellType(this, SpellType_Pet); + } + + if (!IsValidSpell(botSpell.SpellId)) { + return casted_spell; + } + + casted_spell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); + } + return casted_spell; +} + +bool Bot::BotCastDispel(Mob* tar, BotSpell& botSpell, uint32 iSpellTypes, const bool& checked_los) { + + bool casted_spell = false; + if (tar->GetHPRatio() > 95.0f) { + if (!checked_los && !CheckLosFN(tar)) { + return casted_spell; + } + + botSpell = GetFirstBotSpellBySpellType(this, iSpellTypes); + + if (!IsValidSpell(botSpell.SpellId)) { + return casted_spell; + } + // TODO: Check target to see if there is anything to dispel + + if (tar->CountDispellableBuffs() > 0 && IsValidSpellRange(botSpell.SpellId, tar)) { + casted_spell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); + } + } + return casted_spell; +} + +bool Bot::BotCastNuke(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpell, const bool& checked_los) { + + bool casted_spell = false; + if ((tar->GetHPRatio() <= 95.0f) || ((botClass == BARD) || (botClass == SHAMAN) || (botClass == ENCHANTER) || (botClass == PALADIN) || (botClass == SHADOWKNIGHT) || (botClass == WARRIOR))) + { + if (!checked_los && !CheckLosFN(tar)) { + return casted_spell; + } + + if (botClass == CLERIC || botClass == ENCHANTER) + { + float manaRatioToCast = 75.0f; + + switch(GetBotStance()) { + case EQ::constants::stanceEfficient: + manaRatioToCast = 90.0f; + break; + case EQ::constants::stanceBalanced: + manaRatioToCast = 75.0f; + break; + case EQ::constants::stanceReactive: + case EQ::constants::stanceAggressive: + manaRatioToCast = 50.0f; + break; + case EQ::constants::stanceBurn: + case EQ::constants::stanceBurnAE: + manaRatioToCast = 25.0f; + break; + default: + manaRatioToCast = 50.0f; + break; + } + + //If we're at specified mana % or below, don't nuke as cleric or enchanter + if (GetManaRatio() <= manaRatioToCast) + return casted_spell; + } + + if (botClass == MAGICIAN || botClass == SHADOWKNIGHT || botClass == NECROMANCER || botClass == PALADIN || botClass == RANGER || botClass == DRUID || botClass == CLERIC) { + if (tar->GetBodyType() == BT_Undead || tar->GetBodyType() == BT_SummonedUndead || tar->GetBodyType() == BT_Vampire) + botSpell = GetBestBotSpellForNukeByTargetType(this, ST_Undead); + else if (tar->GetBodyType() == BT_Summoned || tar->GetBodyType() == BT_Summoned2 || tar->GetBodyType() == BT_Summoned3) + botSpell = GetBestBotSpellForNukeByTargetType(this, ST_Summoned); + } + + if ((botClass == PALADIN || botClass == DRUID || botClass == CLERIC || botClass == ENCHANTER || botClass == WIZARD) && !IsValidSpell(botSpell.SpellId)) { + uint8 stunChance = (tar->IsCasting() ? 30: 15); + + if (botClass == PALADIN) { + stunChance = 50; + } + + if (!tar->GetSpecialAbility(UNSTUNABLE) && !tar->IsStunned() && (zone->random.Int(1, 100) <= stunChance)) { + botSpell = GetBestBotSpellForStunByTargetType(this, ST_Target); + } + } + + if (botClass == WIZARD && botSpell.SpellId == 0) { + botSpell = GetBestBotWizardNukeSpellByTargetResists(this, tar); + } + + if (!IsValidSpell(botSpell.SpellId)) { + botSpell = GetBestBotSpellForNukeByTargetType(this, ST_Target); + } + if (!IsValidSpell(botSpell.SpellId)) { + return casted_spell; + } + if (!(!tar->IsImmuneToSpell(botSpell.SpellId, this) && (tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0))) { + return casted_spell; + } + if (IsFearSpell(botSpell.SpellId) && tar->GetSnaredAmount() == -1 && !tar->IsRooted()) { + return casted_spell; + } + + if (IsValidSpellRange(botSpell.SpellId, tar)) { + casted_spell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); + } + } + return casted_spell; +} + +bool Bot::BotCastEscape(Mob*& tar, uint8 botClass, BotSpell& botSpell, uint32 iSpellTypes) { + + bool casted_spell = false; + auto hpr = (uint8) GetHPRatio(); + bool mayGetAggro = false; + + if (hpr > 15 && ((botClass == WIZARD) || (botClass == ENCHANTER) || (botClass == RANGER))) { + mayGetAggro = HasOrMayGetAggro(); + } + + if (hpr <= 15 || mayGetAggro) + { + botSpell = GetFirstBotSpellBySpellType(this, iSpellTypes); + + if (!IsValidSpell(botSpell.SpellId)) { + return casted_spell; + } + + if (IsInvulnerabilitySpell(botSpell.SpellId)) { + tar = this; //target self for invul type spells + } + + if (IsValidSpellRange(botSpell.SpellId, tar) || botClass == BARD) { + casted_spell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); + } + } + return casted_spell; +} + +bool Bot::BotCastBuff(Mob* tar, uint8 botLevel, uint8 botClass) { + bool casted_spell = false; + if (tar->DontBuffMeBefore() < Timer::GetCurrentTime()) { + std::list buffSpellList = GetBotSpellsBySpellType(this, SpellType_Buff); + + for(const auto& s : buffSpellList) { + + if (!IsValidSpell(s.SpellId)) { + continue; + } + + // no buffs with illusions.. use #bot command to cast illusions + if (IsEffectInSpell(s.SpellId, SE_Illusion) && tar != this) { + continue; + } + + //no teleport spells use #bot command to cast teleports + if (IsEffectInSpell(s.SpellId, SE_Teleport) || IsEffectInSpell(s.SpellId, SE_Succor)) { + continue; + } + // can not cast buffs for your own pet only on another pet that isn't yours + if ((spells[s.SpellId].target_type == ST_Pet) && (tar != GetPet())) { + continue; + } + + // Validate target + // TODO: Add ST_TargetsTarget support for Buffing. + if ( + !( + ( + spells[s.SpellId].target_type == ST_Target || + spells[s.SpellId].target_type == ST_Pet || + (tar == this && spells[s.SpellId].target_type != ST_TargetsTarget) || + spells[s.SpellId].target_type == ST_Group || + spells[s.SpellId].target_type == ST_GroupTeleport || + (botClass == BARD && spells[s.SpellId].target_type == ST_AEBard) + ) && + !tar->IsImmuneToSpell(s.SpellId, this) && + tar->CanBuffStack(s.SpellId, botLevel, true) >= 0 + ) + ) { + continue; + } + + // Put the zone levitate and movement check here since bots are able to bypass the client casting check + if ( + ( + (IsEffectInSpell(s.SpellId, SE_Levitate) && !zone->CanLevitate()) || + (IsEffectInSpell(s.SpellId, SE_MovementSpeed) && !zone->CanCastOutdoor()) + ) && + (botClass != BARD || !IsSpellUsableThisZoneType(s.SpellId, zone->GetZoneType())) + ) { + continue; + } + + switch (tar->GetArchetype()) + { + case ARCHETYPE_CASTER: + //TODO: probably more caster specific spell effects in here + if (IsEffectInSpell(s.SpellId, SE_AttackSpeed) || IsEffectInSpell(s.SpellId, SE_ATK) || + IsEffectInSpell(s.SpellId, SE_STR) || IsEffectInSpell(s.SpellId, SE_ReverseDS)) + { + continue; + } + break; + case ARCHETYPE_MELEE: + if (IsEffectInSpell(s.SpellId, SE_IncreaseSpellHaste) || IsEffectInSpell(s.SpellId, SE_ManaPool) || + IsEffectInSpell(s.SpellId, SE_CastingLevel) || IsEffectInSpell(s.SpellId, SE_ManaRegen_v2) || + IsEffectInSpell(s.SpellId, SE_CurrentMana)) + { + continue; + } + break; + default: //Hybrids get all buffs + break; + } + + if (botClass == ENCHANTER && IsEffectInSpell(s.SpellId, SE_Rune)) + { + float manaRatioToCast = 75.0f; + + switch (GetBotStance()) { + case EQ::constants::stanceEfficient: + manaRatioToCast = 90.0f; + break; + case EQ::constants::stanceBalanced: + case EQ::constants::stanceAggressive: + manaRatioToCast = 75.0f; + break; + case EQ::constants::stanceReactive: + case EQ::constants::stanceBurn: + case EQ::constants::stanceBurnAE: + manaRatioToCast = 50.0f; + break; + default: + manaRatioToCast = 75.0f; + break; + } + + //If we're at specified mana % or below, don't rune as enchanter + if (GetManaRatio() <= manaRatioToCast) { + return casted_spell; + } + } + + if (CheckSpellRecastTimers(this, s.SpellIndex)) + { + uint32 TempDontBuffMeBefore = tar->DontBuffMeBefore(); + + casted_spell = AIDoSpellCast(s.SpellIndex, tar, s.ManaCost, &TempDontBuffMeBefore); + + if (TempDontBuffMeBefore != tar->DontBuffMeBefore()) { + tar->SetDontBuffMeBefore(TempDontBuffMeBefore); + } + } + } + } + return casted_spell; +} + +bool Bot::BotCastRoot(Mob* tar, uint8 botLevel, uint32 iSpellTypes, BotSpell& botSpell, const bool& checked_los) { + bool casted_spell = false; + if (!tar->IsRooted() && tar->DontRootMeBefore() < Timer::GetCurrentTime()) { + if (!checked_los && !CheckLosFN(tar)) { + return casted_spell; + } + + // TODO: If there is a ranger in the group then don't allow root spells + + botSpell = GetFirstBotSpellBySpellType(this, iSpellTypes); + + if (!IsValidSpell(botSpell.SpellId)) { + return casted_spell; + } + if (tar->CanBuffStack(botSpell.SpellId, botLevel, true) == 0) { + return casted_spell; + } + uint32 TempDontRootMeBefore = tar->DontRootMeBefore(); + + if (IsValidSpellRange(botSpell.SpellId, tar)) { + casted_spell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost, &TempDontRootMeBefore); + } + + if (TempDontRootMeBefore != tar->DontRootMeBefore()) { + tar->SetDontRootMeBefore(TempDontRootMeBefore); + } + } + return casted_spell; +} + +bool Bot::BotCastHeal(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpell, Raid* raid) { + bool casted_spell = false; + if (tar->DontHealMeBefore() < Timer::GetCurrentTime()) { + auto hpr = (uint8)tar->GetHPRatio(); + bool hasAggro = false; + bool isPrimaryHealer = false; + + if (HasGroup() || IsRaidGrouped()) { + isPrimaryHealer = IsGroupHealer(); + } + + if (hpr < 95 || (tar->IsClient() && (hpr < 95)) || (botClass == BARD)) { + if (tar->GetClass() == NECROMANCER && hpr >= 40) { + return false; + } + + if (tar->GetClass() == SHAMAN && hpr >= 80) { + return false; + } + + // Evaluate the situation + if ((IsEngaged()) && ((botClass == CLERIC) || (botClass == DRUID) || (botClass == SHAMAN) || (botClass == PALADIN))) { + if (tar->GetTarget() && tar->GetTarget()->GetHateTop() && tar->GetTarget()->GetHateTop() == tar) { + hasAggro = true; + } + + if (hpr < 35) { + botSpell = GetBestBotSpellForFastHeal(this); + } + else if (hpr >= 35 && hpr < 70) { + if (GetNumberNeedingHealedInGroup(60, false, raid) >= 3) { + botSpell = GetBestBotSpellForGroupHeal(this); + } + + if (!IsValidSpell(botSpell.SpellId)) { + botSpell = GetBestBotSpellForPercentageHeal(this); + } + } + else if (hpr >= 70 && hpr < 95) { + if (GetNumberNeedingHealedInGroup(80, false, raid) >= 3) { + botSpell = GetBestBotSpellForGroupHealOverTime(this); + } + + if (hasAggro) { + botSpell = GetBestBotSpellForPercentageHeal(this); + } + } + else { + if (!tar->FindType(SE_HealOverTime)) { + botSpell = GetBestBotSpellForHealOverTime(this); + } + } + } + else if ((botClass == CLERIC) || (botClass == DRUID) || (botClass == SHAMAN) || (botClass == PALADIN)) { + if (GetNumberNeedingHealedInGroup(40, true, raid) >= 2) { + botSpell = GetBestBotSpellForGroupCompleteHeal(this); + + if (!IsValidSpell(botSpell.SpellId)) { + botSpell = GetBestBotSpellForGroupHeal(this); + } + + if (!IsValidSpell(botSpell.SpellId)) { + botSpell = GetBestBotSpellForGroupHealOverTime(this); + } + + if (hpr < 40 && !IsValidSpell(botSpell.SpellId)) { + botSpell = GetBestBotSpellForPercentageHeal(this); + } + } + else if (GetNumberNeedingHealedInGroup(60, true, raid) >= 2) { + botSpell = GetBestBotSpellForGroupHeal(this); + + if (!IsValidSpell(botSpell.SpellId)) { + botSpell = GetBestBotSpellForGroupHealOverTime(this); + } + + if (hpr < 40 && !IsValidSpell(botSpell.SpellId)) { + botSpell = GetBestBotSpellForPercentageHeal(this); + } + } + else if (hpr < 40) { + botSpell = GetBestBotSpellForPercentageHeal(this); + } + else if (hpr >= 40 && hpr < 75) { + botSpell = GetBestBotSpellForRegularSingleTargetHeal(this); + } + else { + if (hpr < 90 && !tar->FindType(SE_HealOverTime)) { + botSpell = GetBestBotSpellForHealOverTime(this); + } + } + } + else { + float hpRatioToCast = 0.0f; + + switch (GetBotStance()) { + case EQ::constants::stanceEfficient: + case EQ::constants::stanceAggressive: + hpRatioToCast = isPrimaryHealer ? 90.0f : 50.0f; + break; + case EQ::constants::stanceBalanced: + hpRatioToCast = isPrimaryHealer ? 95.0f : 75.0f; + break; + case EQ::constants::stanceReactive: + hpRatioToCast = isPrimaryHealer ? 100.0f : 90.0f; + break; + case EQ::constants::stanceBurn: + case EQ::constants::stanceBurnAE: + hpRatioToCast = isPrimaryHealer ? 75.0f : 25.0f; + break; + default: + hpRatioToCast = isPrimaryHealer ? 100.0f : 0.0f; + break; + } + + //If we're at specified mana % or below, don't heal as hybrid + if (tar->GetHPRatio() <= hpRatioToCast) { + botSpell = GetBestBotSpellForRegularSingleTargetHeal(this); + } + } + + if (!IsValidSpell(botSpell.SpellId)) { + botSpell = GetBestBotSpellForRegularSingleTargetHeal(this); + } + if (!IsValidSpell(botSpell.SpellId)) { + botSpell = GetFirstBotSpellForSingleTargetHeal(this); + } + if (botSpell.SpellId == 0 && botClass == BARD) { + botSpell = GetFirstBotSpellBySpellType(this, SpellType_Heal); + } + + if (!IsValidSpell(botSpell.SpellId)) { + return false; + } + // Can we cast this spell on this target? + if (!(spells[botSpell.SpellId].target_type==ST_GroupTeleport || spells[botSpell.SpellId].target_type == ST_Target || tar == this) + && tar->CanBuffStack(botSpell.SpellId, botLevel, true) < 0) { + return false; + } + + uint32 TempDontHealMeBeforeTime = tar->DontHealMeBefore(); + + if (IsValidSpellRange(botSpell.SpellId, tar) || botClass == BARD) { + casted_spell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost, &TempDontHealMeBeforeTime); + } + + if (casted_spell && botClass != BARD) { + if (IsGroupSpell(botSpell.SpellId)) { + if (HasGroup()) { + Group *group = GetGroup(); + if (group) { + BotGroupSay( + this, + fmt::format( + "Casting {}.", + spells[botSpell.SpellId].name + ).c_str() + ); + + for (const auto& member : group->members) { + if (member && !member->qglobal) { + member->SetDontHealMeBefore(Timer::GetCurrentTime() + 1000); + } + } + } else if (IsRaidGrouped()) { + uint32 r_group = raid->GetGroup(GetName()); + const auto msg = fmt::format("Casting {}.", spells[botSpell.SpellId].name); + raid->RaidGroupSay(msg.c_str(), GetCleanName(), 0, 100); + std::vector raid_group_members = raid->GetRaidGroupMembers(r_group); + for (const auto& rgm : raid_group_members) { + if (rgm.member && !rgm.member->qglobal) { + rgm.member->SetDontHealMeBefore(Timer::GetCurrentTime() + 1000); + } + } + } + } else { + if (tar != this) { //we don't need spam of bots healing themselves + BotGroupSay( + this, + fmt::format( + "Casting {} on {}.", + spells[botSpell.SpellId].name, + tar->GetCleanName() + ).c_str() + ); + } + } + } + tar->SetDontHealMeBefore(Timer::GetCurrentTime() + 2000); + } + } + } + return casted_spell; +} + +bool Bot::BotCastMez(Mob* tar, uint8 botLevel, bool checked_los, BotSpell& botSpell, Raid* raid) { + bool casted_spell = false; + if (!checked_los && !CheckLosFN(tar)) { + return false; + } + + //TODO + //Check if single target or AoE mez is best + //if (TARGETS ON MT IS => 3 THEN botSpell = AoEMez) + //if (TARGETS ON MT IS <= 2 THEN botSpell = BestMez) + + botSpell = GetBestBotSpellForMez(this); + + if (!IsValidSpell(botSpell.SpellId)) { + return false; + } + + Mob* addMob = GetFirstIncomingMobToMez(this, botSpell); + + if (!addMob) { + return false; + } + + if (!(!addMob->IsImmuneToSpell(botSpell.SpellId, this) && addMob->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0)) { + return false; + } + + if (IsValidSpellRange(botSpell.SpellId, addMob)) { + casted_spell = AIDoSpellCast(botSpell.SpellIndex, addMob, botSpell.ManaCost); + } + if (casted_spell) { + if (raid) { + raid->RaidSay( + GetCleanName(), + fmt::format( + "Attempting to mesmerize {} with {}.", + addMob->GetCleanName(), + spells[botSpell.SpellId].name + ).c_str(), + 0, + 100 + ); + } else { + BotGroupSay( + this, + fmt::format( + "Attempting to mesmerize {} with {}.", + addMob->GetCleanName(), + spells[botSpell.SpellId].name + ).c_str() + ); + } + } + return casted_spell; +} + +bool Bot::AIDoSpellCast(int32 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore) { bool result = false; // manacost has special values, -1 is no mana cost, -2 is instant cast (no mana) int32 manaCost = mana_cost; - if (manaCost == -1) + if (manaCost == -1) { manaCost = spells[AIBot_spells[i].spellid].mana; - else if (manaCost == -2) + } else if (manaCost == -2) { manaCost = 0; + } - int32 extraMana = 0; - int32 hasMana = GetMana(); + int64 hasMana = GetMana(); // Allow bots to cast buff spells even if they are out of mana - if (RuleB(Bots, FinishBuffing)) { - if (manaCost > hasMana) { - // Let's have the bots complete the buff time process - if (AIBot_spells[i].type & SpellType_Buff) { - extraMana = manaCost - hasMana; - SetMana(manaCost); - } - } + if ( + RuleB(Bots, FinishBuffing) && + manaCost > hasMana && AIBot_spells[i].type & SpellType_Buff + ) { + SetMana(manaCost); } float dist2 = 0; @@ -1198,7 +1294,7 @@ bool Bot::AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgain ) && ( mana_cost <= GetMana() || - GetMana() == GetMaxMana() + IsBotNonSpellFighter() ) ) { casting_spell_AIindex = i; @@ -1212,19 +1308,8 @@ bool Bot::AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgain // if the spell wasn't casted, then take back any extra mana that was given to the bot to cast that spell if (!result) { SetMana(hasMana); - extraMana = false; } - else { //handle spell recast and recast timers - //if (GetClass() == BARD && IsGroupSpell(AIBot_spells[i].spellid)) { - // // Bard buff songs have been moved to their own npc spell type.. - // // Buff stacking is now checked as opposed to manipulating the timer to avoid rapid casting - - // //AIBot_spells[i].time_cancast = (spells[AIBot_spells[i].spellid].recast_time > (spells[AIBot_spells[i].spellid].buffduration * 6000)) ? Timer::GetCurrentTime() + spells[AIBot_spells[i].spellid].recast_time : Timer::GetCurrentTime() + spells[AIBot_spells[i].spellid].buffduration * 6000; - // //spellend_timer.Start(spells[AIBot_spells[i].spellid].cast_time); - //} - //else - // AIBot_spells[i].time_cancast = Timer::GetCurrentTime() + spells[AIBot_spells[i].spellid].recast_time; - + else { AIBot_spells[i].time_cancast = Timer::GetCurrentTime() + spells[AIBot_spells[i].spellid].recast_time; if (spells[AIBot_spells[i].spellid].timer_id > 0) { @@ -1245,21 +1330,14 @@ bool Bot::AI_PursueCastCheck() { LogAIDetail("Bot Engaged (pursuing) autocast check triggered. Trying to cast offensive spells"); if (!AICastSpell(GetTarget(), 100, SpellType_Snare)) { - if (!AICastSpell(GetTarget(), 100, SpellType_Lifetap)) { - if (!AICastSpell(GetTarget(), 100, SpellType_Nuke)) { - /*AIautocastspell_timer->Start(RandomTimer(500, 2000), false); - result = true;*/ - result = true; - } - - result = true; + if (!AICastSpell(GetTarget(), 100, SpellType_Lifetap) && !AICastSpell(GetTarget(), 100, SpellType_Nuke)) { } - result = true; } - if (!AIautocastspell_timer->Enabled()) + if (!AIautocastspell_timer->Enabled()) { AIautocastspell_timer->Start(RandomTimer(100, 250), false); + } } return result; @@ -1277,8 +1355,7 @@ bool Bot::AI_IdleCastCheck() { if (HasGroup() && GetGroup()->GetLeader() && GetGroup()->GetLeader()->IsClient()) { test_against = GetGroup()->GetLeader()->CastToClient(); - } - else if (GetOwner() && GetOwner()->IsClient()) { + } else if (GetOwner() && GetOwner()->IsClient()) { test_against = GetOwner()->CastToClient(); } @@ -1291,17 +1368,12 @@ bool Bot::AI_IdleCastCheck() { // Healers WITHOUT pets will check if a heal is needed before buffing. case CLERIC: case PALADIN: - case RANGER: - case MONK: - case ROGUE: - case WARRIOR: - case BERSERKER: { + case RANGER: { if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Cure)) { if (!AICastSpell(this, 100, SpellType_Heal)) { if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Heal)) { if (!AICastSpell(this, 100, SpellType_Buff)) { if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Buff)) { - // } } } @@ -1311,13 +1383,46 @@ bool Bot::AI_IdleCastCheck() { result = true; break; } + case MONK: + case ROGUE: + case WARRIOR: + case BERSERKER: { + if (!AICastSpell(this, 100, SpellType_Cure)) { + if (!AICastSpell(this, 100, SpellType_Heal)) { + if (!AICastSpell(this, 100, SpellType_Buff)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Buff)) { + } + } + } + } + + result = true; + break; + } // Pets class will first cast their pet, then buffs - case DRUID: + case MAGICIAN: case SHADOWKNIGHT: - case SHAMAN: case NECROMANCER: - case ENCHANTER: + case ENCHANTER: { + if (!AICastSpell(this, 100, SpellType_Pet)) { + if (!AICastSpell(this, 100, SpellType_Cure)) { + if (!AICastSpell(GetPet(), 100, SpellType_Cure)) { + if (!AICastSpell(this, 100, SpellType_Buff)) { + if (!AICastSpell(GetPet(), 100, SpellType_Heal)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Buff)) { + } + } + } + } + } + } + + result = true; + break; + } + case DRUID: + case SHAMAN: case BEASTLORD: { if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Cure)) { if (!AICastSpell(this, 100, SpellType_Pet)) { @@ -1339,16 +1444,12 @@ bool Bot::AI_IdleCastCheck() { } case WIZARD: { // This can eventually be move into the BEASTLORD case handler once pre-combat is fully implemented if (pre_combat) { - if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Cure)) { - if (!AICastSpell(this, 100, SpellType_Pet)) { + if (!AICastSpell(this, 100, SpellType_Pet)) { + if (!AICastSpell(this, 100, SpellType_Cure)) { if (!AICastSpell(this, 100, SpellType_Heal)) { - if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Heal)) { - if (!AICastSpell(this, 100, SpellType_Buff)) { - if (!AICastSpell(GetPet(), 100, SpellType_Heal)) { - if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_PreCombatBuff)) { - if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Buff)) { - } - } + if (!AICastSpell(this, 100, SpellType_Buff)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_PreCombatBuff)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Buff)) { } } } @@ -1357,15 +1458,11 @@ bool Bot::AI_IdleCastCheck() { } } else { - if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Cure)) { + if (!AICastSpell(this, 100, SpellType_Cure)) { if (!AICastSpell(this, 100, SpellType_Pet)) { if (!AICastSpell(this, 100, SpellType_Heal)) { - if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Heal)) { - if (!AICastSpell(this, 100, SpellType_Buff)) { - if (!AICastSpell(GetPet(), 100, SpellType_Heal)) { - if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Buff)) { - } - } + if (!AICastSpell(this, 100, SpellType_Buff)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Buff)) { } } } @@ -1421,7 +1518,6 @@ bool Bot::AI_EngagedCastCheck() { AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting. uint8 botClass = GetClass(); - EQ::constants::StanceType botStance = GetBotStance(); bool mayGetAggro = HasOrMayGetAggro(); LogAIDetail("Engaged autocast check triggered (BOTS). Trying to cast healing spells then maybe offensive spells"); @@ -1470,7 +1566,6 @@ bool Bot::AI_EngagedCastCheck() { if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_DOT), SpellType_DOT)) { if (!AICastSpell(GetTarget(), mayGetAggro?0:GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) { if (!AICastSpell(GetPet(), GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) { - //AIautocastspell_timer->Start(RandomTimer(100, 250), false); // Do not give healer classes a lot of time off or your tank's die failedToCast = true; } } @@ -1732,19 +1827,19 @@ bool Bot::AIHealRotation(Mob* tar, bool useFastHeals) { if (useFastHeals) { botSpell = GetBestBotSpellForRegularSingleTargetHeal(this); - if (botSpell.SpellId == 0) + if (!IsValidSpell(botSpell.SpellId)) botSpell = GetBestBotSpellForFastHeal(this); } else { botSpell = GetBestBotSpellForPercentageHeal(this); - if (botSpell.SpellId == 0) { + if (!IsValidSpell(botSpell.SpellId)) { botSpell = GetBestBotSpellForRegularSingleTargetHeal(this); } - if (botSpell.SpellId == 0) { + if (!IsValidSpell(botSpell.SpellId)) { botSpell = GetFirstBotSpellForSingleTargetHeal(this); } - if (botSpell.SpellId == 0) { + if (!IsValidSpell(botSpell.SpellId)) { botSpell = GetFirstBotSpellBySpellType(this, SpellType_Heal); } } @@ -1755,17 +1850,26 @@ bool Bot::AIHealRotation(Mob* tar, bool useFastHeals) { LogAIDetail("target [{}] current_time [{}] donthealmebefore [{}]", tar->GetCleanName(), Timer::GetCurrentTime(), tar->DontHealMeBefore()); // If there is still no spell id, then there isn't going to be one so we are done - if (botSpell.SpellId == 0) + if (!IsValidSpell(botSpell.SpellId)) { return false; + } // Can we cast this spell on this target? - if (!(spells[botSpell.SpellId].target_type == ST_GroupTeleport || spells[botSpell.SpellId].target_type == ST_Target || tar == this) - && !(tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0)) + if (! + ( + spells[botSpell.SpellId].target_type == ST_GroupTeleport || + spells[botSpell.SpellId].target_type == ST_Target || + tar == this + ) && + tar->CanBuffStack(botSpell.SpellId, botLevel, true) < 0 + ) { return false; + } uint32 TempDontHealMeBeforeTime = tar->DontHealMeBefore(); - - castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost, &TempDontHealMeBeforeTime); + if (IsValidSpellRange(botSpell.SpellId, tar)) { + castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost, &TempDontHealMeBeforeTime); + } if (castedSpell) { BotGroupSay( @@ -1784,8 +1888,7 @@ bool Bot::AIHealRotation(Mob* tar, bool useFastHeals) { std::list Bot::GetBotSpellsForSpellEffect(Bot* botCaster, int spellEffect) { std::list result; - auto bot_owner = botCaster->GetBotOwner(); - if (!bot_owner) { + if (auto bot_owner = botCaster->GetBotOwner(); !bot_owner) { return result; } @@ -1816,8 +1919,7 @@ std::list Bot::GetBotSpellsForSpellEffect(Bot* botCaster, int spellEff std::list Bot::GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster, int spellEffect, SpellTargetType targetType) { std::list result; - auto bot_owner = botCaster->GetBotOwner(); - if (!bot_owner) { + if (auto bot_owner = botCaster->GetBotOwner(); !bot_owner) { return result; } @@ -1831,15 +1933,18 @@ std::list Bot::GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster, continue; } - if (IsEffectInSpell(botSpellList[i].spellid, spellEffect) || GetTriggerSpellID(botSpellList[i].spellid, spellEffect)) { - if (spells[botSpellList[i].spellid].target_type == targetType) { - BotSpell botSpell; - botSpell.SpellId = botSpellList[i].spellid; - botSpell.SpellIndex = i; - botSpell.ManaCost = botSpellList[i].manacost; - - result.push_back(botSpell); - } + if ( + ( + IsEffectInSpell(botSpellList[i].spellid, spellEffect) || + GetTriggerSpellID(botSpellList[i].spellid, spellEffect) + ) && + spells[botSpellList[i].spellid].target_type == targetType + ) { + BotSpell botSpell; + botSpell.SpellId = botSpellList[i].spellid; + botSpell.SpellIndex = i; + botSpell.ManaCost = botSpellList[i].manacost; + result.push_back(botSpell); } } } @@ -1850,8 +1955,7 @@ std::list Bot::GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster, std::list Bot::GetBotSpellsBySpellType(Bot* botCaster, uint32 spellType) { std::list result; - auto bot_owner = botCaster->GetBotOwner(); - if (!bot_owner) { + if (auto bot_owner = botCaster->GetBotOwner(); !bot_owner) { return result; } @@ -1905,7 +2009,7 @@ std::list Bot::GetPrioritizedBotSpellsBySpellType(Bot* botCa if (result.size() > 1) { result.sort( - [](BotSpell_wPriority& l, BotSpell_wPriority& r) { + [](BotSpell_wPriority const& l, BotSpell_wPriority const& r) { return l.Priority < r.Priority; } ); @@ -1955,12 +2059,12 @@ BotSpell Bot::GetBestBotSpellForFastHeal(Bot *botCaster) { if (botCaster) { std::list botSpellList = GetBotSpellsForSpellEffect(botCaster, SE_CurrentHP); - for (std::list::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) { + for (auto botSpellListItr : botSpellList) { // Assuming all the spells have been loaded into this list by level and in descending order - if (IsFastHealSpell(botSpellListItr->SpellId) && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) { - result.SpellId = botSpellListItr->SpellId; - result.SpellIndex = botSpellListItr->SpellIndex; - result.ManaCost = botSpellListItr->ManaCost; + if (IsFastHealSpell(botSpellListItr.SpellId) && CheckSpellRecastTimers(botCaster, botSpellListItr.SpellIndex)) { + result.SpellId = botSpellListItr.SpellId; + result.SpellIndex = botSpellListItr.SpellIndex; + result.ManaCost = botSpellListItr.ManaCost; break; } @@ -1981,9 +2085,9 @@ BotSpell Bot::GetBestBotSpellForHealOverTime(Bot* botCaster) { std::list botHoTSpellList = GetBotSpellsForSpellEffect(botCaster, SE_HealOverTime); std::vector botSpellList = botCaster->AIBot_spells; - for (std::list::iterator botSpellListItr = botHoTSpellList.begin(); botSpellListItr != botHoTSpellList.end(); ++botSpellListItr) { + for (auto botSpellListItr : botHoTSpellList) { // Assuming all the spells have been loaded into this list by level and in descending order - if (IsHealOverTimeSpell(botSpellListItr->SpellId)) { + if (IsHealOverTimeSpell(botSpellListItr.SpellId)) { for (int i = botSpellList.size() - 1; i >= 0; i--) { if (!IsValidSpell(botSpellList[i].spellid)) { // this is both to quit early to save cpu and to avoid casting bad spells @@ -1992,13 +2096,13 @@ BotSpell Bot::GetBestBotSpellForHealOverTime(Bot* botCaster) { } if ( - botSpellList[i].spellid == botSpellListItr->SpellId && + botSpellList[i].spellid == botSpellListItr.SpellId && (botSpellList[i].type & SpellType_Heal) && - CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex) + CheckSpellRecastTimers(botCaster, botSpellListItr.SpellIndex) ) { - result.SpellId = botSpellListItr->SpellId; - result.SpellIndex = botSpellListItr->SpellIndex; - result.ManaCost = botSpellListItr->ManaCost; + result.SpellId = botSpellListItr.SpellId; + result.SpellIndex = botSpellListItr.SpellIndex; + result.ManaCost = botSpellListItr.ManaCost; } } @@ -2598,11 +2702,11 @@ BotSpell Bot::GetBestBotSpellForResistDebuff(Bot* botCaster, Mob *tar) { { level_mod = -level_mod; } - bool needsMagicResistDebuff = (tar->GetMR() + level_mod) > 100 ? true: false; - bool needsColdResistDebuff = (tar->GetCR() + level_mod) > 100 ? true: false; - bool needsFireResistDebuff = (tar->GetFR() + level_mod) > 100 ? true: false; - bool needsPoisonResistDebuff = (tar->GetPR() + level_mod) > 100 ? true: false; - bool needsDiseaseResistDebuff = (tar->GetDR() + level_mod) > 100 ? true: false; + bool needsMagicResistDebuff = (tar->GetMR() + level_mod) > 100; + bool needsColdResistDebuff = (tar->GetCR() + level_mod) > 100; + bool needsFireResistDebuff = (tar->GetFR() + level_mod) > 100; + bool needsPoisonResistDebuff = (tar->GetPR() + level_mod) > 100; + bool needsDiseaseResistDebuff = (tar->GetDR() + level_mod) > 100; if (botCaster && botCaster->AI_HasSpells()) { std::vector botSpellList = botCaster->AIBot_spells; @@ -3456,3 +3560,17 @@ bool Bot::HasBotSpellEntry(uint16 spellid) { return false; } + +bool Bot::IsValidSpellRange(uint16 spell_id, Mob const* tar) { + if (!IsValidSpell(spell_id)) { + return false; + } + + if (tar) { + int spellrange = (GetActSpellRange(spell_id, spells[spell_id].range) * GetActSpellRange(spell_id, spells[spell_id].range)); + if (spellrange >= DistanceSquared(m_Position, tar->GetPosition())) { + return true; + } + } + return false; +} diff --git a/zone/cheat_manager.cpp b/zone/cheat_manager.cpp index f780bb5f1..b48fa4d31 100644 --- a/zone/cheat_manager.cpp +++ b/zone/cheat_manager.cpp @@ -1,6 +1,10 @@ #include "cheat_manager.h" #include "client.h" #include "quest_parser_collection.h" +#include "../common/events/player_event_logs.h" +#include "worldserver.h" + +extern WorldServer worldserver; void CheatManager::SetClient(Client *cli) { @@ -36,20 +40,21 @@ void CheatManager::CheatDetected(CheatTypes type, glm::vec3 position1, glm::vec3 position2.z, Distance(position1, position2) ); - database.SetMQDetectionFlag( - m_target->AccountName(), - m_target->GetName(), - message.c_str(), - zone->GetShortName() - ); + + RecordPlayerEventLogWithClient(m_target, PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); + LogCheat(fmt::runtime(message)); - std::string export_string = fmt::format( - "{} {} {}", - position1.x, - position1.y, - position1.z - ); - parse->EventPlayer(EVENT_WARP, m_target, export_string, 0); + + if (parse->PlayerHasQuestSub(EVENT_WARP)) { + const auto& export_string = fmt::format( + "{} {} {}", + position1.x, + position1.y, + position1.z + ); + + parse->EventPlayer(EVENT_WARP, m_target, export_string, 0); + } } break; case MQWarpAbsolute: @@ -65,20 +70,20 @@ void CheatManager::CheatDetected(CheatTypes type, glm::vec3 position1, glm::vec3 position2.z, Distance(position1, position2) ); - database.SetMQDetectionFlag( - m_target->AccountName(), - m_target->GetName(), - message.c_str(), - zone->GetShortName() - ); + RecordPlayerEventLogWithClient(m_target, PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); LogCheat(fmt::runtime(message)); - std::string export_string = fmt::format( - "{} {} {}", - position1.x, - position1.y, - position1.z - ); - parse->EventPlayer(EVENT_WARP, m_target, export_string, 0); + + if (parse->PlayerHasQuestSub(EVENT_WARP)) { + const auto& export_string = fmt::format( + "{} {} {}", + position1.x, + position1.y, + position1.z + ); + + parse->EventPlayer(EVENT_WARP, m_target, export_string, 0); + } + m_time_since_last_warp_detection.Start(2500); } break; @@ -91,12 +96,7 @@ void CheatManager::CheatDetected(CheatTypes type, glm::vec3 position1, glm::vec3 position1.y, position1.z ); - database.SetMQDetectionFlag( - m_target->AccountName(), - m_target->GetName(), - message.c_str(), - zone->GetShortName() - ); + RecordPlayerEventLogWithClient(m_target, PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); LogCheat(fmt::runtime(message)); } break; @@ -109,12 +109,7 @@ void CheatManager::CheatDetected(CheatTypes type, glm::vec3 position1, glm::vec3 position1.y, position1.z ); - database.SetMQDetectionFlag( - m_target->AccountName(), - m_target->GetName(), - message.c_str(), - zone->GetShortName() - ); + RecordPlayerEventLogWithClient(m_target, PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); LogCheat(fmt::runtime(message)); } break; @@ -129,12 +124,7 @@ void CheatManager::CheatDetected(CheatTypes type, glm::vec3 position1, glm::vec3 position1.y, position1.z ); - database.SetMQDetectionFlag( - m_target->AccountName(), - m_target->GetName(), - message.c_str(), - zone->GetShortName() - ); + RecordPlayerEventLogWithClient(m_target, PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); LogCheat(fmt::runtime(message)); } } @@ -149,12 +139,7 @@ void CheatManager::CheatDetected(CheatTypes type, glm::vec3 position1, glm::vec3 position1.y, position1.z ); - database.SetMQDetectionFlag( - m_target->AccountName(), - m_target->GetName(), - message.c_str(), - zone->GetShortName() - ); + RecordPlayerEventLogWithClient(m_target, PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); LogCheat(fmt::runtime(message)); } break; @@ -167,12 +152,7 @@ void CheatManager::CheatDetected(CheatTypes type, glm::vec3 position1, glm::vec3 position1.y, position1.z ); - database.SetMQDetectionFlag( - m_target->AccountName(), - m_target->GetName(), - message.c_str(), - zone->GetShortName() - ); + RecordPlayerEventLogWithClient(m_target, PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); LogCheat(fmt::runtime(message)); } break; @@ -185,12 +165,7 @@ void CheatManager::CheatDetected(CheatTypes type, glm::vec3 position1, glm::vec3 position1.y, position1.z ); - database.SetMQDetectionFlag( - m_target->AccountName(), - m_target->GetName(), - message.c_str(), - zone->GetShortName() - ); + RecordPlayerEventLogWithClient(m_target, PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); LogCheat(fmt::runtime(message)); } break; @@ -199,17 +174,13 @@ void CheatManager::CheatDetected(CheatTypes type, glm::vec3 position1, glm::vec3 if (RuleB(Cheat, EnableMQGhostDetector) && ((m_target->Admin() < RuleI(Cheat, MQGhostExemptStatus) || (RuleI(Cheat, MQGhostExemptStatus)) == -1))) { - database.SetMQDetectionFlag( - m_target->AccountName(), - m_target->GetName(), - "Packet blocking detected.", - zone->GetShortName() - ); - LogCheat( + std::string message = fmt::format( "[MQGhost] [{}] [{}] was caught not sending the proper packets as regularly as they were suppose to.", m_target->AccountName(), m_target->GetName() ); + RecordPlayerEventLogWithClient(m_target, PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); + LogCheat("{}", message); } break; case MQFastMem: @@ -222,12 +193,7 @@ void CheatManager::CheatDetected(CheatTypes type, glm::vec3 position1, glm::vec3 position1.y, position1.z ); - database.SetMQDetectionFlag( - m_target->AccountName(), - m_target->GetName(), - message.c_str(), - zone->GetShortName() - ); + RecordPlayerEventLogWithClient(m_target, PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); LogCheat(fmt::runtime(message)); } break; @@ -238,12 +204,7 @@ void CheatManager::CheatDetected(CheatTypes type, glm::vec3 position1, glm::vec3 position1.y, position1.z ); - database.SetMQDetectionFlag( - m_target->AccountName(), - m_target->GetName(), - message.c_str(), - zone->GetShortName() - ); + RecordPlayerEventLogWithClient(m_target, PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); LogCheat(fmt::runtime(message)); break; } diff --git a/zone/client.cpp b/zone/client.cpp index ada87526e..7815e22c4 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -66,6 +66,9 @@ extern volatile bool RunLoops; #include "../common/repositories/character_spells_repository.h" #include "../common/repositories/character_disciplines_repository.h" #include "../common/repositories/character_data_repository.h" +#include "../common/repositories/discovered_items_repository.h" +#include "../common/events/player_events.h" +#include "../common/events/player_event_logs.h" extern QueryServ* QServ; @@ -75,8 +78,6 @@ extern volatile bool is_zone_loaded; extern WorldServer worldserver; extern uint32 numclients; extern PetitionList petition_list; -bool commandlogged; -char entirecommand[255]; void UpdateWindowTitle(char* iNewTitle); @@ -180,9 +181,10 @@ Client::Client(EQStreamInterface *ieqs) : Mob( consent_throttle_timer(2000), tmSitting(0) { + for (auto client_filter = FilterNone; client_filter < _FilterCount; client_filter = eqFilterType(client_filter + 1)) { + SetFilter(client_filter, FilterShow); + } - for (int client_filter = 0; client_filter < _FilterCount; client_filter++) - ClientFilters[client_filter] = FilterShow; cheat_manager.SetClient(this); mMovementManager->AddClient(this); character_id = 0; @@ -238,7 +240,6 @@ Client::Client(EQStreamInterface *ieqs) : Mob( casting_spell_id = 0; npcflag = false; npclevel = 0; - pQueuedSaveWorkID = 0; position_update_same_count = 0; fishing_timer.Disable(); dead_timer.Disable(); @@ -246,8 +247,6 @@ Client::Client(EQStreamInterface *ieqs) : Mob( autosave_timer.Disable(); GetMercTimer()->Disable(); instalog = false; - pLastUpdate = 0; - pLastUpdateWZ = 0; m_pp.autosplit = false; // initialise haste variable m_tradeskill_object = nullptr; @@ -740,9 +739,6 @@ bool Client::Save(uint8 iCommitNow) { return true; } -void Client::SaveBackup() { -} - CLIENTPACKET::CLIENTPACKET() { app = nullptr; @@ -811,16 +807,17 @@ void Client::QueuePacket(const EQApplicationPacket* app, bool ack_req, CLIENT_CO AddPacket(app, ack_req); return; } - + // if the program doesnt care about the status or if the status isnt what we requested if (required_state != CLIENT_CONNECTINGALL && client_state != required_state) { // todo: save packets for later use AddPacket(app, ack_req); } - else - if(eqs) - eqs->QueuePacket(app, ack_req); + else if (eqs) + { + eqs->QueuePacket(app, ack_req); + } } void Client::FastQueuePacket(EQApplicationPacket** app, bool ack_req, CLIENT_CONN_STATUS required_state) { @@ -831,7 +828,7 @@ void Client::FastQueuePacket(EQApplicationPacket** app, bool ack_req, CLIENT_CON return; } else { - if(eqs) + if(eqs) eqs->FastQueuePacket((EQApplicationPacket **)app, ack_req); else if (app && (*app)) delete *app; @@ -919,9 +916,6 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s safe_delete(pack); } - //Return true to proceed, false to return - if(!mod_client_message(message, chan_num)) { return; } - // Garble the message based on drunkness if (m_pp.intoxication > 0 && !(RuleB(Chat, ServerWideOOC) && chan_num == ChatChannel_OOC) && !GetGM()) { GarbleMessage(message, (int)(m_pp.intoxication / 3)); @@ -1122,6 +1116,17 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s break; } case ChatChannel_Say: { /* Say */ + if (player_event_logs.IsEventEnabled(PlayerEvent::SAY)) { + std::string msg = message; + if (!msg.empty() && msg.at(0) != '#' && msg.at(0) != '^') { + auto e = PlayerEvent::SayEvent{ + .message = message, + .target = GetTarget() ? GetTarget()->GetCleanName() : "" + }; + RecordPlayerEventLog(PlayerEvent::SAY, e); + } + } + if (message[0] == COMMAND_CHAR) { if (command_dispatch(this, message, false) == -2) { if (parse->PlayerHasQuestSub(EVENT_COMMAND)) { @@ -1185,7 +1190,9 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s entity_list.ChannelMessage(sender, chan_num, language, lang_skill, message); } - parse->EventPlayer(EVENT_SAY, this, message, language); + if (parse->PlayerHasQuestSub(EVENT_SAY)) { + parse->EventPlayer(EVENT_SAY, this, message, language); + } if (sender != this) { break; @@ -1206,8 +1213,9 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s CheckEmoteHail(t, message); if (DistanceNoZ(m_Position, t->GetPosition()) <= RuleI(Range, Say)) { - - parse->EventNPC(EVENT_SAY, t, this, message, language); + if (parse->HasQuestSub(t->GetNPCTypeID(), EVENT_SAY)) { + parse->EventNPC(EVENT_SAY, t, this, message, language); + } if (RuleB(TaskSystem, EnableTaskSystem)) { if (UpdateTasksOnSpeakWith(t)) { @@ -1216,8 +1224,10 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s } } } else { - if (DistanceSquaredNoZ(m_Position, t->GetPosition()) <= RuleI(Range, Say)) { - parse->EventNPC(EVENT_AGGRO_SAY, t, this, message, language); + if (parse->HasQuestSub(t->GetNPCTypeID(), EVENT_AGGRO_SAY)) { + if (DistanceSquaredNoZ(m_Position, t->GetPosition()) <= RuleI(Range, Say)) { + parse->EventNPC(EVENT_AGGRO_SAY, t, this, message, language); + } } } @@ -1225,9 +1235,13 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s else if (GetTarget() && GetTarget()->IsBot() && !IsInvisible(GetTarget())) { if (DistanceNoZ(m_Position, GetTarget()->GetPosition()) <= RuleI(Range, Say)) { if (GetTarget()->IsEngaged()) { - parse->EventBot(EVENT_AGGRO_SAY, GetTarget()->CastToBot(), this, message, language); + if (parse->BotHasQuestSub(EVENT_AGGRO_SAY)) { + parse->EventBot(EVENT_AGGRO_SAY, GetTarget()->CastToBot(), this, message, language); + } } else { - parse->EventBot(EVENT_SAY, GetTarget()->CastToBot(), this, message, language); + if (parse->BotHasQuestSub(EVENT_SAY)) { + parse->EventBot(EVENT_SAY, GetTarget()->CastToBot(), this, message, language); + } } } } @@ -1317,6 +1331,7 @@ void Client::ChannelMessageSend(const char* from, const char* to, uint8 chan_num cm->chan_num = chan_num; strcpy(&cm->message[0], buffer); + QueuePacket(&app); bool senderCanTrainSelf = RuleB(Client, SelfLanguageLearning); @@ -2485,22 +2500,35 @@ uint64 Client::GetAllMoney() { } bool Client::CheckIncreaseSkill(EQ::skills::SkillType skillid, Mob *against_who, int chancemodi) { - if (IsDead() || IsUnconscious()) + if (IsDead() || IsUnconscious()) { return false; - if (IsAIControlled()) // no skillups while chamred =p + } + + if (IsAIControlled()) { // no skillups while chamred =p return false; - if (against_who != nullptr && against_who->IsCorpse()) // no skillups on corpses + } + + if (against_who && against_who->IsCorpse()) { // no skillups on corpses return false; - if (skillid > EQ::skills::HIGHEST_SKILL) + } + + if (skillid > EQ::skills::HIGHEST_SKILL) { return false; - int skillval = GetRawSkill(skillid); - int maxskill = GetMaxSkillAfterSpecializationRules(skillid, MaxSkill(skillid)); - std::string export_string = fmt::format( - "{} {}", - skillid, - skillval - ); - parse->EventPlayer(EVENT_USE_SKILL, this, export_string, 0); + } + + auto skillval = GetRawSkill(skillid); + auto maxskill = GetMaxSkillAfterSpecializationRules(skillid, MaxSkill(skillid)); + + if (parse->PlayerHasQuestSub(EVENT_USE_SKILL)) { + const auto& export_string = fmt::format( + "{} {}", + skillid, + skillval + ); + + parse->EventPlayer(EVENT_USE_SKILL, this, export_string, 0); + } + if (against_who) { if ( against_who->GetSpecialAbility(IMMUNE_AGGRO) || @@ -2508,10 +2536,7 @@ bool Client::CheckIncreaseSkill(EQ::skills::SkillType skillid, Mob *against_who, against_who->IsClient() || GetLevelCon(against_who->GetLevel()) == CON_GRAY ) { - //false by default - if (!mod_can_increase_skill(skillid, against_who)) { - return false; - } + return false; } } @@ -2528,20 +2553,34 @@ bool Client::CheckIncreaseSkill(EQ::skills::SkillType skillid, Mob *against_who, // This result is increased by the existing SkillUpModifier rule double working_chance = (((RuleI(Character, SkillUpMaximumChancePercentage) - RuleI(Character, SkillUpMinimumChancePercentage) + chancemodi) * (pow(0.99, skillval))) + RuleI(Character, SkillUpMinimumChancePercentage)); Chance = (working_chance * RuleI(Character, SkillUpModifier) / 100); - Chance = mod_increase_skill_chance(Chance, against_who); } if(zone->random.Real(0, 99) < Chance) { SetSkill(skillid, GetRawSkill(skillid) + 1); - std::string export_string = fmt::format( - "{} {} {} {}", - skillid, - skillval+1, - maxskill, - 0 - ); - parse->EventPlayer(EVENT_SKILL_UP, this, export_string, 0); + + if (player_event_logs.IsEventEnabled(PlayerEvent::SKILL_UP)) { + auto e = PlayerEvent::SkillUpEvent{ + .skill_id = static_cast(skillid), + .value = static_cast((skillval + 1)), + .max_skill = static_cast(maxskill), + .against_who = (against_who) ? against_who->GetCleanName() : GetCleanName(), + }; + RecordPlayerEventLog(PlayerEvent::SKILL_UP, e); + } + + if (parse->PlayerHasQuestSub(EVENT_SKILL_UP)) { + const auto& export_string = fmt::format( + "{} {} {} {}", + skillid, + skillval + 1, + maxskill, + 0 + ); + + parse->EventPlayer(EVENT_SKILL_UP, this, export_string, 0); + } + LogSkills("Skill [{}] at value [{}] successfully gain with [{}] chance (mod [{}])", skillid, skillval, Chance, chancemodi); return true; } else { @@ -2569,13 +2608,18 @@ void Client::CheckLanguageSkillIncrease(uint8 langid, uint8 TeacherSkill) { if(zone->random.Real(0,100) < Chance) { // if they make the roll IncreaseLanguageSkill(langid); // increase the language skill by 1 - std::string export_string = fmt::format( - "{} {} {}", - langid, - LangSkill + 1, - 100 - ); - parse->EventPlayer(EVENT_LANGUAGE_SKILL_UP, this, export_string, 0); + + if (parse->PlayerHasQuestSub(EVENT_LANGUAGE_SKILL_UP)) { + const auto& export_string = fmt::format( + "{} {} {}", + langid, + LangSkill + 1, + 100 + ); + + parse->EventPlayer(EVENT_LANGUAGE_SKILL_UP, this, export_string, 0); + } + LogSkills("Language [{}] at value [{}] successfully gain with [{}] % chance", langid, LangSkill, Chance); } else @@ -2764,35 +2808,6 @@ void Client::MemorizeSpell(uint32 slot,uint32 spellid,uint32 scribing, uint32 re safe_delete(outapp); } -void Client::LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 price, const EQ::ItemData* item, bool buying) -{ - if(!player || !merchant || !item) - return; - - std::string LogText = "Qty: "; - - char Buffer[255]; - memset(Buffer, 0, sizeof(Buffer)); - - snprintf(Buffer, sizeof(Buffer)-1, "%3i", quantity); - LogText += Buffer; - snprintf(Buffer, sizeof(Buffer)-1, "%10i", price); - LogText += " TotalValue: "; - LogText += Buffer; - snprintf(Buffer, sizeof(Buffer)-1, " ItemID: %7i", item->ID); - LogText += Buffer; - LogText += " "; - snprintf(Buffer, sizeof(Buffer)-1, " %s", item->Name); - LogText += Buffer; - - if (buying==true) { - database.logevents(player->AccountName(),player->AccountID(),player->admin,player->GetName(),merchant->GetName(),"Buying from Merchant",LogText.c_str(),2); - } - else { - database.logevents(player->AccountName(),player->AccountID(),player->admin,player->GetName(),merchant->GetName(),"Selling to Merchant",LogText.c_str(),3); - } -} - void Client::Disarm(Client* disarmer, int chance) { int16 slot = EQ::invslot::SLOT_INVALID; const EQ::ItemInstance *inst = GetInv().GetItem(EQ::invslot::slotPrimary); @@ -2934,8 +2949,6 @@ bool Client::BindWound(Mob *bindmob, bool start, bool fail) max_percent = 70 + maxHPBonus; } - max_percent = mod_bindwound_percent(max_percent, bindmob); - int64 max_hp = bindmob->GetMaxHP() * max_percent / 100; // send bindmob new hp's @@ -2956,8 +2969,6 @@ bool Client::BindWound(Mob *bindmob, bool start, bool fail) bindhps += bindhps * bindBonus / 100; - bindhps = mod_bindwound_hp(bindhps, bindmob); - // if the bind takes them above the max bindable // cap it at that value. Dont know if live does it this way // but it makes sense to me. @@ -2999,8 +3010,6 @@ bool Client::BindWound(Mob *bindmob, bool start, bool fail) if (max_percent > 100) max_percent = 100; - max_percent = mod_bindwound_percent(max_percent, bindmob); - int max_hp = (bindmob->GetMaxHP() * max_percent) / 100; if (max_hp > bindmob->GetMaxHP()) max_hp = bindmob->GetMaxHP(); @@ -3021,8 +3030,6 @@ bool Client::BindWound(Mob *bindmob, bool start, bool fail) if (bindhps < 3) bindhps = 3; - bindhps = mod_bindwound_hp(bindhps, bindmob); - bindhps += bindmob->GetHP(); if (bindhps > max_hp) bindhps = max_hp; @@ -3091,14 +3098,14 @@ void Client::ServerFilter(SetServerFilter_Struct* filter){ */ #define Filter0(type) \ if(filter->filters[type] == 1) \ - ClientFilters[type] = FilterShow; \ + SetFilter(type, FilterShow); \ else \ - ClientFilters[type] = FilterHide; + SetFilter(type, FilterHide); #define Filter1(type) \ if(filter->filters[type] == 0) \ - ClientFilters[type] = FilterShow; \ + SetFilter(type, FilterShow); \ else \ - ClientFilters[type] = FilterHide; + SetFilter(type, FilterHide); Filter0(FilterGuildChat); Filter0(FilterSocials); @@ -3108,44 +3115,49 @@ void Client::ServerFilter(SetServerFilter_Struct* filter){ Filter0(FilterOOC); Filter0(FilterBadWords); - if(filter->filters[FilterPCSpells] == 0) - ClientFilters[FilterPCSpells] = FilterShow; - else if(filter->filters[FilterPCSpells] == 1) - ClientFilters[FilterPCSpells] = FilterHide; - else - ClientFilters[FilterPCSpells] = FilterShowGroupOnly; + if (filter->filters[FilterPCSpells] == 0) { + SetFilter(FilterPCSpells, FilterShow); + } else if (filter->filters[FilterPCSpells] == 1) { + SetFilter(FilterPCSpells, FilterHide); + } else { + SetFilter(FilterPCSpells, FilterShowGroupOnly); + } Filter1(FilterNPCSpells); - if(filter->filters[FilterBardSongs] == 0) - ClientFilters[FilterBardSongs] = FilterShow; - else if(filter->filters[FilterBardSongs] == 1) - ClientFilters[FilterBardSongs] = FilterShowSelfOnly; - else if(filter->filters[FilterBardSongs] == 2) - ClientFilters[FilterBardSongs] = FilterShowGroupOnly; - else - ClientFilters[FilterBardSongs] = FilterHide; + if (filter->filters[FilterBardSongs] == 0) { + SetFilter(FilterBardSongs, FilterShow); + } else if (filter->filters[FilterBardSongs] == 1) { + SetFilter(FilterBardSongs, FilterShowSelfOnly); + } else if (filter->filters[FilterBardSongs] == 2) { + SetFilter(FilterBardSongs, FilterShowGroupOnly); + } else { + SetFilter(FilterBardSongs, FilterHide); + } - if(filter->filters[FilterSpellCrits] == 0) - ClientFilters[FilterSpellCrits] = FilterShow; - else if(filter->filters[FilterSpellCrits] == 1) - ClientFilters[FilterSpellCrits] = FilterShowSelfOnly; - else - ClientFilters[FilterSpellCrits] = FilterHide; + if (filter->filters[FilterSpellCrits] == 0) { + SetFilter(FilterSpellCrits, FilterShow); + } else if (filter->filters[FilterSpellCrits] == 1) { + SetFilter(FilterSpellCrits, FilterShowSelfOnly); + } else { + SetFilter(FilterSpellCrits, FilterHide); + } - if (filter->filters[FilterMeleeCrits] == 0) - ClientFilters[FilterMeleeCrits] = FilterShow; - else if (filter->filters[FilterMeleeCrits] == 1) - ClientFilters[FilterMeleeCrits] = FilterShowSelfOnly; - else - ClientFilters[FilterMeleeCrits] = FilterHide; + if (filter->filters[FilterMeleeCrits] == 0) { + SetFilter(FilterMeleeCrits, FilterShow); + } else if (filter->filters[FilterMeleeCrits] == 1) { + SetFilter(FilterMeleeCrits, FilterShowSelfOnly); + } else { + SetFilter(FilterMeleeCrits, FilterHide); + } - if(filter->filters[FilterSpellDamage] == 0) - ClientFilters[FilterSpellDamage] = FilterShow; - else if(filter->filters[FilterSpellDamage] == 1) - ClientFilters[FilterSpellDamage] = FilterShowSelfOnly; - else - ClientFilters[FilterSpellDamage] = FilterHide; + if (filter->filters[FilterSpellDamage] == 0) { + SetFilter(FilterSpellDamage, FilterShow); + } else if (filter->filters[FilterSpellDamage] == 1) { + SetFilter(FilterSpellDamage, FilterShowSelfOnly); + } else { + SetFilter(FilterSpellDamage, FilterHide); + } Filter0(FilterMyMisses); Filter0(FilterOthersMiss); @@ -3154,19 +3166,21 @@ void Client::ServerFilter(SetServerFilter_Struct* filter){ Filter1(FilterDamageShields); if (ClientVersionBit() & EQ::versions::maskSoDAndLater) { - if (filter->filters[FilterDOT] == 0) - ClientFilters[FilterDOT] = FilterShow; - else if (filter->filters[FilterDOT] == 1) - ClientFilters[FilterDOT] = FilterShowSelfOnly; - else if (filter->filters[FilterDOT] == 2) - ClientFilters[FilterDOT] = FilterShowGroupOnly; - else - ClientFilters[FilterDOT] = FilterHide; + if (filter->filters[FilterDOT] == 0) { + SetFilter(FilterDOT, FilterShow); + } else if (filter->filters[FilterDOT] == 1) { + SetFilter(FilterDOT, FilterShowSelfOnly); + } else if (filter->filters[FilterDOT] == 2) { + SetFilter(FilterDOT, FilterShowGroupOnly); + } else { + SetFilter(FilterDOT, FilterHide); + } } else { - if (filter->filters[FilterDOT] == 0) // show functions as self only - ClientFilters[FilterDOT] = FilterShowSelfOnly; - else - ClientFilters[FilterDOT] = FilterHide; + if (filter->filters[FilterDOT] == 0) { // show functions as self only + SetFilter(FilterDOT, FilterShowSelfOnly); + } else { + SetFilter(FilterDOT, FilterHide); + } } Filter1(FilterPetHits); @@ -3175,15 +3189,14 @@ void Client::ServerFilter(SetServerFilter_Struct* filter){ Filter1(FilterPetSpells); if (ClientVersionBit() & EQ::versions::maskSoDAndLater) { - if (filter->filters[FilterHealOverTime] == 0) - ClientFilters[FilterHealOverTime] = FilterShow; - // This is called 'Show Mine Only' in the clients - else if (filter->filters[FilterHealOverTime] == 1) - ClientFilters[FilterHealOverTime] = FilterShowSelfOnly; - else - ClientFilters[FilterHealOverTime] = FilterHide; - } else { - // these clients don't have a 'self only' filter + if (filter->filters[FilterHealOverTime] == 0) { + SetFilter(FilterHealOverTime, FilterShow); + } else if (filter->filters[FilterHealOverTime] == 1) { + SetFilter(FilterHealOverTime, FilterShowSelfOnly); + } else { + SetFilter(FilterHealOverTime, FilterHide); + } + } else { // these clients don't have a 'self only' filter Filter1(FilterHealOverTime); } } @@ -4000,7 +4013,7 @@ void Client::KeyRingLoad() } for (auto row = results.begin(); row != results.end(); ++row) - keyring.push_back(atoi(row[0])); + keyring.push_back(Strings::ToInt(row[0])); } @@ -4044,30 +4057,48 @@ void Client::KeyRingList() } } -bool Client::IsDiscovered(uint32 itemid) { - - std::string query = StringFormat("SELECT count(*) FROM discovered_items WHERE item_id = '%lu'", itemid); - auto results = database.QueryDatabase(query); - if (!results.Success()) { +bool Client::IsDiscovered(uint32 item_id) { + const auto& l = DiscoveredItemsRepository::GetWhere( + database, + fmt::format( + "item_id = {}", + item_id + ) + ); + if (l.empty()) { return false; } - auto row = results.begin(); - if (!atoi(row[0])) - return false; - return true; } -void Client::DiscoverItem(uint32 itemid) { +void Client::DiscoverItem(uint32 item_id) { + auto e = DiscoveredItemsRepository::NewEntity(); - std::string query = StringFormat("INSERT INTO discovered_items " - "SET item_id = %lu, char_name = '%s', " - "discovered_date = UNIX_TIMESTAMP(), account_status = %i", - itemid, GetName(), Admin()); - auto results = database.QueryDatabase(query); + e.account_status = Admin(); + e.char_name = GetCleanName(); + e.discovered_date = std::time(nullptr); + e.item_id = item_id; - parse->EventPlayer(EVENT_DISCOVER_ITEM, this, "", itemid); + auto d = DiscoveredItemsRepository::InsertOne(database, e); + + if (player_event_logs.IsEventEnabled(PlayerEvent::DISCOVER_ITEM)) { + const auto* item = database.GetItem(item_id); + + auto e = PlayerEvent::DiscoverItemEvent{ + .item_id = item_id, + .item_name = item->Name, + }; + RecordPlayerEventLog(PlayerEvent::DISCOVER_ITEM, e); + + } + + if (parse->PlayerHasQuestSub(EVENT_DISCOVER_ITEM)) { + auto* item = database.CreateItem(item_id); + std::vector args = { item }; + + parse->EventPlayer(EVENT_DISCOVER_ITEM, this, "", item_id, &args); + } } void Client::UpdateLFP() { @@ -5139,7 +5170,7 @@ void Client::ShowSkillsWindow() "{}", ( skill_maxed ? - "âś”" : + "Max" : fmt::format( "{}/{}", current_skill, @@ -5163,14 +5194,18 @@ void Client::ShowSkillsWindow() void Client::Signal(int signal_id) { - const auto export_string = fmt::format("{}", signal_id); - parse->EventPlayer(EVENT_SIGNAL, this, export_string, 0); + if (parse->PlayerHasQuestSub(EVENT_SIGNAL)) { + parse->EventPlayer(EVENT_SIGNAL, this, std::to_string(signal_id), 0); + } } void Client::SendPayload(int payload_id, std::string payload_value) { - const auto export_string = fmt::format("{} {}", payload_id, payload_value); - parse->EventPlayer(EVENT_PAYLOAD, this, export_string, 0); + if (parse->PlayerHasQuestSub(EVENT_PAYLOAD)) { + const auto& export_string = fmt::format("{} {}", payload_id, payload_value); + + parse->EventPlayer(EVENT_PAYLOAD, this, export_string, 0); + } } void Client::SendRewards() @@ -5187,8 +5222,8 @@ void Client::SendRewards() for (auto row = results.begin(); row != results.end(); ++row) { ClientReward cr; - cr.id = atoi(row[0]); - cr.amount = atoi(row[1]); + cr.id = Strings::ToInt(row[0]); + cr.amount = Strings::ToInt(row[1]); rewards.push_back(cr); } @@ -5256,7 +5291,7 @@ bool Client::TryReward(uint32 claim_id) auto row = results.begin(); - uint32 amt = atoi(row[0]); + uint32 amt = Strings::ToInt(row[0]); if (amt == 0) return false; @@ -6347,7 +6382,7 @@ void Client::SendStatsWindow(Client* client, bool use_window) if(CalcMaxMana() > 0) { cur_name = " M: "; cur_field = itoa(GetMana()); - total_field = itoa(CalcMaxMana()); + total_field = itoa(GetMaxMana()); } else { continue; } @@ -6402,7 +6437,8 @@ void Client::SendStatsWindow(Client* client, bool use_window) regen_row_color = color_red; base_regen_field = itoa(LevelRegen()); - item_regen_field = itoa(itembonuses.HPRegen); + item_regen_field = itoa( + itembonuses.HPRegen +(GetHeroicSTA() * RuleR(Character, HeroicStaminaMultiplier) / 20)); cap_regen_field = itoa(CalcHPRegenCap()); spell_regen_field = itoa(spellbonuses.HPRegen); aa_regen_field = itoa(aabonuses.HPRegen); @@ -6410,12 +6446,15 @@ void Client::SendStatsWindow(Client* client, bool use_window) break; } case 1: { - if(CalcMaxMana() > 0) { + if(GetMaxMana() > 0) { regen_row_header = "M: "; regen_row_color = color_blue; base_regen_field = itoa(CalcBaseManaRegen()); - item_regen_field = itoa(itembonuses.ManaRegen); + int32 heroic_mana_regen = (GetCasterClass() == 'W') ? + GetHeroicWIS() * RuleR(Character, HeroicWisdomMultiplier) / 25 : + GetHeroicINT() * RuleR(Character, HeroicIntelligenceMultiplier) / 25; + item_regen_field = itoa(itembonuses.ManaRegen + heroic_mana_regen); cap_regen_field = itoa(CalcManaRegenCap()); spell_regen_field = itoa(spellbonuses.ManaRegen); aa_regen_field = itoa(aabonuses.ManaRegen); @@ -6429,7 +6468,12 @@ void Client::SendStatsWindow(Client* client, bool use_window) regen_row_color = color_green; base_regen_field = itoa(((GetLevel() * 4 / 10) + 2)); - item_regen_field = itoa(itembonuses.EnduranceRegen); + double heroic_str = GetHeroicSTR() * RuleR(Character, HeroicStrengthMultiplier); + double heroic_sta = GetHeroicSTA() * RuleR(Character, HeroicStaminaMultiplier); + double heroic_dex = GetHeroicDEX() * RuleR(Character, HeroicDexterityMultiplier); + double heroic_agi = GetHeroicAGI() * RuleR(Character, HeroicAgilityMultiplier); + double heroic_stats = (heroic_str + heroic_sta + heroic_dex + heroic_agi) / 4; + item_regen_field = itoa(itembonuses.EnduranceRegen + heroic_stats); cap_regen_field = itoa(CalcEnduranceRegenCap()); spell_regen_field = itoa(spellbonuses.EnduranceRegen); aa_regen_field = itoa(aabonuses.EnduranceRegen); @@ -6653,7 +6697,7 @@ void Client::SendStatsWindow(Client* client, bool use_window) uint32 magic_rune_number = 0; uint32 buff_count = GetMaxTotalSlots(); for (int i=0; i < buff_count; i++) { - if (buffs[i].spellid != SPELL_UNKNOWN) { + if (IsValidSpell(buffs[i].spellid)) { if (buffs[i].melee_rune > 0) { rune_number += buffs[i].melee_rune; } if (buffs[i].magic_rune > 0) { magic_rune_number += buffs[i].magic_rune; } @@ -6864,7 +6908,7 @@ void Client::SetAlternateCurrencyValue(uint32 currency_id, uint32 new_amount) SendAlternateCurrencyValue(currency_id); } -void Client::AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 method) +int Client::AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 method) { /* Added via Quest, rest of the logging methods may be done inline due to information available in that area of the code */ @@ -6877,12 +6921,12 @@ void Client::AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 me } if(amount == 0) { - return; + return 0; } if(!alternate_currency_loaded) { alternate_currency_queued_operations.push(std::make_pair(currency_id, amount)); - return; + return 0; } int new_value = 0; @@ -6901,6 +6945,8 @@ void Client::AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 me database.UpdateAltCurrencyValue(CharacterID(), currency_id, new_value); } SendAlternateCurrencyValue(currency_id); + + return new_value; } void Client::SendAlternateCurrencyValues() @@ -8083,7 +8129,10 @@ void Client::TryItemTick(int slot) if (GetLevel() >= zone->tick_items[iid].level && zone->random.Int(0, 100) >= (100 - zone->tick_items[iid].chance) && (zone->tick_items[iid].bagslot || slot <= EQ::invslot::EQUIPMENT_END)) { EQ::ItemInstance* e_inst = (EQ::ItemInstance*)inst; - parse->EventItem(EVENT_ITEM_TICK, this, e_inst, nullptr, "", slot); + + if (parse->ItemHasQuestSub(e_inst, EVENT_ITEM_TICK)) { + parse->EventItem(EVENT_ITEM_TICK, this, e_inst, nullptr, "", slot); + } } } @@ -8101,8 +8150,11 @@ void Client::TryItemTick(int slot) { if( GetLevel() >= zone->tick_items[iid].level && zone->random.Int(0, 100) >= (100 - zone->tick_items[iid].chance) ) { - EQ::ItemInstance* e_inst = (EQ::ItemInstance*)a_inst; - parse->EventItem(EVENT_ITEM_TICK, this, e_inst, nullptr, "", slot); + EQ::ItemInstance* e_inst = (EQ::ItemInstance*) a_inst; + + if (parse->ItemHasQuestSub(e_inst, EVENT_ITEM_TICK)) { + parse->EventItem(EVENT_ITEM_TICK, this, e_inst, nullptr, "", slot); + } } } } @@ -8132,7 +8184,9 @@ void Client::TryItemTimer(int slot) auto it_iter = item_timers.begin(); while(it_iter != item_timers.end()) { if(it_iter->second.Check()) { - parse->EventItem(EVENT_TIMER, this, inst, nullptr, it_iter->first, 0); + if (parse->ItemHasQuestSub(inst, EVENT_TIMER)) { + parse->EventItem(EVENT_TIMER, this, inst, nullptr, it_iter->first, 0); + } } ++it_iter; } @@ -8152,7 +8206,9 @@ void Client::TryItemTimer(int slot) auto it_iter = item_timers.begin(); while(it_iter != item_timers.end()) { if(it_iter->second.Check()) { - parse->EventItem(EVENT_TIMER, this, a_inst, nullptr, it_iter->first, 0); + if (parse->ItemHasQuestSub(a_inst, EVENT_TIMER)) { + parse->EventItem(EVENT_TIMER, this, a_inst, nullptr, it_iter->first, 0); + } } ++it_iter; } @@ -8326,8 +8382,6 @@ void Client::Consume(const EQ::ItemData *item, uint8 type, int16 slot, bool auto return; if (type == EQ::item::ItemTypeFood) { - increase = mod_food_value(item, increase); - if (increase < 0) return; @@ -8343,8 +8397,6 @@ void Client::Consume(const EQ::ItemData *item, uint8 type, int16 slot, bool auto LogFood("Eating from slot: [{}]", (int)slot); } else { - increase = mod_drink_value(item, increase); - if (increase < 0) return; @@ -8441,7 +8493,7 @@ void Client::ExpeditionSay(const char *str, int ExpID) { ).c_str() ); } - // ChannelList->CreateChannel(ChannelName, ChannelOwner, ChannelPassword, true, atoi(row[3])); + // ChannelList->CreateChannel(ChannelName, ChannelOwner, ChannelPassword, true, Strings::ToInt(row[3])); } @@ -8452,7 +8504,7 @@ void Client::ShowNumHits() uint32 buffcount = GetMaxTotalSlots(); for (uint32 buffslot = 0; buffslot < buffcount; buffslot++) { const Buffs_Struct &curbuff = buffs[buffslot]; - if (curbuff.spellid != SPELL_UNKNOWN && curbuff.hit_number) + if (IsValidSpell(curbuff.spellid) && curbuff.hit_number) Message(0, "You have %d hits left on %s", curbuff.hit_number, GetSpellName(curbuff.spellid)); } return; @@ -9282,8 +9334,8 @@ void Client::SendToGuildHall() uint16 instance_id = 0; std::string guild_hall_instance_key = fmt::format("guild-hall-instance-{}", GuildID()); std::string instance_data = DataBucket::GetData(guild_hall_instance_key); - if (!instance_data.empty() && std::stoi(instance_data) > 0) { - instance_id = std::stoi(instance_data); + if (!instance_data.empty() && Strings::ToInt(instance_data) > 0) { + instance_id = Strings::ToInt(instance_data); } if (instance_id <= 0) { @@ -10414,7 +10466,7 @@ void Client::SendToInstance(std::string instance_type, std::string zone_short_na uint16 instance_id = 0; if (current_bucket_value.length() > 0) { - instance_id = atoi(current_bucket_value.c_str()); + instance_id = Strings::ToInt(current_bucket_value.c_str()); } else { if(!database.GetUnusedInstanceID(instance_id)) { Message(Chat::White, "Server was unable to find a free instance id."); @@ -10446,8 +10498,8 @@ int Client::CountItem(uint32 item_id) { EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END }, { EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END }, }; - const size_t size = sizeof(slots) / sizeof(slots[0]); - for (int slot_index = 0; slot_index < size; ++slot_index) { + const size_t slot_index_count = sizeof(slots) / sizeof(slots[0]); + for (int slot_index = 0; slot_index < slot_index_count; ++slot_index) { for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) { item = GetInv().GetItem(slot_id); if (item && item->GetID() == item_id) { @@ -10459,6 +10511,133 @@ int Client::CountItem(uint32 item_id) return quantity; } +void Client::ResetItemCooldown(uint32 item_id) +{ + EQ::ItemInstance *item = nullptr; + const EQ::ItemData* item_d = database.GetItem(item_id); + if (!item_d) { + return; + } + int recast_type = item_d->RecastType; + bool found_item = false; + + static const int16 slots[][2] = { + { EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END }, + { EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END }, + { EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END}, + { EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END }, + { EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END }, + { EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END }, + { EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END }, + }; + const size_t slot_index_count = sizeof(slots) / sizeof(slots[0]); + for (int slot_index = 0; slot_index < slot_index_count; ++slot_index) { + for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) { + item = GetInv().GetItem(slot_id); + if (item) { + item_d = item->GetItem(); + if (item_d && item->GetID() == item_id || (item_d->RecastType != RECAST_TYPE_UNLINKED_ITEM && item_d->RecastType == recast_type)) { + item->SetRecastTimestamp(0); + DeleteItemRecastTimer(item_d->ID); + SendItemPacket(slot_id, item, ItemPacketCharmUpdate); + found_item = true; + } + } + } + } + if (!found_item) { + DeleteItemRecastTimer(item_id); //We didn't find the item but we still want to remove the timer + } +} + +void Client::SetItemCooldown(uint32 item_id, bool use_saved_timer, uint32 in_seconds) +{ + EQ::ItemInstance *item = nullptr; + const EQ::ItemData* item_d = database.GetItem(item_id); + if (!item_d) { + return; + } + int recast_type = item_d->RecastType; + auto timestamps = database.GetItemRecastTimestamps(CharacterID()); + uint32 total_time = 0; + uint32 current_time = static_cast(std::time(nullptr)); + uint32 final_time = 0; + const auto timer_type = item_d->RecastType != RECAST_TYPE_UNLINKED_ITEM ? item_d->RecastType : item_id; + const int timer_id = recast_type != RECAST_TYPE_UNLINKED_ITEM ? (pTimerItemStart + recast_type) : (pTimerNegativeItemReuse * item_id); + + if (use_saved_timer) { + if (item_d->RecastType != RECAST_TYPE_UNLINKED_ITEM) { + total_time = timestamps.count(item_d->RecastType) ? timestamps.at(item_d->RecastType) : 0; + } else { + total_time = timestamps.count(item_id) ? timestamps.at(item_id) : 0; + } + } else { + total_time = current_time + in_seconds; + } + + if (total_time > current_time) { + final_time = total_time - current_time; + } + + static const int16 slots[][2] = { + { EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END }, + { EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END }, + { EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END}, + { EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END }, + { EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END }, + { EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END }, + { EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END }, + }; + const size_t slot_index_count = sizeof(slots) / sizeof(slots[0]); + for (int slot_index = 0; slot_index < slot_index_count; ++slot_index) { + for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) { + item = GetInv().GetItem(slot_id); + if (item) { + item_d = item->GetItem(); + if (item_d && item->GetID() == item_id || (item_d->RecastType != RECAST_TYPE_UNLINKED_ITEM && item_d->RecastType == recast_type)) { + item->SetRecastTimestamp(total_time); + SendItemPacket(slot_id, item, ItemPacketCharmUpdate); + } + } + } + } + + //Start timers and update in database only when timer is changed + if (!use_saved_timer) { + GetPTimers().Clear(&database, timer_id); + GetPTimers().Start((timer_id), in_seconds); + database.UpdateItemRecast( + CharacterID(), + timer_type, + GetPTimers().Get(timer_id)->GetReadyTimestamp() + ); + } + SendItemRecastTimer(recast_type, final_time, true); +} + +uint32 Client::GetItemCooldown(uint32 item_id) +{ + const EQ::ItemData* item_d = database.GetItem(item_id); + if (!item_d) { + return 0; + } + + int recast_type = item_d->RecastType; + auto timestamps = database.GetItemRecastTimestamps(CharacterID()); + const auto timer_type = recast_type != RECAST_TYPE_UNLINKED_ITEM ? recast_type : item_id; + uint32 total_time = 0; + uint32 current_time = static_cast(std::time(nullptr)); + uint32 final_time = 0; + + total_time = timestamps.count(timer_type) ? timestamps.at(timer_type) : 0; + + if (total_time > current_time) { + final_time = total_time - current_time; + } + + return final_time; +} + void Client::RemoveItem(uint32 item_id, uint32 quantity) { EQ::ItemInstance *item = nullptr; @@ -10472,8 +10651,8 @@ void Client::RemoveItem(uint32 item_id, uint32 quantity) { EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END }, }; int16 removed_count = 0; - const size_t size = sizeof(slots) / sizeof(slots[0]); - for (int slot_index = 0; slot_index < size; ++slot_index) { + const size_t slot_index_count = sizeof(slots) / sizeof(slots[0]); + for (int slot_index = 0; slot_index < slot_index_count; ++slot_index) { for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) { if (removed_count == quantity) { break; @@ -11726,7 +11905,7 @@ void Client::SendPath(Mob* target) target->CastToClient()->Trader || target->CastToClient()->Buyer ) - ) { + ) { Message( Chat::Yellow, fmt::format( @@ -11761,7 +11940,8 @@ void Client::SendPath(Mob* target) points.push_back(a); points.push_back(b); - } else { + } + else { glm::vec3 path_start( GetX(), GetY(), @@ -11774,8 +11954,8 @@ void Client::SendPath(Mob* target) target->GetZ() + (target->GetSize() < 6.0 ? 6 : target->GetSize()) * HEAD_POSITION ); - bool partial = false; - bool stuck = false; + bool partial = false; + bool stuck = false; auto path_list = zone->pathing->FindRoute(path_start, path_end, partial, stuck); if (path_list.empty() || partial) { @@ -11806,7 +11986,7 @@ void Client::SendPath(Mob* target) p.z = GetZ(); points.push_back(p); - for (const auto& n : path_list) { + for (const auto &n: path_list) { if (n.teleport) { leads_to_teleporter = true; break; @@ -11833,3 +12013,202 @@ void Client::SendPath(Mob* target) SendPathPacket(points); } + +void Client::UseAugmentContainer(int container_slot) +{ + auto in_augment = new AugmentItem_Struct[sizeof(AugmentItem_Struct)]; + in_augment->container_slot = container_slot; + in_augment->augment_slot = -1; + Object::HandleAugmentation(this, in_augment, nullptr); + safe_delete_array(in_augment); +} + +PlayerEvent::PlayerEvent Client::GetPlayerEvent() +{ + auto e = PlayerEvent::PlayerEvent{}; + e.account_id = AccountID(); + e.character_id = CharacterID(); + e.character_name = GetCleanName(); + e.x = GetX(); + e.y = GetY(); + e.z = GetZ(); + e.heading = GetHeading(); + e.zone_id = GetZoneID(); + e.zone_short_name = zone ? zone->GetShortName() : ""; + e.zone_long_name = zone ? zone->GetLongName() : ""; + e.instance_id = GetInstanceID(); + e.guild_id = GuildID(); + e.guild_name = guild_mgr.GetGuildName(GuildID()); + e.account_name = AccountName(); + + return e; +} + +void Client::PlayerTradeEventLog(Trade *t, Trade *t2) +{ + Client *trader = t->GetOwner()->CastToClient(); + Client *trader2 = t2->GetOwner()->CastToClient(); + uint8 t_item_count = 0; + uint8 t2_item_count = 0; + + auto money_t = PlayerEvent::Money{ + .platinum = t->pp, + .gold = t->gp, + .silver = t->sp, + .copper = t->cp, + }; + auto money_t2 = PlayerEvent::Money{ + .platinum = t2->pp, + .gold = t2->gp, + .silver = t2->sp, + .copper = t2->cp, + }; + + // trader 1 item count + for (uint16 i = EQ::invslot::TRADE_BEGIN; i <= EQ::invslot::TRADE_END; i++) { + if (trader->GetInv().GetItem(i)) { + t_item_count++; + } + } + + // trader 2 item count + for (uint16 i = EQ::invslot::TRADE_BEGIN; i <= EQ::invslot::TRADE_END; i++) { + if (trader2->GetInv().GetItem(i)) { + t2_item_count++; + } + } + + std::vector t_entries = {}; + t_entries.reserve(t_item_count); + if (t_item_count > 0) { + for (uint16 i = EQ::invslot::TRADE_BEGIN; i <= EQ::invslot::TRADE_END; i++) { + const EQ::ItemInstance *inst = trader->GetInv().GetItem(i); + if (inst) { + t_entries.emplace_back( + PlayerEvent::TradeItemEntry{ + .slot = i, + .item_id = inst->GetItem()->ID, + .item_name = inst->GetItem()->Name, + .charges = static_cast(inst->GetCharges()), + .aug_1_item_id = inst->GetAugmentItemID(0), + .aug_1_item_name = inst->GetAugment(0) ? inst->GetAugment(0)->GetItem()->Name : "", + .aug_2_item_id = inst->GetAugmentItemID(1), + .aug_2_item_name = inst->GetAugment(1) ? inst->GetAugment(1)->GetItem()->Name : "", + .aug_3_item_id = inst->GetAugmentItemID(2), + .aug_3_item_name = inst->GetAugment(2) ? inst->GetAugment(2)->GetItem()->Name : "", + .aug_4_item_id = inst->GetAugmentItemID(3), + .aug_4_item_name = inst->GetAugment(3) ? inst->GetAugment(3)->GetItem()->Name : "", + .aug_5_item_id = inst->GetAugmentItemID(4), + .aug_5_item_name = inst->GetAugment(4) ? inst->GetAugment(4)->GetItem()->Name : "", + .aug_6_item_id = inst->GetAugmentItemID(5), + .aug_6_item_name = inst->GetAugment(5) ? inst->GetAugment(5)->GetItem()->Name : "", + .in_bag = false, + } + ); + + if (inst->IsClassBag()) { + for (uint8 j = EQ::invbag::SLOT_BEGIN; j <= EQ::invbag::SLOT_END; j++) { + inst = trader->GetInv().GetItem(i, j); + if (inst) { + t_entries.emplace_back( + PlayerEvent::TradeItemEntry{ + .slot = j, + .item_id = inst->GetItem()->ID, + .item_name = inst->GetItem()->Name, + .charges = static_cast(inst->GetCharges()), + .aug_1_item_id = inst->GetAugmentItemID(0), + .aug_1_item_name = inst->GetAugment(0) ? inst->GetAugment(0)->GetItem()->Name : "", + .aug_2_item_id = inst->GetAugmentItemID(1), + .aug_2_item_name = inst->GetAugment(1) ? inst->GetAugment(1)->GetItem()->Name : "", + .aug_3_item_id = inst->GetAugmentItemID(2), + .aug_3_item_name = inst->GetAugment(2) ? inst->GetAugment(2)->GetItem()->Name : "", + .aug_4_item_id = inst->GetAugmentItemID(3), + .aug_4_item_name = inst->GetAugment(3) ? inst->GetAugment(3)->GetItem()->Name : "", + .aug_5_item_id = inst->GetAugmentItemID(4), + .aug_5_item_name = inst->GetAugment(4) ? inst->GetAugment(4)->GetItem()->Name : "", + .aug_6_item_id = inst->GetAugmentItemID(5), + .aug_6_item_name = inst->GetAugment(5) ? inst->GetAugment(5)->GetItem()->Name : "", + .in_bag = true, + } + ); + } + } + } + } + } + } + + std::vector t2_entries = {}; + t_entries.reserve(t2_item_count); + if (t2_item_count > 0) { + for (uint16 i = EQ::invslot::TRADE_BEGIN; i <= EQ::invslot::TRADE_END; i++) { + const EQ::ItemInstance *inst = trader2->GetInv().GetItem(i); + if (inst) { + t2_entries.emplace_back( + PlayerEvent::TradeItemEntry{ + .slot = i, + .item_id = inst->GetItem()->ID, + .item_name = inst->GetItem()->Name, + .charges = static_cast(inst->GetCharges()), + .aug_1_item_id = inst->GetAugmentItemID(0), + .aug_1_item_name = inst->GetAugment(0) ? inst->GetAugment(0)->GetItem()->Name : "", + .aug_2_item_id = inst->GetAugmentItemID(1), + .aug_2_item_name = inst->GetAugment(1) ? inst->GetAugment(1)->GetItem()->Name : "", + .aug_3_item_id = inst->GetAugmentItemID(2), + .aug_3_item_name = inst->GetAugment(2) ? inst->GetAugment(2)->GetItem()->Name : "", + .aug_4_item_id = inst->GetAugmentItemID(3), + .aug_4_item_name = inst->GetAugment(3) ? inst->GetAugment(3)->GetItem()->Name : "", + .aug_5_item_id = inst->GetAugmentItemID(4), + .aug_5_item_name = inst->GetAugment(4) ? inst->GetAugment(4)->GetItem()->Name : "", + .aug_6_item_id = inst->GetAugmentItemID(5), + .aug_6_item_name = inst->GetAugment(5) ? inst->GetAugment(5)->GetItem()->Name : "", + .in_bag = false, + } + ); + + if (inst->IsClassBag()) { + for (uint8 j = EQ::invbag::SLOT_BEGIN; j <= EQ::invbag::SLOT_END; j++) { + inst = trader2->GetInv().GetItem(i, j); + if (inst) { + t2_entries.emplace_back( + PlayerEvent::TradeItemEntry{ + .slot = j, + .item_id = inst->GetItem()->ID, + .item_name = inst->GetItem()->Name, + .charges = static_cast(inst->GetCharges()), + .aug_1_item_id = inst->GetAugmentItemID(0), + .aug_1_item_name = inst->GetAugment(0) ? inst->GetAugment(0)->GetItem()->Name : "", + .aug_2_item_id = inst->GetAugmentItemID(1), + .aug_2_item_name = inst->GetAugment(1) ? inst->GetAugment(1)->GetItem()->Name : "", + .aug_3_item_id = inst->GetAugmentItemID(2), + .aug_3_item_name = inst->GetAugment(2) ? inst->GetAugment(2)->GetItem()->Name : "", + .aug_4_item_id = inst->GetAugmentItemID(3), + .aug_4_item_name = inst->GetAugment(3) ? inst->GetAugment(3)->GetItem()->Name : "", + .aug_5_item_id = inst->GetAugmentItemID(4), + .aug_5_item_name = inst->GetAugment(4) ? inst->GetAugment(4)->GetItem()->Name : "", + .aug_6_item_id = inst->GetAugmentItemID(5), + .aug_6_item_name = inst->GetAugment(5) ? inst->GetAugment(5)->GetItem()->Name : "", + .in_bag = true, + } + ); + } + } + } + } + } + } + + auto e = PlayerEvent::TradeEvent{ + .character_1_id = trader->CharacterID(), + .character_1_name = trader->GetCleanName(), + .character_2_id = trader2->CharacterID(), + .character_2_name = trader2->GetCleanName(), + .character_1_give_money = money_t, + .character_2_give_money = money_t2, + .character_1_give_items = t_entries, + .character_2_give_items = t2_entries + }; + + RecordPlayerEventLogWithClient(trader, PlayerEvent::TRADE, e); + RecordPlayerEventLogWithClient(trader2, PlayerEvent::TRADE, e); +} diff --git a/zone/client.h b/zone/client.h index 2bb016fe6..7d02d4fe2 100644 --- a/zone/client.h +++ b/zone/client.h @@ -20,7 +20,6 @@ class Client; class EQApplicationPacket; -class EQStream; class DynamicZone; class Expedition; class ExpeditionLockoutTimer; @@ -67,6 +66,7 @@ namespace EQ #include "task_manager.h" #include "task_client_state.h" #include "cheat_manager.h" +#include "../common/events/player_events.h" #ifdef _WINDOWS // since windows defines these within windef.h (which windows.h include) @@ -83,7 +83,6 @@ namespace EQ #include -#define CLIENT_TIMEOUT 90000 #define CLIENT_LD_TIMEOUT 30000 // length of time client stays in zone after LDing #define TARGETING_RANGE 200 // range for /assist and /target #define XTARGET_HARDCAP 20 @@ -217,11 +216,6 @@ struct ClientReward uint32 amount; }; -class ClientFactory { -public: - Client *MakeClient(std::shared_ptr ieqs); -}; - class Client : public Mob { public: @@ -277,7 +271,9 @@ public: void KeyRingAdd(uint32 item_id); bool KeyRingCheck(uint32 item_id); void KeyRingList(); - virtual bool IsClient() const { return true; } + bool IsClient() const override { return true; } + bool IsOfClientBot() const override { return true; } + bool IsOfClientBotMerc() const override { return true; } void CompleteConnect(); bool TryStacking(EQ::ItemInstance* item, uint8 type = ItemPacketTrade, bool try_worn = true, bool try_cursor = true); void SendTraderPacket(Client* trader, uint32 Unknown72 = 51); @@ -327,7 +323,6 @@ public: bool ShouldISpawnFor(Client *c) { return !GMHideMe(c) && !IsHoveringForRespawn(); } virtual bool Process(); void ProcessPackets(); - void LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 price, const EQ::ItemData* item, bool buying); void QueuePacket(const EQApplicationPacket* app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL, eqFilterType filter=FilterNone); void FastQueuePacket(EQApplicationPacket** app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL); void ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_skill, const char* orig_message, const char* targetname = nullptr, bool is_silent = false); @@ -341,8 +336,6 @@ public: bool HasRecipeLearned(uint32 recipe_id); bool CanIncreaseTradeskill(EQ::skills::SkillType tradeskill); - EQApplicationPacket* ReturnItemPacket(int16 slot_id, const EQ::ItemInstance* inst, ItemPacketType packet_type); - bool GetRevoked() const { return revoked; } void SetRevoked(bool rev) { revoked = rev; } inline uint32 GetIP() const { return ip; } @@ -358,8 +351,7 @@ public: void UpdateLFP(); virtual bool Save() { return Save(0); } - bool Save(uint8 iCommitNow); // 0 = delayed, 1=async now, 2=sync now - void SaveBackup(); + bool Save(uint8 iCommitNow); // 0 = delayed, 1=async now, 2=sync now /* New PP Save Functions */ bool SaveCurrency(){ return database.SaveCharacterCurrency(this->CharacterID(), &m_pp); } @@ -695,7 +687,6 @@ public: void SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, uint8 char_race, uint8 char_deity, bool quest = false); void SetFactionLevel2(uint32 char_id, int32 faction_id, uint8 char_class, uint8 char_race, uint8 char_deity, int32 value, uint8 temp); int32 GetRawItemAC(); - uint16 GetCombinedAC_TEST(); inline uint32 LSAccountID() const { return lsaccountid; } inline uint32 GetWID() const { return WID; } @@ -790,6 +781,7 @@ public: void SendTradeskillDetails(uint32 recipe_id); bool TradeskillExecute(DBTradeskillRecipe_Struct *spec); void CheckIncreaseTradeskill(int16 bonusstat, int16 stat_modifier, float skillup_modifier, uint16 success_modifier, EQ::skills::SkillType tradeskill); + bool CheckTradeskillLoreConflict(int32 recipe_id); void InitInnates(); void GMKill(); @@ -840,17 +832,14 @@ public: void Fling(float value, float target_x, float target_y, float target_z, bool ignore_los = false, bool clip_through_walls = false, bool calculate_speed = false); - inline bool IsStanding() const {return (playeraction == 0);} - inline bool IsSitting() const {return (playeraction == 1);} - inline bool IsCrouching() const {return (playeraction == 2);} + inline bool IsStanding() const { return (playeraction == 0); } + inline bool IsSitting() const override { return (playeraction == 1); } + inline bool IsCrouching() const { return (playeraction == 2); } inline bool IsBecomeNPC() const { return npcflag; } inline uint8 GetBecomeNPCLevel() const { return npclevel; } inline void SetBecomeNPC(bool flag) { npcflag = flag; } inline void SetBecomeNPCLevel(uint8 level) { npclevel = level; } EQStreamInterface* Connection() { return eqs; } -#ifdef PACKET_PROFILER - void DumpPacketProfile() { if(eqs) eqs->DumpPacketProfile(); } -#endif uint32 GetEquippedItemFromTextureSlot(uint8 material_slot) const; // returns item id uint32 GetEquipmentColor(uint8 material_slot) const; virtual void UpdateEquipmentLight() { m_Light.Type[EQ::lightsource::LightEquipment] = m_inv.FindBrightestLightType(); m_Light.Level[EQ::lightsource::LightEquipment] = EQ::lightsource::TypeToLevel(m_Light.Type[EQ::lightsource::LightEquipment]); } @@ -952,6 +941,7 @@ public: void MemorizeSpell(uint32 slot, uint32 spellid, uint32 scribing, uint32 reduction = 0); // Item methods + void UseAugmentContainer(int container_slot); void EVENT_ITEM_ScriptStopReturn(); uint32 NukeItem(uint32 itemnum, uint8 where_to_check = (invWhereWorn | invWherePersonal | invWhereBank | invWhereSharedBank | invWhereTrading | invWhereCursor)); @@ -966,6 +956,9 @@ public: void SendCursorBuffer(); void DeleteItemInInventory(int16 slot_id, int16 quantity = 0, bool client_update = false, bool update_db = true); int CountItem(uint32 item_id); + void ResetItemCooldown(uint32 item_id); + void SetItemCooldown(uint32 item_id, bool use_saved_timer = false, uint32 in_seconds = 1); + uint32 GetItemCooldown(uint32 item_id); void RemoveItem(uint32 item_id, uint32 quantity = 1); bool SwapItem(MoveItem_Struct* move_in); void SwapItemResync(MoveItem_Struct* move_slots); @@ -990,7 +983,7 @@ public: inline bool IsTrader() const { return(Trader); } inline bool IsBuyer() const { return(Buyer); } eqFilterMode GetFilter(eqFilterType filter_id) const { return ClientFilters[filter_id]; } - void SetFilter(eqFilterType filter_id, eqFilterMode value) { ClientFilters[filter_id]=value; } + void SetFilter(eqFilterType filter_id, eqFilterMode filter_mode) { ClientFilters[filter_id] = filter_mode; } void CancelSneakHide(); void BreakInvis(); @@ -1317,7 +1310,6 @@ public: bool m_requested_shared_task_removal = false; std::vector GetPartyMembers(); - void HandleUpdateTasksOnKill(uint32 npc_type_id); inline const EQ::versions::ClientVersion ClientVersion() const { return m_ClientVersion; } inline const uint32 ClientVersionBit() const { return m_ClientVersionBit; } @@ -1481,7 +1473,7 @@ public: void ConsentCorpses(std::string consent_name, bool deny = false); void SendAltCurrencies(); void SetAlternateCurrencyValue(uint32 currency_id, uint32 new_amount); - void AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 method = 0); + int AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 method = 0); void SendAlternateCurrencyValues(); void SendAlternateCurrencyValue(uint32 currency_id, bool send_if_null = true); uint32 GetAlternateCurrencyValue(uint32 currency_id) const; @@ -1516,8 +1508,9 @@ public: void SendReloadCommandMessages(); - void SendItemRecastTimer(int32 recast_type, uint32 recast_delay = 0); + void SendItemRecastTimer(int32 recast_type, uint32 recast_delay = 0, bool in_ignore_casting_requirement = false); void SetItemRecastTimer(int32 spell_id, uint32 inventory_slot); + void DeleteItemRecastTimer(uint32 item_id); bool HasItemRecastTimer(int32 spell_id, uint32 inventory_slot); inline bool AggroMeterAvailable() const { return ((m_ClientVersionBit & EQ::versions::maskRoF2AndLater)) && RuleB(Character, EnableAggroMeter); } // RoF untested @@ -1587,32 +1580,9 @@ public: void SetAccountFlag(std::string flag, std::string val); std::string GetAccountFlag(std::string flag); void SetGMStatus(int16 new_status); - float GetDamageMultiplier(EQ::skills::SkillType how_long_has_this_been_missing); void Consume(const EQ::ItemData *item, uint8 type, int16 slot, bool auto_consume); void PlayMP3(const char* fname); void ExpeditionSay(const char *str, int ExpID); - int mod_client_damage(int64 damage, EQ::skills::SkillType skillinuse, int hand, const EQ::ItemInstance* weapon, Mob* other); - bool mod_client_message(char* message, uint8 chan_num); - bool mod_can_increase_skill(EQ::skills::SkillType skillid, Mob* against_who); - double mod_increase_skill_chance(double chance, Mob* against_who); - int mod_bindwound_percent(int max_percent, Mob* bindmob); - int mod_bindwound_hp(int bindhps, Mob* bindmob); - int mod_client_haste(int h); - void mod_consider(Mob* tmob, Consider_Struct* con); - bool mod_saylink(const std::string&, bool silentsaylink); - int16 mod_pet_power(int16 act_power, uint16 spell_id); - float mod_tradeskill_chance(float chance, DBTradeskillRecipe_Struct *spec); - float mod_tradeskill_skillup(float chance_stage2); - int32 mod_tribute_item_value(int32 pts, const EQ::ItemInstance* item); - void mod_client_death_npc(Mob* killerMob); - void mod_client_death_duel(Mob* killerMob); - void mod_client_death_env(); - int64 mod_client_xp(int64 in_exp, NPC *npc); - uint32 mod_client_xp_for_level(uint32 xp, uint16 check_level); - int mod_client_haste_cap(int cap); - int mod_consume(EQ::ItemData *item, EQ::item::ItemType type, int change); - int mod_food_value(const EQ::ItemData *item, int change); - int mod_drink_value(const EQ::ItemData *item, int change); inline int32 GetEnvironmentDamageModifier() const { return environment_damage_modifier; } void SetEnvironmentDamageModifier(int32 val) { environment_damage_modifier = val; } @@ -1672,18 +1642,18 @@ public: std::string GetGuildPublicNote(); + PlayerEvent::PlayerEvent GetPlayerEvent(); + void RecordKilledNPCEvent(NPC *n); protected: friend class Mob; void CalcItemBonuses(StatBonuses* newbon); void AddItemBonuses(const EQ::ItemInstance *inst, StatBonuses* newbon, bool isAug = false, bool isTribute = false, int rec_override = 0, bool ammo_slot_item = false); void AdditiveWornBonuses(const EQ::ItemInstance *inst, StatBonuses* newbon, bool isAug = false); - int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat); void CalcEdibleBonuses(StatBonuses* newbon); void ProcessItemCaps(); void MakeBuffFadePacket(uint16 spell_id, int slot_id, bool send_message = true); bool client_data_loaded; - uint16 GetSympatheticFocusEffect(focusType type, uint16 spell_id); void FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost); @@ -1763,8 +1733,6 @@ private: inline uint32 GetRestTimer() const { return AggroCount ? m_pp.RestTimer : rest_timer.GetRemainingTime() / 1000; } void UpdateRestTimer(uint32 new_timer); - uint32 pLastUpdate; - uint32 pLastUpdateWZ; uint8 playeraction; EQStreamInterface* eqs; @@ -1803,7 +1771,6 @@ private: bool medding; uint16 horseId; bool revoked; - uint32 pQueuedSaveWorkID; uint16 pClientSideTarget; uint32 weight; bool berserk; @@ -1820,7 +1787,6 @@ private: bool Trader; bool Buyer; std::string BuyerWelcomeMessage; - bool AbilityTimer; int Haste; //precalced value uint32 tmSitting; // time stamp started sitting, used for HP regen bonus added on MAY 5, 2004 @@ -2079,6 +2045,9 @@ private: bool m_bot_precombat; bool CanTradeFVNoDropItem(); + void SendMobPositions(); + void PlayerTradeEventLog(Trade *t, Trade *t2); + }; #endif diff --git a/zone/client_bot.cpp b/zone/client_bot.cpp index e391888fe..1f3f809dd 100644 --- a/zone/client_bot.cpp +++ b/zone/client_bot.cpp @@ -33,7 +33,7 @@ uint32 Client::GetBotCreationLimit(uint8 class_id) auto bucket_value = GetBucket(bucket_name); if (!bucket_value.empty() && Strings::IsNumber(bucket_value)) { - bot_creation_limit = std::stoul(bucket_value); + bot_creation_limit = Strings::ToUnsignedInt(bucket_value); } return bot_creation_limit; @@ -57,7 +57,7 @@ int Client::GetBotRequiredLevel(uint8 class_id) auto bucket_value = GetBucket(bucket_name); if (!bucket_value.empty() && Strings::IsNumber(bucket_value)) { - bot_character_level = std::stoi(bucket_value); + bot_character_level = Strings::ToInt(bucket_value); } return bot_character_level; @@ -81,7 +81,7 @@ int Client::GetBotSpawnLimit(uint8 class_id) auto bucket_value = GetBucket(bucket_name); if (!bucket_value.empty() && Strings::IsNumber(bucket_value)) { - bot_spawn_limit = std::stoi(bucket_value); + bot_spawn_limit = Strings::ToInt(bucket_value); return bot_spawn_limit; } @@ -98,7 +98,7 @@ int Client::GetBotSpawnLimit(uint8 class_id) } auto row = results.begin(); - bot_spawn_limit = std::stoi(row[0]); + bot_spawn_limit = Strings::ToInt(row[0]); } return bot_spawn_limit; diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index c6eb3f31c..a9b70d453 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -51,7 +51,7 @@ int32 Client::GetMaxStat() const else { base = 330; } - return (base); + return base; } int32 Client::GetMaxResist() const @@ -234,7 +234,7 @@ int32 Client::LevelRegen() int64 Client::CalcHPRegen(bool bCombat) { int64 item_regen = itembonuses.HPRegen; // worn spells and +regen, already capped - item_regen += GetHeroicSTA() / 20; + item_regen += GetHeroicSTA() * RuleR(Character, HeroicStaminaMultiplier) / 20; item_regen += aabonuses.HPRegen; @@ -491,7 +491,7 @@ int64 Client::CalcBaseHP() auto base_data = database.GetBaseData(GetLevel(), GetClass()); if (base_data) { base_hp += base_data->base_hp + (base_data->hp_factor * stats); - base_hp += (GetHeroicSTA() * 10); + base_hp += GetHeroicSTA() * RuleR(Character, HeroicStaminaMultiplier) * 10; } } else { @@ -623,7 +623,9 @@ int64 Client::CalcBaseMana() } auto base_data = database.GetBaseData(GetLevel(), GetClass()); if (base_data) { - max_m = base_data->base_mana + (ConvertedWisInt * base_data->mana_factor) + (GetHeroicINT() * 10); + max_m = base_data->base_mana + + (ConvertedWisInt * base_data->mana_factor) + + (GetHeroicINT() * RuleR(Character, HeroicIntelligenceMultiplier) * 10); } } else { @@ -655,7 +657,9 @@ int64 Client::CalcBaseMana() } auto base_data = database.GetBaseData(GetLevel(), GetClass()); if (base_data) { - max_m = base_data->base_mana + (ConvertedWisInt * base_data->mana_factor) + (GetHeroicWIS() * 10); + max_m = base_data->base_mana + + (ConvertedWisInt * base_data->mana_factor) + + ((GetHeroicWIS() * RuleR(Character, HeroicWisdomMultiplier)) * 10); } } else { @@ -752,10 +756,10 @@ int64 Client::CalcManaRegen(bool bCombat) switch (GetCasterClass()) { case 'W': - heroic_bonus = GetHeroicWIS(); + heroic_bonus = GetHeroicWIS() * RuleR(Character, HeroicWisdomMultiplier); break; default: - heroic_bonus = GetHeroicINT(); + heroic_bonus = GetHeroicINT() * RuleR(Character, HeroicIntelligenceMultiplier); break; } @@ -1031,14 +1035,14 @@ int Client::CalcHaste() h += spellbonuses.hastetype2 > 10 ? 10 : spellbonuses.hastetype2; } // 26+ no cap, 1-25 10 - if (level > 25) { // 26+ + if (level > 25 || RuleB(Character, IgnoreLevelBasedHasteCaps)) { // 26+ h += itembonuses.haste; } else { // 1-25 h += itembonuses.haste > 10 ? 10 : itembonuses.haste; } // 60+ 100, 51-59 85, 1-50 level+25 - if (level > 59) { // 60+ + if (level > 59 || RuleB(Character, IgnoreLevelBasedHasteCaps)) { // 60+ cap = RuleI(Character, HasteCap); } else if (level > 50) { // 51-59 @@ -1047,12 +1051,11 @@ int Client::CalcHaste() else { // 1-50 cap = level + 25; } - cap = mod_client_haste_cap(cap); if (h > cap) { h = cap; } // 51+ 25 (despite there being higher spells...), 1-50 10 - if (level > 50) { // 51+ + if (level > 50 || RuleB(Character, IgnoreLevelBasedHasteCaps)) { // 51+ cap = RuleI(Character, Hastev3Cap); if (spellbonuses.hastetype3 > cap) { h += cap; @@ -1064,7 +1067,6 @@ int Client::CalcHaste() h += spellbonuses.hastetype3 > 10 ? 10 : spellbonuses.hastetype3; } h += ExtraHaste; //GM granted haste. - h = mod_client_haste(h); Haste = 100 + h; return Haste; } @@ -1688,8 +1690,13 @@ int64 Client::CalcBaseEndurance() { int64 base_end = 0; if (ClientVersion() >= EQ::versions::ClientVersion::SoF && RuleB(Character, SoDClientUseSoDHPManaEnd)) { - double heroic_stats = (GetHeroicSTR() + GetHeroicSTA() + GetHeroicDEX() + GetHeroicAGI()) / 4.0f; + double heroic_str = GetHeroicSTR() * RuleR(Character, HeroicStrengthMultiplier); + double heroic_sta = GetHeroicSTA() * RuleR(Character, HeroicStaminaMultiplier); + double heroic_dex = GetHeroicDEX() * RuleR(Character, HeroicDexterityMultiplier); + double heroic_agi = GetHeroicAGI() * RuleR(Character, HeroicAgilityMultiplier); + double heroic_stats = (heroic_str + heroic_sta + heroic_dex + heroic_agi) / 4; double stats = (GetSTR() + GetSTA() + GetDEX() + GetAGI()) / 4.0f; + if (stats > 201.0f) { stats = 1.25f * (stats - 201.0f) + 352.5f; } @@ -1787,7 +1794,11 @@ int64 Client::CalcEnduranceRegen(bool bCombat) if (encumbered) base += level / -15; - auto item_bonus = GetHeroicAGI() + GetHeroicDEX() + GetHeroicSTA() + GetHeroicSTR(); + double heroic_str = GetHeroicSTR() * RuleR(Character, HeroicStrengthMultiplier); + double heroic_sta = GetHeroicSTA() * RuleR(Character, HeroicStaminaMultiplier); + double heroic_dex = GetHeroicDEX() * RuleR(Character, HeroicDexterityMultiplier); + double heroic_agi = GetHeroicAGI() * RuleR(Character, HeroicAgilityMultiplier); + int32 item_bonus = heroic_str + heroic_sta + heroic_dex + heroic_agi; item_bonus = item_bonus / 4 / 50; item_bonus += itembonuses.EnduranceRegen; // this is capped already base += item_bonus; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 4b4b8f758..21140e337 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -25,6 +25,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include #include #include +#include "bot.h" +#include "bot_command.h" #ifdef _WINDOWS #define snprintf _snprintf @@ -71,6 +73,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../common/repositories/account_repository.h" #include "bot.h" +#include "../common/events/player_event_logs.h" extern QueryServ* QServ; extern Zone* zone; @@ -446,10 +449,11 @@ void ClearMappedOpcode(EmuOpcode op) // client methods int Client::HandlePacket(const EQApplicationPacket *app) { + auto o = eqs->GetOpcodeManager(); LogPacketClientServer( "[{}] [{:#06x}] Size [{}] {}", OpcodeManager::EmuToName(app->GetOpcode()), - eqs->GetOpcodeManager()->EmuToEQ(app->GetOpcode()), + o->EmuToEQ(app->GetOpcode()) == 0 ? app->GetProtocolOpcode() : o->EmuToEQ(app->GetOpcode()), app->Size(), (LogSys.IsLogEnabled(Logs::Detail, Logs::PacketClientServer) ? DumpPacketToString(app) : "") ); @@ -466,10 +470,10 @@ int Client::HandlePacket(const EQApplicationPacket *app) switch (client_state) { case CLIENT_CONNECTING: { if (ConnectingOpcodes.count(opcode) != 1) { - //Hate const cast but everything in lua needs to be non-const even if i make it non-mutable - std::vector args; - args.push_back(const_cast(app)); - parse->EventPlayer(EVENT_UNHANDLED_OPCODE, this, "", 1, &args); + if (parse->PlayerHasQuestSub(EVENT_UNHANDLED_OPCODE)) { + std::vector args = {const_cast(app)}; + parse->EventPlayer(EVENT_UNHANDLED_OPCODE, this, "", 1, &args); + } break; } @@ -491,9 +495,10 @@ int Client::HandlePacket(const EQApplicationPacket *app) ClientPacketProc p; p = ConnectedOpcodes[opcode]; if (p == nullptr) { - std::vector args; - args.push_back(const_cast(app)); - parse->EventPlayer(EVENT_UNHANDLED_OPCODE, this, "", 0, &args); + if (parse->PlayerHasQuestSub(EVENT_UNHANDLED_OPCODE)) { + std::vector args = {const_cast(app)}; + parse->EventPlayer(EVENT_UNHANDLED_OPCODE, this, "", 0, &args); + } break; } @@ -603,6 +608,29 @@ void Client::CompleteConnect() if (raid) { SetRaidGrouped(true); raid->LearnMembers(); + std::list bots_list; + database.botdb.LoadBotsList(this->CharacterID(), bots_list); + std::vector r_members = raid->GetMembers(); + for (const RaidMember& iter : r_members) { + if (iter.membername) { + for (const BotsAvailableList& b_iter : bots_list) + { + if (strcmp(iter.membername, b_iter.Name) == 0) + { + char buffer[71] = "^spawn "; + strcat(buffer, iter.membername); + bot_command_real_dispatch(this, buffer); + Bot* b = entity_list.GetBotByBotName(iter.membername); + if (b) + { + b->SetRaidGrouped(true); + b->p_raid_instance = raid; + //b->SetFollowID(this->GetID()); + } + } + } + } + } raid->VerifyRaid(); raid->GetRaidDetails(); /* @@ -776,13 +804,26 @@ void Client::CompleteConnect() TotalKarma = database.GetKarma(AccountID()); SendDisciplineTimers(); - parse->EventPlayer(EVENT_ENTER_ZONE, this, "", 0); + if (parse->PlayerHasQuestSub(EVENT_ENTER_ZONE)) { + parse->EventPlayer(EVENT_ENTER_ZONE, this, "", 0); + } + + // the way that the client deals with positions during the initial spawn struct + // is subtly different from how it deals with getting a position update + // if a mob is slightly in the wall or slightly clipping a floor they will be + // sent to a succor point + SendMobPositions(); SetLastPositionBeforeBulkUpdate(GetPosition()); /* This sub event is for if a player logs in for the first time since entering world. */ if (firstlogon == 1) { - parse->EventPlayer(EVENT_CONNECT, this, "", 0); + RecordPlayerEventLog(PlayerEvent::WENT_ONLINE, PlayerEvent::EmptyEvent{}); + + if (parse->PlayerHasQuestSub(EVENT_CONNECT)) { + parse->EventPlayer(EVENT_CONNECT, this, "", 0); + } + /* QS: PlayerLogConnectDisconnect */ if (RuleB(QueryServ, PlayerLogConnectDisconnect)) { std::string event_desc = StringFormat("Connect :: Logged into zoneid:%i instid:%i", GetZoneID(), GetInstanceID()); @@ -1222,17 +1263,17 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) ); auto results = database.QueryDatabase(query); for (auto row : results) { - if (row[4] && atoi(row[4]) > 0) { - guild_id = atoi(row[4]); - guildrank = row[5] ? atoi(row[5]) : GUILD_RANK_NONE; + if (row[4] && Strings::ToInt(row[4]) > 0) { + guild_id = Strings::ToInt(row[4]); + guildrank = row[5] ? Strings::ToInt(row[5]) : GUILD_RANK_NONE; } SetEXPEnabled(atobool(row[6])); - if (LFP) { LFP = atoi(row[0]); } - if (LFG) { LFG = atoi(row[1]); } + if (LFP) { LFP = Strings::ToInt(row[0]); } + if (LFG) { LFG = Strings::ToInt(row[1]); } if (row[3]) - firstlogon = atoi(row[3]); + firstlogon = Strings::ToInt(row[3]); } if (RuleB(Character, SharedBankPlat)) @@ -1440,7 +1481,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) database.LoadBuffs(this); uint32 max_slots = GetMaxBuffSlots(); for (int i = 0; i < BUFF_COUNT; i++) { - if (buffs[i].spellid != SPELL_UNKNOWN) { + if (IsValidSpell(buffs[i].spellid)) { m_pp.buffs[i].spellid = buffs[i].spellid; m_pp.buffs[i].bard_modifier = buffs[i].instrument_mod; m_pp.buffs[i].effect_type = 2; @@ -1518,27 +1559,27 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) group->SetNPCMarker(NPCMarkerName); group->SetGroupAAs(&GLAA); group->SetGroupMentor(mentor_percent, mentoree_name); - - //group->NotifyMainTank(this, 1); - //group->NotifyMainAssist(this, 1); - //group->NotifyPuller(this, 1); - - // If we are the leader, force an update of our group AAs to other members in the zone, in case - // we purchased a new one while out-of-zone. - if (group->IsLeader(this)) - group->SendLeadershipAAUpdate(); } + group->LearnMembers(); JoinGroupXTargets(group); group->UpdatePlayer(this); LFG = false; } + /* Load Bots */ if (RuleB(Bots, Enabled)) { database.botdb.LoadOwnerOptions(this); // TODO: mod below function for loading spawned botgroups Bot::LoadAndSpawnAllZonedBots(this); } + // If we are the leader, force an update of our group AAs to other members in the zone, in case + // we purchased a new one while out-of-zone. + // needs to be done after spawning bots + if (group && group->IsLeader(this)) { + group->SendLeadershipAAUpdate(); + } + m_inv.SetGMInventory((bool)m_pp.gm); // set to current gm state for calc CalcBonuses(); if (RuleB(Zone, EnableLoggedOffReplenishments) && @@ -2070,6 +2111,10 @@ void Client::Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app) if (item->MaxCharges != 0) charges = item->MaxCharges; + if (RuleB(Character, EnableDiscoveredItems) && !GetGM() && !IsDiscovered(item->ID)) { + DiscoverItem(item->ID); + } + EQ::ItemInstance *inst = database.CreateItem(item, charges); if (!AutoPutLootInInventory(*inst, true, true)) { @@ -2128,7 +2173,7 @@ void Client::Handle_OP_AdventureMerchantRequest(const EQApplicationPacket *app) theme = LDoNThemes::RUJ; } else if (item->LDoNTheme & LDoNThemeBits::MMCBit) { theme = LDoNThemes::MMC; - } else if (item->LDoNTheme & LDoNThemeBits::RUJBit) { + } else if (item->LDoNTheme & LDoNThemeBits::MIRBit) { theme = LDoNThemes::MIR; } else if (item->LDoNTheme & LDoNThemeBits::GUKBit) { theme = LDoNThemes::GUK; @@ -2233,9 +2278,6 @@ void Client::Handle_OP_AdventureMerchantSell(const EQApplicationPacket *app) return; } - if (RuleB(EventLog, RecordSellToMerchant)) - LogMerchant(this, vendor, ams_in->charges, price, item, false); - if (!inst->IsStackable()) { DeleteItemInInventory(ams_in->slot); @@ -2362,7 +2404,7 @@ void Client::Handle_OP_AdventureRequest(const EQApplicationPacket *app) if (IsRaidGrouped()) { int i = 0; - for (int x = 0; x < 72; ++x) + for (int x = 0; x < MAX_RAID_MEMBERS; ++x) { if (i == group_members) { @@ -2381,7 +2423,7 @@ void Client::Handle_OP_AdventureRequest(const EQApplicationPacket *app) else { int i = 0; - for (int x = 0; x < 6; ++x) + for (int x = 0; x < MAX_GROUP_MEMBERS; ++x) { if (i == group_members) { @@ -2583,20 +2625,45 @@ void Client::Handle_OP_AltCurrencyPurchase(const EQApplicationPacket *app) QServ->PlayerLogEvent(Player_Log_Alternate_Currency_Transactions, CharacterID(), event_desc); } - const auto& export_string = fmt::format( - "{} {} {} {} {}", - alt_cur_id, - tar->GetNPCTypeID(), - tar->MerchantType, - item->ID, - cost - ); - parse->EventPlayer(EVENT_ALT_CURRENCY_MERCHANT_BUY, this, export_string, 0); + if (parse->PlayerHasQuestSub(EVENT_ALT_CURRENCY_MERCHANT_BUY)) { + const auto& export_string = fmt::format( + "{} {} {} {} {}", + alt_cur_id, + tar->GetNPCTypeID(), + tar->MerchantType, + item->ID, + cost + ); - AddAlternateCurrencyValue(alt_cur_id, -((int32)cost)); - int16 charges = 1; - if (item->MaxCharges != 0) + parse->EventPlayer(EVENT_ALT_CURRENCY_MERCHANT_BUY, this, export_string, 0); + } + + uint64 current_balance = AddAlternateCurrencyValue(alt_cur_id, -((int32) cost)); + int16 charges = 1; + if (item->MaxCharges != 0) { charges = item->MaxCharges; + } + + if (player_event_logs.IsEventEnabled(PlayerEvent::MERCHANT_PURCHASE)) { + auto e = PlayerEvent::MerchantPurchaseEvent{ + .npc_id = tar->GetNPCTypeID(), + .merchant_name = tar->GetCleanName(), + .merchant_type = tar->MerchantType, + .item_id = item->ID, + .item_name = item->Name, + .charges = charges, + .cost = cost, + .alternate_currency_id = alt_cur_id, + .player_money_balance = GetCarriedMoney(), + .player_currency_balance = current_balance, + }; + + RecordPlayerEventLog(PlayerEvent::MERCHANT_PURCHASE, e); + } + + if (RuleB(Character, EnableDiscoveredItems) && !GetGM() && !IsDiscovered(item->ID)) { + DiscoverItem(item->ID); + } EQ::ItemInstance *inst = database.CreateItem(item, charges); if (!AutoPutLootInInventory(*inst, true, true)) @@ -2756,18 +2823,39 @@ void Client::Handle_OP_AltCurrencySell(const EQApplicationPacket *app) QServ->PlayerLogEvent(Player_Log_Alternate_Currency_Transactions, CharacterID(), event_desc); } - const auto& export_string = fmt::format( - "{} {} {} {} {}", - alt_cur_id, - tar->GetNPCTypeID(), - tar->MerchantType, - item->ID, - cost - ); - parse->EventPlayer(EVENT_ALT_CURRENCY_MERCHANT_SELL, this, export_string, 0); + if (parse->PlayerHasQuestSub(EVENT_ALT_CURRENCY_MERCHANT_SELL)) { + const auto& export_string = fmt::format( + "{} {} {} {} {}", + alt_cur_id, + tar->GetNPCTypeID(), + tar->MerchantType, + item->ID, + cost + ); + + parse->EventPlayer(EVENT_ALT_CURRENCY_MERCHANT_SELL, this, export_string, 0); + } FastQueuePacket(&outapp); - AddAlternateCurrencyValue(alt_cur_id, cost); + uint64 new_balance = AddAlternateCurrencyValue(alt_cur_id, cost); + + if (player_event_logs.IsEventEnabled(PlayerEvent::MERCHANT_SELL)) { + auto e = PlayerEvent::MerchantSellEvent{ + .npc_id = tar->GetNPCTypeID(), + .merchant_name = tar->GetCleanName(), + .merchant_type = tar->CastToNPC()->MerchantType, + .item_id = item->ID, + .item_name = item->Name, + .charges = static_cast(sell->charges), + .cost = cost, + .alternate_currency_id = 0, + .player_money_balance = GetCarriedMoney(), + .player_currency_balance = new_balance, + }; + + RecordPlayerEventLog(PlayerEvent::MERCHANT_SELL, e); + } + Save(1); } } @@ -3093,24 +3181,48 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) std::vector args; args.push_back(old_aug); - parse->EventItem(EVENT_UNAUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args); + + if (parse->ItemHasQuestSub(tobe_auged, EVENT_UNAUGMENT_ITEM)) { + parse->EventItem( + EVENT_UNAUGMENT_ITEM, + this, + tobe_auged, + nullptr, + "", + in_augment->augment_index, + &args + ); + } args.assign(1, tobe_auged); args.push_back(false); - parse->EventItem(EVENT_AUGMENT_REMOVE, this, old_aug, nullptr, "", in_augment->augment_index, &args); - const auto export_string = fmt::format( - "{} {} {} {} {}", - tobe_auged->GetID(), - item_slot, - old_aug->GetID(), - in_augment->augment_index, - false - ); + if (parse->ItemHasQuestSub(old_aug, EVENT_AUGMENT_REMOVE)) { + parse->EventItem( + EVENT_AUGMENT_REMOVE, + this, + old_aug, + nullptr, + "", + in_augment->augment_index, + &args + ); + } - args.push_back(old_aug); + if (parse->PlayerHasQuestSub(EVENT_AUGMENT_REMOVE_CLIENT)) { + const auto& export_string = fmt::format( + "{} {} {} {} {}", + tobe_auged->GetID(), + item_slot, + old_aug->GetID(), + in_augment->augment_index, + false + ); - parse->EventPlayer(EVENT_AUGMENT_REMOVE_CLIENT, this, export_string, 0, &args); + args.push_back(old_aug); + + parse->EventPlayer(EVENT_AUGMENT_REMOVE_CLIENT, this, export_string, 0, &args); + } } tobe_auged->PutAugment(in_augment->augment_index, *new_aug); @@ -3120,22 +3232,46 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) if (aug) { std::vector args; args.push_back(aug); - parse->EventItem(EVENT_AUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args); + + if (parse->ItemHasQuestSub(tobe_auged, EVENT_AUGMENT_ITEM)) { + parse->EventItem( + EVENT_AUGMENT_ITEM, + this, + tobe_auged, + nullptr, + "", + in_augment->augment_index, + &args + ); + } args.assign(1, tobe_auged); - parse->EventItem(EVENT_AUGMENT_INSERT, this, aug, nullptr, "", in_augment->augment_index, &args); + + if (parse->ItemHasQuestSub(aug, EVENT_AUGMENT_INSERT)) { + parse->EventItem( + EVENT_AUGMENT_INSERT, + this, + aug, + nullptr, + "", + in_augment->augment_index, + &args + ); + } args.push_back(aug); - const auto export_string = fmt::format( - "{} {} {} {}", - tobe_auged->GetID(), - item_slot, - aug->GetID(), - in_augment->augment_index - ); + if (parse->PlayerHasQuestSub(EVENT_AUGMENT_INSERT_CLIENT)) { + const auto& export_string = fmt::format( + "{} {} {} {}", + tobe_auged->GetID(), + item_slot, + aug->GetID(), + in_augment->augment_index + ); - parse->EventPlayer(EVENT_AUGMENT_INSERT_CLIENT, this, export_string, 0, &args); + parse->EventPlayer(EVENT_AUGMENT_INSERT_CLIENT, this, export_string, 0, &args); + } } else { Message( Chat::Red, @@ -3188,24 +3324,48 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) if (aug) { std::vector args; args.push_back(aug); - parse->EventItem(EVENT_UNAUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args); + + if (parse->ItemHasQuestSub(tobe_auged, EVENT_UNAUGMENT_ITEM)) { + parse->EventItem( + EVENT_UNAUGMENT_ITEM, + this, + tobe_auged, + nullptr, + "", + in_augment->augment_index, + &args + ); + } args.assign(1, tobe_auged); args.push_back(false); - parse->EventItem(EVENT_AUGMENT_REMOVE, this, aug, nullptr, "", in_augment->augment_index, &args); + + if (parse->ItemHasQuestSub(aug, EVENT_AUGMENT_REMOVE)) { + parse->EventItem( + EVENT_AUGMENT_REMOVE, + this, + aug, + nullptr, + "", + in_augment->augment_index, + &args + ); + } args.push_back(aug); - const auto export_string = fmt::format( - "{} {} {} {} {}", - tobe_auged->GetID(), - item_slot, - aug->GetID(), - in_augment->augment_index, - false - ); + if (parse->PlayerHasQuestSub(EVENT_AUGMENT_REMOVE_CLIENT)) { + const auto& export_string = fmt::format( + "{} {} {} {} {}", + tobe_auged->GetID(), + item_slot, + aug->GetID(), + in_augment->augment_index, + false + ); - parse->EventPlayer(EVENT_AUGMENT_REMOVE_CLIENT, this, export_string, 0, &args); + parse->EventPlayer(EVENT_AUGMENT_REMOVE_CLIENT, this, export_string, 0, &args); + } } else { Message(Chat::Red, "Error: Could not find augmentation to remove at index %i. Aborting.", in_augment->augment_index); return; @@ -3252,24 +3412,48 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) if (aug) { std::vector args; args.push_back(aug); - parse->EventItem(EVENT_UNAUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args); + + if (parse->ItemHasQuestSub(tobe_auged, EVENT_UNAUGMENT_ITEM)) { + parse->EventItem( + EVENT_UNAUGMENT_ITEM, + this, + tobe_auged, + nullptr, + "", + in_augment->augment_index, + &args + ); + } args.assign(1, tobe_auged); args.push_back(true); - parse->EventItem(EVENT_AUGMENT_REMOVE, this, aug, nullptr, "", in_augment->augment_index, &args); + + if (parse->ItemHasQuestSub(aug, EVENT_AUGMENT_REMOVE)) { + parse->EventItem( + EVENT_AUGMENT_REMOVE, + this, + aug, + nullptr, + "", + in_augment->augment_index, + &args + ); + } args.push_back(aug); - const auto export_string = fmt::format( - "{} {} {} {} {}", - tobe_auged->GetID(), - item_slot, - aug->GetID(), - in_augment->augment_index, - true - ); + if (parse->PlayerHasQuestSub(EVENT_AUGMENT_REMOVE_CLIENT)) { + const auto& export_string = fmt::format( + "{} {} {} {} {}", + tobe_auged->GetID(), + item_slot, + aug->GetID(), + in_augment->augment_index, + true + ); - parse->EventPlayer(EVENT_AUGMENT_REMOVE_CLIENT, this, export_string, 0, &args); + parse->EventPlayer(EVENT_AUGMENT_REMOVE_CLIENT, this, export_string, 0, &args); + } } else { Message( Chat::Red, @@ -3434,10 +3618,10 @@ void Client::Handle_OP_BankerChange(const EQApplicationPacket *app) if (!banker || distance > USE_NPC_RANGE2) { - auto hacked_string = fmt::format( + auto message = fmt::format( "Player tried to make use of a banker(money) but {} is non-existant or too far away ({} units).", banker ? banker->GetName() : "UNKNOWN NPC", distance); - database.SetMQDetectionFlag(AccountName(), GetName(), hacked_string, zone->GetShortName()); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); return; } @@ -4035,10 +4219,6 @@ void Client::Handle_OP_Bug(const EQApplicationPacket *app) void Client::Handle_OP_Camp(const EQApplicationPacket *app) { - if (RuleB(Bots, Enabled)) { - Bot::BotOrderCampAll(this); - } - if (IsLFP()) worldserver.StopLFP(CharacterID()); @@ -4157,7 +4337,8 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) const EQ::ItemData* item = inst->GetItem(); if (item->Click.Effect != (uint32)castspell->spell_id) { - database.SetMQDetectionFlag(account_name, name, "OP_CastSpell with item, tried to cast a different spell.", zone->GetShortName()); + std::string message = fmt::format("OP_CastSpell with item, tried to cast a different spell than what was on item - item spell id [{}] attempted [{}]", item->Click.Effect, (uint32)castspell->spell_id); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); InterruptSpell(castspell->spell_id); //CHEATER!! return; } @@ -4168,33 +4349,71 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) { if (GetLevel() >= item->Click.Level2) { - EQ::ItemInstance* p_inst = (EQ::ItemInstance*)inst; - int i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, nullptr, "", castspell->inventoryslot); + auto* p_inst = (EQ::ItemInstance*) inst; + int i = 0; + + if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) { + i = parse->EventItem( + EVENT_ITEM_CLICK_CAST, + this, + p_inst, + nullptr, + "", + castspell->inventoryslot + ); + } + + if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) { + std::vector args; + args.emplace_back(p_inst); + i = parse->EventPlayer(EVENT_ITEM_CLICK_CAST_CLIENT, this, std::to_string(castspell->inventoryslot), 0, &args); + } + if (i == 0) { CastSpell(item->Click.Effect, castspell->target_id, slot, item->CastTime, 0, 0, castspell->inventoryslot); } else { InterruptSpell(castspell->spell_id); + SendSpellBarEnable(castspell->spell_id); return; } } else { - database.SetMQDetectionFlag(account_name, name, "OP_CastSpell with item, did not meet req level.", zone->GetShortName()); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "OP_CastSpell with item, did not meet req level."}); Message(Chat::Red, "Error: level not high enough.", castspell->inventoryslot); InterruptSpell(castspell->spell_id); } } else { - EQ::ItemInstance* p_inst = (EQ::ItemInstance*)inst; - int i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, nullptr, "", castspell->inventoryslot); + auto* p_inst = (EQ::ItemInstance*) inst; + + int i = 0; + + if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) { + i = parse->EventItem( + EVENT_ITEM_CLICK_CAST, + this, + p_inst, + nullptr, + "", + castspell->inventoryslot + ); + } + + if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) { + std::vector args; + args.emplace_back(p_inst); + i = parse->EventPlayer(EVENT_ITEM_CLICK_CAST_CLIENT, this, std::to_string(castspell->inventoryslot), 0, &args); + } if (i == 0) { CastSpell(item->Click.Effect, castspell->target_id, slot, item->CastTime, 0, 0, castspell->inventoryslot); } else { InterruptSpell(castspell->spell_id); + SendSpellBarEnable(castspell->spell_id); return; } } @@ -4343,27 +4562,50 @@ void Client::Handle_OP_ClickDoor(const EQApplicationPacket *app) return; } - // set door selected - if (IsDevToolsEnabled()) { + float distance = DistanceNoZ(GetPosition(), currentdoor->GetPosition()); + + LogDoors( + "Door [{}] client handle, client distance from door [{:.2f}]", + currentdoor->GetDoorID(), + distance + ); + + bool within_distance = distance < RuleI(Range, MaxDistanceToClickDoors); + + // distance gate this because some doors are client controlled and the client + // will spam door click even across the zone to force a door back into desired state + if (IsDevToolsEnabled() && within_distance) { SetDoorToolEntityId(currentdoor->GetEntityID()); DoorManipulation::CommandHeader(this); Message( Chat::White, fmt::format( "Door ({}) [{}]", - currentdoor->GetEntityID(), + currentdoor->GetDoorID(), Saylink::Silent("#door edit") ).c_str() ); } - std::string export_string = fmt::format("{}", cd->doorid); - std::vector args; - args.push_back(currentdoor); - if (parse->EventPlayer(EVENT_CLICK_DOOR, this, export_string, 0, &args) == 0) - { + // don't spam scripts with client controlled doors if not within distance + if (within_distance) { + int quest_return = 0; + if (parse->PlayerHasQuestSub(EVENT_CLICK_DOOR)) { + std::vector args = {currentdoor}; + + quest_return = parse->EventPlayer(EVENT_CLICK_DOOR, this, std::to_string(cd->doorid), 0, &args); + } + + if (quest_return == 0) { + currentdoor->HandleClick(this, 0); + } + } + else { + // we let this pass because client controlled doors require this to force the linked doors + // back into state currentdoor->HandleClick(this, 0); } + } void Client::Handle_OP_ClickObject(const EQApplicationPacket *app) @@ -4374,18 +4616,17 @@ void Client::Handle_OP_ClickObject(const EQApplicationPacket *app) return; } - ClickObject_Struct* click_object = (ClickObject_Struct*)app->pBuffer; - Entity* entity = entity_list.GetID(click_object->drop_id); + auto* click_object = (ClickObject_Struct*) app->pBuffer; + auto* entity = entity_list.GetID(click_object->drop_id); if (entity && entity->IsObject()) { - Object* object = entity->CastToObject(); + auto* object = entity->CastToObject(); object->HandleClick(this, click_object); - std::vector args; - args.push_back(object); - - std::string export_string = fmt::format("{}", click_object->drop_id); - parse->EventPlayer(EVENT_CLICK_OBJECT, this, export_string, GetID(), &args); + if (parse->PlayerHasQuestSub(EVENT_CLICK_OBJECT)) { + std::vector args = { object }; + parse->EventPlayer(EVENT_CLICK_OBJECT, this, std::to_string(click_object->drop_id), GetID(), &args); + } } // Observed in RoF after OP_ClickObjectAction: @@ -4824,110 +5065,117 @@ void Client::Handle_OP_ConsentDeny(const EQApplicationPacket *app) void Client::Handle_OP_Consider(const EQApplicationPacket *app) { - if (app->size != sizeof(Consider_Struct)) - { + if (app->size != sizeof(Consider_Struct)) { LogDebug("Size mismatch in Consider expected [{}] got [{}]", sizeof(Consider_Struct), app->size); return; } - Consider_Struct* conin = (Consider_Struct*)app->pBuffer; - Mob* tmob = entity_list.GetMob(conin->targetid); - if (tmob == 0) - return; - std::string export_string = fmt::format("{}", conin->targetid); - if (parse->EventPlayer(EVENT_CONSIDER, this, export_string, 0) == 1) { + auto *conin = (Consider_Struct*) app->pBuffer; + auto *t = entity_list.GetMob(conin->targetid); + if (!t) { return; } - if (tmob->GetClass() == LDON_TREASURE) - { - Message(Chat::Yellow, "%s", tmob->GetCleanName()); + if (parse->PlayerHasQuestSub(EVENT_CONSIDER)) { + std::vector args = { t }; + + if (parse->EventPlayer(EVENT_CONSIDER, this, std::to_string(conin->targetid), 0, &args) == 1) { + return; + } + } + + if (t->GetClass() == LDON_TREASURE) { + Message(Chat::Yellow, fmt::format("{}", t->GetCleanName()).c_str()); return; } auto outapp = new EQApplicationPacket(OP_Consider, sizeof(Consider_Struct)); - Consider_Struct* con = (Consider_Struct*)outapp->pBuffer; + auto* con = (Consider_Struct*) outapp->pBuffer; con->playerid = GetID(); con->targetid = conin->targetid; - if (tmob->IsNPC()) - con->faction = GetFactionLevel(character_id, tmob->GetNPCTypeID(), GetFactionRace(), class_, deity, (tmob->IsNPC()) ? tmob->CastToNPC()->GetPrimaryFaction() : 0, tmob); // Dec. 20, 2001; TODO: Send the players proper deity - else + if (t->IsNPC()) { + con->faction = GetFactionLevel( + character_id, + t->GetNPCTypeID(), + GetFactionRace(), + class_, + deity, + (t->IsNPC()) ? t->CastToNPC()->GetPrimaryFaction() : 0, + t + ); + } else { con->faction = 1; - con->level = GetLevelCon(tmob->GetLevel()); + } + + con->level = GetLevelCon(t->GetLevel()); if (ClientVersion() <= EQ::versions::ClientVersion::Titanium) { - if (con->level == CON_GRAY) { + if (con->level == CON_GRAY) { con->level = CON_GREEN; - } - if (con->level == CON_WHITE) { + } else if (con->level == CON_WHITE) { con->level = CON_WHITE_TITANIUM; } } if (zone->IsPVPZone()) { - if (!tmob->IsNPC()) - con->pvpcon = tmob->CastToClient()->GetPVP(); + if (!t->IsNPC()) { + con->pvpcon = t->CastToClient()->GetPVP(); + } } // If we're feigned show NPC as indifferent - if (tmob->IsNPC()) - { - if (GetFeigned()) + if (t->IsNPC()) { + if (GetFeigned()) { con->faction = FACTION_INDIFFERENTLY; + } } - if (!(con->faction == FACTION_SCOWLS)) - { - if (tmob->IsNPC()) - { - if (tmob->CastToNPC()->IsOnHatelist(this)) + if (!(con->faction == FACTION_SCOWLS)) { + if (t->IsNPC()) { + if (t->CastToNPC()->IsOnHatelist(this)) { con->faction = FACTION_THREATENINGLY; + } } } if (con->faction == FACTION_APPREHENSIVELY) { con->faction = FACTION_SCOWLS; - } - else if (con->faction == FACTION_DUBIOUSLY) { + } else if (con->faction == FACTION_DUBIOUSLY) { con->faction = FACTION_THREATENINGLY; - } - else if (con->faction == FACTION_SCOWLS) { + } else if (con->faction == FACTION_SCOWLS) { con->faction = FACTION_APPREHENSIVELY; - } - else if (con->faction == FACTION_THREATENINGLY) { + } else if (con->faction == FACTION_THREATENINGLY) { con->faction = FACTION_DUBIOUSLY; } - mod_consider(tmob, con); - QueuePacket(outapp); // only wanted to check raid target once // and need con to still be around so, do it here! - if (tmob->IsRaidTarget()) { + if (t->IsRaidTarget()) { uint32 color = 0; switch (con->level) { - case CON_GREEN: - color = 2; - break; - case CON_LIGHTBLUE: - color = 10; - break; - case CON_BLUE: - color = 4; - break; - case CON_WHITE_TITANIUM: - case CON_WHITE: - color = 10; - break; - case CON_YELLOW: - color = 15; - break; - case CON_RED: - color = 13; - break; - case CON_GRAY: - color = 6; - break; + case CON_GREEN: + color = 2; + break; + case CON_LIGHTBLUE: + color = 10; + break; + case CON_BLUE: + color = 4; + break; + case CON_WHITE_TITANIUM: + case CON_WHITE: + color = 10; + break; + case CON_YELLOW: + color = 15; + break; + case CON_RED: + color = 13; + break; + case CON_GRAY: + color = 6; + break; } if (ClientVersion() <= EQ::versions::ClientVersion::Titanium) { @@ -4941,11 +5189,11 @@ void Client::Handle_OP_Consider(const EQApplicationPacket *app) // this could be done better, but this is only called when you con so w/e // Shroud of Stealth has a special message - if (improved_hidden && (!tmob->see_improved_hide && (tmob->SeeInvisible() || tmob->see_hide))) - MessageString(Chat::NPCQuestSay, SOS_KEEPS_HIDDEN); - // we are trying to hide but they can see us - else if ((invisible || invisible_undead || hidden || invisible_animals) && !IsInvisible(tmob)) + if (improved_hidden && (!t->see_improved_hide && (t->SeeInvisible() || t->see_hide))) { + MessageString(Chat::NPCQuestSay, SOS_KEEPS_HIDDEN); // we are trying to hide but they can see us + } else if ((invisible || invisible_undead || hidden || invisible_animals) && !IsInvisible(t)) { MessageString(Chat::NPCQuestSay, SUSPECT_SEES_YOU); + } safe_delete(outapp); @@ -4959,18 +5207,21 @@ void Client::Handle_OP_ConsiderCorpse(const EQApplicationPacket *app) return; } - Consider_Struct* conin = (Consider_Struct*)app->pBuffer; - Corpse* target = entity_list.GetCorpseByID(conin->targetid); - std::string export_string = fmt::format("{}", conin->targetid); - if (!target) { + auto* conin = (Consider_Struct*)app->pBuffer; + auto* t = entity_list.GetCorpseByID(conin->targetid); + if (!t) { return; } - if (parse->EventPlayer(EVENT_CONSIDER_CORPSE, this, export_string, 0)) { - return; + if (parse->PlayerHasQuestSub(EVENT_CONSIDER_CORPSE)) { + std::vector args = { t }; + + if (parse->EventPlayer(EVENT_CONSIDER_CORPSE, this, std::to_string(conin->targetid), 0, &args)) { + return; + } } - uint32 decay_time = target->GetDecayTime(); + uint32 decay_time = t->GetDecayTime(); if (decay_time) { auto time_string = Strings::SecondsToTime(decay_time, true); Message( @@ -4981,12 +5232,12 @@ void Client::Handle_OP_ConsiderCorpse(const EQApplicationPacket *app) ).c_str() ); - if (target->IsPlayerCorpse()) { + if (t->IsPlayerCorpse()) { Message( Chat::NPCQuestSay, fmt::format( "This corpse {} be resurrected.", - target->IsRezzed() ? "cannot" : "can" + t->IsRezzed() ? "cannot" : "can" ).c_str() ); } @@ -5083,8 +5334,8 @@ void Client::Handle_OP_ControlBoat(const EQApplicationPacket *app) if (!boat->IsNPC() || !boat->IsControllableBoat()) { - auto hacked_string = fmt::format("OP_Control Boat was sent against {} which is of race {}", boat->GetName(), boat->GetRace()); - database.SetMQDetectionFlag(AccountName(), GetName(), hacked_string, zone->GetShortName()); + auto message = fmt::format("OP_Control Boat was sent against {} which is of race {}", boat->GetName(), boat->GetRace()); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); return; } @@ -5353,6 +5604,17 @@ void Client::Handle_OP_DeleteItem(const EQApplicationPacket *app) } DeleteItemInInventory(alc->from_slot, 1); + if (player_event_logs.IsEventEnabled(PlayerEvent::ITEM_DESTROY)) { + auto e = PlayerEvent::DestroyItemEvent{ + .item_id = inst->GetItem()->ID, + .item_name = inst->GetItem()->Name, + .charges = inst->GetCharges(), + .reason = "Client deleted", + }; + + RecordPlayerEventLog(PlayerEvent::ITEM_DESTROY, e); + } + return; } @@ -5404,8 +5666,9 @@ void Client::Handle_OP_Disarm(const EQApplicationPacket *app) { return; if (pmob->GetID() != GetID()) { // Client sent a disarm request with an originator ID not matching their own ID. - auto hack_str = fmt::format("Player {} ({}) sent OP_Disarm with source ID of: {}", GetCleanName(), GetID(), pmob->GetID()); - database.SetMQDetectionFlag(account_name, name, hack_str, zone->GetShortName()); + auto message = fmt::format("Player {} ({}) sent OP_Disarm with source ID of: {}", GetCleanName(), GetID(), pmob->GetID()); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); + return; } // No disarm on corpses @@ -5958,18 +6221,20 @@ void Client::Handle_OP_EnvDamage(const EQApplicationPacket *app) return; } else { SetHP(GetHP() - (damage * RuleR(Character, EnvironmentDamageMulipliter))); - int final_damage = (damage * RuleR(Character, EnvironmentDamageMulipliter)); - std::string export_string = fmt::format( - "{} {} {}", - ed->damage, - ed->dmgtype, - final_damage - ); - parse->EventPlayer(EVENT_ENVIRONMENTAL_DAMAGE, this, export_string, 0); + + if (parse->PlayerHasQuestSub(EVENT_ENVIRONMENTAL_DAMAGE)) { + int final_damage = (damage * RuleR(Character, EnvironmentDamageMulipliter)); + const auto& export_string = fmt::format( + "{} {} {}", + ed->damage, + ed->dmgtype, + final_damage + ); + parse->EventPlayer(EVENT_ENVIRONMENTAL_DAMAGE, this, export_string, 0); + } } if (GetHP() <= 0) { - mod_client_death_env(); Death(0, 32000, SPELL_UNKNOWN, EQ::skills::SkillHandtoHand); } SendHPUpdate(); @@ -6069,7 +6334,9 @@ void Client::Handle_OP_Fishing(const EQApplicationPacket *app) } if (CanFish()) { - parse->EventPlayer(EVENT_FISH_START, this, "", 0); + if (parse->PlayerHasQuestSub(EVENT_FISH_START)) { + parse->EventPlayer(EVENT_FISH_START, this, "", 0); + } //these will trigger GoFish() after a delay if we're able to actually fish, and if not, we won't stop the client from trying again immediately (although we may need to tell it to repop the button) p_timers.Start(pTimerFishing, FishingReuseTime - 1); @@ -6132,7 +6399,7 @@ void Client::Handle_OP_GMBecomeNPC(const EQApplicationPacket *app) { if (Admin() < minStatusToUseGMCommands) { Message(Chat::Red, "Your account has been reported for hacking."); - database.SetHackerFlag(account_name, name, "/becomenpc"); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /becomenpc when they shouldn't be able to"}); return; } if (app->size != sizeof(BecomeNPC_Struct)) { @@ -6172,7 +6439,7 @@ void Client::Handle_OP_GMDelCorpse(const EQApplicationPacket *app) return; if (Admin() < commandEditPlayerCorpses) { Message(Chat::Red, "Your account has been reported for hacking."); - database.SetHackerFlag(account_name, name, "/delcorpse"); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /delcorpse"}); return; } GMDelCorpse_Struct* dc = (GMDelCorpse_Struct *)app->pBuffer; @@ -6193,7 +6460,6 @@ void Client::Handle_OP_GMEmoteZone(const EQApplicationPacket *app) { if (Admin() < minStatusToUseGMCommands) { Message(Chat::Red, "Your account has been reported for hacking."); - database.SetHackerFlag(account_name, name, "/emote"); return; } if (app->size != sizeof(GMEmoteZone_Struct)) { @@ -6226,7 +6492,7 @@ void Client::Handle_OP_GMFind(const EQApplicationPacket *app) { if (Admin() < minStatusToUseGMCommands) { Message(Chat::Red, "Your account has been reported for hacking."); - database.SetHackerFlag(account_name, name, "/find"); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /find"}); return; } if (app->size != sizeof(GMSummon_Struct)) { @@ -6264,7 +6530,7 @@ void Client::Handle_OP_GMGoto(const EQApplicationPacket *app) } if (Admin() < minStatusToUseGMCommands) { Message(Chat::Red, "Your account has been reported for hacking."); - database.SetHackerFlag(account_name, name, "/goto"); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /goto"}); return; } GMSummon_Struct* gmg = (GMSummon_Struct*)app->pBuffer; @@ -6291,7 +6557,7 @@ void Client::Handle_OP_GMHideMe(const EQApplicationPacket *app) { if (Admin() < minStatusToUseGMCommands) { Message(Chat::Red, "Your account has been reported for hacking."); - database.SetHackerFlag(account_name, name, "/hideme"); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /hideme"}); return; } if (app->size != sizeof(SpawnAppearance_Struct)) { @@ -6311,7 +6577,7 @@ void Client::Handle_OP_GMKick(const EQApplicationPacket *app) return; if (Admin() < minStatusToKick) { Message(Chat::Red, "Your account has been reported for hacking."); - database.SetHackerFlag(account_name, name, "/kick"); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /kick"}); return; } GMKick_Struct* gmk = (GMKick_Struct *)app->pBuffer; @@ -6341,7 +6607,7 @@ void Client::Handle_OP_GMKill(const EQApplicationPacket *app) { if (Admin() < minStatusToUseGMCommands) { Message(Chat::Red, "Your account has been reported for hacking."); - database.SetHackerFlag(account_name, name, "/kill"); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /kill"}); return; } if (app->size != sizeof(GMKill_Struct)) { @@ -6393,7 +6659,7 @@ void Client::Handle_OP_GMLastName(const EQApplicationPacket *app) else { if (Admin() < minStatusToUseGMCommands) { Message(Chat::Red, "Your account has been reported for hacking."); - database.SetHackerFlag(client->account_name, client->name, "/lastname"); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /lastname"}); return; } else @@ -6418,7 +6684,7 @@ void Client::Handle_OP_GMNameChange(const EQApplicationPacket *app) const GMName_Struct* gmn = (const GMName_Struct *)app->pBuffer; if (Admin() < minStatusToUseGMCommands) { Message(Chat::Red, "Your account has been reported for hacking."); - database.SetHackerFlag(account_name, name, "/name"); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /name"}); return; } Client* client = entity_list.GetClientByName(gmn->oldname); @@ -6502,15 +6768,15 @@ void Client::Handle_OP_GMSearchCorpse(const EQApplicationPacket *app) strn0cpy(charName, row[0], sizeof(charName)); - uint32 ZoneID = atoi(row[1]); - float CorpseX = atof(row[2]); - float CorpseY = atof(row[3]); - float CorpseZ = atof(row[4]); + uint32 ZoneID = Strings::ToInt(row[1]); + float CorpseX = Strings::ToFloat(row[2]); + float CorpseY = Strings::ToFloat(row[3]); + float CorpseZ = Strings::ToFloat(row[4]); strn0cpy(time_of_death, row[5], sizeof(time_of_death)); - bool corpseRezzed = atoi(row[6]); - bool corpseBuried = atoi(row[7]); + bool corpseRezzed = Strings::ToInt(row[6]); + bool corpseBuried = Strings::ToInt(row[7]); popupText += StringFormat("%s%s%8.0f%8.0f%8.0f%s%s%s", charName, StaticGetZoneName(ZoneID), CorpseX, CorpseY, CorpseZ, time_of_death, @@ -6561,7 +6827,7 @@ void Client::Handle_OP_GMToggle(const EQApplicationPacket *app) } if (Admin() < minStatusToUseGMCommands) { Message(Chat::Red, "Your account has been reported for hacking."); - database.SetHackerFlag(account_name, name, "/toggle"); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /toggle"}); return; } GMToggle_Struct *ts = (GMToggle_Struct *)app->pBuffer; @@ -6608,7 +6874,7 @@ void Client::Handle_OP_GMZoneRequest(const EQApplicationPacket *app) } if (Admin() < minStatusToBeGM) { Message(Chat::Red, "Your account has been reported for hacking."); - database.SetHackerFlag(account_name, name, "/zone"); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /zone"}); return; } @@ -6664,7 +6930,7 @@ void Client::Handle_OP_GMZoneRequest2(const EQApplicationPacket *app) { if (Admin() < minStatusToBeGM) { Message(Chat::Red, "Your account has been reported for hacking."); - database.SetHackerFlag(account_name, name, "/zone"); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /zone"}); return; } if (app->size < sizeof(uint32)) { @@ -6739,47 +7005,48 @@ void Client::Handle_OP_GroupDisband(const EQApplicationPacket *app) GroupGeneric_Struct* gd = (GroupGeneric_Struct*)app->pBuffer; Raid *raid = entity_list.GetRaidByClient(this); - if (raid) - { - Mob* memberToDisband = nullptr; + if (raid) { + Mob *memberToDisband = nullptr; - if (!raid->IsGroupLeader(GetName())) + if (!raid->IsGroupLeader(GetName())) { memberToDisband = this; - else + } else { memberToDisband = GetTarget(); + } - if (!memberToDisband) + if (!memberToDisband) { memberToDisband = entity_list.GetMob(gd->name2); + } - if (!memberToDisband) + if (!memberToDisband) { memberToDisband = this; + } - if (!memberToDisband->IsClient()) + if (!memberToDisband->IsOfClientBot()) { return; - + } //we have a raid.. see if we're in a raid group uint32 grp = raid->GetGroup(memberToDisband->GetName()); bool wasGrpLdr = raid->members[raid->GetPlayerIndex(memberToDisband->GetName())].IsGroupLeader; if (grp < 12) { if (wasGrpLdr) { raid->SetGroupLeader(memberToDisband->GetName(), false); - for (int x = 0; x < MAX_RAID_MEMBERS; x++) - { - if (raid->members[x].GroupNumber == grp) - { - if (strlen(raid->members[x].membername) > 0 && strcmp(raid->members[x].membername, memberToDisband->GetName()) != 0) - { + for (int x = 0; x < MAX_RAID_MEMBERS; x++) { + if (raid->members[x].GroupNumber == grp) { + if (strlen(raid->members[x].membername) > 0 && + strcmp(raid->members[x].membername, memberToDisband->GetName()) != 0) { raid->SetGroupLeader(raid->members[x].membername); break; } } } } - raid->MoveMember(memberToDisband->GetName(), 0xFFFFFFFF); - raid->GroupUpdate(grp); //break - //raid->SendRaidGroupRemove(memberToDisband->GetName(), grp); - //raid->SendGroupUpdate(memberToDisband->CastToClient()); - raid->SendGroupDisband(memberToDisband->CastToClient()); + raid->MoveMember(memberToDisband->GetName(), RAID_GROUPLESS); + raid->GroupUpdate(grp); + + if (memberToDisband->IsClient()) { + raid->SendGroupDisband(memberToDisband->CastToClient()); + } } //we're done return; @@ -6787,8 +7054,9 @@ void Client::Handle_OP_GroupDisband(const EQApplicationPacket *app) Group* group = GetGroup(); - if (!group) + if (!group) { return; + } // this block is necessary to allow more control over controlling how bots are zoned or camped. if (RuleB(Bots, Enabled) && Bot::GroupHasBot(group)) { @@ -6798,13 +7066,17 @@ void Client::Handle_OP_GroupDisband(const EQApplicationPacket *app) } else { Mob* tempMember = entity_list.GetMob(gd->name1); //Name1 is the target you are disbanding + if (tempMember && tempMember->IsBot()) { - tempMember->CastToBot()->RemoveBotFromGroup(tempMember->CastToBot(), group); + auto b = tempMember->CastToBot(); + Bot::RemoveBotFromGroup(b, group); + if (LFP) { // If we are looking for players, update to show we are on our own now. UpdateLFP(); } + return; //No need to continue from here we were removing a bot from party } } @@ -7006,7 +7278,15 @@ void Client::Handle_OP_GroupInvite2(const EQApplicationPacket *app) } } else if (Invitee->IsBot()) { - Bot::ProcessBotGroupInvite(this, std::string(Invitee->GetName())); + Client* inviter = entity_list.GetClientByName(gis->inviter_name); + if (inviter && inviter->IsRaidGrouped() && !Invitee->HasRaid()) { + Bot::ProcessRaidInvite(Invitee->CastToBot(), inviter, true); + } + else if (!Invitee->HasRaid()) { + Bot::ProcessBotGroupInvite(this, std::string(Invitee->GetName())); + } else { + MessageString(Chat::LightGray, ALREADY_IN_RAID, Invitee->GetCleanName()); + } } } else @@ -8338,9 +8618,12 @@ void Client::Handle_OP_Illusion(const EQApplicationPacket *app) return; } - if (!GetGM()) - { - database.SetMQDetectionFlag(AccountName(), GetName(), "OP_Illusion sent by non Game Master.", zone->GetShortName()); + if (!GetGM()) { + RecordPlayerEventLog( + PlayerEvent::POSSIBLE_HACK, + PlayerEvent::PossibleHackEvent{.message = "OP_Illusion sent by non Game Master"} + ); + return; } @@ -8497,16 +8780,12 @@ void Client::Handle_OP_ItemLinkClick(const EQApplicationPacket *app) } if (!response.empty()) { - if (!mod_saylink(response, silentsaylink)) { - return; - } - - ChannelMessageReceived(ChatChannel_Say, 0, 100, response.c_str(), nullptr, true); - if (!silentsaylink) { Message(Chat::LightGray, "You say, '%s'", response.c_str()); } + ChannelMessageReceived(ChatChannel_Say, 0, 100, response.c_str(), nullptr, true); + return; } else { @@ -8836,9 +9115,18 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) if (m_inv.SupportsClickCasting(slot_id) || ((item->ItemType == EQ::item::ItemTypePotion || item->PotionBelt) && m_inv.SupportsPotionBeltCasting(slot_id))) // sanity check { - EQ::ItemInstance* p_inst = (EQ::ItemInstance*)inst; + auto* p_inst = (EQ::ItemInstance*) inst; + + if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK)) { + parse->EventItem(EVENT_ITEM_CLICK, this, p_inst, nullptr, "", slot_id); + } + + if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CLIENT)) { + std::vector args; + args.emplace_back(p_inst); + parse->EventPlayer(EVENT_ITEM_CLICK_CLIENT, this, std::to_string(slot_id), 0, &args); + } - parse->EventItem(EVENT_ITEM_CLICK, this, p_inst, nullptr, "", slot_id); inst = m_inv[slot_id]; if (!inst) { @@ -8927,16 +9215,38 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) { if (item->RecastDelay > 0) { - if (!GetPTimers().Expired(&database, (pTimerItemStart + item->RecastType), false)) { - SendItemRecastTimer(item->RecastType); //Problem: When you loot corpse, recast display is not present. This causes it to display again. Could not get to display when sending from looting. - MessageString(Chat::Red, SPELL_RECAST); + if (item->RecastType != RECAST_TYPE_UNLINKED_ITEM && !GetPTimers().Expired(&database, (pTimerItemStart + item->RecastType), false)) { + SetItemCooldown(item->ID, true); + SendSpellBarEnable(item->Click.Effect); + LogSpells("Casting of [{}] canceled: item spell reuse timer not expired", spell_id); + return; + } else if (item->RecastType == RECAST_TYPE_UNLINKED_ITEM && !GetPTimers().Expired(&database, (pTimerNegativeItemReuse * item->ID), false)) { + SetItemCooldown(item->ID, true); SendSpellBarEnable(item->Click.Effect); LogSpells("Casting of [{}] canceled: item spell reuse timer not expired", spell_id); return; } } - int i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, nullptr, "", slot_id); + int i = 0; + + if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) { + i = parse->EventItem( + EVENT_ITEM_CLICK_CAST, + this, + p_inst, + nullptr, + "", + slot_id + ); + } + + if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) { + std::vector args; + args.emplace_back(p_inst); + i = parse->EventPlayer(EVENT_ITEM_CLICK_CAST_CLIENT, this, std::to_string(slot_id), 0, &args); + } + inst = m_inv[slot_id]; if (!inst) { @@ -8952,6 +9262,10 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) else { CastSpell(item->Click.Effect, target_id, CastingSlot::Item, item->CastTime, 0, 0, slot_id); } + } else { + InterruptSpell(item->Click.Effect); + SendSpellBarEnable(item->Click.Effect); + return; } } else @@ -8972,15 +9286,38 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) { if (augitem->RecastDelay > 0) { - if (!GetPTimers().Expired(&database, (pTimerItemStart + augitem->RecastType), false)) { + if (augitem->RecastType != RECAST_TYPE_UNLINKED_ITEM && !GetPTimers().Expired(&database, (pTimerItemStart + augitem->RecastType), false)) { LogSpells("Casting of [{}] canceled: item spell reuse timer from augment not expired", spell_id); MessageString(Chat::Red, SPELL_RECAST); SendSpellBarEnable(augitem->Click.Effect); return; + } else if (augitem->RecastType == RECAST_TYPE_UNLINKED_ITEM && !GetPTimers().Expired(&database, (pTimerNegativeItemReuse * augitem->ID), false)) { + MessageString(Chat::Red, SPELL_RECAST); + SendSpellBarEnable(augitem->Click.Effect); + LogSpells("Casting of [{}] canceled: item spell reuse timer not expired", spell_id); + return; } } - int i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, clickaug, nullptr, "", slot_id); + int i = 0; + + if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) { + i = parse->EventItem( + EVENT_ITEM_CLICK_CAST, + this, + clickaug, + nullptr, + "", + slot_id + ); + } + + if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) { + std::vector args; + args.emplace_back(clickaug); + i = parse->EventPlayer(EVENT_ITEM_CLICK_CAST_CLIENT, this, std::to_string(slot_id), 0, &args); + } + inst = m_inv[slot_id]; if (!inst) { @@ -8997,6 +9334,10 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) else { CastSpell(augitem->Click.Effect, target_id, CastingSlot::Item, augitem->CastTime, 0, 0, slot_id); } + } else { + InterruptSpell(item->Click.Effect); + SendSpellBarEnable(item->Click.Effect); + return; } } else @@ -9122,13 +9463,13 @@ void Client::Handle_OP_LDoNDisarmTraps(const EQApplicationPacket *app) void Client::Handle_OP_LDoNInspect(const EQApplicationPacket *app) { - Mob * target = GetTarget(); - if (target && target->GetClass() == LDON_TREASURE && !target->IsAura()) - { - std::vector args = { target }; - if (parse->EventPlayer(EVENT_INSPECT, this, "", target->GetID(), &args) == 0) - { - Message(Chat::Yellow, "%s", target->GetCleanName()); + auto* t = GetTarget(); + if (t && t->GetClass() == LDON_TREASURE && !t->IsAura()) { + if (parse->PlayerHasQuestSub(EVENT_INSPECT)) { + std::vector args = { t }; + if (parse->EventPlayer(EVENT_INSPECT, this, "", t->GetID(), &args) == 0) { + Message(Chat::Yellow, fmt::format("{}", t->GetCleanName()).c_str()); + } } } } @@ -9653,7 +9994,7 @@ void Client::Handle_OP_Mend(const EQApplicationPacket *app) Message(Chat::Red, "Ability recovery time not yet met."); return; } - p_timers.Start(pTimerMend, MendReuseTime - 1); + p_timers.Start(pTimerMend, (MendReuseTime - GetSkillReuseTime(EQ::skills::SkillMend))); int mendhp = GetMaxHP() / 4; int currenthp = GetHP(); @@ -9665,9 +10006,11 @@ void Client::Handle_OP_Mend(const EQApplicationPacket *app) mendhp *= 2; MessageString(Chat::LightBlue, MEND_CRITICAL); } + else { + MessageString(Chat::LightBlue, MEND_SUCCESS); + } SetHP(GetHP() + mendhp); SendHPUpdate(); - MessageString(Chat::LightBlue, MEND_SUCCESS); } else { /* the purpose of the following is to make the chance to worsen wounds much less common, @@ -10083,13 +10426,13 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app) { const EQ::ItemInstance *itm_from = GetInv().GetItem(mi->from_slot); const EQ::ItemInstance *itm_to = GetInv().GetItem(mi->to_slot); - auto detect = fmt::format("Player issued a move item from {}(item id {}) to {}(item id {}) while casting {}.", + auto message = fmt::format("Player issued a move item from {}(item id {}) to {}(item id {}) while casting {}.", mi->from_slot, itm_from ? itm_from->GetID() : 0, mi->to_slot, itm_to ? itm_to->GetID() : 0, casting_spell_id); - database.SetMQDetectionFlag(AccountName(), GetName(), detect, zone->GetShortName()); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); Kick("Inventory desync"); // Kick client to prevent client and server from getting out-of-sync inventory slots return; } @@ -11072,7 +11415,7 @@ void Client::Handle_OP_PickPocket(const EQApplicationPacket *app) if (!p_timers.Expired(&database, pTimerBeggingPickPocket, false)) { Message(Chat::Red, "Ability recovery time not yet met."); - database.SetMQDetectionFlag(AccountName(), GetName(), "OP_PickPocket was sent again too quickly.", zone->GetShortName()); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "OP_PickPocket was sent again too quickly."}); return; } PickPocket_Struct* pick_in = (PickPocket_Struct*)app->pBuffer; @@ -11094,7 +11437,7 @@ void Client::Handle_OP_PickPocket(const EQApplicationPacket *app) } else if (Distance(GetPosition(), victim->GetPosition()) > 20) { Message(Chat::Red, "Attempt to pickpocket out of range detected."); - database.SetMQDetectionFlag(AccountName(), GetName(), "OP_PickPocket was sent from outside combat range.", zone->GetShortName()); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "OP_PickPocket was sent from outside combat range"}); } else if (victim->IsNPC()) { auto body = victim->GetBodyType(); @@ -11128,8 +11471,8 @@ void Client::Handle_OP_PopupResponse(const EQApplicationPacket *app) std::string response; switch (popup_response->popupid) { case POPUPID_REPLACE_SPELLWINDOW: - DeleteItemInInventory(std::stoi(GetEntityVariable("slot_id")), 1, true); - MemorizeSpellFromItem(std::stoi(GetEntityVariable("spell_id"))); + DeleteItemInInventory(Strings::ToInt(GetEntityVariable("slot_id")), 1, true); + MemorizeSpellFromItem(Strings::ToInt(GetEntityVariable("spell_id"))); return; break; @@ -11169,16 +11512,20 @@ void Client::Handle_OP_PopupResponse(const EQApplicationPacket *app) break; } - const auto export_string = fmt::format("{}", popup_response->popupid); - - parse->EventPlayer(EVENT_POPUP_RESPONSE, this, export_string, 0); + if (parse->PlayerHasQuestSub(EVENT_POPUP_RESPONSE)) { + parse->EventPlayer(EVENT_POPUP_RESPONSE, this, std::to_string(popup_response->popupid), 0); + } auto t = GetTarget(); if (t) { if (t->IsNPC()) { - parse->EventNPC(EVENT_POPUP_RESPONSE, t->CastToNPC(), this, export_string, 0); + if (parse->HasQuestSub(t->GetNPCTypeID(), EVENT_POPUP_RESPONSE)) { + parse->EventNPC(EVENT_POPUP_RESPONSE, t->CastToNPC(), this, std::to_string(popup_response->popupid), 0); + } } else if (t->IsBot()) { - parse->EventBot(EVENT_POPUP_RESPONSE, t->CastToBot(), this, export_string, 0); + if (parse->BotHasQuestSub(EVENT_POPUP_RESPONSE)) { + parse->EventBot(EVENT_POPUP_RESPONSE, t->CastToBot(), this, std::to_string(popup_response->popupid), 0); + } } } } @@ -11430,7 +11777,7 @@ void Client::Handle_OP_QueryUCSServerStatus(const EQApplicationPacket *app) } } -void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app) +void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app) { if (app->size < sizeof(RaidGeneral_Struct)) { LogError("Wrong size: OP_RaidCommand, size=[{}], expected at least [{}]", app->size, sizeof(RaidGeneral_Struct)); @@ -11438,18 +11785,42 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app) return; } - RaidGeneral_Struct *raid_command_packet = (RaidGeneral_Struct*)app->pBuffer; + auto raid_command_packet = (RaidGeneral_Struct*)app->pBuffer; switch (raid_command_packet->action) { - case RaidCommandInviteIntoExisting: - case RaidCommandInvite: { + case RaidCommandInviteIntoExisting: + case RaidCommandInvite: { - Client *player_to_invite = entity_list.GetClientByName(raid_command_packet->player_name); + Bot* player_to_invite = nullptr; - if (!player_to_invite) + if (RuleB(Bots, Enabled) && entity_list.GetBotByBotName(raid_command_packet->player_name)) { + Bot* player_to_invite = entity_list.GetBotByBotName(raid_command_packet->player_name); + Group* player_to_invite_group = player_to_invite->GetGroup(); + + if (!player_to_invite) { break; + } - Group *player_to_invite_group = player_to_invite->GetGroup(); + if (player_to_invite_group && player_to_invite_group->IsGroupMember(this)) { + MessageString(Chat::Red, ALREADY_IN_PARTY); + break; + } + + if (player_to_invite->IsRaidGrouped()) { + MessageString(Chat::White, ALREADY_IN_RAID, player_to_invite->GetCleanName()); //must invite members not in raid... + return; + } + + Bot::ProcessRaidInvite(player_to_invite, this); + break; + + } else { + Client* player_to_invite = entity_list.GetClientByName(raid_command_packet->player_name); + if (!player_to_invite) { + break; + } + + Group* player_to_invite_group = player_to_invite->GetGroup(); if (player_to_invite->HasRaid()) { Message(Chat::Red, "%s is already in a raid.", player_to_invite->GetName()); @@ -11460,7 +11831,7 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app) MessageString(Chat::Red, ALREADY_IN_PARTY); break; } - + // Not allowed: Invite a client that is in a group but not the groupleader if (player_to_invite_group && !player_to_invite_group->IsLeader(player_to_invite)) { Message(Chat::Red, "You can only invite an ungrouped player or group leader to join your raid."); break; @@ -11468,7 +11839,7 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app) /* Send out invite to the client */ auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct)); - RaidGeneral_Struct *raid_command = (RaidGeneral_Struct*)outapp->pBuffer; + RaidGeneral_Struct* raid_command = (RaidGeneral_Struct*)outapp->pBuffer; strn0cpy(raid_command->leader_name, raid_command_packet->leader_name, 64); strn0cpy(raid_command->player_name, raid_command_packet->player_name, 64); @@ -11482,578 +11853,658 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app) break; } - case RaidCommandAcceptInvite: { - Client *player_accepting_invite = entity_list.GetClientByName(raid_command_packet->player_name); - if (player_accepting_invite) { - if (IsRaidGrouped()) { - player_accepting_invite->MessageString(Chat::White, ALREADY_IN_RAID, GetName()); //group failed, must invite members not in raid... - return; + } + + case RaidCommandAcceptInvite: { + Client* player_sending_invite = entity_list.GetClientByName(raid_command_packet->player_name); + + // If the accepting client is in a group with a Bot or the invitor is in a group with a Bot, send the invite to Bot:ProcessRaidInvite + // instead of remaining here. + Bot* b = nullptr; + Client* invitee = entity_list.GetClientByName(raid_command_packet->leader_name); + Client* invitor = entity_list.GetClientByName(raid_command_packet->player_name); + + if (!invitee || !invitor) { + return; + } + + Group* g_invitee = invitee->GetGroup(); + Group* g_invitor = invitor->GetGroup(); + + if (invitee && invitee->IsRaidGrouped()) { + invitor->MessageString(Chat::White, ALREADY_IN_RAID, GetName()); //group failed, must invite members not in raid... + return; + } + + bool invitor_has_bot = false; + bool invitee_has_bot = false; + + if (RuleB(Bots, Enabled)) { + if (g_invitor && g_invitor->IsLeader(invitor)) { + for (const auto& g_invitor_member : g_invitor->members) { + if (g_invitor_member && g_invitor_member->IsBot()) { + invitee_has_bot = true; + } } - Raid *raid = entity_list.GetRaidByClient(player_accepting_invite); - if (raid) { - raid->VerifyRaid(); - Group *group = GetGroup(); - if (group) { - if (group->GroupCount() + raid->RaidCount() > MAX_RAID_MEMBERS) { - player_accepting_invite->Message(Chat::Red, "Invite failed, group invite would create a raid larger than the maximum number of members allowed."); - return; + } + if (g_invitee && g_invitee->IsLeader(invitee)) { + for (const auto& g_invitee_member : g_invitee->members) { + if (g_invitee_member && g_invitee_member->IsBot()) { + invitee_has_bot = true; + break; + } + } + } + if (invitor_has_bot || invitee_has_bot) { + Bot::ProcessRaidInvite(invitee, invitor); //two clients with one or both having groups with bots + break; + } + } + + if (player_sending_invite) { + if (IsRaidGrouped()) { + player_sending_invite->MessageString(Chat::White, ALREADY_IN_RAID, GetName()); //group failed, must invite members not in raid... + return; + } + Raid* raid = entity_list.GetRaidByClient(player_sending_invite); + if (raid) { + raid->VerifyRaid(); + Group* group = GetGroup(); + if (group) { + if (group->GroupCount() + raid->RaidCount() > MAX_RAID_MEMBERS) { + player_sending_invite->Message(Chat::Red, "Invite failed, group invite would create a raid larger than the maximum number of members allowed."); + return; + } + } + else { + if (1 + raid->RaidCount() > MAX_RAID_MEMBERS) { + player_sending_invite->Message(Chat::Red, "Invite failed, member invite would create a raid larger than the maximum number of members allowed."); + return; + } + } + if (group) {//add us all + uint32 free_group_id = raid->GetFreeGroup(); + Client* addClient = nullptr; + for (int x = 0; x < MAX_GROUP_MEMBERS; x++) { + if (group->members[x]) { + Client* c = nullptr; + if (group->members[x]->IsClient()) + c = group->members[x]->CastToClient(); + else + continue; + + if (!addClient) + { + addClient = c; + raid->SetGroupLeader(addClient->GetName()); + } + + raid->SendRaidCreate(c); + if (group->IsLeader(group->members[x])) + raid->AddMember(c, free_group_id, false, true); + else + raid->AddMember(c, free_group_id); + raid->SendBulkRaid(c); + raid->SendMakeLeaderPacketTo(raid->leadername, c); + if (raid->IsLocked()) { + raid->SendRaidLockTo(c); + } } } + group->JoinRaidXTarget(raid); + group->DisbandGroup(true); + raid->GroupUpdate(free_group_id); + } + else { + raid->SendRaidCreate(this); + raid->AddMember(this); + raid->SendBulkRaid(this); + raid->SendMakeLeaderPacketTo(raid->leadername, this); + if (raid->IsLocked()) { + raid->SendRaidLockTo(this); + } + } + } + else + { + auto player_sending_invite_group = player_sending_invite->GetGroup(); + Group* group = GetGroup(); + if (group) //if our target has a group + { + raid = new Raid(player_sending_invite); + entity_list.AddRaid(raid); + raid->SetRaidDetails(); + + uint32 raid_free_group_id = raid->GetFreeGroup(); + + /* If we already have a group then cycle through adding us... */ + if (player_sending_invite_group) { + Client* client_to_be_leader = nullptr; + for (const auto& sending_invite_member : player_sending_invite_group->members) { + if (sending_invite_member) { + if (!client_to_be_leader) { + if (sending_invite_member->IsClient()) { + client_to_be_leader = sending_invite_member->CastToClient(); + raid->SetGroupLeader(client_to_be_leader->GetName()); + } + } + if (player_sending_invite_group->IsLeader(sending_invite_member)) { + Client* c = nullptr; + + if (sending_invite_member->IsClient()) + c = sending_invite_member->CastToClient(); + else + continue; + + raid->SendRaidCreate(c); + raid->AddMember(c, raid_free_group_id, true, true, true); + raid->SendBulkRaid(c); + raid->SendMakeLeaderPacketTo(raid->leadername, c); + if (raid->IsLocked()) { + raid->SendRaidLockTo(c); + } + } + else { + Client* c = nullptr; + + if (sending_invite_member->IsClient()) + c = sending_invite_member->CastToClient(); + else + continue; + + raid->SendRaidCreate(c); + raid->AddMember(c, raid_free_group_id); + raid->SendBulkRaid(c); + raid->SendMakeLeaderPacketTo(raid->leadername, c); + if (raid->IsLocked()) { + raid->SendRaidLockTo(c); + } + } + } + } + player_sending_invite_group->JoinRaidXTarget(raid, true); + player_sending_invite_group->DisbandGroup(true); + raid->GroupUpdate(raid_free_group_id); + raid_free_group_id = raid->GetFreeGroup(); + } else { - if (1 + raid->RaidCount() > MAX_RAID_MEMBERS) { - player_accepting_invite->Message(Chat::Red, "Invite failed, member invite would create a raid larger than the maximum number of members allowed."); - return; - } + raid->SendRaidCreate(player_sending_invite); + raid->AddMember(player_sending_invite, RAID_GROUPLESS, true, false, true); } - if (group) {//add us all - uint32 free_group_id = raid->GetFreeGroup(); - Client *addClient = nullptr; - for (int x = 0; x < 6; x++) { - if (group->members[x]) { - Client *c = nullptr; + + Client* client_to_add = nullptr; + /* Add client to an existing group */ + for (int x = 0; x < MAX_GROUP_MEMBERS; x++) { + if (group->members[x]) { + if (!client_to_add) { + if (group->members[x]->IsClient()) { + client_to_add = group->members[x]->CastToClient(); + raid->SetGroupLeader(client_to_add->GetName()); + } + } + if (group->IsLeader(group->members[x])) { + Client* c = nullptr; + if (group->members[x]->IsClient()) c = group->members[x]->CastToClient(); else continue; - if (!addClient) - { - addClient = c; - raid->SetGroupLeader(addClient->GetName()); + raid->SendRaidCreate(c); + raid->AddMember(c, raid_free_group_id, false, true); + raid->SendBulkRaid(c); + raid->SendMakeLeaderPacketTo(raid->leadername, c); + + if (raid->IsLocked()) { + raid->SendRaidLockTo(c); } + } + else + { + Client* c = nullptr; + + if (group->members[x]->IsClient()) + c = group->members[x]->CastToClient(); + else + continue; raid->SendRaidCreate(c); - raid->SendMakeLeaderPacketTo(raid->leadername, c); - if (group->IsLeader(group->members[x])) - raid->AddMember(c, free_group_id, false, true); - else - raid->AddMember(c, free_group_id); + raid->AddMember(c, raid_free_group_id); raid->SendBulkRaid(c); + raid->SendMakeLeaderPacketTo(raid->leadername, c); if (raid->IsLocked()) { raid->SendRaidLockTo(c); } } } - group->JoinRaidXTarget(raid); - group->DisbandGroup(true); - raid->GroupUpdate(free_group_id); - } - else { - raid->SendRaidCreate(this); - raid->SendMakeLeaderPacketTo(raid->leadername, this); - raid->AddMember(this); - raid->SendBulkRaid(this); - if (raid->IsLocked()) { - raid->SendRaidLockTo(this); - } } + group->JoinRaidXTarget(raid); + group->DisbandGroup(true); + + raid->GroupUpdate(raid_free_group_id); } - else - { - Group *player_invited_group = player_accepting_invite->GetGroup(); - Group *group = GetGroup(); - if (group) //if our target has a group - { - raid = new Raid(player_accepting_invite); + /* Target does not have a group */ + else { + if (player_sending_invite_group) { + + raid = new Raid(player_sending_invite); + entity_list.AddRaid(raid); raid->SetRaidDetails(); - - uint32 raid_free_group_id = raid->GetFreeGroup(); - - /* If we already have a group then cycle through adding us... */ - if (player_invited_group) { - Client *client_to_be_leader = nullptr; - for (int x = 0; x < 6; x++) { - if (player_invited_group->members[x]) { - if (!client_to_be_leader) { - if (player_invited_group->members[x]->IsClient()) { - client_to_be_leader = player_invited_group->members[x]->CastToClient(); - raid->SetGroupLeader(client_to_be_leader->GetName()); - } - } - if (player_invited_group->IsLeader(player_invited_group->members[x])) { - Client *c = nullptr; - - if (player_invited_group->members[x]->IsClient()) - c = player_invited_group->members[x]->CastToClient(); - else - continue; - - raid->SendRaidCreate(c); - raid->SendMakeLeaderPacketTo(raid->leadername, c); - raid->AddMember(c, raid_free_group_id, true, true, true); - raid->SendBulkRaid(c); - - if (raid->IsLocked()) { - raid->SendRaidLockTo(c); - } - } - else { - Client *c = nullptr; - - if (player_invited_group->members[x]->IsClient()) - c = player_invited_group->members[x]->CastToClient(); - else - continue; - - raid->SendRaidCreate(c); - raid->SendMakeLeaderPacketTo(raid->leadername, c); - raid->AddMember(c, raid_free_group_id); - raid->SendBulkRaid(c); - - if (raid->IsLocked()) { - raid->SendRaidLockTo(c); - } + Client* addClientig = nullptr; + for (int x = 0; x < MAX_GROUP_MEMBERS; x++) { + if (player_sending_invite_group->members[x]) { + if (!addClientig) { + if (player_sending_invite_group->members[x]->IsClient()) { + addClientig = player_sending_invite_group->members[x]->CastToClient(); + raid->SetGroupLeader(addClientig->GetName()); } } - } - player_invited_group->JoinRaidXTarget(raid, true); - player_invited_group->DisbandGroup(true); - raid->GroupUpdate(raid_free_group_id); - raid_free_group_id = raid->GetFreeGroup(); - } - else { - raid->SendRaidCreate(player_accepting_invite); - raid->AddMember(player_accepting_invite, 0xFFFFFFFF, true, false, true); - } + if (player_sending_invite_group->IsLeader(player_sending_invite_group->members[x])) { + Client* c = nullptr; - Client *client_to_add = nullptr; - /* Add client to an existing group */ - for (int x = 0; x < 6; x++) { - if (group->members[x]) { - if (!client_to_add) { - if (group->members[x]->IsClient()) { - client_to_add = group->members[x]->CastToClient(); - raid->SetGroupLeader(client_to_add->GetName()); - } - } - if (group->IsLeader(group->members[x])) { - Client *c = nullptr; - - if (group->members[x]->IsClient()) - c = group->members[x]->CastToClient(); + if (player_sending_invite_group->members[x]->IsClient()) + c = player_sending_invite_group->members[x]->CastToClient(); else continue; raid->SendRaidCreate(c); - raid->SendMakeLeaderPacketTo(raid->leadername, c); - raid->AddMember(c, raid_free_group_id, false, true); + raid->AddMember(c, 0, true, true, true); raid->SendBulkRaid(c); - + raid->SendMakeLeaderPacketTo(raid->leadername, c); if (raid->IsLocked()) { raid->SendRaidLockTo(c); } } else { - Client *c = nullptr; - - if (group->members[x]->IsClient()) - c = group->members[x]->CastToClient(); + Client* c = nullptr; + if (player_sending_invite_group->members[x]->IsClient()) + c = player_sending_invite_group->members[x]->CastToClient(); else continue; raid->SendRaidCreate(c); - raid->SendMakeLeaderPacketTo(raid->leadername, c); - raid->AddMember(c, raid_free_group_id); + raid->AddMember(c, 0); raid->SendBulkRaid(c); - + raid->SendMakeLeaderPacketTo(raid->leadername, c); if (raid->IsLocked()) { raid->SendRaidLockTo(c); } } } } - group->JoinRaidXTarget(raid); - group->DisbandGroup(true); - - raid->GroupUpdate(raid_free_group_id); - } - /* Target does not have a group */ - else { - if (player_invited_group) { - - raid = new Raid(player_accepting_invite); - - entity_list.AddRaid(raid); - raid->SetRaidDetails(); - Client *addClientig = nullptr; - for (int x = 0; x < 6; x++) { - if (player_invited_group->members[x]) { - if (!addClientig) { - if (player_invited_group->members[x]->IsClient()) { - addClientig = player_invited_group->members[x]->CastToClient(); - raid->SetGroupLeader(addClientig->GetName()); - } - } - if (player_invited_group->IsLeader(player_invited_group->members[x])) { - Client *c = nullptr; - - if (player_invited_group->members[x]->IsClient()) - c = player_invited_group->members[x]->CastToClient(); - else - continue; - - raid->SendRaidCreate(c); - raid->SendMakeLeaderPacketTo(raid->leadername, c); - raid->AddMember(c, 0, true, true, true); - raid->SendBulkRaid(c); - - if (raid->IsLocked()) { - raid->SendRaidLockTo(c); - } - } - else - { - Client *c = nullptr; - if (player_invited_group->members[x]->IsClient()) - c = player_invited_group->members[x]->CastToClient(); - else - continue; - - raid->SendRaidCreate(c); - raid->SendMakeLeaderPacketTo(raid->leadername, c); - raid->AddMember(c, 0); - raid->SendBulkRaid(c); - if (raid->IsLocked()) { - raid->SendRaidLockTo(c); - } - } - } - } - raid->SendRaidCreate(this); - raid->SendMakeLeaderPacketTo(raid->leadername, this); - raid->SendBulkRaid(this); - player_invited_group->JoinRaidXTarget(raid, true); - raid->AddMember(this); - player_invited_group->DisbandGroup(true); - raid->GroupUpdate(0); - if (raid->IsLocked()) { - raid->SendRaidLockTo(this); - } + raid->SendRaidCreate(this); + raid->SendBulkRaid(this); + player_sending_invite_group->JoinRaidXTarget(raid, true); + raid->AddMember(this); + player_sending_invite_group->DisbandGroup(true); + raid->GroupUpdate(0); + raid->SendMakeLeaderPacketTo(raid->leadername, this); + if (raid->IsLocked()) { + raid->SendRaidLockTo(this); } - else { // neither has a group - raid = new Raid(player_accepting_invite); - entity_list.AddRaid(raid); - raid->SetRaidDetails(); - raid->SendRaidCreate(player_accepting_invite); - raid->SendRaidCreate(this); - raid->SendMakeLeaderPacketTo(raid->leadername, this); - raid->AddMember(player_accepting_invite, 0xFFFFFFFF, true, false, true); - raid->SendBulkRaid(this); - raid->AddMember(this); - if (raid->IsLocked()) { - raid->SendRaidLockTo(this); - } + } + else { // neither has a group + raid = new Raid(player_sending_invite); + entity_list.AddRaid(raid); + raid->SetRaidDetails(); + raid->SendRaidCreate(player_sending_invite); + raid->SendRaidCreate(this); + raid->AddMember(player_sending_invite, RAID_GROUPLESS, true, false, true); + raid->SendBulkRaid(this); + raid->AddMember(this); + raid->SendMakeLeaderPacketTo(raid->leadername, this); + if (raid->IsLocked()) { + raid->SendRaidLockTo(this); } } } } - break; } - case RaidCommandDisband: { - Raid *raid = entity_list.GetRaidByClient(this); - if (raid) { - uint32 group = raid->GetGroup(raid_command_packet->leader_name); + break; + } + case RaidCommandDisband: { + Raid* raid = entity_list.GetRaidByClient(this); + Client* c_to_disband = entity_list.GetClientByName(raid_command_packet->leader_name); + Client* c_doing_disband = entity_list.GetClientByName(raid_command_packet->player_name); - if (group < 12) { - uint32 i = raid->GetPlayerIndex(raid_command_packet->leader_name); - if (raid->members[i].IsGroupLeader) { //assign group leader to someone else - for (int x = 0; x < MAX_RAID_MEMBERS; x++) { - if (strlen(raid->members[x].membername) > 0 && i != x) { - if (raid->members[x].GroupNumber == group) { - raid->SetGroupLeader(raid_command_packet->leader_name, false); - raid->SetGroupLeader(raid->members[x].membername); - raid->UpdateGroupAAs(group); - break; - } - } - } + if (raid) { + raid->VerifyRaid(); + uint32 group = raid->GetGroup(raid_command_packet->leader_name); + if (RuleB(Bots, Enabled)) { + Bot* const b_to_disband = entity_list.GetBotByBotName(raid_command_packet->leader_name); + + //Added to remove all bots if the Bot_Owner is removed from the Raid + //Does not camp the Bots, just removes from the raid + if (c_to_disband) { + raid->HandleBotGroupDisband(c_to_disband->CharacterID()); + raid->RemoveMember(raid_command_packet->leader_name); + if (raid->IsLeader(c_to_disband->GetName())) { + uint32 i = raid->GetPlayerIndex(raid_command_packet->leader_name); + raid->SetNewRaidLeader(i); } - if (raid->members[i].IsRaidLeader) { - for (int x = 0; x < MAX_RAID_MEMBERS; x++) { - if (strlen(raid->members[x].membername) > 0 && strcmp(raid->members[x].membername, raid->members[i].membername) != 0) - { - raid->SetRaidLeader(raid->members[i].membername, raid->members[x].membername); - raid->UpdateRaidAAs(); - raid->SendAllRaidLeadershipAA(); + raid->SendGroupDisband(c_to_disband); + raid->GroupUpdate(group); + if (!raid->RaidCount() || !raid->GetLeader()) { + raid->DisbandRaid(); + } + break; + } else if (b_to_disband) { + uint32 gid = raid->GetGroup(b_to_disband->GetName()); + + if (gid < 12 && (raid->IsGroupLeader(b_to_disband->GetName()) || raid->GroupCount(gid) < 2)) { + uint32 owner_id = b_to_disband->CastToBot()->GetOwner()->CastToClient()->CharacterID(); + raid->HandleBotGroupDisband(owner_id, gid); + + } else if (b_to_disband && raid->IsRaidMember(b_to_disband->GetName())) { + Bot::RemoveBotFromRaid(b_to_disband); + + } else if (gid < 12 && raid->GetGroupLeader(gid) && raid->GetGroupLeader(gid)->IsBot()) { + c_doing_disband->Message( + Chat::Yellow, + fmt::format( + "{} is in a Bot Group. Please disband {} instead to remove the entire Bot group.", + raid_command_packet->leader_name, + raid->GetGroupLeader(gid)->CastToBot()->GetName() + ).c_str() + ); + } + + break; + } + } + if (group < 12) { + uint32 i = raid->GetPlayerIndex(raid_command_packet->leader_name); + if (raid->members[i].IsGroupLeader) { //assign group leader to someone else + for (int x = 0; x < MAX_RAID_MEMBERS; x++) { + if (strlen(raid->members[x].membername) > 0 && i != x) { + if (raid->members[x].GroupNumber == group) { + raid->SetGroupLeader(raid_command_packet->leader_name, false); + raid->SetGroupLeader(raid->members[x].membername); + raid->UpdateGroupAAs(group); break; } } } } - - raid->RemoveMember(raid_command_packet->leader_name); - Client *c = entity_list.GetClientByName(raid_command_packet->leader_name); - if (c) - raid->SendGroupDisband(c); - else { - auto pack = - new ServerPacket(ServerOP_RaidGroupDisband, sizeof(ServerRaidGeneralAction_Struct)); - ServerRaidGeneralAction_Struct* rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; - rga->rid = GetID(); - rga->zoneid = zone->GetZoneID(); - rga->instance_id = zone->GetInstanceID(); - strn0cpy(rga->playername, raid_command_packet->leader_name, 64); - worldserver.SendPacket(pack); - safe_delete(pack); - } - //r->SendRaidGroupRemove(ri->leader_name, grp); - raid->GroupUpdate(group);// break - //} + raid->SetNewRaidLeader(i); } - break; + raid->RemoveMember(raid_command_packet->leader_name); + Client* c = entity_list.GetClientByName(raid_command_packet->leader_name); + if (c) { + + raid->SendGroupDisband(c); + } + else { + auto pack = + new ServerPacket(ServerOP_RaidGroupDisband, sizeof(ServerRaidGeneralAction_Struct)); + ServerRaidGeneralAction_Struct* rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; + rga->rid = GetID(); + rga->zoneid = zone->GetZoneID(); + rga->instance_id = zone->GetInstanceID(); + strn0cpy(rga->playername, raid_command_packet->leader_name, 64); + worldserver.SendPacket(pack); + safe_delete(pack); + } + raid->GroupUpdate(group);// break + if (!raid->RaidCount()) + raid->DisbandRaid(); } - case RaidCommandMoveGroup: - { - Raid *raid = entity_list.GetRaidByClient(this); - if (raid) { - /* Moving to group */ - if (raid_command_packet->parameter < 12) { - uint8 group_count = raid->GroupCount(raid_command_packet->parameter); + break; + } + case RaidCommandMoveGroup: + { + Raid* raid = entity_list.GetRaidByClient(this); + if (raid) { + /* Moving to group */ + if (raid_command_packet->parameter < 12) { + uint8 group_count = raid->GroupCount(raid_command_packet->parameter); - if (group_count < 6) { - Client *c = entity_list.GetClientByName(raid_command_packet->leader_name); - uint32 old_group = raid->GetGroup(raid_command_packet->leader_name); - if (raid_command_packet->parameter == old_group) //don't rejoin grp if we order to join same group. - break; + if (group_count < 6) { + Client* c = entity_list.GetClientByName(raid_command_packet->leader_name); + uint32 old_group = raid->GetGroup(raid_command_packet->leader_name); + if (raid_command_packet->parameter == old_group) //don't rejoin grp if we order to join same group. + break; - if (raid->members[raid->GetPlayerIndex(raid_command_packet->leader_name)].IsGroupLeader) { - raid->SetGroupLeader(raid_command_packet->leader_name, false); - - /* We were the leader of our old group */ - if (old_group < 12) { - /* Assign new group leader if we can */ - for (int x = 0; x < MAX_RAID_MEMBERS; x++) { - if (raid->members[x].GroupNumber == old_group) { - if (strcmp(raid_command_packet->leader_name, raid->members[x].membername) != 0 && strlen(raid_command_packet->leader_name) > 0) { - raid->SetGroupLeader(raid->members[x].membername); - raid->UpdateGroupAAs(old_group); - - Client *client_to_update = entity_list.GetClientByName(raid->members[x].membername); - if (client_to_update) { - raid->SendRaidRemove(raid->members[x].membername, client_to_update); - raid->SendRaidCreate(client_to_update); - raid->SendMakeLeaderPacketTo(raid->leadername, client_to_update); - raid->SendRaidAdd(raid->members[x].membername, client_to_update); - raid->SendBulkRaid(client_to_update); - if (raid->IsLocked()) { - raid->SendRaidLockTo(client_to_update); - } - } - else { - auto pack = new ServerPacket(ServerOP_RaidChangeGroup, sizeof(ServerRaidGeneralAction_Struct)); - ServerRaidGeneralAction_Struct *raid_command_packet = (ServerRaidGeneralAction_Struct*)pack->pBuffer; - - raid_command_packet->rid = raid->GetID(); - raid_command_packet->zoneid = zone->GetZoneID(); - raid_command_packet->instance_id = zone->GetInstanceID(); - strn0cpy(raid_command_packet->playername, raid->members[x].membername, 64); - - worldserver.SendPacket(pack); - - safe_delete(pack); - } - break; - } - } - } - } - } - if (group_count == 0) { - raid->SetGroupLeader(raid_command_packet->leader_name); - raid->UpdateGroupAAs(raid_command_packet->parameter); - } - - raid->MoveMember(raid_command_packet->leader_name, raid_command_packet->parameter); - if (c) { - raid->SendGroupDisband(c); - } - else { - auto pack = new ServerPacket(ServerOP_RaidGroupDisband, sizeof(ServerRaidGeneralAction_Struct)); - ServerRaidGeneralAction_Struct* raid_command = (ServerRaidGeneralAction_Struct*)pack->pBuffer; - raid_command->rid = raid->GetID(); - raid_command->zoneid = zone->GetZoneID(); - raid_command->instance_id = zone->GetInstanceID(); - strn0cpy(raid_command->playername, raid_command_packet->leader_name, 64); - worldserver.SendPacket(pack); - safe_delete(pack); - } - - /* Send group update to our new group */ - raid->GroupUpdate(raid_command_packet->parameter); - - /* If our old was a group send update there too */ - if (old_group < 12) - raid->GroupUpdate(old_group); - - } - } - /* Move player to ungrouped bank */ - else { - Client *c = entity_list.GetClientByName(raid_command_packet->leader_name); - uint32 oldgrp = raid->GetGroup(raid_command_packet->leader_name); if (raid->members[raid->GetPlayerIndex(raid_command_packet->leader_name)].IsGroupLeader) { raid->SetGroupLeader(raid_command_packet->leader_name, false); - for (int x = 0; x < MAX_RAID_MEMBERS; x++) { - if (raid->members[x].GroupNumber == oldgrp && strlen(raid->members[x].membername) > 0 && strcmp(raid->members[x].membername, raid_command_packet->leader_name) != 0){ - raid->SetGroupLeader(raid->members[x].membername); - raid->UpdateGroupAAs(oldgrp); + /* We were the leader of our old group */ + if (old_group < 12) { + /* Assign new group leader if we can */ + for (int x = 0; x < MAX_RAID_MEMBERS; x++) { + if (raid->members[x].GroupNumber == old_group) { + if (strcmp(raid_command_packet->leader_name, raid->members[x].membername) != 0 && strlen(raid_command_packet->leader_name) > 0) { + raid->SetGroupLeader(raid->members[x].membername); + raid->UpdateGroupAAs(old_group); - Client *client_leaving_group = entity_list.GetClientByName(raid->members[x].membername); - if (client_leaving_group) { - raid->SendRaidRemove(raid->members[x].membername, client_leaving_group); - raid->SendRaidCreate(client_leaving_group); - raid->SendMakeLeaderPacketTo(raid->leadername, client_leaving_group); - raid->SendRaidAdd(raid->members[x].membername, client_leaving_group); - raid->SendBulkRaid(client_leaving_group); - if (raid->IsLocked()) { - raid->SendRaidLockTo(client_leaving_group); + Client* client_to_update = entity_list.GetClientByName(raid->members[x].membername); + if (client_to_update) { + raid->SendRaidRemove(raid->members[x].membername, client_to_update); + raid->SendRaidCreate(client_to_update); + raid->SendMakeLeaderPacketTo(raid->leadername, client_to_update); + raid->SendRaidAdd(raid->members[x].membername, client_to_update); + raid->SendBulkRaid(client_to_update); + if (raid->IsLocked()) { + raid->SendRaidLockTo(client_to_update); + } + } + else { + auto pack = new ServerPacket(ServerOP_RaidChangeGroup, sizeof(ServerRaidGeneralAction_Struct)); + ServerRaidGeneralAction_Struct* raid_command_packet = (ServerRaidGeneralAction_Struct*)pack->pBuffer; + + raid_command_packet->rid = raid->GetID(); + raid_command_packet->zoneid = zone->GetZoneID(); + raid_command_packet->instance_id = zone->GetInstanceID(); + strn0cpy(raid_command_packet->playername, raid->members[x].membername, 64); + + worldserver.SendPacket(pack); + + safe_delete(pack); + } + break; } } - else { - auto pack = new ServerPacket( ServerOP_RaidChangeGroup, sizeof(ServerRaidGeneralAction_Struct)); - ServerRaidGeneralAction_Struct *raid_command = (ServerRaidGeneralAction_Struct*)pack->pBuffer; - - raid_command->rid = raid->GetID(); - strn0cpy(raid_command->playername, raid->members[x].membername, 64); - raid_command->zoneid = zone->GetZoneID(); - raid_command->instance_id = zone->GetInstanceID(); - - worldserver.SendPacket(pack); - safe_delete(pack); - } - break; } } } - raid->MoveMember(raid_command_packet->leader_name, 0xFFFFFFFF); + if (group_count == 0) { + raid->SetGroupLeader(raid_command_packet->leader_name); + raid->UpdateGroupAAs(raid_command_packet->parameter); + } + + raid->MoveMember(raid_command_packet->leader_name, raid_command_packet->parameter); if (c) { raid->SendGroupDisband(c); } else { auto pack = new ServerPacket(ServerOP_RaidGroupDisband, sizeof(ServerRaidGeneralAction_Struct)); ServerRaidGeneralAction_Struct* raid_command = (ServerRaidGeneralAction_Struct*)pack->pBuffer; - raid_command->rid = raid->GetID(); raid_command->zoneid = zone->GetZoneID(); raid_command->instance_id = zone->GetInstanceID(); strn0cpy(raid_command->playername, raid_command_packet->leader_name, 64); - worldserver.SendPacket(pack); - safe_delete(pack); } - raid->GroupUpdate(oldgrp); + /* Send group update to our new group */ + raid->GroupUpdate(raid_command_packet->parameter); + + /* If our old was a group send update there too */ + if (old_group < 12) + raid->GroupUpdate(old_group); + } } + /* Move player to ungrouped bank */ + else { + Client* c = entity_list.GetClientByName(raid_command_packet->leader_name); + uint32 oldgrp = raid->GetGroup(raid_command_packet->leader_name); + if (raid->members[raid->GetPlayerIndex(raid_command_packet->leader_name)].IsGroupLeader) { + raid->SetGroupLeader(raid_command_packet->leader_name, false); + for (int x = 0; x < MAX_RAID_MEMBERS; x++) { + if (raid->members[x].GroupNumber == oldgrp && strlen(raid->members[x].membername) > 0 && strcmp(raid->members[x].membername, raid_command_packet->leader_name) != 0) { - Client *client_moved = entity_list.GetClientByName(raid_command_packet->leader_name); + raid->SetGroupLeader(raid->members[x].membername); + raid->UpdateGroupAAs(oldgrp); - if (client_moved && client_moved->GetRaid()) { - client_moved->GetRaid()->SendHPManaEndPacketsTo(client_moved); - client_moved->GetRaid()->SendHPManaEndPacketsFrom(client_moved); + Client* client_leaving_group = entity_list.GetClientByName(raid->members[x].membername); + if (client_leaving_group) { + raid->SendRaidRemove(raid->members[x].membername, client_leaving_group); + raid->SendRaidCreate(client_leaving_group); + raid->SendMakeLeaderPacketTo(raid->leadername, client_leaving_group); + raid->SendRaidAdd(raid->members[x].membername, client_leaving_group); + raid->SendBulkRaid(client_leaving_group); + if (raid->IsLocked()) { + raid->SendRaidLockTo(client_leaving_group); + } + } + else { + auto pack = new ServerPacket(ServerOP_RaidChangeGroup, sizeof(ServerRaidGeneralAction_Struct)); + ServerRaidGeneralAction_Struct* raid_command = (ServerRaidGeneralAction_Struct*)pack->pBuffer; - Log(Logs::General, Logs::HPUpdate, - "Client::Handle_OP_RaidCommand :: %s sending and recieving HP/Mana/End updates", - client_moved->GetCleanName() - ); - } + raid_command->rid = raid->GetID(); + strn0cpy(raid_command->playername, raid->members[x].membername, 64); + raid_command->zoneid = zone->GetZoneID(); + raid_command->instance_id = zone->GetInstanceID(); - break; - } - case RaidCommandRaidLock: - { - Raid *raid = entity_list.GetRaidByClient(this); - if (raid) { - if (!raid->IsLocked()) - raid->LockRaid(true); - else - raid->SendRaidLockTo(this); - } - break; - } - case RaidCommandRaidUnlock: - { - Raid *raid = entity_list.GetRaidByClient(this); - if (raid) - { - if (raid->IsLocked()) - raid->LockRaid(false); - else - raid->SendRaidUnlockTo(this); - } - break; - } - case RaidCommandLootType2: - case RaidCommandLootType: - { - Raid *raid = entity_list.GetRaidByClient(this); - if (raid) { - Message(Chat::Yellow, "Loot type changed to: %d.", raid_command_packet->parameter); - raid->ChangeLootType(raid_command_packet->parameter); - } - break; - } - - case RaidCommandAddLooter2: - case RaidCommandAddLooter: - { - Raid *raid = entity_list.GetRaidByClient(this); - if (raid) { - Message(Chat::Yellow, "Adding %s as a raid looter.", raid_command_packet->leader_name); - raid->AddRaidLooter(raid_command_packet->leader_name); - } - break; - } - - case RaidCommandRemoveLooter2: - case RaidCommandRemoveLooter: - { - Raid *raid = entity_list.GetRaidByClient(this); - if (raid) { - Message(Chat::Yellow, "Removing %s as a raid looter.", raid_command_packet->leader_name); - raid->RemoveRaidLooter(raid_command_packet->leader_name); - } - break; - } - - case RaidCommandMakeLeader: - { - Raid *raid = entity_list.GetRaidByClient(this); - if (raid) { - if (strcmp(raid->leadername, GetName()) == 0) { - raid->SetRaidLeader(GetName(), raid_command_packet->leader_name); - raid->UpdateRaidAAs(); - raid->SendAllRaidLeadershipAA(); + worldserver.SendPacket(pack); + safe_delete(pack); + } + break; + } + } } + raid->MoveMember(raid_command_packet->leader_name, RAID_GROUPLESS); + if (c) { + raid->SendGroupDisband(c); + } + else { + auto pack = new ServerPacket(ServerOP_RaidGroupDisband, sizeof(ServerRaidGeneralAction_Struct)); + ServerRaidGeneralAction_Struct* raid_command = (ServerRaidGeneralAction_Struct*)pack->pBuffer; + + raid_command->rid = raid->GetID(); + raid_command->zoneid = zone->GetZoneID(); + raid_command->instance_id = zone->GetInstanceID(); + strn0cpy(raid_command->playername, raid_command_packet->leader_name, 64); + + worldserver.SendPacket(pack); + + safe_delete(pack); + } + + raid->GroupUpdate(oldgrp); } - break; } - case RaidCommandSetMotd: + Client* client_moved = entity_list.GetClientByName(raid_command_packet->leader_name); + + if (client_moved && client_moved->GetRaid()) { + client_moved->GetRaid()->SendHPManaEndPacketsTo(client_moved); + client_moved->GetRaid()->SendHPManaEndPacketsFrom(client_moved); + + Log(Logs::General, Logs::HPUpdate, + "Client::Handle_OP_RaidCommand :: %s sending and recieving HP/Mana/End updates", + client_moved->GetCleanName() + ); + } + + break; + } + case RaidCommandRaidLock: + { + Raid* raid = entity_list.GetRaidByClient(this); + if (raid) { + if (!raid->IsLocked()) + raid->LockRaid(true); + else + raid->SendRaidLockTo(this); + } + break; + } + case RaidCommandRaidUnlock: + { + Raid* raid = entity_list.GetRaidByClient(this); + if (raid) { - Raid *raid = entity_list.GetRaidByClient(this); - if (!raid) - break; - // we don't use the RaidGeneral here! - RaidMOTD_Struct *motd = (RaidMOTD_Struct *)app->pBuffer; - raid->SetRaidMOTD(std::string(motd->motd)); - raid->SaveRaidMOTD(); - raid->SendRaidMOTDToWorld(); - break; + if (raid->IsLocked()) + raid->LockRaid(false); + else + raid->SendRaidUnlockTo(this); } + break; + } + case RaidCommandLootType2: + case RaidCommandLootType: + { + Raid* raid = entity_list.GetRaidByClient(this); + if (raid) { + Message(Chat::Yellow, "Loot type changed to: %d.", raid_command_packet->parameter); + raid->ChangeLootType(raid_command_packet->parameter); + } + break; + } - default: { - Message(Chat::Red, "Raid command (%d) NYI", raid_command_packet->action); - break; + case RaidCommandAddLooter2: + case RaidCommandAddLooter: + { + Raid* raid = entity_list.GetRaidByClient(this); + if (raid) { + Message(Chat::Yellow, "Adding %s as a raid looter.", raid_command_packet->leader_name); + raid->AddRaidLooter(raid_command_packet->leader_name); } + break; + } + + case RaidCommandRemoveLooter2: + case RaidCommandRemoveLooter: + { + Raid* raid = entity_list.GetRaidByClient(this); + if (raid) { + Message(Chat::Yellow, "Removing %s as a raid looter.", raid_command_packet->leader_name); + raid->RemoveRaidLooter(raid_command_packet->leader_name); + } + break; + } + + case RaidCommandMakeLeader: + { + Raid* raid = entity_list.GetRaidByClient(this); + if (raid) { + if (strcmp(raid->leadername, GetName()) == 0) { + raid->SetRaidLeader(GetName(), raid_command_packet->leader_name); + raid->UpdateRaidAAs(); + raid->SendAllRaidLeadershipAA(); + } + } + break; + } + + case RaidCommandSetMotd: + { + Raid* raid = entity_list.GetRaidByClient(this); + if (!raid) + break; + // we don't use the RaidGeneral here! + RaidMOTD_Struct* motd = (RaidMOTD_Struct*)app->pBuffer; + raid->SetRaidMOTD(std::string(motd->motd)); + raid->SaveRaidMOTD(); + raid->SendRaidMOTDToWorld(); + break; + } + + default: { + Message(Chat::Red, "Raid command (%d) NYI", raid_command_packet->action); + break; + } } } + + void Client::Handle_OP_RandomReq(const EQApplicationPacket *app) { if (app->size != sizeof(RandomReq_Struct)) { @@ -12580,16 +13031,27 @@ void Client::Handle_OP_RezzAnswer(const EQApplicationPacket *app) { VERIFY_PACKET_LENGTH(OP_RezzAnswer, app, Resurrect_Struct); - const Resurrect_Struct* ra = (const Resurrect_Struct*)app->pBuffer; + const auto* r = (const Resurrect_Struct*) app->pBuffer; - LogSpells("[Client::Handle_OP_RezzAnswer] Received OP_RezzAnswer from client. Pendingrezzexp is [{}] action is [{}]", - PendingRezzXP, ra->action ? "ACCEPT" : "DECLINE"); + LogSpells( + "[Client::Handle_OP_RezzAnswer] Received OP_RezzAnswer from client. Pendingrezzexp is [{}] action is [{}]", + PendingRezzXP, + r->action ? "ACCEPT" : "DECLINE" + ); - OPRezzAnswer(ra->action, ra->spellid, ra->zone_id, ra->instance_id, ra->x, ra->y, ra->z); + OPRezzAnswer(r->action, r->spellid, r->zone_id, r->instance_id, r->x, r->y, r->z); + + if (r->action == ResurrectionActions::Accept) { + if (player_event_logs.IsEventEnabled(PlayerEvent::REZ_ACCEPTED)) { + auto e = PlayerEvent::ResurrectAcceptEvent{ + .resurrecter_name = r->rezzer_name, + .spell_name = spells[r->spellid].name, + .spell_id = r->spellid, + }; + RecordPlayerEventLog(PlayerEvent::REZ_ACCEPTED, e); + } - if (ra->action == 1) - { EQApplicationPacket* outapp = app->Copy(); // Send the OP_RezzComplete to the world server. This finds it's way to the zone that // the rezzed corpse is in to mark the corpse as rezzed. @@ -12597,7 +13059,6 @@ void Client::Handle_OP_RezzAnswer(const EQApplicationPacket *app) worldserver.RezzPlayer(outapp, 0, 0, OP_RezzComplete); safe_delete(outapp); } - return; } void Client::Handle_OP_Sacrifice(const EQApplicationPacket *app) @@ -12836,19 +13297,19 @@ void Client::Handle_OP_SetStartCity(const EQApplicationPacket *app) bool valid_city = false; for (auto row = results.begin(); row != results.end(); ++row) { - if (atoi(row[1]) != 0) - zone_id = atoi(row[1]); + if (Strings::ToInt(row[1]) != 0) + zone_id = Strings::ToInt(row[1]); else - zone_id = atoi(row[0]); + zone_id = Strings::ToInt(row[0]); if (zone_id != start_city) continue; valid_city = true; - x = atof(row[2]); - y = atof(row[3]); - z = atof(row[4]); - heading = atof(row[5]); + x = Strings::ToFloat(row[2]); + y = Strings::ToFloat(row[3]); + z = Strings::ToFloat(row[4]); + heading = Strings::ToFloat(row[5]); } if (valid_city) { @@ -12881,10 +13342,10 @@ void Client::Handle_OP_SetStartCity(const EQApplicationPacket *app) Message(Chat::Yellow, "Use \"/setstartcity #\" to choose a home city from the following list:"); for (auto row = results.begin(); row != results.end(); ++row) { - if (atoi(row[1]) != 0) - zone_id = atoi(row[1]); + if (Strings::ToInt(row[1]) != 0) + zone_id = Strings::ToInt(row[1]); else - zone_id = atoi(row[0]); + zone_id = Strings::ToInt(row[0]); std::string zone_long_name = ZoneLongName(zone_id); Message(Chat::Yellow, "%d - %s", zone_id, zone_long_name.c_str()); @@ -13120,10 +13581,19 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) if (!TakeMoneyFromPP(mpo->price)) { - auto hacker_str = fmt::format("Vendor Cheat: attempted to buy {} of {}: {} that cost {} cp but only has {} pp {} gp {} sp {} cp", - mpo->quantity, item->ID, item->Name, - mpo->price, m_pp.platinum, m_pp.gold, m_pp.silver, m_pp.copper); - database.SetMQDetectionFlag(AccountName(), GetName(), Strings::Escape(hacker_str), zone->GetShortName()); + auto message = fmt::format( + "Vendor Cheat attempted to buy qty [{}] of item_id [{}] item_name[{}] that cost [{}] copper but only has platinum [{}] gold [{}] silver [{}] copper [{}]", + mpo->quantity, + item->ID, + item->Name, + mpo->price, + m_pp.platinum, + m_pp.gold, + m_pp.silver, + m_pp.copper + ); + + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); safe_delete(outapp); safe_delete(inst); return; @@ -13188,6 +13658,23 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) safe_delete(inst); safe_delete(outapp); + if (player_event_logs.IsEventEnabled(PlayerEvent::MERCHANT_PURCHASE)) { + auto e = PlayerEvent::MerchantPurchaseEvent{ + .npc_id = tmp->GetNPCTypeID(), + .merchant_name = tmp->GetCleanName(), + .merchant_type = tmp->CastToNPC()->MerchantType, + .item_id = item->ID, + .item_name = item->Name, + .charges = static_cast(mpo->quantity), + .cost = mpo->price, + .alternate_currency_id = 0, + .player_money_balance = GetCarriedMoney(), + .player_currency_balance = 0, + }; + + RecordPlayerEventLog(PlayerEvent::MERCHANT_PURCHASE, e); + } + // start QS code // stacking purchases not supported at this time - entire process will need some work to catch them properly if (RuleB(QueryServ, PlayerLogMerchantTransactions)) { @@ -13243,23 +13730,37 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) } // end QS code - if (RuleB(EventLog, RecordBuyFromMerchant)) - LogMerchant(this, tmp, mpo->quantity, mpo->price, item, true); + if (parse->PlayerHasQuestSub(EVENT_MERCHANT_BUY)) { + const auto& export_string = fmt::format( + "{} {} {} {} {}", + tmp->GetNPCTypeID(), + tmp->CastToNPC()->MerchantType, + item_id, + mpo->quantity, + mpo->price + ); - const auto& export_string = fmt::format( - "{} {} {} {} {}", - tmp->GetNPCTypeID(), - tmp->CastToNPC()->MerchantType, - item_id, - mpo->quantity, - mpo->price - ); - parse->EventPlayer(EVENT_MERCHANT_BUY, this, export_string, 0); + parse->EventPlayer(EVENT_MERCHANT_BUY, this, export_string, 0); + } - if ((RuleB(Character, EnableDiscoveredItems))) - { - if (!GetGM() && !IsDiscovered(item_id)) - DiscoverItem(item_id); + if (player_event_logs.IsEventEnabled(PlayerEvent::MERCHANT_PURCHASE)) { + auto e = PlayerEvent::MerchantPurchaseEvent{ + .npc_id = tmp->GetNPCTypeID(), + .merchant_name = tmp->GetCleanName(), + .merchant_type = tmp->CastToNPC()->MerchantType, + .item_id = item->ID, + .item_name = item->Name, + .charges = static_cast(mpo->quantity), + .cost = mpo->price, + .alternate_currency_id = 0, + .player_money_balance = GetCarriedMoney(), + .player_currency_balance = 0, + }; + RecordPlayerEventLog(PlayerEvent::MERCHANT_PURCHASE, e); + } + + if (RuleB(Character, EnableDiscoveredItems) && !GetGM() && !IsDiscovered(item_id)) { + DiscoverItem(item_id); } t1.stop(); @@ -13344,9 +13845,6 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) else mp->quantity = 1; - if (RuleB(EventLog, RecordSellToMerchant)) - LogMerchant(this, vendor, mp->quantity, price, item, false); - int charges = mp->quantity; if (vendor->GetKeepsSoldItems()) { @@ -13359,7 +13857,7 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) charges, true ) - ) > 0) { + ) > 0) { EQ::ItemInstance *inst2 = inst->Clone(); while (true) { @@ -13431,16 +13929,35 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) } // end QS code - const auto& export_string = fmt::format( - "{} {} {} {} {}", - vendor->GetNPCTypeID(), - vendor->CastToNPC()->MerchantType, - itemid, - mp->quantity, - price - ); - parse->EventPlayer(EVENT_MERCHANT_SELL, this, export_string, 0); + if (parse->PlayerHasQuestSub(EVENT_MERCHANT_SELL)) { + const auto& export_string = fmt::format( + "{} {} {} {} {}", + vendor->GetNPCTypeID(), + vendor->CastToNPC()->MerchantType, + itemid, + mp->quantity, + price + ); + parse->EventPlayer(EVENT_MERCHANT_SELL, this, export_string, 0); + } + + if (player_event_logs.IsEventEnabled(PlayerEvent::MERCHANT_SELL)) { + auto e = PlayerEvent::MerchantSellEvent{ + .npc_id = vendor->GetNPCTypeID(), + .merchant_name = vendor->GetCleanName(), + .merchant_type = vendor->CastToNPC()->MerchantType, + .item_id = item->ID, + .item_name = item->Name, + .charges = static_cast(mp->quantity), + .cost = price, + .alternate_currency_id = 0, + .player_money_balance = GetCarriedMoney(), + .player_currency_balance = 0, + }; + + RecordPlayerEventLog(PlayerEvent::MERCHANT_SELL, e); + } // Now remove the item from the player, this happens regardless of outcome DeleteItemInInventory( @@ -13631,8 +14148,8 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app) { if (ClientVersion() < EQ::versions::ClientVersion::SoF) { - auto hack_str = fmt::format("Player sent OP_SpawnAppearance with AT_Invis: {}", sa->parameter); - database.SetMQDetectionFlag(account_name, name, hack_str, zone->GetShortName()); + auto message = fmt::format("Player sent OP_SpawnAppearance with AT_Invis [{}]", sa->parameter); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); } } return; @@ -13731,8 +14248,8 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app) { if (!HasSkill(EQ::skills::SkillSneak)) { - auto hack_str = fmt::format("Player sent OP_SpawnAppearance with AT_Sneak: {}", sa->parameter); - database.SetMQDetectionFlag(account_name, name, hack_str, zone->GetShortName()); + auto message = fmt::format("Player sent OP_SpawnAppearance with AT_Sneak [{}]", sa->parameter); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); } return; } @@ -13741,8 +14258,8 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app) } else if (sa->type == AT_Size) { - auto hack_str = fmt::format("Player sent OP_SpawnAppearance with AT_Size: {}", sa->parameter); - database.SetMQDetectionFlag(account_name, name, hack_str, zone->GetShortName()); + auto message = fmt::format("Player sent OP_SpawnAppearance with AT_Size [{}]", sa->parameter); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); } else if (sa->type == AT_Light) // client emitting light (lightstone, shiny shield) { @@ -14085,9 +14602,14 @@ void Client::Handle_OP_TargetCommand(const EQApplicationPacket *app) else if (GetTarget()->GetBodyType() == BT_NoTarget2 || GetTarget()->GetBodyType() == BT_Special || GetTarget()->GetBodyType() == BT_NoTarget) { - auto hacker_str = fmt::format("{} attempting to target something untargetable, {} bodytype: {}", - GetName(), GetTarget()->GetName(), (int)GetTarget()->GetBodyType()); - database.SetMQDetectionFlag(AccountName(), GetName(), Strings::Escape(hacker_str), zone->GetShortName()); + auto message = fmt::format( + "[{}] attempting to target something untargetable [{}] bodytype [{}]", + GetName(), + GetTarget()->GetName(), + (int) GetTarget()->GetBodyType() + ); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); + SetTarget((Mob*)nullptr); return; } @@ -14116,15 +14638,16 @@ void Client::Handle_OP_TargetCommand(const EQApplicationPacket *app) { if (DistanceSquared(m_Position, GetTarget()->GetPosition()) > (zone->newzone_data.maxclip*zone->newzone_data.maxclip)) { - auto hacker_str = fmt::format( - "{} attempting to target something beyond the clip plane of {:.2f} " + auto message = fmt::format( + "[{}] attempting to target something beyond the clip plane of {:.2f} " "units, from ({:.2f}, {:.2f}, {:.2f}) to {} ({:.2f}, {:.2f}, " "{:.2f})", GetName(), (zone->newzone_data.maxclip * zone->newzone_data.maxclip), GetX(), GetY(), GetZ(), GetTarget()->GetName(), GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ()); - database.SetMQDetectionFlag(AccountName(), GetName(), Strings::Escape(hacker_str), zone->GetShortName()); + + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); SetTarget(nullptr); return; } @@ -14132,13 +14655,21 @@ void Client::Handle_OP_TargetCommand(const EQApplicationPacket *app) } else if (DistanceSquared(m_Position, GetTarget()->GetPosition()) > (zone->newzone_data.maxclip*zone->newzone_data.maxclip)) { - auto hacker_str = - fmt::format("{} attempting to target something beyond the clip plane of {:.2f} " - "units, from ({:.2f}, {:.2f}, {:.2f}) to {} ({:.2f}, {:.2f}, {:.2f})", - GetName(), (zone->newzone_data.maxclip * zone->newzone_data.maxclip), - GetX(), GetY(), GetZ(), GetTarget()->GetName(), GetTarget()->GetX(), - GetTarget()->GetY(), GetTarget()->GetZ()); - database.SetMQDetectionFlag(AccountName(), GetName(), Strings::Escape(hacker_str), zone->GetShortName()); + auto message = fmt::format( + "{} attempting to target something beyond the clip plane of {:.2f} " + "units, from ({:.2f}, {:.2f}, {:.2f}) to {} ({:.2f}, {:.2f}, {:.2f})", + GetName(), + (zone->newzone_data.maxclip * zone->newzone_data.maxclip), + GetX(), + GetY(), + GetZ(), + GetTarget()->GetName(), + GetTarget()->GetX(), + GetTarget()->GetY(), + GetTarget()->GetZ() + ); + + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); SetTarget(nullptr); return; } @@ -14202,8 +14733,10 @@ void Client::Handle_OP_TestBuff(const EQApplicationPacket *app) if (!RuleB(Character, EnableTestBuff)) { return; } - parse->EventPlayer(EVENT_TEST_BUFF, this, "", 0); - return; + + if (parse->PlayerHasQuestSub(EVENT_TEST_BUFF)) { + parse->EventPlayer(EVENT_TEST_BUFF, this, "", 0); + } } void Client::Handle_OP_TGB(const EQApplicationPacket *app) @@ -14295,16 +14828,14 @@ void Client::Handle_OP_TradeAcceptClick(const EQApplicationPacket *app) // TODO: query (other) as a hacker } else { - // Audit trade to database for both trade streams - other->trade->LogTrade(); - trade->LogTrade(); + other->PlayerTradeEventLog(other->trade, trade); // start QS code if (RuleB(QueryServ, PlayerLogTrades)) { - QSPlayerLogTrade_Struct event_entry; + PlayerLogTrade_Struct event_entry; std::list event_details; - memset(&event_entry, 0, sizeof(QSPlayerLogTrade_Struct)); + memset(&event_entry, 0, sizeof(PlayerLogTrade_Struct)); // Perform actual trade FinishTrade(other, true, &event_entry, &event_details); @@ -14314,18 +14845,18 @@ void Client::Handle_OP_TradeAcceptClick(const EQApplicationPacket *app) auto qs_pack = new ServerPacket( ServerOP_QSPlayerLogTrades, - sizeof(QSPlayerLogTrade_Struct) + - (sizeof(QSTradeItems_Struct) * event_entry._detail_count)); - QSPlayerLogTrade_Struct* qs_buf = (QSPlayerLogTrade_Struct*)qs_pack->pBuffer; + sizeof(PlayerLogTrade_Struct) + + (sizeof(PlayerLogTradeItemsEntry_Struct) * event_entry._detail_count)); + PlayerLogTrade_Struct* qs_buf = (PlayerLogTrade_Struct*)qs_pack->pBuffer; - memcpy(qs_buf, &event_entry, sizeof(QSPlayerLogTrade_Struct)); + memcpy(qs_buf, &event_entry, sizeof(PlayerLogTrade_Struct)); int offset = 0; for (auto iter = event_details.begin(); iter != event_details.end(); ++iter, ++offset) { - QSTradeItems_Struct* detail = reinterpret_cast(*iter); - qs_buf->items[offset] = *detail; + PlayerLogTradeItemsEntry_Struct* detail = reinterpret_cast(*iter); + qs_buf->item_entries[offset] = *detail; safe_delete(detail); } @@ -14857,7 +15388,12 @@ void Client::Handle_OP_Translocate(const EQApplicationPacket *app) zone->GetInstanceID() == PendingTranslocateData.instance_id ); - if (parse->EventSpell(EVENT_SPELL_EFFECT_TRANSLOCATE_COMPLETE, nullptr, this, spell_id, "", 0) == 0) { + int quest_return = 0; + if (parse->SpellHasQuestSub(spell_id, EVENT_SPELL_EFFECT_TRANSLOCATE_COMPLETE)) { + quest_return = parse->EventSpell(EVENT_SPELL_EFFECT_TRANSLOCATE_COMPLETE, nullptr, this, spell_id, "", 0); + } + + if (quest_return == 0) { // If the spell has a translocate to bind effect, AND we are already in the zone the client // is bound in, use the GoToBind method. If we send OP_Translocate in this case, the client moves itself // to the bind coords it has from the PlayerProfile, but with the X and Y reversed. I suspect they are @@ -14865,7 +15401,7 @@ void Client::Handle_OP_Translocate(const EQApplicationPacket *app) if ( IsTranslocateSpell(spell_id) && in_translocate_zone - ) { + ) { PendingTranslocate = false; GoToBind(); return; @@ -15640,3 +16176,43 @@ bool Client::CanTradeFVNoDropItem() return false; } + +void Client::SendMobPositions() +{ + auto p = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); + auto *s = (PlayerPositionUpdateServer_Struct *) p->pBuffer; + for (auto &m: entity_list.GetMobList()) { + m.second->MakeSpawnUpdate(s); + QueuePacket(p, false); + } + safe_delete(p); +} + +struct RecordKillCheck { + PlayerEvent::EventType event; + bool check; +}; + +void Client::RecordKilledNPCEvent(NPC *n) +{ + bool is_named = Strings::Contains(n->GetName(), "#") && !n->IsRaidTarget(); + + std::vector checks = { + RecordKillCheck{.event = PlayerEvent::KILLED_NPC, .check = true}, + RecordKillCheck{.event = PlayerEvent::KILLED_NAMED_NPC, .check = is_named}, + RecordKillCheck{.event = PlayerEvent::KILLED_RAID_NPC, .check = n->IsRaidTarget()}, + }; + + for (auto &c: checks) { + if (c.check && player_event_logs.IsEventEnabled(c.event)) { + auto e = PlayerEvent::KilledNPCEvent{ + .npc_id = n->GetNPCTypeID(), + .npc_name = n->GetCleanName(), + .combat_time_seconds = static_cast(n->GetCombatRecord().TimeInCombat()), + .total_damage_per_second_taken = static_cast(n->GetCombatRecord().GetDamageReceivedPerSecond()), + .total_heal_per_second_taken = static_cast(n->GetCombatRecord().GetHealedReceivedPerSecond()), + }; + RecordPlayerEventLog(c.event, e); + } + } +} diff --git a/zone/client_process.cpp b/zone/client_process.cpp index ef2fe1b9e..01c92f75e 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -55,6 +55,7 @@ #include "zone.h" #include "zonedb.h" #include "../common/zone_store.h" +#include "../common/events/player_event_logs.h" extern QueryServ* QServ; extern Zone* zone; @@ -183,12 +184,19 @@ bool Client::Process() { SetDynamicZoneMemberStatus(DynamicZoneMemberStatus::Offline); - parse->EventPlayer(EVENT_DISCONNECT, this, "", 0); + RecordPlayerEventLog(PlayerEvent::WENT_OFFLINE, PlayerEvent::EmptyEvent{}); + + if (parse->PlayerHasQuestSub(EVENT_DISCONNECT)) { + parse->EventPlayer(EVENT_DISCONNECT, this, "", 0); + } return false; //delete client } if (camp_timer.Check()) { + Raid* raid = entity_list.GetRaidByClient(this); + if (raid) + raid->RemoveMember(this->GetName()); LeaveGroup(); Save(); if (GetMerc()) @@ -542,7 +550,7 @@ bool Client::Process() { if (client_state == DISCONNECTED) { OnDisconnect(true); std::cout << "Client disconnected (cs=d): " << GetName() << std::endl; - database.SetMQDetectionFlag(AccountName(), GetName(), "/MQInstantCamp: Possible instant camp disconnect.", zone->GetShortName()); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "/MQInstantCamp: Possible instant camp disconnect"}); return false; } @@ -692,7 +700,11 @@ void Client::OnDisconnect(bool hard_disconnect) { if (MyRaid) MyRaid->MemberZoned(this); - parse->EventPlayer(EVENT_DISCONNECT, this, "", 0); + RecordPlayerEventLog(PlayerEvent::WENT_OFFLINE, PlayerEvent::EmptyEvent{}); + + if (parse->PlayerHasQuestSub(EVENT_DISCONNECT)) { + parse->EventPlayer(EVENT_DISCONNECT, this, "", 0); + } /* QS: PlayerLogConnectDisconnect */ if (RuleB(QueryServ, PlayerLogConnectDisconnect)){ @@ -872,6 +884,9 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { continue; } + if (!EQ::ValueWithin(Admin(), static_cast(ml.min_status), static_cast(ml.max_status))) { + continue; + } int32 faction_id = npc ? npc->GetPrimaryFaction() : 0; int32 faction_level = ( @@ -1152,12 +1167,8 @@ void Client::OPMemorizeSpell(const EQApplicationPacket* app) if (HasSpellScribed(m->spell_id)) { MemSpell(m->spell_id, m->slot); } else { - database.SetMQDetectionFlag( - AccountName(), - GetName(), - "OP_MemorizeSpell but we don't have this spell scribed...", - zone->GetShortName() - ); + std::string message = fmt::format("OP_MemorizeSpell [{}] but we don't have this spell scribed", m->spell_id); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); } break; } @@ -1296,10 +1307,13 @@ void Client::OPMoveCoin(const EQApplicationPacket* app) NPC *banker = entity_list.GetClosestBanker(this, distance); if(!banker || distance > USE_NPC_RANGE2) { - auto hacked_string = fmt::format("Player tried to make use of a banker(coin move) but " - "{} is non-existant or too far away ({} units).", - banker ? banker->GetName() : "UNKNOWN NPC", distance); - database.SetMQDetectionFlag(AccountName(), GetName(), hacked_string, zone->GetShortName()); + auto message = fmt::format( + "Player tried to make use of a banker (coin move) but " + "banker [{}] is non-existent or too far away [{}] units", + banker ? banker->GetName() : "UNKNOWN NPC", distance + ); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); + return; } @@ -1327,11 +1341,13 @@ void Client::OPMoveCoin(const EQApplicationPacket* app) NPC *banker = entity_list.GetClosestBanker(this, distance); if(!banker || distance > USE_NPC_RANGE2) { - auto hacked_string = - fmt::format("Player tried to make use of a banker(shared coin move) but {} is " - "non-existant or too far away ({} units).", - banker ? banker->GetName() : "UNKNOWN NPC", distance); - database.SetMQDetectionFlag(AccountName(), GetName(), hacked_string, zone->GetShortName()); + auto message = fmt::format( + "Player tried to make use of a banker (shared coin move) but banker [{}] is " + "non-existent or too far away [{}] units", + banker ? banker->GetName() : "UNKNOWN NPC", distance + ); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); + return; } if(mc->cointype1 == COINTYPE_PP) // there's only platinum here @@ -1383,10 +1399,13 @@ void Client::OPMoveCoin(const EQApplicationPacket* app) NPC *banker = entity_list.GetClosestBanker(this, distance); if(!banker || distance > USE_NPC_RANGE2) { - auto hacked_string = fmt::format("Player tried to make use of a banker(coin move) but " - "{} is non-existant or too far away ({} units).", - banker ? banker->GetName() : "UNKNOWN NPC", distance); - database.SetMQDetectionFlag(AccountName(), GetName(), hacked_string, zone->GetShortName()); + auto message = fmt::format( + "Player tried to make use of a banker(coin move) but " + "banker [{}] is non-existent or too far away [{}] units", + banker ? banker->GetName() : "UNKNOWN NPC", distance + ); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); + return; } switch(mc->cointype2) @@ -1426,11 +1445,13 @@ void Client::OPMoveCoin(const EQApplicationPacket* app) NPC *banker = entity_list.GetClosestBanker(this, distance); if(!banker || distance > USE_NPC_RANGE2) { - auto hacked_string = - fmt::format("Player tried to make use of a banker(shared coin move) but {} is " - "non-existant or too far away ({} units).", - banker ? banker->GetName() : "UNKNOWN NPC", distance); - database.SetMQDetectionFlag(AccountName(), GetName(), hacked_string, zone->GetShortName()); + auto message = fmt::format( + "Player tried to make use of a banker (shared coin move) but banker [{}] is " + "non-existent or too far away [{}] units", + banker ? banker->GetName() : "UNKNOWN NPC", distance + ); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); + return; } if(mc->cointype2 == COINTYPE_PP) // there's only platinum here @@ -1899,7 +1920,7 @@ void Client::DoEnduranceUpkeep() { uint32 buffs_i; uint32 buff_count = GetMaxTotalSlots(); for (buffs_i = 0; buffs_i < buff_count; buffs_i++) { - if (buffs[buffs_i].spellid != SPELL_UNKNOWN) { + if (IsValidSpell(buffs[buffs_i].spellid)) { int upkeep = spells[buffs[buffs_i].spellid].endurance_upkeep; if(upkeep > 0) { has_effect = true; @@ -1948,7 +1969,7 @@ void Client::CalcRestState() uint32 buff_count = GetMaxTotalSlots(); for (unsigned int j = 0; j < buff_count; j++) { - if(buffs[j].spellid != SPELL_UNKNOWN) { + if(IsValidSpell(buffs[j].spellid)) { if(IsDetrimentalSpell(buffs[j].spellid) && (buffs[j].ticsremaining > 0)) if(!DetrimentalSpellAllowsRest(buffs[j].spellid)) return; @@ -2144,8 +2165,9 @@ void Client::HandleRespawnFromHover(uint32 Option) } //After they've respawned into the same zone, trigger EVENT_RESPAWN - std::string export_string = fmt::format("{}", Option); - parse->EventPlayer(EVENT_RESPAWN, this, export_string, is_rez ? 1 : 0); + if (parse->PlayerHasQuestSub(EVENT_RESPAWN)) { + parse->EventPlayer(EVENT_RESPAWN, this, std::to_string(Option), is_rez ? 1 : 0); + } //Pop Rez option from the respawn options list; //easiest way to make sure it stays at the end and diff --git a/zone/combat_record.cpp b/zone/combat_record.cpp index 8d746b52d..814c2d256 100644 --- a/zone/combat_record.cpp +++ b/zone/combat_record.cpp @@ -4,50 +4,51 @@ void CombatRecord::Start(std::string in_mob_name) { - start_time = std::time(nullptr); - end_time = 0; - damage_received = 0; - heal_received = 0; - mob_name = in_mob_name; + m_start_time = std::time(nullptr); + m_end_time = 0; + m_damage_received = 0; + m_heal_received = 0; + m_mob_name = in_mob_name; } + void CombatRecord::Stop() { - end_time = std::time(nullptr); + m_end_time = std::time(nullptr); double time_in_combat = TimeInCombat(); LogCombatRecord( "[Summary] Mob [{}] [Received] DPS [{:.0f}] Heal/s [{:.0f}] Duration [{}] ({}s)", - mob_name, - time_in_combat > 0 ? (damage_received / time_in_combat) : damage_received, - time_in_combat > 0 ? (heal_received / time_in_combat) : heal_received, + m_mob_name, + GetDamageReceivedPerSecond(), + GetHealedReceivedPerSecond(), time_in_combat > 0 ? Strings::SecondsToTime(time_in_combat) : "", time_in_combat ); } -bool CombatRecord::InCombat() +bool CombatRecord::InCombat() const { - return start_time > 0; + return m_start_time > 0; } void CombatRecord::ProcessHPEvent(int64 hp, int64 current_hp) { // damage if (hp < current_hp) { - damage_received = damage_received + std::llabs(current_hp - hp); + m_damage_received = m_damage_received + std::llabs(current_hp - hp); } // heal if (hp > current_hp && current_hp > 0) { - heal_received = heal_received + std::llabs(current_hp - hp); + m_heal_received = m_heal_received + std::llabs(current_hp - hp); } LogCombatRecordDetail( "damage_received [{}] heal_received [{}] current_hp [{}] hp [{}] calc [{}]", - damage_received, - heal_received, + m_damage_received, + m_heal_received, current_hp, hp, std::llabs(current_hp - hp) @@ -56,5 +57,27 @@ void CombatRecord::ProcessHPEvent(int64 hp, int64 current_hp) double CombatRecord::TimeInCombat() const { - return difftime(end_time, start_time); + return m_end_time > m_start_time ? difftime(m_end_time, m_start_time) : 0; +} + +float CombatRecord::GetDamageReceivedPerSecond() const +{ + double time_in_combat = TimeInCombat(); + return time_in_combat > 0 ? (m_damage_received / time_in_combat) : m_damage_received; +} + +float CombatRecord::GetHealedReceivedPerSecond() const +{ + double time_in_combat = TimeInCombat(); + return time_in_combat > 0 ? (m_heal_received / time_in_combat) : m_heal_received; +} + +int64 CombatRecord::GetDamageReceived() const +{ + return m_damage_received; +} + +int64 CombatRecord::GetHealReceived() const +{ + return m_heal_received; } diff --git a/zone/combat_record.h b/zone/combat_record.h index 77e67c57f..eff98a42c 100644 --- a/zone/combat_record.h +++ b/zone/combat_record.h @@ -9,15 +9,19 @@ class CombatRecord { public: void Start(std::string in_mob_name); void Stop(); - bool InCombat(); + bool InCombat() const; void ProcessHPEvent(int64 hp, int64 current_hp); double TimeInCombat() const; + int64 GetDamageReceived() const; + int64 GetHealReceived() const; + float GetDamageReceivedPerSecond() const; + float GetHealedReceivedPerSecond() const; private: - std::string mob_name; - time_t start_time = 0; - time_t end_time = 0; - int64 damage_received = 0; - int64 heal_received = 0; + std::string m_mob_name; + time_t m_start_time = 0; + time_t m_end_time = 0; + int64 m_damage_received = 0; + int64 m_heal_received = 0; }; #endif //EQEMU_COMBAT_RECORD_H diff --git a/zone/command.cpp b/zone/command.cpp index 9b61bb427..086558b4b 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -36,6 +36,7 @@ #include "fastmath.h" #include "mob_movement_manager.h" #include "npc_scale_manager.h" +#include "../common/events/player_event_logs.h" extern QueryServ* QServ; extern WorldServer worldserver; @@ -94,7 +95,7 @@ int command_init(void) command_add("aggrozone", "[aggro] - Aggro every mob in the zone with X aggro. Default is 0. Not recommend if you're not invulnerable.", AccountStatus::GMAdmin, command_aggrozone) || command_add("ai", "[factionid/spellslist/con/guard/roambox/stop/start] - Modify AI on NPC target", AccountStatus::GMAdmin, command_ai) || command_add("appearance", "[type] [value] - Send an appearance packet for you or your target", AccountStatus::GMLeadAdmin, command_appearance) || - command_add("appearanceeffects", "[view] [set] [remove] appearance effects.", AccountStatus::GMAdmin, command_appearanceeffects) || + command_add("appearanceeffects", "[Help|Remove|Set|View] - Modify appearance effects on yourself or your target.", AccountStatus::GMAdmin, command_appearanceeffects) || command_add("apply_shared_memory", "[shared_memory_name] - Tells every zone and world to apply a specific shared memory segment by name.", AccountStatus::GMImpossible, command_apply_shared_memory) || command_add("attack", "[Entity Name] - Make your NPC target attack an entity by name", AccountStatus::GMLeadAdmin, command_attack) || command_add("augmentitem", "Force augments an item. Must have the augment item window open.", AccountStatus::GMImpossible, command_augmentitem) || @@ -135,7 +136,6 @@ int command_init(void) command_add("emptyinventory", "Clears your or your target's entire inventory (Equipment, General, Bank, and Shared Bank)", AccountStatus::GMImpossible, command_emptyinventory) || command_add("enablerecipe", "[Recipe ID] - Enables a Recipe", AccountStatus::QuestTroupe, command_enablerecipe) || command_add("endurance", "Restores your or your target's endurance.", AccountStatus::Guide, command_endurance) || - command_add("equipitem", "[slotid(0-21)] - Equip the item on your cursor into the specified slot", AccountStatus::Guide, command_equipitem) || command_add("exptoggle", "[Toggle] - Toggle your or your target's experience gain.", AccountStatus::QuestTroupe, command_exptoggle) || command_add("faction", "[Find (criteria | all ) | Review (criteria | all) | Reset (id)] - Resets Player's Faction", AccountStatus::QuestTroupe, command_faction) || command_add("factionassociation", "[factionid] [amount] - triggers a faction hits via association", AccountStatus::GMLeadAdmin, command_faction_association) || @@ -176,21 +176,18 @@ int command_init(void) command_add("goto", "[playername] or [x y z] [h] - Teleport to the provided coordinates or to your target", AccountStatus::Steward, command_goto) || command_add("grid", "[add/delete] [grid_num] [wandertype] [pausetype] - Create/delete a wandering grid", AccountStatus::GMAreas, command_grid) || command_add("guild", "Guild manipulation commands. Use argument help for more info.", AccountStatus::Steward, command_guild) || - command_add("guildapprove", "[guildapproveid] - Approve a guild with specified ID (guild creator receives the id)", AccountStatus::Player, command_guildapprove) || - command_add("guildcreate", "[guildname] - Creates an approval setup for guild name specified", AccountStatus::Player, command_guildcreate) || - command_add("guildlist", "[guildapproveid] - Lists character names who have approved the guild specified by the approve id", AccountStatus::Player, command_guildlist) || - command_add("haste", "[percentage] - Set your haste percentage", AccountStatus::GMAdmin, command_haste) || + command_add("haste", "[Percentage] - Set your or your target's GM Bonus Haste (100 is 100% more Attack Speed)", AccountStatus::GMAdmin, command_haste) || command_add("hatelist", "Display hate list for NPC.", AccountStatus::QuestTroupe, command_hatelist) || command_add("heal", "Completely heal your target", AccountStatus::Steward, command_heal) || command_add("help", "[Search Criteria] - List available commands and their description, specify partial command as argument to search", AccountStatus::Player, command_help) || command_add("heromodel", "[Hero Model] [Slot] - Set your or your target's appearance to a full set of Hero's Forge Armor, if slot is set, sends exact model just to slot.", AccountStatus::GMMgmt, command_heromodel) || - command_add("hideme", "[on/off] - Hide yourself from spawn lists.", AccountStatus::QuestTroupe, command_hideme) || + command_add("hideme", "[On|Off] or [0|1] - Hide yourself from players below your status level.", AccountStatus::QuestTroupe, command_hideme) || command_add("hotfix", "[hotfix_name] - Reloads shared memory into a hotfix, equiv to load_shared_memory followed by apply_shared_memory", AccountStatus::GMImpossible, command_hotfix) || command_add("hp", "Refresh your HP bar from the server.", AccountStatus::Player, command_hp) || command_add("incstat", "Increases or Decreases a client's stats permanently.", AccountStatus::GMMgmt, command_incstat) || command_add("instance", "Modify Instances", AccountStatus::GMMgmt, command_instance) || command_add("interrogateinv", "use [help] argument for available options", AccountStatus::Player, command_interrogateinv) || - command_add("interrupt", "[message id] [color] - Interrupt your casting. Arguments are optional.", AccountStatus::Guide, command_interrupt) || + command_add("interrupt", "[Message ID] [Color] - Interrupt your casting. Arguments are optional.", AccountStatus::Guide, command_interrupt) || command_add("invsnapshot", "Manipulates inventory snapshots for your current target", AccountStatus::QuestTroupe, command_invsnapshot) || command_add("invul", "[On|Off]] - Turn player target's or your invulnerable flag on or off", AccountStatus::QuestTroupe, command_invul) || command_add("ipban", "[IP] - Ban IP", AccountStatus::GMMgmt, command_ipban) || @@ -200,7 +197,7 @@ int command_init(void) command_add("kill", "Kill your target", AccountStatus::GMAdmin, command_kill) || command_add("killallnpcs", "[npc_name] - Kills all npcs by search name, leave blank for all attackable NPC's", AccountStatus::GMMgmt, command_killallnpcs) || command_add("lastname", "[Last Name] - Set your or your player target's last name (use \"-1\" to remove last name)", AccountStatus::Guide, command_lastname) || - command_add("level", "[Level] - Set your target's level", AccountStatus::Steward, command_level) || + command_add("level", "[Level] - Set your or your target's level", AccountStatus::Steward, command_level) || command_add("list", "[npcs|players|corpses|doors|objects] [search] - Search entities", AccountStatus::ApprenticeGuide, command_list) || command_add("listpetition", "List petitions", AccountStatus::Guide, command_listpetition) || command_add("lootsim", "[npc_type_id] [loottable_id] [iterations] - Runs benchmark simulations using real loot logic to report numbers and data", AccountStatus::GMImpossible, command_lootsim) || @@ -333,7 +330,6 @@ int command_init(void) command_add("trapinfo", "Gets infomation about the traps currently spawned in the zone.", AccountStatus::QuestTroupe, command_trapinfo) || command_add("tune", "Calculate statistical values related to combat.", AccountStatus::GMAdmin, command_tune) || command_add("undye", "Remove dye from all of your or your target's armor slots", AccountStatus::GMAdmin, command_undye) || - command_add("undyeme", "Remove dye from all of your armor slots", AccountStatus::Player, command_undyeme) || command_add("unfreeze", "Unfreeze your target", AccountStatus::QuestTroupe, command_unfreeze) || command_add("unmemspell", "[Spell ID] - Unmemorize a Spell by ID for you or your target", AccountStatus::Guide, command_unmemspell) || command_add("unmemspells", " Unmemorize all spells for you or your target", AccountStatus::Guide, command_unmemspells) || @@ -349,7 +345,7 @@ int command_init(void) command_add("viewpetition", "[petition number] - View a petition", AccountStatus::ApprenticeGuide, command_viewpetition) || command_add("viewrecipe", "[Recipe ID] - Show a recipe's entries", AccountStatus::GMAdmin, command_viewrecipe) || command_add("viewzoneloot", "[item id] - Allows you to search a zone's loot for a specific item ID. (0 shows all loot in the zone)", AccountStatus::QuestTroupe, command_viewzoneloot) || - command_add("wc", "[wear slot] [material] - Sends an OP_WearChange for your target", AccountStatus::GMMgmt, command_wc) || + command_add("wc", "[Slot ID] [Material] [Hero Forge Model] [Elite Material] - Sets the specified slot for you or your target to a material, Hero Forge Model and Elite Material are optional", AccountStatus::GMMgmt, command_wc) || command_add("weather", "[0/1/2/3] (Off/Rain/Snow/Manual) - Change the weather", AccountStatus::QuestTroupe, command_weather) || command_add("who", "[search]", AccountStatus::ApprenticeGuide, command_who) || command_add("worldshutdown", "Shut down world and all zones", AccountStatus::GMMgmt, command_worldshutdown) || @@ -555,8 +551,6 @@ int command_realdispatch(Client *c, std::string message, bool ignore_status) { Seperator sep(message.c_str(), ' ', 10, 100, true); // "three word argument" should be considered 1 arg - command_logcommand(c, message.c_str()); - std::string cstr(sep.arg[0] + 1); if (commandlist.count(cstr) != 1) { @@ -595,7 +589,18 @@ int command_realdispatch(Client *c, std::string message, bool ignore_status) return -1; } - parse->EventPlayer(EVENT_GM_COMMAND, c, message, 0); + if (parse->PlayerHasQuestSub(EVENT_GM_COMMAND)) { + parse->EventPlayer(EVENT_GM_COMMAND, c, message, 0); + } + + if (player_event_logs.IsEventEnabled(PlayerEvent::GM_COMMAND) && message != "#help") { + auto e = PlayerEvent::GMCommandEvent{ + .message = message, + .target = c->GetTarget() ? c->GetTarget()->GetName() : "NONE" + }; + + RecordPlayerEventLogWithClient(c, PlayerEvent::GM_COMMAND, e); + } cur->function(c, &sep); // Dispatch C++ Command @@ -977,7 +982,6 @@ void command_bot(Client *c, const Seperator *sep) #include "gm_commands/emptyinventory.cpp" #include "gm_commands/enablerecipe.cpp" #include "gm_commands/endurance.cpp" -#include "gm_commands/equipitem.cpp" #include "gm_commands/exptoggle.cpp" #include "gm_commands/faction.cpp" #include "gm_commands/feature.cpp" @@ -1015,9 +1019,6 @@ void command_bot(Client *c, const Seperator *sep) #include "gm_commands/goto.cpp" #include "gm_commands/grid.cpp" #include "gm_commands/guild.cpp" -#include "gm_commands/guildapprove.cpp" -#include "gm_commands/guildcreate.cpp" -#include "gm_commands/guildlist.cpp" #include "gm_commands/haste.cpp" #include "gm_commands/hatelist.cpp" #include "gm_commands/heal.cpp" @@ -1042,7 +1043,6 @@ void command_bot(Client *c, const Seperator *sep) #include "gm_commands/listpetition.cpp" #include "gm_commands/lootsim.cpp" #include "gm_commands/loc.cpp" -#include "gm_commands/logcommand.cpp" #include "gm_commands/logs.cpp" #include "gm_commands/makepet.cpp" #include "gm_commands/mana.cpp" @@ -1169,7 +1169,6 @@ void command_bot(Client *c, const Seperator *sep) #include "gm_commands/trapinfo.cpp" #include "gm_commands/tune.cpp" #include "gm_commands/undye.cpp" -#include "gm_commands/undyeme.cpp" #include "gm_commands/unfreeze.cpp" #include "gm_commands/unmemspell.cpp" #include "gm_commands/unmemspells.cpp" diff --git a/zone/command.h b/zone/command.h index c20a4c02c..51ce0572c 100644 --- a/zone/command.h +++ b/zone/command.h @@ -26,7 +26,6 @@ void command_deinit(void); int command_add(std::string command_name, std::string description, uint8 admin, CmdFuncPtr function); int command_notavail(Client *c, std::string message, bool ignore_status); int command_realdispatch(Client *c, std::string message, bool ignore_status); -void command_logcommand(Client *c, std::string message); uint8 GetCommandStatus(Client *c, std::string command_name); void ListModifyNPCStatMap(Client *c); std::map GetModifyNPCStatMap(); @@ -34,6 +33,7 @@ std::string GetModifyNPCStatDescription(std::string stat); void SendNPCEditSubCommands(Client *c); void SendRuleSubCommands(Client *c); void SendGuildSubCommands(Client *c); +void SendPeekInvSubCommands(Client *c); // Commands void command_acceptrules(Client *c, const Seperator *sep); @@ -82,7 +82,6 @@ void command_emoteview(Client *c, const Seperator *sep); void command_emptyinventory(Client *c, const Seperator *sep); void command_enablerecipe(Client *c, const Seperator *sep); void command_endurance(Client *c, const Seperator *sep); -void command_equipitem(Client *c, const Seperator *sep); void command_exptoggle(Client *c, const Seperator *sep); void command_faction(Client *c, const Seperator *sep); void command_faction_association(Client *c, const Seperator *sep); @@ -122,9 +121,6 @@ void command_godmode(Client* c, const Seperator *sep); void command_goto(Client *c, const Seperator *sep); void command_grid(Client *c, const Seperator *sep); void command_guild(Client *c, const Seperator *sep); -void command_guildapprove(Client *c, const Seperator *sep); -void command_guildcreate(Client *c, const Seperator *sep); -void command_guildlist(Client *c, const Seperator *sep); void command_haste(Client *c, const Seperator *sep); void command_hatelist(Client *c, const Seperator *sep); void command_heal(Client *c, const Seperator *sep); @@ -208,7 +204,7 @@ void command_pvp(Client *c, const Seperator *sep); void command_qglobal(Client *c, const Seperator *sep); void command_questerrors(Client *c, const Seperator *sep); void command_race(Client *c, const Seperator *sep); -void command_raidloot(Client *c, const Seperator *sep); +void command_raidloot(Client* c, const Seperator* sep); void command_randomfeatures(Client *c, const Seperator *sep); void command_refreshgroup(Client *c, const Seperator *sep); void command_reload(Client *c, const Seperator *sep); @@ -284,7 +280,6 @@ void command_traindisc(Client *c, const Seperator *sep); void command_trapinfo(Client *c, const Seperator *sep); void command_tune(Client *c, const Seperator *sep); void command_undye(Client *c, const Seperator *sep); -void command_undyeme(Client *c, const Seperator *sep); void command_unfreeze(Client *c, const Seperator *sep); void command_unlock(Client *c, const Seperator *sep); void command_unmemspell(Client *c, const Seperator *sep); diff --git a/zone/common.h b/zone/common.h index 798795130..08c9e078c 100644 --- a/zone/common.h +++ b/zone/common.h @@ -848,11 +848,6 @@ public: // Add item from cursor slot to trade bucket (automatically does bag data too) void AddEntity(uint16 trade_slot_id, uint32 stack_size); - // Audit trade - void LogTrade(); - - void DumpTrade(); - public: // Object state @@ -868,6 +863,8 @@ private: uint32 with_id; Mob* owner; +public: + Mob *GetOwner() const; }; struct ExtraAttackOptions { diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 4e7715dc9..dc026c94d 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -49,6 +49,7 @@ Child of the Mob class. #include "quest_parser_collection.h" #include "string_ids.h" #include "worldserver.h" +#include "../common/events/player_event_logs.h" #include @@ -361,7 +362,6 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( is_corpse_changed = true; rez_experience = in_rezexp; - can_corpse_be_rezzed = true; is_player_corpse = true; is_locked = false; being_looted_by = 0xFFFFFFFF; @@ -394,11 +394,29 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( !RuleB(Character, RespawnFromHover) || client->ClientVersion() < EQ::versions::ClientVersion::SoF ) { - SetCash(pp->copper, pp->silver, pp->gold, pp->platinum); + auto corpse_copper = pp->copper; + auto corpse_silver = pp->silver; + auto corpse_gold = pp->gold; + auto corpse_platinum = pp->platinum; + pp->copper = 0; pp->silver = 0; pp->gold = 0; pp->platinum = 0; + + if (RuleB(Character, LeaveCursorMoneyOnCorpse)) { + corpse_copper += pp->copper_cursor; + corpse_silver += pp->silver_cursor; + corpse_gold += pp->gold_cursor; + corpse_platinum += pp->platinum_cursor; + + pp->copper_cursor = 0; + pp->silver_cursor = 0; + pp->gold_cursor = 0; + pp->platinum_cursor = 0; + } + + SetCash(corpse_copper, corpse_silver, corpse_gold, corpse_platinum); } // get their tints @@ -1209,8 +1227,13 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a auto pkinst = database.CreateItem(pkitem, pkitem->MaxCharges); if (pkinst) { - if (pkitem->RecastDelay) - pkinst->SetRecastTimestamp(timestamps.count(pkitem->RecastType) ? timestamps.at(pkitem->RecastType) : 0); + if (pkitem->RecastDelay) { + if (pkitem->RecastType != RECAST_TYPE_UNLINKED_ITEM) { + pkinst->SetRecastTimestamp(timestamps.count(pkitem->RecastType) ? timestamps.at(pkitem->RecastType) : 0); + } else { + pkinst->SetRecastTimestamp(timestamps.count(pkitem->ID) ? timestamps.at(pkitem->ID) : 0); + } + } LogInventory("MakeLootRequestPackets() Slot [{}], Item [{}]", EQ::invslot::CORPSE_BEGIN, pkitem->Name); @@ -1264,8 +1287,13 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a if (!inst) continue; - if (item->RecastDelay) - inst->SetRecastTimestamp(timestamps.count(item->RecastType) ? timestamps.at(item->RecastType) : 0); + if (item->RecastDelay) { + if (item->RecastType != RECAST_TYPE_UNLINKED_ITEM) { + inst->SetRecastTimestamp(timestamps.count(item->RecastType) ? timestamps.at(item->RecastType) : 0); + } else { + inst->SetRecastTimestamp(timestamps.count(item->ID) ? timestamps.at(item->ID) : 0); + } + } LogInventory("MakeLootRequestPackets() Slot [{}], Item [{}]", loot_slot, item->Name); @@ -1409,28 +1437,53 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app) } } - std::string export_string = fmt::format( - "{} {} {} {}", - inst->GetItem()->ID, - inst->GetCharges(), - EntityList::RemoveNumbers(corpse_name), - GetID() - ); - std::vector args; - args.push_back(inst); - args.push_back(this); - bool prevent_loot = false; + auto prevent_loot = false; + if (RuleB(Zone, UseZoneController)) { auto controller = entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID); - if (controller){ - if (parse->EventNPC(EVENT_LOOT_ZONE, controller, client, export_string, 0, &args) != 0) { - prevent_loot = true; + if (controller) { + if (parse->HasQuestSub(ZONE_CONTROLLER_NPC_ID, EVENT_LOOT_ZONE)) { + const auto& export_string = fmt::format( + "{} {} {} {}", + inst->GetItem()->ID, + inst->GetCharges(), + EntityList::RemoveNumbers(corpse_name), + GetID() + ); + + std::vector args = { inst, this }; + if (parse->EventNPC(EVENT_LOOT_ZONE, controller, client, export_string, 0, &args) != 0) { + prevent_loot = true; + } } } } - if (parse->EventPlayer(EVENT_LOOT, client, export_string, 0, &args) != 0) { - prevent_loot = true; + if (parse->PlayerHasQuestSub(EVENT_LOOT)) { + const auto& export_string = fmt::format( + "{} {} {} {}", + inst->GetItem()->ID, + inst->GetCharges(), + EntityList::RemoveNumbers(corpse_name), + GetID() + ); + + std::vector args = { inst, this }; + if (parse->EventPlayer(EVENT_LOOT, client, export_string, 0, &args) != 0) { + prevent_loot = true; + } + } + + if (player_event_logs.IsEventEnabled(PlayerEvent::LOOT_ITEM) && !IsPlayerCorpse()) { + auto e = PlayerEvent::LootItemEvent{ + .item_id = inst->GetItem()->ID, + .item_name = inst->GetItem()->Name, + .charges = inst->GetCharges(), + .npc_id = GetNPCTypeID(), + .corpse_name = EntityList::RemoveNumbers(corpse_name) + }; + + RecordPlayerEventLogWithClient(client, PlayerEvent::LOOT_ITEM, e); } if (!IsPlayerCorpse()) @@ -1445,9 +1498,19 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app) } } - // do we want this to have a fail option too? Sure? - if (parse->EventItem(EVENT_LOOT, client, inst, this, export_string, 0) != 0) { - prevent_loot = true; + if (parse->ItemHasQuestSub(inst, EVENT_LOOT)) { + const auto& export_string = fmt::format( + "{} {} {} {}", + inst->GetItem()->ID, + inst->GetCharges(), + EntityList::RemoveNumbers(corpse_name), + GetID() + ); + + std::vector args = { inst, this }; + if (parse->EventItem(EVENT_LOOT, client, inst, this, export_string, 0, &args) != 0) { + prevent_loot = true; + } } if (prevent_loot) { @@ -1461,9 +1524,14 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app) // safe to ACK now client->QueuePacket(app); - if (!IsPlayerCorpse() && RuleB(Character, EnableDiscoveredItems)) { - if (client && !client->GetGM() && !client->IsDiscovered(inst->GetItem()->ID)) - client->DiscoverItem(inst->GetItem()->ID); + if ( + !IsPlayerCorpse() && + RuleB(Character, EnableDiscoveredItems) && + client && + !client->GetGM() && + !client->IsDiscovered(inst->GetItem()->ID) + ) { + client->DiscoverItem(inst->GetItem()->ID); } if (zone->adv_data) { @@ -1477,6 +1545,16 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app) // get count for task update before it's mutated by AutoPutLootInInventory int count = inst->IsStackable() ? inst->GetCharges() : 1; + //Set recast on item when looting it! + auto timestamps = database.GetItemRecastTimestamps(client->CharacterID()); + const auto* d = inst->GetItem(); + if (d->RecastDelay) { + if (d->RecastType != RECAST_TYPE_UNLINKED_ITEM) { + inst->SetRecastTimestamp(timestamps.count(d->RecastType) ? timestamps.at(d->RecastType) : 0); + } else { + inst->SetRecastTimestamp(timestamps.count(d->ID) ? timestamps.at(d->ID) : 0); + } + } /* First add it to the looter - this will do the bag contents too */ if (lootitem->auto_loot > 0) { diff --git a/zone/corpse.h b/zone/corpse.h index a5841cec2..ac76f9b85 100644 --- a/zone/corpse.h +++ b/zone/corpse.h @@ -54,8 +54,8 @@ class Corpse : public Mob { virtual bool Death(Mob* killerMob, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill) { return true; } virtual void Damage(Mob* from, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None) { return; } bool Attack(Mob* other, int Hand = EQ::invslot::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = true, - bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) override { - return false; + bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) override { + return false; } virtual bool HasRaid() { return false; } virtual bool HasGroup() { return false; } @@ -172,7 +172,6 @@ private: uint32 being_looted_by; /* Determines what the corpse is being looted by internally for logic */ uint32 rez_experience; /* Amount of experience that the corpse would rez for */ bool rez; - bool can_corpse_be_rezzed; /* Bool declaring whether or not a corpse can be rezzed */ bool become_npc; int allowed_looters[MAX_LOOTERS]; /* People allowed to loot the corpse, character id */ Timer corpse_decay_timer; /* The amount of time in millseconds in which a corpse will take to decay (Depop/Poof) */ diff --git a/zone/data_bucket.cpp b/zone/data_bucket.cpp index 46f204ece..fd05f8795 100644 --- a/zone/data_bucket.cpp +++ b/zone/data_bucket.cpp @@ -23,7 +23,7 @@ void DataBucket::SetData(std::string bucket_key, std::string bucket_value, std:: if (isalpha(expires_time[0]) || isalpha(expires_time[expires_time.length() - 1])) { expires_time_unix = (long long) std::time(nullptr) + Strings::TimeToSeconds(expires_time); } else { - expires_time_unix = (long long) std::time(nullptr) + atoi(expires_time.c_str()); + expires_time_unix = (long long) std::time(nullptr) + Strings::ToInt(expires_time.c_str()); } } @@ -146,7 +146,7 @@ uint64 DataBucket::DoesBucketExist(std::string bucket_key) { if (results.RowCount() != 1) return 0; - return std::stoull(row[0]); + return Strings::ToUnsignedBigInt(row[0]); } /** diff --git a/zone/dialogue_window.cpp b/zone/dialogue_window.cpp index e2cd9e2a1..e5835794e 100644 --- a/zone/dialogue_window.cpp +++ b/zone/dialogue_window.cpp @@ -1,6 +1,7 @@ #include #include "dialogue_window.h" +#include "../common/strings.h" void DialogueWindow::Render(Client *c, std::string markdown) { @@ -74,7 +75,7 @@ void DialogueWindow::Render(Client *c, std::string markdown) bool found_animation = false; if (Strings::IsNumber(animation)) { LogDiaWindDetail("Client [{}] Animation is a number, firing animation [{}]", c->GetCleanName(), animation); - target->DoAnim(std::stoi(animation)); + target->DoAnim(Strings::ToInt(animation)); found_animation = true; } else { @@ -126,7 +127,7 @@ void DialogueWindow::Render(Client *c, std::string markdown) c->GetCleanName(), expire_time ); - window_expire_seconds = std::stoi(expire_time); + window_expire_seconds = Strings::ToInt(expire_time); } } @@ -198,7 +199,7 @@ void DialogueWindow::Render(Client *c, std::string markdown) // set the popup id if (!popupid.empty()) { - popup_id = (Strings::IsNumber(popupid) ? std::atoi(popupid.c_str()) : 0); + popup_id = (Strings::IsNumber(popupid) ? Strings::ToInt(popupid.c_str()) : 0); } } } @@ -230,7 +231,7 @@ void DialogueWindow::Render(Client *c, std::string markdown) Strings::FindReplace(output, fmt::format("secondresponseid:{}", secondresponseid), ""); if (!secondresponseid.empty()) { - negative_id = (Strings::IsNumber(secondresponseid) ? std::atoi(secondresponseid.c_str()) : 0); + negative_id = (Strings::IsNumber(secondresponseid) ? Strings::ToInt(secondresponseid.c_str()) : 0); } } } @@ -409,7 +410,7 @@ void DialogueWindow::Render(Client *c, std::string markdown) // click response // window type response - uint32 window_type = (Strings::IsNumber(wintype) ? std::atoi(wintype.c_str()) : 0); + uint32 window_type = (Strings::IsNumber(wintype) ? Strings::ToInt(wintype.c_str()) : 0); std::string click_response_button = (window_type == 1 ? "Yes" : "OK"); std::string click_response = fmt::format( "Click [{}] to continue...", diff --git a/zone/doors.cpp b/zone/doors.cpp index b977ce066..a21244c0b 100644 --- a/zone/doors.cpp +++ b/zone/doors.cpp @@ -53,6 +53,14 @@ Doors::Doors(const DoorsRepository::Doors &door) : strn0cpy(m_door_name, door.name.c_str(), sizeof(m_door_name)); strn0cpy(m_destination_zone_name, door.dest_zone.c_str(), sizeof(m_destination_zone_name)); + // destination helpers + if (!door.dest_zone.empty() && Strings::ToLower(door.dest_zone) != "none" && !door.dest_zone.empty()) { + m_has_destination_zone = true; + } + if (!door.dest_zone.empty() && !door.zone.empty() && Strings::EqualFold(door.dest_zone, door.zone)) { + m_same_destination_zone = true; + } + m_database_id = door.id; m_door_id = door.doorid; m_incline = door.incline; @@ -121,6 +129,7 @@ Doors::~Doors() bool Doors::Process() { if (m_close_timer.Enabled() && m_close_timer.Check() && IsDoorOpen()) { + LogDoorsDetail("door open and timer triggered door_id [{}] open_type [{}]", GetDoorID(), m_open_type); if (m_open_type == 40 || GetTriggerType() == 1) { auto outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct)); MoveDoor_Struct *md = (MoveDoor_Struct *) outapp->pBuffer; @@ -267,7 +276,7 @@ void Doors::HandleClick(Client *sender, uint8 trigger) // enforce flags before they hit zoning process auto z = GetZone(m_destination_zone_name, 0); - if (z && !z->flag_needed.empty() && Strings::IsNumber(z->flag_needed) && std::stoi(z->flag_needed) == 1) { + if (z && !z->flag_needed.empty() && Strings::IsNumber(z->flag_needed) && Strings::ToInt(z->flag_needed) == 1) { if (sender->Admin() < minStatusToIgnoreZoneFlags && !sender->HasZoneFlag(z->zoneidnumber)) { LogInfo( "Character [{}] does not have the flag to be in this zone [{}]!", @@ -449,7 +458,7 @@ void Doors::HandleClick(Client *sender, uint8 trigger) m_close_timer.Start(); } - if (strncmp(m_destination_zone_name, "NONE", strlen("NONE")) == 0) { + if (!HasDestinationZone()) { SetOpenState(true); } } @@ -496,19 +505,15 @@ void Doors::HandleClick(Client *sender, uint8 trigger) } } - /** - * Teleport door - */ - if (((m_open_type == 57) || (m_open_type == 58)) && - (strncmp(m_destination_zone_name, "NONE", strlen("NONE")) != 0)) { + // teleport door + if (((m_open_type == 57) || (m_open_type == 58)) && HasDestinationZone()) { + bool has_key_required = (required_key_item && ((required_key_item == player_key) || sender->GetGM())); - /** - * If click destination is same zone and doesn't require a key - */ - if ((strncmp(m_destination_zone_name, m_zone_name, strlen(m_zone_name)) == 0) && (!required_key_item)) { + if (IsDestinationZoneSame() && (!required_key_item)) { if (!disable_add_to_key_ring) { sender->KeyRingAdd(player_key); } + sender->MovePC( zone->GetZoneID(), zone->GetInstanceID(), @@ -518,14 +523,7 @@ void Doors::HandleClick(Client *sender, uint8 trigger) m_destination.w ); } - /** - * If requires a key - */ - else if ( - (!IsDoorOpen() || m_open_type == 58) && - (required_key_item && ((required_key_item == player_key) || sender->GetGM())) - ) { - + else if ((!IsDoorOpen() || m_open_type == 58) && has_key_required) { if (!disable_add_to_key_ring) { sender->KeyRingAdd(player_key); } @@ -627,11 +625,13 @@ void Doors::ForceOpen(Mob *sender, bool alt_mode) if (!alt_mode) { // original function if (!m_is_open) { if (!m_disable_timer) { + LogDoorsDetail("door_id [{}] starting timer", md->doorid); m_close_timer.Start(); } m_is_open = true; } else { + LogDoorsDetail("door_id [{}] disable timer", md->doorid); m_close_timer.Disable(); if (!m_disable_timer) { m_is_open = false; @@ -640,6 +640,7 @@ void Doors::ForceOpen(Mob *sender, bool alt_mode) } else { // alternative function if (!m_disable_timer) { + LogDoorsDetail("door_id [{}] alt starting timer", md->doorid); m_close_timer.Start(); } m_is_open = true; @@ -726,7 +727,7 @@ int ZoneDatabase::GetDoorsDBCountPlusOne(std::string zone_short_name, int16 vers return 0; } - return std::stoi(row[0]) + 1; + return Strings::ToInt(row[0]) + 1; } std::vector ZoneDatabase::LoadDoors(const std::string &zone_name, int16 version) @@ -802,20 +803,75 @@ void Doors::CreateDatabaseEntry() return; } - content_db.InsertDoor( - GetDoorDBID(), - GetDoorID(), - GetDoorName(), - m_position, - GetOpenType(), - static_cast(GetGuildID()), - GetLockpick(), - GetKeyItem(), - static_cast(GetDoorParam()), - static_cast(GetInvertState()), - GetIncline(), - GetSize() + const auto& l = DoorsRepository::GetWhere( + content_db, + fmt::format( + "zone = '{}' AND doorid = {}", + zone->GetShortName(), + GetDoorID() + ) ); + if (!l.empty()) { + auto e = l[0]; + + e.name = GetDoorName(); + e.pos_x = GetX(); + e.pos_y = GetY(); + e.pos_z = GetZ(); + e.heading = GetHeading(); + e.opentype = GetOpenType(); + e.guild = static_cast(GetGuildID()); + e.lockpick = GetLockpick(); + e.keyitem = GetKeyItem(); + e.door_param = static_cast(GetDoorParam()); + e.invert_state = static_cast(GetInvertState()); + e.incline = GetIncline(); + e.size = GetSize(); + + auto updated = DoorsRepository::UpdateOne(content_db, e); + if (!updated) { + LogError( + "Failed to update door in Zone [{}] Version [{}] Database ID [{}] ID [{}]", + zone->GetShortName(), + zone->GetInstanceVersion(), + GetDoorDBID(), + GetDoorID() + ); + } + + return; + } + + auto e = DoorsRepository::NewEntity(); + + e.id = GetDoorDBID(); + e.doorid = GetDoorID(); + e.zone = zone->GetShortName(); + e.version = zone->GetInstanceVersion(); + e.name = GetDoorName(); + e.pos_x = GetX(); + e.pos_y = GetY(); + e.pos_z = GetZ(); + e.heading = GetHeading(); + e.opentype = GetOpenType(); + e.guild = static_cast(GetGuildID()); + e.lockpick = GetLockpick(); + e.keyitem = GetKeyItem(); + e.door_param = static_cast(GetDoorParam()); + e.invert_state = static_cast(GetInvertState()); + e.incline = GetIncline(); + e.size = GetSize(); + + const auto& n = DoorsRepository::InsertOne(content_db, e); + if (!n.id) { + LogError( + "Failed to create door in Zone [{}] Version [{}] Database ID [{}] ID [{}]", + zone->GetShortName(), + zone->GetInstanceVersion(), + GetDoorDBID(), + GetDoorID() + ); + } } float Doors::GetX() @@ -832,3 +888,18 @@ float Doors::GetZ() { return m_position.z; } + +float Doors::GetHeading() +{ + return m_position.w; +} + +bool Doors::HasDestinationZone() const +{ + return m_has_destination_zone; +} + +bool Doors::IsDestinationZoneSame() const +{ + return m_same_destination_zone; +} diff --git a/zone/doors.h b/zone/doors.h index 6ee15f46b..0ea60843d 100644 --- a/zone/doors.h +++ b/zone/doors.h @@ -23,7 +23,6 @@ public: bool Process(); bool triggered; char *GetDoorName() { return m_door_name; } - const glm::vec4 GetDestination() const { return m_destination; } const glm::vec4 &GetPosition() const { return m_position; } int GetDzSwitchID() const { return m_dz_switch_id; } int GetIncline() { return m_incline; } @@ -38,7 +37,7 @@ public: uint16 GetSize() { return m_size; } uint32 GetClientVersionMask() { return m_client_version_mask; } uint32 GetDoorDBID() { return m_database_id; } - uint32 GetDoorParam() { return m_door_param; } + int32 GetDoorParam() { return m_door_param; } uint32 GetEntityID() { return m_entity_id; } uint32 GetGuildID() { return m_guild_id; } uint32 GetKeyItem() { return m_key_item_id; } @@ -65,9 +64,15 @@ public: float GetX(); float GetY(); float GetZ(); + float GetHeading(); + + bool HasDestinationZone() const; + bool IsDestinationZoneSame() const; private: + bool m_has_destination_zone = false; + bool m_same_destination_zone = false; uint32 m_database_id; uint8 m_door_id; char m_zone_name[32]; @@ -81,7 +86,7 @@ private: uint8 m_no_key_ring; uint8 m_trigger_door; uint8 m_trigger_type; - uint32 m_door_param; + int32 m_door_param; uint16 m_size; int m_invert_state; uint32 m_entity_id; diff --git a/zone/effects.cpp b/zone/effects.cpp index 86a5c847f..9883b5368 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -42,11 +42,21 @@ float Mob::GetActSpellRange(uint16 spell_id, float range) int64 Mob::GetActSpellDamage(uint16 spell_id, int64 value, Mob* target) { - if (spells[spell_id].target_type == ST_Self) + if (spells[spell_id].target_type == ST_Self) { return value; + } - if (IsNPC()) - value += value*CastToNPC()->GetSpellFocusDMG()/100; + if (IsNPC()) { + value += value * CastToNPC()->GetSpellFocusDMG() / 100; + + if (CastToNPC()->GetSpellScale()) { + value = int64(static_cast(value) * CastToNPC()->GetSpellScale() / 100.0f); + } + } + + if (RuleB(Spells, AllowExtraDmgSkill) && RuleB(Character, ItemExtraSkillDamageCalcAsPercent) && GetSkillDmgAmt(spells[spell_id].skill) > 0) { + value *= std::abs(GetSkillDmgAmt(spells[spell_id].skill) / 100); + } bool Critical = false; int64 base_value = value; @@ -57,20 +67,21 @@ int64 Mob::GetActSpellDamage(uint16 spell_id, int64 value, Mob* target) { value -= (GetLevel() - 40) * 20; //This adds the extra damage from the AA Unholy Touch, 450 per level to the AA Improved Harm TOuch. - if (spell_id == SPELL_IMP_HARM_TOUCH && (IsClient() || IsBot())) //Improved Harm Touch + if (spell_id == SPELL_IMP_HARM_TOUCH && IsOfClientBot()) { //Improved Harm Touch value -= GetAA(aaUnholyTouch) * 450; //Unholy Touch + } - chance = RuleI(Spells, BaseCritChance); //Wizard base critical chance is 2% (Does not scale with level) - chance += itembonuses.CriticalSpellChance + spellbonuses.CriticalSpellChance + aabonuses.CriticalSpellChance; - chance += itembonuses.FrenziedDevastation + spellbonuses.FrenziedDevastation + aabonuses.FrenziedDevastation; + chance = RuleI(Spells, BaseCritChance); //Wizard base critical chance is 2% (Does not scale with level) + chance += itembonuses.CriticalSpellChance + spellbonuses.CriticalSpellChance + aabonuses.CriticalSpellChance; + chance += itembonuses.FrenziedDevastation + spellbonuses.FrenziedDevastation + aabonuses.FrenziedDevastation; //Crtical Hit Calculation pathway - if (chance > 0 || ((IsClient() || IsBot()) && GetClass() == WIZARD && GetLevel() >= RuleI(Spells, WizCritLevel))) { + if (chance > 0 || (IsOfClientBot() && GetClass() == WIZARD && GetLevel() >= RuleI(Spells, WizCritLevel))) { int32 ratio = RuleI(Spells, BaseCritRatio); //Critical modifier is applied from spell effects only. Keep at 100 for live like criticals. //Improved Harm Touch is a guaranteed crit if you have at least one level of SCF. - if (spell_id == SPELL_IMP_HARM_TOUCH && (IsClient() || IsBot()) && (GetAA(aaSpellCastingFury) > 0) && (GetAA(aaUnholyTouch) > 0)) + if (spell_id == SPELL_IMP_HARM_TOUCH && IsOfClientBot() && (GetAA(aaSpellCastingFury) > 0) && (GetAA(aaUnholyTouch) > 0)) chance = 100; if (spells[spell_id].override_crit_chance > 0 && chance > spells[spell_id].override_crit_chance) @@ -82,7 +93,7 @@ int64 Mob::GetActSpellDamage(uint16 spell_id, int64 value, Mob* target) { ratio += itembonuses.SpellCritDmgIncNoStack + spellbonuses.SpellCritDmgIncNoStack + aabonuses.SpellCritDmgIncNoStack; } - else if (((IsClient() || IsBot()) && GetClass() == WIZARD) || (IsMerc() && GetClass() == CASTERDPS)) { + else if ((IsOfClientBot() && GetClass() == WIZARD) || (IsMerc() && GetClass() == CASTERDPS)) { if ((GetLevel() >= RuleI(Spells, WizCritLevel)) && zone->random.Roll(RuleI(Spells, WizCritChance))){ //Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio. (20-70 is parse confirmed) ratio += zone->random.Int(20,70); @@ -90,10 +101,11 @@ int64 Mob::GetActSpellDamage(uint16 spell_id, int64 value, Mob* target) { } } - if ((IsClient() || IsBot()) && GetClass() == WIZARD) + if (IsOfClientBot() && GetClass() == WIZARD) { ratio += RuleI(Spells, WizCritRatio); //Default is zero + } - if (Critical){ + if (Critical) { value = base_value*ratio/100; @@ -114,14 +126,17 @@ int64 Mob::GetActSpellDamage(uint16 spell_id, int64 value, Mob* target) { value -= GetFocusEffect(focusFcDamageAmt2, spell_id); value -= GetFocusEffect(focusFcAmplifyAmt, spell_id); - if (RuleB(Spells, IgnoreSpellDmgLvlRestriction) && !spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg) - value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, base_value)*ratio / 100; + if (RuleB(Spells, AllowExtraDmgSkill) && !RuleB(Character, ItemExtraSkillDamageCalcAsPercent)) { + value -= GetSkillDmgAmt(spells[spell_id].skill) * ratio / 100; + } - else if(!spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5) - value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, base_value)*ratio/100; + if (RuleB(Spells, IgnoreSpellDmgLvlRestriction) && !spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg) { + value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, base_value) * ratio / 100; + } - else if (IsNPC() && CastToNPC()->GetSpellScale()) - value = int64(static_cast(value) * CastToNPC()->GetSpellScale() / 100.0f); + else if (!spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5) { + value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, base_value) * ratio / 100; + } entity_list.FilteredMessageCloseString( this, true, 100, Chat::SpellCrit, FilterSpellCrits, @@ -153,19 +168,20 @@ int64 Mob::GetActSpellDamage(uint16 spell_id, int64 value, Mob* target) { value -= GetFocusEffect(focusFcDamageAmt2, spell_id); value -= GetFocusEffect(focusFcAmplifyAmt, spell_id); + if (RuleB(Spells, AllowExtraDmgSkill) && !RuleB(Character, ItemExtraSkillDamageCalcAsPercent)) { + value -= GetSkillDmgAmt(spells[spell_id].skill); + } + if (RuleB(Spells, IgnoreSpellDmgLvlRestriction) && !spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg) value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, base_value); else if (!spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5) value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, base_value); - if (IsNPC() && CastToNPC()->GetSpellScale()) - value = int64(static_cast(value) * CastToNPC()->GetSpellScale() / 100.0f); - return value; } -int64 Mob::GetActReflectedSpellDamage(int32 spell_id, int64 value, int effectiveness) { +int64 Mob::GetActReflectedSpellDamage(uint16 spell_id, int64 value, int effectiveness) { /* Reflected spells use the spells base damage before any modifiers or formulas applied. That value can then be modifier by the reflect spells 'max' value, defined here as effectiveness @@ -181,10 +197,18 @@ int64 Mob::GetActReflectedSpellDamage(int32 spell_id, int64 value, int effective } } + if (RuleB(Spells, AllowExtraDmgSkill) && RuleB(Character, ItemExtraSkillDamageCalcAsPercent) && GetSkillDmgAmt(spells[spell_id].skill) > 0) { + value *= std::abs(GetSkillDmgAmt(spells[spell_id].skill) / 100); + } + int64 base_spell_dmg = value; value = value * effectiveness / 100; + if (RuleB(Spells, AllowExtraDmgSkill) && !RuleB(Character, ItemExtraSkillDamageCalcAsPercent)) { + value -= GetSkillDmgAmt(spells[spell_id].skill); + } + if (!spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg) { value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, base_spell_dmg); } @@ -199,6 +223,14 @@ int64 Mob::GetActDoTDamage(uint16 spell_id, int64 value, Mob* target, bool from_ if (IsNPC()) { value += value * CastToNPC()->GetSpellFocusDMG() / 100; + + if (CastToNPC()->GetSpellScale()) { + value = int64(static_cast(value) * CastToNPC()->GetSpellScale() / 100.0f); + } + } + + if (RuleB(Spells, AllowExtraDmgSkill) && RuleB(Character, ItemExtraSkillDamageCalcAsPercent) && GetSkillDmgAmt(spells[spell_id].skill) > 0) { + value *= std::abs(GetSkillDmgAmt(spells[spell_id].skill) / 100); } int64 base_value = value; @@ -236,6 +268,10 @@ int64 Mob::GetActDoTDamage(uint16 spell_id, int64 value, Mob* target, bool from_ } } + if (RuleB(Spells, AllowExtraDmgSkill) && !RuleB(Character, ItemExtraSkillDamageCalcAsPercent)) { + extra_dmg += GetSkillDmgAmt(spells[spell_id].skill) * ratio / 100; + } + if (extra_dmg) { int duration = CalcBuffDuration(this, target, spell_id); if (duration > 0) @@ -267,6 +303,10 @@ int64 Mob::GetActDoTDamage(uint16 spell_id, int64 value, Mob* target, bool from_ } } + if (RuleB(Spells, AllowExtraDmgSkill) && !RuleB(Character, ItemExtraSkillDamageCalcAsPercent)) { + extra_dmg += GetSkillDmgAmt(spells[spell_id].skill); + } + if (extra_dmg) { int duration = CalcBuffDuration(this, target, spell_id); if (duration > 0) @@ -276,9 +316,6 @@ int64 Mob::GetActDoTDamage(uint16 spell_id, int64 value, Mob* target, bool from_ value -= extra_dmg; } - if (IsNPC() && CastToNPC()->GetSpellScale()) - value = int64(static_cast(value) * CastToNPC()->GetSpellScale() / 100.0f); - return value; } @@ -327,6 +364,14 @@ int64 Mob::GetActSpellHealing(uint16 spell_id, int64 value, Mob* target, bool fr if (IsNPC()) { value += value * CastToNPC()->GetSpellFocusHeal() / 100; + + if (IsNPC() && CastToNPC()->GetHealScale()) { + value = int(static_cast(value) * CastToNPC()->GetHealScale() / 100.0f); + } + } + + if (RuleB(Spells, AllowExtraDmgSkill) && RuleB(Character, ItemExtraSkillDamageCalcAsPercent) && GetSkillDmgAmt(spells[spell_id].skill) > 0) { + value *= std::abs(GetSkillDmgAmt(spells[spell_id].skill) / 100); } int64 base_value = value; @@ -368,6 +413,10 @@ int64 Mob::GetActSpellHealing(uint16 spell_id, int64 value, Mob* target, bool fr // Instant Heals if (spells[spell_id].buff_duration < 1) { + if (RuleB(Spells, AllowExtraDmgSkill) && !RuleB(Character, ItemExtraSkillDamageCalcAsPercent)) { + value += GetSkillDmgAmt(spells[spell_id].skill); + } + if (target) { value += int64(base_value * target->GetFocusEffect(focusFcHealPctIncoming, spell_id, this)/100); //SPA 393 Add before critical value += int64(base_value * target->GetFocusEffect(focusFcHealPctCritIncoming, spell_id, this)/100); //SPA 395 Add before critical (?) @@ -384,7 +433,7 @@ int64 Mob::GetActSpellHealing(uint16 spell_id, int64 value, Mob* target, bool fr } if (target) { - value += value * target->GetHealRate() / 100; //SPA 120 modifies value after Focus Applied but before critical + value += value * target->GetHealRate() / 100; //SPA 120 modifies value after Focus Applied but before critical } /* @@ -399,10 +448,6 @@ int64 Mob::GetActSpellHealing(uint16 spell_id, int64 value, Mob* target, bool fr value += target->GetFocusEffect(focusFcHealAmtIncoming, spell_id, this); //SPA 394 Add after critical } - if (IsNPC() && CastToNPC()->GetHealScale()) { - value = int(static_cast(value) * CastToNPC()->GetHealScale() / 100.0f); - } - if (critical_modifier > 1) { entity_list.MessageCloseString( this, true, 100, Chat::SpellCrit, @@ -420,6 +465,11 @@ int64 Mob::GetActSpellHealing(uint16 spell_id, int64 value, Mob* target, bool fr else { //Using IgnoreSpellDmgLvlRestriction to also allow healing to scale int64 extra_heal = 0; + + if (RuleB(Spells, AllowExtraDmgSkill) && !RuleB(Character, ItemExtraSkillDamageCalcAsPercent)) { + extra_heal += GetSkillDmgAmt(spells[spell_id].skill); + } + if (RuleB(Spells, HOTsScaleWithHealAmt)) { if (RuleB(Spells, IgnoreSpellDmgLvlRestriction) && !spells[spell_id].no_heal_damage_item_mod && itembonuses.HealAmt) { extra_heal += GetExtraSpellAmt(spell_id, itembonuses.HealAmt, base_value); @@ -437,12 +487,7 @@ int64 Mob::GetActSpellHealing(uint16 spell_id, int64 value, Mob* target, bool fr } } - if (critical_chance && zone->random.Roll(critical_chance)) - value *= critical_modifier; - } - - if (IsNPC() && CastToNPC()->GetHealScale()) { - value = int(static_cast(value) * CastToNPC()->GetHealScale() / 100.0f); + value *= critical_modifier; } return value; @@ -1026,7 +1071,7 @@ void EntityList::AESpell( continue; } - if (spells[spell_id].target_type == ST_AreaClientOnly && !current_mob->IsClient()) { + if (spells[spell_id].target_type == ST_AreaClientOnly && !current_mob->IsOfClientBot()) { continue; } @@ -1039,13 +1084,11 @@ void EntityList::AESpell( * 1 = PC * 2 = NPC */ - if (spells[spell_id].pcnpc_only_flag == 1 && !current_mob->IsClient() && !current_mob->IsMerc() && - !current_mob->IsBot()) { + if (spells[spell_id].pcnpc_only_flag == 1 && !current_mob->IsOfClientBotMerc()) { continue; } - if (spells[spell_id].pcnpc_only_flag == 2 && - (current_mob->IsClient() || current_mob->IsMerc() || current_mob->IsBot())) { + if (spells[spell_id].pcnpc_only_flag == 2 && current_mob->IsOfClientBotMerc()) { continue; } @@ -1186,7 +1229,7 @@ void EntityList::MassGroupBuff( if (current_mob->IsNPC()) { Mob *owner = current_mob->GetOwner(); if (owner) { - if (!owner->IsClient()) { + if (!owner->IsOfClientBot()) { continue; } } diff --git a/zone/embparser.cpp b/zone/embparser.cpp index 3b895a63c..114766c36 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -161,6 +161,8 @@ const char *QuestEventSubroutines[_LargestEventID] = { "EVENT_TASK_BEFORE_UPDATE", "EVENT_AA_BUY", "EVENT_AA_GAIN", + "EVENT_AA_EXP_GAIN", + "EVENT_EXP_GAIN", "EVENT_PAYLOAD", "EVENT_LEVEL_DOWN", "EVENT_GM_COMMAND", @@ -169,6 +171,14 @@ const char *QuestEventSubroutines[_LargestEventID] = { "EVENT_BOT_CREATE", "EVENT_AUGMENT_INSERT_CLIENT", "EVENT_AUGMENT_REMOVE_CLIENT", + "EVENT_EQUIP_ITEM_BOT", + "EVENT_UNEQUIP_ITEM_BOT", + "EVENT_DAMAGE_GIVEN", + "EVENT_DAMAGE_TAKEN", + "EVENT_ITEM_CLICK_CLIENT", + "EVENT_ITEM_CLICK_CAST_CLIENT", + "EVENT_DESTROY_ITEM_CLIENT", + "EVENT_DROP_ITEM_CLIENT", // Add new events before these or Lua crashes "EVENT_SPELL_EFFECT_BOT", "EVENT_SPELL_EFFECT_BUFF_TIC_BOT" @@ -1554,6 +1564,13 @@ void PerlembParser::ExportEventVariables( break; } + case EVENT_TARGET_CHANGE: { + if (extra_pointers && extra_pointers->size() == 1) { + ExportVar(package_name.c_str(), "target", "Mob", std::any_cast(extra_pointers->at(0))); + } + break; + } + case EVENT_WAYPOINT_ARRIVE: case EVENT_WAYPOINT_DEPART: { ExportVar(package_name.c_str(), "wp", data); @@ -1585,6 +1602,7 @@ void PerlembParser::ExportEventVariables( case EVENT_NPC_SLAY: { ExportVar(package_name.c_str(), "killed", mob->GetNPCTypeID()); + ExportVar(package_name.c_str(), "killed_npc", "NPC", mob->CastToNPC()); break; } @@ -1596,6 +1614,9 @@ void PerlembParser::ExportEventVariables( case EVENT_CLICK_DOOR: { ExportVar(package_name.c_str(), "doorid", data); ExportVar(package_name.c_str(), "version", zone->GetInstanceVersion()); + if (extra_pointers && extra_pointers->size() == 1) { + ExportVar(package_name.c_str(), "door", "Doors", std::any_cast(extra_pointers->at(0))); + } break; } @@ -1604,8 +1625,17 @@ void PerlembParser::ExportEventVariables( Seperator sep(data); ExportVar(package_name.c_str(), "looted_id", sep.arg[0]); ExportVar(package_name.c_str(), "looted_charges", sep.arg[1]); - ExportVar(package_name.c_str(), "corpse", sep.arg[2]); + ExportVar(package_name.c_str(), "corpse_name", sep.arg[2]); ExportVar(package_name.c_str(), "corpse_id", sep.arg[3]); + + if (extra_pointers && extra_pointers->size() >= 1) { + ExportVar(package_name.c_str(), "item", "QuestItem", std::any_cast(extra_pointers->at(0))); + } + + if (extra_pointers && extra_pointers->size() == 2) { + ExportVar(package_name.c_str(), "corpse", "Corpse", std::any_cast(extra_pointers->at(1))); + } + break; } @@ -1661,6 +1691,9 @@ void PerlembParser::ExportEventVariables( case EVENT_PLAYER_PICKUP: { ExportVar(package_name.c_str(), "picked_up_id", data); ExportVar(package_name.c_str(), "picked_up_entity_id", extradata); + if (extra_pointers && extra_pointers->size() == 1) { + ExportVar(package_name.c_str(), "item", "QuestItem", std::any_cast(extra_pointers->at(0))); + } break; } @@ -1709,6 +1742,21 @@ void PerlembParser::ExportEventVariables( break; } + case EVENT_ITEM_CLICK_CAST_CLIENT: + case EVENT_ITEM_CLICK_CLIENT: { + ExportVar(package_name.c_str(), "slot_id", data); + if (extra_pointers && extra_pointers->size() == 1) { + auto* item = std::any_cast(extra_pointers->at(0)); + if (item) { + ExportVar(package_name.c_str(), "item_id", item->GetID()); + ExportVar(package_name.c_str(), "item_name", item->GetItem()->Name); + ExportVar(package_name.c_str(), "spell_id", item->GetItem()->Click.Effect); + ExportVar(package_name.c_str(), "item", "QuestItem", item); + } + } + break; + } + case EVENT_GROUP_CHANGE: { if (mob && mob->IsClient()) { ExportVar(package_name.c_str(), "grouped", mob->IsGrouped()); @@ -1719,10 +1767,10 @@ void PerlembParser::ExportEventVariables( case EVENT_HATE_LIST: { ExportVar(package_name.c_str(), "hate_state", data); + ExportVar(package_name.c_str(), "hate_entity", "Mob", mob); break; } - case EVENT_SPELL_EFFECT_BUFF_TIC_BOT: case EVENT_SPELL_EFFECT_BUFF_TIC_CLIENT: case EVENT_SPELL_EFFECT_BUFF_TIC_NPC: @@ -1749,22 +1797,34 @@ void PerlembParser::ExportEventVariables( case EVENT_FORAGE_SUCCESS: { ExportVar(package_name.c_str(), "foraged_item", extradata); + if (extra_pointers && extra_pointers->size() == 1) { + ExportVar(package_name.c_str(), "item", "QuestItem", std::any_cast(extra_pointers->at(0))); + } break; } case EVENT_FISH_SUCCESS: { ExportVar(package_name.c_str(), "fished_item", extradata); + if (extra_pointers && extra_pointers->size() == 1) { + ExportVar(package_name.c_str(), "item", "QuestItem", std::any_cast(extra_pointers->at(0))); + } break; } case EVENT_CLICK_OBJECT: { ExportVar(package_name.c_str(), "objectid", data); ExportVar(package_name.c_str(), "clicker_id", extradata); + if (extra_pointers && extra_pointers->size() == 1) { + ExportVar(package_name.c_str(), "object", "Object", std::any_cast(extra_pointers->at(0))); + } break; } case EVENT_DISCOVER_ITEM: { ExportVar(package_name.c_str(), "itemid", extradata); + if (extra_pointers && extra_pointers->size() == 1) { + ExportVar(package_name.c_str(), "item", "QuestItem", std::any_cast(extra_pointers->at(0))); + } break; } @@ -1826,10 +1886,24 @@ void PerlembParser::ExportEventVariables( break; } + case EVENT_DROP_ITEM_CLIENT: { + if (extra_pointers && extra_pointers->size() == 1) { + EQ::ItemInstance* item_instance = std::any_cast(extra_pointers->at(0)); + ExportVar(package_name.c_str(), "quantity", item_instance->IsStackable() ? item_instance->GetCharges() : 1); + ExportVar(package_name.c_str(), "item_name", item_instance->GetItem()->Name); + ExportVar(package_name.c_str(), "item_id", item_instance->GetItem()->ID); + ExportVar(package_name.c_str(), "spell_id", item_instance->GetItem()->Click.Effect); + ExportVar(package_name.c_str(), "slot_id", extradata); + ExportVar(package_name.c_str(), "item", "QuestItem", item_instance); + } + break; + } + case EVENT_SPAWN_ZONE: { ExportVar(package_name.c_str(), "spawned_entity_id", mob->GetID()); ExportVar(package_name.c_str(), "spawned_bot_id", mob->IsBot() ? mob->CastToBot()->GetBotID() : 0); ExportVar(package_name.c_str(), "spawned_npc_id", mob->IsNPC() ? mob->GetNPCTypeID() : 0); + ExportVar(package_name.c_str(), "spawned", "Mob", mob); break; } @@ -1878,17 +1952,23 @@ void PerlembParser::ExportEventVariables( } case EVENT_CONSIDER: { - ExportVar(package_name.c_str(), "entity_id", std::stoi(data)); + ExportVar(package_name.c_str(), "entity_id", Strings::ToInt(data)); + if (extra_pointers && extra_pointers->size() == 1) { + ExportVar(package_name.c_str(), "target", "Mob", std::any_cast(extra_pointers->at(0))); + } break; } case EVENT_CONSIDER_CORPSE: { - ExportVar(package_name.c_str(), "corpse_entity_id", std::stoi(data)); + ExportVar(package_name.c_str(), "corpse_entity_id", Strings::ToInt(data)); + if (extra_pointers && extra_pointers->size() == 1) { + ExportVar(package_name.c_str(), "corpse", "Corpse", std::any_cast(extra_pointers->at(0))); + } break; } case EVENT_COMBINE: { - ExportVar(package_name.c_str(), "container_slot", std::stoi(data)); + ExportVar(package_name.c_str(), "container_slot", Strings::ToInt(data)); break; } @@ -1898,19 +1978,58 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "item_id", extradata); ExportVar(package_name.c_str(), "item_quantity", sep.arg[0]); ExportVar(package_name.c_str(), "slot_id", sep.arg[1]); + if (extra_pointers && extra_pointers->size() == 1) { + ExportVar(package_name.c_str(), "item", "QuestItem", std::any_cast(extra_pointers->at(0))); + } + break; + } + + case EVENT_EQUIP_ITEM_BOT: + case EVENT_UNEQUIP_ITEM_BOT: { + Seperator sep(data); + ExportVar(package_name.c_str(), "item_id", extradata); + ExportVar(package_name.c_str(), "item_quantity", sep.arg[0]); + ExportVar(package_name.c_str(), "slot_id", sep.arg[1]); + if (extra_pointers && extra_pointers->size() == 1) { + ExportVar(package_name.c_str(), "item", "QuestItem", std::any_cast(extra_pointers->at(0))); + } + break; + } + + case EVENT_AUGMENT_INSERT_CLIENT: { + Seperator sep(data); + ExportVar(package_name.c_str(), "item_id", sep.arg[0]); + ExportVar(package_name.c_str(), "item_slot", sep.arg[1]); + ExportVar(package_name.c_str(), "augment_id", sep.arg[2]); + ExportVar(package_name.c_str(), "augment_slot", sep.arg[3]); + + if (extra_pointers && extra_pointers->size() >= 1) { + ExportVar(package_name.c_str(), "item", "QuestItem", std::any_cast(extra_pointers->at(0))); + } + + if (extra_pointers && extra_pointers->size() >= 2) { + ExportVar(package_name.c_str(), "augment", "QuestItem", std::any_cast(extra_pointers->at(1))); + } + break; } - case EVENT_AUGMENT_INSERT_CLIENT: case EVENT_AUGMENT_REMOVE_CLIENT: { Seperator sep(data); ExportVar(package_name.c_str(), "item_id", sep.arg[0]); ExportVar(package_name.c_str(), "item_slot", sep.arg[1]); ExportVar(package_name.c_str(), "augment_id", sep.arg[2]); ExportVar(package_name.c_str(), "augment_slot", sep.arg[3]); - if (sep.argnum >= 4) { - ExportVar(package_name.c_str(), "destroyed", sep.arg[4]); + ExportVar(package_name.c_str(), "destroyed", sep.arg[4]); + + if (extra_pointers && extra_pointers->size() >= 1) { + ExportVar(package_name.c_str(), "item", "QuestItem", std::any_cast(extra_pointers->at(0))); } + + if (extra_pointers && extra_pointers->size() >= 3) { + ExportVar(package_name.c_str(), "augment", "QuestItem", std::any_cast(extra_pointers->at(2))); + } + break; } @@ -1967,8 +2086,21 @@ void PerlembParser::ExportEventVariables( break; } + case EVENT_AA_EXP_GAIN: { + ExportVar(package_name.c_str(), "aa_exp_gained", data); + break; + } + + case EVENT_EXP_GAIN: { + ExportVar(package_name.c_str(), "exp_gained", data); + break; + } + case EVENT_INSPECT: { ExportVar(package_name.c_str(), "target_id", extradata); + if (extra_pointers && extra_pointers->size() == 1) { + ExportVar(package_name.c_str(), "target", "Mob", std::any_cast(extra_pointers->at(0))); + } break; } @@ -2020,6 +2152,32 @@ void PerlembParser::ExportEventVariables( break; } + case EVENT_DAMAGE_GIVEN: + case EVENT_DAMAGE_TAKEN:{ + Seperator sep(data); + ExportVar(package_name.c_str(), "entity_id", sep.arg[0]); + ExportVar(package_name.c_str(), "damage", sep.arg[1]); + ExportVar(package_name.c_str(), "spell_id", sep.arg[2]); + ExportVar(package_name.c_str(), "skill_id", sep.arg[3]); + ExportVar(package_name.c_str(), "is_damage_shield", sep.arg[4]); + ExportVar(package_name.c_str(), "is_avoidable", sep.arg[5]); + ExportVar(package_name.c_str(), "buff_slot", sep.arg[6]); + ExportVar(package_name.c_str(), "is_buff_tic", sep.arg[7]); + ExportVar(package_name.c_str(), "special_attack", sep.arg[8]); + break; + } + + case EVENT_DESTROY_ITEM_CLIENT: { + if (extra_pointers && extra_pointers->size() == 1) { + EQ::ItemInstance* inst = std::any_cast(extra_pointers->at(0)); + ExportVar(package_name.c_str(), "item_id", inst->GetID()); + ExportVar(package_name.c_str(), "item_name", inst->GetItem()->Name); + ExportVar(package_name.c_str(), "quantity", inst->IsStackable() ? inst->GetCharges() : 1); + ExportVar(package_name.c_str(), "item", "QuestItem", inst); + } + break; + } + default: { break; } diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 77036ecbe..61ce723b0 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -1063,12 +1063,12 @@ void Perl__playertexture(int texture_id) quest_manager.playertexture(texture_id); } -void Perl__playerfeature(char* feature, int value) +void Perl__playerfeature(const char* feature, int value) { quest_manager.playerfeature(feature, value); } -void Perl__npcfeature(char* feature, int value) +void Perl__npcfeature(const char* feature, int value) { quest_manager.npcfeature(feature, value); } @@ -3981,6 +3981,121 @@ int8 Perl__does_augment_fit(EQ::ItemInstance* inst, uint32 augment_id) return quest_manager.DoesAugmentFit(inst, augment_id); } +int8 Perl__does_augment_fit_slot(EQ::ItemInstance* inst, uint32 augment_id, uint8 augment_slot) +{ + return quest_manager.DoesAugmentFit(inst, augment_id, augment_slot); +} + +perl::array Perl__GetRecipeComponentItemIDs(uint32 recipe_id) +{ + perl::array result; + + const auto& l = content_db.GetRecipeComponentItemIDs(RecipeCountType::Component, recipe_id); + + if (!l.empty()) { + result.reserve(l.size()); + + for (int i = 0; i < l.size(); i++) { + result.push_back(l[i]); + } + } + + return result; +} + +perl::array Perl__GetRecipeContainerItemIDs(uint32 recipe_id) +{ + perl::array result; + + const auto& l = content_db.GetRecipeComponentItemIDs(RecipeCountType::Container, recipe_id); + + if (!l.empty()) { + result.reserve(l.size()); + + for (int i = 0; i < l.size(); i++) { + result.push_back(l[i]); + } + } + + return result; +} + +perl::array Perl__GetRecipeFailItemIDs(uint32 recipe_id) +{ + perl::array result; + + const auto &l = content_db.GetRecipeComponentItemIDs(RecipeCountType::Fail, recipe_id); + + if (!l.empty()) { + result.reserve(l.size()); + + for (int i = 0; i < l.size(); i++) { + result.push_back(l[i]); + } + } + + return result; +} + +perl::array Perl__GetRecipeSalvageItemIDs(uint32 recipe_id) +{ + perl::array result; + + const auto& l = content_db.GetRecipeComponentItemIDs(RecipeCountType::Salvage, recipe_id); + + if (!l.empty()) { + result.reserve(l.size()); + + for (int i = 0; i < l.size(); i++) { + result.push_back(l[i]); + } + } + + return result; +} + +perl::array Perl__GetRecipeSuccessItemIDs(uint32 recipe_id) +{ + perl::array result; + + const auto& l = content_db.GetRecipeComponentItemIDs(RecipeCountType::Success, recipe_id); + + if (!l.empty()) { + result.reserve(l.size()); + + for (int i = 0; i < l.size(); i++) { + result.push_back(l[i]); + } + } + + return result; +} + +int8 Perl__GetRecipeComponentCount(uint32 recipe_id, uint32 item_id) +{ + return content_db.GetRecipeComponentCount(RecipeCountType::Component, recipe_id, item_id); +} + +int8 Perl__GetRecipeFailCount(uint32 recipe_id, uint32 item_id) +{ + return content_db.GetRecipeComponentCount(RecipeCountType::Fail, recipe_id, item_id); +} + +int8 Perl__GetRecipeSalvageCount(uint32 recipe_id, uint32 item_id) +{ + return content_db.GetRecipeComponentCount(RecipeCountType::Salvage, recipe_id, item_id); +} + +int8 Perl__GetRecipeSuccessCount(uint32 recipe_id, uint32 item_id) +{ + return content_db.GetRecipeComponentCount(RecipeCountType::Success, recipe_id, item_id); +} + +void Perl__send_player_handin_event() +{ + quest_manager.SendPlayerHandinEvent(); +} + void perl_register_quest() { perl::interpreter perl(PERL_GET_THX); @@ -4326,7 +4441,8 @@ void perl_register_quest() package.add("doanim", (void(*)(int, int, bool))&Perl__doanim); package.add("doanim", (void(*)(int, int, bool, int))&Perl__doanim); package.add("do_augment_slots_match", &Perl__do_augment_slots_match); - package.add("does_augment_fit", &Perl__does_augment_fit); + package.add("does_augment_fit", (int8(*)(EQ::ItemInstance*, uint32))&Perl__does_augment_fit); + package.add("does_augment_fit_slot", (int8(*)(EQ::ItemInstance*, uint32, uint8))&Perl__does_augment_fit_slot); package.add("echo", &Perl__echo); package.add("emote", &Perl__emote); package.add("enable_proximity_say", &Perl__enable_proximity_say); @@ -4390,6 +4506,15 @@ void perl_register_quest() package.add("getgroupidbycharid", &Perl__getgroupidbycharid); package.add("getinventoryslotname", &Perl__getinventoryslotname); package.add("getraididbycharid", &Perl__getraididbycharid); + package.add("get_recipe_component_item_ids", &Perl__GetRecipeComponentItemIDs); + package.add("get_recipe_container_item_ids", &Perl__GetRecipeContainerItemIDs); + package.add("get_recipe_fail_item_ids", &Perl__GetRecipeFailItemIDs); + package.add("get_recipe_salvage_item_ids", &Perl__GetRecipeSalvageItemIDs); + package.add("get_recipe_success_item_ids", &Perl__GetRecipeSuccessItemIDs); + package.add("get_recipe_component_count", &Perl__GetRecipeComponentCount); + package.add("get_recipe_fail_count", &Perl__GetRecipeFailCount); + package.add("get_recipe_salvage_count", &Perl__GetRecipeSalvageCount); + package.add("get_recipe_success_count", &Perl__GetRecipeSuccessCount); package.add("getracename", &Perl__getracename); package.add("getremainingtimeMS", &Perl__getremainingtimeMS); package.add("getspell", &Perl__getspell); @@ -4512,6 +4637,7 @@ void perl_register_quest() package.add("scribespells", (int(*)(int, int))&Perl__scribespells); package.add("secondstotime", &Perl__secondstotime); package.add("selfcast", &Perl__selfcast); + package.add("send_player_handin_event", &Perl__send_player_handin_event); package.add("setaaexpmodifierbycharid", (void(*)(uint32, uint32, double))&Perl__setaaexpmodifierbycharid); package.add("setaaexpmodifierbycharid", (void(*)(uint32, uint32, double, int16))&Perl__setaaexpmodifierbycharid); package.add("set_proximity", (void(*)(float, float, float, float))&Perl__set_proximity); diff --git a/zone/embperl.h b/zone/embperl.h index d639a4311..a728eecd6 100644 --- a/zone/embperl.h +++ b/zone/embperl.h @@ -25,6 +25,8 @@ Eglin #include namespace perl = perlbind; +#undef Null + #ifdef WIN32 #define snprintf _snprintf #endif diff --git a/zone/entity.cpp b/zone/entity.cpp index af1d4e880..a447ec650 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -389,9 +389,7 @@ void EntityList::GroupProcess() for (auto &group : group_list) group->Process(); -#if EQDEBUG >= 5 - CheckGroupList (__FILE__, __LINE__); -#endif + } void EntityList::QueueToGroupsForNPCHealthAA(Mob *sender, const EQApplicationPacket *app) @@ -552,12 +550,10 @@ void EntityList::MobProcess() #endif Group *g = GetGroupByMob(mob); if(g) { - LogError("About to delete a client still in a group"); g->DelMember(mob); } Raid *r = entity_list.GetRaidByClient(mob->CastToClient()); if(r) { - LogError("About to delete a client still in a raid"); r->MemberZoned(mob->CastToClient()); } entity_list.RemoveClient(id); @@ -611,9 +607,7 @@ void EntityList::AddGroup(Group *group) } AddGroup(group, gid); -#if EQDEBUG >= 5 - CheckGroupList (__FILE__, __LINE__); -#endif + } void EntityList::AddGroup(Group *group, uint32 gid) @@ -683,7 +677,9 @@ void EntityList::AddNPC(NPC *npc, bool send_spawn_packet, bool dont_queue) npc_list.insert(std::pair(npc->GetID(), npc)); mob_list.insert(std::pair(npc->GetID(), npc)); - parse->EventNPC(EVENT_SPAWN, npc, nullptr, "", 0); + if (parse->HasQuestSub(npc->GetNPCTypeID(), EVENT_SPAWN)) { + parse->EventNPC(EVENT_SPAWN, npc, nullptr, "", 0); + } const auto emote_id = npc->GetEmoteID(); if (emote_id != 0) { @@ -718,9 +714,13 @@ void EntityList::AddNPC(NPC *npc, bool send_spawn_packet, bool dont_queue) } } + npc->SendPositionToClients(); + entity_list.ScanCloseMobs(npc->close_mobs, npc, true); - npc->DispatchZoneControllerEvent(EVENT_SPAWN_ZONE, npc, "", 0, nullptr); + if (parse->HasQuestSub(ZONE_CONTROLLER_NPC_ID, EVENT_SPAWN_ZONE)) { + npc->DispatchZoneControllerEvent(EVENT_SPAWN_ZONE, npc, "", 0, nullptr); + } if (zone->HasMap() && zone->HasWaterMap()) { npc->SetSpawnedInWater(false); @@ -844,8 +844,10 @@ void EntityList::CheckSpawnQueue() NPC *pnpc = it->second; pnpc->SendArmorAppearance(); pnpc->SetAppearance(pnpc->GetGuardPointAnim(), false); - if (!pnpc->IsTargetable()) + if (!pnpc->IsTargetable()) { pnpc->SendTargetable(false); + } + pnpc->SendPositionToClients(); } safe_delete(outapp); iterator.RemoveCurrent(); @@ -1783,12 +1785,29 @@ void EntityList::QueueClientsStatus(Mob *sender, const EQApplicationPacket *app, void EntityList::DuelMessage(Mob *winner, Mob *loser, bool flee) { if (winner->GetLevelCon(winner->GetLevel(), loser->GetLevel()) > 2) { - std::vector args; - args.push_back(winner); - args.push_back(loser); + if (parse->PlayerHasQuestSub(EVENT_DUEL_WIN)) { + std::vector args = { winner, loser }; - parse->EventPlayer(EVENT_DUEL_WIN, winner->CastToClient(), loser->GetName(), loser->CastToClient()->CharacterID(), &args); - parse->EventPlayer(EVENT_DUEL_LOSE, loser->CastToClient(), winner->GetName(), winner->CastToClient()->CharacterID(), &args); + parse->EventPlayer( + EVENT_DUEL_WIN, + winner->CastToClient(), + loser->GetName(), + loser->CastToClient()->CharacterID(), + &args + ); + } + + if (parse->PlayerHasQuestSub(EVENT_DUEL_LOSE)) { + std::vector args = { winner, loser }; + + parse->EventPlayer( + EVENT_DUEL_LOSE, + loser->CastToClient(), + winner->GetName(), + winner->CastToClient()->CharacterID(), + &args + ); + } } auto it = client_list.begin(); @@ -2092,9 +2111,6 @@ Group *EntityList::GetGroupByMob(Mob *mob) return *iterator; ++iterator; } -#if EQDEBUG >= 5 - CheckGroupList (__FILE__, __LINE__); -#endif return nullptr; } @@ -2109,9 +2125,6 @@ Group *EntityList::GetGroupByLeaderName(const char *leader) return *iterator; ++iterator; } -#if EQDEBUG >= 5 - CheckGroupList (__FILE__, __LINE__); -#endif return nullptr; } @@ -2126,9 +2139,6 @@ Group *EntityList::GetGroupByID(uint32 group_id) return *iterator; ++iterator; } -#if EQDEBUG >= 5 - CheckGroupList (__FILE__, __LINE__); -#endif return nullptr; } @@ -2147,13 +2157,12 @@ Group *EntityList::GetGroupByClient(Client *client) iterator = group_list.begin(); while (iterator != group_list.end()) { - if ((*iterator)->IsGroupMember(client->CastToMob())) + if ((*iterator)->IsGroupMember(client->CastToMob())) { return *iterator; + } ++iterator; } -#if EQDEBUG >= 5 - CheckGroupList (__FILE__, __LINE__); -#endif + return nullptr; } @@ -2164,9 +2173,9 @@ Raid *EntityList::GetRaidByLeaderName(const char *leader) iterator = raid_list.begin(); while (iterator != raid_list.end()) { - if ((*iterator)->GetLeader()) - if(strcmp((*iterator)->GetLeader()->GetName(), leader) == 0) - return *iterator; + if ((*iterator)->GetLeader() && strcmp((*iterator)->GetLeader()->GetName(), leader) == 0) { + return *iterator; + } ++iterator; } return nullptr; @@ -2186,22 +2195,20 @@ Raid *EntityList::GetRaidByID(uint32 id) return nullptr; } -Raid *EntityList::GetRaidByClient(Client* client) +Raid* EntityList::GetRaidByClient(Client* client) { if (client->p_raid_instance) { return client->p_raid_instance; } - std::list::iterator iterator; + std::list::iterator iterator; iterator = raid_list.begin(); while (iterator != raid_list.end()) { - for (auto &member : (*iterator)->members) { - if (member.member) { - if (member.member == client) { - client->p_raid_instance = *iterator; - return *iterator; - } + for (const auto& member : (*iterator)->members) { + if (member.member && member.member == client) { + client->p_raid_instance = *iterator; + return *iterator; } } @@ -2210,6 +2217,49 @@ Raid *EntityList::GetRaidByClient(Client* client) return nullptr; } +Raid* EntityList::GetRaidByBotName(const char* name) +{ + std::list rm; + auto GetMembersWithNames = [&rm](Raid const* r) -> std::list { + for (const auto& m : r->members) { + if (strlen(m.membername) > 0) + rm.push_back(m); + } + return rm; + }; + + for (const auto& r : raid_list) { + for (const auto& m : GetMembersWithNames(r)) { + if (strcmp(m.membername, name) == 0) { + return r; + } + } + } + return nullptr; +} + +Raid* EntityList::GetRaidByBot(const Bot* bot) +{ + std::list rm; + auto GetMembersWhoAreBots = [&rm](Raid* r) -> std::list { + for (auto const& m : r->members) { + if (m.IsBot) { + rm.push_back(m); + } + } + return rm; + }; + + for (const auto& r : raid_list) { + for (const auto& m : GetMembersWhoAreBots(r)) { + if (m.member->CastToBot() == bot) { + return r; + } + } + } + return nullptr; +} + Raid *EntityList::GetRaidByMob(Mob *mob) { @@ -2635,6 +2685,12 @@ void EntityList::RemoveAllNPCs() npc_limit_list.clear(); } +void EntityList::RemoveAllBots() +{ + // doesn't clear the data + bot_list.clear(); +} + void EntityList::RemoveAllMercs() { // doesn't clear the data @@ -2648,9 +2704,6 @@ void EntityList::RemoveAllGroups() group_list.pop_front(); safe_delete(group); } -#if EQDEBUG >= 5 - CheckGroupList (__FILE__, __LINE__); -#endif } void EntityList::RemoveAllRaids() @@ -3058,6 +3111,8 @@ void EntityList::Clear() { RemoveAllClients(); entity_list.RemoveAllTraps(); //we can have child npcs so we go first + entity_list.RemoveAllMercs(); + entity_list.RemoveAllBots(); entity_list.RemoveAllNPCs(); entity_list.RemoveAllMobs(); entity_list.RemoveAllCorpses(); @@ -3238,7 +3293,7 @@ char *EntityList::MakeNameUnique(char *name) if (it->second->IsMob()) { if (strncasecmp(it->second->CastToMob()->GetName(), name, len) == 0) { if (Seperator::IsNumber(&it->second->CastToMob()->GetName()[len])) { - used[atoi(&it->second->CastToMob()->GetName()[len])] = true; + used[Strings::ToInt(&it->second->CastToMob()->GetName()[len])] = true; } } } @@ -3641,21 +3696,25 @@ void EntityList::ClearFeignAggro(Mob *targ) } if (targ->IsClient()) { - std::vector args; - args.push_back(it->second); - int i = parse->EventPlayer(EVENT_FEIGN_DEATH, targ->CastToClient(), "", 0, &args); - if (i != 0) { - ++it; - continue; - } + if (parse->PlayerHasQuestSub(EVENT_FEIGN_DEATH)) { + std::vector args = { it->second }; - if (it->second->IsNPC()) { - int i = parse->EventNPC(EVENT_FEIGN_DEATH, it->second->CastToNPC(), targ, "", 0); + int i = parse->EventPlayer(EVENT_FEIGN_DEATH, targ->CastToClient(), "", 0, &args); if (i != 0) { ++it; continue; } } + + if (it->second->IsNPC()) { + if (parse->HasQuestSub(it->second->GetNPCTypeID(), EVENT_FEIGN_DEATH)) { + int i = parse->EventNPC(EVENT_FEIGN_DEATH, it->second->CastToNPC(), targ, "", 0); + if (i != 0) { + ++it; + continue; + } + } + } } it->second->RemoveFromHateList(targ); @@ -3988,29 +4047,43 @@ void EntityList::ProcessMove(Client *c, const glm::vec3& location) for (auto iter = events.begin(); iter != events.end(); ++iter) { quest_proximity_event& evt = (*iter); - std::vector args; - args.push_back(&evt.area_id); - args.push_back(&evt.area_type); + std::vector args = { &evt.area_id, &evt.area_type }; if (evt.npc) { if (evt.event_id == EVENT_ENTER) { - parse->EventNPC(EVENT_ENTER, evt.npc, evt.client, "", 0); + if (parse->HasQuestSub(evt.npc->GetNPCTypeID(), EVENT_ENTER)) { + parse->EventNPC(EVENT_ENTER, evt.npc, evt.client, "", 0); + } } else if (evt.event_id == EVENT_EXIT) { - parse->EventNPC(EVENT_EXIT, evt.npc, evt.client, "", 0); + if (parse->HasQuestSub(evt.npc->GetNPCTypeID(), EVENT_EXIT)) { + parse->EventNPC(EVENT_EXIT, evt.npc, evt.client, "", 0); + } } else if (evt.event_id == EVENT_ENTER_AREA) { - parse->EventNPC(EVENT_ENTER_AREA, evt.npc, evt.client, "", 0, &args); + if (parse->HasQuestSub(evt.npc->GetNPCTypeID(), EVENT_ENTER_AREA)) { + parse->EventNPC(EVENT_ENTER_AREA, evt.npc, evt.client, "", 0, &args); + } } else if (evt.event_id == EVENT_LEAVE_AREA) { - parse->EventNPC(EVENT_LEAVE_AREA, evt.npc, evt.client, "", 0, &args); + if (parse->HasQuestSub(evt.npc->GetNPCTypeID(), EVENT_LEAVE_AREA)) { + parse->EventNPC(EVENT_LEAVE_AREA, evt.npc, evt.client, "", 0, &args); + } } } else { if (evt.event_id == EVENT_ENTER) { - parse->EventPlayer(EVENT_ENTER, evt.client, "", 0); + if (parse->PlayerHasQuestSub(EVENT_ENTER)) { + parse->EventPlayer(EVENT_ENTER, evt.client, "", 0); + } } else if (evt.event_id == EVENT_EXIT) { - parse->EventPlayer(EVENT_EXIT, evt.client, "", 0); + if (parse->PlayerHasQuestSub(EVENT_EXIT)) { + parse->EventPlayer(EVENT_EXIT, evt.client, "", 0); + } } else if (evt.event_id == EVENT_ENTER_AREA) { - parse->EventPlayer(EVENT_ENTER_AREA, evt.client, "", 0, &args); + if (parse->PlayerHasQuestSub(EVENT_ENTER_AREA)) { + parse->EventPlayer(EVENT_ENTER_AREA, evt.client, "", 0, &args); + } } else if (evt.event_id == EVENT_LEAVE_AREA) { - parse->EventPlayer(EVENT_LEAVE_AREA, evt.client, "", 0, &args); + if (parse->PlayerHasQuestSub(EVENT_LEAVE_AREA)) { + parse->EventPlayer(EVENT_LEAVE_AREA, evt.client, "", 0, &args); + } } } } @@ -4023,20 +4096,22 @@ void EntityList::ProcessMove(NPC *n, float x, float y, float z) { std::list events; - for (auto iter = area_list.begin(); iter != area_list.end(); ++iter) { - - Area &a = (*iter); + for (const auto& a : area_list) { bool old_in = true; bool new_in = true; - if (last_x < a.min_x || last_x > a.max_x || - last_y < a.min_y || last_y > a.max_y || - last_z < a.min_z || last_z > a.max_z) { + if ( + !EQ::ValueWithin(last_x, a.min_x, a.max_x) || + !EQ::ValueWithin(last_y, a.min_y, a.max_y) || + !EQ::ValueWithin(last_z, a.min_z, a.max_z) + ) { old_in = false; } - if (x < a.min_x || x > a.max_x || - y < a.min_y || y > a.max_y || - z < a.min_z || z > a.max_z) { + if ( + !EQ::ValueWithin(x, a.min_x, a.max_x) || + !EQ::ValueWithin(y, a.min_y, a.max_y) || + !EQ::ValueWithin(z, a.min_z, a.max_z) + ) { new_in = false; } @@ -4048,7 +4123,7 @@ void EntityList::ProcessMove(NPC *n, float x, float y, float z) { evt.npc = n; evt.area_id = a.id; evt.area_type = a.type; - events.push_back(evt); + events.emplace_back(evt); } else if (!old_in && new_in) { //were not in but now are @@ -4058,25 +4133,29 @@ void EntityList::ProcessMove(NPC *n, float x, float y, float z) { evt.npc = n; evt.area_id = a.id; evt.area_type = a.type; - events.push_back(evt); + events.emplace_back(evt); } } - for (auto iter = events.begin(); iter != events.end(); ++iter) { - quest_proximity_event &evt = (*iter); - - std::vector args; - args.push_back(&evt.area_id); - args.push_back(&evt.area_type); + for (const auto& evt : events) { + std::vector args = { &evt.area_id, &evt.area_type }; if (evt.event_id == EVENT_ENTER) { - parse->EventNPC(EVENT_ENTER, evt.npc, evt.client, "", 0); + if (parse->HasQuestSub(evt.npc->GetNPCTypeID(), EVENT_ENTER)) { + parse->EventNPC(EVENT_ENTER, evt.npc, evt.client, "", 0); + } } else if (evt.event_id == EVENT_EXIT) { - parse->EventNPC(EVENT_EXIT, evt.npc, evt.client, "", 0); + if (parse->HasQuestSub(evt.npc->GetNPCTypeID(), EVENT_EXIT)) { + parse->EventNPC(EVENT_EXIT, evt.npc, evt.client, "", 0); + } } else if (evt.event_id == EVENT_ENTER_AREA) { - parse->EventNPC(EVENT_ENTER_AREA, evt.npc, evt.client, "", 0, &args); + if (parse->HasQuestSub(evt.npc->GetNPCTypeID(), EVENT_ENTER_AREA)) { + parse->EventNPC(EVENT_ENTER_AREA, evt.npc, evt.client, "", 0, &args); + } } else if (evt.event_id == EVENT_LEAVE_AREA) { - parse->EventNPC(EVENT_LEAVE_AREA, evt.npc, evt.client, "", 0, &args); + if (parse->HasQuestSub(evt.npc->GetNPCTypeID(), EVENT_LEAVE_AREA)) { + parse->EventNPC(EVENT_LEAVE_AREA, evt.npc, evt.client, "", 0, &args); + } } } } @@ -4130,24 +4209,31 @@ void EntityList::ClearAreas() area_list.clear(); } -void EntityList::ProcessProximitySay(const char *Message, Client *c, uint8 language) +void EntityList::ProcessProximitySay(const char *message, Client *c, uint8 language) { - if (!Message || !c) + if (!message || !c) { return; + } - auto iter = proximity_list.begin(); - for (; iter != proximity_list.end(); ++iter) { - NPC *d = (*iter); - NPCProximity *l = d->proximity; - if (l == nullptr || !l->say) + for (const auto& n : proximity_list) { + auto* p = n->proximity; + if (!p || !p->say) { continue; + } - if (c->GetX() < l->min_x || c->GetX() > l->max_x - || c->GetY() < l->min_y || c->GetY() > l->max_y - || c->GetZ() < l->min_z || c->GetZ() > l->max_z) + if (!parse->HasQuestSub(n->GetNPCTypeID(), EVENT_PROXIMITY_SAY)) { continue; + } - parse->EventNPC(EVENT_PROXIMITY_SAY, d, c, Message, language); + if ( + !EQ::ValueWithin(c->GetX(), p->min_x, p->max_x) || + !EQ::ValueWithin(c->GetY(), p->min_y, p->max_y) || + !EQ::ValueWithin(c->GetZ(), p->min_z, p->max_z) + ) { + continue; + } + + parse->EventNPC(EVENT_PROXIMITY_SAY, n, c, message, language); } } @@ -5852,7 +5938,7 @@ void EntityList::DespawnGridNodes(int32 grid_id) { mob->IsNPC() && mob->GetRace() == RACE_NODE_2254 && mob->EntityVariableExists("grid_id") && - std::stoi(mob->GetEntityVariable("grid_id")) == grid_id) + Strings::ToInt(mob->GetEntityVariable("grid_id")) == grid_id) { mob->Depop(); } diff --git a/zone/entity.h b/zone/entity.h index d79bd9e83..5a2939e60 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -67,20 +67,22 @@ public: Entity(); virtual ~Entity(); - virtual bool IsClient() const { return false; } - virtual bool IsNPC() const { return false; } - virtual bool IsMob() const { return false; } - virtual bool IsMerc() const { return false; } - virtual bool IsCorpse() const { return false; } - virtual bool IsPlayerCorpse() const { return false; } - virtual bool IsNPCCorpse() const { return false; } - virtual bool IsObject() const { return false; } - virtual bool IsDoor() const { return false; } - virtual bool IsTrap() const { return false; } - virtual bool IsBeacon() const { return false; } - virtual bool IsEncounter() const { return false; } - virtual bool IsBot() const { return false; } - virtual bool IsAura() const { return false; } + virtual bool IsClient() const { return false; } + virtual bool IsNPC() const { return false; } + virtual bool IsMob() const { return false; } + virtual bool IsMerc() const { return false; } + virtual bool IsCorpse() const { return false; } + virtual bool IsPlayerCorpse() const { return false; } + virtual bool IsNPCCorpse() const { return false; } + virtual bool IsObject() const { return false; } + virtual bool IsDoor() const { return false; } + virtual bool IsTrap() const { return false; } + virtual bool IsBeacon() const { return false; } + virtual bool IsEncounter() const { return false; } + virtual bool IsBot() const { return false; } + virtual bool IsAura() const { return false; } + virtual bool IsOfClientBot() const { return false; } + virtual bool IsOfClientBotMerc() const { return false; } virtual bool Process() { return false; } virtual bool Save() { return true; } @@ -190,7 +192,8 @@ public: Client* GetRandomClient(const glm::vec3& location = glm::vec3(0.f), float distance = 0, Client* exclude_client = nullptr); NPC* GetRandomNPC(const glm::vec3& location = glm::vec3(0.f), float distance = 0, NPC* exclude_npc = nullptr); Mob* GetRandomMob(const glm::vec3& location = glm::vec3(0.f), float distance = 0, Mob* exclude_mob = nullptr); - Group *GetGroupByMob(Mob* mob); + Group* GetGroupByMob(Mob* mob); + Group* GetGroupByBot(Bot* bot); bool IsInSameGroupOrRaidGroup(Client *client1, Client *client2); Group *GetGroupByClient(Client* client); Group *GetGroupByID(uint32 id); @@ -199,6 +202,8 @@ public: Raid *GetRaidByClient(Client* client); Raid *GetRaidByID(uint32 id); Raid *GetRaidByLeaderName(const char *leader); + Raid* GetRaidByBotName(const char* name); + Raid* GetRaidByBot(const Bot* bot); Corpse *GetCorpseByOwner(Client* client); Corpse *GetCorpseByOwnerWithinRange(Client* client, Mob* center, int range); @@ -261,7 +266,7 @@ public: void RemoveArea(int id); void ClearAreas(); void ReloadMerchants(); - void ProcessProximitySay(const char *Message, Client *c, uint8 language = 0); + void ProcessProximitySay(const char *message, Client *c, uint8 language = 0); void SendAATimer(uint32 charid,UseAA_Struct* uaa); Doors *FindDoor(uint8 door_id); Object *FindObject(uint32 object_id); @@ -302,6 +307,7 @@ public: void RemoveAllMobs(); void RemoveAllClients(); void RemoveAllNPCs(); + void RemoveAllBots(); void RemoveAllMercs(); void RemoveAllGroups(); void RemoveAllCorpses(); @@ -617,7 +623,7 @@ private: bool RemoveBot(uint16 entityID); Mob* GetMobByBotID(uint32 botID); Bot* GetBotByBotID(uint32 botID); - Bot* GetBotByBotName(std::string botName); + Bot* GetBotByBotName(std::string_view botName); Client* GetBotOwnerByBotEntityID(uint32 entity_id); Client* GetBotOwnerByBotID(const uint32 bot_id); std::list GetBotsByBotOwnerCharacterID(uint32 botOwnerCharacterID); diff --git a/zone/event_codes.h b/zone/event_codes.h index 2c56f42c6..df54ba231 100644 --- a/zone/event_codes.h +++ b/zone/event_codes.h @@ -106,6 +106,8 @@ typedef enum { EVENT_TASK_BEFORE_UPDATE, EVENT_AA_BUY, EVENT_AA_GAIN, + EVENT_AA_EXP_GAIN, + EVENT_EXP_GAIN, EVENT_PAYLOAD, EVENT_LEVEL_DOWN, EVENT_GM_COMMAND, @@ -114,6 +116,14 @@ typedef enum { EVENT_BOT_CREATE, EVENT_AUGMENT_INSERT_CLIENT, EVENT_AUGMENT_REMOVE_CLIENT, + EVENT_EQUIP_ITEM_BOT, + EVENT_UNEQUIP_ITEM_BOT, + EVENT_DAMAGE_GIVEN, + EVENT_DAMAGE_TAKEN, + EVENT_ITEM_CLICK_CLIENT, + EVENT_ITEM_CLICK_CAST_CLIENT, + EVENT_DESTROY_ITEM_CLIENT, + EVENT_DROP_ITEM_CLIENT, // Add new events before these or Lua crashes EVENT_SPELL_EFFECT_BOT, EVENT_SPELL_EFFECT_BUFF_TIC_BOT, diff --git a/zone/exp.cpp b/zone/exp.cpp index 27d7987dd..2907667d2 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -34,6 +34,10 @@ #include "../common/data_verification.h" #include "bot.h" +#include "../common/events/player_event_logs.h" +#include "worldserver.h" + +extern WorldServer worldserver; extern QueryServ* QServ; @@ -721,12 +725,11 @@ void Client::SetEXP(uint64 set_exp, uint64 set_aaxp, bool isrezzexp) { SendSound(); } - const auto export_string = fmt::format( - "{}", - gained - ); + if (parse->PlayerHasQuestSub(EVENT_AA_GAIN)) { + parse->EventPlayer(EVENT_AA_GAIN, this, std::to_string(gained), 0); + } - parse->EventPlayer(EVENT_AA_GAIN, this, export_string, 0); + RecordPlayerEventLog(PlayerEvent::AA_GAIN, PlayerEvent::AAGainedEvent{gained}); /* QS: PlayerLogAARate */ if (RuleB(QueryServ, PlayerLogAARate)){ @@ -801,14 +804,23 @@ void Client::SetEXP(uint64 set_exp, uint64 set_aaxp, bool isrezzexp) { } } + if (parse->PlayerHasQuestSub(EVENT_EXP_GAIN) && m_pp.exp != set_exp) { + parse->EventPlayer(EVENT_EXP_GAIN, this, std::to_string(set_exp - m_pp.exp), 0); + } + + if (parse->PlayerHasQuestSub(EVENT_AA_EXP_GAIN) && m_pp.expAA != set_aaxp) { + parse->EventPlayer(EVENT_AA_EXP_GAIN, this, std::to_string(set_aaxp - m_pp.expAA), 0); + } + //set the client's EXP and AAEXP m_pp.exp = set_exp; m_pp.expAA = set_aaxp; if (GetLevel() < 51) { m_epp.perAA = 0; // turn off aa exp if they drop below 51 - } else - SendAlternateAdvancementStats(); //otherwise, send them an AA update + } else { + SendAlternateAdvancementStats(); //otherwise, send them an AA update + } //send the expdata in any case so the xp bar isnt stuck after leveling uint32 tmpxp1 = GetEXPForLevel(GetLevel()+1); @@ -867,8 +879,21 @@ void Client::SetLevel(uint8 set_level, bool command) } if (set_level > m_pp.level) { - const auto export_string = fmt::format("{}", (set_level - m_pp.level)); - parse->EventPlayer(EVENT_LEVEL_UP, this, export_string, 0); + int levels_gained = (set_level - m_pp.level); + + if (parse->PlayerHasQuestSub(EVENT_LEVEL_UP)) { + parse->EventPlayer(EVENT_LEVEL_UP, this, std::to_string(levels_gained), 0); + } + + if (player_event_logs.IsEventEnabled(PlayerEvent::LEVEL_GAIN)) { + auto e = PlayerEvent::LevelGainedEvent{ + .from_level = m_pp.level, + .to_level = set_level, + .levels_gained = levels_gained + }; + + RecordPlayerEventLog(PlayerEvent::LEVEL_GAIN, e); + } if (RuleB(QueryServ, PlayerLogLevels)) { const auto event_desc = fmt::format( @@ -881,8 +906,21 @@ void Client::SetLevel(uint8 set_level, bool command) QServ->PlayerLogEvent(Player_Log_Levels, CharacterID(), event_desc); } } else if (set_level < m_pp.level) { - const auto export_string = fmt::format("{}", (m_pp.level - set_level)); - parse->EventPlayer(EVENT_LEVEL_DOWN, this, export_string, 0); + int levels_lost = (m_pp.level - set_level); + + if (parse->PlayerHasQuestSub(EVENT_LEVEL_DOWN)) { + parse->EventPlayer(EVENT_LEVEL_DOWN, this, std::to_string(levels_lost), 0); + } + + if (player_event_logs.IsEventEnabled(PlayerEvent::LEVEL_LOSS)) { + auto e = PlayerEvent::LevelLostEvent{ + .from_level = m_pp.level, + .to_level = set_level, + .levels_lost = levels_lost + }; + + RecordPlayerEventLog(PlayerEvent::LEVEL_LOSS, e); + } if (RuleB(QueryServ, PlayerLogLevels)) { const auto event_desc = fmt::format( @@ -1028,8 +1066,6 @@ uint32 Client::GetEXPForLevel(uint16 check_level) finalxp = uint64(finalxp * classmod); } - finalxp = mod_client_xp_for_level(finalxp, check_level); - return finalxp; } @@ -1079,11 +1115,11 @@ void Group::SplitExp(const uint64 exp, Mob* other) { return; } - auto group_experience = exp; + auto group_experience = exp; const auto highest_level = GetHighestLevel(); auto group_modifier = 1.0f; - if (RuleB(Character, EnableGroupEXPModifier)) { + if (RuleB(Character, EnableGroupMemberEXPModifier)) { if (EQ::ValueWithin(member_count, 2, 5)) { group_modifier = 1 + RuleR(Character, GroupMemberEXPModifier) * (member_count - 1); // 2 = 1.2x, 3 = 1.4x, 4 = 1.6x, 5 = 1.8x } else if (member_count == 6) { @@ -1092,11 +1128,18 @@ void Group::SplitExp(const uint64 exp, Mob* other) { } if (EQ::ValueWithin(member_count, 2, 6)) { - group_experience += static_cast( - static_cast(exp) * - group_modifier * - RuleR(Character, GroupExpMultiplier) - ); + if (RuleB(Character, EnableGroupEXPModifier)) { + group_experience += static_cast( + static_cast(exp) * + group_modifier * + RuleR(Character, GroupExpMultiplier) + ); + } else { + group_experience += static_cast( + static_cast(exp) * + group_modifier + ); + } } const uint8 consider_level = Mob::GetLevelCon(highest_level, other->GetLevel()); @@ -1106,8 +1149,8 @@ void Group::SplitExp(const uint64 exp, Mob* other) { for (const auto& m : members) { if (m && m->IsClient()) { - const int32 diff = m->GetLevel() - highest_level; - int32 max_diff = -(m->GetLevel() * 15 / 10 - m->GetLevel()); + const int32 diff = m->GetLevel() - highest_level; + int32 max_diff = -(m->GetLevel() * 15 / 10 - m->GetLevel()); if (max_diff > -5) { max_diff = -5; @@ -1136,23 +1179,30 @@ void Raid::SplitExp(const uint64 exp, Mob* other) { return; } - auto raid_experience = exp; + auto raid_experience = exp; const auto highest_level = GetHighestLevel(); - raid_experience = static_cast( - static_cast(raid_experience) * - (1.0f - RuleR(Character, RaidExpMultiplier)) - ); + if (RuleB(Character, EnableRaidEXPModifier)) { + raid_experience = static_cast( + static_cast(raid_experience) * + (1.0f - RuleR(Character, RaidExpMultiplier)) + ); + } const auto consider_level = Mob::GetLevelCon(highest_level, other->GetLevel()); if (consider_level == CON_GRAY) { return; } + uint32 member_modifier = 1; + if (RuleB(Character, EnableRaidMemberEXPModifier)) { + member_modifier = member_count; + } + for (const auto& m : members) { - if (m.member) { + if (m.member && !m.IsBot) { const int32 diff = m.member->GetLevel() - highest_level; - int32 max_diff = -(m.member->GetLevel() * 15 / 10 - m.member->GetLevel()); + int32 max_diff = -(m.member->GetLevel() * 15 / 10 - m.member->GetLevel()); if (max_diff > -5) { max_diff = -5; @@ -1160,7 +1210,7 @@ void Raid::SplitExp(const uint64 exp, Mob* other) { if (diff >= max_diff) { const uint64 tmp = (m.member->GetLevel() + 3) * (m.member->GetLevel() + 3) * 75 * 35 / 10; - const uint64 tmp2 = (raid_experience / member_count) + 1; + const uint64 tmp2 = (raid_experience / member_modifier) + 1; m.member->AddEXP(tmp < tmp2 ? tmp : tmp2, consider_level); } } @@ -1213,7 +1263,7 @@ uint8 Client::GetCharMaxLevelFromQGlobal() { for (const auto& global : global_map) { if (global.name == "CharMaxLevel") { if (Strings::IsNumber(global.value)) { - return static_cast(std::stoul(global.value)); + return static_cast(Strings::ToUnsignedInt(global.value)); } } } @@ -1231,7 +1281,7 @@ uint8 Client::GetCharMaxLevelFromBucket() auto bucket_value = DataBucket::GetData(new_bucket_name); if (!bucket_value.empty()) { if (Strings::IsNumber(bucket_value)) { - return static_cast(std::stoul(bucket_value)); + return static_cast(Strings::ToUnsignedInt(bucket_value)); } } @@ -1243,7 +1293,7 @@ uint8 Client::GetCharMaxLevelFromBucket() bucket_value = DataBucket::GetData(old_bucket_name); if (!bucket_value.empty()) { if (Strings::IsNumber(bucket_value)) { - return static_cast(std::stoul(bucket_value)); + return static_cast(Strings::ToUnsignedInt(bucket_value)); } } diff --git a/zone/expedition.h b/zone/expedition.h index d9d47a34e..1379b724d 100644 --- a/zone/expedition.h +++ b/zone/expedition.h @@ -29,6 +29,7 @@ #include #include #include +#include class Client; class EQApplicationPacket; diff --git a/zone/forage.cpp b/zone/forage.cpp index 21074b4a4..eba72977d 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -32,6 +32,10 @@ #include "zonedb.h" #include "../common/zone_store.h" #include "../common/repositories/criteria/content_filter_criteria.h" +#include "../common/events/player_event_logs.h" +#include "worldserver.h" + +extern WorldServer worldserver; #include @@ -86,10 +90,9 @@ uint32 ZoneDatabase::GetZoneForage(uint32 ZoneID, uint8 skill) { break; } - item[index] = atoi(row[0]); - chance[index] = atoi(row[1]) + chancepool; - LogError("Possible Forage: [{}] with a [{}] chance", item[index], chance[index]); - chancepool = chance[index]; + item[index] = Strings::ToInt(row[0]); + chance[index] = Strings::ToInt(row[1]) + chancepool; + chancepool = chance[index]; } if(chancepool == 0 || index < 1) @@ -155,12 +158,12 @@ uint32 ZoneDatabase::GetZoneFishing(uint32 ZoneID, uint8 skill, uint32 &npc_id, if (index >= 50) break; - item[index] = atoi(row[0]); - chance[index] = atoi(row[1])+chancepool; + item[index] = Strings::ToInt(row[0]); + chance[index] = Strings::ToInt(row[1])+chancepool; chancepool = chance[index]; - npc_ids[index] = atoi(row[2]); - npc_chances[index] = atoi(row[3]); + npc_ids[index] = Strings::ToInt(row[2]); + npc_chances[index] = Strings::ToInt(row[3]); } npc_id = 0; @@ -374,9 +377,19 @@ void Client::GoFish() } if (inst) { - std::vector args; - args.push_back(inst); - parse->EventPlayer(EVENT_FISH_SUCCESS, this, "", inst->GetID(), &args); + if (player_event_logs.IsEventEnabled(PlayerEvent::FISH_SUCCESS)) { + auto e = PlayerEvent::FishSuccessEvent{ + .item_id = inst->GetItem()->ID, + .item_name = inst->GetItem()->Name, + }; + + RecordPlayerEventLog(PlayerEvent::FISH_SUCCESS, e); + } + + if (parse->PlayerHasQuestSub(EVENT_FISH_SUCCESS)) { + std::vector args = { inst }; + parse->EventPlayer(EVENT_FISH_SUCCESS, this, "", inst->GetID(), &args); + } } } } @@ -395,7 +408,10 @@ void Client::GoFish() MessageString(Chat::Skills, FISHING_FAILED); //You didn't catch anything. } - parse->EventPlayer(EVENT_FISH_FAILURE, this, "", 0); + RecordPlayerEventLog(PlayerEvent::FISH_FAILURE, PlayerEvent::EmptyEvent{}); + if (parse->PlayerHasQuestSub(EVENT_FISH_FAILURE)) { + parse->EventPlayer(EVENT_FISH_FAILURE, this, "", 0); + } } //chance to break fishing pole... @@ -494,9 +510,18 @@ void Client::ForageItem(bool guarantee) { } if (inst) { - std::vector args; - args.push_back(inst); - parse->EventPlayer(EVENT_FORAGE_SUCCESS, this, "", inst->GetID(), &args); + if (player_event_logs.IsEventEnabled(PlayerEvent::FORAGE_SUCCESS)) { + auto e = PlayerEvent::ForageSuccessEvent{ + .item_id = inst->GetItem()->ID, + .item_name = inst->GetItem()->Name + }; + RecordPlayerEventLog(PlayerEvent::FORAGE_SUCCESS, e); + } + + if (parse->PlayerHasQuestSub(EVENT_FORAGE_SUCCESS)) { + std::vector args = { inst }; + parse->EventPlayer(EVENT_FORAGE_SUCCESS, this, "", inst->GetID(), &args); + } } } @@ -507,7 +532,11 @@ void Client::ForageItem(bool guarantee) { } } else { MessageString(Chat::Skills, FORAGE_FAILED); - parse->EventPlayer(EVENT_FORAGE_FAILURE, this, "", 0); + RecordPlayerEventLog(PlayerEvent::FORAGE_FAILURE, PlayerEvent::EmptyEvent{}); + + if (parse->PlayerHasQuestSub(EVENT_FORAGE_FAILURE)) { + parse->EventPlayer(EVENT_FORAGE_FAILURE, this, "", 0); + } } CheckIncreaseSkill(EQ::skills::SkillForage, nullptr, 5); diff --git a/zone/gm_commands/advnpcspawn.cpp b/zone/gm_commands/advnpcspawn.cpp index 0ec3cbd63..235362f3f 100755 --- a/zone/gm_commands/advnpcspawn.cpp +++ b/zone/gm_commands/advnpcspawn.cpp @@ -91,9 +91,9 @@ void command_advnpcspawn(Client *c, const Seperator *sep) return; } - auto spawngroup_id = std::stoul(sep->arg[2]); - auto npc_id = std::stoul(sep->arg[3]); - auto spawn_chance = std::stoul(sep->arg[4]); + auto spawngroup_id = Strings::ToUnsignedInt(sep->arg[2]); + auto npc_id = Strings::ToUnsignedInt(sep->arg[3]); + auto spawn_chance = Strings::ToUnsignedInt(sep->arg[4]); auto query = fmt::format( SQL( @@ -129,14 +129,14 @@ void command_advnpcspawn(Client *c, const Seperator *sep) zone->GetInstanceVersion(), c, 0, - std::stoul(sep->arg[2]) + Strings::ToUnsignedInt(sep->arg[2]) ) ) { c->Message( Chat::White, fmt::format( "Spawn Added | Added spawn from Spawngroup ID {}.", - std::stoul(sep->arg[2]) + Strings::ToUnsignedInt(sep->arg[2]) ).c_str() ); } @@ -149,7 +149,7 @@ void command_advnpcspawn(Client *c, const Seperator *sep) auto query = fmt::format( "UPDATE spawngroup SET dist = 0, min_x = 0, max_x = 0, min_y = 0, max_y = 0, delay = 0 WHERE id = {}", - std::stoul(sep->arg[2]) + Strings::ToUnsignedInt(sep->arg[2]) ); auto results = content_db.QueryDatabase(query); if (!results.Success()) { @@ -161,7 +161,7 @@ void command_advnpcspawn(Client *c, const Seperator *sep) Chat::White, fmt::format( "Spawngroup {} Roambox Cleared | Delay: 0 Distance: 0.00", - std::stoul(sep->arg[2]) + Strings::ToUnsignedInt(sep->arg[2]) ).c_str() ); @@ -169,7 +169,7 @@ void command_advnpcspawn(Client *c, const Seperator *sep) Chat::White, fmt::format( "Spawngroup {} Roambox Cleared | Minimum X: 0.00 Maximum X: 0.00", - std::stoul(sep->arg[2]) + Strings::ToUnsignedInt(sep->arg[2]) ).c_str() ); @@ -177,7 +177,7 @@ void command_advnpcspawn(Client *c, const Seperator *sep) Chat::White, fmt::format( "Spawngroup {} Roambox Cleared | Minimum Y: 0.00 Maximum Y: 0.00", - std::stoul(sep->arg[2]) + Strings::ToUnsignedInt(sep->arg[2]) ).c_str() ); return; @@ -231,13 +231,13 @@ void command_advnpcspawn(Client *c, const Seperator *sep) ); return; } - auto spawngroup_id = std::stoul(sep->arg[2]); - auto distance = std::stof(sep->arg[3]); - auto minimum_x = std::stof(sep->arg[4]); - auto maximum_x = std::stof(sep->arg[5]); - auto minimum_y = std::stof(sep->arg[6]); - auto maximum_y = std::stof(sep->arg[7]); - auto delay = std::stoi(sep->arg[8]); + auto spawngroup_id = Strings::ToUnsignedInt(sep->arg[2]); + auto distance = Strings::ToFloat(sep->arg[3]); + auto minimum_x = Strings::ToFloat(sep->arg[4]); + auto maximum_x = Strings::ToFloat(sep->arg[5]); + auto minimum_y = Strings::ToFloat(sep->arg[6]); + auto maximum_y = Strings::ToFloat(sep->arg[7]); + auto delay = Strings::ToInt(sep->arg[8]); auto query = fmt::format( "UPDATE spawngroup SET dist = {:.2f}, min_x = {:.2f}, max_x = {:.2f}, max_y = {:.2f}, min_y = {:.2f}, delay = {} WHERE id = {}", @@ -304,8 +304,8 @@ void command_advnpcspawn(Client *c, const Seperator *sep) } auto spawn2_id = spawn2->GetID(); - auto respawn_timer = std::stoul(sep->arg[2]); - auto variance = sep->IsNumber(3) ? std::stoul(sep->arg[3]) : spawn2->GetVariance(); + auto respawn_timer = Strings::ToUnsignedInt(sep->arg[2]); + auto variance = sep->IsNumber(3) ? Strings::ToUnsignedInt(sep->arg[3]) : spawn2->GetVariance(); auto query = fmt::format( "UPDATE spawn2 SET respawntime = {}, variance = {} WHERE id = {}", @@ -343,13 +343,13 @@ void command_advnpcspawn(Client *c, const Seperator *sep) } std::string spawngroup_name = sep->arg[2]; - auto spawn_limit = sep->IsNumber(3) ? std::stoi(sep->arg[3]) : 0; - auto distance = sep->IsNumber(4) ? std::stof(sep->arg[4]) : 0.0f; - auto minimum_x = sep->IsNumber(5) ? std::stof(sep->arg[5]) : 0.0f; - auto maximum_x = sep->IsNumber(6) ? std::stof(sep->arg[6]) : 0.0f; - auto minimum_y = sep->IsNumber(7) ? std::stof(sep->arg[7]) : 0.0f; - auto maximum_y = sep->IsNumber(8) ? std::stof(sep->arg[8]) : 0.0f; - auto delay = sep->IsNumber(9) ? std::stoi(sep->arg[9]) : 0; + auto spawn_limit = sep->IsNumber(3) ? Strings::ToInt(sep->arg[3]) : 0; + auto distance = sep->IsNumber(4) ? Strings::ToFloat(sep->arg[4]) : 0.0f; + auto minimum_x = sep->IsNumber(5) ? Strings::ToFloat(sep->arg[5]) : 0.0f; + auto maximum_x = sep->IsNumber(6) ? Strings::ToFloat(sep->arg[6]) : 0.0f; + auto minimum_y = sep->IsNumber(7) ? Strings::ToFloat(sep->arg[7]) : 0.0f; + auto maximum_y = sep->IsNumber(8) ? Strings::ToFloat(sep->arg[8]) : 0.0f; + auto delay = sep->IsNumber(9) ? Strings::ToInt(sep->arg[9]) : 0; auto query = fmt::format( "INSERT INTO spawngroup" @@ -497,7 +497,7 @@ void command_advnpcspawn(Client *c, const Seperator *sep) } auto target = c->GetTarget()->CastToNPC(); - auto version = std::stoul(sep->arg[2]); + auto version = Strings::ToUnsignedInt(sep->arg[2]); auto query = fmt::format( "UPDATE spawn2 SET version = {} WHERE spawngroupID = {}", diff --git a/zone/gm_commands/aggro.cpp b/zone/gm_commands/aggro.cpp index 90fe9e335..926904131 100755 --- a/zone/gm_commands/aggro.cpp +++ b/zone/gm_commands/aggro.cpp @@ -21,7 +21,7 @@ void command_aggro(Client *c, const Seperator *sep) NPC* target = c->GetTarget()->CastToNPC(); - float distance = std::stof(sep->arg[1]); + float distance = Strings::ToFloat(sep->arg[1]); bool verbose = !strcasecmp("-v", sep->arg[2]); entity_list.DescribeAggro(c, target, distance, verbose); } diff --git a/zone/gm_commands/ai.cpp b/zone/gm_commands/ai.cpp index 9ae6351e1..b746ac0b4 100755 --- a/zone/gm_commands/ai.cpp +++ b/zone/gm_commands/ai.cpp @@ -64,7 +64,7 @@ void command_ai(Client *c, const Seperator *sep) } } else if (is_faction) { if (sep->IsNumber(2)) { - auto faction_id = std::stoi(sep->arg[2]); + auto faction_id = Strings::ToInt(sep->arg[2]); auto faction_name = content_db.GetFactionName(faction_id); target->SetNPCFactionID(faction_id); c->Message( @@ -113,21 +113,21 @@ void command_ai(Client *c, const Seperator *sep) sep->IsNumber(5) && sep->IsNumber(6) ) { - auto distance = std::stof(sep->arg[2]); - auto min_x = std::stof(sep->arg[3]); - auto max_x = std::stof(sep->arg[4]); - auto min_y = std::stof(sep->arg[5]); - auto max_y = std::stof(sep->arg[6]); + auto distance = Strings::ToFloat(sep->arg[2]); + auto min_x = Strings::ToFloat(sep->arg[3]); + auto max_x = Strings::ToFloat(sep->arg[4]); + auto min_y = Strings::ToFloat(sep->arg[5]); + auto max_y = Strings::ToFloat(sep->arg[6]); uint32 delay = 2500; uint32 minimum_delay = 2500; if (sep->IsNumber(7)) { - delay = std::stoul(sep->arg[7]); + delay = Strings::ToUnsignedInt(sep->arg[7]); } if (sep->IsNumber(8)) { - minimum_delay = std::stoul(sep->arg[8]); + minimum_delay = Strings::ToUnsignedInt(sep->arg[8]); } target->CastToNPC()->AI_SetRoambox( @@ -176,18 +176,18 @@ void command_ai(Client *c, const Seperator *sep) sep->IsNumber(2) && sep->IsNumber(3) ) { - auto max_distance = std::stof(sep->arg[2]); - auto roam_distance_variance = std::stof(sep->arg[3]); + auto max_distance = Strings::ToFloat(sep->arg[2]); + auto roam_distance_variance = Strings::ToFloat(sep->arg[3]); uint32 delay = 2500; uint32 minimum_delay = 2500; if (sep->IsNumber(4)) { - delay = std::stoul(sep->arg[4]); + delay = Strings::ToUnsignedInt(sep->arg[4]); } if (sep->IsNumber(5)) { - minimum_delay = std::stoul(sep->arg[5]); + minimum_delay = Strings::ToUnsignedInt(sep->arg[5]); } target->CastToNPC()->AI_SetRoambox( @@ -233,7 +233,7 @@ void command_ai(Client *c, const Seperator *sep) } } else if (is_spells) { if (sep->IsNumber(2)) { - auto spell_list_id = std::stoul(sep->arg[2]); + auto spell_list_id = Strings::ToUnsignedInt(sep->arg[2]); if (spell_list_id >= 0) { target->CastToNPC()->AI_AddNPCSpells(spell_list_id); diff --git a/zone/gm_commands/appearance.cpp b/zone/gm_commands/appearance.cpp index 4f28fc50f..5e4113817 100755 --- a/zone/gm_commands/appearance.cpp +++ b/zone/gm_commands/appearance.cpp @@ -13,7 +13,7 @@ void command_appearance(Client *c, const Seperator *sep) if ((c->GetTarget())) { t = c->GetTarget(); } - t->SendAppearancePacket(atoi(sep->arg[1]), atoi(sep->arg[2])); + t->SendAppearancePacket(Strings::ToInt(sep->arg[1]), Strings::ToInt(sep->arg[2])); c->Message( Chat::White, "Sending appearance packet: target=%s, type=%s, value=%s", diff --git a/zone/gm_commands/appearanceeffects.cpp b/zone/gm_commands/appearanceeffects.cpp index 8a9a5eb44..d978c527e 100644 --- a/zone/gm_commands/appearanceeffects.cpp +++ b/zone/gm_commands/appearanceeffects.cpp @@ -2,43 +2,98 @@ void command_appearanceeffects(Client *c, const Seperator *sep) { - if (sep->arg[1][0] == '\0' || !strcasecmp(sep->arg[1], "help")) { - c->Message(Chat::White, "Syntax: #appearanceeffects [subcommand]."); - c->Message(Chat::White, "[view] Display all appearance effects saved to your target. #appearanceffects view"); - c->Message(Chat::White, "[set] Set an appearance effects saved to your target. #appearanceffects set [app_effectid] [slotid]"); - c->Message(Chat::White, "[remove] Remove all appearance effects saved to your target. #appearanceffects remove"); - } - - if (!strcasecmp(sep->arg[1], "view")) { - Mob* m_target = c->GetTarget(); - if (m_target) { - m_target->GetAppearenceEffects(); - } + const auto arguments = sep->argnum; + if (!arguments) { + c->Message(Chat::White, "Usage: #appearanceeffects help - Display appearance effects help menu"); + c->Message(Chat::White, "Usage: #appearanceeffects remove - Remove all appearance effects saved to your target"); + c->Message(Chat::White, "Usage: #appearanceeffects set [Effect ID] [Slot ID] - Set an appearance effect saved to your target"); + c->Message(Chat::White, "Usage: #appearanceeffects view - Display all appearance effects saved to your target"); return; } + const bool is_help = !strcasecmp(sep->arg[1], "help"); + const bool is_remove = !strcasecmp(sep->arg[1], "remove"); + const bool is_set = !strcasecmp(sep->arg[1], "set"); + const bool is_view = !strcasecmp(sep->arg[1], "view"); - if (!strcasecmp(sep->arg[1], "set")) { - int32 app_effectid = atof(sep->arg[2]); - int32 slot = atoi(sep->arg[3]); - - Mob* m_target = c->GetTarget(); - if (m_target) { - m_target->SendAppearanceEffect(app_effectid, 0, 0, 0, 0, nullptr, slot, 0, 0, 0, 0, 0, 0, 0, 0, 0); - c->Message(Chat::White, "Appearance Effect ID %i for slot %i has been set.", app_effectid, slot); - } + if (is_help) { + c->Message(Chat::White, "Usage: #appearanceeffects help - Display appearance effects help menu"); + c->Message(Chat::White, "Usage: #appearanceeffects remove - Remove all appearance effects saved to your target"); + c->Message(Chat::White, "Usage: #appearanceeffects set [Effect ID] [Slot ID] - Set an appearance effect saved to your target"); + c->Message(Chat::White, "Usage: #appearanceeffects view - Display all appearance effects saved to your target"); + return; } - if (!strcasecmp(sep->arg[1], "remove")) { - Mob* m_target = c->GetTarget(); - if (m_target) { - m_target->SendIllusionPacket(m_target->GetRace(), m_target->GetGender(), m_target->GetTexture(), m_target->GetHelmTexture(), - m_target->GetHairColor(), m_target->GetBeardColor(), m_target->GetEyeColor1(), m_target->GetEyeColor2(), - m_target->GetHairStyle(), m_target->GetLuclinFace(), m_target->GetBeard(), 0xFF, - m_target->GetDrakkinHeritage(), m_target->GetDrakkinTattoo(), m_target->GetDrakkinDetails(), m_target->GetSize(), false); - m_target->ClearAppearenceEffects(); - c->Message(Chat::White, "All Appearance Effects have been removed."); + Mob* t = c; + if (c->GetTarget()) { + t = c->GetTarget(); + } + + if (is_set) { + if (arguments != 3 || !sep->IsNumber(2) || !sep->IsNumber(3)) { + c->Message(Chat::White, "Usage: #appearanceeffects set [Effect ID] [Slot ID] - Set an appearance effect saved to your target"); + return; } - return; + + const auto effect_id = Strings::ToUnsignedInt(sep->arg[2]); + const auto slot_id = Strings::ToUnsignedInt(sep->arg[3]); + + t->SendAppearanceEffect( + effect_id, + 0, + 0, + 0, + 0, + nullptr, + slot_id, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ); + c->Message( + Chat::White, + fmt::format( + "Appearance Effect ID {} in slot ID {} has been set for {}.", + effect_id, + slot_id, + c->GetTargetDescription(t, TargetDescriptionType::LCSelf) + ).c_str() + ); + } else if (is_remove) { + t->SendIllusionPacket( + t->GetRace(), + t->GetGender(), + t->GetTexture(), + t->GetHelmTexture(), + t->GetHairColor(), + t->GetBeardColor(), + t->GetEyeColor1(), + t->GetEyeColor2(), + t->GetHairStyle(), + t->GetLuclinFace(), + t->GetBeard(), + 0xFF, + t->GetDrakkinHeritage(), + t->GetDrakkinTattoo(), + t->GetDrakkinDetails(), + t->GetSize(), + false + ); + t->ClearAppearenceEffects(); + c->Message( + Chat::White, + fmt::format( + "Appearance Effects have been removed for {}.", + c->GetTargetDescription(t, TargetDescriptionType::LCSelf) + ).c_str() + ); + } else if (is_view) { + t->ListAppearanceEffects(c); } } diff --git a/zone/gm_commands/bugs.cpp b/zone/gm_commands/bugs.cpp index 44e49686e..1f3e7a771 100755 --- a/zone/gm_commands/bugs.cpp +++ b/zone/gm_commands/bugs.cpp @@ -39,7 +39,7 @@ void command_bugs(Client *c, const Seperator *sep) return; } - auto bug_id = std::stoul(sep->arg[2]); + auto bug_id = Strings::ToUnsignedInt(sep->arg[2]); auto r = BugReportsRepository::FindOne(content_db, bug_id); if (!r.id) { @@ -80,7 +80,7 @@ void command_bugs(Client *c, const Seperator *sep) return; } - auto bug_id = std::stoul(sep->arg[2]); + auto bug_id = Strings::ToUnsignedInt(sep->arg[2]); auto deleted_count = BugReportsRepository::DeleteOne(content_db, bug_id); if (!deleted_count) { c->Message( @@ -109,7 +109,7 @@ void command_bugs(Client *c, const Seperator *sep) return; } - auto bug_id = std::stoul(sep->arg[2]); + auto bug_id = Strings::ToUnsignedInt(sep->arg[2]); auto bug_review = sep->argplus[3]; auto r = BugReportsRepository::FindOne(content_db, bug_id); @@ -203,7 +203,7 @@ void command_bugs(Client *c, const Seperator *sep) return; } - auto bug_id = std::stoul(sep->arg[2]); + auto bug_id = Strings::ToUnsignedInt(sep->arg[2]); auto r = BugReportsRepository::FindOne(content_db, bug_id); if (!r.id) { diff --git a/zone/gm_commands/camerashake.cpp b/zone/gm_commands/camerashake.cpp index 9c2e8a5f0..dc6adf799 100755 --- a/zone/gm_commands/camerashake.cpp +++ b/zone/gm_commands/camerashake.cpp @@ -11,8 +11,8 @@ void command_camerashake(Client *c, const Seperator *sep) return; } - auto duration = std::stoi(sep->arg[1]); - auto intensity = std::stoi(sep->arg[2]); + auto duration = Strings::ToInt(sep->arg[1]); + auto intensity = Strings::ToInt(sep->arg[2]); auto pack = new ServerPacket(ServerOP_CameraShake, sizeof(ServerCameraShake_Struct)); ServerCameraShake_Struct *camera_shake = (ServerCameraShake_Struct *) pack->pBuffer; diff --git a/zone/gm_commands/castspell.cpp b/zone/gm_commands/castspell.cpp index ef0be063d..bbe134f04 100755 --- a/zone/gm_commands/castspell.cpp +++ b/zone/gm_commands/castspell.cpp @@ -19,7 +19,7 @@ void command_castspell(Client *c, const Seperator *sep) ); } else { - uint16 spell_id = std::stoul(sep->arg[1]); + uint16 spell_id = Strings::ToUnsignedInt(sep->arg[1]); if (CastRestrictedSpell(spell_id) && c->Admin() < commandCastSpecials) { c->Message(Chat::Red, "Unable to cast spell."); @@ -30,8 +30,8 @@ void command_castspell(Client *c, const Seperator *sep) else { bool instant_cast = (c->Admin() >= commandInstacast ? true : false); if (instant_cast && sep->IsNumber(2)) { - instant_cast = std::stoi(sep->arg[2]) ? true : false; - c->Message(Chat::White, fmt::format("{}", std::stoi(sep->arg[2])).c_str()); + instant_cast = Strings::ToInt(sep->arg[2]) ? true : false; + c->Message(Chat::White, fmt::format("{}", Strings::ToInt(sep->arg[2])).c_str()); } if (c->Admin() >= commandInstacast && instant_cast) { diff --git a/zone/gm_commands/chat.cpp b/zone/gm_commands/chat.cpp index 30bbe11d7..c72f7475c 100755 --- a/zone/gm_commands/chat.cpp +++ b/zone/gm_commands/chat.cpp @@ -11,7 +11,7 @@ void command_chat(Client *c, const Seperator *sep) return; } - auto channel_id = static_cast(std::stoul(sep->arg[1])); + auto channel_id = static_cast(Strings::ToUnsignedInt(sep->arg[1])); std::string message = sep->argplus[2]; if (!worldserver.SendChannelMessage(0, 0, channel_id, 0, 0, 100, message.c_str())) { c->Message(Chat::White, "World server is disconnected."); diff --git a/zone/gm_commands/corpse.cpp b/zone/gm_commands/corpse.cpp index d1176b599..2c3eae8b3 100755 --- a/zone/gm_commands/corpse.cpp +++ b/zone/gm_commands/corpse.cpp @@ -81,7 +81,7 @@ void command_corpse(Client *c, const Seperator *sep) auto deleted_string = ( corpses_deleted ? fmt::format( - "{} Player corpse{} deleted.", + "{} Player corpse{} deleted.", corpses_deleted, corpses_deleted != 1 ? "s" : "" ) : @@ -104,7 +104,7 @@ void command_corpse(Client *c, const Seperator *sep) } if ( - target->IsNPCCorpse() || + target->IsNPCCorpse() || c->Admin() >= commandEditPlayerCorpses ) { c->Message( @@ -116,7 +116,7 @@ void command_corpse(Client *c, const Seperator *sep) ).c_str() ); target->CastToCorpse()->Delete(); - } + } } else if (is_list_npc) { entity_list.ListNPCCorpses(c); } else if (is_list_player) { @@ -150,7 +150,7 @@ void command_corpse(Client *c, const Seperator *sep) return; } - auto character_id = std::stoi(sep->arg[2]); + auto character_id = Strings::ToInt(sep->arg[2]); c->Message( Chat::White, fmt::format( @@ -174,7 +174,7 @@ void command_corpse(Client *c, const Seperator *sep) c->Message(Chat::White, "Your status is not high enough to reset looter on a player corpse."); return; } - + target->CastToCorpse()->ResetLooter(); c->Message( Chat::White, @@ -196,7 +196,7 @@ void command_corpse(Client *c, const Seperator *sep) } if ( - target->IsNPCCorpse() || + target->IsNPCCorpse() || c->Admin() >= commandEditPlayerCorpses ) { target->CastToCorpse()->RemoveCash(); @@ -219,7 +219,7 @@ void command_corpse(Client *c, const Seperator *sep) c->Message(Chat::White, "Your status is not high enough to inspect the loot of a player corpse."); return; } - + target->CastToCorpse()->QueryLoot(c); } else if (is_lock) { if (!target || !target->IsCorpse()) { @@ -271,7 +271,7 @@ void command_corpse(Client *c, const Seperator *sep) bool bury_corpse = ( sep->IsNumber(2) ? ( - std::stoi(sep->arg[2]) != 0 ? + Strings::ToInt(sep->arg[2]) != 0 ? true : false ) : @@ -302,7 +302,7 @@ void command_corpse(Client *c, const Seperator *sep) bool bury_corpse = ( sep->IsNumber(2) ? ( - std::stoi(sep->arg[2]) != 0 ? + Strings::ToInt(sep->arg[2]) != 0 ? true : false ) : diff --git a/zone/gm_commands/countitem.cpp b/zone/gm_commands/countitem.cpp index c65e9c46f..306f48942 100644 --- a/zone/gm_commands/countitem.cpp +++ b/zone/gm_commands/countitem.cpp @@ -18,8 +18,8 @@ void command_countitem(Client *c, const Seperator *sep) ) { target = c->GetTarget(); } - - auto item_id = std::stoul(sep->arg[1]); + + auto item_id = Strings::ToUnsignedInt(sep->arg[1]); if (!database.GetItem(item_id)) { c->Message( Chat::White, diff --git a/zone/gm_commands/damage.cpp b/zone/gm_commands/damage.cpp index fbe1242d5..2044cc483 100755 --- a/zone/gm_commands/damage.cpp +++ b/zone/gm_commands/damage.cpp @@ -14,6 +14,6 @@ void command_damage(Client *c, const Seperator *sep) return; } - int64 damage = std::stoll(sep->arg[1], nullptr, 10); + const auto damage = Strings::ToBigInt(sep->arg[1]); target->Damage(c, damage, SPELL_UNKNOWN, EQ::skills::SkillHandtoHand, false); } diff --git a/zone/gm_commands/databuckets.cpp b/zone/gm_commands/databuckets.cpp index 48ad596f2..bcf6b0669 100755 --- a/zone/gm_commands/databuckets.cpp +++ b/zone/gm_commands/databuckets.cpp @@ -16,7 +16,7 @@ void command_databuckets(Client *c, const Seperator *sep) break; } if (strcasecmp(sep->arg[i], "limit") == 0) { - limit = (uint8) atoi(sep->arg[i + 1]); + limit = (uint8) Strings::ToInt(sep->arg[i + 1]); continue; } } @@ -46,7 +46,7 @@ void command_databuckets(Client *c, const Seperator *sep) "Value" ""; for (auto row = results.begin(); row != results.end(); ++row) { - auto id = static_cast(atoi(row[0])); + auto id = static_cast(Strings::ToInt(row[0])); std::string key = row[1]; std::string value = row[2]; std::string expires = row[3]; diff --git a/zone/gm_commands/date.cpp b/zone/gm_commands/date.cpp index 0154f233f..08cde4e60 100755 --- a/zone/gm_commands/date.cpp +++ b/zone/gm_commands/date.cpp @@ -16,12 +16,12 @@ void command_date(Client *c, const Seperator *sep) TimeOfDay_Struct eq_time; zone->zone_time.GetCurrentEQTimeOfDay(time(0), &eq_time); - auto year = static_cast(std::stoul(sep->arg[1])); - auto month = static_cast(std::stoul(sep->arg[2])); - auto day = static_cast(std::stoul(sep->arg[3])); + auto year = static_cast(Strings::ToUnsignedInt(sep->arg[1])); + auto month = static_cast(Strings::ToUnsignedInt(sep->arg[2])); + auto day = static_cast(Strings::ToUnsignedInt(sep->arg[3])); - auto hour = !sep->IsNumber(4) ? eq_time.hour : static_cast(std::stoul(sep->arg[4]) + 1); - auto minute = !sep->IsNumber(5) ? eq_time.minute : static_cast(std::stoul(sep->arg[5])); + auto hour = !sep->IsNumber(4) ? eq_time.hour : static_cast(Strings::ToUnsignedInt(sep->arg[4]) + 1); + auto minute = !sep->IsNumber(5) ? eq_time.minute : static_cast(Strings::ToUnsignedInt(sep->arg[5])); c->Message( Chat::White, diff --git a/zone/gm_commands/dbspawn2.cpp b/zone/gm_commands/dbspawn2.cpp index aa5740b32..e52419f28 100755 --- a/zone/gm_commands/dbspawn2.cpp +++ b/zone/gm_commands/dbspawn2.cpp @@ -16,12 +16,12 @@ void command_dbspawn2(Client *c, const Seperator *sep) auto position = c->GetPosition(); - auto spawngroup_id = std::stoul(sep->arg[1]); - auto respawn = std::stoul(sep->arg[2]); - auto variance = std::stoul(sep->arg[3]); + auto spawngroup_id = Strings::ToUnsignedInt(sep->arg[1]); + auto respawn = Strings::ToUnsignedInt(sep->arg[2]); + auto variance = Strings::ToUnsignedInt(sep->arg[3]); - auto condition_id = sep->IsNumber(4) ? static_cast(std::stoul(sep->arg[4])) : static_cast(0); - auto condition_minimum = sep->IsNumber(5) ? static_cast(std::stoul(sep->arg[5])) : static_cast(0); + auto condition_id = sep->IsNumber(4) ? static_cast(Strings::ToUnsignedInt(sep->arg[4])) : static_cast(0); + auto condition_minimum = sep->IsNumber(5) ? static_cast(Strings::ToUnsignedInt(sep->arg[5])) : static_cast(0); if (!database.CreateSpawn2( c, diff --git a/zone/gm_commands/delacct.cpp b/zone/gm_commands/delacct.cpp index ff3a10edd..a4602a9a3 100755 --- a/zone/gm_commands/delacct.cpp +++ b/zone/gm_commands/delacct.cpp @@ -13,7 +13,7 @@ void command_delacct(Client *c, const Seperator *sep) std::string account_name; if (sep->IsNumber(1)) { - account_id = std::stoul(sep->arg[1]); + account_id = Strings::ToUnsignedInt(sep->arg[1]); auto a = AccountRepository::FindOne(content_db, account_id); if (!a.id) { c->Message( diff --git a/zone/gm_commands/delpetition.cpp b/zone/gm_commands/delpetition.cpp index 556e33866..3630a9b3b 100755 --- a/zone/gm_commands/delpetition.cpp +++ b/zone/gm_commands/delpetition.cpp @@ -7,14 +7,14 @@ void command_delpetition(Client *c, const Seperator *sep) return; } - c->Message(Chat::Red, "Attempting to delete petition number: %i", atoi(sep->argplus[1])); - std::string query = StringFormat("DELETE FROM petitions WHERE petid = %i", atoi(sep->argplus[1])); + c->Message(Chat::Red, "Attempting to delete petition number: %i", Strings::ToInt(sep->argplus[1])); + std::string query = StringFormat("DELETE FROM petitions WHERE petid = %i", Strings::ToInt(sep->argplus[1])); auto results = database.QueryDatabase(query); if (!results.Success()) { return; } - LogInfo("Delete petition request from [{}], petition number:", c->GetName(), atoi(sep->argplus[1])); + LogInfo("Delete petition request from [{}], petition number:", c->GetName(), Strings::ToInt(sep->argplus[1])); } diff --git a/zone/gm_commands/depop.cpp b/zone/gm_commands/depop.cpp index a2bb85676..1b69fb8f8 100755 --- a/zone/gm_commands/depop.cpp +++ b/zone/gm_commands/depop.cpp @@ -11,7 +11,7 @@ void command_depop(Client *c, const Seperator *sep) auto start_spawn_timer = false; if (sep->IsNumber(1)) { - start_spawn_timer = std::stoi(sep->arg[1]) ? true : false; + start_spawn_timer = Strings::ToInt(sep->arg[1]) ? true : false; } c->Message( diff --git a/zone/gm_commands/depopzone.cpp b/zone/gm_commands/depopzone.cpp index e24c45f46..ef90d7c04 100755 --- a/zone/gm_commands/depopzone.cpp +++ b/zone/gm_commands/depopzone.cpp @@ -5,7 +5,7 @@ void command_depopzone(Client *c, const Seperator *sep) auto start_spawn_timers = false; if (sep->IsNumber(1)) { - start_spawn_timers = std::stoi(sep->arg[1]) ? true : false; + start_spawn_timers = Strings::ToInt(sep->arg[1]) ? true : false; } zone->Depop(start_spawn_timers); diff --git a/zone/gm_commands/disablerecipe.cpp b/zone/gm_commands/disablerecipe.cpp index b09a6317c..f57fa97d0 100755 --- a/zone/gm_commands/disablerecipe.cpp +++ b/zone/gm_commands/disablerecipe.cpp @@ -8,8 +8,8 @@ void command_disablerecipe(Client *c, const Seperator *sep) return; } - auto recipe_id = std::stoul(sep->arg[1]); - if (!recipe_id) { + auto recipe_id = Strings::ToUnsignedInt(sep->arg[1]); + if (!recipe_id) { c->Message(Chat::White, "Usage: #disablerecipe [Recipe ID]"); return; } diff --git a/zone/gm_commands/doanim.cpp b/zone/gm_commands/doanim.cpp index ec57650ff..1391e54b3 100755 --- a/zone/gm_commands/doanim.cpp +++ b/zone/gm_commands/doanim.cpp @@ -19,7 +19,7 @@ void command_doanim(Client *c, const Seperator *sep) auto animation_speed = 0; if (sep->IsNumber(1)) { - animation_id = std::stoi(sep->arg[1]); + animation_id = Strings::ToInt(sep->arg[1]); const auto& a = animation_names_map.find(animation_id); if (a != animation_names_map.end()) { @@ -69,7 +69,7 @@ void command_doanim(Client *c, const Seperator *sep) } if (sep->IsNumber(2)) { - animation_speed = std::stoi(sep->arg[2]); + animation_speed = Strings::ToInt(sep->arg[2]); } const auto speed_message = ( diff --git a/zone/gm_commands/door_manipulation.cpp b/zone/gm_commands/door_manipulation.cpp index c0e7c48ba..e9c6a4de2 100644 --- a/zone/gm_commands/door_manipulation.cpp +++ b/zone/gm_commands/door_manipulation.cpp @@ -1,6 +1,7 @@ #include "door_manipulation.h" #include "../doors.h" #include "../../common/misc_functions.h" +#include "../../common/strings.h" #define MAX_CLIENT_MESSAGE_LENGTH 2000 @@ -54,23 +55,23 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep) float set_size = 0.0f; if (arg2 == move_x_action) { - x_move = std::atof(arg3.c_str()); + x_move = Strings::ToFloat(arg3.c_str()); } if (arg2 == move_y_action) { - y_move = std::atof(arg3.c_str()); + y_move = Strings::ToFloat(arg3.c_str()); } if (arg2 == move_z_action) { - z_move = std::atof(arg3.c_str()); + z_move = Strings::ToFloat(arg3.c_str()); } if (arg2 == move_h_action) { - h_move = std::atof(arg3.c_str()); + h_move = Strings::ToFloat(arg3.c_str()); } if (arg2 == set_size_action) { - set_size = std::atof(arg3.c_str()); + set_size = Strings::ToFloat(arg3.c_str()); } door->SetLocation( @@ -187,7 +188,7 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep) std::vector set_size_options_negative; std::vector xyz_values = { - ".1", "1", "5", "10", "25", "50", "100" + "0.1", "1", "5", "10", "25", "50", "100" }; // build positive options x/y/z @@ -369,7 +370,7 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep) if (arg1 == "opentype" && !arg2.empty() && Strings::IsNumber(arg2)) { Doors *door = entity_list.GetDoorsByID(c->GetDoorToolEntityId()); if (door) { - door->SetOpenType(std::atoi(arg2.c_str())); + door->SetOpenType(Strings::ToInt(arg2.c_str())); } } @@ -377,7 +378,7 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep) if (arg1 == "setincline" && !arg2.empty() && Strings::IsNumber(arg2)) { Doors *door = entity_list.GetDoorsByID(c->GetDoorToolEntityId()); if (door) { - door->SetIncline(std::atoi(arg2.c_str())); + door->SetIncline(Strings::ToInt(arg2.c_str())); } } @@ -385,7 +386,7 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep) if (arg1 == "setinvertstate" && !arg2.empty() && Strings::IsNumber(arg2)) { Doors *door = entity_list.GetDoorsByID(c->GetDoorToolEntityId()); if (door) { - door->SetInvertState(std::atoi(arg2.c_str())); + door->SetInvertState(Strings::ToInt(arg2.c_str())); } } @@ -402,7 +403,7 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep) if (arg1 == "setinclineinc" && !arg2.empty() && Strings::IsNumber(arg2)) { Doors *door = entity_list.GetDoorsByID(c->GetDoorToolEntityId()); if (door) { - door->SetIncline(door->GetIncline() + std::atoi(arg2.c_str())); + door->SetIncline(door->GetIncline() + Strings::ToInt(arg2.c_str())); } } diff --git a/zone/gm_commands/dye.cpp b/zone/gm_commands/dye.cpp index 195792f16..4f2d39c1d 100755 --- a/zone/gm_commands/dye.cpp +++ b/zone/gm_commands/dye.cpp @@ -48,23 +48,23 @@ void command_dye(Client *c, const Seperator *sep) } if (arguments >= 1 && sep->IsNumber(1)) { - slot = atoi(sep->arg[1]); + slot = Strings::ToInt(sep->arg[1]); } if (arguments >= 2 && sep->IsNumber(2)) { - red = atoi(sep->arg[2]); + red = Strings::ToInt(sep->arg[2]); } if (arguments >= 3 && sep->IsNumber(3)) { - green = atoi(sep->arg[3]); + green = Strings::ToInt(sep->arg[3]); } if (arguments >= 4 && sep->IsNumber(4)) { - blue = atoi(sep->arg[4]); + blue = Strings::ToInt(sep->arg[4]); } if (arguments >= 5 && sep->IsNumber(5)) { - use_tint = atoi(sep->arg[5]); + use_tint = Strings::ToInt(sep->arg[5]); } if (RuleB(Command, DyeCommandRequiresDyes)) { diff --git a/zone/gm_commands/editmassrespawn.cpp b/zone/gm_commands/editmassrespawn.cpp index 32e29cd32..a520ed6cc 100755 --- a/zone/gm_commands/editmassrespawn.cpp +++ b/zone/gm_commands/editmassrespawn.cpp @@ -14,7 +14,7 @@ void command_editmassrespawn(Client *c, const Seperator *sep) int change_respawn_seconds = 0; if (sep->arg[2] && sep->IsNumber(2)) { - change_respawn_seconds = atoi(sep->arg[2]); + change_respawn_seconds = Strings::ToInt(sep->arg[2]); } bool change_apply = false; diff --git a/zone/gm_commands/emote.cpp b/zone/gm_commands/emote.cpp index f04e2fa3f..761f1fd12 100755 --- a/zone/gm_commands/emote.cpp +++ b/zone/gm_commands/emote.cpp @@ -22,7 +22,7 @@ void command_emote(Client *c, const Seperator *sep) bool is_zone = !strcasecmp(sep->arg[1], "zone"); const std::string emote_message = sep->argplus[3]; - const auto emote_type = std::stoul(sep->arg[2]); + const auto emote_type = Strings::ToUnsignedInt(sep->arg[2]); if (is_zone) { if (!Strings::Contains(emote_message, "^")) { diff --git a/zone/gm_commands/emotesearch.cpp b/zone/gm_commands/emotesearch.cpp index 5b8e9d09e..209f46c71 100755 --- a/zone/gm_commands/emotesearch.cpp +++ b/zone/gm_commands/emotesearch.cpp @@ -21,7 +21,7 @@ void command_emotesearch(Client *c, const Seperator *sep) while (iterator.MoreElements()) { auto &e = iterator.GetData(); auto current_text = Strings::ToLower(e->text); - + if (Strings::Contains(current_text, Strings::ToLower(search_criteria))) { c->Message( Chat::White, @@ -64,8 +64,8 @@ void command_emotesearch(Client *c, const Seperator *sep) iterator.Advance(); } } else { - auto emote_id = std::stoul(search_criteria); - + auto emote_id = Strings::ToUnsignedInt(search_criteria); + LinkedListIterator iterator(zone->NPCEmoteList); iterator.Reset(); while (iterator.MoreElements()) { diff --git a/zone/gm_commands/enablerecipe.cpp b/zone/gm_commands/enablerecipe.cpp index 088907a75..60c8fefbe 100755 --- a/zone/gm_commands/enablerecipe.cpp +++ b/zone/gm_commands/enablerecipe.cpp @@ -8,8 +8,8 @@ void command_enablerecipe(Client *c, const Seperator *sep) return; } - auto recipe_id = std::stoul(sep->arg[1]); - if (!recipe_id) { + auto recipe_id = Strings::ToUnsignedInt(sep->arg[1]); + if (!recipe_id) { c->Message(Chat::White, "Usage: #enablerecipe [Recipe ID]"); return; } diff --git a/zone/gm_commands/equipitem.cpp b/zone/gm_commands/equipitem.cpp deleted file mode 100755 index 7ffe8ad84..000000000 --- a/zone/gm_commands/equipitem.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "../client.h" - -void command_equipitem(Client *c, const Seperator *sep) -{ - uint32 slot_id = atoi(sep->arg[1]); - if (sep->IsNumber(1) && (slot_id >= EQ::invslot::EQUIPMENT_BEGIN && slot_id <= EQ::invslot::EQUIPMENT_END)) { - const EQ::ItemInstance *from_inst = c->GetInv().GetItem(EQ::invslot::slotCursor); - const EQ::ItemInstance *to_inst = c->GetInv().GetItem(slot_id); // added (desync issue when forcing stack to stack) - bool partialmove = false; - int16 movecount; - - if (from_inst && from_inst->IsClassCommon()) { - auto outapp = new EQApplicationPacket(OP_MoveItem, sizeof(MoveItem_Struct)); - MoveItem_Struct *mi = (MoveItem_Struct *) outapp->pBuffer; - mi->from_slot = EQ::invslot::slotCursor; - mi->to_slot = slot_id; - // mi->number_in_stack = from_inst->GetCharges(); // replaced with con check for stacking - - // crude stackable check to only 'move' the difference count on client instead of entire stack when applicable - if (to_inst && to_inst->IsStackable() && - (to_inst->GetItem()->ID == from_inst->GetItem()->ID) && - (to_inst->GetCharges() < to_inst->GetItem()->StackSize) && - (from_inst->GetCharges() > to_inst->GetItem()->StackSize - to_inst->GetCharges())) { - movecount = to_inst->GetItem()->StackSize - to_inst->GetCharges(); - mi->number_in_stack = (uint32) movecount; - partialmove = true; - } - else { - mi->number_in_stack = from_inst->GetCharges(); - } - - // Save move changes - // Added conditional check to packet send..would have sent change even on a swap failure..whoops! - - if (partialmove) { // remove this con check if someone can figure out removing charges from cursor stack issue below - // mi->number_in_stack is always from_inst->GetCharges() when partialmove is false - c->Message(Chat::Red, "Error: Partial stack added to existing stack exceeds allowable stacksize"); - safe_delete(outapp); - return; - } - else if (c->SwapItem(mi)) { - c->FastQueuePacket(&outapp); - - // if the below code is still needed..just send an an item trade packet to each slot..it should overwrite the client instance - - // below code has proper logic, but client does not like to have cursor charges changed - // (we could delete the cursor item and resend, but issues would arise if there are queued items) - //if (partialmove) { - // EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_DeleteItem, sizeof(DeleteItem_Struct)); - // DeleteItem_Struct* di = (DeleteItem_Struct*)outapp2->pBuffer; - // di->from_slot = SLOT_CURSOR; - // di->to_slot = 0xFFFFFFFF; - // di->number_in_stack = 0xFFFFFFFF; - - // c->Message(Chat::White, "Deleting %i charges from stack", movecount); // debug line..delete - - // for (int16 deletecount=0; deletecount < movecount; deletecount++) - // have to use 'movecount' because mi->number_in_stack is 'ENCODED' at this point (i.e., 99 charges returns 22...) - // c->QueuePacket(outapp2); - - // safe_delete(outapp2); - //} - } - else { - c->Message(Chat::Red, "Error: Unable to equip current item"); - } - safe_delete(outapp); - - // also send out a wear change packet? - } - else if (from_inst == nullptr) { - c->Message(Chat::Red, "Error: There is no item on your cursor"); - } - else { - c->Message(Chat::Red, "Error: Item on your cursor cannot be equipped"); - } - } - else { - c->Message(Chat::White, "Usage: #equipitem slotid[0-21] - equips the item on your cursor to the position"); - } -} - diff --git a/zone/gm_commands/faction.cpp b/zone/gm_commands/faction.cpp index 87a8ef5aa..b7ca12a65 100755 --- a/zone/gm_commands/faction.cpp +++ b/zone/gm_commands/faction.cpp @@ -53,7 +53,7 @@ void command_faction(Client *c, const Seperator *sep) uint32 found_count = 0; for (auto row : results) { uint32 faction_number = (found_count + 1); - auto faction_id = std::stoul(row[0]); + auto faction_id = Strings::ToUnsignedInt(row[0]); std::string faction_name = row[1]; std::string faction_value = row[2]; std::string reset_link = Saylink::Silent( @@ -107,7 +107,7 @@ void command_faction(Client *c, const Seperator *sep) ) ) { uint32 character_id = target->CharacterID(); - uint32 faction_id = std::stoul(faction_filter.c_str()); + uint32 faction_id = Strings::ToUnsignedInt(faction_filter.c_str()); if (target->ReloadCharacterFaction(target, faction_id, character_id)) { c->Message( Chat::White, diff --git a/zone/gm_commands/faction_association.cpp b/zone/gm_commands/faction_association.cpp index 47410f248..a39f25dbc 100644 --- a/zone/gm_commands/faction_association.cpp +++ b/zone/gm_commands/faction_association.cpp @@ -14,5 +14,5 @@ void command_faction_association(Client *c, const Seperator *sep) target = c->GetTarget()->CastToClient(); } - target->RewardFaction(atoi(sep->arg[1]), atoi(sep->arg[2])); + target->RewardFaction(Strings::ToInt(sep->arg[1]), Strings::ToInt(sep->arg[2])); } diff --git a/zone/gm_commands/feature.cpp b/zone/gm_commands/feature.cpp index 55b6648d9..835ddd91f 100644 --- a/zone/gm_commands/feature.cpp +++ b/zone/gm_commands/feature.cpp @@ -116,11 +116,11 @@ void command_feature(Client *c, const Seperator *sep) float value_changed = 0.0f; if (is_beard) { - face.beard = static_cast(std::stoul(sep->arg[2])); + face.beard = static_cast(Strings::ToUnsignedInt(sep->arg[2])); feature_changed = "Beard"; value_changed = face.beard; } else if (is_beard_color) { - face.beardcolor = static_cast(std::stoul(sep->arg[2])); + face.beardcolor = static_cast(Strings::ToUnsignedInt(sep->arg[2])); feature_changed = "Beard Color"; value_changed = face.beardcolor; } else if (is_details) { @@ -129,31 +129,31 @@ void command_feature(Client *c, const Seperator *sep) return; } - face.drakkin_details = static_cast(std::stoul(sep->arg[2])); + face.drakkin_details = static_cast(Strings::ToUnsignedInt(sep->arg[2])); feature_changed = "Drakkin Details"; value_changed = static_cast(face.drakkin_details); } else if (is_eyes) { - face.eyecolor1 = static_cast(std::stoul(sep->arg[2])); + face.eyecolor1 = static_cast(Strings::ToUnsignedInt(sep->arg[2])); feature_changed = "Eyes"; value_changed = face.eyecolor1; // eyecolor2 isn't used } else if (is_face) { - face.face = static_cast(std::stoul(sep->arg[2])); + face.face = static_cast(Strings::ToUnsignedInt(sep->arg[2])); feature_changed = "Face"; value_changed = face.face; } else if (is_gender) { - gender = static_cast(std::stoul(sep->arg[2])); + gender = static_cast(Strings::ToUnsignedInt(sep->arg[2])); feature_changed = "Gender"; value_changed = gender; } else if (is_hair) { - face.hairstyle = static_cast(std::stoul(sep->arg[2])); + face.hairstyle = static_cast(Strings::ToUnsignedInt(sep->arg[2])); feature_changed = "Hair"; value_changed = face.hairstyle; } else if (is_hair_color) { - face.haircolor = static_cast(std::stoul(sep->arg[2])); + face.haircolor = static_cast(Strings::ToUnsignedInt(sep->arg[2])); feature_changed = "Hair Color"; value_changed = face.haircolor; } else if (is_helm) { - helm_texture = static_cast(std::stoul(sep->arg[2])); + helm_texture = static_cast(Strings::ToUnsignedInt(sep->arg[2])); feature_changed = "Helmet Texture"; value_changed = helm_texture; } else if (is_heritage) { @@ -162,11 +162,11 @@ void command_feature(Client *c, const Seperator *sep) return; } - face.drakkin_heritage = static_cast(std::stoul(sep->arg[2])); + face.drakkin_heritage = static_cast(Strings::ToUnsignedInt(sep->arg[2])); feature_changed = "Drakkin Heritage"; value_changed = static_cast(face.drakkin_heritage); } else if (is_race) { - race = static_cast(std::stoul(sep->arg[2])); + race = static_cast(Strings::ToUnsignedInt(sep->arg[2])); feature_changed = "Race"; value_changed = race; } else if (is_size) { @@ -174,11 +174,11 @@ void command_feature(Client *c, const Seperator *sep) if (is_size_alias) { c->Message(Chat::White, "Usage: #feature size [Size] - Change your or your target's Size temporarily (Valid values are 0 to 255, decimal increments are allowed.)"); if (sep->arg[1] && Strings::IsFloat(sep->arg[1])) { - size = std::stof(sep->arg[1]); + size = Strings::ToFloat(sep->arg[1]); } } else { - size = std::stof(sep->arg[2]); + size = Strings::ToFloat(sep->arg[2]); } if (size < 0 || size > 255) { @@ -194,11 +194,11 @@ void command_feature(Client *c, const Seperator *sep) return; } - face.drakkin_tattoo = static_cast(std::stoul(sep->arg[2])); + face.drakkin_tattoo = static_cast(Strings::ToUnsignedInt(sep->arg[2])); feature_changed = "Drakkin Tattoos"; value_changed = static_cast(face.drakkin_tattoo); } else if (is_texture) { - texture = static_cast(std::stoul(sep->arg[2])); + texture = static_cast(Strings::ToUnsignedInt(sep->arg[2])); feature_changed = "Texture"; value_changed = texture; } diff --git a/zone/gm_commands/findaa.cpp b/zone/gm_commands/findaa.cpp index c5d15437c..3a0640153 100755 --- a/zone/gm_commands/findaa.cpp +++ b/zone/gm_commands/findaa.cpp @@ -9,7 +9,7 @@ void command_findaa(Client *c, const Seperator *sep) } if (sep->IsNumber(1)) { - int aa_id = std::stoi(sep->arg[1]); + int aa_id = Strings::ToInt(sep->arg[1]); auto aa_name = zone->GetAAName(aa_id); if (!aa_name.empty()) { c->Message( @@ -35,7 +35,7 @@ void command_findaa(Client *c, const Seperator *sep) std::map ordered_aas; for (const auto& a : zone->aa_abilities) { - ordered_aas[a.second.get()->id] = a.second.get()->name; + ordered_aas[a.second.get()->first->id] = a.second.get()->name; } int found_count = 0; diff --git a/zone/gm_commands/findcharacter.cpp b/zone/gm_commands/findcharacter.cpp index 811978af5..fccd7bf20 100755 --- a/zone/gm_commands/findcharacter.cpp +++ b/zone/gm_commands/findcharacter.cpp @@ -10,7 +10,7 @@ void command_findcharacter(Client *c, const Seperator *sep) } if (sep->IsNumber(1)) { - const auto character_id = std::stoul(sep->arg[1]); + const auto character_id = Strings::ToUnsignedInt(sep->arg[1]); const auto& e = CharacterDataRepository::FindOne(content_db, character_id); if (!e.id) { diff --git a/zone/gm_commands/findclass.cpp b/zone/gm_commands/findclass.cpp index 62e484e81..a1ddaa18f 100755 --- a/zone/gm_commands/findclass.cpp +++ b/zone/gm_commands/findclass.cpp @@ -9,7 +9,7 @@ void command_findclass(Client *c, const Seperator *sep) } if (sep->IsNumber(1)) { - int class_id = std::stoi(sep->arg[1]); + int class_id = Strings::ToInt(sep->arg[1]); if (class_id >= WARRIOR && class_id <= MERCENARY_MASTER) { std::string class_name = GetClassIDName(class_id); c->Message( diff --git a/zone/gm_commands/findfaction.cpp b/zone/gm_commands/findfaction.cpp index 8038a2e00..a6d75874d 100755 --- a/zone/gm_commands/findfaction.cpp +++ b/zone/gm_commands/findfaction.cpp @@ -10,7 +10,7 @@ void command_findfaction(Client *c, const Seperator *sep) } if (sep->IsNumber(1)) { - int faction_id = std::stoi(sep->arg[1]); + int faction_id = Strings::ToInt(sep->arg[1]); auto faction_name = content_db.GetFactionName(faction_id); if (!faction_name.empty()) { c->Message( diff --git a/zone/gm_commands/findrace.cpp b/zone/gm_commands/findrace.cpp index 6e02a7041..b0bee13c1 100755 --- a/zone/gm_commands/findrace.cpp +++ b/zone/gm_commands/findrace.cpp @@ -9,7 +9,7 @@ void command_findrace(Client *c, const Seperator *sep) } if (sep->IsNumber(1)) { - auto race_id = static_cast(std::stoul(sep->arg[1])); + auto race_id = static_cast(Strings::ToUnsignedInt(sep->arg[1])); std::string race_name = GetRaceIDName(race_id); if ( race_id >= RACE_HUMAN_1 && diff --git a/zone/gm_commands/findrecipe.cpp b/zone/gm_commands/findrecipe.cpp index fdcdb9169..4b3593ea9 100755 --- a/zone/gm_commands/findrecipe.cpp +++ b/zone/gm_commands/findrecipe.cpp @@ -11,7 +11,7 @@ void command_findrecipe(Client *c, const Seperator *sep) } if (sep->IsNumber(1)) { - auto recipe_id = static_cast(std::stoul(sep->arg[1])); + auto recipe_id = static_cast(Strings::ToUnsignedInt(sep->arg[1])); auto r = TradeskillRecipeRepository::GetWhere( database, fmt::format("id = {}", recipe_id) @@ -42,7 +42,7 @@ void command_findrecipe(Client *c, const Seperator *sep) } else { auto search_criteria = Strings::ToLower(sep->argplus[1]); int found_count = 0; - + auto rl = TradeskillRecipeRepository::GetWhere( database, fmt::format("`name` LIKE '%{}%' ORDER BY `id` ASC", search_criteria) diff --git a/zone/gm_commands/findskill.cpp b/zone/gm_commands/findskill.cpp index 5c9a3b50e..68231200f 100755 --- a/zone/gm_commands/findskill.cpp +++ b/zone/gm_commands/findskill.cpp @@ -11,7 +11,7 @@ void command_findskill(Client *c, const Seperator *sep) std::map skills = EQ::skills::GetSkillTypeMap(); if (sep->IsNumber(1)) { - int skill_id = std::stoi(sep->arg[1]); + int skill_id = Strings::ToInt(sep->arg[1]); if (skill_id >= EQ::skills::Skill1HBlunt && skill_id < EQ::skills::SkillCount) { for (auto skill : skills) { if (skill_id == skill.first) { diff --git a/zone/gm_commands/findspell.cpp b/zone/gm_commands/findspell.cpp index 0585bda1c..1ec4f1d10 100755 --- a/zone/gm_commands/findspell.cpp +++ b/zone/gm_commands/findspell.cpp @@ -15,7 +15,7 @@ void command_findspell(Client *c, const Seperator *sep) } if (sep->IsNumber(1)) { - int spell_id = std::stoi(sep->arg[1]); + int spell_id = Strings::ToInt(sep->arg[1]); if (!IsValidSpell(spell_id)) { c->Message( Chat::White, diff --git a/zone/gm_commands/findtask.cpp b/zone/gm_commands/findtask.cpp index a643b28a3..78556a158 100755 --- a/zone/gm_commands/findtask.cpp +++ b/zone/gm_commands/findtask.cpp @@ -11,7 +11,7 @@ void command_findtask(Client *c, const Seperator *sep) } if (sep->IsNumber(1)) { - auto task_id = std::stoul(sep->arg[1]); + auto task_id = Strings::ToUnsignedInt(sep->arg[1]); auto task_name = task_manager->GetTaskName(task_id); std::string task_message = ( diff --git a/zone/gm_commands/findzone.cpp b/zone/gm_commands/findzone.cpp index c80346159..baba6b63a 100755 --- a/zone/gm_commands/findzone.cpp +++ b/zone/gm_commands/findzone.cpp @@ -9,7 +9,7 @@ void command_findzone(Client *c, const Seperator *sep) } std::string query; - int id = atoi((const char *) sep->arg[1]); + int id = Strings::ToInt((const char *) sep->arg[1]); std::string arg1 = sep->arg[1]; @@ -53,7 +53,7 @@ void command_findzone(Client *c, const Seperator *sep) std::string zone_id = row[0]; std::string short_name = row[1]; std::string long_name = row[2]; - int version = atoi(row[3]); + int version = Strings::ToInt(row[3]); if (++count > maxrows) { c->Message(Chat::White, "%i zones shown. Too many results.", maxrows); diff --git a/zone/gm_commands/flag.cpp b/zone/gm_commands/flag.cpp index b49011ba2..12135fbe3 100755 --- a/zone/gm_commands/flag.cpp +++ b/zone/gm_commands/flag.cpp @@ -30,8 +30,8 @@ void command_flag(Client *c, const Seperator *sep) target->UpdateAdmin(); return; } - - + + if ( !sep->IsNumber(1) || strlen(sep->arg[2]) == 0 @@ -40,7 +40,7 @@ void command_flag(Client *c, const Seperator *sep) return; } - auto status = std::stoi(sep->arg[1]); + auto status = Strings::ToInt(sep->arg[1]); if (status < -2 || status > 255) { c->Message(Chat::White, "The lowest a status level can go is -2 and the highest a status level can go is 255."); return; @@ -48,7 +48,7 @@ void command_flag(Client *c, const Seperator *sep) std::string account_name = sep->argplus[2]; auto account_id = database.GetAccountIDByChar(account_name.c_str()); - + if (c->Admin() < commandChangeFlags) { //this check makes banning players by less than this level impossible, but i'll leave it in anyways c->Message(Chat::White, "You may only refresh your own flag, doing so now."); c->UpdateAdmin(); diff --git a/zone/gm_commands/flagedit.cpp b/zone/gm_commands/flagedit.cpp index 85d76392a..bb29620f1 100755 --- a/zone/gm_commands/flagedit.cpp +++ b/zone/gm_commands/flagedit.cpp @@ -82,7 +82,7 @@ void command_flagedit(Client *c, const Seperator *sep) if (is_give) { uint32 zone_id = ( sep->IsNumber(2) ? - std::stoul(sep->arg[2]) : + Strings::ToUnsignedInt(sep->arg[2]) : ZoneID(sep->arg[2]) ); std::string zone_short_name = Strings::ToLower(ZoneName(zone_id, true)); @@ -129,7 +129,7 @@ void command_flagedit(Client *c, const Seperator *sep) row[0], row[1], ( - std::stoi(row[2]) != 0 ? + Strings::ToInt(row[2]) != 0 ? fmt::format( "[Version {}]", row[2] @@ -151,7 +151,7 @@ void command_flagedit(Client *c, const Seperator *sep) } else if (is_lock) { uint32 zone_id = ( sep->IsNumber(2) ? - std::stoul(sep->arg[2]) : + Strings::ToUnsignedInt(sep->arg[2]) : ZoneID(sep->arg[2]) ); std::string zone_short_name = Strings::ToLower(ZoneName(zone_id, true)); @@ -206,7 +206,7 @@ void command_flagedit(Client *c, const Seperator *sep) } else if (is_take) { uint32 zone_id = ( sep->IsNumber(2) ? - std::stoul(sep->arg[2]) : + Strings::ToUnsignedInt(sep->arg[2]) : ZoneID(sep->arg[2]) ); std::string zone_short_name = Strings::ToLower(ZoneName(zone_id, true)); @@ -234,7 +234,7 @@ void command_flagedit(Client *c, const Seperator *sep) } else if (is_unlock) { uint32 zone_id = ( sep->IsNumber(2) ? - std::stoul(sep->arg[2]) : + Strings::ToUnsignedInt(sep->arg[2]) : ZoneID(sep->arg[2]) ); std::string zone_short_name = Strings::ToLower(ZoneName(zone_id, true)); diff --git a/zone/gm_commands/flymode.cpp b/zone/gm_commands/flymode.cpp index 591977939..46ebc40b9 100755 --- a/zone/gm_commands/flymode.cpp +++ b/zone/gm_commands/flymode.cpp @@ -13,7 +13,7 @@ void command_flymode(Client *c, const Seperator *sep) target = c->GetTarget(); } - auto flymode_id = std::stoul(sep->arg[1]); + auto flymode_id = Strings::ToUnsignedInt(sep->arg[1]); if (!EQ::ValueWithin(flymode_id, EQ::constants::GravityBehavior::Ground, EQ::constants::GravityBehavior::LevitateWhileRunning)) { c->Message(Chat::White, "Usage:: #flymode [Flymode ID]"); c->Message(Chat::White, "0 = Ground, 1 = Flying, 2 = Levitating, 3 = Water, 4 = Floating, 5 = Levitating While Running"); diff --git a/zone/gm_commands/gassign.cpp b/zone/gm_commands/gassign.cpp index 81260ff8a..4c4b61aa9 100755 --- a/zone/gm_commands/gassign.cpp +++ b/zone/gm_commands/gassign.cpp @@ -13,7 +13,7 @@ void command_gassign(Client *c, const Seperator *sep) return; } - auto grid_id = std::stoul(sep->arg[1]); + auto grid_id = Strings::ToUnsignedInt(sep->arg[1]); auto target = c->GetTarget()->CastToNPC(); if (target->GetSpawnPointID() > 0) { diff --git a/zone/gm_commands/gearup.cpp b/zone/gm_commands/gearup.cpp index 36817ad91..2d9cbc1c5 100755 --- a/zone/gm_commands/gearup.cpp +++ b/zone/gm_commands/gearup.cpp @@ -97,8 +97,8 @@ void command_gearup(Client *c, const Seperator *sep) std::set equipped; for (auto row : results) { - auto item_id = std::stoul(row[0]); - auto slot_id = static_cast(std::stoul(row[1])); + auto item_id = Strings::ToUnsignedInt(row[0]); + auto slot_id = static_cast(Strings::ToUnsignedInt(row[1])); if (equipped.find(slot_id) != equipped.end()) { if (slot_id == EQ::invslot::slotEar1) { @@ -116,7 +116,7 @@ void command_gearup(Client *c, const Seperator *sep) if (t->IsClient()) { has_item = t->CastToClient()->GetInv().HasItem(item_id, 1, invWhereWorn) != INVALID_INDEX; } else if (t->IsBot()) { - has_item = t->CastToBot()->HasBotItem(item_id); + has_item = t->CastToBot()->HasBotItem(item_id) != INVALID_INDEX; } bool can_wear_item = false; @@ -178,7 +178,7 @@ void command_gearup(Client *c, const Seperator *sep) c->Message(Chat::White, "Choose Armor by Expansion:"); std::string message; for (auto row : results) { - const auto expansion = std::stoi(row[0]); + const auto expansion = Strings::ToInt(row[0]); message += fmt::format( "[{}] ", Saylink::Silent( diff --git a/zone/gm_commands/gender.cpp b/zone/gm_commands/gender.cpp index 6e611e04a..42e7396c4 100755 --- a/zone/gm_commands/gender.cpp +++ b/zone/gm_commands/gender.cpp @@ -14,7 +14,7 @@ void command_gender(Client *c, const Seperator *sep) target = c->GetTarget(); } - auto gender_id = std::stoi(sep->arg[1]); + auto gender_id = Strings::ToInt(sep->arg[1]); if (gender_id < 0 || gender_id > 2) { c->Message(Chat::White, "Usage: #gender [Gender ID]"); c->Message(Chat::White, "Genders: 0 = Male, 1 = Female, 2 = Neuter"); diff --git a/zone/gm_commands/ginfo.cpp b/zone/gm_commands/ginfo.cpp index a8ab9cff1..3850c6b91 100755 --- a/zone/gm_commands/ginfo.cpp +++ b/zone/gm_commands/ginfo.cpp @@ -45,7 +45,7 @@ void command_ginfo(Client *c, const Seperator *sep) if (target_group->membername[group_member][0] == '\0') { continue; } - + bool is_assist = target_group->MemberRoles[group_member] & RoleAssist; bool is_puller = target_group->MemberRoles[group_member] & RolePuller; bool is_tank = target_group->MemberRoles[group_member] & RoleTank; @@ -61,10 +61,10 @@ void command_ginfo(Client *c, const Seperator *sep) target_group->membername[group_member] ) ), - target_group->members[group_member] ? "âś”" : "❌", - is_assist ? "âś”" : "❌", - is_puller ? "âś”" : "❌", - is_tank ? "âś”" : "❌" + target_group->members[group_member] ? "Y" : "N", + is_assist ? "Y" : "N", + is_puller ? "Y" : "N", + is_tank ? "Y" : "N" ); } diff --git a/zone/gm_commands/giveitem.cpp b/zone/gm_commands/giveitem.cpp index 17458182b..0e4c894ee 100755 --- a/zone/gm_commands/giveitem.cpp +++ b/zone/gm_commands/giveitem.cpp @@ -34,7 +34,7 @@ void command_giveitem(Client *c, const Seperator *sep) augment_six = link_body.augment_6; } else if (sep->IsNumber(1)) { - item_id = atoi(sep->arg[1]); + item_id = Strings::ToInt(sep->arg[1]); } else if (!sep->IsNumber(1)) { c->Message( @@ -65,31 +65,31 @@ void command_giveitem(Client *c, const Seperator *sep) } if (arguments >= 2 && sep->IsNumber(2)) { - charges = atoi(sep->arg[2]); + charges = Strings::ToInt(sep->arg[2]); } if (arguments >= 3 && sep->IsNumber(3)) { - augment_one = atoi(sep->arg[3]); + augment_one = Strings::ToInt(sep->arg[3]); } if (arguments >= 4 && sep->IsNumber(4)) { - augment_two = atoi(sep->arg[4]); + augment_two = Strings::ToInt(sep->arg[4]); } if (arguments >= 5 && sep->IsNumber(5)) { - augment_three = atoi(sep->arg[5]); + augment_three = Strings::ToInt(sep->arg[5]); } if (arguments >= 6 && sep->IsNumber(6)) { - augment_four = atoi(sep->arg[6]); + augment_four = Strings::ToInt(sep->arg[6]); } if (arguments >= 7 && sep->IsNumber(7)) { - augment_five = atoi(sep->arg[7]); + augment_five = Strings::ToInt(sep->arg[7]); } if (arguments == 8 && sep->IsNumber(8)) { - augment_six = atoi(sep->arg[8]); + augment_six = Strings::ToInt(sep->arg[8]); } client_target->SummonItem( diff --git a/zone/gm_commands/givemoney.cpp b/zone/gm_commands/givemoney.cpp index 9aa17e76d..dd8499ee7 100755 --- a/zone/gm_commands/givemoney.cpp +++ b/zone/gm_commands/givemoney.cpp @@ -14,10 +14,10 @@ void command_givemoney(Client *c, const Seperator *sep) target = c->GetTarget()->CastToClient(); } - uint32 platinum = std::stoul(sep->arg[1]); - uint32 gold = sep->IsNumber(2) ? std::stoul(sep->arg[2]) : 0; - uint32 silver = sep->IsNumber(3) ? std::stoul(sep->arg[3]) : 0; - uint32 copper = sep->IsNumber(4) ? std::stoul(sep->arg[4]) : 0; + uint32 platinum = Strings::ToUnsignedInt(sep->arg[1]); + uint32 gold = sep->IsNumber(2) ? Strings::ToUnsignedInt(sep->arg[2]) : 0; + uint32 silver = sep->IsNumber(3) ? Strings::ToUnsignedInt(sep->arg[3]) : 0; + uint32 copper = sep->IsNumber(4) ? Strings::ToUnsignedInt(sep->arg[4]) : 0; if (!platinum && !gold && !silver && !copper) { c->Message(Chat::Red, "Usage: #Usage: #givemoney [Platinum] [Gold] [Silver] [Copper]"); return; diff --git a/zone/gm_commands/gmzone.cpp b/zone/gm_commands/gmzone.cpp index 94b462706..d10885d62 100755 --- a/zone/gm_commands/gmzone.cpp +++ b/zone/gm_commands/gmzone.cpp @@ -11,7 +11,7 @@ void command_gmzone(Client *c, const Seperator *sep) std::string zone_short_name = Strings::ToLower( sep->IsNumber(1) ? - ZoneName(std::stoul(sep->arg[1]), true) : + ZoneName(Strings::ToUnsignedInt(sep->arg[1]), true) : sep->arg[1] ); bool is_unknown_zone = zone_short_name.find("unknown") != std::string::npos; @@ -41,7 +41,7 @@ void command_gmzone(Client *c, const Seperator *sep) auto zone_version = ( sep->IsNumber(2) ? - std::stoul(sep->arg[2]) : + Strings::ToUnsignedInt(sep->arg[2]) : 0 ); @@ -63,7 +63,7 @@ void command_gmzone(Client *c, const Seperator *sep) uint32 duration = 100000000; if (!existing_zone_instance.empty()) { - instance_id = std::stoi(existing_zone_instance); + instance_id = Strings::ToInt(existing_zone_instance); c->Message( Chat::White, fmt::format( diff --git a/zone/gm_commands/goto.cpp b/zone/gm_commands/goto.cpp index cdc8da2e2..b3b4cccf0 100755 --- a/zone/gm_commands/goto.cpp +++ b/zone/gm_commands/goto.cpp @@ -49,10 +49,10 @@ void command_goto(Client *c, const Seperator *sep) c->MovePC( zone->GetZoneID(), zone->GetInstanceID(), - atof(sep->arg[1]), - atof(sep->arg[2]), - atof(sep->arg[3]), - (sep->arg[4] ? atof(sep->arg[4]) : c->GetHeading()) + Strings::ToFloat(sep->arg[1]), + Strings::ToFloat(sep->arg[2]), + Strings::ToFloat(sep->arg[3]), + (sep->arg[4] ? Strings::ToFloat(sep->arg[4]) : c->GetHeading()) ); } else { diff --git a/zone/gm_commands/grid.cpp b/zone/gm_commands/grid.cpp index 3ff62539c..3a346807e 100755 --- a/zone/gm_commands/grid.cpp +++ b/zone/gm_commands/grid.cpp @@ -14,9 +14,9 @@ void command_grid(Client *c, const Seperator *sep) ); } else if (strcasecmp("add", command_type) == 0) { - auto grid_id = atoi(sep->arg[2]); - auto wander_type = atoi(sep->arg[3]); - auto pause_type = atoi(sep->arg[4]); + auto grid_id = Strings::ToInt(sep->arg[2]); + auto wander_type = Strings::ToInt(sep->arg[3]); + auto pause_type = Strings::ToInt(sep->arg[4]); if (!content_db.GridExistsInZone(zone_id, grid_id)) { content_db.ModifyGrid(c, false, grid_id, wander_type, pause_type, zone_id); c->Message( @@ -76,7 +76,7 @@ void command_grid(Client *c, const Seperator *sep) // Spawn grid nodes std::map, int32> zoffset; for (auto row : results) { - glm::vec4 node_position = glm::vec4(atof(row[0]), atof(row[1]), atof(row[2]), atof(row[3])); + glm::vec4 node_position = glm::vec4(Strings::ToFloat(row[0]), Strings::ToFloat(row[1]), Strings::ToFloat(row[2]), Strings::ToFloat(row[3])); std::vector node_loc{ node_position.x, node_position.y, @@ -95,7 +95,7 @@ void command_grid(Client *c, const Seperator *sep) } node_position.z += zoffset[node_loc]; - NPC::SpawnGridNodeNPC(node_position, grid_id, atoi(row[4]), zoffset[node_loc]); + NPC::SpawnGridNodeNPC(node_position, grid_id, Strings::ToInt(row[4]), zoffset[node_loc]); } c->Message( Chat::White, @@ -123,7 +123,7 @@ void command_grid(Client *c, const Seperator *sep) ); } else if (strcasecmp("delete", command_type) == 0) { - auto grid_id = atoi(sep->arg[2]); + auto grid_id = Strings::ToInt(sep->arg[2]); content_db.ModifyGrid(c, true, grid_id, 0, 0, zone_id); c->Message( Chat::White, diff --git a/zone/gm_commands/guild.cpp b/zone/gm_commands/guild.cpp index 13fd07cb4..3d1ad2717 100755 --- a/zone/gm_commands/guild.cpp +++ b/zone/gm_commands/guild.cpp @@ -53,7 +53,7 @@ void command_guild(Client *c, const Seperator *sep) } else { auto leader_id = ( sep->IsNumber(2) ? - std::stoul(sep->arg[2]) : + Strings::ToUnsignedInt(sep->arg[2]) : database.GetCharacterID(sep->arg[2]) ); auto leader_name = database.GetCharNameByID(leader_id); @@ -132,7 +132,7 @@ void command_guild(Client *c, const Seperator *sep) if (!sep->IsNumber(2)) { c->Message(Chat::White, "Usage: #guild delete [Guild ID]"); } else { - auto guild_id = std::stoul(sep->arg[2]); + auto guild_id = Strings::ToUnsignedInt(sep->arg[2]); if (!guild_mgr.GuildExists(guild_id)) { c->Message( Chat::White, @@ -185,7 +185,7 @@ void command_guild(Client *c, const Seperator *sep) if (arguments != 2 || !sep->IsNumber(2)) { guild_id = c->GuildID(); } else if (c->Admin() >= minStatusToEditOtherGuilds) { - guild_id = std::stoul(sep->arg[2]); + guild_id = Strings::ToUnsignedInt(sep->arg[2]); } if (guild_id != GUILD_NONE) { @@ -203,7 +203,7 @@ void command_guild(Client *c, const Seperator *sep) if (!sep->IsNumber(2)) { c->Message(Chat::White, "Usage: #guild rename [Guild ID] [New Guild Name]"); } else { - auto guild_id = std::stoul(sep->arg[2]); + auto guild_id = Strings::ToUnsignedInt(sep->arg[2]); if (!guild_mgr.GuildExists(guild_id)) { c->Message( Chat::White, @@ -246,7 +246,7 @@ void command_guild(Client *c, const Seperator *sep) } } else if (is_search) { if (Strings::IsNumber(sep->arg[2])) { - const auto guild_id = std::stoul(sep->arg[2]); + const auto guild_id = Strings::ToUnsignedInt(sep->arg[2]); guild_mgr.ListGuilds(c, guild_id); } else { @@ -262,7 +262,7 @@ void command_guild(Client *c, const Seperator *sep) c->Message(Chat::White, "#guild set [Character ID|Character Name] [Guild ID] (Guild ID 0 is Guildless)"); return; } else { - auto guild_id = std::stoul(sep->arg[3]); + auto guild_id = Strings::ToUnsignedInt(sep->arg[3]); if (!guild_id) { guild_id = GUILD_NONE; } else if (!guild_mgr.GuildExists(guild_id)) { @@ -278,7 +278,7 @@ void command_guild(Client *c, const Seperator *sep) auto character_id = ( sep->IsNumber(2) ? - std::stoul(sep->arg[2]) : + Strings::ToUnsignedInt(sep->arg[2]) : database.GetCharacterID(sep->arg[2]) ); auto character_name = database.GetCharNameByID(character_id); @@ -348,7 +348,7 @@ void command_guild(Client *c, const Seperator *sep) } else { auto leader_id = ( sep->IsNumber(2) ? - std::stoul(sep->arg[2]) : + Strings::ToUnsignedInt(sep->arg[2]) : database.GetCharacterID(sep->arg[2]) ); auto leader_name = database.GetCharNameByID(leader_id); @@ -377,7 +377,7 @@ void command_guild(Client *c, const Seperator *sep) ); } else { - auto guild_id = std::stoul(sep->arg[2]); + auto guild_id = Strings::ToUnsignedInt(sep->arg[2]); if (!guild_mgr.GuildExists(guild_id)) { c->Message( Chat::White, @@ -419,7 +419,7 @@ void command_guild(Client *c, const Seperator *sep) } } } else if (is_set_rank) { - auto rank = static_cast(std::stoul(sep->arg[3])); + auto rank = static_cast(Strings::ToUnsignedInt(sep->arg[3])); if (!sep->IsNumber(3)) { c->Message(Chat::White, "#guild setrank [Character ID|Character Name] [Rank]"); } else if (rank < 0 || rank > GUILD_MAX_RANK) { @@ -433,7 +433,7 @@ void command_guild(Client *c, const Seperator *sep) } else { auto character_id = ( sep->IsNumber(2) ? - std::stoul(sep->arg[2]) : + Strings::ToUnsignedInt(sep->arg[2]) : database.GetCharacterID(sep->arg[2]) ); auto character_name = database.GetCharNameByID(character_id); diff --git a/zone/gm_commands/guildapprove.cpp b/zone/gm_commands/guildapprove.cpp deleted file mode 100755 index 5c7805224..000000000 --- a/zone/gm_commands/guildapprove.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include "../client.h" -#include "../guild_mgr.h" - -void command_guildapprove(Client *c, const Seperator *sep) -{ - guild_mgr.AddMemberApproval(atoi(sep->arg[1]), c); -} - diff --git a/zone/gm_commands/guildcreate.cpp b/zone/gm_commands/guildcreate.cpp deleted file mode 100755 index 48e90d3ef..000000000 --- a/zone/gm_commands/guildcreate.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "../client.h" -#include "../guild_mgr.h" - -void command_guildcreate(Client *c, const Seperator *sep) -{ - if (strlen(sep->argplus[1]) > 4 && strlen(sep->argplus[1]) < 16) { - guild_mgr.AddGuildApproval(sep->argplus[1], c); - } - else { - c->Message(Chat::White, "Guild name must be more than 4 characters and less than 16."); - } -} - diff --git a/zone/gm_commands/guildlist.cpp b/zone/gm_commands/guildlist.cpp deleted file mode 100755 index 3ec40ef02..000000000 --- a/zone/gm_commands/guildlist.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "../client.h" -#include "../guild_mgr.h" - -void command_guildlist(Client *c, const Seperator *sep) -{ - GuildApproval *tmp = guild_mgr.FindGuildByIDApproval(atoi(sep->arg[1])); - if (tmp) { - tmp->ApprovedMembers(c); - } - else { - c->Message(Chat::White, "Could not find reference id."); - } -} - diff --git a/zone/gm_commands/haste.cpp b/zone/gm_commands/haste.cpp index bf5be4d26..d5e19f569 100755 --- a/zone/gm_commands/haste.cpp +++ b/zone/gm_commands/haste.cpp @@ -2,19 +2,30 @@ void command_haste(Client *c, const Seperator *sep) { - // #haste command to set client attack speed. Takes a percentage (100 = twice normal attack speed) - if (sep->arg[1][0] != 0) { - uint16 Haste = atoi(sep->arg[1]); - if (Haste > 85) { - Haste = 85; - } - c->SetExtraHaste(Haste); - // SetAttackTimer must be called to make this take effect, so player needs to change - // the primary weapon. - c->Message(Chat::White, "Haste set to %d%% - Need to re-equip primary weapon before it takes effect", Haste); + const auto arguments = sep->argnum; + if (!arguments || !sep->IsNumber(1)) { + c->Message(Chat::White, "Usage: #haste [Percentage] - Set GM Bonus Haste (100 is 100% more Attack Speed)"); + return; } - else { - c->Message(Chat::White, "Usage: #haste [percentage]"); + + auto t = c; + if (c->GetGM() && c->GetTarget() && c->GetTarget()->IsClient()) { + t = c->GetTarget()->CastToClient(); } + + const auto extra_haste = Strings::ToInt(sep->arg[1]); + + t->SetExtraHaste(extra_haste); + t->CalcBonuses(); + t->SetAttackTimer(); + + c->Message( + Chat::White, + fmt::format( + "GM Haste Bonus set to {}%% for {}.", + Strings::Commify(extra_haste), + c->GetTargetDescription(t) + ).c_str() + ); } diff --git a/zone/gm_commands/heromodel.cpp b/zone/gm_commands/heromodel.cpp index 45b9048c1..f6c35b142 100755 --- a/zone/gm_commands/heromodel.cpp +++ b/zone/gm_commands/heromodel.cpp @@ -21,10 +21,10 @@ void command_heromodel(Client *c, const Seperator *sep) t = c->GetTarget(); } - auto hero_forge_model = std::stoul(sep->arg[1]); + auto hero_forge_model = Strings::IsNumber(sep->arg[1]) ? Strings::ToUnsignedInt(sep->arg[1]) : 0; if (arguments > 1) { - auto slot = static_cast(std::stoul(sep->arg[2])); + auto slot = static_cast(Strings::ToUnsignedInt(sep->arg[2])); c->GetTarget()->SendTextureWC(slot, 0, hero_forge_model, 0, 0, 0); } else { if (hero_forge_model) { diff --git a/zone/gm_commands/hideme.cpp b/zone/gm_commands/hideme.cpp index d936a7fdc..108807d8d 100755 --- a/zone/gm_commands/hideme.cpp +++ b/zone/gm_commands/hideme.cpp @@ -1,16 +1,31 @@ #include "../client.h" -#include "../string_ids.h" void command_hideme(Client *c, const Seperator *sep) { - bool state = atobool(sep->arg[1]); + const auto arguments = sep->argnum; + if (!arguments) { + c->Message(Chat::White, "Usage: #hideme [On|Off]"); + c->Message(Chat::White, "Usage: #hideme [0|1]"); + return; + } - if (sep->arg[1][0] == 0) { - c->Message(Chat::White, "Usage: #hideme [on/off]"); - } - else { - c->SetHideMe(state); - c->MessageString(Chat::Broadcasts, c->GetHideMe() ? NOW_INVISIBLE : NOW_VISIBLE, c->GetName()); + auto t = c; + if (c->GetGM() && c->GetTarget() && c->GetTarget()->IsClient()) { + t = c->GetTarget()->CastToClient(); } + + const auto is_hidden = Strings::ToBool(sep->arg[1]); + + t->SetHideMe(is_hidden); + + c->Message( + Chat::White, + fmt::format( + "{} {} now {} to players below a status level of {}.", + c->GetTargetDescription(t, TargetDescriptionType::UCYou), + c == t ? "are" : "is", + is_hidden ? "invisible" : "visible", + t->Admin() + ).c_str() + ); } - diff --git a/zone/gm_commands/incstat.cpp b/zone/gm_commands/incstat.cpp index 6a09c1785..14ad4a235 100755 --- a/zone/gm_commands/incstat.cpp +++ b/zone/gm_commands/incstat.cpp @@ -3,7 +3,7 @@ void command_incstat(Client *c, const Seperator *sep) { if (sep->arg[1][0] && sep->arg[2][0] && c->GetTarget() != 0 && c->GetTarget()->IsClient()) { - c->GetTarget()->CastToClient()->IncStats(atoi(sep->arg[1]), atoi(sep->arg[2])); + c->GetTarget()->CastToClient()->IncStats(Strings::ToInt(sep->arg[1]), Strings::ToInt(sep->arg[2])); } else { c->Message(Chat::White, "This command is used to permanently increase or decrease a players stats."); diff --git a/zone/gm_commands/instance.cpp b/zone/gm_commands/instance.cpp index 83ca06d9e..413eeebed 100755 --- a/zone/gm_commands/instance.cpp +++ b/zone/gm_commands/instance.cpp @@ -79,7 +79,7 @@ void command_instance(Client *c, const Seperator *sep) } std::string character_name = sep->arg[3]; - uint16 instance_id = static_cast(std::stoul(sep->arg[2])); + uint16 instance_id = static_cast(Strings::ToUnsignedInt(sep->arg[2])); uint32 character_id = database.GetCharacterID(character_name.c_str()); if (instance_id <= 0 || character_id <= 0) { c->Message(Chat::White, "You must enter a valid Instance ID and player name."); @@ -146,11 +146,11 @@ void command_instance(Client *c, const Seperator *sep) uint32 zone_id = ( sep->IsNumber(2) ? - std::stoul(sep->arg[2]) : + Strings::ToUnsignedInt(sep->arg[2]) : ZoneID(sep->arg[2]) ); - uint32 version = std::stoul(sep->arg[3]); - uint32 duration = std::stoul(sep->arg[4]); + uint32 version = Strings::ToUnsignedInt(sep->arg[3]); + uint32 duration = Strings::ToUnsignedInt(sep->arg[4]); std::string zone_short_name = ZoneName(zone_id); if (zone_short_name.empty()) { c->Message( @@ -210,7 +210,7 @@ void command_instance(Client *c, const Seperator *sep) return; } - uint16 instance_id = std::stoul(sep->arg[2]); + uint16 instance_id = Strings::ToUnsignedInt(sep->arg[2]); if (!database.CheckInstanceExists(instance_id)) { c->Message( Chat::White, @@ -269,7 +269,7 @@ void command_instance(Client *c, const Seperator *sep) } std::string character_name = sep->arg[3]; - uint16 instance_id = static_cast(std::stoul(sep->arg[2])); + uint16 instance_id = static_cast(Strings::ToUnsignedInt(sep->arg[2])); uint32 character_id = database.GetCharacterID(character_name.c_str()); if (instance_id <= 0 || character_id <= 0) { c->Message(Chat::White, "You must enter a valid Instance ID and player name."); diff --git a/zone/gm_commands/interrupt.cpp b/zone/gm_commands/interrupt.cpp index 1126a850c..1a1200c1e 100755 --- a/zone/gm_commands/interrupt.cpp +++ b/zone/gm_commands/interrupt.cpp @@ -2,15 +2,18 @@ void command_interrupt(Client *c, const Seperator *sep) { - uint16 ci_message = 0x01b7, ci_color = 0x0121; + const auto arguments = sep->argnum; - if (sep->arg[1][0]) { - ci_message = atoi(sep->arg[1]); - } - if (sep->arg[2][0]) { - ci_color = atoi(sep->arg[2]); + uint16 interrupt_message = 0x01b7, interrupt_color = 0x0121; + + if (arguments >= 1 && sep->IsNumber(1)) { + interrupt_message = static_cast(Strings::ToUnsignedInt(sep->arg[1])); } - c->InterruptSpell(ci_message, ci_color); + if (arguments == 2 && sep->IsNumber(2)) { + interrupt_color = static_cast(Strings::ToUnsignedInt(sep->arg[2])); + } + + c->InterruptSpell(interrupt_message, interrupt_color); } diff --git a/zone/gm_commands/invsnapshot.cpp b/zone/gm_commands/invsnapshot.cpp index 6e818524a..4c60fb8ce 100755 --- a/zone/gm_commands/invsnapshot.cpp +++ b/zone/gm_commands/invsnapshot.cpp @@ -189,7 +189,7 @@ void command_invsnapshot(Client *c, const Seperator *sep) auto list_count = 0; if (sep->IsNumber(2)) { - list_count = atoi(sep->arg[2]); + list_count = Strings::ToInt(sep->arg[2]); } if (list_count < 1 || list_count > is_list.size()) { list_count = is_list.size(); @@ -237,7 +237,7 @@ void command_invsnapshot(Client *c, const Seperator *sep) return; } - uint32 timestamp = atoul(sep->arg[2]); + uint32 timestamp = Strings::ToUnsignedInt(sep->arg[2]); if (!database.ValidateCharacterInvSnapshotTimestamp(tc->CharacterID(), timestamp)) { c->Message( @@ -285,7 +285,7 @@ void command_invsnapshot(Client *c, const Seperator *sep) return; } - uint32 timestamp = atoul(sep->arg[2]); + uint32 timestamp = Strings::ToUnsignedInt(sep->arg[2]); if (!database.ValidateCharacterInvSnapshotTimestamp(tc->CharacterID(), timestamp)) { c->Message( @@ -374,7 +374,7 @@ void command_invsnapshot(Client *c, const Seperator *sep) return; } - uint32 timestamp = atoul(sep->arg[2]); + uint32 timestamp = Strings::ToUnsignedInt(sep->arg[2]); if (!database.ValidateCharacterInvSnapshotTimestamp(tc->CharacterID(), timestamp)) { c->Message( diff --git a/zone/gm_commands/itemsearch.cpp b/zone/gm_commands/itemsearch.cpp index be720275f..084b38833 100755 --- a/zone/gm_commands/itemsearch.cpp +++ b/zone/gm_commands/itemsearch.cpp @@ -13,7 +13,7 @@ void command_itemsearch(Client *c, const Seperator *sep) linker.SetLinkType(EQ::saylink::SayLinkItemData); if (Seperator::IsNumber(search_criteria)) { - item = database.GetItem(atoi(search_criteria)); + item = database.GetItem(Strings::ToInt(search_criteria)); if (item) { linker.SetItemData(item); std::string item_id = std::to_string(item->ID); diff --git a/zone/gm_commands/level.cpp b/zone/gm_commands/level.cpp index 663633cd7..37f6a4bb2 100644 --- a/zone/gm_commands/level.cpp +++ b/zone/gm_commands/level.cpp @@ -2,22 +2,21 @@ void command_level(Client *c, const Seperator *sep) { - int arguments = sep->argnum; + const auto arguments = sep->argnum; if (!arguments || !sep->IsNumber(1)) { c->Message(Chat::White, "Usage: #level [Level]"); return; } - auto target = c->GetTarget(); - if (!target) { - c->Message(Chat::White, "You must have a target to use this command."); - return; + Mob* t = c; + if (c->GetTarget()) { + t = c->GetTarget(); } - auto level = static_cast(std::stoul(sep->arg[1])); + auto level = static_cast(Strings::ToUnsignedInt(sep->arg[1])); auto max_level = static_cast(RuleI(Character, MaxLevel)); - if (c->Admin() < RuleI(GM, MinStatusToLevelTarget)) { + if (c != t && c->Admin() < RuleI(GM, MinStatusToLevelTarget)) { c->Message(Chat::White, "Your status is not high enough to change another person's level."); return; } @@ -37,12 +36,12 @@ void command_level(Client *c, const Seperator *sep) return; } - target->SetLevel(level, true); - if (target->IsClient()) { - target->CastToClient()->SendLevelAppearance(); + t->SetLevel(level, true); + if (t->IsClient()) { + t->CastToClient()->SendLevelAppearance(); if (RuleB(Bots, Enabled) && RuleB(Bots, BotLevelsWithOwner)) { - Bot::LevelBotWithClient(target->CastToClient(), level, true); + Bot::LevelBotWithClient(t->CastToClient(), level, true); } } } diff --git a/zone/gm_commands/list.cpp b/zone/gm_commands/list.cpp index fe675ae9c..a5ee110d5 100755 --- a/zone/gm_commands/list.cpp +++ b/zone/gm_commands/list.cpp @@ -34,12 +34,10 @@ void command_list(Client *c, const Seperator *sep) std::string search_string; if (sep->arg[2]) { - search_string = sep->arg[2]; + search_string = Strings::ToLower(sep->arg[2]); } - /** - * NPC - */ + // NPC if (search_type.find("npcs") != std::string::npos) { auto &entity_list_search = entity_list.GetMobList(); @@ -51,11 +49,7 @@ void command_list(Client *c, const Seperator *sep) entity_count++; - std::string entity_name = entity->GetName(); - - /** - * Filter by name - */ + std::string entity_name = Strings::ToLower(entity->GetName()); if (search_string.length() > 0 && entity_name.find(search_string) == std::string::npos) { continue; } @@ -81,9 +75,7 @@ void command_list(Client *c, const Seperator *sep) } } - /** - * Client - */ + // Client if (search_type.find("players") != std::string::npos) { auto &entity_list_search = entity_list.GetClientList(); @@ -92,7 +84,7 @@ void command_list(Client *c, const Seperator *sep) entity_count++; - std::string entity_name = entity->GetName(); + std::string entity_name = Strings::ToLower(entity->GetName()); /** * Filter by name @@ -122,9 +114,7 @@ void command_list(Client *c, const Seperator *sep) } } - /** - * Corpse - */ + // Corpse if (search_type.find("corpses") != std::string::npos) { auto &entity_list_search = entity_list.GetCorpseList(); @@ -133,11 +123,7 @@ void command_list(Client *c, const Seperator *sep) entity_count++; - std::string entity_name = entity->GetName(); - - /** - * Filter by name - */ + std::string entity_name = Strings::ToLower(entity->GetName()); if (search_string.length() > 0 && entity_name.find(search_string) == std::string::npos) { continue; } @@ -163,9 +149,7 @@ void command_list(Client *c, const Seperator *sep) } } - /** - * Doors - */ + // Doors if (search_type.find("doors") != std::string::npos) { auto &entity_list_search = entity_list.GetDoorsList(); @@ -174,11 +158,7 @@ void command_list(Client *c, const Seperator *sep) entity_count++; - std::string entity_name = entity->GetDoorName(); - - /** - * Filter by name - */ + std::string entity_name = Strings::ToLower(entity->GetDoorName()); if (search_string.length() > 0 && entity_name.find(search_string) == std::string::npos) { continue; } @@ -205,9 +185,7 @@ void command_list(Client *c, const Seperator *sep) } } - /** - * Objects - */ + // Objects if (search_type.find("objects") != std::string::npos) { auto &entity_list_search = entity_list.GetObjectList(); @@ -216,11 +194,7 @@ void command_list(Client *c, const Seperator *sep) entity_count++; - std::string entity_name = entity->GetModelName(); - - /** - * Filter by name - */ + std::string entity_name = Strings::ToLower(entity->GetModelName()); if (search_string.length() > 0 && entity_name.find(search_string) == std::string::npos) { continue; } diff --git a/zone/gm_commands/loc.cpp b/zone/gm_commands/loc.cpp index 8928b8051..62fdf4be4 100755 --- a/zone/gm_commands/loc.cpp +++ b/zone/gm_commands/loc.cpp @@ -29,6 +29,7 @@ void command_loc(Client *c, const Seperator *sep) glm::vec3 hit; auto best_z = zone->zonemap->FindBestZ(tarloc, &hit); + auto fixed_z = c->GetFixedZ(c->GetPosition()); if (best_z != BEST_Z_INVALID) { c->Message( @@ -39,6 +40,14 @@ void command_loc(Client *c, const Seperator *sep) best_z ).c_str() ); + c->Message( + Chat::White, + fmt::format( + "Fixed Z for {} | {:.2f}", + c->GetTargetDescription(target, TargetDescriptionType::UCSelf), + fixed_z + ).c_str() + ); } else { c->Message(Chat::White, "Could not find Best Z."); } diff --git a/zone/gm_commands/logcommand.cpp b/zone/gm_commands/logcommand.cpp deleted file mode 100755 index 33fe83516..000000000 --- a/zone/gm_commands/logcommand.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include "../client.h" - -void command_logcommand(Client *c, std::string message) -{ - int admin = c->Admin(); - - bool log = false; - switch (zone->loglevelvar) { //catch failsafe - case 9: { // log only LeadGM - if ( - admin >= AccountStatus::GMLeadAdmin && - admin < AccountStatus::GMMgmt - ) { - log = true; - } - - break; - } - case 8: { // log only GM - if ( - admin >= AccountStatus::GMAdmin && - admin < AccountStatus::GMLeadAdmin - ) { - log = true; - } - - break; - } - case 1: { - if (admin >= AccountStatus::GMMgmt) { - log = true; - } - - break; - } - case 2: { - if (admin >= AccountStatus::GMLeadAdmin) { - log = true; - } - - break; - } - case 3: { - if (admin >= AccountStatus::GMAdmin) { - log = true; - } - - break; - } - case 4: { - if (admin >= AccountStatus::QuestTroupe) { - log = true; - } - - break; - } - case 5: { - if (admin >= AccountStatus::ApprenticeGuide) { - log = true; - } - - break; - } - case 6: { - if (admin >= AccountStatus::Steward) { - log = true; - } - - break; - } - case 7: { - log = true; - break; - } - } - - if (log) { - database.logevents( - c->AccountName(), - c->AccountID(), - admin, - c->GetName(), - c->GetTarget() ? c->GetTarget()->GetName() : "None", - "Command", - message.c_str(), - 1 - ); - } -} diff --git a/zone/gm_commands/logs.cpp b/zone/gm_commands/logs.cpp index 9a05745e6..f7029ee40 100755 --- a/zone/gm_commands/logs.cpp +++ b/zone/gm_commands/logs.cpp @@ -53,7 +53,7 @@ void command_logs(Client *c, const Seperator *sep) if (is_list || (is_set && !sep->IsNumber(3))) { uint32 start_category_id = 1; if (sep->IsNumber(2)) { - start_category_id = std::stoul(sep->arg[2]); + start_category_id = Strings::ToUnsignedInt(sep->arg[2]); } uint32 max_category_id = (start_category_id + 49); @@ -204,8 +204,8 @@ void command_logs(Client *c, const Seperator *sep) logs_set = true; - auto category_id = std::stoul(sep->arg[3]); - auto setting = std::stoul(sep->arg[4]); + auto category_id = Strings::ToUnsignedInt(sep->arg[3]); + auto setting = Strings::ToUnsignedInt(sep->arg[4]); if (is_console) { LogSys.log_settings[category_id].log_to_console = setting; diff --git a/zone/gm_commands/lootsim.cpp b/zone/gm_commands/lootsim.cpp index 2213c12a1..e7d28b7fc 100755 --- a/zone/gm_commands/lootsim.cpp +++ b/zone/gm_commands/lootsim.cpp @@ -8,10 +8,10 @@ void command_lootsim(Client *c, const Seperator *sep) return; } - auto npc_id = std::stoul(sep->arg[1]); - auto loottable_id = std::stoul(sep->arg[2]); - auto iterations = std::stoul(sep->arg[3]) > 1000 ? 1000 : std::stoul(sep->arg[3]); - auto log_enabled = arguments > 3 ? std::stoul(sep->arg[4]) : false; + auto npc_id = Strings::ToUnsignedInt(sep->arg[1]); + auto loottable_id = Strings::ToUnsignedInt(sep->arg[2]); + auto iterations = Strings::ToUnsignedInt(sep->arg[3]) > 1000 ? 1000 : Strings::ToUnsignedInt(sep->arg[3]); + auto log_enabled = arguments > 3 ? Strings::ToUnsignedInt(sep->arg[4]) : false; // temporarily disable loot logging unless set explicitly LogSys.log_settings[Logs::Loot].log_to_console = log_enabled ? LogSys.log_settings[Logs::Loot].log_to_console : 0; diff --git a/zone/gm_commands/memspell.cpp b/zone/gm_commands/memspell.cpp index e0fc422a4..c48e986a7 100755 --- a/zone/gm_commands/memspell.cpp +++ b/zone/gm_commands/memspell.cpp @@ -16,7 +16,7 @@ void command_memspell(Client *c, const Seperator *sep) target = c->GetTarget()->CastToClient(); } - auto spell_id = static_cast(std::stoul(sep->arg[1])); + auto spell_id = static_cast(Strings::ToUnsignedInt(sep->arg[1])); if (!IsValidSpell(spell_id)) { c->Message( Chat::White, @@ -43,7 +43,7 @@ void command_memspell(Client *c, const Seperator *sep) return; } - auto spell_gem = sep->IsNumber(2) ? std::stoul(sep->arg[2]) : empty_slot; + auto spell_gem = sep->IsNumber(2) ? Strings::ToUnsignedInt(sep->arg[2]) : empty_slot; if (spell_gem > EQ::spells::SPELL_GEM_COUNT) { c->Message( Chat::White, diff --git a/zone/gm_commands/movechar.cpp b/zone/gm_commands/movechar.cpp index 83e72cc37..1acde33a1 100755 --- a/zone/gm_commands/movechar.cpp +++ b/zone/gm_commands/movechar.cpp @@ -10,7 +10,7 @@ void command_movechar(Client *c, const Seperator *sep) std::string character_name = ( sep->IsNumber(1) ? - database.GetCharNameByID(std::stoul(sep->arg[1])) : + database.GetCharNameByID(Strings::ToUnsignedInt(sep->arg[1])) : sep->arg[1] ); auto character_id = database.GetCharacterID(character_name.c_str()); @@ -29,7 +29,7 @@ void command_movechar(Client *c, const Seperator *sep) std::string zone_short_name = Strings::ToLower( sep->IsNumber(2) ? - ZoneName(std::stoul(sep->arg[2]), true) : + ZoneName(Strings::ToUnsignedInt(sep->arg[2]), true) : sep->arg[2] ); @@ -39,7 +39,7 @@ void command_movechar(Client *c, const Seperator *sep) Chat::White, fmt::format( "Zone ID {} could not be found.", - std::stoul(sep->arg[2]) + Strings::ToUnsignedInt(sep->arg[2]) ).c_str() ); return; diff --git a/zone/gm_commands/movement.cpp b/zone/gm_commands/movement.cpp index f934f900c..daaedd7a5 100755 --- a/zone/gm_commands/movement.cpp +++ b/zone/gm_commands/movement.cpp @@ -61,11 +61,11 @@ void command_movement(Client *c, const Seperator *sep) mgr.SendCommandToClients( target, - atof(sep->arg[2]), - atof(sep->arg[3]), - atof(sep->arg[4]), - atof(sep->arg[5]), - atoi(sep->arg[6]), + Strings::ToFloat(sep->arg[2]), + Strings::ToFloat(sep->arg[3]), + Strings::ToFloat(sep->arg[4]), + Strings::ToFloat(sep->arg[5]), + Strings::ToInt(sep->arg[6]), ClientRangeAny ); } diff --git a/zone/gm_commands/network.cpp b/zone/gm_commands/network.cpp index 1c35d28ec..7f18e86ac 100755 --- a/zone/gm_commands/network.cpp +++ b/zone/gm_commands/network.cpp @@ -86,11 +86,11 @@ void command_network(Client *c, const Seperator *sep) std::string value = sep->arg[3]; if (!strcasecmp(sep->arg[2], "max_connection_count")) { - opts.daybreak_options.max_connection_count = std::stoull(value); + opts.daybreak_options.max_connection_count = Strings::ToUnsignedBigInt(value); manager->SetOptions(opts); } else if (!strcasecmp(sep->arg[2], "keepalive_delay_ms")) { - opts.daybreak_options.keepalive_delay_ms = std::stoull(value); + opts.daybreak_options.keepalive_delay_ms = Strings::ToUnsignedBigInt(value); manager->SetOptions(opts); } else if (!strcasecmp(sep->arg[2], "resend_delay_factor")) { @@ -98,51 +98,51 @@ void command_network(Client *c, const Seperator *sep) manager->SetOptions(opts); } else if (!strcasecmp(sep->arg[2], "resend_delay_ms")) { - opts.daybreak_options.resend_delay_ms = std::stoull(value); + opts.daybreak_options.resend_delay_ms = Strings::ToUnsignedBigInt(value); manager->SetOptions(opts); } else if (!strcasecmp(sep->arg[2], "resend_delay_min")) { - opts.daybreak_options.resend_delay_min = std::stoull(value); + opts.daybreak_options.resend_delay_min = Strings::ToUnsignedBigInt(value); manager->SetOptions(opts); } else if (!strcasecmp(sep->arg[2], "resend_delay_max")) { - opts.daybreak_options.resend_delay_max = std::stoull(value); + opts.daybreak_options.resend_delay_max = Strings::ToUnsignedBigInt(value); manager->SetOptions(opts); } else if (!strcasecmp(sep->arg[2], "connect_delay_ms")) { - opts.daybreak_options.connect_delay_ms = std::stoull(value); + opts.daybreak_options.connect_delay_ms = Strings::ToUnsignedBigInt(value); manager->SetOptions(opts); } else if (!strcasecmp(sep->arg[2], "connect_stale_ms")) { - opts.daybreak_options.connect_stale_ms = std::stoull(value); + opts.daybreak_options.connect_stale_ms = Strings::ToUnsignedBigInt(value); manager->SetOptions(opts); } else if (!strcasecmp(sep->arg[2], "stale_connection_ms")) { - opts.daybreak_options.stale_connection_ms = std::stoull(value); + opts.daybreak_options.stale_connection_ms = Strings::ToUnsignedBigInt(value); manager->SetOptions(opts); } else if (!strcasecmp(sep->arg[2], "hold_size")) { - opts.daybreak_options.hold_size = std::stoull(value); + opts.daybreak_options.hold_size = Strings::ToUnsignedBigInt(value); manager->SetOptions(opts); } else if (!strcasecmp(sep->arg[2], "hold_length_ms")) { - opts.daybreak_options.hold_length_ms = std::stoull(value); + opts.daybreak_options.hold_length_ms = Strings::ToUnsignedBigInt(value); manager->SetOptions(opts); } else if (!strcasecmp(sep->arg[2], "simulated_in_packet_loss")) { - opts.daybreak_options.simulated_in_packet_loss = std::stoull(value); + opts.daybreak_options.simulated_in_packet_loss = Strings::ToUnsignedBigInt(value); manager->SetOptions(opts); } else if (!strcasecmp(sep->arg[2], "simulated_out_packet_loss")) { - opts.daybreak_options.simulated_out_packet_loss = std::stoull(value); + opts.daybreak_options.simulated_out_packet_loss = Strings::ToUnsignedBigInt(value); manager->SetOptions(opts); } else if (!strcasecmp(sep->arg[2], "resend_timeout")) { - opts.daybreak_options.resend_timeout = std::stoull(value); + opts.daybreak_options.resend_timeout = Strings::ToUnsignedBigInt(value); manager->SetOptions(opts); } else if (!strcasecmp(sep->arg[2], "connection_close_time")) { - opts.daybreak_options.connection_close_time = std::stoull(value); + opts.daybreak_options.connection_close_time = Strings::ToUnsignedBigInt(value); manager->SetOptions(opts); } else { diff --git a/zone/gm_commands/npccast.cpp b/zone/gm_commands/npccast.cpp index 408e5e576..14cdb8395 100755 --- a/zone/gm_commands/npccast.cpp +++ b/zone/gm_commands/npccast.cpp @@ -10,7 +10,7 @@ void command_npccast(Client *c, const Seperator *sep) auto target = c->GetTarget()->CastToNPC(); if (!sep->IsNumber(1) && sep->arg[1] && sep->IsNumber(2)) { std::string entity_name = sep->arg[1] ? sep->arg[1] : 0; - auto spell_id = sep->arg[2] ? std::stoul(sep->arg[2]) : 0; + auto spell_id = sep->arg[2] ? Strings::ToUnsignedInt(sep->arg[2]) : 0; auto spell_target = entity_list.GetMob(entity_name.c_str()); if (spell_target && IsValidSpell(spell_id) && spell_id < SPDAT_RECORDS) { c->Message( @@ -45,8 +45,8 @@ void command_npccast(Client *c, const Seperator *sep) } } } else if (sep->IsNumber(1) && sep->IsNumber(2)) { - uint16 entity_id = static_cast(std::stoul(sep->arg[1])); - auto spell_id = std::stoul(sep->arg[2]); + uint16 entity_id = static_cast(Strings::ToUnsignedInt(sep->arg[1])); + auto spell_id = Strings::ToUnsignedInt(sep->arg[2]); auto spell_target = entity_list.GetMob(entity_id); if (spell_target && IsValidSpell(spell_id) && spell_id < SPDAT_RECORDS) { c->Message( diff --git a/zone/gm_commands/npcedit.cpp b/zone/gm_commands/npcedit.cpp index ddabd6380..26e449498 100755 --- a/zone/gm_commands/npcedit.cpp +++ b/zone/gm_commands/npcedit.cpp @@ -59,7 +59,7 @@ void command_npcedit(Client *c, const Seperator *sep) ); } else if (!strcasecmp(sep->arg[1], "level")) { if (sep->IsNumber(2)) { - auto level = static_cast(std::stoul(sep->arg[2])); + auto level = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.level = level; d = fmt::format( "{} is now level {}.", @@ -72,7 +72,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "race")) { if (sep->IsNumber(2)) { - auto race_id = static_cast(std::stoul(sep->arg[2])); + auto race_id = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.race = race_id; d = fmt::format( "{} is now a(n) {} ({}).", @@ -86,7 +86,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "class")) { if (sep->IsNumber(2)) { - auto class_id = static_cast(std::stoul(sep->arg[2])); + auto class_id = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.class_ = class_id; d = fmt::format( "{} is now a(n) {} ({}).", @@ -100,7 +100,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "bodytype")) { if (sep->IsNumber(2)) { - auto body_type_id = static_cast(std::stoul(sep->arg[2])); + auto body_type_id = static_cast(Strings::ToUnsignedInt(sep->arg[2])); auto body_type_name = EQ::constants::GetBodyTypeName(static_cast(body_type_id)); n.bodytype = body_type_id; d = fmt::format( @@ -122,7 +122,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "hp")) { if (sep->IsNumber(2)) { - auto hp = std::stoll(sep->arg[2]); + auto hp = Strings::ToBigInt(sep->arg[2]); n.hp = hp; d = fmt::format( "{} now has {} Health.", @@ -135,7 +135,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "mana")) { if (sep->IsNumber(2)) { - auto mana = std::stoll(sep->arg[2]); + auto mana = Strings::ToBigInt(sep->arg[2]); n.mana = mana; d = fmt::format( "{} now has {} Mana.", @@ -148,7 +148,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "gender")) { if (sep->IsNumber(2)) { - auto gender_id = static_cast(std::stoul(sep->arg[2])); + auto gender_id = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.gender = gender_id; d = fmt::format( "{} is now a {} ({}).", @@ -162,7 +162,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "texture")) { if (sep->IsNumber(2)) { - auto texture = static_cast(std::stoul(sep->arg[2])); + auto texture = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.texture = texture; d = fmt::format( "{} is now using Texture {}.", @@ -175,7 +175,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "helmtexture")) { if (sep->IsNumber(2)) { - auto helmet_texture = static_cast(std::stoul(sep->arg[2])); + auto helmet_texture = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.helmtexture = helmet_texture; d = fmt::format( "{} is now using Helmet Texture {}.", @@ -188,7 +188,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "herosforgemodel")) { if (sep->IsNumber(2)) { - auto heros_forge_model = std::stoi(sep->arg[2]); + auto heros_forge_model = Strings::ToInt(sep->arg[2]); n.herosforgemodel = heros_forge_model; d = fmt::format( "{} is now using Hero's Forge Model {}.", @@ -204,7 +204,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "size")) { if (sep->IsNumber(2)) { - auto size = std::stof(sep->arg[2]); + auto size = Strings::ToFloat(sep->arg[2]); n.size = size; d = fmt::format( "{} is now Size {:.2f}.", @@ -217,7 +217,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "hpregen")) { if (sep->IsNumber(2)) { - auto hp_regen = std::stoll(sep->arg[2]); + auto hp_regen = Strings::ToBigInt(sep->arg[2]); n.hp_regen_rate = hp_regen; d = fmt::format( "{} now regenerates {} Health per Tick.", @@ -230,7 +230,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "hp_regen_per_second")) { if (sep->IsNumber(2)) { - auto hp_regen_per_second = std::stoll(sep->arg[2]); + auto hp_regen_per_second = Strings::ToBigInt(sep->arg[2]); n.hp_regen_per_second = hp_regen_per_second; d = fmt::format( "{} now regenerates {} HP per Second.", @@ -246,7 +246,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "manaregen")) { if (sep->IsNumber(2)) { - auto mana_regen = std::stoll(sep->arg[2]); + auto mana_regen = Strings::ToBigInt(sep->arg[2]); n.mana_regen_rate = mana_regen; d = fmt::format( "{} now regenerates {} Mana per Tick.", @@ -259,7 +259,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "loottable")) { if (sep->IsNumber(2)) { - auto loottable_id = std::stoul(sep->arg[2]); + auto loottable_id = Strings::ToUnsignedInt(sep->arg[2]); n.loottable_id = loottable_id; d = fmt::format( "{} is now using Loottable ID {}.", @@ -272,7 +272,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "merchantid")) { if (sep->IsNumber(2)) { - auto merchant_id = std::stoul(sep->arg[2]); + auto merchant_id = Strings::ToUnsignedInt(sep->arg[2]); n.merchant_id = merchant_id; d = fmt::format( "{} is now using Merchant ID {}.", @@ -285,7 +285,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "alt_currency_id")) { if (sep->IsNumber(2)) { - auto alternate_currency_id = std::stoul(sep->arg[2]); + auto alternate_currency_id = Strings::ToUnsignedInt(sep->arg[2]); auto alternate_currency_item_id = zone->GetCurrencyItemID(alternate_currency_id); n.alt_currency_id = alternate_currency_id; d = fmt::format( @@ -310,7 +310,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "spell")) { if (sep->IsNumber(2)) { - auto spell_list_id = std::stoul(sep->arg[2]); + auto spell_list_id = Strings::ToUnsignedInt(sep->arg[2]); n.npc_spells_id = spell_list_id; d = fmt::format( "{} is now using Spell List ID {}.", @@ -323,7 +323,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "npc_spells_effects_id")) { if (sep->IsNumber(2)) { - auto spell_effects_id = std::stoul(sep->arg[2]); + auto spell_effects_id = Strings::ToUnsignedInt(sep->arg[2]); n.npc_spells_effects_id = spell_effects_id; d = fmt::format( "{} is now using Spells Effects ID {}.", @@ -339,7 +339,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "faction")) { if (sep->IsNumber(2)) { - auto faction_id = std::stoi(sep->arg[2]); + auto faction_id = Strings::ToInt(sep->arg[2]); auto faction_name = content_db.GetFactionName(faction_id); n.npc_faction_id = faction_id; d = fmt::format( @@ -361,7 +361,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "adventure_template_id")) { if (sep->IsNumber(2)) { - auto adventure_template_id = std::stoul(sep->arg[2]); + auto adventure_template_id = Strings::ToUnsignedInt(sep->arg[2]); n.adventure_template_id = adventure_template_id; d = fmt::format( "{} is now using Adventure Template ID {}.", @@ -377,7 +377,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "trap_template")) { if (sep->IsNumber(2)) { - auto trap_template = std::stoul(sep->arg[2]); + auto trap_template = Strings::ToUnsignedInt(sep->arg[2]); n.trap_template = trap_template; d = fmt::format( "{} is now using Trap Template ID {}.", @@ -390,8 +390,8 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "damage")) { if (sep->IsNumber(2) && sep->IsNumber(3)) { - auto minimum_damage = std::stoul(sep->arg[2]); - auto maximum_damage = std::stoul(sep->arg[3]); + auto minimum_damage = Strings::ToUnsignedInt(sep->arg[2]); + auto maximum_damage = Strings::ToUnsignedInt(sep->arg[3]); n.mindmg = minimum_damage; n.maxdmg = maximum_damage; d = fmt::format( @@ -406,7 +406,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "attackcount")) { if (sep->IsNumber(2)) { - auto attack_count = static_cast(std::stoi(sep->arg[2])); + auto attack_count = static_cast(Strings::ToInt(sep->arg[2])); n.attack_count = attack_count; d = fmt::format( "{} now has an Attack Count of {}.", @@ -441,7 +441,7 @@ void command_npcedit(Client *c, const Seperator *sep) ); } else if (!strcasecmp(sep->arg[1], "aggroradius")) { if (sep->IsNumber(2)) { - auto aggro_radius = std::stoul(sep->arg[2]); + auto aggro_radius = Strings::ToUnsignedInt(sep->arg[2]); n.aggroradius = aggro_radius; d = fmt::format( "{} now has an Aggro Radius of {}.", @@ -454,7 +454,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "assistradius")) { if (sep->IsNumber(2)) { - auto assist_radius = std::stoul(sep->arg[2]); + auto assist_radius = Strings::ToUnsignedInt(sep->arg[2]); n.assistradius = assist_radius; d = fmt::format( "{} now has an Assist Radius of {}", @@ -487,7 +487,7 @@ void command_npcedit(Client *c, const Seperator *sep) n.drakkin_details = t->GetDrakkinDetails(); } else if (!strcasecmp(sep->arg[1], "armortint_id")) { if (sep->IsNumber(2)) { - auto armor_tint_id = std::stoul(sep->arg[2]); + auto armor_tint_id = Strings::ToUnsignedInt(sep->arg[2]); n.armortint_id = armor_tint_id; d = fmt::format( "{} is now using Armor Tint ID {}.", @@ -500,9 +500,9 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "color")) { if (sep->IsNumber(2)) { - auto red = static_cast(std::stoul(sep->arg[2])); - uint8_t green = sep->IsNumber(3) ? static_cast(std::stoul(sep->arg[3])) : 0; - uint8_t blue = sep->IsNumber(4) ? static_cast(std::stoul(sep->arg[4])) : 0; + auto red = static_cast(Strings::ToUnsignedInt(sep->arg[2])); + uint8_t green = sep->IsNumber(3) ? static_cast(Strings::ToUnsignedInt(sep->arg[3])) : 0; + uint8_t blue = sep->IsNumber(4) ? static_cast(Strings::ToUnsignedInt(sep->arg[4])) : 0; n.armortint_red = red; n.armortint_green = green; n.armortint_blue = blue; @@ -522,7 +522,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "ammoidfile")) { if (sep->IsNumber(2)) { - auto ammo_id_file = std::stoul(sep->arg[2]); + auto ammo_id_file = Strings::ToUnsignedInt(sep->arg[2]); n.ammo_idfile = ammo_id_file; d = fmt::format( "{} is now using Ammo ID File {}.", @@ -535,15 +535,15 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "weapon")) { if (sep->IsNumber(2)) { - auto primary_model = std::stoul(sep->arg[2]); - uint32_t secondary_model = sep->IsNumber(3) ? std::stoul(sep->arg[3]) : 0; + auto primary_model = Strings::ToUnsignedInt(sep->arg[2]); + uint32_t secondary_model = sep->arg[3] && sep->IsNumber(3) ? Strings::ToUnsignedInt(sep->arg[3]) : 0; n.d_melee_texture1 = primary_model; n.d_melee_texture2 = secondary_model; d = fmt::format( "{} will have Model {} set to their Primary and Model {} set to their Secondary on repop.", npc_id_string, Strings::Commify(sep->arg[2]), - sep->IsNumber(3) ? Strings::Commify(sep->arg[3]) : 0 + sep->arg[3] && sep->IsNumber(3) ? Strings::Commify(sep->arg[3]) : 0 ); } else { c->Message( @@ -554,8 +554,8 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "meleetype")) { if (sep->IsNumber(2)) { - auto primary_type = std::stoul(sep->arg[2]); - uint32_t secondary_type = sep->IsNumber(3) ? std::stoul(sep->arg[3]) : 0; + auto primary_type = Strings::ToUnsignedInt(sep->arg[2]); + uint32_t secondary_type = sep->IsNumber(3) ? Strings::ToUnsignedInt(sep->arg[3]) : 0; auto primary_skill = EQ::skills::GetSkillName(static_cast(primary_type)); auto secondary_skill = EQ::skills::GetSkillName(static_cast(secondary_type)); @@ -594,7 +594,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "rangedtype")) { if (sep->IsNumber(2)) { - auto ranged_type = std::stoul(sep->arg[2]); + auto ranged_type = Strings::ToUnsignedInt(sep->arg[2]); auto ranged_skill = EQ::skills::GetSkillName(static_cast(ranged_type)); @@ -619,7 +619,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "runspeed")) { if (sep->IsNumber(2)) { - auto run_speed = std::stof(sep->arg[2]); + auto run_speed = Strings::ToFloat(sep->arg[2]); n.runspeed = run_speed; d = fmt::format( "{} now runs at a Run Speed of {:.2f}.", @@ -632,7 +632,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "mr")) { if (sep->IsNumber(2)) { - auto magic_resist = static_cast(std::stoul(sep->arg[2])); + auto magic_resist = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.MR = magic_resist; d = fmt::format( "{} now has a Magic Resistance of {}.", @@ -645,7 +645,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "pr")) { if (sep->IsNumber(2)) { - auto poison_resist = static_cast(std::stoul(sep->arg[2])); + auto poison_resist = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.PR = poison_resist; d = fmt::format( "{} now has a Poison Resistance of {}.", @@ -658,7 +658,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "dr")) { if (sep->IsNumber(2)) { - auto disease_resist = static_cast(std::stoul(sep->arg[2])); + auto disease_resist = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.DR = disease_resist; d = fmt::format( "{} now has a Disease Resistance of {}.", @@ -671,7 +671,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "fr")) { if (sep->IsNumber(2)) { - auto fire_resist = static_cast(std::stoul(sep->arg[2])); + auto fire_resist = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.FR = fire_resist; d = fmt::format( "{} now has a Fire Resistance of {}.", @@ -684,7 +684,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "cr")) { if (sep->IsNumber(2)) { - auto cold_resist = static_cast(std::stoul(sep->arg[2])); + auto cold_resist = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.CR = cold_resist; d = fmt::format( "{} now has a Cold Resistance of {}.", @@ -697,7 +697,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "corrup")) { if (sep->IsNumber(2)) { - auto corruption_resist = static_cast(std::stoul(sep->arg[2])); + auto corruption_resist = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.Corrup = corruption_resist; d = fmt::format( "{} now has a Corruption Resistance of {}.", @@ -710,7 +710,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "phr")) { if (sep->IsNumber(2)) { - auto physical_resist = static_cast(std::stoul(sep->arg[2])); + auto physical_resist = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.PhR = physical_resist; d = fmt::format( "{} now has a Physical Resistance of {}.", @@ -723,7 +723,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "seeinvis")) { if (sep->IsNumber(2)) { - auto see_invisible = static_cast(std::stoul(sep->arg[2])); + auto see_invisible = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.see_invis = see_invisible; d = fmt::format( "{} can {} See Invisible.", @@ -739,7 +739,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "seeinvisundead")) { if (sep->IsNumber(2)) { - auto see_invisible_undead = static_cast(std::stoul(sep->arg[2])); + auto see_invisible_undead = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.see_invis_undead = see_invisible_undead; d = fmt::format( "{} can {} See Invisible vs. Undead.", @@ -755,7 +755,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "qglobal")) { if (sep->IsNumber(2)) { - auto use_qglobals = std::stoul(sep->arg[2]); + auto use_qglobals = Strings::ToUnsignedInt(sep->arg[2]); n.qglobal = use_qglobals; d = fmt::format( "{} can {} use Quest Globals.", @@ -771,7 +771,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "ac")) { if (sep->IsNumber(2)) { - auto armor_class = static_cast(std::stoul(sep->arg[2])); + auto armor_class = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.AC = armor_class; d = fmt::format( "{} now has {} Armor Class.", @@ -784,7 +784,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "npcaggro")) { if (sep->IsNumber(2)) { - auto aggro_npcs = static_cast(std::stoul(sep->arg[2])); + auto aggro_npcs = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.npc_aggro = aggro_npcs; d = fmt::format( "{} will {} aggro other NPCs that have a hostile faction.", @@ -800,7 +800,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "spawn_limit")) { if (sep->IsNumber(2)) { - auto spawn_limit = static_cast(std::stoul(sep->arg[2])); + auto spawn_limit = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.spawn_limit = spawn_limit; d = fmt::format( "{} now has a Spawn Limit of {}.", @@ -813,7 +813,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "attackspeed")) { if (sep->IsNumber(2)) { - auto attack_speed = std::stof(sep->arg[2]); + auto attack_speed = Strings::ToFloat(sep->arg[2]); n.attack_speed = attack_speed; d = fmt::format( "{} now has an Attack Speed of {:.2f}.", @@ -826,7 +826,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "attackdelay")) { if (sep->IsNumber(2)) { - auto attack_delay = static_cast(std::stoul(sep->arg[2])); + auto attack_delay = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.attack_delay = attack_delay; d = fmt::format( "{} now has an Attack Delay of {}.", @@ -839,7 +839,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "findable")) { if (sep->IsNumber(2)) { - auto is_findable = static_cast(std::stoul(sep->arg[2])); + auto is_findable = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.findable = is_findable; d = fmt::format( "{} is {} Findable.", @@ -855,7 +855,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "str")) { if (sep->IsNumber(2)) { - auto strength = std::stoul(sep->arg[2]); + auto strength = Strings::ToUnsignedInt(sep->arg[2]); n.STR = strength; d = fmt::format( "{} now has {} Strength.", @@ -868,7 +868,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "sta")) { if (sep->IsNumber(2)) { - auto stamina = std::stoul(sep->arg[2]); + auto stamina = Strings::ToUnsignedInt(sep->arg[2]); n.STA = stamina; d = fmt::format( "{} now has {} Stamina.", @@ -881,7 +881,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "agi")) { if (sep->IsNumber(2)) { - auto agility = std::stoul(sep->arg[2]); + auto agility = Strings::ToUnsignedInt(sep->arg[2]); n.AGI = agility; d = fmt::format( "{} now has {} Agility.", @@ -894,7 +894,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "dex")) { if (sep->IsNumber(2)) { - auto dexterity = std::stoul(sep->arg[2]); + auto dexterity = Strings::ToUnsignedInt(sep->arg[2]); n.DEX = dexterity; d = fmt::format( "{} now has {} Dexterity.", @@ -907,7 +907,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "int")) { if (sep->IsNumber(2)) { - auto intelligence = std::stoul(sep->arg[2]); + auto intelligence = Strings::ToUnsignedInt(sep->arg[2]); n._INT = intelligence; d = fmt::format( "{} now has {} Intelligence.", @@ -920,7 +920,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "wis")) { if (sep->IsNumber(2)) { - auto wisdom = std::stoul(sep->arg[2]); + auto wisdom = Strings::ToUnsignedInt(sep->arg[2]); n.WIS = wisdom; d = fmt::format( "{} now has {} Wisdom.", @@ -933,7 +933,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "cha")) { if (sep->IsNumber(2)) { - auto charisma = std::stoul(sep->arg[2]); + auto charisma = Strings::ToUnsignedInt(sep->arg[2]); n.CHA = charisma; d = fmt::format( "{} now has {} Charisma.", @@ -946,7 +946,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "seehide")) { if (sep->IsNumber(2)) { - auto see_hide = static_cast(std::stoi(sep->arg[2])); + auto see_hide = static_cast(Strings::ToInt(sep->arg[2])); n.see_hide = see_hide; d = fmt::format( "{} can {} See Hide.", @@ -962,7 +962,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "seeimprovedhide")) { if (sep->IsNumber(2)) { - auto see_improved_hide = static_cast(std::stoi(sep->arg[2])); + auto see_improved_hide = static_cast(Strings::ToInt(sep->arg[2])); n.see_improved_hide = see_improved_hide; d = fmt::format( "{} can {} See Improved Hide.", @@ -978,7 +978,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "trackable")) { if (sep->IsNumber(2)) { - auto is_trackable = static_cast(std::stoi(sep->arg[2])); + auto is_trackable = static_cast(Strings::ToInt(sep->arg[2])); n.trackable = is_trackable; d = fmt::format( "{} is {} Trackable.", @@ -994,7 +994,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "atk")) { if (sep->IsNumber(2)) { - auto attack = std::stoi(sep->arg[2]); + auto attack = Strings::ToInt(sep->arg[2]); n.ATK = attack; d = fmt::format( "{} now has {} Attack.", @@ -1007,7 +1007,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "accuracy")) { if (sep->IsNumber(2)) { - auto accuracy = std::stoi(sep->arg[2]); + auto accuracy = Strings::ToInt(sep->arg[2]); n.Accuracy = accuracy; d = fmt::format( "{} now has {} Accuracy.", @@ -1020,7 +1020,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "avoidance")) { if (sep->IsNumber(2)) { - auto avoidance = std::stoul(sep->arg[2]); + auto avoidance = Strings::ToUnsignedInt(sep->arg[2]); n.Avoidance = avoidance; d = fmt::format( "{} now has {} Avoidance.", @@ -1033,7 +1033,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "slow_mitigation")) { if (sep->IsNumber(2)) { - auto slow_mitigation = static_cast(std::stoi(sep->arg[2])); + auto slow_mitigation = static_cast(Strings::ToInt(sep->arg[2])); n.slow_mitigation = slow_mitigation; d = fmt::format( "{} now has {} Slow Mitigation.", @@ -1049,7 +1049,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "version")) { if (sep->IsNumber(2)) { - auto version = static_cast(std::stoul(sep->arg[2])); + auto version = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.version = version; d = fmt::format( "{} is now using Version {}.", @@ -1062,7 +1062,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "maxlevel")) { if (sep->IsNumber(2)) { - auto max_level = static_cast(std::stoi(sep->arg[2])); + auto max_level = static_cast(Strings::ToInt(sep->arg[2])); n.maxlevel = max_level; d = fmt::format( "{} now has a Maximum Level of {}.", @@ -1075,7 +1075,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "scalerate")) { if (sep->IsNumber(2)) { - auto scale_rate = std::stoi(sep->arg[2]); + auto scale_rate = Strings::ToInt(sep->arg[2]); n.scalerate = scale_rate; d = fmt::format( "{} now has a Scaling Rate of {}%%.", @@ -1091,7 +1091,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "spellscale")) { if (sep->IsNumber(2)) { - auto spell_scale = std::stoul(sep->arg[2]); + auto spell_scale = Strings::ToUnsignedInt(sep->arg[2]); n.spellscale = static_cast(spell_scale); d = fmt::format( "{} now has a Spell Scaling Rate of {}%%.", @@ -1107,7 +1107,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "healscale")) { if (sep->IsNumber(2)) { - auto heal_scale = std::stoul(sep->arg[2]); + auto heal_scale = Strings::ToUnsignedInt(sep->arg[2]); n.healscale = static_cast(heal_scale); d = fmt::format( "{} now has a Heal Scaling Rate of {}%%.", @@ -1123,7 +1123,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "no_target")) { if (sep->IsNumber(2)) { - auto is_no_target = static_cast(std::stoul(sep->arg[2])); + auto is_no_target = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.no_target_hotkey = is_no_target; d = fmt::format( "{} is {} Targetable with Target Hotkey.", @@ -1139,7 +1139,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "raidtarget")) { if (sep->IsNumber(2)) { - auto is_raid_target = static_cast(std::stoul(sep->arg[2])); + auto is_raid_target = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.raid_target = is_raid_target; d = fmt::format( "{} is {} designated as a Raid Target.", @@ -1155,7 +1155,7 @@ void command_npcedit(Client *c, const Seperator *sep) return; } else if (!strcasecmp(sep->arg[1], "armtexture")) { if (sep->IsNumber(2)) { - auto arm_texture = static_cast(std::stoi(sep->arg[2])); + auto arm_texture = static_cast(Strings::ToInt(sep->arg[2])); n.armtexture = arm_texture; d = fmt::format( "{} is now using Arm Texture {}.", @@ -1168,7 +1168,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "bracertexture")) { if (sep->IsNumber(2)) { - auto bracer_texture = static_cast(std::stoi(sep->arg[2])); + auto bracer_texture = static_cast(Strings::ToInt(sep->arg[2])); n.bracertexture = bracer_texture; d = fmt::format( "{} is now using Bracer Texture {}.", @@ -1181,7 +1181,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "handtexture")) { if (sep->IsNumber(2)) { - auto hand_texture = static_cast(std::stoi(sep->arg[2])); + auto hand_texture = static_cast(Strings::ToInt(sep->arg[2])); n.handtexture = hand_texture; d = fmt::format( "{} is now using Hand Texture {}.", @@ -1194,7 +1194,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "legtexture")) { if (sep->IsNumber(2)) { - auto leg_texture = static_cast(std::stoi(sep->arg[2])); + auto leg_texture = static_cast(Strings::ToInt(sep->arg[2])); n.legtexture = leg_texture; d = fmt::format( "{} is now using Leg Texture {}.", @@ -1207,7 +1207,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "feettexture")) { if (sep->IsNumber(2)) { - auto feet_texture = static_cast(std::stoi(sep->arg[2])); + auto feet_texture = static_cast(Strings::ToInt(sep->arg[2])); n.feettexture = feet_texture; d = fmt::format( "{} is now using Feet Texture {}.", @@ -1220,7 +1220,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "walkspeed")) { if (sep->IsNumber(2)) { - auto walk_speed = static_cast(std::stoi(sep->arg[2])); + auto walk_speed = static_cast(Strings::ToInt(sep->arg[2])); n.walkspeed = walk_speed; d = fmt::format( "{} now walks at a Walk Speed of {}.", @@ -1233,7 +1233,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "show_name")) { if (sep->IsNumber(2)) { - auto show_name = static_cast(std::stoi(sep->arg[2])); + auto show_name = static_cast(Strings::ToInt(sep->arg[2])); n.show_name = show_name; d = fmt::format( "{} will {} show their name.", @@ -1249,7 +1249,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "untargetable")) { if (sep->IsNumber(2)) { - auto is_untargetable = static_cast(std::stoi(sep->arg[2])); + auto is_untargetable = static_cast(Strings::ToInt(sep->arg[2])); n.untargetable = is_untargetable; d = fmt::format( "{} will {} be untargetable.", @@ -1265,7 +1265,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "charm_ac")) { if (sep->IsNumber(2)) { - auto charm_armor_class = static_cast(std::stoi(sep->arg[2])); + auto charm_armor_class = static_cast(Strings::ToInt(sep->arg[2])); n.charm_ac = charm_armor_class; d = fmt::format( "{} now has {} Armor Class while Charmed.", @@ -1278,7 +1278,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "charm_min_dmg")) { if (sep->IsNumber(2)) { - auto charm_minimum_damage = std::stoi(sep->arg[2]); + auto charm_minimum_damage = Strings::ToInt(sep->arg[2]); n.charm_min_dmg = charm_minimum_damage; d = fmt::format( "{} now does {} Minimum Damage while Charmed.", @@ -1294,7 +1294,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "charm_max_dmg")) { if (sep->IsNumber(2)) { - auto charm_maximum_damage = std::stoi(sep->arg[2]); + auto charm_maximum_damage = Strings::ToInt(sep->arg[2]); n.charm_max_dmg = charm_maximum_damage; d = fmt::format( "{} now does {} Maximum Damage while Charmed.", @@ -1310,7 +1310,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "charm_attack_delay")) { if (sep->IsNumber(2)) { - auto charm_attack_delay = static_cast(std::stoi(sep->arg[2])); + auto charm_attack_delay = static_cast(Strings::ToInt(sep->arg[2])); n.charm_attack_delay = charm_attack_delay; d = fmt::format( "{} now has {} Attack Delay while Charmed.", @@ -1326,7 +1326,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "charm_accuracy_rating")) { if (sep->IsNumber(2)) { - auto charm_accuracy_rating = std::stoi(sep->arg[2]); + auto charm_accuracy_rating = Strings::ToInt(sep->arg[2]); n.charm_accuracy_rating = charm_accuracy_rating; d = fmt::format( "{} now has {} Accuracy Rating while Charmed.", @@ -1342,7 +1342,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "charm_avoidance_rating")) { if (sep->IsNumber(2)) { - auto charm_avoidance_rating = std::stoi(sep->arg[2]); + auto charm_avoidance_rating = Strings::ToInt(sep->arg[2]); n.charm_avoidance_rating = charm_avoidance_rating; d = fmt::format( "{} now has {} Avoidance Rating while Charmed.", @@ -1358,7 +1358,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "charm_atk")) { if (sep->IsNumber(2)) { - auto charm_attack = std::stoi(sep->arg[2]); + auto charm_attack = Strings::ToInt(sep->arg[2]); n.charm_atk = charm_attack; d = fmt::format( "{} now has {} Attack while Charmed.", @@ -1371,7 +1371,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "skip_global_loot")) { if (sep->IsNumber(2)) { - auto skip_global_loot = static_cast(std::stoi(sep->arg[2])); + auto skip_global_loot = static_cast(Strings::ToInt(sep->arg[2])); n.skip_global_loot = skip_global_loot; d = fmt::format( "{} will {} skip Global Loot.", @@ -1387,7 +1387,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "rarespawn")) { if (sep->IsNumber(2)) { - auto is_rare_spawn = static_cast(std::stoi(sep->arg[2])); + auto is_rare_spawn = static_cast(Strings::ToInt(sep->arg[2])); n.rare_spawn = is_rare_spawn; d = fmt::format( "{} is {} designated as a Rare Spawn.", @@ -1403,7 +1403,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "stuck_behavior")) { if (sep->IsNumber(2)) { - auto behavior_id = static_cast(std::stoi(sep->arg[2])); + auto behavior_id = static_cast(Strings::ToInt(sep->arg[2])); if (behavior_id > EQ::constants::StuckBehavior::EvadeCombat) { behavior_id = EQ::constants::StuckBehavior::EvadeCombat; } @@ -1432,7 +1432,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "flymode")) { if (sep->IsNumber(2)) { - auto flymode_id = static_cast(std::stoi(sep->arg[2])); + auto flymode_id = static_cast(Strings::ToInt(sep->arg[2])); if (flymode_id > GravityBehavior::LevitateWhileRunning) { flymode_id = GravityBehavior::LevitateWhileRunning; } @@ -1461,7 +1461,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "always_aggro")) { if (sep->IsNumber(2)) { - auto always_aggro = static_cast(std::stoi(sep->arg[2])); + auto always_aggro = static_cast(Strings::ToInt(sep->arg[2])); n.always_aggro = always_aggro; d = fmt::format( "{} will {} Always Aggro.", @@ -1477,7 +1477,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "exp_mod")) { if (sep->IsNumber(2)) { - auto experience_modifier = std::stoi(sep->arg[2]); + auto experience_modifier = Strings::ToInt(sep->arg[2]); n.exp_mod = experience_modifier; d = fmt::format( "{} now has an Experience Modifier of {}%%.", @@ -1493,7 +1493,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "keeps_sold_items")) { if (sep->IsNumber(2)) { - auto keeps_sold_items = static_cast(std::stoul(sep->arg[2])); + auto keeps_sold_items = static_cast(Strings::ToUnsignedInt(sep->arg[2])); n.keeps_sold_items = keeps_sold_items; d = fmt::format( "{} will {} Keep Sold Items.", @@ -1509,7 +1509,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "setanimation")) { if (sep->IsNumber(2)) { - auto animation_id = std::stoul(sep->arg[2]); + auto animation_id = Strings::ToUnsignedInt(sep->arg[2]); if (animation_id > EQ::constants::SpawnAnimations::Looting) { animation_id = EQ::constants::SpawnAnimations::Looting; } @@ -1546,7 +1546,7 @@ void command_npcedit(Client *c, const Seperator *sep) } } else if (!strcasecmp(sep->arg[1], "respawntime")) { if (sep->IsNumber(2)) { - auto respawn_time = std::stoul(sep->arg[2]); + auto respawn_time = Strings::ToUnsignedInt(sep->arg[2]); if (respawn_time) { d = fmt::format( "{} now has a Respawn Timer of {} ({}) on Spawn Group ID {}.", diff --git a/zone/gm_commands/npcloot.cpp b/zone/gm_commands/npcloot.cpp index a3c50854f..2bb8873bb 100755 --- a/zone/gm_commands/npcloot.cpp +++ b/zone/gm_commands/npcloot.cpp @@ -42,15 +42,15 @@ void command_npcloot(Client *c, const Seperator *sep) return; } - auto item_id = std::stoul(sep->arg[2]); - auto item_charges = sep->IsNumber(3) ? static_cast(std::stoul(sep->arg[3])) : 1; + auto item_id = Strings::ToUnsignedInt(sep->arg[2]); + auto item_charges = sep->IsNumber(3) ? static_cast(Strings::ToUnsignedInt(sep->arg[3])) : 1; bool equip_item = arguments >= 4 ? atobool(sep->arg[4]) : false; - auto augment_one_id = sep->IsNumber(5) ? std::stoul(sep->arg[5]) : 0; - auto augment_two_id = sep->IsNumber(6) ? std::stoul(sep->arg[6]) : 0; - auto augment_three_id = sep->IsNumber(7) ? std::stoul(sep->arg[7]) : 0; - auto augment_four_id = sep->IsNumber(8) ? std::stoul(sep->arg[8]) : 0; - auto augment_five_id = sep->IsNumber(9) ? std::stoul(sep->arg[9]) : 0; - auto augment_six_id = sep->IsNumber(10) ? std::stoul(sep->arg[10]) : 0; + auto augment_one_id = sep->IsNumber(5) ? Strings::ToUnsignedInt(sep->arg[5]) : 0; + auto augment_two_id = sep->IsNumber(6) ? Strings::ToUnsignedInt(sep->arg[6]) : 0; + auto augment_three_id = sep->IsNumber(7) ? Strings::ToUnsignedInt(sep->arg[7]) : 0; + auto augment_four_id = sep->IsNumber(8) ? Strings::ToUnsignedInt(sep->arg[8]) : 0; + auto augment_five_id = sep->IsNumber(9) ? Strings::ToUnsignedInt(sep->arg[9]) : 0; + auto augment_six_id = sep->IsNumber(10) ? Strings::ToUnsignedInt(sep->arg[10]) : 0; auto item_data = database.GetItem(item_id); @@ -114,10 +114,10 @@ void command_npcloot(Client *c, const Seperator *sep) auto target = c->GetTarget()->CastToNPC(); if (sep->IsNumber(2)) { - uint16 platinum = EQ::Clamp(std::stoi(sep->arg[2]), 0, 65535); - uint16 gold = sep->IsNumber(3) ? EQ::Clamp(std::stoi(sep->arg[3]), 0, 65535) : 0; - uint16 silver = sep->IsNumber(4) ? EQ::Clamp(std::stoi(sep->arg[4]), 0, 65535) : 0; - uint16 copper = sep->IsNumber(5) ? EQ::Clamp(std::stoi(sep->arg[5]), 0, 65535) : 0; + uint16 platinum = EQ::Clamp(Strings::ToInt(sep->arg[2]), 0, 65535); + uint16 gold = sep->IsNumber(3) ? EQ::Clamp(Strings::ToInt(sep->arg[3]), 0, 65535) : 0; + uint16 silver = sep->IsNumber(4) ? EQ::Clamp(Strings::ToInt(sep->arg[4]), 0, 65535) : 0; + uint16 copper = sep->IsNumber(5) ? EQ::Clamp(Strings::ToInt(sep->arg[5]), 0, 65535) : 0; target->AddCash( copper, silver, @@ -204,7 +204,7 @@ void command_npcloot(Client *c, const Seperator *sep) } } else { if (sep->IsNumber(2)) { - auto item_id = std::stoul(sep->arg[2]); + auto item_id = Strings::ToUnsignedInt(sep->arg[2]); auto item_count = target->CountItem(item_id); if (item_count) { target->RemoveItem(item_id); diff --git a/zone/gm_commands/npcspawn.cpp b/zone/gm_commands/npcspawn.cpp index a6ea88899..8c1815214 100755 --- a/zone/gm_commands/npcspawn.cpp +++ b/zone/gm_commands/npcspawn.cpp @@ -36,7 +36,7 @@ void command_npcspawn(Client *c, const Seperator *sep) sep->IsNumber(2) ? ( is_add ? - std::stoi(sep->arg[2]) : + Strings::ToInt(sep->arg[2]) : 1 ) : ( is_add ? diff --git a/zone/gm_commands/npctypespawn.cpp b/zone/gm_commands/npctypespawn.cpp index 81d47cfcd..9bbc77ba7 100755 --- a/zone/gm_commands/npctypespawn.cpp +++ b/zone/gm_commands/npctypespawn.cpp @@ -8,7 +8,7 @@ void command_npctypespawn(Client *c, const Seperator *sep) return; } - auto npc_id = std::stoul(sep->arg[1]); + auto npc_id = Strings::ToUnsignedInt(sep->arg[1]); int faction_id = 0; auto npc_type = content_db.LoadNPCTypesData(npc_id); @@ -16,7 +16,7 @@ void command_npctypespawn(Client *c, const Seperator *sep) auto npc = new NPC(npc_type, 0, c->GetPosition(), GravityBehavior::Water); if (npc) { if (sep->IsNumber(2)) { - faction_id = std::stoi(sep->arg[2]); + faction_id = Strings::ToInt(sep->arg[2]); npc->SetNPCFactionID(faction_id); } diff --git a/zone/gm_commands/nudge.cpp b/zone/gm_commands/nudge.cpp index 0d80acacd..d1219261e 100755 --- a/zone/gm_commands/nudge.cpp +++ b/zone/gm_commands/nudge.cpp @@ -39,16 +39,16 @@ void command_nudge(Client *c, const Seperator *sep) switch (argsep.arg[0][0]) { case 'x': - position_offset.x = std::stof(argsep.arg[1]); + position_offset.x = Strings::ToFloat(argsep.arg[1]); break; case 'y': - position_offset.y = std::stof(argsep.arg[1]); + position_offset.y = Strings::ToFloat(argsep.arg[1]); break; case 'z': - position_offset.z = std::stof(argsep.arg[1]); + position_offset.z = Strings::ToFloat(argsep.arg[1]); break; case 'h': - position_offset.w = std::stof(argsep.arg[1]); + position_offset.w = Strings::ToFloat(argsep.arg[1]); break; default: break; diff --git a/zone/gm_commands/nukeitem.cpp b/zone/gm_commands/nukeitem.cpp index d31cba7aa..0918ce1e0 100755 --- a/zone/gm_commands/nukeitem.cpp +++ b/zone/gm_commands/nukeitem.cpp @@ -12,8 +12,8 @@ void command_nukeitem(Client *c, const Seperator *sep) if (c->GetTarget() && c->GetTarget()->IsClient()) { target = c->GetTarget()->CastToClient(); } - - auto item_id = std::stoi(sep->arg[1]); + + auto item_id = Strings::ToInt(sep->arg[1]); auto deleted_count = target->NukeItem(item_id); if (deleted_count) { c->Message( diff --git a/zone/gm_commands/object.cpp b/zone/gm_commands/object.cpp index 0784ec2d2..df8f090f8 100755 --- a/zone/gm_commands/object.cpp +++ b/zone/gm_commands/object.cpp @@ -50,7 +50,7 @@ void command_object(Client *c, const Seperator *sep) if ((sep->arg[2][0] & 0xDF) == 'A') { radius = 0; // List All } - else if ((radius = atoi(sep->arg[2])) <= 0) { + else if ((radius = Strings::ToInt(sep->arg[2])) <= 0) { radius = 500; } // Invalid radius. Default to 500 units. @@ -89,21 +89,21 @@ void command_object(Client *c, const Seperator *sep) } for (auto row = results.begin(); row != results.end(); ++row) { - id = atoi(row[0]); - od.x = atof(row[1]); - od.y = atof(row[2]); - od.z = atof(row[3]); - od.heading = atof(row[4]); - itemid = atoi(row[5]); + id = Strings::ToInt(row[0]); + od.x = Strings::ToFloat(row[1]); + od.y = Strings::ToFloat(row[2]); + od.z = Strings::ToFloat(row[3]); + od.heading = Strings::ToFloat(row[4]); + itemid = Strings::ToInt(row[5]); strn0cpy(od.object_name, row[6], sizeof(od.object_name)); od.object_name[sizeof(od.object_name) - 1] = '\0'; // Required if strlen(row[col++]) exactly == sizeof(object_name) - od.object_type = atoi(row[7]); - icon = atoi(row[8]); - od.size = atoi(row[9]); - od.solidtype = atoi(row[10]); - od.unknown020 = atoi(row[11]); + od.object_type = Strings::ToInt(row[7]); + icon = Strings::ToInt(row[8]); + od.size = Strings::ToInt(row[9]); + od.solidtype = Strings::ToInt(row[10]); + od.unknown020 = Strings::ToInt(row[11]); switch (od.object_type) { case 0: // Static Object @@ -162,7 +162,7 @@ void command_object(Client *c, const Seperator *sep) if (sep->argnum > 3) { // Model name in arg3? if ((sep->arg[3][0] <= '9') && (sep->arg[3][0] >= '0')) { // Nope, user must have specified ObjectID. Extract it. - id = atoi(sep->arg[2]); + id = Strings::ToInt(sep->arg[2]); col = 1; // Bump all other arguments one to the right. Model is in arg4. } else { @@ -179,18 +179,18 @@ void command_object(Client *c, const Seperator *sep) memset(&od, 0, sizeof(od)); - od.object_type = atoi(sep->arg[2 + col]); + od.object_type = Strings::ToInt(sep->arg[2 + col]); switch (od.object_type) { case 0: // Static Object if ((sep->argnum - col) > 3) { - od.size = atoi(sep->arg[4 + col]); // Size specified + od.size = Strings::ToInt(sep->arg[4 + col]); // Size specified if ((sep->argnum - col) > 4) { - od.solidtype = atoi(sep->arg[5 + col]); // SolidType specified + od.solidtype = Strings::ToInt(sep->arg[5 + col]); // SolidType specified if ((sep->argnum - col) > 5) { - od.unknown020 = atoi(sep->arg[6 + col]); + od.unknown020 = Strings::ToInt(sep->arg[6 + col]); } // Incline specified } } @@ -205,7 +205,7 @@ void command_object(Client *c, const Seperator *sep) return; default: // Everything else == Tradeskill Object - icon = ((sep->argnum - col) > 3) ? atoi(sep->arg[4 + col]) : 0; + icon = ((sep->argnum - col) > 3) ? Strings::ToInt(sep->arg[4 + col]) : 0; if (icon == 0) { c->Message(Chat::White, "ERROR: Required property 'Icon' not specified for Tradeskill Object"); @@ -227,7 +227,7 @@ void command_object(Client *c, const Seperator *sep) auto results = content_db.QueryDatabase(query); if (results.Success() && results.RowCount() != 0) { auto row = results.begin(); - if (atoi(row[0]) > 0) { // Yep, in database already. + if (Strings::ToInt(row[0]) > 0) { // Yep, in database already. id = 0; } } @@ -239,7 +239,7 @@ void command_object(Client *c, const Seperator *sep) } if (id == 0) { - c->Message(Chat::White, "ERROR: An object already exists with the id %u", atoi(sep->arg[2])); + c->Message(Chat::White, "ERROR: An object already exists with the id %u", Strings::ToInt(sep->arg[2])); return; } } @@ -260,7 +260,7 @@ void command_object(Client *c, const Seperator *sep) auto results = content_db.QueryDatabase(query); if (results.Success() && results.RowCount() != 0) { auto row = results.begin(); - objectsFound = atoi(row[0]); // Number of nearby objects from database + objectsFound = Strings::ToInt(row[0]); // Number of nearby objects from database } // No objects found in database too close. How about spawned but not yet saved? @@ -304,7 +304,7 @@ void command_object(Client *c, const Seperator *sep) results = content_db.QueryDatabase(query); if (results.Success() && results.RowCount() != 0) { auto row = results.begin(); - id = atoi(row[0]); + id = Strings::ToInt(row[0]); } id++; @@ -352,7 +352,7 @@ void command_object(Client *c, const Seperator *sep) if (strcasecmp(sep->arg[1], "edit") == 0) { - if ((sep->argnum < 2) || ((id = atoi(sep->arg[2])) < 1)) { + if ((sep->argnum < 2) || ((id = Strings::ToInt(sep->arg[2])) < 1)) { c->Message(Chat::White, "Usage: #object Edit (ObjectID) [PropertyName] [NewValue]"); c->Message(Chat::White, "- Static Object (Type 0) Properties: model, type, size, solidtype, incline"); c->Message(Chat::White, "- Tradeskill Object (Type 2+) Properties: model, type, icon"); @@ -381,9 +381,9 @@ void command_object(Client *c, const Seperator *sep) } auto row = results.begin(); - od.zone_id = atoi(row[0]); - od.zone_instance = atoi(row[1]); - od.object_type = atoi(row[2]); + od.zone_id = Strings::ToInt(row[0]); + od.zone_instance = Strings::ToInt(row[1]); + od.object_type = Strings::ToInt(row[2]); uint32 objectsFound = 1; // Object not in this zone? @@ -471,7 +471,7 @@ void command_object(Client *c, const Seperator *sep) return; } - od.object_type = atoi(sep->arg[4]); + od.object_type = Strings::ToInt(sep->arg[4]); switch (od.object_type) { case 0: @@ -514,7 +514,7 @@ void command_object(Client *c, const Seperator *sep) return; } - od.size = atoi(sep->arg[4]); + od.size = Strings::ToInt(sep->arg[4]); o->SetObjectData(&od); if (od.size == 0) { // 0 == unspecified == 100% @@ -544,7 +544,7 @@ void command_object(Client *c, const Seperator *sep) return; } - od.solidtype = atoi(sep->arg[4]); + od.solidtype = Strings::ToInt(sep->arg[4]); o->SetObjectData(&od); c->Message( @@ -565,7 +565,7 @@ void command_object(Client *c, const Seperator *sep) return; } - if ((icon = atoi(sep->arg[4])) == 0) { + if ((icon = Strings::ToInt(sep->arg[4])) == 0) { c->Message(Chat::White, "ERROR: Invalid Icon specified. Please enter an icon number."); return; } @@ -591,7 +591,7 @@ void command_object(Client *c, const Seperator *sep) return; } - od.unknown020 = atoi(sep->arg[4]); + od.unknown020 = Strings::ToInt(sep->arg[4]); o->SetObjectData(&od); c->Message( @@ -622,7 +622,7 @@ void command_object(Client *c, const Seperator *sep) if (strcasecmp(sep->arg[1], "move") == 0) { if ((sep->argnum < 2) || // Not enough arguments - ((id = atoi(sep->arg[2])) == 0) || // ID not specified + ((id = Strings::ToInt(sep->arg[2])) == 0) || // ID not specified (((sep->arg[3][0] < '0') || (sep->arg[3][0] > '9')) && ((sep->arg[3][0] & 0xDF) != 'T') && (sep->arg[3][0] != '-') && (sep->arg[3][0] != '.'))) { // Location argument not specified correctly c->Message(Chat::White, "Usage: #object Move (ObjectID) ToMe|(x y z [h])"); @@ -638,9 +638,9 @@ void command_object(Client *c, const Seperator *sep) } auto row = results.begin(); - od.zone_id = atoi(row[0]); - od.zone_instance = atoi(row[1]); - od.object_type = atoi(row[2]); + od.zone_id = Strings::ToInt(row[0]); + od.zone_instance = Strings::ToInt(row[1]); + od.object_type = Strings::ToInt(row[2]); if (od.zone_id != zone->GetZoneID()) { c->Message(Chat::White, "ERROR: Object %u is not in this zone", id); @@ -702,23 +702,23 @@ void command_object(Client *c, const Seperator *sep) c->MovePC(c->GetX() - x2, c->GetY() - y2, c->GetZ(), c->GetHeading()); } // Move to x, y, z [h] else { - od.x = atof(sep->arg[3]); + od.x = Strings::ToFloat(sep->arg[3]); if (sep->argnum > 3) { - od.y = atof(sep->arg[4]); + od.y = Strings::ToFloat(sep->arg[4]); } else { o->GetLocation(nullptr, &od.y, nullptr); } if (sep->argnum > 4) { - od.z = atof(sep->arg[5]); + od.z = Strings::ToFloat(sep->arg[5]); } else { o->GetLocation(nullptr, nullptr, &od.z); } if (sep->argnum > 5) { - o->SetHeading(atof(sep->arg[6])); + o->SetHeading(Strings::ToFloat(sep->arg[6])); } } @@ -739,7 +739,7 @@ void command_object(Client *c, const Seperator *sep) if (strcasecmp(sep->arg[1], "rotate") == 0) { // Insufficient or invalid arguments - if ((sep->argnum < 3) || ((id = atoi(sep->arg[2])) == 0)) { + if ((sep->argnum < 3) || ((id = Strings::ToInt(sep->arg[2])) == 0)) { c->Message(Chat::White, "Usage: #object Rotate (ObjectID) (Heading, 0-512)"); return; } @@ -753,7 +753,7 @@ void command_object(Client *c, const Seperator *sep) return; } - o->SetHeading(atof(sep->arg[3])); + o->SetHeading(Strings::ToFloat(sep->arg[3])); // Despawn and respawn object to reflect change app = new EQApplicationPacket(); @@ -770,7 +770,7 @@ void command_object(Client *c, const Seperator *sep) if (strcasecmp(sep->arg[1], "save") == 0) { // Insufficient or invalid arguments - if ((sep->argnum < 2) || ((id = atoi(sep->arg[2])) == 0)) { + if ((sep->argnum < 2) || ((id = Strings::ToInt(sep->arg[2])) == 0)) { c->Message(Chat::White, "Usage: #object Save (ObjectID)"); return; } @@ -787,9 +787,9 @@ void command_object(Client *c, const Seperator *sep) auto results = content_db.QueryDatabase(query); if (results.Success() && results.RowCount() != 0) { auto row = results.begin(); - od.zone_id = atoi(row[0]); - od.zone_instance = atoi(row[1]); - od.object_type = atoi(row[2]); + od.zone_id = Strings::ToInt(row[0]); + od.zone_instance = Strings::ToInt(row[1]); + od.object_type = Strings::ToInt(row[2]); // ID already in database. Not a new object. bNewObject = false; @@ -1014,7 +1014,7 @@ void command_object(Client *c, const Seperator *sep) return; } - od.zone_instance = atoi(sep->arg[3]); + od.zone_instance = Strings::ToInt(sep->arg[3]); if (od.zone_instance == zone->GetInstanceVersion()) { c->Message(Chat::White, "ERROR: Source and destination instance versions are the same."); @@ -1046,7 +1046,7 @@ void command_object(Client *c, const Seperator *sep) return; } - id = atoi(sep->arg[2]); + id = Strings::ToInt(sep->arg[2]); std::string query = StringFormat( "INSERT INTO object " @@ -1085,13 +1085,13 @@ void command_object(Client *c, const Seperator *sep) auto row = results.begin(); // Wrong ZoneID? - if (atoi(row[0]) != zone->GetZoneID()) { + if (Strings::ToInt(row[0]) != zone->GetZoneID()) { c->Message(Chat::White, "ERROR: Object %u is not part of this zone.", id); return; } // Wrong Instance Version? - if (atoi(row[1]) != zone->GetInstanceVersion()) { + if (Strings::ToInt(row[1]) != zone->GetInstanceVersion()) { c->Message(Chat::White, "ERROR: Object %u is not part of this instance version.", id); return; } @@ -1106,7 +1106,7 @@ void command_object(Client *c, const Seperator *sep) if (strcasecmp(sep->arg[1], "delete") == 0) { - if ((sep->argnum < 2) || ((id = atoi(sep->arg[2])) <= 0)) { + if ((sep->argnum < 2) || ((id = Strings::ToInt(sep->arg[2])) <= 0)) { c->Message( Chat::White, "Usage: #object Delete (ObjectID) -- NOTE: Object deletions are permanent and " "cannot be undone!" @@ -1156,7 +1156,7 @@ void command_object(Client *c, const Seperator *sep) auto row = results.begin(); - switch (atoi(row[0])) { + switch (Strings::ToInt(row[0])) { case 0: // Static Object query = StringFormat( "DELETE FROM object WHERE id = %u " @@ -1185,7 +1185,7 @@ void command_object(Client *c, const Seperator *sep) if (strcasecmp(sep->arg[1], "undo") == 0) { // Insufficient or invalid arguments - if ((sep->argnum < 2) || ((id = atoi(sep->arg[2])) == 0)) { + if ((sep->argnum < 2) || ((id = Strings::ToInt(sep->arg[2])) == 0)) { c->Message( Chat::White, "Usage: #object Undo (ObjectID) -- Reload object from database, undoing any " "changes you have made" @@ -1236,16 +1236,16 @@ void command_object(Client *c, const Seperator *sep) auto row = results.begin(); - od.x = atof(row[0]); - od.y = atof(row[1]); - od.z = atof(row[2]); - od.heading = atof(row[3]); + od.x = Strings::ToFloat(row[0]); + od.y = Strings::ToFloat(row[1]); + od.z = Strings::ToFloat(row[2]); + od.heading = Strings::ToFloat(row[3]); strn0cpy(od.object_name, row[4], sizeof(od.object_name)); - od.object_type = atoi(row[5]); - icon = atoi(row[6]); - od.size = atoi(row[7]); - od.solidtype = atoi(row[8]); - od.unknown020 = atoi(row[9]); + od.object_type = Strings::ToInt(row[5]); + icon = Strings::ToInt(row[6]); + od.size = Strings::ToInt(row[7]); + od.solidtype = Strings::ToInt(row[8]); + od.unknown020 = Strings::ToInt(row[9]); if (od.object_type == 0) { od.object_type = staticType; diff --git a/zone/gm_commands/oocmute.cpp b/zone/gm_commands/oocmute.cpp index a19f424ec..d8711eccf 100755 --- a/zone/gm_commands/oocmute.cpp +++ b/zone/gm_commands/oocmute.cpp @@ -10,7 +10,7 @@ void command_oocmute(Client *c, const Seperator *sep) return; } - bool is_muted = std::stoi(sep->arg[1]) ? true : false; + bool is_muted = Strings::ToInt(sep->arg[1]) ? true : false; ServerPacket pack(ServerOP_OOCMute, sizeof(ServerOOCMute_Struct)); auto o = (ServerOOCMute_Struct*) pack.pBuffer; diff --git a/zone/gm_commands/peekinv.cpp b/zone/gm_commands/peekinv.cpp index fe6956191..596ad27bc 100755 --- a/zone/gm_commands/peekinv.cpp +++ b/zone/gm_commands/peekinv.cpp @@ -3,6 +3,12 @@ void command_peekinv(Client *c, const Seperator *sep) { + auto arguments = sep->argnum; + if (!arguments) { + SendPeekInvSubCommands(c); + return; + } + // this can be cleaned up once inventory is cleaned up enum { peekNone = 0x0000, @@ -15,63 +21,83 @@ void command_peekinv(Client *c, const Seperator *sep) peekShBank = 0x0040, peekTrade = 0x0080, peekWorld = 0x0100, - peekOutOfScope = (peekWorld * 2) // less than + peekOutOfScope = (peekWorld * 2) }; - static const char *scope_prefix[] = {"equip", "gen", "cursor", "limbo", "trib", "bank", "shbank", "trade", "world"}; - static const int16 scope_range[][2] = { - {EQ::invslot::EQUIPMENT_BEGIN, EQ::invslot::EQUIPMENT_END}, - {EQ::invslot::GENERAL_BEGIN, EQ::invslot::GENERAL_END}, - {EQ::invslot::slotCursor, EQ::invslot::slotCursor}, - {EQ::invslot::SLOT_INVALID, EQ::invslot::SLOT_INVALID}, - {EQ::invslot::TRIBUTE_BEGIN, EQ::invslot::TRIBUTE_END}, - {EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END}, - {EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END}, - {EQ::invslot::TRADE_BEGIN, EQ::invslot::TRADE_END}, - {EQ::invslot::SLOT_BEGIN, (EQ::invtype::WORLD_SIZE - 1)} + { EQ::invslot::EQUIPMENT_BEGIN, EQ::invslot::EQUIPMENT_END }, + { EQ::invslot::GENERAL_BEGIN, EQ::invslot::GENERAL_END }, + { EQ::invslot::slotCursor, EQ::invslot::slotCursor }, + { EQ::invslot::SLOT_INVALID, EQ::invslot::SLOT_INVALID }, + { EQ::invslot::TRIBUTE_BEGIN, EQ::invslot::TRIBUTE_END }, + { EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END }, + { EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END }, + { EQ::invslot::TRADE_BEGIN, EQ::invslot::TRADE_END }, + { EQ::invslot::SLOT_BEGIN, (EQ::invtype::WORLD_SIZE - 1) } }; - static const bool scope_bag[] = {false, true, true, true, false, true, true, true, true}; + static const bool scope_bag[] = { + false, // Equip + true, // General + true, // Cursor + true, // Cursor Limbo + false, // Tribute + true, // Bank + true, // Shared Bank + true, // Trade + true // World + }; - if (!c) { + int scope_mask = peekNone; + + const bool is_all = !strcasecmp(sep->arg[1], "all"); + const bool is_all_bank = !strcasecmp(sep->arg[1], "allbank"); + const bool is_bank = !strcasecmp(sep->arg[1], "bank"); + const bool is_cursor = !strcasecmp(sep->arg[1], "cursor"); + const bool is_cursor_limbo = !strcasecmp(sep->arg[1], "curlimbo"); + const bool is_equipment = !strcasecmp(sep->arg[1], "equip"); + const bool is_general = !strcasecmp(sep->arg[1], "gen"); + const bool is_limbo = !strcasecmp(sep->arg[1], "limbo"); + const bool is_possessions = !strcasecmp(sep->arg[1], "poss"); + const bool is_shared_bank = !strcasecmp(sep->arg[1], "shbank"); + const bool is_trade = !strcasecmp(sep->arg[1], "trade"); + const bool is_tribute = !strcasecmp(sep->arg[1], "trib"); + const bool is_world = !strcasecmp(sep->arg[1], "world"); + + if (is_all) { + scope_mask = (peekOutOfScope - 1); + } else if (is_all_bank) { + scope_mask |= (peekBank | peekShBank); + } else if (is_bank) { + scope_mask |= peekBank; + } else if (is_cursor) { + scope_mask |= peekCursor; + } else if (is_cursor_limbo) { + scope_mask |= (peekCursor | peekLimbo); + } else if (is_equipment) { + scope_mask |= peekEquip; + } else if (is_general) { + scope_mask |= peekGen; + } else if (is_limbo) { + scope_mask |= peekLimbo; + } else if (is_possessions) { + scope_mask |= (peekEquip | peekGen | peekCursor); + } else if (is_shared_bank) { + scope_mask |= peekShBank; + } else if (is_tribute) { + scope_mask |= peekTrib; + } else if (is_trade) { + scope_mask |= peekTrade; + } else if (is_world) { + scope_mask |= peekWorld; + } else { + SendPeekInvSubCommands(c); return; } - if (c->GetTarget() && !c->GetTarget()->IsClient()) { - c->Message(Chat::White, "You must target a PC for this command."); - return; - } - - int scopeMask = peekNone; - - if (strcasecmp(sep->arg[1], "all") == 0) { scopeMask = (peekOutOfScope - 1); } - else if (strcasecmp(sep->arg[1], "equip") == 0) { scopeMask |= peekEquip; } - else if (strcasecmp(sep->arg[1], "gen") == 0) { scopeMask |= peekGen; } - else if (strcasecmp(sep->arg[1], "cursor") == 0) { scopeMask |= peekCursor; } - else if (strcasecmp(sep->arg[1], "poss") == 0) { scopeMask |= (peekEquip | peekGen | peekCursor); } - else if (strcasecmp(sep->arg[1], "limbo") == 0) { scopeMask |= peekLimbo; } - else if (strcasecmp(sep->arg[1], "curlim") == 0) { scopeMask |= (peekCursor | peekLimbo); } - else if (strcasecmp(sep->arg[1], "trib") == 0) { scopeMask |= peekTrib; } - else if (strcasecmp(sep->arg[1], "bank") == 0) { scopeMask |= peekBank; } - else if (strcasecmp(sep->arg[1], "shbank") == 0) { scopeMask |= peekShBank; } - else if (strcasecmp(sep->arg[1], "allbank") == 0) { scopeMask |= (peekBank | peekShBank); } - else if (strcasecmp(sep->arg[1], "trade") == 0) { scopeMask |= peekTrade; } - else if (strcasecmp(sep->arg[1], "world") == 0) { scopeMask |= peekWorld; } - - if (!scopeMask) { - c->Message( - Chat::White, - "Usage: #peekinv [equip|gen|cursor|poss|limbo|curlim|trib|bank|shbank|allbank|trade|world|all]" - ); - c->Message(Chat::White, "- Displays a portion of the targeted user's inventory"); - c->Message(Chat::White, "- Caution: 'all' is a lot of information!"); - return; - } - - Client *targetClient = c; - if (c->GetTarget()) { - targetClient = c->GetTarget()->CastToClient(); + auto t = c; + if (c->GetTarget() && c->GetTarget()->IsClient()) { + t = c->GetTarget()->CastToClient(); } const EQ::ItemInstance *inst_main = nullptr; @@ -82,62 +108,81 @@ void command_peekinv(Client *c, const Seperator *sep) EQ::SayLinkEngine linker; linker.SetLinkType(EQ::saylink::SayLinkItemInst); - c->Message(Chat::White, "Displaying inventory for %s...", targetClient->GetName()); + c->Message( + Chat::White, + fmt::format( + "Displaying inventory of {}.", + c->GetTargetDescription(t) + ).c_str() + ); - Object *objectTradeskill = targetClient->GetTradeskillObject(); + auto o = t->GetTradeskillObject(); + auto found_items = false; - bool itemsFound = false; - - for (int scopeIndex = 0, scopeBit = peekEquip; scopeBit < peekOutOfScope; ++scopeIndex, scopeBit <<= 1) { - if (scopeBit & ~scopeMask) { + for (int scope_index = 0, scope_bit = peekEquip; scope_bit < peekOutOfScope; ++scope_index, scope_bit <<= 1) { + if (scope_bit & ~scope_mask) { continue; } - if (scopeBit & peekWorld) { - if (objectTradeskill == nullptr) { - c->Message(Chat::Default, "No world tradeskill object selected..."); + if (scope_bit & peekWorld) { + if (!o) { + c->Message(Chat::White, "No world Tradeskill object selected."); continue; - } - else { + } else { c->Message( Chat::White, - "[WorldObject DBID: %i (entityid: %i)]", - objectTradeskill->GetDBID(), - objectTradeskill->GetID()); + fmt::format( + "[World Object] Database ID: {} Entity ID: {}", + o->GetDBID(), + o->GetID() + ).c_str() + ); } } - for (int16 indexMain = scope_range[scopeIndex][0]; indexMain <= scope_range[scopeIndex][1]; ++indexMain) { - if (indexMain == EQ::invslot::SLOT_INVALID) { + for (int16 index_main = scope_range[scope_index][0]; index_main <= scope_range[scope_index][1]; ++index_main) { + if (index_main == EQ::invslot::SLOT_INVALID) { continue; } - inst_main = ((scopeBit & peekWorld) ? objectTradeskill->GetItem(indexMain) : targetClient->GetInv().GetItem( - indexMain - )); + inst_main = ( + (scope_bit & peekWorld) ? + o->GetItem(index_main) : + t->GetInv().GetItem(index_main) + ); + if (inst_main) { - itemsFound = true; + found_items = true; item_data = inst_main->GetItem(); - } - else { + } else { item_data = nullptr; } linker.SetItemInst(inst_main); - c->Message( - (item_data == nullptr), - "%sSlot: %i, Item: %i (%s), Charges: %i", - scope_prefix[scopeIndex], - ((scopeBit & peekWorld) ? (EQ::invslot::WORLD_BEGIN + indexMain) : indexMain), - ((item_data == nullptr) ? 0 : item_data->ID), - linker.GenerateLink().c_str(), - ((inst_main == nullptr) ? 0 : inst_main->GetCharges()) - ); + if (item_data) { + c->Message( + Chat::White, + fmt::format( + "Slot {} | {} ({}){}", + ((scope_bit & peekWorld) ? (EQ::invslot::WORLD_BEGIN + index_main) : index_main), + linker.GenerateLink(), + item_data->ID, + ( + inst_main->IsStackable() && inst_main->GetCharges() > 0 ? + fmt::format( + " (Stack of {})", + inst_main->GetCharges() + ) : + "" + ) + ).c_str() + ); + } if (inst_main && inst_main->IsClassCommon()) { - for (uint8 indexAug = EQ::invaug::SOCKET_BEGIN; indexAug <= EQ::invaug::SOCKET_END; ++indexAug) { - inst_aug = inst_main->GetItem(indexAug); + for (uint8 augment_index = EQ::invaug::SOCKET_BEGIN; augment_index <= EQ::invaug::SOCKET_END; ++augment_index) { + inst_aug = inst_main->GetItem(augment_index); if (!inst_aug) { // extant only continue; } @@ -146,25 +191,33 @@ void command_peekinv(Client *c, const Seperator *sep) linker.SetItemInst(inst_aug); c->Message( - (item_data == nullptr), - ".%sAugSlot: %i (Slot #%i, Aug idx #%i), Item: %i (%s), Charges: %i", - scope_prefix[scopeIndex], - INVALID_INDEX, - ((scopeBit & peekWorld) ? (EQ::invslot::WORLD_BEGIN + indexMain) : indexMain), - indexAug, - ((item_data == nullptr) ? 0 : item_data->ID), - linker.GenerateLink().c_str(), - ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges()) + Chat::White, + fmt::format( + "Slot {} (Augment Slot {}) | {} ({}){}", + ((scope_bit & peekWorld) ? (EQ::invslot::WORLD_BEGIN + index_main) : index_main), + augment_index, + linker.GenerateLink(), + item_data->ID, + ( + inst_aug->IsStackable() && inst_aug->GetCharges() > 0 ? + fmt::format( + " (Stack of {})", + inst_aug->GetCharges() + ) : + "" + ) + ).c_str() ); + } } - if (!scope_bag[scopeIndex] || !(inst_main && inst_main->IsClassBag())) { + if (!scope_bag[scope_index] || !(inst_main && inst_main->IsClassBag())) { continue; } - for (uint8 indexSub = EQ::invbag::SLOT_BEGIN; indexSub <= EQ::invbag::SLOT_END; ++indexSub) { - inst_sub = inst_main->GetItem(indexSub); + for (uint8 sub_index = EQ::invbag::SLOT_BEGIN; sub_index <= EQ::invbag::SLOT_END; ++sub_index) { + inst_sub = inst_main->GetItem(sub_index); if (!inst_sub) { // extant only continue; } @@ -173,20 +226,32 @@ void command_peekinv(Client *c, const Seperator *sep) linker.SetItemInst(inst_sub); c->Message( - (item_data == nullptr), - "..%sBagSlot: %i (Slot #%i, Bag idx #%i), Item: %i (%s), Charges: %i", - scope_prefix[scopeIndex], - ((scopeBit & peekWorld) ? INVALID_INDEX : EQ::InventoryProfile::CalcSlotId(indexMain, indexSub)), - ((scopeBit & peekWorld) ? (EQ::invslot::WORLD_BEGIN + indexMain) : indexMain), - indexSub, - ((item_data == nullptr) ? 0 : item_data->ID), - linker.GenerateLink().c_str(), - ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges()) + Chat::White, + fmt::format( + "Slot {} Bag Slot {} | {} ({}){}", + ( + (scope_bit & peekWorld) ? + INVALID_INDEX : + EQ::InventoryProfile::CalcSlotId(index_main, sub_index) + ), + ((scope_bit & peekWorld) ? (EQ::invslot::WORLD_BEGIN + index_main) : index_main), + sub_index, + linker.GenerateLink(), + item_data->ID, + ( + inst_sub->IsStackable() && inst_sub->GetCharges() > 0 ? + fmt::format( + " (Stack of {})", + inst_sub->GetCharges() + ) : + "" + ) + ).c_str() ); if (inst_sub->IsClassCommon()) { - for (uint8 indexAug = EQ::invaug::SOCKET_BEGIN; indexAug <= EQ::invaug::SOCKET_END; ++indexAug) { - inst_aug = inst_sub->GetItem(indexAug); + for (uint8 augment_index = EQ::invaug::SOCKET_BEGIN; augment_index <= EQ::invaug::SOCKET_END; ++augment_index) { + inst_aug = inst_sub->GetItem(augment_index); if (!inst_aug) { // extant only continue; } @@ -195,58 +260,73 @@ void command_peekinv(Client *c, const Seperator *sep) linker.SetItemInst(inst_aug); c->Message( - (item_data == nullptr), - "...%sAugSlot: %i (Slot #%i, Sub idx #%i, Aug idx #%i), Item: %i (%s), Charges: %i", - scope_prefix[scopeIndex], - INVALID_INDEX, - ((scopeBit & peekWorld) ? INVALID_INDEX : EQ::InventoryProfile::CalcSlotId( - indexMain, - indexSub - )), - indexSub, - indexAug, - ((item_data == nullptr) ? 0 : item_data->ID), - linker.GenerateLink().c_str(), - ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges()) + Chat::White, + fmt::format( + "Slot {} Bag Slot {} (Augment Slot {}) | {} ({}){}", + ( + (scope_bit & peekWorld) ? + INVALID_INDEX : + EQ::InventoryProfile::CalcSlotId(index_main,sub_index) + ), + sub_index, + augment_index, + linker.GenerateLink(), + item_data->ID, + ( + inst_sub->IsStackable() && inst_sub->GetCharges() > 0 ? + fmt::format( + " (Stack of {})", + inst_sub->GetCharges() + ) : + "" + ) + ).c_str() ); } } } } - if (scopeBit & peekLimbo) { + if (scope_bit & peekLimbo) { int limboIndex = 0; - for (auto it = targetClient->GetInv().cursor_cbegin(); - (it != targetClient->GetInv().cursor_cend()); - ++it, ++limboIndex) { - if (it == targetClient->GetInv().cursor_cbegin()) { + for (auto it = t->GetInv().cursor_cbegin(); (it != t->GetInv().cursor_cend()); ++it, ++limboIndex) { + if (it == t->GetInv().cursor_cbegin()) { continue; } inst_main = *it; if (inst_main) { - itemsFound = true; + found_items = true; item_data = inst_main->GetItem(); - } - else { + } else { item_data = nullptr; } linker.SetItemInst(inst_main); - c->Message( - (item_data == nullptr), - "%sSlot: %i, Item: %i (%s), Charges: %i", - scope_prefix[scopeIndex], - (8000 + limboIndex), - ((item_data == nullptr) ? 0 : item_data->ID), - linker.GenerateLink().c_str(), - ((inst_main == nullptr) ? 0 : inst_main->GetCharges()) - ); + if (item_data) { + c->Message( + Chat::White, + fmt::format( + "Slot {} | {} ({}){}", + (8000 + limboIndex), + item_data->ID, + linker.GenerateLink(), + ( + inst_main->IsStackable() && inst_main->GetCharges() > 0 ? + fmt::format( + " (Stack of {})", + inst_main->GetCharges() + ) : + "" + ) + ).c_str() + ); + } if (inst_main && inst_main->IsClassCommon()) { - for (uint8 indexAug = EQ::invaug::SOCKET_BEGIN; indexAug <= EQ::invaug::SOCKET_END; ++indexAug) { - inst_aug = inst_main->GetItem(indexAug); + for (uint8 augment_index = EQ::invaug::SOCKET_BEGIN; augment_index <= EQ::invaug::SOCKET_END; ++augment_index) { + inst_aug = inst_main->GetItem(augment_index); if (!inst_aug) { // extant only continue; } @@ -255,25 +335,32 @@ void command_peekinv(Client *c, const Seperator *sep) linker.SetItemInst(inst_aug); c->Message( - (item_data == nullptr), - ".%sAugSlot: %i (Slot #%i, Aug idx #%i), Item: %i (%s), Charges: %i", - scope_prefix[scopeIndex], - INVALID_INDEX, - (8000 + limboIndex), - indexAug, - ((item_data == nullptr) ? 0 : item_data->ID), - linker.GenerateLink().c_str(), - ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges()) + Chat::White, + fmt::format( + "Slot {} (Augment Slot {}) | {} ({}){}", + (8000 + limboIndex), + augment_index, + linker.GenerateLink(), + item_data->ID, + ( + inst_aug->IsStackable() && inst_aug->GetCharges() > 0 ? + fmt::format( + " (Stack of {})", + inst_aug->GetCharges() + ) : + "" + ) + ).c_str() ); } } - if (!scope_bag[scopeIndex] || !(inst_main && inst_main->IsClassBag())) { + if (!scope_bag[scope_index] || !(inst_main && inst_main->IsClassBag())) { continue; } - for (uint8 indexSub = EQ::invbag::SLOT_BEGIN; indexSub <= EQ::invbag::SLOT_END; ++indexSub) { - inst_sub = inst_main->GetItem(indexSub); + for (uint8 sub_index = EQ::invbag::SLOT_BEGIN; sub_index <= EQ::invbag::SLOT_END; ++sub_index) { + inst_sub = inst_main->GetItem(sub_index); if (!inst_sub) { continue; } @@ -282,23 +369,32 @@ void command_peekinv(Client *c, const Seperator *sep) linker.SetItemInst(inst_sub); - c->Message( - (item_data == nullptr), - "..%sBagSlot: %i (Slot #%i, Bag idx #%i), Item: %i (%s), Charges: %i", - scope_prefix[scopeIndex], - INVALID_INDEX, - (8000 + limboIndex), - indexSub, - ((item_data == nullptr) ? 0 : item_data->ID), - linker.GenerateLink().c_str(), - ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges()) - ); + if (item_data) { + c->Message( + Chat::White, + fmt::format( + "Slot {} Bag Slot {} | {} ({}){}", + (8000 + limboIndex), + sub_index, + linker.GenerateLink(), + item_data->ID, + ( + inst_sub->IsStackable() && inst_sub->GetCharges() > 0 ? + fmt::format( + " (Stack of {})", + inst_sub->GetCharges() + ) : + "" + ) + ).c_str() + ); + } if (inst_sub->IsClassCommon()) { - for (uint8 indexAug = EQ::invaug::SOCKET_BEGIN; - indexAug <= EQ::invaug::SOCKET_END; - ++indexAug) { - inst_aug = inst_sub->GetItem(indexAug); + for (uint8 augment_index = EQ::invaug::SOCKET_BEGIN; + augment_index <= EQ::invaug::SOCKET_END; + ++augment_index) { + inst_aug = inst_sub->GetItem(augment_index); if (!inst_aug) { // extant only continue; } @@ -307,16 +403,23 @@ void command_peekinv(Client *c, const Seperator *sep) linker.SetItemInst(inst_aug); c->Message( - (item_data == nullptr), - "...%sAugSlot: %i (Slot #%i, Sub idx #%i, Aug idx #%i), Item: %i (%s), Charges: %i", - scope_prefix[scopeIndex], - INVALID_INDEX, - (8000 + limboIndex), - indexSub, - indexAug, - ((item_data == nullptr) ? 0 : item_data->ID), - linker.GenerateLink().c_str(), - ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges()) + Chat::White, + fmt::format( + "Slot {} Bag Slot {} (Augment Slot {}) | {} ({}){}", + (8000 + limboIndex), + sub_index, + augment_index, + linker.GenerateLink(), + item_data->ID, + ( + inst_sub->IsStackable() && inst_sub->GetCharges() > 0 ? + fmt::format( + " (Stack of {})", + inst_sub->GetCharges() + ) : + "" + ) + ).c_str() ); } } @@ -325,8 +428,23 @@ void command_peekinv(Client *c, const Seperator *sep) } } - if (!itemsFound) { + if (!found_items) { c->Message(Chat::White, "No items found."); } } +void SendPeekInvSubCommands(Client* c) { + c->Message(Chat::White, "Usage: #peekinv equip - Shows items in Equipment slots"); + c->Message(Chat::White, "Usage: #peekinv gen - Shows items in General slots"); + c->Message(Chat::White, "Usage: #peekinv cursor - Shows items in Cursor slots"); + c->Message(Chat::White, "Usage: #peekinv poss - Shows items in Equipment, General, and Cursor slots"); + c->Message(Chat::White, "Usage: #peekinv limbo - Shows items in Limbo slots"); + c->Message(Chat::White, "Usage: #peekinv curlim - Shows items in Cursor and Limbo slots"); + c->Message(Chat::White, "Usage: #peekinv trib - Shows items in Tribute slots"); + c->Message(Chat::White, "Usage: #peekinv bank - Shows items in Bank slots"); + c->Message(Chat::White, "Usage: #peekinv shbank - Shows items in Shared Bank slots"); + c->Message(Chat::White, "Usage: #peekinv allbank - Shows items in Bank and Shared Bank slots"); + c->Message(Chat::White, "Usage: #peekinv trade - Shows items in Trade slots"); + c->Message(Chat::White, "Usage: #peekinv world - Shows items in World slots"); + c->Message(Chat::White, "Usage: #peekinv all - Shows items in all slots"); +} diff --git a/zone/gm_commands/peqzone.cpp b/zone/gm_commands/peqzone.cpp index cf4d66c4f..15b4109af 100755 --- a/zone/gm_commands/peqzone.cpp +++ b/zone/gm_commands/peqzone.cpp @@ -49,7 +49,7 @@ void command_peqzone(Client *c, const Seperator *sep) auto zone_id = ( sep->IsNumber(1) ? - static_cast(std::stoul(sep->arg[1])) : + static_cast(Strings::ToUnsignedInt(sep->arg[1])) : static_cast(ZoneID(sep->arg[1])) ); auto zone_short_name = ZoneName(zone_id); diff --git a/zone/gm_commands/permaclass.cpp b/zone/gm_commands/permaclass.cpp index 648c61169..1c8d9924f 100755 --- a/zone/gm_commands/permaclass.cpp +++ b/zone/gm_commands/permaclass.cpp @@ -13,8 +13,8 @@ void command_permaclass(Client *c, const Seperator *sep) target = c->GetTarget()->CastToClient(); } - auto class_id = std::stoi(sep->arg[1]); - + auto class_id = Strings::ToInt(sep->arg[1]); + LogInfo("Class changed by {} for {} to {} ({})", c->GetCleanName(), c->GetTargetDescription(target), diff --git a/zone/gm_commands/permagender.cpp b/zone/gm_commands/permagender.cpp index f4f2f16f3..a23cbce95 100755 --- a/zone/gm_commands/permagender.cpp +++ b/zone/gm_commands/permagender.cpp @@ -14,13 +14,13 @@ void command_permagender(Client *c, const Seperator *sep) target = c->GetTarget()->CastToClient(); } - auto gender_id = std::stoi(sep->arg[1]); + auto gender_id = Strings::ToInt(sep->arg[1]); if (gender_id < 0 || gender_id > 2) { c->Message(Chat::White, "Usage: #permagender [Gender ID]"); c->Message(Chat::White, "Genders: 0 = Male, 1 = Female, 2 = Neuter"); return; } - + LogInfo("Gender changed by {} for {} to {} ({})", c->GetCleanName(), c->GetTargetDescription(target), diff --git a/zone/gm_commands/permarace.cpp b/zone/gm_commands/permarace.cpp index b84157f3b..2595e1838 100755 --- a/zone/gm_commands/permarace.cpp +++ b/zone/gm_commands/permarace.cpp @@ -17,9 +17,9 @@ void command_permarace(Client *c, const Seperator *sep) target = c->GetTarget()->CastToClient(); } - auto race_id = std::stoi(sep->arg[1]); + auto race_id = Strings::ToInt(sep->arg[1]); auto gender_id = Mob::GetDefaultGender(race_id, target->GetBaseGender()); - + LogInfo("Race changed by {} for {} to {} ({})", c->GetCleanName(), c->GetTargetDescription(target), diff --git a/zone/gm_commands/petitioninfo.cpp b/zone/gm_commands/petitioninfo.cpp index 1700e4100..c9c1e49f5 100755 --- a/zone/gm_commands/petitioninfo.cpp +++ b/zone/gm_commands/petitioninfo.cpp @@ -13,7 +13,7 @@ void command_petitioninfo(Client *c, const Seperator *sep) return; } - LogInfo("Petition information request from [{}], petition number:", c->GetName(), atoi(sep->argplus[1])); + LogInfo("Petition information request from [{}], petition number:", c->GetName(), Strings::ToInt(sep->argplus[1])); if (results.RowCount() == 0) { c->Message(Chat::Red, "There was an error in your request: ID not found! Please check the Id and try again."); diff --git a/zone/gm_commands/picklock.cpp b/zone/gm_commands/picklock.cpp index c4b538eff..7d6efc607 100755 --- a/zone/gm_commands/picklock.cpp +++ b/zone/gm_commands/picklock.cpp @@ -2,23 +2,28 @@ void command_picklock(Client *c, const Seperator *sep) { - Mob *target = c->GetTarget(); - if (!target) { - c->Message(Chat::Red, "You must have a target."); + if (!c->GetTarget() || !c->GetTarget()->IsNPC()) { + c->Message(Chat::White, "You must target an NPC to use this command."); return; } - if (target->IsNPC()) { - if (c->HasSkill(EQ::skills::SkillPickLock)) { - if (DistanceSquaredNoZ(c->GetPosition(), target->GetPosition()) > RuleI(Adventure, LDoNTrapDistanceUse)) { - c->Message(Chat::Red, "%s is too far away.", target->GetCleanName()); - return; - } - c->HandleLDoNPickLock(target->CastToNPC(), c->GetSkill(EQ::skills::SkillPickLock), LDoNTypeMechanical); - } - else { - c->Message(Chat::Red, "You do not have the pick locks skill."); + auto t = c->GetTarget()->CastToNPC(); + + if (c->HasSkill(EQ::skills::SkillPickLock)) { + if (DistanceSquaredNoZ(c->GetPosition(), t->GetPosition()) > RuleI(Adventure, LDoNTrapDistanceUse)) { + c->Message( + Chat::White, + fmt::format( + "{} is too far away.", + c->GetTargetDescription(t) + ).c_str() + ); + return; } + + c->HandleLDoNPickLock(t, c->GetSkill(EQ::skills::SkillPickLock), LDoNTypeMechanical); + } else { + c->Message(Chat::White, "You do not have the Pick Lock skill."); } } diff --git a/zone/gm_commands/push.cpp b/zone/gm_commands/push.cpp index 7d693cff1..05042fb74 100755 --- a/zone/gm_commands/push.cpp +++ b/zone/gm_commands/push.cpp @@ -17,11 +17,11 @@ void command_push(Client *c, const Seperator *sep) } auto target = c->GetTarget(); - auto back = std::stof(sep->arg[1]); + auto back = Strings::ToFloat(sep->arg[1]); auto up = 0.0f; if (arguments == 2 && sep->IsNumber(2)) { - up = std::stof(sep->arg[2]); + up = Strings::ToFloat(sep->arg[2]); } c->Message( diff --git a/zone/gm_commands/race.cpp b/zone/gm_commands/race.cpp index 2729965b1..cc3b51888 100755 --- a/zone/gm_commands/race.cpp +++ b/zone/gm_commands/race.cpp @@ -5,7 +5,7 @@ void command_race(Client *c, const Seperator *sep) Mob *target = c->CastToMob(); if (sep->IsNumber(1)) { - auto race = atoi(sep->arg[1]); + auto race = Strings::ToInt(sep->arg[1]); if ((race >= 0 && race <= RuleI(NPC, MaxRaceID)) || (race >= 2253 && race <= 2259)) { if ((c->GetTarget()) && c->Admin() >= commandRaceOthers) { target = c->GetTarget(); diff --git a/zone/gm_commands/raidloot.cpp b/zone/gm_commands/raidloot.cpp index b75eb43c2..5bd3f3c8c 100755 --- a/zone/gm_commands/raidloot.cpp +++ b/zone/gm_commands/raidloot.cpp @@ -67,4 +67,3 @@ void command_raidloot(Client *c, const Seperator *sep) ).c_str() ); } - diff --git a/zone/gm_commands/reload.cpp b/zone/gm_commands/reload.cpp index 2f4e9511e..09db786ea 100644 --- a/zone/gm_commands/reload.cpp +++ b/zone/gm_commands/reload.cpp @@ -135,7 +135,7 @@ void command_reload(Client *c, const Seperator *sep) bool stop_timers = false; if (sep->IsNumber(2)) { - stop_timers = std::stoi(sep->arg[2]) != 0 ? true : false; + stop_timers = Strings::ToInt(sep->arg[2]) != 0 ? true : false; } std::string stop_timers_message = stop_timers ? " and timers stopped" : ""; @@ -167,7 +167,7 @@ void command_reload(Client *c, const Seperator *sep) pack = new ServerPacket(ServerOP_ReloadTasks, sizeof(ReloadTasks_Struct)); } else { - task_id = std::stoul(sep->arg[2]); + task_id = Strings::ToUnsignedInt(sep->arg[2]); } auto rts = (ReloadTasks_Struct *) pack->pBuffer; @@ -191,7 +191,7 @@ void command_reload(Client *c, const Seperator *sep) return; } - bool global = std::stoi(sep->arg[2]) ? true : false; + bool global = Strings::ToInt(sep->arg[2]) ? true : false; if (!global) { entity_list.UpdateAllTraps(true, true); @@ -220,7 +220,7 @@ void command_reload(Client *c, const Seperator *sep) uint8 global_repop = ReloadWorld::NoRepop; if (sep->IsNumber(2)) { - global_repop = static_cast(std::stoul(sep->arg[2])); + global_repop = static_cast(Strings::ToUnsignedInt(sep->arg[2])); if (global_repop > ReloadWorld::ForceRepop) { global_repop = ReloadWorld::ForceRepop; @@ -268,7 +268,7 @@ void command_reload(Client *c, const Seperator *sep) auto zone_id = ( sep->IsNumber(2) ? - std::stoul(sep->arg[2]) : + Strings::ToUnsignedInt(sep->arg[2]) : ZoneID(sep->arg[2]) ); if (!zone_id) { @@ -286,7 +286,7 @@ void command_reload(Client *c, const Seperator *sep) auto zone_long_name = ZoneLongName(zone_id); auto version = ( sep->IsNumber(3) ? - std::stoul(sep->arg[3]) : + Strings::ToUnsignedInt(sep->arg[3]) : 0 ); diff --git a/zone/gm_commands/removeitem.cpp b/zone/gm_commands/removeitem.cpp index 44ad46d84..0ed69eb45 100644 --- a/zone/gm_commands/removeitem.cpp +++ b/zone/gm_commands/removeitem.cpp @@ -12,8 +12,8 @@ void command_removeitem(Client *c, const Seperator *sep) if (c->GetTarget() && c->GetTarget()->IsClient()) { target = c->GetTarget()->CastToClient(); } - - auto item_id = std::stoi(sep->arg[1]); + + auto item_id = Strings::ToInt(sep->arg[1]); if (!database.GetItem(item_id)) { c->Message( Chat::White, @@ -24,9 +24,9 @@ void command_removeitem(Client *c, const Seperator *sep) ); return; } - + auto item_link = database.CreateItemLink(item_id); - auto amount = sep->IsNumber(2) ? std::stoul(sep->arg[2]) : 1; + auto amount = sep->IsNumber(2) ? Strings::ToUnsignedInt(sep->arg[2]) : 1; auto item_count = target->CountItem(item_id); if (item_count) { if (item_count >= amount) { diff --git a/zone/gm_commands/resetaa.cpp b/zone/gm_commands/resetaa.cpp index c0a9a075d..bac9892ff 100755 --- a/zone/gm_commands/resetaa.cpp +++ b/zone/gm_commands/resetaa.cpp @@ -7,15 +7,14 @@ void command_resetaa(Client *c, const Seperator *sep) return; } - auto target = c->GetTarget()->CastToClient(); - target->ResetAA(); - + auto t = c->GetTarget()->CastToClient(); + t->ResetAA(); + c->Message( Chat::White, fmt::format( "Successfully reset all Alternate Advancements for {}.", - c->GetTargetDescription(target) + c->GetTargetDescription(t) ).c_str() ); } - diff --git a/zone/gm_commands/resetaa_timer.cpp b/zone/gm_commands/resetaa_timer.cpp index bb108c6c4..766c76b06 100755 --- a/zone/gm_commands/resetaa_timer.cpp +++ b/zone/gm_commands/resetaa_timer.cpp @@ -2,43 +2,44 @@ void command_resetaa_timer(Client *c, const Seperator *sep) { - int arguments = sep->argnum; + const auto arguments = sep->argnum; if (!arguments) { c->Message(Chat::White, "Usage: #resetaa_timer all - Reset all Alternate Advancement timers"); c->Message(Chat::White, "Usage: #resetaa_timer [Timer ID] - Reset Alternate Advancement timer by ID"); return; } - auto target = c; + auto t = c; if (c->GetTarget() && c->GetTarget()->IsClient()) { - target = c->GetTarget()->CastToClient(); + t = c->GetTarget()->CastToClient(); } - bool is_all = !strcasecmp(sep->arg[1], "all"); + const bool is_all = !strcasecmp(sep->arg[1], "all"); if (is_all) { c->Message( Chat::White, fmt::format( "Reset all Alternate Advancement timers for {}.", - c->GetTargetDescription(target) + c->GetTargetDescription(t) ).c_str() ); - target->ResetAlternateAdvancementTimers(); - return; - } - if (sep->IsNumber(1)) { - int timer_id = std::stoi(sep->arg[1]); + t->ResetAlternateAdvancementTimers(); + + return; + } else if (sep->IsNumber(1)) { + const auto timer_id = Strings::ToInt(sep->arg[1]); + c->Message( Chat::White, fmt::format( "Reset Alternate Advancement timer {} for {}.", timer_id, - c->GetTargetDescription(target) + c->GetTargetDescription(t) ).c_str() ); - target->ResetAlternateAdvancementTimer(timer_id); + + t->ResetAlternateAdvancementTimer(timer_id); } } - diff --git a/zone/gm_commands/resetdisc_timer.cpp b/zone/gm_commands/resetdisc_timer.cpp index 305ae5c3a..4223aab62 100755 --- a/zone/gm_commands/resetdisc_timer.cpp +++ b/zone/gm_commands/resetdisc_timer.cpp @@ -29,7 +29,7 @@ void command_resetdisc_timer(Client *c, const Seperator *sep) } if (sep->IsNumber(1)) { - auto timer_id = std::stoul(sep->arg[1]); + auto timer_id = Strings::ToUnsignedInt(sep->arg[1]); c->Message( Chat::White, fmt::format( diff --git a/zone/gm_commands/revoke.cpp b/zone/gm_commands/revoke.cpp index 50eba21a2..abad1655b 100755 --- a/zone/gm_commands/revoke.cpp +++ b/zone/gm_commands/revoke.cpp @@ -25,7 +25,7 @@ void command_revoke(Client *c, const Seperator *sep) return; } - bool revoked = std::stoi(sep->arg[2]) ? true : false; + bool revoked = Strings::ToInt(sep->arg[2]) ? true : false; auto query = fmt::format( "UPDATE account SET revoked = {} WHERE id = {}", diff --git a/zone/gm_commands/roambox.cpp b/zone/gm_commands/roambox.cpp index 1955fb09c..410928f9d 100755 --- a/zone/gm_commands/roambox.cpp +++ b/zone/gm_commands/roambox.cpp @@ -52,10 +52,10 @@ void command_roambox(Client *c, const Seperator *sep) int delay = 15000; if (arguments >= 2) { - box_size = std::stof(sep->arg[2]); + box_size = Strings::ToFloat(sep->arg[2]); if (arguments == 3) { - delay = std::stoi(sep->arg[3]); + delay = Strings::ToInt(sep->arg[3]); } } diff --git a/zone/gm_commands/scribespell.cpp b/zone/gm_commands/scribespell.cpp index a5c843f49..03594464f 100755 --- a/zone/gm_commands/scribespell.cpp +++ b/zone/gm_commands/scribespell.cpp @@ -13,7 +13,7 @@ void command_scribespell(Client *c, const Seperator *sep) t = c->GetTarget()->CastToClient(); } - const auto spell_id = std::stoul(sep->arg[1]); + const auto spell_id = Strings::ToUnsignedInt(sep->arg[1]); if (IsValidSpell(spell_id)) { t->Message( diff --git a/zone/gm_commands/scribespells.cpp b/zone/gm_commands/scribespells.cpp index 2a141de4b..93ce21538 100755 --- a/zone/gm_commands/scribespells.cpp +++ b/zone/gm_commands/scribespells.cpp @@ -14,10 +14,10 @@ void command_scribespells(Client *c, const Seperator *sep) } uint8 rule_max_level = RuleI(Character, MaxLevel); - auto max_level = static_cast(std::stoul(sep->arg[1])); + auto max_level = static_cast(Strings::ToUnsignedInt(sep->arg[1])); uint8 min_level = ( sep->IsNumber(2) ? - static_cast(std::stoul(sep->arg[2])) : + static_cast(Strings::ToUnsignedInt(sep->arg[2])) : 1 ); // Default to Level 1 if there isn't a 2nd argument diff --git a/zone/gm_commands/serverlock.cpp b/zone/gm_commands/serverlock.cpp index 59a43f912..cd2c38ff9 100644 --- a/zone/gm_commands/serverlock.cpp +++ b/zone/gm_commands/serverlock.cpp @@ -9,8 +9,8 @@ void command_serverlock(Client *c, const Seperator *sep) c->Message(Chat::White, "Usage: #serverlock [0|1] - Lock or Unlock the World Server (0 = Unlocked, 1 = Locked)"); return; } - - auto is_locked = std::stoi(sep->arg[1]) ? true : false; + + auto is_locked = Strings::ToInt(sep->arg[1]) ? true : false; auto pack = new ServerPacket(ServerOP_Lock, sizeof(ServerLock_Struct)); auto l = (ServerLock_Struct *) pack->pBuffer; diff --git a/zone/gm_commands/set_adventure_points.cpp b/zone/gm_commands/set_adventure_points.cpp index 8518f2aa8..160344fd2 100755 --- a/zone/gm_commands/set_adventure_points.cpp +++ b/zone/gm_commands/set_adventure_points.cpp @@ -4,7 +4,7 @@ void command_set_adventure_points(Client *c, const Seperator *sep) { int arguments = sep->argnum; - + if ( !arguments || !sep->IsNumber(1) || @@ -32,7 +32,7 @@ void command_set_adventure_points(Client *c, const Seperator *sep) target = c->GetTarget()->CastToClient(); } - auto theme_id = std::stoul(sep->arg[1]); + auto theme_id = Strings::ToUnsignedInt(sep->arg[1]); if (!EQ::ValueWithin(theme_id, LDoNThemes::Unused, LDoNThemes::TAK)) { c->Message(Chat::White, "Valid themes are as follows."); auto theme_map = EQ::constants::GetLDoNThemeMap(); @@ -45,12 +45,12 @@ void command_set_adventure_points(Client *c, const Seperator *sep) theme.second ).c_str() ); - } + } c->Message(Chat::White, "Note: Theme 0 splits the points evenly across all Themes."); return; } - auto points = std::stoi(sep->arg[2]); + auto points = Strings::ToInt(sep->arg[2]); c->Message( Chat::White, diff --git a/zone/gm_commands/setaapts.cpp b/zone/gm_commands/setaapts.cpp index c1c730a5f..86b8c2994 100755 --- a/zone/gm_commands/setaapts.cpp +++ b/zone/gm_commands/setaapts.cpp @@ -18,7 +18,7 @@ void command_setaapts(Client *c, const Seperator *sep) std::string aa_type = Strings::ToLower(sep->arg[1]); std::string group_raid_string; - uint32 aa_points = static_cast(std::min(std::stoull(sep->arg[2]), (unsigned long long) 2000000000)); + uint32 aa_points = static_cast(std::min(Strings::ToUnsignedBigInt(sep->arg[2]), (uint64) 2000000000)); bool is_aa = aa_type.find("aa") != std::string::npos; bool is_group = aa_type.find("group") != std::string::npos; bool is_raid = aa_type.find("raid") != std::string::npos; diff --git a/zone/gm_commands/setaaxp.cpp b/zone/gm_commands/setaaxp.cpp index 12339c3ed..dbf81320f 100755 --- a/zone/gm_commands/setaaxp.cpp +++ b/zone/gm_commands/setaaxp.cpp @@ -19,8 +19,8 @@ void command_setaaxp(Client *c, const Seperator *sep) std::string aa_type = Strings::ToLower(sep->arg[1]); std::string group_raid_string; uint32 aa_experience = static_cast(std::min( - std::stoull(sep->arg[2]), - (unsigned long long) 2000000000 + Strings::ToUnsignedBigInt(sep->arg[2]), + (uint64) 2000000000 )); bool is_aa = aa_type.find("aa") != std::string::npos; bool is_group = aa_type.find("group") != std::string::npos; diff --git a/zone/gm_commands/setaltcurrency.cpp b/zone/gm_commands/setaltcurrency.cpp index d484ee3b1..d3208cc0c 100644 --- a/zone/gm_commands/setaltcurrency.cpp +++ b/zone/gm_commands/setaltcurrency.cpp @@ -17,8 +17,8 @@ void command_setaltcurrency(Client *c, const Seperator *sep) target = c->GetTarget()->CastToClient(); } - auto currency_id = std::stoul(sep->arg[1]); - auto amount = static_cast(std::min(std::stoll(sep->arg[2]), (long long) 2000000000)); + auto currency_id = Strings::ToUnsignedInt(sep->arg[1]); + auto amount = static_cast(std::min(Strings::ToBigInt(sep->arg[2]), (int64) 2000000000)); uint32 currency_item_id = zone->GetCurrencyItemID(currency_id); if (!currency_item_id) { c->Message( @@ -32,7 +32,7 @@ void command_setaltcurrency(Client *c, const Seperator *sep) } target->SetAlternateCurrencyValue(currency_id, amount); - + c->Message( Chat::White, fmt::format( diff --git a/zone/gm_commands/setanim.cpp b/zone/gm_commands/setanim.cpp index b6deeec01..2a191aac2 100755 --- a/zone/gm_commands/setanim.cpp +++ b/zone/gm_commands/setanim.cpp @@ -14,7 +14,7 @@ void command_setanim(Client *c, const Seperator *sep) } - int animation_id = std::stoi(sep->arg[1]); + int animation_id = Strings::ToInt(sep->arg[1]); if ( animation_id < 0 || animation_id > eaLooting @@ -36,7 +36,7 @@ void command_setanim(Client *c, const Seperator *sep) } else if (animation_id == eaLooting) { animation_name = "Looting"; } - + c->Message( Chat::White, fmt::format( diff --git a/zone/gm_commands/setanon.cpp b/zone/gm_commands/setanon.cpp index 955bbd884..2b50c3def 100755 --- a/zone/gm_commands/setanon.cpp +++ b/zone/gm_commands/setanon.cpp @@ -12,7 +12,7 @@ void command_setanon(Client *c, const Seperator *sep) } if (arguments == 1) { - const uint8 anon_flag = static_cast(std::stoul(sep->arg[1])); + const uint8 anon_flag = static_cast(Strings::ToUnsignedInt(sep->arg[1])); auto t = c; if (c->GetTarget() && c->GetTarget()->IsClient() && c->GetGM()) { t = c->GetTarget()->CastToClient(); @@ -44,8 +44,8 @@ void command_setanon(Client *c, const Seperator *sep) ).c_str() ); } else if (arguments == 2) { - const auto character_id = std::stoi(sep->arg[1]); - const uint8 anon_flag = static_cast(std::stoul(sep->arg[2])); + const auto character_id = Strings::ToInt(sep->arg[1]); + const uint8 anon_flag = static_cast(Strings::ToUnsignedInt(sep->arg[2])); auto e = CharacterDataRepository::FindOne(content_db, character_id); if (!e.id) { diff --git a/zone/gm_commands/setcrystals.cpp b/zone/gm_commands/setcrystals.cpp index 95a537e9a..b2befc92a 100755 --- a/zone/gm_commands/setcrystals.cpp +++ b/zone/gm_commands/setcrystals.cpp @@ -15,8 +15,8 @@ void command_setcrystals(Client *c, const Seperator *sep) std::string crystal_type = Strings::ToLower(sep->arg[1]); uint32 crystal_amount = static_cast(std::min( - std::stoull(sep->arg[2]), - (unsigned long long) 2000000000 + Strings::ToUnsignedBigInt(sep->arg[2]), + (uint64) 2000000000 )); bool is_ebon = crystal_type.find("ebon") != std::string::npos; bool is_radiant = crystal_type.find("radiant") != std::string::npos; diff --git a/zone/gm_commands/setendurance.cpp b/zone/gm_commands/setendurance.cpp index 920b30829..86da26008 100644 --- a/zone/gm_commands/setendurance.cpp +++ b/zone/gm_commands/setendurance.cpp @@ -8,13 +8,13 @@ void command_setendurance(Client *c, const Seperator *sep) return; } - auto endurance = static_cast(std::min(std::stoll(sep->arg[1]), (long long) 2000000000)); + auto endurance = static_cast(std::min(Strings::ToBigInt(sep->arg[1]), (int64) 2000000000)); bool set_to_max = false; Mob* target = c; if (c->GetTarget()) { target = c->GetTarget(); } - + if (target->IsClient()) { if (endurance >= target->CastToClient()->GetMaxEndurance()) { endurance = target->CastToClient()->GetMaxEndurance(); @@ -51,4 +51,4 @@ void command_setendurance(Client *c, const Seperator *sep) ) ).c_str() ); -} \ No newline at end of file +} diff --git a/zone/gm_commands/setfaction.cpp b/zone/gm_commands/setfaction.cpp index 17b3c288f..a3d8a82a3 100755 --- a/zone/gm_commands/setfaction.cpp +++ b/zone/gm_commands/setfaction.cpp @@ -7,7 +7,7 @@ void command_setfaction(Client *c, const Seperator *sep) c->Message(Chat::White, "Usage: #setfaction [Faction ID]"); return; } - + if ( !c->GetTarget() || ( @@ -21,7 +21,7 @@ void command_setfaction(Client *c, const Seperator *sep) NPC* target = c->GetTarget()->CastToNPC(); auto npc_id = target->GetNPCTypeID(); - auto faction_id = std::stoi(sep->arg[1]); + auto faction_id = Strings::ToInt(sep->arg[1]); auto faction_name = content_db.GetFactionName(faction_id); if (!faction_name.empty()) { c->Message( diff --git a/zone/gm_commands/sethp.cpp b/zone/gm_commands/sethp.cpp index e3efbc955..9c1463e13 100644 --- a/zone/gm_commands/sethp.cpp +++ b/zone/gm_commands/sethp.cpp @@ -8,7 +8,7 @@ void command_sethp(Client *c, const Seperator *sep) return; } - auto health = static_cast(std::min(std::stoll(sep->arg[1]), (long long) 2000000000)); + auto health = static_cast(std::min(Strings::ToBigInt(sep->arg[1]), (int64) 2000000000)); bool set_to_max = false; Mob* target = c; if (c->GetTarget()) { diff --git a/zone/gm_commands/setlanguage.cpp b/zone/gm_commands/setlanguage.cpp index 5b8073b8d..ad9b400ef 100755 --- a/zone/gm_commands/setlanguage.cpp +++ b/zone/gm_commands/setlanguage.cpp @@ -9,8 +9,8 @@ void command_setlanguage(Client *c, const Seperator *sep) target = c->GetTarget()->CastToClient(); } - auto language_id = sep->IsNumber(1) ? std::stoi(sep->arg[1]) : -1; - auto language_value = sep->IsNumber(2) ? std::stoi(sep->arg[2]) : -1; + auto language_id = sep->IsNumber(1) ? Strings::ToInt(sep->arg[1]) : -1; + auto language_value = sep->IsNumber(2) ? Strings::ToInt(sep->arg[2]) : -1; if (!strcasecmp(sep->arg[1], "list")) { for (const auto& language : EQ::constants::GetLanguageMap()) { c->Message( diff --git a/zone/gm_commands/setmana.cpp b/zone/gm_commands/setmana.cpp index 3b1c1132b..57e2e6ece 100644 --- a/zone/gm_commands/setmana.cpp +++ b/zone/gm_commands/setmana.cpp @@ -8,7 +8,7 @@ void command_setmana(Client *c, const Seperator *sep) return; } - auto mana = static_cast(std::min(std::stoll(sep->arg[1]), (long long) 2000000000)); + auto mana = static_cast(std::min(Strings::ToBigInt(sep->arg[1]), (int64) 2000000000)); bool set_to_max = false; Mob* target = c; if (c->GetTarget()) { diff --git a/zone/gm_commands/setpvppoints.cpp b/zone/gm_commands/setpvppoints.cpp index b6d3a0598..15b24a01a 100755 --- a/zone/gm_commands/setpvppoints.cpp +++ b/zone/gm_commands/setpvppoints.cpp @@ -13,7 +13,7 @@ void command_setpvppoints(Client *c, const Seperator *sep) target = c->GetTarget()->CastToClient(); } - uint32 pvp_points = static_cast(std::min(std::stoull(sep->arg[1]), (unsigned long long) 2000000000)); + uint32 pvp_points = static_cast(std::min(Strings::ToUnsignedBigInt(sep->arg[1]), (uint64) 2000000000)); target->SetPVPPoints(pvp_points); target->Save(); target->SendPVPStats(); diff --git a/zone/gm_commands/setskill.cpp b/zone/gm_commands/setskill.cpp index fd6cacaa5..297b36688 100755 --- a/zone/gm_commands/setskill.cpp +++ b/zone/gm_commands/setskill.cpp @@ -7,8 +7,8 @@ void command_setskill(Client *c, const Seperator *sep) target = c->GetTarget()->CastToClient(); } - auto skill_id = sep->IsNumber(1) ? std::stoi(sep->arg[1]) : -1; - auto skill_value = sep->IsNumber(2) ? std::stoi(sep->arg[2]) : -1; + auto skill_id = sep->IsNumber(1) ? Strings::ToInt(sep->arg[1]) : -1; + auto skill_value = sep->IsNumber(2) ? Strings::ToInt(sep->arg[2]) : -1; if ( skill_id < 0 || skill_id > EQ::skills::HIGHEST_SKILL || diff --git a/zone/gm_commands/setskillall.cpp b/zone/gm_commands/setskillall.cpp index f9ec1e3e4..e3652aef0 100755 --- a/zone/gm_commands/setskillall.cpp +++ b/zone/gm_commands/setskillall.cpp @@ -24,7 +24,7 @@ void command_setskillall(Client *c, const Seperator *sep) c->GetTargetDescription(target) ); - auto skill_level = static_cast(std::stoul(sep->arg[1])); + auto skill_level = static_cast(Strings::ToUnsignedInt(sep->arg[1])); c->Message( Chat::White, diff --git a/zone/gm_commands/setstartzone.cpp b/zone/gm_commands/setstartzone.cpp index 16e66bb6e..7accda12e 100755 --- a/zone/gm_commands/setstartzone.cpp +++ b/zone/gm_commands/setstartzone.cpp @@ -19,7 +19,7 @@ void command_setstartzone(Client *c, const Seperator *sep) auto zone_id = ( sep->IsNumber(1) ? - std::stoul(sep->arg[1]) : + Strings::ToUnsignedInt(sep->arg[1]) : ZoneID(sep->arg[1]) ); diff --git a/zone/gm_commands/setstat.cpp b/zone/gm_commands/setstat.cpp index 56ff81a05..7e4c42cd3 100755 --- a/zone/gm_commands/setstat.cpp +++ b/zone/gm_commands/setstat.cpp @@ -3,7 +3,7 @@ void command_setstat(Client *c, const Seperator *sep) { if (sep->arg[1][0] && sep->arg[2][0] && c->GetTarget() != 0 && c->GetTarget()->IsClient()) { - c->GetTarget()->CastToClient()->SetStats(atoi(sep->arg[1]), atoi(sep->arg[2])); + c->GetTarget()->CastToClient()->SetStats(Strings::ToInt(sep->arg[1]), Strings::ToInt(sep->arg[2])); } else { c->Message(Chat::White, "This command is used to permanently increase or decrease a players stats."); diff --git a/zone/gm_commands/setxp.cpp b/zone/gm_commands/setxp.cpp index c82bb87a3..8aa810b0b 100755 --- a/zone/gm_commands/setxp.cpp +++ b/zone/gm_commands/setxp.cpp @@ -9,11 +9,11 @@ void command_setxp(Client *c, const Seperator *sep) } if (sep->IsNumber(1)) { - if (atoi(sep->arg[1]) > 9999999) { + if (Strings::ToInt(sep->arg[1]) > 9999999) { c->Message(Chat::White, "Error: Value too high."); } else { - t->AddEXP(atoi(sep->arg[1])); + t->AddEXP(Strings::ToInt(sep->arg[1])); } } else { diff --git a/zone/gm_commands/showskills.cpp b/zone/gm_commands/showskills.cpp index d4c23d91a..d70df9974 100755 --- a/zone/gm_commands/showskills.cpp +++ b/zone/gm_commands/showskills.cpp @@ -9,7 +9,7 @@ void command_showskills(Client *c, const Seperator *sep) uint32 start_skill_id = 0; if (sep->IsNumber(1)) { - start_skill_id = std::stoul(sep->arg[1]); + start_skill_id = Strings::ToUnsignedInt(sep->arg[1]); } bool show_all = !strcasecmp(sep->arg[2], "all"); diff --git a/zone/gm_commands/spawneditmass.cpp b/zone/gm_commands/spawneditmass.cpp index 8321cf840..8e66d0fca 100644 --- a/zone/gm_commands/spawneditmass.cpp +++ b/zone/gm_commands/spawneditmass.cpp @@ -66,7 +66,7 @@ void command_spawneditmass(Client *c, const Seperator *sep) Strings::Commify(spawn2_id), Strings::Commify(npc_id), npc_name, - Strings::SecondsToTime(std::stoi(respawn_time)), + Strings::SecondsToTime(Strings::ToInt(respawn_time)), Strings::Commify(respawn_time) ).c_str() ); @@ -131,7 +131,7 @@ void command_spawneditmass(Client *c, const Seperator *sep) SQL( UPDATE spawn2 SET respawntime = {} WHERE id IN ({}) ), - std::stoi(edit_value), + Strings::ToInt(edit_value), spawn2_ids_string ) ); diff --git a/zone/gm_commands/spawnstatus.cpp b/zone/gm_commands/spawnstatus.cpp index ed465899c..5b88e6c50 100755 --- a/zone/gm_commands/spawnstatus.cpp +++ b/zone/gm_commands/spawnstatus.cpp @@ -38,7 +38,7 @@ void command_spawnstatus(Client *c, const Seperator *sep) uint32 spawn_id = 0; if (is_search) { - spawn_id = std::stoul(sep->arg[1]); + spawn_id = Strings::ToUnsignedInt(sep->arg[1]); } LinkedListIterator iterator(zone->spawn2_list); diff --git a/zone/gm_commands/spellinfo.cpp b/zone/gm_commands/spellinfo.cpp index 7b9720fe1..83c6c5cfe 100755 --- a/zone/gm_commands/spellinfo.cpp +++ b/zone/gm_commands/spellinfo.cpp @@ -6,7 +6,7 @@ void command_spellinfo(Client *c, const Seperator *sep) c->Message(Chat::White, "Usage: #spellinfo [spell_id]"); } else { - int32_t spell_id = atoi(sep->arg[1]); + int32_t spell_id = Strings::ToInt(sep->arg[1]); const struct SPDat_Spell_Struct *s = &spells[spell_id]; c->Message(Chat::White, "Spell info for spell #%d:", spell_id); c->Message(Chat::White, " name: %s", s->name); diff --git a/zone/gm_commands/stun.cpp b/zone/gm_commands/stun.cpp index 8468aad60..32da4593c 100755 --- a/zone/gm_commands/stun.cpp +++ b/zone/gm_commands/stun.cpp @@ -9,7 +9,7 @@ void command_stun(Client *c, const Seperator *sep) } Mob *target = c; - int duration = static_cast(std::min(std::stoll(sep->arg[1]), (long long) 2000000000)); + int duration = static_cast(std::min(Strings::ToBigInt(sep->arg[1]), (int64) 2000000000)); if (duration < 0) { duration = 0; diff --git a/zone/gm_commands/summonitem.cpp b/zone/gm_commands/summonitem.cpp index e3053bd71..65a744dea 100755 --- a/zone/gm_commands/summonitem.cpp +++ b/zone/gm_commands/summonitem.cpp @@ -33,7 +33,7 @@ void command_summonitem(Client *c, const Seperator *sep) return; } else { - item_id = atoi(sep->arg[1]); + item_id = Strings::ToInt(sep->arg[1]); } if (!item_id) { @@ -60,31 +60,31 @@ void command_summonitem(Client *c, const Seperator *sep) } if (arguments >= 2 && sep->IsNumber(2)) { - charges = atoi(sep->arg[2]); + charges = Strings::ToInt(sep->arg[2]); } if (arguments >= 3 && sep->IsNumber(3)) { - augment_one = atoi(sep->arg[3]); + augment_one = Strings::ToInt(sep->arg[3]); } if (arguments >= 4 && sep->IsNumber(4)) { - augment_two = atoi(sep->arg[4]); + augment_two = Strings::ToInt(sep->arg[4]); } if (arguments >= 5 && sep->IsNumber(5)) { - augment_three = atoi(sep->arg[5]); + augment_three = Strings::ToInt(sep->arg[5]); } if (arguments >= 6 && sep->IsNumber(6)) { - augment_four = atoi(sep->arg[6]); + augment_four = Strings::ToInt(sep->arg[6]); } if (arguments >= 7 && sep->IsNumber(7)) { - augment_five = atoi(sep->arg[7]); + augment_five = Strings::ToInt(sep->arg[7]); } if (arguments == 8 && sep->IsNumber(8)) { - augment_six = atoi(sep->arg[8]); + augment_six = Strings::ToInt(sep->arg[8]); } c->SummonItem(item_id, charges, augment_one, augment_two, augment_three, augment_four, augment_five, augment_six); diff --git a/zone/gm_commands/suspend.cpp b/zone/gm_commands/suspend.cpp index c11daff53..8ee19cd42 100755 --- a/zone/gm_commands/suspend.cpp +++ b/zone/gm_commands/suspend.cpp @@ -14,7 +14,7 @@ void command_suspend(Client *c, const Seperator *sep) } const std::string character_name = Strings::ToLower(sep->arg[1]); - auto days = std::stoul(sep->arg[2]); + auto days = Strings::ToUnsignedInt(sep->arg[2]); const std::string reason = sep->arg[3] ? sep->argplus[3] : ""; diff --git a/zone/gm_commands/suspendmulti.cpp b/zone/gm_commands/suspendmulti.cpp index 9f77aaf7c..b2ff2fb1c 100755 --- a/zone/gm_commands/suspendmulti.cpp +++ b/zone/gm_commands/suspendmulti.cpp @@ -19,7 +19,7 @@ void command_suspendmulti(Client *c, const Seperator *sep) v.push_back(fmt::format("'{}'", Strings::ToLower(c))); } - auto days = std::stoul(sep->arg[2]); + auto days = Strings::ToUnsignedInt(sep->arg[2]); const std::string reason = sep->arg[3] ? sep->argplus[3] : ""; diff --git a/zone/gm_commands/task.cpp b/zone/gm_commands/task.cpp index 6ae2c7d69..723e461bc 100755 --- a/zone/gm_commands/task.cpp +++ b/zone/gm_commands/task.cpp @@ -246,7 +246,7 @@ void command_task(Client *c, const Seperator *sep) return; } else if (is_uncomplete) { if (sep->IsNumber(2)) { - auto task_id = std::stoul(sep->arg[2]); + auto task_id = Strings::ToUnsignedInt(sep->arg[2]); if (!task_id) { c->Message(Chat::White, "Invalid task ID specified."); return; diff --git a/zone/gm_commands/texture.cpp b/zone/gm_commands/texture.cpp index 1a5c94a16..24dde1f0f 100755 --- a/zone/gm_commands/texture.cpp +++ b/zone/gm_commands/texture.cpp @@ -8,10 +8,10 @@ void command_texture(Client *c, const Seperator *sep) return; } - auto texture = static_cast(std::min(std::stoul(sep->arg[1]), (unsigned long) 65535)); + auto texture = static_cast(std::min(Strings::ToUnsignedInt(sep->arg[1]), (uint32) 65535)); auto helmet_texture = static_cast( sep->IsNumber(2) ? - std::min(std::stoul(sep->arg[2]), (unsigned long) 255) : + std::min(Strings::ToUnsignedInt(sep->arg[2]), (uint32) 255) : 0 ); diff --git a/zone/gm_commands/time.cpp b/zone/gm_commands/time.cpp index 8254a3de1..7df178eca 100755 --- a/zone/gm_commands/time.cpp +++ b/zone/gm_commands/time.cpp @@ -8,7 +8,7 @@ void command_time(Client *c, const Seperator *sep) TimeOfDay_Struct world_time; zone->zone_time.GetCurrentEQTimeOfDay(time(0), &world_time); - + auto time_string = fmt::format( "{:02}:{:02} {} (Timezone: {:02}:{:02} {})", ( @@ -47,7 +47,7 @@ void command_time(Client *c, const Seperator *sep) } uint8 minutes = 0; - auto hours = static_cast(std::stoul(sep->arg[1]) + 1); + auto hours = static_cast(Strings::ToUnsignedInt(sep->arg[1]) + 1); if (hours > 24) { hours = 24; @@ -60,7 +60,7 @@ void command_time(Client *c, const Seperator *sep) ); if (sep->IsNumber(2)) { - minutes = static_cast(std::stoul(sep->arg[2])); + minutes = static_cast(Strings::ToUnsignedInt(sep->arg[2])); if (minutes > 59) { minutes = 59; diff --git a/zone/gm_commands/timezone.cpp b/zone/gm_commands/timezone.cpp index 4e73a8108..9270f1445 100755 --- a/zone/gm_commands/timezone.cpp +++ b/zone/gm_commands/timezone.cpp @@ -26,7 +26,7 @@ void command_timezone(Client *c, const Seperator *sep) } uint8 minutes = 0; - auto hours = static_cast(std::stoul(sep->arg[1])); + auto hours = static_cast(Strings::ToUnsignedInt(sep->arg[1])); if (hours > 24) { hours = 24; @@ -39,7 +39,7 @@ void command_timezone(Client *c, const Seperator *sep) ); if (sep->IsNumber(2)) { - minutes = static_cast(std::stoul(sep->arg[2])); + minutes = static_cast(Strings::ToUnsignedInt(sep->arg[2])); if (minutes > 59) { minutes = 59; diff --git a/zone/gm_commands/traindisc.cpp b/zone/gm_commands/traindisc.cpp index 4392aa126..aeb4e8d9f 100755 --- a/zone/gm_commands/traindisc.cpp +++ b/zone/gm_commands/traindisc.cpp @@ -13,11 +13,11 @@ void command_traindisc(Client *c, const Seperator *sep) } uint8 rule_max_level = (uint8) RuleI(Character, MaxLevel); - uint8 max_level = (uint8) std::stoi(sep->arg[1]); + uint8 max_level = (uint8) Strings::ToInt(sep->arg[1]); uint8 min_level = ( sep->IsNumber(2) ? (uint8) - std::stoi(sep->arg[2]) : + Strings::ToInt(sep->arg[2]) : 1 ); // Default to Level 1 if there isn't a 2nd argument diff --git a/zone/gm_commands/tune.cpp b/zone/gm_commands/tune.cpp index e34f9aa49..7174039e9 100755 --- a/zone/gm_commands/tune.cpp +++ b/zone/gm_commands/tune.cpp @@ -197,11 +197,11 @@ void command_tune(Client *c, const Seperator *sep) } if (!strcasecmp(sep->arg[1], "FindATK")) { - float pct_mitigation = atof(sep->arg[3]); - int interval = atoi(sep->arg[4]); - int max_loop = atoi(sep->arg[5]); - int ac_override = atoi(sep->arg[6]); - int info_level = atoi(sep->arg[7]); + float pct_mitigation = Strings::ToFloat(sep->arg[3]); + int interval = Strings::ToInt(sep->arg[4]); + int max_loop = Strings::ToInt(sep->arg[5]); + int ac_override = Strings::ToInt(sep->arg[6]); + int info_level = Strings::ToInt(sep->arg[7]); if (!pct_mitigation) { c->Message(Chat::White, "[#Tune] - Error must enter the desired percent mitigation on defender."); @@ -277,11 +277,11 @@ void command_tune(Client *c, const Seperator *sep) } if (!strcasecmp(sep->arg[1], "FindAC")) { - float pct_mitigation = atof(sep->arg[3]); - int interval = atoi(sep->arg[4]); - int max_loop = atoi(sep->arg[5]); - int atk_override = atoi(sep->arg[6]); - int info_level = atoi(sep->arg[7]); + float pct_mitigation = Strings::ToFloat(sep->arg[3]); + int interval = Strings::ToInt(sep->arg[4]); + int max_loop = Strings::ToInt(sep->arg[5]); + int atk_override = Strings::ToInt(sep->arg[6]); + int info_level = Strings::ToInt(sep->arg[7]); if (!pct_mitigation) { c->Message(Chat::White, "#Tune - Error must enter the desired percent mitigation on defender."); @@ -358,11 +358,11 @@ void command_tune(Client *c, const Seperator *sep) } if (!strcasecmp(sep->arg[1], "FindAccuracy")) { - float hit_chance = atof(sep->arg[3]); - int interval = atoi(sep->arg[4]); - int max_loop = atoi(sep->arg[5]); - int avoid_override = atoi(sep->arg[6]); - int info_level = atoi(sep->arg[7]); + float hit_chance = Strings::ToFloat(sep->arg[3]); + int interval = Strings::ToInt(sep->arg[4]); + int max_loop = Strings::ToInt(sep->arg[5]); + int avoid_override = Strings::ToInt(sep->arg[6]); + int info_level = Strings::ToInt(sep->arg[7]); if (!hit_chance) { c->Message(Chat::White, "#Tune - Error must enter the desired hit chance on defender."); @@ -439,11 +439,11 @@ void command_tune(Client *c, const Seperator *sep) } if (!strcasecmp(sep->arg[1], "FindAvoidance")) { - float hit_chance = atof(sep->arg[3]); - int interval = atoi(sep->arg[4]); - int max_loop = atoi(sep->arg[5]); - int acc_override = atoi(sep->arg[6]); - int info_level = atoi(sep->arg[7]); + float hit_chance = Strings::ToFloat(sep->arg[3]); + int interval = Strings::ToInt(sep->arg[4]); + int max_loop = Strings::ToInt(sep->arg[5]); + int acc_override = Strings::ToInt(sep->arg[6]); + int info_level = Strings::ToInt(sep->arg[7]); if (!hit_chance) { c->Message(Chat::White, "#Tune - Error must enter the desired hit chance on defender."); diff --git a/zone/gm_commands/undye.cpp b/zone/gm_commands/undye.cpp index 414ac9ab4..f66cc9185 100755 --- a/zone/gm_commands/undye.cpp +++ b/zone/gm_commands/undye.cpp @@ -3,7 +3,7 @@ void command_undye(Client *c, const Seperator *sep) { auto target = c; - if (c->GetTarget() && c->GetTarget()->IsClient()) { + if (c->GetTarget() && c->GetTarget()->IsClient() && c->GetGM()) { target = c->GetTarget()->CastToClient(); } diff --git a/zone/gm_commands/undyeme.cpp b/zone/gm_commands/undyeme.cpp deleted file mode 100755 index 8bd6924b1..000000000 --- a/zone/gm_commands/undyeme.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "../client.h" - -void command_undyeme(Client *c, const Seperator *sep) -{ - c->Undye(); - c->Message(Chat::White, "Undyed armor for yourself."); -} diff --git a/zone/gm_commands/unmemspell.cpp b/zone/gm_commands/unmemspell.cpp index 56589f9ec..b5450035f 100644 --- a/zone/gm_commands/unmemspell.cpp +++ b/zone/gm_commands/unmemspell.cpp @@ -16,7 +16,7 @@ void command_unmemspell(Client *c, const Seperator *sep) target = c->GetTarget()->CastToClient(); } - auto spell_id = static_cast(std::stoul(sep->arg[1])); + auto spell_id = static_cast(Strings::ToUnsignedInt(sep->arg[1])); if (!IsValidSpell(spell_id)) { c->Message( Chat::White, diff --git a/zone/gm_commands/unscribespell.cpp b/zone/gm_commands/unscribespell.cpp index bbb59af07..423288c3b 100755 --- a/zone/gm_commands/unscribespell.cpp +++ b/zone/gm_commands/unscribespell.cpp @@ -14,7 +14,7 @@ void command_unscribespell(Client *c, const Seperator *sep) target = c->GetTarget()->CastToClient(); } - uint16 spell_id = EQ::Clamp(std::stoi(sep->arg[1]), 0, 65535); + uint16 spell_id = EQ::Clamp(Strings::ToInt(sep->arg[1]), 0, 65535); if (!IsValidSpell(spell_id)) { c->Message( @@ -28,7 +28,7 @@ void command_unscribespell(Client *c, const Seperator *sep) } auto spell_name = GetSpellName(spell_id); - + if (target->HasSpellScribed(spell_id)) { target->UnscribeSpellBySpellID(spell_id); diff --git a/zone/gm_commands/untraindisc.cpp b/zone/gm_commands/untraindisc.cpp index 31620d78a..2337d7ae9 100755 --- a/zone/gm_commands/untraindisc.cpp +++ b/zone/gm_commands/untraindisc.cpp @@ -14,7 +14,7 @@ void command_untraindisc(Client *c, const Seperator *sep) target = c->GetTarget()->CastToClient(); } - uint16 spell_id = EQ::Clamp(std::stoi(sep->arg[1]), 0, 65535); + uint16 spell_id = EQ::Clamp(Strings::ToInt(sep->arg[1]), 0, 65535); if (!IsValidSpell(spell_id)) { c->Message( diff --git a/zone/gm_commands/uptime.cpp b/zone/gm_commands/uptime.cpp index 3c1c7bfbc..00b247d9f 100755 --- a/zone/gm_commands/uptime.cpp +++ b/zone/gm_commands/uptime.cpp @@ -12,8 +12,8 @@ void command_uptime(Client *c, const Seperator *sep) auto pack = new ServerPacket(ServerOP_Uptime, sizeof(ServerUptime_Struct)); ServerUptime_Struct *sus = (ServerUptime_Struct *) pack->pBuffer; strcpy(sus->adminname, c->GetName()); - if (sep->IsNumber(1) && atoi(sep->arg[1]) > 0) { - sus->zoneserverid = atoi(sep->arg[1]); + if (sep->IsNumber(1) && Strings::ToInt(sep->arg[1]) > 0) { + sus->zoneserverid = Strings::ToInt(sep->arg[1]); } worldserver.SendPacket(pack); safe_delete(pack); diff --git a/zone/gm_commands/viewnpctype.cpp b/zone/gm_commands/viewnpctype.cpp index bf3cc8fef..80c73bfef 100755 --- a/zone/gm_commands/viewnpctype.cpp +++ b/zone/gm_commands/viewnpctype.cpp @@ -3,7 +3,7 @@ void command_viewnpctype(Client *c, const Seperator *sep) { if (sep->IsNumber(1)) { - uint32 npc_id = std::stoul(sep->arg[1]); + uint32 npc_id = Strings::ToUnsignedInt(sep->arg[1]); const NPCType *npc_type_data = content_db.LoadNPCTypesData(npc_id); if (npc_type_data) { auto npc = new NPC( diff --git a/zone/gm_commands/viewpetition.cpp b/zone/gm_commands/viewpetition.cpp index a59821a81..eaff518a9 100755 --- a/zone/gm_commands/viewpetition.cpp +++ b/zone/gm_commands/viewpetition.cpp @@ -15,7 +15,7 @@ void command_viewpetition(Client *c, const Seperator *sep) return; } - LogInfo("View petition request from [{}], petition number: [{}]", c->GetName(), atoi(sep->argplus[1])); + LogInfo("View petition request from [{}], petition number: [{}]", c->GetName(), Strings::ToInt(sep->argplus[1])); if (results.RowCount() == 0) { c->Message(Chat::Red, "There was an error in your request: ID not found! Please check the Id and try again."); diff --git a/zone/gm_commands/viewrecipe.cpp b/zone/gm_commands/viewrecipe.cpp index d8eb820f3..74035de2a 100755 --- a/zone/gm_commands/viewrecipe.cpp +++ b/zone/gm_commands/viewrecipe.cpp @@ -11,7 +11,7 @@ void command_viewrecipe(Client *c, const Seperator *sep) return; } - auto recipe_id = static_cast(std::stoul(sep->arg[1])); + auto recipe_id = static_cast(Strings::ToUnsignedInt(sep->arg[1])); auto re = TradeskillRecipeEntriesRepository::GetWhere( database, fmt::format("recipe_id = {} ORDER BY id ASC", recipe_id) @@ -55,7 +55,7 @@ void command_viewrecipe(Client *c, const Seperator *sep) can_summon_items && e.item_id > 1000 ? fmt::format(" | {}", Saylink::Silent(fmt::format("#si {}", e.item_id), "Summon")) : "" ).c_str() ); - + std::vector emv; bool has_message = false; @@ -69,7 +69,7 @@ void command_viewrecipe(Client *c, const Seperator *sep) has_message = true; } - + if (e.failcount) { emv.push_back( fmt::format( @@ -80,7 +80,7 @@ void command_viewrecipe(Client *c, const Seperator *sep) has_message = true; } - + if (e.salvagecount) { emv.push_back( fmt::format( @@ -91,7 +91,7 @@ void command_viewrecipe(Client *c, const Seperator *sep) has_message = true; } - + if (e.successcount) { emv.push_back( fmt::format( diff --git a/zone/gm_commands/viewzoneloot.cpp b/zone/gm_commands/viewzoneloot.cpp index 24818663c..3f48a3847 100755 --- a/zone/gm_commands/viewzoneloot.cpp +++ b/zone/gm_commands/viewzoneloot.cpp @@ -6,7 +6,7 @@ void command_viewzoneloot(Client *c, const Seperator *sep) auto npc_list = entity_list.GetNPCList(); uint32 loot_amount = 0, loot_id = 1, search_item_id = 0; if (sep->argnum == 1 && sep->IsNumber(1)) { - search_item_id = atoi(sep->arg[1]); + search_item_id = Strings::ToInt(sep->arg[1]); } else if (sep->argnum == 1 && !sep->IsNumber(1)) { c->Message( diff --git a/zone/gm_commands/wc.cpp b/zone/gm_commands/wc.cpp index 0ec247aca..ada629b7f 100755 --- a/zone/gm_commands/wc.cpp +++ b/zone/gm_commands/wc.cpp @@ -1,44 +1,44 @@ #include "../client.h" +#include "../../common/data_verification.h" void command_wc(Client *c, const Seperator *sep) { - if (sep->argnum < 2) { - c->Message( - 0, - "Usage: #wc [wear slot] [material] [ [hero_forge_model] [elite_material] [unknown06] [unknown18] ]" - ); + const auto arguments = sep->argnum; + if ( + arguments < 2 || + !sep->IsNumber(1) || + !sep->IsNumber(2) + ) { + c->Message(Chat::White, "Usage: #wc [Slot ID] [Material]"); + c->Message(Chat::White, "Usage: #wc [Slot ID] [Material] [Hero Forge Model] [Elite Material]"); + return; } - else if (c->GetTarget() == nullptr) { - c->Message(Chat::Red, "You must have a target to do a wear change."); + + Mob* t = c; + if (c->GetTarget()) { + t = c->GetTarget(); } - else { - uint32 hero_forge_model = 0; - uint32 wearslot = atoi(sep->arg[1]); - // Hero Forge - if (sep->argnum > 2) { - hero_forge_model = atoi(sep->arg[3]); + const auto slot_id = static_cast(Strings::ToUnsignedInt(sep->arg[1])); + const auto texture = static_cast(Strings::ToUnsignedInt(sep->arg[2])); + uint32 hero_forge_model = 0; + uint32 elite_material = 0; - if (hero_forge_model != 0 && hero_forge_model < 1000) { - // Shorthand Hero Forge ID. Otherwise use the value the user entered. - hero_forge_model = (hero_forge_model * 100) + wearslot; - } + if (arguments >= 3 && sep->IsNumber(3)) { + hero_forge_model = Strings::ToUnsignedInt(sep->arg[3]); + if (EQ::ValueWithin(hero_forge_model, 1, 999)) { // Shorthand Hero Forge ID. Otherwise use the value the user entered. + hero_forge_model = (hero_forge_model * 100) + slot_id; } - /* - // Leaving here to add color option to the #wc command eventually - uint32 Color; - if (c->GetTarget()->IsClient()) - Color = c->GetTarget()->GetEquipmentColor(atoi(sep->arg[1])); - else - Color = c->GetTarget()->GetArmorTint(atoi(sep->arg[1])); - */ - c->GetTarget()->SendTextureWC( - wearslot, - atoi(sep->arg[2]), - hero_forge_model, - atoi(sep->arg[4]), - atoi(sep->arg[5]), - atoi(sep->arg[6])); } -} + if (arguments >= 4 && sep->IsNumber(4)) { + elite_material = Strings::ToUnsignedInt(sep->arg[4]); + } + + c->GetTarget()->SendTextureWC( + slot_id, + texture, + hero_forge_model, + elite_material + ); +} diff --git a/zone/gm_commands/weather.cpp b/zone/gm_commands/weather.cpp index 7c06255a7..6289275f1 100755 --- a/zone/gm_commands/weather.cpp +++ b/zone/gm_commands/weather.cpp @@ -10,11 +10,11 @@ void command_weather(Client *c, const Seperator *sep) int arguments = sep->argnum; if (arguments == 1) { - auto new_weather = static_cast(std::stoul(sep->arg[1])); + auto new_weather = static_cast(Strings::ToUnsignedInt(sep->arg[1])); uint8 new_intensity = 0; std::string weather_message = "The sky clears."; - if (new_weather == EQ::constants::WeatherTypes::Snowing) { + if (new_weather == EQ::constants::WeatherTypes::Snowing) { weather_message = "Snowflakes begin to fall from the sky."; new_weather = EQ::constants::WeatherTypes::Snowing; new_intensity = 0x02; @@ -22,10 +22,6 @@ void command_weather(Client *c, const Seperator *sep) weather_message = "Raindrops begin to fall from the sky."; new_weather = EQ::constants::WeatherTypes::Raining; new_intensity = 0x01; // This is how it's done in Fear, and you can see a decent distance with it at this value - } else { - c->Message(Chat::White, "Usage: #weather [0|1|2] - [Off|Rain|Snow]"); - c->Message(Chat::White, "Usage: #weather 3 [Type] [Intensity] - Manually set weather type and intensity"); - return; } zone->zone_weather = new_weather; @@ -45,15 +41,15 @@ void command_weather(Client *c, const Seperator *sep) safe_delete(outapp); } else if (arguments == 3) { - auto command_type = static_cast(std::stoul(sep->arg[1])); + auto command_type = static_cast(Strings::ToUnsignedInt(sep->arg[1])); uint8 new_weather = EQ::constants::WeatherTypes::None; uint8 new_intensity = 0; std::string weather_message; if (zone->zone_weather == EQ::constants::WeatherTypes::None) { if (command_type > EQ::constants::WeatherTypes::Snowing) { - new_weather = static_cast(std::stoul(sep->arg[2])); - new_intensity = static_cast(std::stoul(sep->arg[3])); + new_weather = static_cast(Strings::ToUnsignedInt(sep->arg[2])); + new_intensity = static_cast(Strings::ToUnsignedInt(sep->arg[3])); weather_message = fmt::format( "Sending {} ({}) with an intensity of {}.", @@ -61,7 +57,7 @@ void command_weather(Client *c, const Seperator *sep) new_weather, new_intensity ); - } else if (command_type == EQ::constants::WeatherTypes::Snowing) { + } else if (command_type == EQ::constants::WeatherTypes::Snowing) { weather_message = "Snowflakes begin to fall from the sky."; new_weather = EQ::constants::WeatherTypes::Snowing; new_intensity = 0x02; @@ -77,9 +73,9 @@ void command_weather(Client *c, const Seperator *sep) if (new_weather != EQ::constants::WeatherTypes::Raining) { outapp->pBuffer[0] = new_weather; } - + outapp->pBuffer[4] = new_intensity; - + c->Message(Chat::White, weather_message.c_str()); entity_list.QueueClients(c, outapp); diff --git a/zone/gm_commands/who.cpp b/zone/gm_commands/who.cpp index 0b833eaad..a67cc2799 100755 --- a/zone/gm_commands/who.cpp +++ b/zone/gm_commands/who.cpp @@ -64,17 +64,17 @@ void command_who(Client *c, const Seperator *sep) c->Message(Chat::Who, "------------------------------"); for (auto row : results) { - auto account_id = std::stoul(row[0]); + auto account_id = Strings::ToUnsignedInt(row[0]); std::string player_name = row[1]; - auto zone_id = std::stoul(row[2]); + auto zone_id = Strings::ToUnsignedInt(row[2]); std::string zone_short_name = ZoneName(zone_id); std::string zone_long_name = ZoneLongName(zone_id); - auto zone_instance = std::stoul(row[3]); + auto zone_instance = Strings::ToUnsignedInt(row[3]); std::string guild_name = row[4]; - auto player_level = std::stoul(row[5]); - auto player_race = std::stoul(row[6]); - auto player_class = std::stoul(row[7]); - auto account_status = std::stoul(row[8]); + auto player_level = Strings::ToUnsignedInt(row[5]); + auto player_race = Strings::ToUnsignedInt(row[6]); + auto player_class = Strings::ToUnsignedInt(row[7]); + auto account_status = Strings::ToUnsignedInt(row[8]); std::string account_name = row[9]; std::string account_ip = row[10]; std::string base_class_name = GetClassIDName(static_cast(player_class)); diff --git a/zone/gm_commands/worldshutdown.cpp b/zone/gm_commands/worldshutdown.cpp index 9c173c7d0..e42bcd29a 100755 --- a/zone/gm_commands/worldshutdown.cpp +++ b/zone/gm_commands/worldshutdown.cpp @@ -12,8 +12,8 @@ void command_worldshutdown(Client *c, const Seperator *sep) if ( sep->IsNumber(1) && sep->IsNumber(2) && - ((time = std::stoi(sep->arg[1])) > 0) && - ((interval = std::stoi(sep->arg[2])) > 0) + ((time = Strings::ToInt(sep->arg[1])) > 0) && + ((interval = Strings::ToInt(sep->arg[2])) > 0) ) { int time_minutes = (time / 60); quest_manager.WorldWideMessage( diff --git a/zone/gm_commands/worldwide.cpp b/zone/gm_commands/worldwide.cpp index 8962ef132..a61be457b 100755 --- a/zone/gm_commands/worldwide.cpp +++ b/zone/gm_commands/worldwide.cpp @@ -11,7 +11,7 @@ void command_worldwide(Client *c, const Seperator *sep) c->Message(Chat::White, "Usage: #worldwide remove [Spell ID] - Remove a spell worldwide"); return; } - + bool is_cast = !strcasecmp(sep->arg[1], "cast"); bool is_remove = !strcasecmp(sep->arg[1], "remove"); bool is_message = !strcasecmp(sep->arg[1], "message"); @@ -36,10 +36,10 @@ void command_worldwide(Client *c, const Seperator *sep) if (is_cast) { if (sep->IsNumber(2)) { uint8 update_type = WWSpellUpdateType_Cast; - auto spell_id = std::stoul(sep->arg[2]); + auto spell_id = Strings::ToUnsignedInt(sep->arg[2]); bool disable_message = false; if (sep->IsNumber(3)) { - disable_message = std::stoi(sep->arg[3]) ? true : false; + disable_message = Strings::ToInt(sep->arg[3]) ? true : false; } if (!IsValidSpell(spell_id)) { @@ -93,7 +93,7 @@ void command_worldwide(Client *c, const Seperator *sep) uint8 update_type = WWMoveUpdateType_MoveZone; auto zone_id = ( sep->IsNumber(2) ? - static_cast(std::stoul(sep->arg[2])) : + static_cast(Strings::ToUnsignedInt(sep->arg[2])) : static_cast(ZoneID(sep->arg[2])) ); auto zone_short_name = ZoneName(zone_id); @@ -127,7 +127,7 @@ void command_worldwide(Client *c, const Seperator *sep) if (sep->IsNumber(2)) { uint8 update_type = WWMoveUpdateType_MoveZoneInstance; const char *zone_short_name = ""; - auto instance_id = static_cast(std::stoul(sep->arg[2])); + auto instance_id = static_cast(Strings::ToUnsignedInt(sep->arg[2])); c->Message( Chat::White, @@ -144,7 +144,7 @@ void command_worldwide(Client *c, const Seperator *sep) } else if (is_remove) { if (sep->IsNumber(2)) { uint8 update_type = WWSpellUpdateType_Remove; - auto spell_id = std::stoul(sep->arg[2]); + auto spell_id = Strings::ToUnsignedInt(sep->arg[2]); if (!IsValidSpell(spell_id)) { c->Message( diff --git a/zone/gm_commands/wp.cpp b/zone/gm_commands/wp.cpp index 4f0b9330e..407a76d2e 100755 --- a/zone/gm_commands/wp.cpp +++ b/zone/gm_commands/wp.cpp @@ -3,10 +3,10 @@ void command_wp(Client *c, const Seperator *sep) { auto command_type = sep->arg[1]; - auto grid_id = atoi(sep->arg[2]); + auto grid_id = Strings::ToInt(sep->arg[2]); if (grid_id != 0) { - auto pause = atoi(sep->arg[3]); - auto waypoint = atoi(sep->arg[4]); + auto pause = Strings::ToInt(sep->arg[3]); + auto waypoint = Strings::ToInt(sep->arg[4]); auto zone_id = zone->GetZoneID(); if (strcasecmp("add", command_type) == 0) { if (waypoint == 0) { // Default to highest if it's left blank, or we enter 0 diff --git a/zone/gm_commands/wpadd.cpp b/zone/gm_commands/wpadd.cpp index df74c03e4..2ce56faac 100755 --- a/zone/gm_commands/wpadd.cpp +++ b/zone/gm_commands/wpadd.cpp @@ -15,8 +15,8 @@ void command_wpadd(Client *c, const Seperator *sep) } if (sep->arg[1][0]) { - if (atoi(sep->arg[1]) >= 0) { - pause = atoi(sep->arg[1]); + if (Strings::ToInt(sep->arg[1]) >= 0) { + pause = Strings::ToInt(sep->arg[1]); } else { c->Message(Chat::White, "Usage: #wpadd [pause] [-h]"); diff --git a/zone/gm_commands/xtargets.cpp b/zone/gm_commands/xtargets.cpp index c352b26b3..e153c477c 100755 --- a/zone/gm_commands/xtargets.cpp +++ b/zone/gm_commands/xtargets.cpp @@ -14,7 +14,7 @@ void command_xtargets(Client *c, const Seperator *sep) return; } - const auto new_max = static_cast(std::stoul(sep->arg[1])); + const auto new_max = static_cast(Strings::ToUnsignedInt(sep->arg[1])); if (!EQ::ValueWithin(new_max, 5, XTARGET_HARDCAP)) { c->Message( diff --git a/zone/gm_commands/zclip.cpp b/zone/gm_commands/zclip.cpp index 957464c72..09c7e0e64 100755 --- a/zone/gm_commands/zclip.cpp +++ b/zone/gm_commands/zclip.cpp @@ -11,10 +11,10 @@ void command_zclip(Client *c, const Seperator *sep) return; } - auto minimum_clip = sep->arg[1] ? std::stof(sep->arg[1]) : 0; - auto maximum_clip = sep->arg[2] ? std::stof(sep->arg[2]) : 0; - auto minimum_fog_clip = sep->arg[3] ? std::stof(sep->arg[3]) : 0; - auto maximum_fog_clip = sep->arg[4] ? std::stof(sep->arg[4]) : 0; + auto minimum_clip = sep->arg[1] ? Strings::ToFloat(sep->arg[1]) : 0; + auto maximum_clip = sep->arg[2] ? Strings::ToFloat(sep->arg[2]) : 0; + auto minimum_fog_clip = sep->arg[3] ? Strings::ToFloat(sep->arg[3]) : 0; + auto maximum_fog_clip = sep->arg[4] ? Strings::ToFloat(sep->arg[4]) : 0; auto permanent = sep->arg[5] ? atobool(sep->arg[5]) : false; if (minimum_clip <= 0 || maximum_clip <= 0) { diff --git a/zone/gm_commands/zcolor.cpp b/zone/gm_commands/zcolor.cpp index 77f7379ca..9e107d1f6 100755 --- a/zone/gm_commands/zcolor.cpp +++ b/zone/gm_commands/zcolor.cpp @@ -13,9 +13,9 @@ void command_zcolor(Client *c, const Seperator *sep) return; } - auto red = std::stoul(sep->arg[1]); - auto green = std::stoul(sep->arg[2]); - auto blue = std::stoul(sep->arg[3]); + auto red = Strings::ToUnsignedInt(sep->arg[1]); + auto green = Strings::ToUnsignedInt(sep->arg[2]); + auto blue = Strings::ToUnsignedInt(sep->arg[3]); auto permanent = sep->arg[4] ? atobool(sep->arg[4]) : false; if ( red < 0 || @@ -29,7 +29,7 @@ void command_zcolor(Client *c, const Seperator *sep) return; } - if (permanent) { + if (permanent) { auto query = fmt::format( "UPDATE zone SET fog_red = {}, fog_green = {}, fog_blue = {} " "WHERE zoneidnumber = {} AND version = {}", diff --git a/zone/gm_commands/zheader.cpp b/zone/gm_commands/zheader.cpp index f7449344c..5d91fd9a2 100755 --- a/zone/gm_commands/zheader.cpp +++ b/zone/gm_commands/zheader.cpp @@ -10,7 +10,7 @@ void command_zheader(Client *c, const Seperator *sep) auto zone_id = ( sep->IsNumber(2) ? - std::stoul(sep->arg[2]) : + Strings::ToUnsignedInt(sep->arg[2]) : ZoneID(sep->arg[2]) ); if (!zone_id) { @@ -28,7 +28,7 @@ void command_zheader(Client *c, const Seperator *sep) auto zone_long_name = ZoneLongName(zone_id); auto version = ( sep->IsNumber(3) ? - std::stoul(sep->arg[3]) : + Strings::ToUnsignedInt(sep->arg[3]) : 0 ); diff --git a/zone/gm_commands/zone.cpp b/zone/gm_commands/zone.cpp index 19deb4554..13601da4d 100644 --- a/zone/gm_commands/zone.cpp +++ b/zone/gm_commands/zone.cpp @@ -15,7 +15,7 @@ void command_zone(Client *c, const Seperator *sep) // if input is id if (Strings::IsNumber(zone_input)) { - zone_id = std::stoi(zone_input); + zone_id = Strings::ToInt(zone_input); // validate if (zone_id != 0 && !GetZone(zone_id)) { @@ -66,9 +66,9 @@ void command_zone(Client *c, const Seperator *sep) } // coordinates - auto x = sep->IsNumber(2) ? std::stof(sep->arg[2]) : 0.0f; - auto y = sep->IsNumber(3) ? std::stof(sep->arg[3]) : 0.0f; - auto z = sep->IsNumber(4) ? std::stof(sep->arg[4]) : 0.0f; + auto x = sep->IsNumber(2) ? Strings::ToFloat(sep->arg[2]) : 0.0f; + auto y = sep->IsNumber(3) ? Strings::ToFloat(sep->arg[3]) : 0.0f; + auto z = sep->IsNumber(4) ? Strings::ToFloat(sep->arg[4]) : 0.0f; auto zone_mode = sep->IsNumber(2) ? ZoneSolicited : ZoneToSafeCoords; c->MovePC( diff --git a/zone/gm_commands/zone_instance.cpp b/zone/gm_commands/zone_instance.cpp index e18d43990..5101468ba 100644 --- a/zone/gm_commands/zone_instance.cpp +++ b/zone/gm_commands/zone_instance.cpp @@ -8,7 +8,7 @@ void command_zone_instance(Client *c, const Seperator *sep) return; } - auto instance_id = std::stoul(sep->arg[1]); + auto instance_id = Strings::ToUnsignedInt(sep->arg[1]); if (!instance_id) { c->Message(Chat::White, "You must enter a valid Instance ID."); return; @@ -52,9 +52,9 @@ void command_zone_instance(Client *c, const Seperator *sep) return; } - auto x = sep->IsNumber(2) ? std::stof(sep->arg[2]) : 0.0f; - auto y = sep->IsNumber(3) ? std::stof(sep->arg[3]) : 0.0f; - auto z = sep->IsNumber(4) ? std::stof(sep->arg[4]) : 0.0f; + auto x = sep->IsNumber(2) ? Strings::ToFloat(sep->arg[2]) : 0.0f; + auto y = sep->IsNumber(3) ? Strings::ToFloat(sep->arg[3]) : 0.0f; + auto z = sep->IsNumber(4) ? Strings::ToFloat(sep->arg[4]) : 0.0f; auto zone_mode = sep->IsNumber(2) ? ZoneSolicited : ZoneToSafeCoords; c->MovePC( diff --git a/zone/gm_commands/zonebootup.cpp b/zone/gm_commands/zonebootup.cpp index 7c54e24fb..d071d9426 100755 --- a/zone/gm_commands/zonebootup.cpp +++ b/zone/gm_commands/zonebootup.cpp @@ -14,7 +14,7 @@ void command_zonebootup(Client *c, const Seperator *sep) else { auto pack = new ServerPacket(ServerOP_ZoneBootup, sizeof(ServerZoneStateChange_struct)); ServerZoneStateChange_struct *s = (ServerZoneStateChange_struct *) pack->pBuffer; - s->ZoneServerID = atoi(sep->arg[1]); + s->ZoneServerID = Strings::ToInt(sep->arg[1]); strcpy(s->adminname, c->GetName()); s->zoneid = ZoneID(sep->arg[2]); s->makestatic = (bool) (strcasecmp(sep->arg[3], "static") == 0); diff --git a/zone/gm_commands/zonelock.cpp b/zone/gm_commands/zonelock.cpp index b304f1a0f..1f0de1f0a 100755 --- a/zone/gm_commands/zonelock.cpp +++ b/zone/gm_commands/zonelock.cpp @@ -51,7 +51,7 @@ void command_zonelock(Client *c, const Seperator *sep) else if (!is_list && c->Admin() >= commandLockZones) { auto zone_id = ( sep->IsNumber(2) ? - static_cast(std::stoul(sep->arg[2])) : + static_cast(Strings::ToUnsignedInt(sep->arg[2])) : static_cast(ZoneID(sep->arg[2])) ); std::string zone_short_name = Strings::ToLower(ZoneName(zone_id, true)); diff --git a/zone/gm_commands/zoneshutdown.cpp b/zone/gm_commands/zoneshutdown.cpp index 14550b9db..31b09849b 100755 --- a/zone/gm_commands/zoneshutdown.cpp +++ b/zone/gm_commands/zoneshutdown.cpp @@ -18,7 +18,7 @@ void command_zoneshutdown(Client *c, const Seperator *sep) ServerZoneStateChange_struct *s = (ServerZoneStateChange_struct *) pack->pBuffer; strcpy(s->adminname, c->GetName()); if (sep->arg[1][0] >= '0' && sep->arg[1][0] <= '9') { - s->ZoneServerID = atoi(sep->arg[1]); + s->ZoneServerID = Strings::ToInt(sep->arg[1]); } else { s->zoneid = ZoneID(sep->arg[1]); diff --git a/zone/gm_commands/zopp.cpp b/zone/gm_commands/zopp.cpp index 08f10395b..ef6c7ce8f 100755 --- a/zone/gm_commands/zopp.cpp +++ b/zone/gm_commands/zopp.cpp @@ -25,9 +25,9 @@ void command_zopp(Client *c, const Seperator *sep) packettype = ItemPacketLimbo; } - int16 slotid = atoi(sep->arg[2]); - uint32 itemid = atoi(sep->arg[3]); - int16 charges = sep->argnum == 4 ? atoi(sep->arg[4]) : 1; // defaults to 1 charge if not specified + int16 slotid = Strings::ToInt(sep->arg[2]); + uint32 itemid = Strings::ToInt(sep->arg[3]); + int16 charges = sep->argnum == 4 ? Strings::ToInt(sep->arg[4]) : 1; // defaults to 1 charge if not specified const EQ::ItemData *FakeItem = database.GetItem(itemid); diff --git a/zone/gm_commands/zsafecoords.cpp b/zone/gm_commands/zsafecoords.cpp index 25be80391..4f3e5be4b 100755 --- a/zone/gm_commands/zsafecoords.cpp +++ b/zone/gm_commands/zsafecoords.cpp @@ -14,10 +14,10 @@ void command_zsafecoords(Client *c, const Seperator *sep) return; } - auto x = std::stof(sep->arg[1]); - auto y = std::stof(sep->arg[2]); - auto z = std::stof(sep->arg[3]); - auto heading = sep->arg[3] ? std::stof(sep->arg[3]) : c->GetHeading(); + auto x = Strings::ToFloat(sep->arg[1]); + auto y = Strings::ToFloat(sep->arg[2]); + auto z = Strings::ToFloat(sep->arg[3]); + auto heading = sep->arg[3] ? Strings::ToFloat(sep->arg[3]) : c->GetHeading(); auto permanent = sep->arg[4] ? atobool(sep->arg[4]) : false; if (permanent) { auto query = fmt::format( @@ -31,7 +31,7 @@ void command_zsafecoords(Client *c, const Seperator *sep) ); database.QueryDatabase(query); } - + zone->newzone_data.safe_x = x; zone->newzone_data.safe_y = y; zone->newzone_data.safe_z = z; diff --git a/zone/gm_commands/zsky.cpp b/zone/gm_commands/zsky.cpp index ed3ef2dc8..5802b7011 100755 --- a/zone/gm_commands/zsky.cpp +++ b/zone/gm_commands/zsky.cpp @@ -8,7 +8,7 @@ void command_zsky(Client *c, const Seperator *sep) return; } - auto sky_type = std::stoul(sep->arg[1]); + auto sky_type = Strings::ToUnsignedInt(sep->arg[1]); auto permanent = sep->arg[2] ? atobool(sep->arg[2]) : false; if (sky_type < 0 || sky_type > 255) { c->Message(Chat::White, "Sky Type cannot be less than 0 or greater than 255!"); diff --git a/zone/gm_commands/zunderworld.cpp b/zone/gm_commands/zunderworld.cpp index be55236ef..8f7c8832d 100755 --- a/zone/gm_commands/zunderworld.cpp +++ b/zone/gm_commands/zunderworld.cpp @@ -8,7 +8,7 @@ void command_zunderworld(Client *c, const Seperator *sep) return; } - auto z = std::stof(sep->arg[1]); + auto z = Strings::ToFloat(sep->arg[1]); auto permanent = sep->arg[2] ? atobool(sep->arg[2]) : false; if (permanent) { auto query = fmt::format( diff --git a/zone/groups.cpp b/zone/groups.cpp index 910d5b21c..7bb51bfb2 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -9,7 +9,7 @@ but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software @@ -20,12 +20,13 @@ #include "../common/eqemu_logsys.h" #include "expedition.h" #include "masterentity.h" -#include "npc_ai.h" #include "../common/packet_functions.h" #include "../common/packet_dump.h" #include "../common/strings.h" #include "worldserver.h" #include "string_ids.h" +#include "../common/events/player_event_logs.h" +#include "../common/repositories/group_id_repository.h" extern EntityList entity_list; extern WorldServer worldserver; @@ -177,6 +178,18 @@ void Group::SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinu true ); + if (player_event_logs.IsEventEnabled(PlayerEvent::SPLIT_MONEY)) { + auto e = PlayerEvent::SplitMoneyEvent{ + .copper = copper_split, + .silver = silver_split, + .gold = gold_split, + .platinum = platinum_split, + .player_money_balance = members[i]->CastToClient()->GetCarriedMoney(), + }; + + RecordPlayerEventLogWithClient(members[i]->CastToClient(), PlayerEvent::SPLIT_MONEY, e); + } + members[i]->CastToClient()->MessageString( Chat::MoneySplit, YOU_RECEIVE_AS_SPLIT, @@ -234,7 +247,7 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte uint32 i = 0; for (i = 0; i < MAX_GROUP_MEMBERS; ++i) { - if(!strcasecmp(membername[i], NewMemberName)) + if (!strcasecmp(membername[i], NewMemberName)) { return false; } @@ -483,7 +496,7 @@ void Group::SendEndurancePacketFrom(Mob* member) //updates a group member's client pointer when they zone in //if the group was in the zone already -bool Group::UpdatePlayer(Mob* update){ +bool Group::UpdatePlayer(Mob* update) { if (!update) return false; @@ -531,7 +544,6 @@ bool Group::UpdatePlayer(Mob* update){ return updateSuccess; } - void Group::MemberZoned(Mob* removemob) { uint32 i; @@ -541,11 +553,10 @@ void Group::MemberZoned(Mob* removemob) { if(removemob == GetLeader()) SetLeader(nullptr); - for (i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (members[i] == removemob) { - members[i] = nullptr; - //should NOT clear the name, it is used for world communication. - break; + //should NOT clear the name, it is used for world communication. + for (auto & m : members) { + if (m && (m == removemob || m->IsBot() && m->CastToBot()->GetBotOwner() == removemob)) { + m = nullptr; } } @@ -911,6 +922,7 @@ void Group::DisbandGroup(bool joinraid) { { if (members[i] == nullptr) { + membername[i][0] = '\0'; continue; } @@ -1126,32 +1138,34 @@ void Group::TeleportGroup(Mob* sender, uint32 zoneID, uint16 instance_id, float } bool Group::LearnMembers() { - std::string query = StringFormat("SELECT name FROM group_id WHERE groupid = %lu", (unsigned long)GetID()); - auto results = database.QueryDatabase(query); - if (!results.Success()) - return false; - if (results.RowCount() == 0) { + auto rows = GroupIdRepository::GetWhere( + database, + fmt::format( + "groupid = {}", + GetID() + ) + ); + + if (rows.empty()) { LogError( - "Error getting group members for group [{}]: [{}]", - (unsigned long) GetID(), - results.ErrorMessage().c_str() + "Error getting group members for group [{}]", + GetID() ); - return false; } int memberIndex = 0; - for(auto row = results.begin(); row != results.end(); ++row) { - if(!row[0]) + for (const auto& member : rows) { + if (member.name.empty()) { continue; - + } members[memberIndex] = nullptr; - strn0cpy(membername[memberIndex], row[0], 64); - + strn0cpy(membername[memberIndex], member.name.c_str(), 64); memberIndex++; } + VerifyGroup(); return true; } @@ -1162,36 +1176,23 @@ void Group::VerifyGroup() { Only called every once in a while (on member re-join for now). */ - uint32 i; - for (i = 0; i < MAX_GROUP_MEMBERS; i++) { + for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { if (membername[i][0] == '\0') { -#if EQDEBUG >= 7 - LogDebug("Group [{}]: Verify [{}]: Empty.\n", (unsigned long)GetID(), i); -#endif members[i] = nullptr; continue; } Mob *them = entity_list.GetMob(membername[i]); if(them == nullptr && members[i] != nullptr) { //they aren't in zone -#if EQDEBUG >= 6 - LogDebug("Member of group [{}] named [{}] has disappeared!!", (unsigned long)GetID(), membername[i]); -#endif membername[i][0] = '\0'; members[i] = nullptr; continue; } if(them != nullptr && members[i] != them) { //our pointer is out of date... not so good. -#if EQDEBUG >= 5 - LogDebug("Member of group [{}] named [{}] had an out of date pointer!!", (unsigned long)GetID(), membername[i]); -#endif members[i] = them; continue; } -#if EQDEBUG >= 8 - LogDebug("Member of group [{}] named [{}] is valid", (unsigned long)GetID(), membername[i]); -#endif } } @@ -2320,7 +2321,6 @@ void Group::UpdateXTargetMarkedNPC(uint32 Number, Mob *m) members[i]->CastToClient()->UpdateXTargetType((Number == 1) ? GroupMarkTarget1 : ((Number == 2) ? GroupMarkTarget2 : GroupMarkTarget3), m); } } - } void Group::SetDirtyAutoHaters() @@ -2485,4 +2485,4 @@ bool Group::IsLeader(const char* name) { } return false; -} +} \ No newline at end of file diff --git a/zone/guild_mgr.cpp b/zone/guild_mgr.cpp index e778647e3..9756d1a0b 100644 --- a/zone/guild_mgr.cpp +++ b/zone/guild_mgr.cpp @@ -338,14 +338,14 @@ void ZoneGuildManager::DescribeGuild(Client *c, uint32 guild_id) const { popup_text += ""; for (uint8 guild_rank = 0; guild_rank <= GUILD_MAX_RANK; guild_rank++) { - auto can_hear_guild_chat = info->ranks[guild_rank].permissions[GUILD_HEAR] ? "âś”" : "❌"; - auto can_speak_guild_chat = info->ranks[guild_rank].permissions[GUILD_SPEAK] ? "âś”" : "❌"; - auto can_invite = info->ranks[guild_rank].permissions[GUILD_INVITE] ? "âś”" : "❌"; - auto can_remove = info->ranks[guild_rank].permissions[GUILD_REMOVE] ? "âś”" : "❌"; - auto can_promote = info->ranks[guild_rank].permissions[GUILD_PROMOTE] ? "âś”" : "❌"; - auto can_demote = info->ranks[guild_rank].permissions[GUILD_DEMOTE] ? "âś”" : "❌"; - auto can_set_motd = info->ranks[guild_rank].permissions[GUILD_MOTD] ? "âś”" : "❌"; - auto can_war_peace = info->ranks[guild_rank].permissions[GUILD_WARPEACE] ? "âś”" : "❌"; + auto can_hear_guild_chat = info->ranks[guild_rank].permissions[GUILD_HEAR] ? "Y" : "N"; + auto can_speak_guild_chat = info->ranks[guild_rank].permissions[GUILD_SPEAK] ? "Y" : "N"; + auto can_invite = info->ranks[guild_rank].permissions[GUILD_INVITE] ? "Y" : "N"; + auto can_remove = info->ranks[guild_rank].permissions[GUILD_REMOVE] ? "Y" : "N"; + auto can_promote = info->ranks[guild_rank].permissions[GUILD_PROMOTE] ? "Y" : "N"; + auto can_demote = info->ranks[guild_rank].permissions[GUILD_DEMOTE] ? "Y" : "N"; + auto can_set_motd = info->ranks[guild_rank].permissions[GUILD_MOTD] ? "Y" : "N"; + auto can_war_peace = info->ranks[guild_rank].permissions[GUILD_WARPEACE] ? "Y" : "N"; popup_text += fmt::format( "" "{} ({})" @@ -652,79 +652,11 @@ void ZoneGuildManager::RequestOnlineGuildMembers(uint32 FromID, uint32 GuildID) safe_delete(pack); } -void ZoneGuildManager::ProcessApproval() -{ - LinkedListIterator iterator(list); - - iterator.Reset(); - while(iterator.MoreElements()) - { - if(!iterator.GetData()->ProcessApproval()) - iterator.RemoveCurrent(); - iterator.Advance(); - } -} - -void ZoneGuildManager::AddGuildApproval(const char* guildname,Client* owner) -{ - auto tmp = new GuildApproval(guildname, owner, GetFreeID()); - list.Insert(tmp); -} - -void ZoneGuildManager::AddMemberApproval(uint32 refid,Client* name) -{ - GuildApproval* tmp = FindGuildByIDApproval(refid); - if(tmp != 0) - { - if(!tmp->AddMemberApproval(name)) - name->Message(Chat::White,"Unable to add to list."); - else - { - name->Message(Chat::White,"Added to list."); - } - } - else - name->Message(Chat::White,"Unable to find guild reference id."); -} - ZoneGuildManager::~ZoneGuildManager() { ClearGuilds(); } -void ZoneGuildManager::ClearGuildsApproval() -{ - list.Clear(); -} - -GuildApproval* ZoneGuildManager::FindGuildByIDApproval(uint32 refid) -{ - LinkedListIterator iterator(list); - - iterator.Reset(); - while(iterator.MoreElements()) - { - if(iterator.GetData()->GetID() == refid) - return iterator.GetData(); - iterator.Advance(); - } - return 0; -} - -GuildApproval* ZoneGuildManager::FindGuildByOwnerApproval(Client* owner) -{ - LinkedListIterator iterator(list); - - iterator.Reset(); - while(iterator.MoreElements()) - { - if(iterator.GetData()->GetOwner() == owner) - return iterator.GetData(); - iterator.Advance(); - } - return 0; -} - GuildBankManager::~GuildBankManager() { auto Iterator = Banks.begin(); @@ -760,17 +692,17 @@ bool GuildBankManager::Load(uint32 guildID) char donator[64], whoFor[64]; for (auto row = results.begin(); row != results.end(); ++row) { - int area = atoi(row[0]); - int slot = atoi(row[1]); - int itemID = atoi(row[2]); - int qty = atoi(row[3]); + int area = Strings::ToInt(row[0]); + int slot = Strings::ToInt(row[1]); + int itemID = Strings::ToInt(row[2]); + int qty = Strings::ToInt(row[3]); if (row[4]) strn0cpy(donator, row[4], sizeof(donator)); else donator[0] = '\0'; - int permissions = atoi(row[5]); + int permissions = Strings::ToInt(row[5]); if (row[6]) strn0cpy(whoFor, row[6], sizeof(whoFor)); @@ -1524,154 +1456,3 @@ bool GuildBankManager::AllowedToWithdraw(uint32 GuildID, uint16 Area, uint16 Slo return false; } - -/*================== GUILD APPROVAL ========================*/ - -bool GuildApproval::ProcessApproval() -{ - if(owner && owner->GuildID() != 0) - { - owner->Message(Chat::NPCQuestSay,"You are already in a guild! Guild request deleted."); - return false; - } - if(deletion_timer->Check() || !owner) - { - if(owner) - owner->Message(Chat::White,"You took too long! Your guild request has been deleted."); - return false; - } - - return true; -} - -GuildApproval::GuildApproval(const char* guildname, Client* owner,uint32 id) -{ - std::string founders; - database.GetVariable("GuildCreation", founders); - uint8 tmp = atoi(founders.c_str()); - deletion_timer = new Timer(1800000); - strcpy(guild,guildname); - owner = owner; - refid = id; - if(owner) - owner->Message(Chat::White,"You can now start getting your guild approved, tell your %i members to #guildapprove %i, you have 30 minutes to create your guild.",tmp,GetID()); - for(int i=0;iMessage(Chat::White,"%i: %s",i,members[i]->GetName()); - } -} - -void GuildApproval::GuildApproved() -{ - char petitext[PBUFFER] = "A new guild was founded! Guildname: "; - char gmembers[MBUFFER] = " "; - - if(!owner) - return; - std::string founders; - database.GetVariable("GuildCreation", founders); - uint8 tmp = atoi(founders.c_str()); - uint32 tmpeq = guild_mgr.CreateGuild(guild, owner->CharacterID()); - guild_mgr.SetGuild(owner->CharacterID(),tmpeq,2); - owner->SendAppearancePacket(AT_GuildID,true,false); - for(int i=0;iMessage(Chat::White, "%s",members[i]->GetName()); - owner->Message(Chat::White, "%i",members[i]->CharacterID()); - guild_mgr.SetGuild(members[i]->CharacterID(),tmpeq,0); - size_t len = MBUFFER - strlen(gmembers)+1; - strncat(gmembers," ",len); - strncat(gmembers,members[i]->GetName(),len); - } - } - size_t len = PBUFFER - strlen(petitext)+1; - strncat(petitext,guild,len); - strncat(petitext," Leader: ",len); - strncat(petitext,owner->CastToClient()->GetName(),len); - strncat(petitext," Members:",len); - strncat(petitext,gmembers,len); - auto pet = new Petition(owner->CastToClient()->CharacterID()); - pet->SetAName(owner->CastToClient()->AccountName()); - pet->SetClass(owner->CastToClient()->GetClass()); - pet->SetLevel(owner->CastToClient()->GetLevel()); - pet->SetCName(owner->CastToClient()->GetName()); - pet->SetRace(owner->CastToClient()->GetRace()); - pet->SetLastGM(""); - pet->SetCName(owner->CastToClient()->GetName()); //aza77 is this really 2 times needed ?? - pet->SetPetitionText(petitext); - pet->SetZone(zone->GetZoneID()); - pet->SetUrgency(0); - petition_list.AddPetition(pet); - database.InsertPetitionToDB(pet); - petition_list.UpdateGMQueue(); - petition_list.UpdateZoneListQueue(); - worldserver.SendEmoteMessage( - 0, - 0, - AccountStatus::QuestTroupe, - Chat::Yellow, - fmt::format( - "{} has made a petition. ID: {}", - owner->CastToClient()->GetName(), - pet->GetID() - ).c_str() - ); - auto pack = new ServerPacket; - pack->opcode = ServerOP_RefreshGuild; - pack->size = tmp; - pack->pBuffer = new uchar[pack->size]; - memcpy(pack->pBuffer, &tmpeq, 4); - worldserver.SendPacket(pack); - safe_delete(pack); - owner->Message(Chat::White, "Your guild was created."); - owner = 0; -} - diff --git a/zone/guild_mgr.h b/zone/guild_mgr.h index 2e6a12de1..ae21c55c3 100644 --- a/zone/guild_mgr.h +++ b/zone/guild_mgr.h @@ -47,36 +47,10 @@ enum { GuildBankDepositArea = 0, GuildBankMainArea = 1 }; enum { GuildBankBankerOnly = 0, GuildBankSingleMember = 1, GuildBankPublicIfUsable = 2, GuildBankPublic = 3 }; -class GuildApproval -{ -public: - GuildApproval(const char* guildname,Client* owner,uint32 id); - ~GuildApproval(); - bool ProcessApproval(); - bool AddMemberApproval(Client* addition); - uint32 GetID() { return refid; } - Client* GetOwner() { return owner; } - void GuildApproved(); - void ApprovedMembers(Client* requestee); -private: - Timer* deletion_timer; - char guild[16]; - Client* owner; - Client* members[6]; - uint32 refid; -}; - class ZoneGuildManager : public BaseGuildManager { public: ~ZoneGuildManager(void); - void AddGuildApproval(const char* guildname, Client* owner); - void AddMemberApproval(uint32 refid,Client* name); - void ClearGuildsApproval(); - GuildApproval* FindGuildByIDApproval(uint32 refid); - GuildApproval* FindGuildByOwnerApproval(Client* owner); - void ProcessApproval(); - uint32 GetFreeID() { return id+1; } //called by worldserver when it receives a message from world. void ProcessWorldPacket(ServerPacket *pack); @@ -103,9 +77,7 @@ protected: std::map > m_inviteQueue; //map from char ID to guild,rank private: - LinkedList list; uint32 id; - }; diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index fba3c1e0d..e5452921d 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -66,7 +66,9 @@ void HateList::WipeHateList() Mob* m = (*iterator)->entity_on_hatelist; if (m) { - parse->EventNPC(EVENT_HATE_LIST, hate_owner->CastToNPC(), m, "0", 0); + if (parse->HasQuestSub(hate_owner->GetNPCTypeID(), EVENT_HATE_LIST)) { + parse->EventNPC(EVENT_HATE_LIST, hate_owner->CastToNPC(), m, "0", 0); + } if (m->IsClient()) { m->CastToClient()->DecrementAggroCount(); @@ -183,18 +185,20 @@ Mob* HateList::GetClosestEntOnHateList(Mob *hater, bool skip_mezzed) { void HateList::AddEntToHateList(Mob *in_entity, int64 in_hate, int64 in_damage, bool in_is_entity_frenzied, bool iAddIfNotExist) { - if (!in_entity) + if (!in_entity) { return; + } - if (in_entity->IsCorpse()) + if (in_entity->IsCorpse()) { return; + } - if (in_entity->IsClient() && in_entity->CastToClient()->IsDead()) + if (in_entity->IsClient() && in_entity->CastToClient()->IsDead()) { return; + } struct_HateList *entity = Find(in_entity); - if (entity) - { + if (entity) { entity->hatelist_damage += (in_damage >= 0) ? in_damage : 0; entity->stored_hate_amount += in_hate; entity->is_entity_frenzy = in_is_entity_frenzied; @@ -209,8 +213,7 @@ void HateList::AddEntToHateList(Mob *in_entity, int64 in_hate, int64 in_damage, entity->stored_hate_amount, entity->hatelist_damage ); - } - else if (iAddIfNotExist) { + } else if (iAddIfNotExist) { entity = new struct_HateList; entity->entity_on_hatelist = in_entity; entity->hatelist_damage = (in_damage >= 0) ? in_damage : 0; @@ -219,7 +222,10 @@ void HateList::AddEntToHateList(Mob *in_entity, int64 in_hate, int64 in_damage, entity->oor_count = 0; entity->last_modified = Timer::GetCurrentTime(); list.push_back(entity); - parse->EventNPC(EVENT_HATE_LIST, hate_owner->CastToNPC(), in_entity, "1", 0); + + if (parse->HasQuestSub(hate_owner->GetNPCTypeID(), EVENT_HATE_LIST)) { + parse->EventNPC(EVENT_HATE_LIST, hate_owner->CastToNPC(), in_entity, "1", 0); + } if (in_entity->IsClient()) { in_entity->CastToClient()->IncrementAggroCount(hate_owner->CastToNPC()->IsRaidTarget()); @@ -229,30 +235,32 @@ void HateList::AddEntToHateList(Mob *in_entity, int64 in_hate, int64 in_damage, bool HateList::RemoveEntFromHateList(Mob *in_entity) { - if (!in_entity) + if (!in_entity) { return false; + } bool is_found = false; auto iterator = list.begin(); - while (iterator != list.end()) - { - if ((*iterator)->entity_on_hatelist == in_entity) - { + while (iterator != list.end()) { + if ((*iterator)->entity_on_hatelist == in_entity) { is_found = true; - if (in_entity && in_entity->IsClient()) + if (in_entity && in_entity->IsClient()) { in_entity->CastToClient()->DecrementAggroCount(); + } delete (*iterator); iterator = list.erase(iterator); - if (in_entity) - parse->EventNPC(EVENT_HATE_LIST, hate_owner->CastToNPC(), in_entity, "0", 0); - - } - else + if (in_entity) { + if (parse->HasQuestSub(hate_owner->GetNPCTypeID(), EVENT_HATE_LIST)) { + parse->EventNPC(EVENT_HATE_LIST, hate_owner->CastToNPC(), in_entity, "0", 0); + } + } + } else { ++iterator; + } } return is_found; } @@ -811,19 +819,23 @@ void HateList::RemoveStaleEntries(int time_ms, float dist) if (m) { bool remove = false; - if (cur_time - (*it)->last_modified > time_ms) + if (cur_time - (*it)->last_modified > time_ms) { remove = true; + } if (!remove && DistanceSquaredNoZ(hate_owner->GetPosition(), m->GetPosition()) > dist2) { (*it)->oor_count++; - if ((*it)->oor_count == 2) + if ((*it)->oor_count == 2) { remove = true; + } } else if ((*it)->oor_count != 0) { (*it)->oor_count = 0; } if (remove) { - parse->EventNPC(EVENT_HATE_LIST, hate_owner->CastToNPC(), m, "0", 0); + if (parse->HasQuestSub(hate_owner->GetNPCTypeID(), EVENT_HATE_LIST)) { + parse->EventNPC(EVENT_HATE_LIST, hate_owner->CastToNPC(), m, "0", 0); + } if (m->IsClient()) { m->CastToClient()->DecrementAggroCount(); diff --git a/zone/horse.cpp b/zone/horse.cpp index 43c04202f..36dd4aa8e 100644 --- a/zone/horse.cpp +++ b/zone/horse.cpp @@ -92,16 +92,16 @@ const NPCType *Horse::BuildHorseType(uint16 spell_id) { strcpy(npc_type->special_abilities, "19,1^20,1^24,1"); npc_type->current_hp = 1; npc_type->max_hp = 1; - npc_type->race = atoi(row[0]); - npc_type->gender = atoi(row[1]); // Drogmor's are female horses. Yuck. + npc_type->race = Strings::ToInt(row[0]); + npc_type->gender = Strings::ToInt(row[1]); // Drogmor's are female horses. Yuck. npc_type->class_ = 1; npc_type->deity = 1; npc_type->level = 1; npc_type->npc_id = 0; npc_type->loottable_id = 0; - npc_type->texture = atoi(row[2]); // mount color - npc_type->helmtexture = atoi(row[2]); // mount color - npc_type->runspeed = atof(row[3]); + npc_type->texture = Strings::ToInt(row[2]); // mount color + npc_type->helmtexture = Strings::ToInt(row[2]); // mount color + npc_type->runspeed = Strings::ToFloat(row[3]); npc_type->light = 0; npc_type->STR = 75; diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 397bc3863..6f8854b3f 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -24,8 +24,10 @@ #include "worldserver.h" #include "zonedb.h" #include "../common/zone_store.h" +#include "../common/events/player_event_logs.h" #include "bot.h" +#include "../common/events/player_event_logs.h" extern WorldServer worldserver; @@ -714,6 +716,15 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, // in any other situation just use charges as passed EQ::ItemInstance* inst = database.CreateItem(item, charges); + auto timestamps = database.GetItemRecastTimestamps(CharacterID()); + const auto* d = inst->GetItem(); + if (d->RecastDelay) { + if (d->RecastType != RECAST_TYPE_UNLINKED_ITEM) { + inst->SetRecastTimestamp(timestamps.count(d->RecastType) ? timestamps.at(d->RecastType) : 0); + } else { + inst->SetRecastTimestamp(timestamps.count(d->ID) ? timestamps.at(d->ID) : 0); + } + } if(inst == nullptr) { Message(Chat::Red, "An unknown server error has occurred and your item was not created."); @@ -783,6 +794,23 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, } } + if (player_event_logs.IsEventEnabled(PlayerEvent::ITEM_CREATION)) { + auto e = PlayerEvent::ItemCreationEvent{}; + e.item_id = item->ID; + e.item_name = item->Name; + e.to_slot = to_slot; + e.charges = charges; + e.aug1 = aug1; + e.aug2 = aug2; + e.aug3 = aug3; + e.aug4 = aug4; + e.aug5 = aug5; + e.aug6 = aug6; + e.attuned = attuned; + + RecordPlayerEventLog(PlayerEvent::ITEM_CREATION, e); + } + // put item into inventory if (to_slot == EQ::invslot::slotCursor) { PushItemOnCursor(*inst); @@ -794,17 +822,12 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, safe_delete(inst); // discover item and any augments - if((RuleB(Character, EnableDiscoveredItems)) && !GetGM()) { - if(!IsDiscovered(item_id)) { - DiscoverItem(item_id); - } - /* - // Augments should have been discovered prior to being placed on an item. - for (int iter = AUG_BEGIN; iter < EQ::constants::ITEM_COMMON_SIZE; ++iter) { - if(augments[iter] && !IsDiscovered(augments[iter])) - DiscoverItem(augments[iter]); - } - */ + if ( + RuleB(Character, EnableDiscoveredItems) && + !GetGM() && + !IsDiscovered(item_id) + ) { + DiscoverItem(item_id); } return true; @@ -813,11 +836,14 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, // Drop item from inventory to ground (generally only dropped from SLOT_CURSOR) void Client::DropItem(int16 slot_id, bool recurse) { - LogInventory("[{}] (char_id: [{}]) Attempting to drop item from slot [{}] on the ground", - GetCleanName(), CharacterID(), slot_id); + LogInventory( + "[{}] (char_id: [{}]) Attempting to drop item from slot [{}] on the ground", + GetCleanName(), + CharacterID(), + slot_id + ); - if(GetInv().CheckNoDrop(slot_id, recurse) && !CanTradeFVNoDropItem()) - { + if (GetInv().CheckNoDrop(slot_id, recurse) && !CanTradeFVNoDropItem()) { auto invalid_drop = m_inv.GetItem(slot_id); if (!invalid_drop) { LogInventory("Error in InventoryProfile::CheckNoDrop() - returned 'true' for empty slot"); @@ -839,50 +865,102 @@ void Client::DropItem(int16 slot_id, bool recurse) } } } - invalid_drop = nullptr; - database.SetHackerFlag(AccountName(), GetCleanName(), "Tried to drop an item on the ground that was nodrop!"); + std::string message = fmt::format( + "Tried to drop an item on the ground that was no-drop! item_name [{}] item_id ({})", + invalid_drop->GetItem()->Name, + invalid_drop->GetItem()->ID + ); + + invalid_drop = nullptr; + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); GetInv().DeleteItem(slot_id); return; } // Take control of item in client inventory - EQ::ItemInstance *inst = m_inv.PopItem(slot_id); - if(inst) { + auto* inst = m_inv.PopItem(slot_id); + if (inst) { if (LogSys.log_settings[Logs::Inventory].is_category_enabled) { LogInventory("DropItem() Processing - full item parse:"); - LogInventory("depth: 0, Item: [{}] (id: [{}]), IsDroppable: [{}]", - (inst->GetItem() ? inst->GetItem()->Name : "null data"), inst->GetID(), (inst->IsDroppable(false) ? "true" : "false")); + LogInventory( + "depth: 0, Item: [{}] (id: [{}]), IsDroppable: [{}]", + (inst->GetItem() ? inst->GetItem()->Name : "null data"), + inst->GetID(), + (inst->IsDroppable(false) ? "true" : "false") + ); - if (!inst->IsDroppable(false)) + if (!inst->IsDroppable(false)) { LogError("Non-droppable item being processed for drop by [{}]", GetCleanName()); + } for (auto iter1 : *inst->GetContents()) { // depth 1 - LogInventory("-depth: 1, Item: [{}] (id: [{}]), IsDroppable: [{}]", - (iter1.second->GetItem() ? iter1.second->GetItem()->Name : "null data"), iter1.second->GetID(), (iter1.second->IsDroppable(false) ? "true" : "false")); + LogInventory( + "-depth: 1, Item: [{}] (id: [{}]), IsDroppable: [{}]", + (iter1.second->GetItem() ? iter1.second->GetItem()->Name : "null data"), + iter1.second->GetID(), + (iter1.second->IsDroppable(false) ? "true" : "false") + ); - if (!iter1.second->IsDroppable(false)) + if (!iter1.second->IsDroppable(false)) { LogError("Non-droppable item being processed for drop by [{}]", GetCleanName()); + } for (auto iter2 : *iter1.second->GetContents()) { // depth 2 - LogInventory("--depth: 2, Item: [{}] (id: [{}]), IsDroppable: [{}]", - (iter2.second->GetItem() ? iter2.second->GetItem()->Name : "null data"), iter2.second->GetID(), (iter2.second->IsDroppable(false) ? "true" : "false")); + LogInventory( + "--depth: 2, Item: [{}] (id: [{}]), IsDroppable: [{}]", + (iter2.second->GetItem() ? iter2.second->GetItem()->Name : "null data"), + iter2.second->GetID(), + (iter2.second->IsDroppable(false) ? "true" : "false") + ); - if (!iter2.second->IsDroppable(false)) + if (!iter2.second->IsDroppable(false)) { LogError("Non-droppable item being processed for drop by [{}]", GetCleanName()); + } } } } - int i = parse->EventItem(EVENT_DROP_ITEM, this, inst, nullptr, "", slot_id); - if(i != 0) { - LogInventory("Item drop handled by [EVENT_DROP_ITEM]"); - safe_delete(inst); + + int i = 0; + + if (player_event_logs.IsEventEnabled(PlayerEvent::DROPPED_ITEM)) { + auto e = PlayerEvent::DroppedItemEvent{ + .item_id = inst->GetID(), + .item_name = inst->GetItem()->Name, + .slot_id = slot_id, + .charges = (uint32) inst->GetCharges() + }; + RecordPlayerEventLog(PlayerEvent::DROPPED_ITEM, e); + } + + if (parse->ItemHasQuestSub(inst, EVENT_DROP_ITEM)) { + parse->EventItem(EVENT_DROP_ITEM, this, inst, nullptr, "", slot_id); + if (i != 0) { + LogInventory("Item drop handled by [EVENT_DROP_ITEM]"); + safe_delete(inst); + } + } + + if (parse->PlayerHasQuestSub(EVENT_DROP_ITEM_CLIENT)) { + std::vector args = { inst }; + + i = parse->EventPlayer(EVENT_DROP_ITEM_CLIENT, this, "", slot_id, &args); + if (i != 0) { + LogInventory("Item drop handled by [EVENT_DROP_ITEM_CLIENT]"); + safe_delete(inst); + } } } else { // Item doesn't exist in inventory! LogInventory("DropItem() - No item found in slot [{}]", slot_id); - Message(Chat::Red, "Error: Item not found in slot %i", slot_id); + Message( + Chat::Red, + fmt::format( + "Error: Item not found in slot {}.", + slot_id + ).c_str() + ); return; } @@ -895,15 +973,16 @@ void Client::DropItem(int16 slot_id, bool recurse) database.SaveInventory(CharacterID(), nullptr, slot_id); } - if(!inst) + if (!inst) { return; + } // Package as zone object auto object = new Object(this, inst); entity_list.AddObject(object, true); object->StartDecay(); - LogInventory("Item drop handled ut assolet"); + LogInventory("[{}] dropped [{}] from slot [{}]", GetCleanName(), inst->GetItem()->Name, slot_id); DropItemQS(inst, false); safe_delete(inst); @@ -1084,7 +1163,16 @@ void Client::SendCursorBuffer() LogInventory("([{}]) Duplicate lore items are not allowed - destroying item [{}](id:[{}]) on cursor", GetName(), test_item->Name, test_item->ID); MessageString(Chat::Loot, 290); - parse->EventItem(EVENT_DESTROY_ITEM, this, test_inst, nullptr, "", 0); + + if (parse->ItemHasQuestSub(test_inst, EVENT_DESTROY_ITEM)) { + parse->EventItem(EVENT_DESTROY_ITEM, this, test_inst, nullptr, "", 0); + } + + if (parse->PlayerHasQuestSub(EVENT_DESTROY_ITEM_CLIENT)) { + std::vector args = { test_inst }; + parse->EventPlayer(EVENT_DESTROY_ITEM_CLIENT, this, "", 0, &args); + } + DeleteItemInInventory(EQ::invslot::slotCursor); SendCursorBuffer(); } @@ -1423,7 +1511,11 @@ bool Client::AutoPutLootInInventory(EQ::ItemInstance& inst, bool try_worn, bool if (worn_slot_material != EQ::textures::materialInvalid) { SendWearChange(worn_slot_material); } - parse->EventItem(EVENT_EQUIP_ITEM, this, &inst, nullptr, "", i); + + if (parse->ItemHasQuestSub(&inst, EVENT_EQUIP_ITEM)) { + parse->EventItem(EVENT_EQUIP_ITEM, this, &inst, nullptr, "", i); + } + return true; } } @@ -1811,8 +1903,29 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { LogInventory("([{}]) Duplicate lore items are not allowed - destroying item [{}](id:[{}]) on cursor", GetName(), test_item->Name, test_item->ID); MessageString(Chat::Loot, 290); - parse->EventItem(EVENT_DESTROY_ITEM, this, test_inst, nullptr, "", 0); + + if (parse->ItemHasQuestSub(test_inst, EVENT_DESTROY_ITEM)) { + parse->EventItem(EVENT_DESTROY_ITEM, this, test_inst, nullptr, "", 0); + } + + if (parse->PlayerHasQuestSub(EVENT_DESTROY_ITEM_CLIENT)) { + std::vector args = { test_inst }; + parse->EventPlayer(EVENT_DESTROY_ITEM_CLIENT, this, "", 0, &args); + } + DeleteItemInInventory(EQ::invslot::slotCursor, 0, true); + + if (player_event_logs.IsEventEnabled(PlayerEvent::ITEM_DESTROY)) { + auto e = PlayerEvent::DestroyItemEvent{ + .item_id = test_inst->GetItem()->ID, + .item_name = test_inst->GetItem()->Name, + .charges = test_inst->GetCharges(), + .reason = "Duplicate lore item", + }; + + RecordPlayerEventLog(PlayerEvent::ITEM_DESTROY, e); + } + } } return true; @@ -1824,8 +1937,27 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit EQ::ItemInstance *inst = m_inv.GetItem(EQ::invslot::slotCursor); - if(inst) { - parse->EventItem(EVENT_DESTROY_ITEM, this, inst, nullptr, "", 0); + + if (inst) { + if (player_event_logs.IsEventEnabled(PlayerEvent::ITEM_DESTROY)) { + auto e = PlayerEvent::DestroyItemEvent{ + .item_id = inst->GetItem()->ID, + .item_name = inst->GetItem()->Name, + .charges = inst->GetCharges(), + .reason = "Client destroy cursor", + }; + + RecordPlayerEventLog(PlayerEvent::ITEM_DESTROY, e); + } + + if (parse->ItemHasQuestSub(inst, EVENT_DESTROY_ITEM)) { + parse->EventItem(EVENT_DESTROY_ITEM, this, inst, nullptr, "", 0); + } + + if (parse->PlayerHasQuestSub(EVENT_DESTROY_ITEM_CLIENT)) { + std::vector args = { inst }; + parse->EventPlayer(EVENT_DESTROY_ITEM_CLIENT, this, "", 0, &args); + } } DeleteItemInInventory(move_in->from_slot); @@ -1858,10 +1990,13 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if(!banker || distance > USE_NPC_RANGE2) { - auto hacked_string = fmt::format("Player tried to make use of a banker(items) but {} is " - "non-existant or too far away ({} units).", - banker ? banker->GetName() : "UNKNOWN NPC", distance); - database.SetMQDetectionFlag(AccountName(), GetName(), hacked_string, zone->GetShortName()); + auto message = fmt::format( + "Player tried to make use of a banker (items) but banker [{}] is " + "non-existent or too far away [{}] units", + banker ? banker->GetName() : "UNKNOWN NPC", distance + ); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); + Kick("Inventory desync"); // Kicking player to avoid item loss do to client and server inventories not being sync'd return false; } @@ -2205,53 +2340,73 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if (src_slot_id <= EQ::invslot::EQUIPMENT_END) { if(src_inst) { - parse->EventItem(EVENT_UNEQUIP_ITEM, this, src_inst, nullptr, "", src_slot_id); + if (parse->ItemHasQuestSub(src_inst, EVENT_UNEQUIP_ITEM)) { + parse->EventItem(EVENT_UNEQUIP_ITEM, this, src_inst, nullptr, "", src_slot_id); + } - std::string export_string = fmt::format( - "{} {}", - src_inst->IsStackable() ? src_inst->GetCharges() : 1, - src_slot_id - ); + if (parse->PlayerHasQuestSub(EVENT_UNEQUIP_ITEM_CLIENT)) { + const auto& export_string = fmt::format( + "{} {}", + src_inst->IsStackable() ? src_inst->GetCharges() : 1, + src_slot_id + ); - parse->EventPlayer(EVENT_UNEQUIP_ITEM_CLIENT, this, export_string, src_inst->GetItem()->ID); + parse->EventPlayer(EVENT_UNEQUIP_ITEM_CLIENT, this, export_string, src_inst->GetItem()->ID); + } } - if(dst_inst) { - parse->EventItem(EVENT_EQUIP_ITEM, this, dst_inst, nullptr, "", src_slot_id); + if (dst_inst) { + if (parse->ItemHasQuestSub(dst_inst, EVENT_EQUIP_ITEM)) { + parse->EventItem(EVENT_EQUIP_ITEM, this, dst_inst, nullptr, "", src_slot_id); + } - std::string export_string = fmt::format( - "{} {}", - dst_inst->IsStackable() ? dst_inst->GetCharges() : 1, - src_slot_id - ); + if (parse->PlayerHasQuestSub(EVENT_EQUIP_ITEM_CLIENT)) { + const auto& export_string = fmt::format( + "{} {}", + dst_inst->IsStackable() ? dst_inst->GetCharges() : 1, + src_slot_id + ); - parse->EventPlayer(EVENT_EQUIP_ITEM_CLIENT, this, export_string, dst_inst->GetItem()->ID); + parse->EventPlayer(EVENT_EQUIP_ITEM_CLIENT, this, export_string, dst_inst->GetItem()->ID); + } } } if (dst_slot_id <= EQ::invslot::EQUIPMENT_END) { - if(dst_inst) { - parse->EventItem(EVENT_UNEQUIP_ITEM, this, dst_inst, nullptr, "", dst_slot_id); + if (dst_inst) { + if (parse->ItemHasQuestSub(dst_inst, EVENT_UNEQUIP_ITEM)) { + parse->EventItem(EVENT_UNEQUIP_ITEM, this, dst_inst, nullptr, "", dst_slot_id); + } - std::string export_string = fmt::format( - "{} {}", - dst_inst->IsStackable() ? dst_inst->GetCharges() : 1, - dst_slot_id - ); + if (parse->PlayerHasQuestSub(EVENT_UNEQUIP_ITEM_CLIENT)) { + const auto& export_string = fmt::format( + "{} {}", + dst_inst->IsStackable() ? dst_inst->GetCharges() : 1, + dst_slot_id + ); - parse->EventPlayer(EVENT_UNEQUIP_ITEM_CLIENT, this, export_string, dst_inst->GetItem()->ID); + std::vector args = { dst_inst }; + + parse->EventPlayer(EVENT_UNEQUIP_ITEM_CLIENT, this, export_string, dst_inst->GetItem()->ID, &args); + } } - if(src_inst) { - parse->EventItem(EVENT_EQUIP_ITEM, this, src_inst, nullptr, "", dst_slot_id); + if (src_inst) { + if (parse->ItemHasQuestSub(src_inst, EVENT_EQUIP_ITEM)) { + parse->EventItem(EVENT_EQUIP_ITEM, this, src_inst, nullptr, "", dst_slot_id); + } - std::string export_string = fmt::format( - "{} {}", - src_inst->IsStackable() ? src_inst->GetCharges() : 1, - dst_slot_id - ); + if (parse->PlayerHasQuestSub(EVENT_EQUIP_ITEM_CLIENT)) { + const auto& export_string = fmt::format( + "{} {}", + src_inst->IsStackable() ? src_inst->GetCharges() : 1, + dst_slot_id + ); - parse->EventPlayer(EVENT_EQUIP_ITEM_CLIENT, this, export_string, src_inst->GetItem()->ID); + std::vector args = { src_inst }; + + parse->EventPlayer(EVENT_EQUIP_ITEM_CLIENT, this, export_string, src_inst->GetItem()->ID, &args); + } } } } @@ -3221,31 +3376,6 @@ void Client::SendItemPacket(int16 slot_id, const EQ::ItemInstance* inst, ItemPac FastQueuePacket(&outapp); } -EQApplicationPacket* Client::ReturnItemPacket(int16 slot_id, const EQ::ItemInstance* inst, ItemPacketType packet_type) -{ - if (!inst) - return nullptr; - - // Serialize item into |-delimited string - std::string packet = inst->Serialize(slot_id); - - EmuOpcode opcode = OP_Unknown; - EQApplicationPacket* outapp = nullptr; - BulkItemPacket_Struct* itempacket = nullptr; - - // Construct packet - opcode = OP_ItemPacket; - outapp = new EQApplicationPacket(opcode, packet.length()+1); - itempacket = (BulkItemPacket_Struct*)outapp->pBuffer; - memcpy(itempacket->SerializedItem, packet.c_str(), packet.length()); - -#if EQDEBUG >= 9 - DumpPacket(outapp); -#endif - - return outapp; -} - static int16 BandolierSlotToWeaponSlot(int BandolierSlot) { switch (BandolierSlot) @@ -3894,7 +4024,7 @@ const int EQ::InventoryProfile::GetItemStatValue(uint32 item_id, std::string ide } if (Strings::EqualFold(identifier, "idfile")) { - stat = Strings::IsNumber(&item->IDFile[2]) ? std::stoi(&item->IDFile[2]) : 0; + stat = Strings::IsNumber(&item->IDFile[2]) ? Strings::ToInt(&item->IDFile[2]) : 0; } if (Strings::EqualFold(identifier, "weight")) { diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 7afe959ff..ed9c8e5cc 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -434,7 +434,7 @@ void NPC::AddLootDrop( } } - emat = atoi(newid); + emat = Strings::ToInt(newid); } else { emat = item2->Material; } @@ -485,12 +485,12 @@ void NPC::AddLootDrop( what was this about??? if (((npc->GetRace()==127) && (npc->CastToMob()->GetOwnerID()!=0)) && (item2->Slots==24576) || (item2->Slots==8192) || (item2->Slots==16384)){ - npc->d_melee_texture2=atoi(newid); + npc->d_melee_texture2=Strings::ToInt(newid); wc->wear_slot_id=8; if (item2->Material >0) wc->material=item2->Material; else - wc->material=atoi(newid); + wc->material=Strings::ToInt(newid); npc->AC+=item2->AC; npc->STR+=item2->STR; npc->INT+=item2->INT; @@ -633,52 +633,52 @@ void ZoneDatabase::LoadGlobalLoot() } } - GlobalLootEntry e(atoi(row[0]), atoi(row[1]), row[2] ? row[2] : ""); + GlobalLootEntry e(Strings::ToInt(row[0]), Strings::ToInt(row[1]), row[2] ? row[2] : ""); - auto min_level = atoi(row[3]); + auto min_level = Strings::ToInt(row[3]); if (min_level) { e.AddRule(GlobalLoot::RuleTypes::LevelMin, min_level); } - auto max_level = atoi(row[4]); + auto max_level = Strings::ToInt(row[4]); if (max_level) { e.AddRule(GlobalLoot::RuleTypes::LevelMax, max_level); } // null is not used if (row[5]) { - e.AddRule(GlobalLoot::RuleTypes::Rare, atoi(row[5])); + e.AddRule(GlobalLoot::RuleTypes::Rare, Strings::ToInt(row[5])); } // null is not used if (row[6]) { - e.AddRule(GlobalLoot::RuleTypes::Raid, atoi(row[6])); + e.AddRule(GlobalLoot::RuleTypes::Raid, Strings::ToInt(row[6])); } if (row[7]) { auto races = Strings::Split(row[7], '|'); for (auto &r : races) - e.AddRule(GlobalLoot::RuleTypes::Race, std::stoi(r)); + e.AddRule(GlobalLoot::RuleTypes::Race, Strings::ToInt(r)); } if (row[8]) { auto classes = Strings::Split(row[8], '|'); for (auto &c : classes) - e.AddRule(GlobalLoot::RuleTypes::Class, std::stoi(c)); + e.AddRule(GlobalLoot::RuleTypes::Class, Strings::ToInt(c)); } if (row[9]) { auto bodytypes = Strings::Split(row[9], '|'); for (auto &b : bodytypes) - e.AddRule(GlobalLoot::RuleTypes::BodyType, std::stoi(b)); + e.AddRule(GlobalLoot::RuleTypes::BodyType, Strings::ToInt(b)); } // null is not used if (row[11]) { - e.AddRule(GlobalLoot::RuleTypes::HotZone, atoi(row[11])); + e.AddRule(GlobalLoot::RuleTypes::HotZone, Strings::ToInt(row[11])); } zone->AddGlobalLootEntry(e); diff --git a/zone/lua_bot.cpp b/zone/lua_bot.cpp index 096fcd9e7..7b63e3844 100644 --- a/zone/lua_bot.cpp +++ b/zone/lua_bot.cpp @@ -8,6 +8,7 @@ #include "lua_iteminst.h" #include "lua_mob.h" #include "lua_group.h" +#include "lua_item.h" void Lua_Bot::AddBotItem(uint16 slot_id, uint32 item_id) { Lua_Safe_Call_Void(); @@ -64,8 +65,8 @@ Lua_Mob Lua_Bot::GetOwner() { return Lua_Mob(self->GetOwner()); } -bool Lua_Bot::HasBotItem(uint32 item_id) { - Lua_Safe_Call_Bool(); +int16 Lua_Bot::HasBotItem(uint32 item_id) { + Lua_Safe_Call_Int(); return self->HasBotItem(item_id); } @@ -393,6 +394,66 @@ void Lua_Bot::SendSpellAnim(uint16 target_id, uint16 spell_id) self->SendSpellAnim(target_id, spell_id); } +luabind::object Lua_Bot::GetAugmentIDsBySlotID(lua_State* L, int16 slot_id) const { + auto lua_table = luabind::newtable(L); + if (d_) { + auto self = reinterpret_cast(d_); + auto augments = self->GetInv().GetAugmentIDsBySlotID(slot_id); + int index = 1; + for (auto item_id : augments) { + lua_table[index] = item_id; + index++; + } + } + return lua_table; +} + +void Lua_Bot::AddItem(const luabind::object& item_table) { + Lua_Safe_Call_Void(); + if (luabind::type(item_table) != LUA_TTABLE) { + return; + } + + auto item_id = luabind::object_cast(item_table["item_id"]); + int16 charges = luabind::object_cast(item_table["charges"]); + uint32 augment_one = luabind::type(item_table["augment_one"]) != LUA_TNIL ? luabind::object_cast(item_table["augment_one"]) : 0; + uint32 augment_two = luabind::type(item_table["augment_two"]) != LUA_TNIL ? luabind::object_cast(item_table["augment_two"]) : 0; + uint32 augment_three = luabind::type(item_table["augment_three"]) != LUA_TNIL ? luabind::object_cast(item_table["augment_three"]) : 0; + uint32 augment_four = luabind::type(item_table["augment_four"]) != LUA_TNIL ? luabind::object_cast(item_table["augment_four"]) : 0; + uint32 augment_five = luabind::type(item_table["augment_five"]) != LUA_TNIL ? luabind::object_cast(item_table["augment_five"]) : 0; + uint32 augment_six = luabind::type(item_table["augment_six"]) != LUA_TNIL ? luabind::object_cast(item_table["augment_six"]) : 0; + bool attuned = luabind::type(item_table["attuned"]) != LUA_TNIL ? luabind::object_cast(item_table["attuned"]) : false; + uint16 slot_id = luabind::type(item_table["slot_id"]) != LUA_TNIL ? luabind::object_cast(item_table["slot_id"]) : EQ::invslot::slotCursor; + + if (slot_id <= EQ::invslot::slotAmmo) { + self->AddBotItem( + slot_id, + item_id, + charges, + attuned, + augment_one, + augment_two, + augment_three, + augment_four, + augment_five, + augment_six + ); + } else { + self->GetOwner()->CastToClient()->SummonItem( + item_id, + charges, + augment_one, + augment_two, + augment_three, + augment_four, + augment_five, + augment_six, + attuned, + slot_id + ); + } +} + luabind::scope lua_register_bot() { return luabind::class_("Bot") .def(luabind::constructor<>()) @@ -405,6 +466,7 @@ luabind::scope lua_register_bot() { .def("AddBotItem", (void(Lua_Bot::*)(uint16,uint32,int16,bool,uint32,uint32,uint32,uint32))&Lua_Bot::AddBotItem) .def("AddBotItem", (void(Lua_Bot::*)(uint16,uint32,int16,bool,uint32,uint32,uint32,uint32,uint32))&Lua_Bot::AddBotItem) .def("AddBotItem", (void(Lua_Bot::*)(uint16,uint32,int16,bool,uint32,uint32,uint32,uint32,uint32,uint32))&Lua_Bot::AddBotItem) + .def("AddItem", (void(Lua_Bot::*)(luabind::adl::object))&Lua_Bot::AddItem) .def("ApplySpell", (void(Lua_Bot::*)(int))&Lua_Bot::ApplySpell) .def("ApplySpell", (void(Lua_Bot::*)(int,int))&Lua_Bot::ApplySpell) .def("ApplySpell", (void(Lua_Bot::*)(int,int,bool))&Lua_Bot::ApplySpell) @@ -424,6 +486,7 @@ luabind::scope lua_register_bot() { .def("Fling", (void(Lua_Bot::*)(float,float,float,float,bool,bool))&Lua_Bot::Fling) .def("GetAugmentAt", (Lua_ItemInst(Lua_Bot::*)(int16,uint8))&Lua_Bot::GetAugmentAt) .def("GetAugmentIDAt", (int(Lua_Bot::*)(int16,uint8))&Lua_Bot::GetAugmentIDAt) + .def("GetAugmentIDsBySlotID", (luabind::object(Lua_Bot::*)(lua_State* L,int16))&Lua_Bot::GetAugmentIDsBySlotID) .def("GetBaseAGI", (int(Lua_Bot::*)(void))&Lua_Bot::GetBaseAGI) .def("GetBaseCHA", (int(Lua_Bot::*)(void))&Lua_Bot::GetBaseCHA) .def("GetBaseDEX", (int(Lua_Bot::*)(void))&Lua_Bot::GetBaseDEX) @@ -444,7 +507,7 @@ luabind::scope lua_register_bot() { .def("GetRawItemAC", (int(Lua_Bot::*)(void))&Lua_Bot::GetRawItemAC) .def("GetSpellDamage", (int(Lua_Bot::*)(void))&Lua_Bot::GetSpellDamage) .def("HasAugmentEquippedByID", (bool(Lua_Bot::*)(uint32))&Lua_Bot::HasAugmentEquippedByID) - .def("HasBotItem", (bool(Lua_Bot::*)(uint32))&Lua_Bot::HasBotItem) + .def("HasBotItem", (int16(Lua_Bot::*)(uint32))&Lua_Bot::HasBotItem) .def("HasBotSpellEntry", (bool(Lua_Bot::*)(uint16)) & Lua_Bot::HasBotSpellEntry) .def("HasItemEquippedByID", (bool(Lua_Bot::*)(uint32))&Lua_Bot::HasItemEquippedByID) .def("IsGrouped", (bool(Lua_Bot::*)(void))&Lua_Bot::IsGrouped) diff --git a/zone/lua_bot.h b/zone/lua_bot.h index 8e25f5b5e..041745091 100644 --- a/zone/lua_bot.h +++ b/zone/lua_bot.h @@ -8,6 +8,7 @@ class Bot; class Lua_Bot; class Lua_Mob; class Lua_Group; +class Lua_Inventory; namespace luabind { struct scope; @@ -36,12 +37,13 @@ public: void AddBotItem(uint16 slot_id, uint32 item_id, int16 charges, bool attuned, uint32 augment_one, uint32 augment_two, uint32 augment_three, uint32 augment_four); void AddBotItem(uint16 slot_id, uint32 item_id, int16 charges, bool attuned, uint32 augment_one, uint32 augment_two, uint32 augment_three, uint32 augment_four, uint32 augment_five); void AddBotItem(uint16 slot_id, uint32 item_id, int16 charges, bool attuned, uint32 augment_one, uint32 augment_two, uint32 augment_three, uint32 augment_four, uint32 augment_five, uint32 augment_six); + void AddItem(const luabind::object& item_table); uint32 CountBotItem(uint32 item_id); Lua_ItemInst GetBotItem(uint16 slot_id); uint32 GetBotItemIDBySlot(uint16 slot_id); int GetExpansionBitmask(); Lua_Mob GetOwner(); - bool HasBotItem(uint32 item_id); + int16 HasBotItem(uint32 item_id); void OwnerMessage(std::string message); bool ReloadBotDataBuckets(); bool ReloadBotOwnerDataBuckets(); @@ -59,6 +61,7 @@ public: void Camp(bool save_to_database); Lua_ItemInst GetAugmentAt(int16 slot_id, uint8 augment_index); int GetAugmentIDAt(int16 slot_id, uint8 augment_index); + luabind::object GetAugmentIDsBySlotID(lua_State* L, int16 slot_id) const; Lua_ItemInst GetItemAt(int16 slot_id); int GetItemIDAt(int16 slot_id); void SendSpellAnim(uint16 target_id, uint16 spell_id); diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index bc5884427..0ae70ee66 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -36,11 +36,6 @@ void Lua_Client::Save(int commit_now) { self->Save(commit_now); } -void Lua_Client::SaveBackup() { - Lua_Safe_Call_Void(); - self->SaveBackup(); -} - bool Lua_Client::Connected() { Lua_Safe_Call_Bool(); return self->Connected(); @@ -3014,6 +3009,43 @@ void Lua_Client::CampAllBots(uint8 class_id) self->CampAllBots(class_id); } +void Lua_Client::ResetItemCooldown(uint32 item_id) +{ + Lua_Safe_Call_Void(); + self->ResetItemCooldown(item_id); +} + +void Lua_Client::SetItemCooldown(uint32 item_id, uint32 in_time) +{ + Lua_Safe_Call_Void(); + self->SetItemCooldown(item_id, false, in_time); +} + +uint32 Lua_Client::GetItemCooldown(uint32 item_id) +{ + Lua_Safe_Call_Int(); + return self->GetItemCooldown(item_id); +} + +void Lua_Client::UseAugmentContainer(int container_slot) +{ + Lua_Safe_Call_Void(); + self->UseAugmentContainer(container_slot); +} + + +bool Lua_Client::IsAutoAttackEnabled() +{ + Lua_Safe_Call_Bool(); + return self->AutoAttackEnabled(); +} + +bool Lua_Client::IsAutoFireEnabled() +{ + Lua_Safe_Call_Bool(); + return self->AutoFireEnabled(); +} + luabind::scope lua_register_client() { return luabind::class_("Client") .def(luabind::constructor<>()) @@ -3204,6 +3236,7 @@ luabind::scope lua_register_client() { .def("GetInventory", (Lua_Inventory(Lua_Client::*)(void))&Lua_Client::GetInventory) .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("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) @@ -3271,6 +3304,8 @@ luabind::scope lua_register_client() { .def("IncreaseSkill", (void(Lua_Client::*)(int))&Lua_Client::IncreaseSkill) .def("IncreaseSkill", (void(Lua_Client::*)(int,int))&Lua_Client::IncreaseSkill) .def("IncrementAA", (void(Lua_Client::*)(int))&Lua_Client::IncrementAA) + .def("IsAutoAttackEnabled", (bool(Lua_Client::*)(void))&Lua_Client::IsAutoAttackEnabled) + .def("IsAutoFireEnabled", (bool(Lua_Client::*)(void))&Lua_Client::IsAutoFireEnabled) .def("IsCrouching", (bool(Lua_Client::*)(void))&Lua_Client::IsCrouching) .def("IsDead", &Lua_Client::IsDead) .def("IsDueling", (bool(Lua_Client::*)(void))&Lua_Client::IsDueling) @@ -3373,11 +3408,11 @@ luabind::scope lua_register_client() { .def("ResetCastbarCooldownBySlot", (void(Lua_Client::*)(int))&Lua_Client::ResetCastbarCooldownBySlot) .def("ResetCastbarCooldownBySpellID", (void(Lua_Client::*)(uint32))&Lua_Client::ResetCastbarCooldownBySpellID) .def("ResetDisciplineTimer", (void(Lua_Client::*)(uint32))&Lua_Client::ResetDisciplineTimer) + .def("ResetItemCooldown", (void(Lua_Client::*)(uint32))&Lua_Client::ResetItemCooldown) .def("ResetTrade", (void(Lua_Client::*)(void))&Lua_Client::ResetTrade) .def("RewardFaction", (void(Lua_Client::*)(int,int))&Lua_Client::RewardFaction) .def("Save", (void(Lua_Client::*)(int))&Lua_Client::Save) .def("Save", (void(Lua_Client::*)(void))&Lua_Client::Save) - .def("SaveBackup", (void(Lua_Client::*)(void))&Lua_Client::SaveBackup) .def("ScribeSpell", (void(Lua_Client::*)(int,int))&Lua_Client::ScribeSpell) .def("ScribeSpell", (void(Lua_Client::*)(int,int,bool))&Lua_Client::ScribeSpell) .def("ScribeSpells", (uint16(Lua_Client::*)(uint8,uint8))&Lua_Client::ScribeSpells) @@ -3447,6 +3482,7 @@ luabind::scope lua_register_client() { .def("SetHunger", (void(Lua_Client::*)(int))&Lua_Client::SetHunger) .def("SetInvulnerableEnvironmentDamage", (void(Lua_Client::*)(int))&Lua_Client::SetInvulnerableEnvironmentDamage) .def("SetIPExemption", (void(Lua_Client::*)(int))&Lua_Client::SetIPExemption) + .def("SetItemCooldown", (void(Lua_Client::*)(uint32,uint32))&Lua_Client::SetItemCooldown) .def("SetLanguageSkill", (void(Lua_Client::*)(int,int))&Lua_Client::SetLanguageSkill) .def("SetMaterial", (void(Lua_Client::*)(int,uint32))&Lua_Client::SetMaterial) .def("SetPEQZoneFlag", (void(Lua_Client::*)(uint32))&Lua_Client::SetPEQZoneFlag) @@ -3532,6 +3568,7 @@ luabind::scope lua_register_client() { .def("UpdateLDoNPoints", (void(Lua_Client::*)(uint32,int))&Lua_Client::UpdateLDoNPoints) .def("UpdateTaskActivity", (void(Lua_Client::*)(int,int,int))&Lua_Client::UpdateTaskActivity) .def("UseDiscipline", (bool(Lua_Client::*)(int,int))&Lua_Client::UseDiscipline) + .def("UseAugmentContainer", (void(Lua_Client::*)(int))&Lua_Client::UseAugmentContainer) .def("WorldKick", (void(Lua_Client::*)(void))&Lua_Client::WorldKick); } diff --git a/zone/lua_client.h b/zone/lua_client.h index 187b841a4..a5d0c8409 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -34,7 +34,6 @@ public: void Sit(); void Save(); void Save(int commit_now); - void SaveBackup(); bool Connected(); bool InZone(); void Kick(); @@ -462,6 +461,12 @@ public: bool CanEnterZone(std::string zone_short_name); bool CanEnterZone(std::string zone_short_name, int16 instance_version); void SendPath(Lua_Mob target); + void ResetItemCooldown(uint32 item_id); + void SetItemCooldown(uint32 item_id, uint32 in_time); + uint32 GetItemCooldown(uint32 item_id); + void UseAugmentContainer(int container_slot); + bool IsAutoAttackEnabled(); + bool IsAutoFireEnabled(); void ApplySpell(int spell_id); void ApplySpell(int spell_id, int duration); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 086c5dc5e..366195e2e 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -3700,6 +3700,114 @@ int8 lua_does_augment_fit(Lua_ItemInst inst, uint32 augment_id) return quest_manager.DoesAugmentFit(inst, augment_id); } +int8 lua_does_augment_fit_slot(Lua_ItemInst inst, uint32 augment_id, uint8 augment_slot) +{ + return quest_manager.DoesAugmentFit(inst, augment_id, augment_slot); +} + +luabind::object lua_get_recipe_component_item_ids(lua_State* L, uint32 recipe_id) +{ + auto lua_table = luabind::newtable(L); + + const auto& l = content_db.GetRecipeComponentItemIDs(RecipeCountType::Component, recipe_id); + if (!l.empty()) { + int index = 1; + for (const auto& i : l) { + lua_table[index] = i; + index++; + } + } + + return lua_table; +} + +luabind::object lua_get_recipe_container_item_ids(lua_State* L, uint32 recipe_id) +{ + auto lua_table = luabind::newtable(L); + + const auto& l = content_db.GetRecipeComponentItemIDs(RecipeCountType::Container, recipe_id); + if (!l.empty()) { + int index = 1; + for (const auto& i : l) { + lua_table[index] = i; + index++; + } + } + + return lua_table; +} + +luabind::object lua_get_recipe_fail_item_ids(lua_State* L, uint32 recipe_id) +{ + auto lua_table = luabind::newtable(L); + + const auto& l = content_db.GetRecipeComponentItemIDs(RecipeCountType::Fail, recipe_id); + if (!l.empty()) { + int index = 1; + for (const auto& i : l) { + lua_table[index] = i; + index++; + } + } + + return lua_table; +} + +luabind::object lua_get_recipe_salvage_item_ids(lua_State* L, uint32 recipe_id) { + auto lua_table = luabind::newtable(L); + + const auto& l = content_db.GetRecipeComponentItemIDs(RecipeCountType::Salvage, recipe_id); + if (!l.empty()) { + int index = 1; + for (const auto& i : l) { + lua_table[index] = i; + index++; + } + } + + return lua_table; +} + +luabind::object lua_get_recipe_success_item_ids(lua_State* L, uint32 recipe_id) { + auto lua_table = luabind::newtable(L); + + const auto& l = content_db.GetRecipeComponentItemIDs(RecipeCountType::Success, recipe_id); + if (!l.empty()) { + int index = 1; + for (const auto& i : l) { + lua_table[index] = i; + index++; + } + } + + return lua_table; +} + +int8 lua_get_recipe_component_count(uint32 recipe_id, uint32 item_id) +{ + return content_db.GetRecipeComponentCount(RecipeCountType::Component, recipe_id, item_id); +} + +int8 lua_get_recipe_fail_count(uint32 recipe_id, uint32 item_id) +{ + return content_db.GetRecipeComponentCount(RecipeCountType::Fail, recipe_id, item_id); +} + +int8 lua_get_recipe_salvage_count(uint32 recipe_id, uint32 item_id) +{ + return content_db.GetRecipeComponentCount(RecipeCountType::Salvage, recipe_id, item_id); +} + +int8 lua_get_recipe_success_count(uint32 recipe_id, uint32 item_id) +{ + return content_db.GetRecipeComponentCount(RecipeCountType::Success, recipe_id, item_id); +} + +void lua_send_player_handin_event() +{ + quest_manager.SendPlayerHandinEvent(); +} + #define LuaCreateNPCParse(name, c_type, default_value) do { \ cur = table[#name]; \ if(luabind::type(cur) != LUA_TNIL) { \ @@ -4217,7 +4325,18 @@ luabind::scope lua_register_general() { luabind::def("do_anim", (void(*)(int,int,bool))&lua_do_anim), luabind::def("do_anim", (void(*)(int,int,bool,int))&lua_do_anim), luabind::def("do_augment_slots_match", &lua_do_augment_slots_match), - luabind::def("does_augment_fit", &lua_does_augment_fit), + luabind::def("does_augment_fit", (int8(*)(Lua_ItemInst, uint32))&lua_does_augment_fit), + luabind::def("does_augment_fit_slot", (int8(*)(Lua_ItemInst, uint32, uint8))&lua_does_augment_fit_slot), + luabind::def("get_recipe_component_item_ids", (luabind::object(*)(lua_State*,uint32))&lua_get_recipe_component_item_ids), + luabind::def("get_recipe_container_item_ids", (luabind::object(*)(lua_State*,uint32))&lua_get_recipe_container_item_ids), + luabind::def("get_recipe_fail_item_ids", (luabind::object(*)(lua_State*,uint32))&lua_get_recipe_fail_item_ids), + luabind::def("get_recipe_salvage_item_ids", (luabind::object(*)(lua_State*,uint32))&lua_get_recipe_salvage_item_ids), + luabind::def("get_recipe_success_item_ids", (luabind::object(*)(lua_State*,uint32))&lua_get_recipe_success_item_ids), + luabind::def("get_recipe_component_count", (int8(*)(uint32,uint32))&lua_get_recipe_component_count), + luabind::def("get_recipe_fail_count", (int8(*)(uint32,uint32))&lua_get_recipe_fail_count), + luabind::def("get_recipe_salvage_count", (int8(*)(uint32,uint32))&lua_get_recipe_salvage_count), + luabind::def("get_recipe_success_count", (int8(*)(uint32,uint32))&lua_get_recipe_success_count), + luabind::def("send_player_handin_event", (void(*)(void))&lua_send_player_handin_event), /* Cross Zone */ @@ -4617,7 +4736,9 @@ luabind::scope lua_register_events() { luabind::value("inspect", static_cast(EVENT_INSPECT)), luabind::value("task_before_update", static_cast(EVENT_TASK_BEFORE_UPDATE)), luabind::value("aa_buy", static_cast(EVENT_AA_BUY)), - luabind::value("aa_gain", static_cast(EVENT_AA_GAIN)), + luabind::value("aa_gained", static_cast(EVENT_AA_GAIN)), + luabind::value("aa_exp_gained", static_cast(EVENT_AA_EXP_GAIN)), + luabind::value("exp_gain", static_cast(EVENT_EXP_GAIN)), luabind::value("payload", static_cast(EVENT_PAYLOAD)), luabind::value("level_down", static_cast(EVENT_LEVEL_DOWN)), luabind::value("gm_command", static_cast(EVENT_GM_COMMAND)), @@ -4625,7 +4746,15 @@ luabind::scope lua_register_events() { luabind::value("despawn_zone", static_cast(EVENT_DESPAWN_ZONE)), luabind::value("bot_create", static_cast(EVENT_BOT_CREATE)), luabind::value("augment_insert_client", static_cast(EVENT_AUGMENT_INSERT_CLIENT)), - luabind::value("augment_remove_client", static_cast(EVENT_AUGMENT_REMOVE_CLIENT)) + luabind::value("augment_remove_client", static_cast(EVENT_AUGMENT_REMOVE_CLIENT)), + luabind::value("equip_item_bot", static_cast(EVENT_EQUIP_ITEM_BOT)), + luabind::value("unequip_item_bot", static_cast(EVENT_UNEQUIP_ITEM_BOT)), + luabind::value("damage_given", static_cast(EVENT_DAMAGE_GIVEN)), + luabind::value("damage_taken", static_cast(EVENT_DAMAGE_TAKEN)), + luabind::value("item_click_client", static_cast(EVENT_ITEM_CLICK_CLIENT)), + luabind::value("item_click_cast_client", static_cast(EVENT_ITEM_CLICK_CAST_CLIENT)), + luabind::value("destroy_item_client", static_cast(EVENT_DESTROY_ITEM_CLIENT)), + luabind::value("drop_item_client", static_cast(EVENT_DROP_ITEM_CLIENT)) )]; } diff --git a/zone/lua_hate_entry.cpp b/zone/lua_hate_entry.cpp deleted file mode 100644 index 7d209bd43..000000000 --- a/zone/lua_hate_entry.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#ifdef LUA_EQEMU - -#include "lua.hpp" -#include -#include -#include - -#include "masterentity.h" -#include "hate_list.h" -#include "lua_mob.h" -#include "lua_hate_list.h" - -struct Lua_HateList -{ - std::vector entries; -}; - -Lua_Mob Lua_HateEntry::GetEnt() { - Lua_Safe_Call_Class(Lua_Mob); - return Lua_Mob(self->ent); -} - -void Lua_HateEntry::SetEnt(Lua_Mob e) { - Lua_Safe_Call_Void(); - self->ent = e; -} - -int Lua_HateEntry::GetDamage() { - Lua_Safe_Call_Int(); - return self->damage; -} - -void Lua_HateEntry::SetDamage(int value) { - Lua_Safe_Call_Void(); - self->damage = value; -} - -int Lua_HateEntry::GetHate() { - Lua_Safe_Call_Int(); - return self->hate; -} - -void Lua_HateEntry::SetHate(int value) { - Lua_Safe_Call_Void(); - self->hate = value; -} - -int Lua_HateEntry::GetFrenzy() { - Lua_Safe_Call_Int(); - return self->bFrenzy; -} - -void Lua_HateEntry::SetFrenzy(bool value) { - Lua_Safe_Call_Void(); - self->bFrenzy = value; -} - -luabind::scope lua_register_hate_entry() { - - return luabind::class_("HateEntry") - .property("null", &Lua_HateEntry::Null) - .property("valid", &Lua_HateEntry::Valid) - .property("damage", &Lua_HateEntry::GetDamage, &Lua_HateEntry::SetDamage) - .property("ent", &Lua_HateEntry::GetEnt, &Lua_HateEntry::SetEnt) - .property("frenzy", &Lua_HateEntry::GetFrenzy, &Lua_HateEntry::SetFrenzy) - .property("hate", &Lua_HateEntry::GetHate, &Lua_HateEntry::SetHate); -} - -luabind::scope lua_register_hate_list() { - return luabind::class_("HateList") - .def_readwrite("entries", &Lua_HateList::entries, luabind::return_stl_iterator); -} - -#endif diff --git a/zone/lua_hate_list.cpp b/zone/lua_hate_list.cpp index 7d40ae451..9adb9afdd 100644 --- a/zone/lua_hate_list.cpp +++ b/zone/lua_hate_list.cpp @@ -1,12 +1,9 @@ #ifdef LUA_EQEMU -#include "lua.hpp" #include -#include #include #include "masterentity.h" -#include "hate_list.h" #include "lua_mob.h" #include "lua_hate_list.h" diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 07b5163c8..4face4b8f 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -1567,153 +1567,189 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) { return; } - int race = RACE_DOUG_0; - int gender = 255; - int texture = 255; - int helmtexture = 255; - int haircolor = 255; - int beardcolor = 255; - int eyecolor1 = 255; - int eyecolor2 = 255; - int hairstyle = 255; - int luclinface = 255; - int beard = 255; - int aa_title = 255; - uint32 drakkin_heritage = 4294967295; - uint32 drakkin_tattoo = 4294967295; - uint32 drakkin_details = 4294967295; - float size = -1.0f; + uint16 race = self->GetRace(); + uint8 gender = self->GetGender(); + uint8 texture = self->GetTexture(); + uint8 helmtexture = self->GetHelmTexture(); + uint8 haircolor = self->GetHairColor(); + uint8 beardcolor = self->GetBeardColor(); + uint8 eyecolor1 = self->GetEyeColor1(); + uint8 eyecolor2 = self->GetEyeColor2(); + uint8 hairstyle = self->GetHairStyle(); + uint8 luclinface = self->GetLuclinFace(); + uint8 beard = self->GetBeard(); + uint8 aa_title = 255; + uint32 drakkin_heritage = self->GetDrakkinHeritage(); + uint32 drakkin_tattoo = self->GetDrakkinTattoo(); + uint32 drakkin_details = self->GetDrakkinDetails(); + float size = self->GetSize(); + bool send_appearance_effects = true; + Lua_Client target = Lua_Client(); auto cur = illusion["race"]; - if(luabind::type(cur) != LUA_TNIL) { + if (luabind::type(cur) != LUA_TNIL) { try { - race = luabind::object_cast(cur); - } catch(luabind::cast_failed &) { + race = luabind::object_cast(cur); + } catch (luabind::cast_failed &) { } } cur = illusion["gender"]; - if(luabind::type(cur) != LUA_TNIL) { + if (luabind::type(cur) != LUA_TNIL) { try { - gender = luabind::object_cast(cur); - } catch(luabind::cast_failed &) { + gender = luabind::object_cast(cur); + } catch (luabind::cast_failed &) { } } cur = illusion["texture"]; - if(luabind::type(cur) != LUA_TNIL) { + if (luabind::type(cur) != LUA_TNIL) { try { - texture = luabind::object_cast(cur); - } catch(luabind::cast_failed &) { + texture = luabind::object_cast(cur); + } catch (luabind::cast_failed &) { } } cur = illusion["helmtexture"]; - if(luabind::type(cur) != LUA_TNIL) { + if (luabind::type(cur) != LUA_TNIL) { try { - helmtexture = luabind::object_cast(cur); - } catch(luabind::cast_failed &) { + helmtexture = luabind::object_cast(cur); + } catch (luabind::cast_failed &) { } } cur = illusion["haircolor"]; - if(luabind::type(cur) != LUA_TNIL) { + if (luabind::type(cur) != LUA_TNIL) { try { - haircolor = luabind::object_cast(cur); - } catch(luabind::cast_failed &) { + haircolor = luabind::object_cast(cur); + } catch (luabind::cast_failed &) { } } cur = illusion["beardcolor"]; - if(luabind::type(cur) != LUA_TNIL) { + if (luabind::type(cur) != LUA_TNIL) { try { - beardcolor = luabind::object_cast(cur); - } catch(luabind::cast_failed &) { + beardcolor = luabind::object_cast(cur); + } catch (luabind::cast_failed &) { } } cur = illusion["eyecolor1"]; - if(luabind::type(cur) != LUA_TNIL) { + if (luabind::type(cur) != LUA_TNIL) { try { - eyecolor1 = luabind::object_cast(cur); - } catch(luabind::cast_failed &) { + eyecolor1 = luabind::object_cast(cur); + } catch (luabind::cast_failed &) { } } cur = illusion["eyecolor2"]; - if(luabind::type(cur) != LUA_TNIL) { + if (luabind::type(cur) != LUA_TNIL) { try { - eyecolor2 = luabind::object_cast(cur); - } catch(luabind::cast_failed &) { + eyecolor2 = luabind::object_cast(cur); + } catch (luabind::cast_failed &) { } } cur = illusion["hairstyle"]; - if(luabind::type(cur) != LUA_TNIL) { + if (luabind::type(cur) != LUA_TNIL) { try { - hairstyle = luabind::object_cast(cur); - } catch(luabind::cast_failed &) { + hairstyle = luabind::object_cast(cur); + } catch (luabind::cast_failed &) { } } cur = illusion["luclinface"]; - if(luabind::type(cur) != LUA_TNIL) { + if (luabind::type(cur) != LUA_TNIL) { try { - luclinface = luabind::object_cast(cur); - } catch(luabind::cast_failed &) { + luclinface = luabind::object_cast(cur); + } catch (luabind::cast_failed &) { } } cur = illusion["beard"]; - if(luabind::type(cur) != LUA_TNIL) { + if (luabind::type(cur) != LUA_TNIL) { try { - beard = luabind::object_cast(cur); - } catch(luabind::cast_failed &) { + beard = luabind::object_cast(cur); + } catch (luabind::cast_failed &) { } } cur = illusion["aa_title"]; - if(luabind::type(cur) != LUA_TNIL) { + if (luabind::type(cur) != LUA_TNIL) { try { - aa_title = luabind::object_cast(cur); - } catch(luabind::cast_failed &) { + aa_title = luabind::object_cast(cur); + } catch (luabind::cast_failed &) { } } cur = illusion["drakkin_heritage"]; - if(luabind::type(cur) != LUA_TNIL) { + if (luabind::type(cur) != LUA_TNIL) { try { - drakkin_heritage = luabind::object_cast(cur); - } catch(luabind::cast_failed &) { + drakkin_heritage = luabind::object_cast(cur); + } catch (luabind::cast_failed &) { } } cur = illusion["drakkin_tattoo"]; - if(luabind::type(cur) != LUA_TNIL) { + if (luabind::type(cur) != LUA_TNIL) { try { - drakkin_tattoo = luabind::object_cast(cur); - } catch(luabind::cast_failed &) { + drakkin_tattoo = luabind::object_cast(cur); + } catch (luabind::cast_failed &) { } } cur = illusion["drakkin_details"]; - if(luabind::type(cur) != LUA_TNIL) { + if (luabind::type(cur) != LUA_TNIL) { try { - drakkin_details = luabind::object_cast(cur); - } catch(luabind::cast_failed &) { + drakkin_details = luabind::object_cast(cur); + } catch (luabind::cast_failed &) { } } cur = illusion["size"]; - if(luabind::type(cur) != LUA_TNIL) { + if (luabind::type(cur) != LUA_TNIL) { try { size = luabind::object_cast(cur); - } catch(luabind::cast_failed &) { + } catch (luabind::cast_failed &) { } } - self->SendIllusionPacket(race, gender, texture, helmtexture, haircolor, beardcolor, eyecolor1, eyecolor2, hairstyle, luclinface, - beard, aa_title, drakkin_heritage, drakkin_tattoo, drakkin_details, size); + cur = illusion["send_appearance_effects"]; + if (luabind::type(cur) != LUA_TNIL) { + try { + send_appearance_effects = luabind::object_cast(cur); + } catch (luabind::cast_failed &) { + } + } + + cur = illusion["target"]; + if (luabind::type(cur) != LUA_TNIL) { + try { + target = luabind::object_cast(cur); + } catch (luabind::cast_failed &) { + } + } + + self->SendIllusionPacket( + race, + gender, + texture, + helmtexture, + haircolor, + beardcolor, + eyecolor1, + eyecolor2, + hairstyle, + luclinface, + beard, + aa_title, + drakkin_heritage, + drakkin_tattoo, + drakkin_details, + size, + send_appearance_effects, + target + ); } void Lua_Mob::ChangeRace(int in) { @@ -2823,6 +2859,82 @@ Lua_HateList Lua_Mob::GetHateListBots(uint32 distance) { return ret; } +bool Lua_Mob::IsFindable() { + Lua_Safe_Call_Bool(); + return self->IsFindable(); +} + + +bool Lua_Mob::IsTrackable() { + Lua_Safe_Call_Bool(); + return self->IsTrackable(); +} + +float Lua_Mob::GetDefaultRaceSize() { + Lua_Safe_Call_Real(); + return self->GetDefaultRaceSize(); +} + +float Lua_Mob::GetActSpellRange(uint16 spell_id, float range) { + Lua_Safe_Call_Real(); + return self->GetActSpellRange(spell_id, range); +} + +int64 Lua_Mob::GetActSpellDamage(uint16 spell_id, int64 value) { + Lua_Safe_Call_Int(); + return self->GetActSpellDamage(spell_id, value); +} + +int64 Lua_Mob::GetActSpellDamage(uint16 spell_id, int64 value, Lua_Mob target) { + Lua_Safe_Call_Int(); + return self->GetActSpellDamage(spell_id, value, target); +} + +int64 Lua_Mob::GetActDoTDamage(uint16 spell_id, int64 value, Lua_Mob target) { + Lua_Safe_Call_Int(); + return self->GetActDoTDamage(spell_id, value, target); +} + +int64 Lua_Mob::GetActDoTDamage(uint16 spell_id, int64 value, Lua_Mob target, bool from_buff_tic) { + Lua_Safe_Call_Int(); + return self->GetActDoTDamage(spell_id, value, target, from_buff_tic); +} + +int64 Lua_Mob::GetActSpellHealing(uint16 spell_id, int64 value) { + Lua_Safe_Call_Int(); + return self->GetActSpellHealing(spell_id, value); +} + +int64 Lua_Mob::GetActSpellHealing(uint16 spell_id, int64 value, Lua_Mob target) { + Lua_Safe_Call_Int(); + return self->GetActSpellHealing(spell_id, value, target); +} + +int64 Lua_Mob::GetActSpellHealing(uint16 spell_id, int64 value, Lua_Mob target, bool from_buff_tic) { + Lua_Safe_Call_Int(); + return self->GetActSpellHealing(spell_id, value, target, from_buff_tic); +} + +int Lua_Mob::GetActSpellCost(uint16 spell_id, int cost) { + Lua_Safe_Call_Int(); + return self->GetActSpellCost(spell_id, cost); +} + +int Lua_Mob::GetActSpellDuration(uint16 spell_id, int duration) { + Lua_Safe_Call_Int(); + return self->GetActSpellDuration(spell_id, duration); +} + +int Lua_Mob::GetActSpellCasttime(uint16 spell_id, uint32 cast_time) { + Lua_Safe_Call_Int(); + return self->GetActSpellCasttime(spell_id, cast_time); +} + +int64 Lua_Mob::GetActReflectedSpellDamage(uint16 spell_id, int64 value, int effectiveness) { + Lua_Safe_Call_Int(); + return self->GetActReflectedSpellDamage(spell_id, value, effectiveness); +} + luabind::scope lua_register_mob() { return luabind::class_("Mob") .def(luabind::constructor<>()) @@ -2995,6 +3107,18 @@ luabind::scope lua_register_mob() { .def("GetAC", &Lua_Mob::GetAC) .def("GetAGI", &Lua_Mob::GetAGI) .def("GetATK", &Lua_Mob::GetATK) + .def("GetActDoTDamage", (int64(Lua_Mob::*)(uint16,int64,Lua_Mob))&Lua_Mob::GetActDoTDamage) + .def("GetActDoTDamage", (int64(Lua_Mob::*)(uint16,int64,Lua_Mob,bool))&Lua_Mob::GetActDoTDamage) + .def("GetActReflectedSpellDamage", &Lua_Mob::GetActReflectedSpellDamage) + .def("GetActSpellCasttime", &Lua_Mob::GetActSpellCasttime) + .def("GetActSpellCost", &Lua_Mob::GetActSpellCost) + .def("GetActSpellDuration", &Lua_Mob::GetActSpellDuration) + .def("GetActSpellDamage", (int64(Lua_Mob::*)(uint16,int64))&Lua_Mob::GetActSpellDamage) + .def("GetActSpellDamage", (int64(Lua_Mob::*)(uint16,int64,Lua_Mob))&Lua_Mob::GetActSpellDamage) + .def("GetActSpellHealing", (int64(Lua_Mob::*)(uint16,int64))&Lua_Mob::GetActSpellHealing) + .def("GetActSpellHealing", (int64(Lua_Mob::*)(uint16,int64,Lua_Mob))&Lua_Mob::GetActSpellHealing) + .def("GetActSpellHealing", (int64(Lua_Mob::*)(uint16,int64,Lua_Mob,bool))&Lua_Mob::GetActSpellHealing) + .def("GetActSpellRange", &Lua_Mob::GetActSpellRange) .def("GetAggroRange", (float(Lua_Mob::*)(void))&Lua_Mob::GetAggroRange) .def("GetAllowBeneficial", (bool(Lua_Mob::*)(void))&Lua_Mob::GetAllowBeneficial) .def("GetAppearance", (uint32(Lua_Mob::*)(void))&Lua_Mob::GetAppearance) @@ -3022,6 +3146,7 @@ luabind::scope lua_register_mob() { .def("GetDEX", &Lua_Mob::GetDEX) .def("GetDR", &Lua_Mob::GetDR) .def("GetDamageAmount", (uint32(Lua_Mob::*)(Lua_Mob))&Lua_Mob::GetDamageAmount) + .def("GetDefaultRaceSize", &Lua_Mob::GetDefaultRaceSize) .def("GetDeity", &Lua_Mob::GetDeity) .def("GetDisplayAC", &Lua_Mob::GetDisplayAC) .def("GetDrakkinDetails", &Lua_Mob::GetDrakkinDetails) @@ -3164,6 +3289,7 @@ luabind::scope lua_register_mob() { .def("IsEngaged", (bool(Lua_Mob::*)(void))&Lua_Mob::IsEngaged) .def("IsEnraged", (bool(Lua_Mob::*)(void))&Lua_Mob::IsEnraged) .def("IsFeared", (bool(Lua_Mob::*)(void))&Lua_Mob::IsFeared) + .def("IsFindable", (bool(Lua_Mob::*)(void))&Lua_Mob::IsFindable) .def("IsHorse", &Lua_Mob::IsHorse) .def("IsImmuneToSpell", (bool(Lua_Mob::*)(int,Lua_Mob))&Lua_Mob::IsImmuneToSpell) .def("IsInvisible", (bool(Lua_Mob::*)(Lua_Mob))&Lua_Mob::IsInvisible) @@ -3179,6 +3305,7 @@ luabind::scope lua_register_mob() { .def("IsStunned", (bool(Lua_Mob::*)(void))&Lua_Mob::IsStunned) .def("IsTargetable", (bool(Lua_Mob::*)(void))&Lua_Mob::IsTargetable) .def("IsTargeted", &Lua_Mob::IsTargeted) + .def("IsTrackable", (bool(Lua_Mob::*)(void))&Lua_Mob::IsTrackable) .def("IsWarriorClass", &Lua_Mob::IsWarriorClass) .def("Kill", (void(Lua_Mob::*)(void))&Lua_Mob::Kill) .def("Mesmerize", (void(Lua_Mob::*)(void))&Lua_Mob::Mesmerize) diff --git a/zone/lua_mob.h b/zone/lua_mob.h index fb3dbead5..a3bcace30 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -513,6 +513,21 @@ public: void CopyHateList(Lua_Mob to); bool IsAttackAllowed(Lua_Mob target); bool IsAttackAllowed(Lua_Mob target, bool is_spell_attack); + bool IsFindable(); + bool IsTrackable(); + float GetDefaultRaceSize(); + int64 GetActDoTDamage(uint16 spell_id, int64 value, Lua_Mob target); + int64 GetActDoTDamage(uint16 spell_id, int64 value, Lua_Mob target, bool from_buff_tic); + int64 GetActReflectedSpellDamage(uint16 spell_id, int64 value, int effectiveness); + int GetActSpellCasttime(uint16 spell_id, uint32 cast_time); + int GetActSpellCost(uint16 spell_id, int cost); + int64 GetActSpellDamage(uint16 spell_id, int64 value); + int64 GetActSpellDamage(uint16 spell_id, int64 value, Lua_Mob target); + int GetActSpellDuration(uint16 spell_id, int duration); + int64 GetActSpellHealing(uint16 spell_id, int64 value); + int64 GetActSpellHealing(uint16 spell_id, int64 value, Lua_Mob target); + int64 GetActSpellHealing(uint16 spell_id, int64 value, Lua_Mob target, bool from_buff_tic); + float GetActSpellRange(uint16 spell_id, float range); }; #endif diff --git a/zone/lua_npc.cpp b/zone/lua_npc.cpp index 8e1ac586f..1be00ac38 100644 --- a/zone/lua_npc.cpp +++ b/zone/lua_npc.cpp @@ -573,12 +573,6 @@ void Lua_NPC::RecalculateSkills() self->RecalculateSkills(); } -void Lua_NPC::ScaleNPC(uint8 npc_level) -{ - Lua_Safe_Call_Void(); - self->ScaleNPC(npc_level); -} - bool Lua_NPC::IsRaidTarget() { Lua_Safe_Call_Bool(); @@ -701,6 +695,88 @@ void Lua_NPC::SetKeepsSoldItems(bool keeps_sold_items) { self->SetKeepsSoldItems(keeps_sold_items); } +bool Lua_NPC::IsLDoNTrapped() { + Lua_Safe_Call_Bool(); + return self->IsLDoNTrapped(); +} + +void Lua_NPC::SetLDoNTrapped(bool is_trapped) { + Lua_Safe_Call_Void(); + self->SetLDoNTrapped(is_trapped); +} + +uint8 Lua_NPC::GetLDoNTrapType() { + Lua_Safe_Call_Int(); + return self->GetLDoNTrapType(); +} + +void Lua_NPC::SetLDoNTrapType(uint8 trap_type) { + Lua_Safe_Call_Void(); + self->SetLDoNTrapType(trap_type); +} + +uint16 Lua_NPC::GetLDoNTrapSpellID() { + Lua_Safe_Call_Int(); + return self->GetLDoNTrapSpellID(); +} + +void Lua_NPC::SetLDoNTrapSpellID(uint16 spell_id) { + Lua_Safe_Call_Void(); + self->SetLDoNTrapSpellID(spell_id); +} + +bool Lua_NPC::IsLDoNLocked() { + Lua_Safe_Call_Bool(); + return self->IsLDoNLocked(); +} + +void Lua_NPC::SetLDoNLocked(bool is_locked) { + Lua_Safe_Call_Void(); + self->SetLDoNLocked(is_locked); +} + +uint16 Lua_NPC::GetLDoNLockedSkill() { + Lua_Safe_Call_Int(); + return self->GetLDoNLockedSkill(); +} + +void Lua_NPC::SetLDoNLockedSkill(uint16 skill_value) { + Lua_Safe_Call_Void(); + self->SetLDoNLockedSkill(skill_value); +} + +bool Lua_NPC::IsLDoNTrapDetected() { + Lua_Safe_Call_Bool(); + return self->IsLDoNTrapDetected(); +} + +void Lua_NPC::SetLDoNTrapDetected(bool is_detected) { + Lua_Safe_Call_Void(); + self->SetLDoNTrapDetected(is_detected); +} + +void Lua_NPC::ScaleNPC(uint8 npc_level) +{ + Lua_Safe_Call_Void(); + self->ScaleNPC(npc_level); +} + +void Lua_NPC::ScaleNPC(uint8 npc_level, bool override_special_abilities) +{ + Lua_Safe_Call_Void(); + self->ScaleNPC(npc_level, true, override_special_abilities); +} + +bool Lua_NPC::IsUnderwaterOnly() { + Lua_Safe_Call_Bool(); + return self->IsUnderwaterOnly(); +} + +bool Lua_NPC::HasSpecialAbilities() { + Lua_Safe_Call_Bool(); + return self->HasSpecialAbilities(); +} + luabind::scope lua_register_npc() { return luabind::class_("NPC") .def(luabind::constructor<>()) @@ -753,6 +829,9 @@ luabind::scope lua_register_npc() { .def("GetMaxDamage", (uint32(Lua_NPC::*)(int))&Lua_NPC::GetMaxDamage) .def("GetMaxWp", (int(Lua_NPC::*)(void))&Lua_NPC::GetMaxWp) .def("GetMinDMG", (uint32(Lua_NPC::*)(void))&Lua_NPC::GetMinDMG) + .def("GetLDoNLockedSkill", (uint16(Lua_NPC::*)(void))&Lua_NPC::GetLDoNLockedSkill) + .def("GetLDoNTrapType", (uint8(Lua_NPC::*)(void))&Lua_NPC::GetLDoNTrapType) + .def("GetLDoNTrapSpellID", (uint16(Lua_NPC::*)(void))&Lua_NPC::GetLDoNTrapSpellID) .def("GetNPCFactionID", (int(Lua_NPC::*)(void))&Lua_NPC::GetNPCFactionID) .def("GetNPCHate", (int64(Lua_NPC::*)(Lua_Mob))&Lua_NPC::GetNPCHate) .def("GetNPCSpellsID", (int(Lua_NPC::*)(void))&Lua_NPC::GetNPCSpellsID) @@ -784,10 +863,14 @@ luabind::scope lua_register_npc() { .def("HasItem", (bool(Lua_NPC::*)(uint32))&Lua_NPC::HasItem) .def("IsAnimal", (bool(Lua_NPC::*)(void))&Lua_NPC::IsAnimal) .def("IsGuarding", (bool(Lua_NPC::*)(void))&Lua_NPC::IsGuarding) + .def("IsLDoNLocked", (bool(Lua_NPC::*)(void))&Lua_NPC::IsLDoNLocked) + .def("IsLDoNTrapped", (bool(Lua_NPC::*)(void))&Lua_NPC::IsLDoNTrapped) + .def("IsLDoNTrapDetected", (bool(Lua_NPC::*)(void))&Lua_NPC::IsLDoNTrapDetected) .def("IsOnHatelist", (bool(Lua_NPC::*)(Lua_Mob))&Lua_NPC::IsOnHatelist) .def("IsRaidTarget", (bool(Lua_NPC::*)(void))&Lua_NPC::IsRaidTarget) .def("IsRareSpawn", (bool(Lua_NPC::*)(void))&Lua_NPC::IsRareSpawn) .def("IsTaunting", (bool(Lua_NPC::*)(void))&Lua_NPC::IsTaunting) + .def("IsUnderwaterOnly", (bool(Lua_NPC::*)(void))&Lua_NPC::IsUnderwaterOnly) .def("MerchantCloseShop", (void(Lua_NPC::*)(void))&Lua_NPC::MerchantCloseShop) .def("MerchantOpenShop", (void(Lua_NPC::*)(void))&Lua_NPC::MerchantOpenShop) .def("ModifyNPCStat", (void(Lua_NPC::*)(std::string,std::string))&Lua_NPC::ModifyNPCStat) @@ -808,6 +891,7 @@ luabind::scope lua_register_npc() { .def("SaveGuardSpot", (void(Lua_NPC::*)(bool))&Lua_NPC::SaveGuardSpot) .def("SaveGuardSpot", (void(Lua_NPC::*)(float,float,float,float))&Lua_NPC::SaveGuardSpot) .def("ScaleNPC", (void(Lua_NPC::*)(uint8))&Lua_NPC::ScaleNPC) + .def("ScaleNPC", (void(Lua_NPC::*)(uint8,bool))&Lua_NPC::ScaleNPC) .def("SendPayload", (void(Lua_NPC::*)(int))&Lua_NPC::SendPayload) .def("SendPayload", (void(Lua_NPC::*)(int,std::string))&Lua_NPC::SendPayload) .def("SetCopper", (void(Lua_NPC::*)(uint32))&Lua_NPC::SetCopper) @@ -817,6 +901,12 @@ luabind::scope lua_register_npc() { .def("SetGold", (void(Lua_NPC::*)(uint32))&Lua_NPC::SetGold) .def("SetGrid", (void(Lua_NPC::*)(int))&Lua_NPC::SetGrid) .def("SetKeepsSoldItems", (void(Lua_NPC::*)(bool))&Lua_NPC::SetKeepsSoldItems) + .def("SetLDoNLocked", (void(Lua_NPC::*)(bool))&Lua_NPC::SetLDoNLocked) + .def("SetLDoNLockedSkill", (void(Lua_NPC::*)(uint16))&Lua_NPC::SetLDoNLockedSkill) + .def("SetLDoNTrapped", (void(Lua_NPC::*)(bool))&Lua_NPC::SetLDoNTrapped) + .def("SetLDoNTrapDetected", (void(Lua_NPC::*)(bool))&Lua_NPC::SetLDoNTrapDetected) + .def("SetLDoNTrapSpellID", (void(Lua_NPC::*)(uint16))&Lua_NPC::SetLDoNTrapSpellID) + .def("SetLDoNTrapType", (void(Lua_NPC::*)(uint8))&Lua_NPC::SetLDoNTrapType) .def("SetNPCFactionID", (void(Lua_NPC::*)(int))&Lua_NPC::SetNPCFactionID) .def("SetPetSpellID", (void(Lua_NPC::*)(int))&Lua_NPC::SetPetSpellID) .def("SetPlatinum", (void(Lua_NPC::*)(uint32))&Lua_NPC::SetPlatinum) diff --git a/zone/lua_npc.h b/zone/lua_npc.h index ad42c5cee..9d0f959aa 100644 --- a/zone/lua_npc.h +++ b/zone/lua_npc.h @@ -141,7 +141,6 @@ public: void SetSimpleRoamBox(float box_size, float move_distance, int move_delay); void RecalculateSkills(); void ReloadSpells(); - void ScaleNPC(uint8 npc_level); bool IsRaidTarget(); bool IsRareSpawn(); void ChangeLastName(std::string last_name); @@ -161,6 +160,22 @@ public: void SendPayload(int payload_id, std::string payload_value); bool GetKeepsSoldItems(); void SetKeepsSoldItems(bool keeps_sold_items); + bool IsLDoNTrapped(); + void SetLDoNTrapped(bool is_trapped); + uint8 GetLDoNTrapType(); + void SetLDoNTrapType(uint8 trap_type); + uint16 GetLDoNTrapSpellID(); + void SetLDoNTrapSpellID(uint16 spell_id); + bool IsLDoNLocked(); + void SetLDoNLocked(bool is_locked); + uint16 GetLDoNLockedSkill(); + void SetLDoNLockedSkill(uint16 skill_value); + bool IsLDoNTrapDetected(); + void SetLDoNTrapDetected(bool is_detected); + void ScaleNPC(uint8 npc_level); + void ScaleNPC(uint8 npc_level, bool override_special_abilities); + bool IsUnderwaterOnly(); + bool HasSpecialAbilities(); }; #endif diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index bbd7aa33d..97b29b1b0 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -148,6 +148,8 @@ const char *LuaEvents[_LargestEventID] = { "event_task_before_update", "event_aa_buy", "event_aa_gain", + "event_aa_exp_gain", + "event_exp_gain", "event_payload", "event_level_down", "event_gm_command", @@ -156,6 +158,14 @@ const char *LuaEvents[_LargestEventID] = { "event_bot_create", "event_augment_insert_client", "event_augment_remove_client", + "event_equip_item_bot", + "event_unequip_item_bot", + "event_damage_given", + "event_damage_taken", + "event_item_click_client", + "event_item_click_cast_client", + "event_destroy_item_client", + "event_drop_item_client" }; extern Zone *zone; @@ -171,143 +181,159 @@ std::map lua_encounters_loaded; std::map lua_encounters; LuaParser::LuaParser() { - for(int i = 0; i < _LargestEventID; ++i) { - NPCArgumentDispatch[i] = handle_npc_null; - PlayerArgumentDispatch[i] = handle_player_null; - ItemArgumentDispatch[i] = handle_item_null; - SpellArgumentDispatch[i] = handle_spell_null; + for (int i = 0; i < _LargestEventID; ++i) { + NPCArgumentDispatch[i] = handle_npc_null; + PlayerArgumentDispatch[i] = handle_player_null; + ItemArgumentDispatch[i] = handle_item_null; + SpellArgumentDispatch[i] = handle_spell_null; EncounterArgumentDispatch[i] = handle_encounter_null; - BotArgumentDispatch[i] = handle_bot_null; + BotArgumentDispatch[i] = handle_bot_null; } - NPCArgumentDispatch[EVENT_SAY] = handle_npc_event_say; - NPCArgumentDispatch[EVENT_AGGRO_SAY] = handle_npc_event_say; - NPCArgumentDispatch[EVENT_PROXIMITY_SAY] = handle_npc_event_say; - NPCArgumentDispatch[EVENT_TRADE] = handle_npc_event_trade; - NPCArgumentDispatch[EVENT_HP] = handle_npc_event_hp; - NPCArgumentDispatch[EVENT_TARGET_CHANGE] = handle_npc_single_mob; - NPCArgumentDispatch[EVENT_CAST_ON] = handle_npc_cast; - NPCArgumentDispatch[EVENT_KILLED_MERIT] = handle_npc_single_client; - NPCArgumentDispatch[EVENT_SLAY] = handle_npc_single_mob; - NPCArgumentDispatch[EVENT_ENTER] = handle_npc_single_client; - NPCArgumentDispatch[EVENT_EXIT] = handle_npc_single_client; - NPCArgumentDispatch[EVENT_TASK_ACCEPTED] = handle_npc_task_accepted; - NPCArgumentDispatch[EVENT_POPUP_RESPONSE] = handle_npc_popup; + NPCArgumentDispatch[EVENT_SAY] = handle_npc_event_say; + NPCArgumentDispatch[EVENT_AGGRO_SAY] = handle_npc_event_say; + NPCArgumentDispatch[EVENT_PROXIMITY_SAY] = handle_npc_event_say; + NPCArgumentDispatch[EVENT_TRADE] = handle_npc_event_trade; + NPCArgumentDispatch[EVENT_HP] = handle_npc_event_hp; + NPCArgumentDispatch[EVENT_TARGET_CHANGE] = handle_npc_single_mob; + NPCArgumentDispatch[EVENT_CAST_ON] = handle_npc_cast; + NPCArgumentDispatch[EVENT_KILLED_MERIT] = handle_npc_single_client; + NPCArgumentDispatch[EVENT_SLAY] = handle_npc_single_mob; + NPCArgumentDispatch[EVENT_ENTER] = handle_npc_single_client; + NPCArgumentDispatch[EVENT_EXIT] = handle_npc_single_client; + NPCArgumentDispatch[EVENT_TASK_ACCEPTED] = handle_npc_task_accepted; + NPCArgumentDispatch[EVENT_POPUP_RESPONSE] = handle_npc_popup; NPCArgumentDispatch[EVENT_WAYPOINT_ARRIVE] = handle_npc_waypoint; NPCArgumentDispatch[EVENT_WAYPOINT_DEPART] = handle_npc_waypoint; - NPCArgumentDispatch[EVENT_HATE_LIST] = handle_npc_hate; - NPCArgumentDispatch[EVENT_COMBAT] = handle_npc_hate; - NPCArgumentDispatch[EVENT_SIGNAL] = handle_npc_signal; - NPCArgumentDispatch[EVENT_TIMER] = handle_npc_timer; - NPCArgumentDispatch[EVENT_DEATH] = handle_npc_death; - NPCArgumentDispatch[EVENT_DEATH_COMPLETE] = handle_npc_death; - NPCArgumentDispatch[EVENT_DEATH_ZONE] = handle_npc_death; - NPCArgumentDispatch[EVENT_CAST] = handle_npc_cast; - NPCArgumentDispatch[EVENT_CAST_BEGIN] = handle_npc_cast; - NPCArgumentDispatch[EVENT_FEIGN_DEATH] = handle_npc_single_client; - NPCArgumentDispatch[EVENT_ENTER_AREA] = handle_npc_area; - NPCArgumentDispatch[EVENT_LEAVE_AREA] = handle_npc_area; - NPCArgumentDispatch[EVENT_LOOT_ZONE] = handle_npc_loot_zone; - NPCArgumentDispatch[EVENT_SPAWN_ZONE] = handle_npc_spawn_zone; - NPCArgumentDispatch[EVENT_PAYLOAD] = handle_npc_payload; - NPCArgumentDispatch[EVENT_DESPAWN_ZONE] = handle_npc_despawn_zone; + NPCArgumentDispatch[EVENT_HATE_LIST] = handle_npc_hate; + NPCArgumentDispatch[EVENT_COMBAT] = handle_npc_hate; + NPCArgumentDispatch[EVENT_SIGNAL] = handle_npc_signal; + NPCArgumentDispatch[EVENT_TIMER] = handle_npc_timer; + NPCArgumentDispatch[EVENT_DEATH] = handle_npc_death; + NPCArgumentDispatch[EVENT_DEATH_COMPLETE] = handle_npc_death; + NPCArgumentDispatch[EVENT_DEATH_ZONE] = handle_npc_death; + NPCArgumentDispatch[EVENT_CAST] = handle_npc_cast; + NPCArgumentDispatch[EVENT_CAST_BEGIN] = handle_npc_cast; + NPCArgumentDispatch[EVENT_FEIGN_DEATH] = handle_npc_single_client; + NPCArgumentDispatch[EVENT_ENTER_AREA] = handle_npc_area; + NPCArgumentDispatch[EVENT_LEAVE_AREA] = handle_npc_area; + NPCArgumentDispatch[EVENT_LOOT_ZONE] = handle_npc_loot_zone; + NPCArgumentDispatch[EVENT_SPAWN_ZONE] = handle_npc_spawn_zone; + NPCArgumentDispatch[EVENT_PAYLOAD] = handle_npc_payload; + NPCArgumentDispatch[EVENT_DESPAWN_ZONE] = handle_npc_despawn_zone; + NPCArgumentDispatch[EVENT_DAMAGE_GIVEN] = handle_npc_damage; + NPCArgumentDispatch[EVENT_DAMAGE_TAKEN] = handle_npc_damage; - PlayerArgumentDispatch[EVENT_SAY] = handle_player_say; - PlayerArgumentDispatch[EVENT_ENVIRONMENTAL_DAMAGE] = handle_player_environmental_damage; - PlayerArgumentDispatch[EVENT_DEATH] = handle_player_death; - PlayerArgumentDispatch[EVENT_DEATH_COMPLETE] = handle_player_death; - PlayerArgumentDispatch[EVENT_TIMER] = handle_player_timer; - PlayerArgumentDispatch[EVENT_DISCOVER_ITEM] = handle_player_discover_item; - PlayerArgumentDispatch[EVENT_FISH_SUCCESS] = handle_player_fish_forage_success; - PlayerArgumentDispatch[EVENT_FORAGE_SUCCESS] = handle_player_fish_forage_success; - PlayerArgumentDispatch[EVENT_CLICK_OBJECT] = handle_player_click_object; - PlayerArgumentDispatch[EVENT_CLICK_DOOR] = handle_player_click_door; - PlayerArgumentDispatch[EVENT_SIGNAL] = handle_player_signal; - PlayerArgumentDispatch[EVENT_POPUP_RESPONSE] = handle_player_popup_response; - PlayerArgumentDispatch[EVENT_PLAYER_PICKUP] = handle_player_pick_up; - PlayerArgumentDispatch[EVENT_CAST] = handle_player_cast; - PlayerArgumentDispatch[EVENT_CAST_BEGIN] = handle_player_cast; - PlayerArgumentDispatch[EVENT_CAST_ON] = handle_player_cast; - PlayerArgumentDispatch[EVENT_TASK_FAIL] = handle_player_task_fail; - PlayerArgumentDispatch[EVENT_ZONE] = handle_player_zone; - PlayerArgumentDispatch[EVENT_DUEL_WIN] = handle_player_duel_win; - PlayerArgumentDispatch[EVENT_DUEL_LOSE] = handle_player_duel_loss; - PlayerArgumentDispatch[EVENT_LOOT] = handle_player_loot; - PlayerArgumentDispatch[EVENT_TASK_STAGE_COMPLETE] = handle_player_task_stage_complete; - PlayerArgumentDispatch[EVENT_TASK_COMPLETE] = handle_player_task_update; - PlayerArgumentDispatch[EVENT_TASK_UPDATE] = handle_player_task_update; - PlayerArgumentDispatch[EVENT_TASK_BEFORE_UPDATE] = handle_player_task_update; - PlayerArgumentDispatch[EVENT_COMMAND] = handle_player_command; - PlayerArgumentDispatch[EVENT_COMBINE_SUCCESS] = handle_player_combine; - PlayerArgumentDispatch[EVENT_COMBINE_FAILURE] = handle_player_combine; - PlayerArgumentDispatch[EVENT_FEIGN_DEATH] = handle_player_feign; - PlayerArgumentDispatch[EVENT_ENTER_AREA] = handle_player_area; - PlayerArgumentDispatch[EVENT_LEAVE_AREA] = handle_player_area; - PlayerArgumentDispatch[EVENT_RESPAWN] = handle_player_respawn; - PlayerArgumentDispatch[EVENT_UNHANDLED_OPCODE] = handle_player_packet; - PlayerArgumentDispatch[EVENT_USE_SKILL] = handle_player_use_skill; - PlayerArgumentDispatch[EVENT_TEST_BUFF] = handle_test_buff; - PlayerArgumentDispatch[EVENT_COMBINE_VALIDATE] = handle_player_combine_validate; - PlayerArgumentDispatch[EVENT_BOT_COMMAND] = handle_player_bot_command; - PlayerArgumentDispatch[EVENT_WARP] = handle_player_warp; - PlayerArgumentDispatch[EVENT_COMBINE] = handle_player_quest_combine; - PlayerArgumentDispatch[EVENT_CONSIDER] = handle_player_consider; - PlayerArgumentDispatch[EVENT_CONSIDER_CORPSE] = handle_player_consider_corpse; - PlayerArgumentDispatch[EVENT_EQUIP_ITEM_CLIENT] = handle_player_equip_item; - PlayerArgumentDispatch[EVENT_UNEQUIP_ITEM_CLIENT] = handle_player_equip_item; - PlayerArgumentDispatch[EVENT_SKILL_UP] = handle_player_skill_up; - PlayerArgumentDispatch[EVENT_LANGUAGE_SKILL_UP] = handle_player_skill_up; - PlayerArgumentDispatch[EVENT_ALT_CURRENCY_MERCHANT_BUY] = handle_player_alt_currency_merchant; + PlayerArgumentDispatch[EVENT_SAY] = handle_player_say; + PlayerArgumentDispatch[EVENT_ENVIRONMENTAL_DAMAGE] = handle_player_environmental_damage; + PlayerArgumentDispatch[EVENT_DEATH] = handle_player_death; + PlayerArgumentDispatch[EVENT_DEATH_COMPLETE] = handle_player_death; + PlayerArgumentDispatch[EVENT_TIMER] = handle_player_timer; + PlayerArgumentDispatch[EVENT_DISCOVER_ITEM] = handle_player_discover_item; + PlayerArgumentDispatch[EVENT_FISH_SUCCESS] = handle_player_fish_forage_success; + PlayerArgumentDispatch[EVENT_FORAGE_SUCCESS] = handle_player_fish_forage_success; + PlayerArgumentDispatch[EVENT_CLICK_OBJECT] = handle_player_click_object; + PlayerArgumentDispatch[EVENT_CLICK_DOOR] = handle_player_click_door; + PlayerArgumentDispatch[EVENT_SIGNAL] = handle_player_signal; + PlayerArgumentDispatch[EVENT_POPUP_RESPONSE] = handle_player_popup_response; + PlayerArgumentDispatch[EVENT_PLAYER_PICKUP] = handle_player_pick_up; + PlayerArgumentDispatch[EVENT_CAST] = handle_player_cast; + PlayerArgumentDispatch[EVENT_CAST_BEGIN] = handle_player_cast; + PlayerArgumentDispatch[EVENT_CAST_ON] = handle_player_cast; + PlayerArgumentDispatch[EVENT_TASK_FAIL] = handle_player_task_fail; + PlayerArgumentDispatch[EVENT_ZONE] = handle_player_zone; + PlayerArgumentDispatch[EVENT_DUEL_WIN] = handle_player_duel_win; + PlayerArgumentDispatch[EVENT_DUEL_LOSE] = handle_player_duel_loss; + PlayerArgumentDispatch[EVENT_LOOT] = handle_player_loot; + PlayerArgumentDispatch[EVENT_TASK_STAGE_COMPLETE] = handle_player_task_stage_complete; + PlayerArgumentDispatch[EVENT_TASK_ACCEPTED] = handle_player_task_accepted; + PlayerArgumentDispatch[EVENT_TASK_COMPLETE] = handle_player_task_update; + PlayerArgumentDispatch[EVENT_TASK_UPDATE] = handle_player_task_update; + PlayerArgumentDispatch[EVENT_TASK_BEFORE_UPDATE] = handle_player_task_update; + PlayerArgumentDispatch[EVENT_COMMAND] = handle_player_command; + PlayerArgumentDispatch[EVENT_COMBINE_SUCCESS] = handle_player_combine; + PlayerArgumentDispatch[EVENT_COMBINE_FAILURE] = handle_player_combine; + PlayerArgumentDispatch[EVENT_FEIGN_DEATH] = handle_player_feign; + PlayerArgumentDispatch[EVENT_ENTER_AREA] = handle_player_area; + PlayerArgumentDispatch[EVENT_LEAVE_AREA] = handle_player_area; + PlayerArgumentDispatch[EVENT_RESPAWN] = handle_player_respawn; + PlayerArgumentDispatch[EVENT_UNHANDLED_OPCODE] = handle_player_packet; + PlayerArgumentDispatch[EVENT_USE_SKILL] = handle_player_use_skill; + PlayerArgumentDispatch[EVENT_TEST_BUFF] = handle_test_buff; + PlayerArgumentDispatch[EVENT_COMBINE_VALIDATE] = handle_player_combine_validate; + PlayerArgumentDispatch[EVENT_BOT_COMMAND] = handle_player_bot_command; + PlayerArgumentDispatch[EVENT_WARP] = handle_player_warp; + PlayerArgumentDispatch[EVENT_COMBINE] = handle_player_quest_combine; + PlayerArgumentDispatch[EVENT_CONSIDER] = handle_player_consider; + PlayerArgumentDispatch[EVENT_CONSIDER_CORPSE] = handle_player_consider_corpse; + PlayerArgumentDispatch[EVENT_EQUIP_ITEM_CLIENT] = handle_player_equip_item; + PlayerArgumentDispatch[EVENT_UNEQUIP_ITEM_CLIENT] = handle_player_equip_item; + PlayerArgumentDispatch[EVENT_SKILL_UP] = handle_player_skill_up; + PlayerArgumentDispatch[EVENT_LANGUAGE_SKILL_UP] = handle_player_skill_up; + PlayerArgumentDispatch[EVENT_ALT_CURRENCY_MERCHANT_BUY] = handle_player_alt_currency_merchant; PlayerArgumentDispatch[EVENT_ALT_CURRENCY_MERCHANT_SELL] = handle_player_alt_currency_merchant; - PlayerArgumentDispatch[EVENT_MERCHANT_BUY] = handle_player_merchant; - PlayerArgumentDispatch[EVENT_MERCHANT_SELL] = handle_player_merchant; - PlayerArgumentDispatch[EVENT_INSPECT] = handle_player_inspect; - PlayerArgumentDispatch[EVENT_AA_BUY] = handle_player_aa_buy; - PlayerArgumentDispatch[EVENT_AA_GAIN] = handle_player_aa_gain; - PlayerArgumentDispatch[EVENT_PAYLOAD] = handle_player_payload; - PlayerArgumentDispatch[EVENT_LEVEL_UP] = handle_player_level_up; - PlayerArgumentDispatch[EVENT_LEVEL_DOWN] = handle_player_level_down; - PlayerArgumentDispatch[EVENT_GM_COMMAND] = handle_player_gm_command; - PlayerArgumentDispatch[EVENT_BOT_CREATE] = handle_player_bot_create; - PlayerArgumentDispatch[EVENT_AUGMENT_INSERT_CLIENT] = handle_player_augment_insert; - PlayerArgumentDispatch[EVENT_AUGMENT_REMOVE_CLIENT] = handle_player_augment_remove; + PlayerArgumentDispatch[EVENT_MERCHANT_BUY] = handle_player_merchant; + PlayerArgumentDispatch[EVENT_MERCHANT_SELL] = handle_player_merchant; + PlayerArgumentDispatch[EVENT_INSPECT] = handle_player_inspect; + PlayerArgumentDispatch[EVENT_AA_BUY] = handle_player_aa_buy; + PlayerArgumentDispatch[EVENT_AA_GAIN] = handle_player_aa_gain; + PlayerArgumentDispatch[EVENT_AA_EXP_GAIN] = handle_player_aa_exp_gain; + PlayerArgumentDispatch[EVENT_EXP_GAIN] = handle_player_exp_gain; + PlayerArgumentDispatch[EVENT_PAYLOAD] = handle_player_payload; + PlayerArgumentDispatch[EVENT_LEVEL_UP] = handle_player_level_up; + PlayerArgumentDispatch[EVENT_LEVEL_DOWN] = handle_player_level_down; + PlayerArgumentDispatch[EVENT_GM_COMMAND] = handle_player_gm_command; + PlayerArgumentDispatch[EVENT_BOT_CREATE] = handle_player_bot_create; + PlayerArgumentDispatch[EVENT_AUGMENT_INSERT_CLIENT] = handle_player_augment_insert; + PlayerArgumentDispatch[EVENT_AUGMENT_REMOVE_CLIENT] = handle_player_augment_remove; + PlayerArgumentDispatch[EVENT_DAMAGE_GIVEN] = handle_player_damage; + PlayerArgumentDispatch[EVENT_DAMAGE_TAKEN] = handle_player_damage; + PlayerArgumentDispatch[EVENT_ITEM_CLICK_CAST_CLIENT] = handle_player_item_click; + PlayerArgumentDispatch[EVENT_ITEM_CLICK_CLIENT] = handle_player_item_click; + PlayerArgumentDispatch[EVENT_DESTROY_ITEM_CLIENT] = handle_player_destroy_item; + PlayerArgumentDispatch[EVENT_TARGET_CHANGE] = handle_player_target_change; + PlayerArgumentDispatch[EVENT_DROP_ITEM_CLIENT] = handle_player_drop_item; - ItemArgumentDispatch[EVENT_ITEM_CLICK] = handle_item_click; + ItemArgumentDispatch[EVENT_ITEM_CLICK] = handle_item_click; ItemArgumentDispatch[EVENT_ITEM_CLICK_CAST] = handle_item_click; - ItemArgumentDispatch[EVENT_TIMER] = handle_item_timer; - ItemArgumentDispatch[EVENT_WEAPON_PROC] = handle_item_proc; - ItemArgumentDispatch[EVENT_LOOT] = handle_item_loot; - ItemArgumentDispatch[EVENT_EQUIP_ITEM] = handle_item_equip; - ItemArgumentDispatch[EVENT_UNEQUIP_ITEM] = handle_item_equip; - ItemArgumentDispatch[EVENT_AUGMENT_ITEM] = handle_item_augment; - ItemArgumentDispatch[EVENT_UNAUGMENT_ITEM] = handle_item_augment; - ItemArgumentDispatch[EVENT_AUGMENT_INSERT] = handle_item_augment_insert; - ItemArgumentDispatch[EVENT_AUGMENT_REMOVE] = handle_item_augment_remove; + ItemArgumentDispatch[EVENT_TIMER] = handle_item_timer; + ItemArgumentDispatch[EVENT_WEAPON_PROC] = handle_item_proc; + ItemArgumentDispatch[EVENT_LOOT] = handle_item_loot; + ItemArgumentDispatch[EVENT_EQUIP_ITEM] = handle_item_equip; + ItemArgumentDispatch[EVENT_UNEQUIP_ITEM] = handle_item_equip; + ItemArgumentDispatch[EVENT_AUGMENT_ITEM] = handle_item_augment; + ItemArgumentDispatch[EVENT_UNAUGMENT_ITEM] = handle_item_augment; + ItemArgumentDispatch[EVENT_AUGMENT_INSERT] = handle_item_augment_insert; + ItemArgumentDispatch[EVENT_AUGMENT_REMOVE] = handle_item_augment_remove; - SpellArgumentDispatch[EVENT_SPELL_EFFECT_CLIENT] = handle_spell_event; - SpellArgumentDispatch[EVENT_SPELL_EFFECT_BUFF_TIC_CLIENT] = handle_spell_event; - SpellArgumentDispatch[EVENT_SPELL_FADE] = handle_spell_event; + SpellArgumentDispatch[EVENT_SPELL_EFFECT_CLIENT] = handle_spell_event; + SpellArgumentDispatch[EVENT_SPELL_EFFECT_BUFF_TIC_CLIENT] = handle_spell_event; + SpellArgumentDispatch[EVENT_SPELL_FADE] = handle_spell_event; SpellArgumentDispatch[EVENT_SPELL_EFFECT_TRANSLOCATE_COMPLETE] = handle_translocate_finish; - EncounterArgumentDispatch[EVENT_TIMER] = handle_encounter_timer; - EncounterArgumentDispatch[EVENT_ENCOUNTER_LOAD] = handle_encounter_load; + EncounterArgumentDispatch[EVENT_TIMER] = handle_encounter_timer; + EncounterArgumentDispatch[EVENT_ENCOUNTER_LOAD] = handle_encounter_load; EncounterArgumentDispatch[EVENT_ENCOUNTER_UNLOAD] = handle_encounter_unload; - BotArgumentDispatch[EVENT_CAST] = handle_bot_cast; - BotArgumentDispatch[EVENT_CAST_BEGIN] = handle_bot_cast; - BotArgumentDispatch[EVENT_CAST_ON] = handle_bot_cast; - BotArgumentDispatch[EVENT_COMBAT] = handle_bot_combat; - BotArgumentDispatch[EVENT_DEATH] = handle_bot_death; - BotArgumentDispatch[EVENT_DEATH_COMPLETE] = handle_bot_death; - BotArgumentDispatch[EVENT_POPUP_RESPONSE] = handle_bot_popup_response; - BotArgumentDispatch[EVENT_SAY] = handle_bot_say; - BotArgumentDispatch[EVENT_SIGNAL] = handle_bot_signal; - BotArgumentDispatch[EVENT_SLAY] = handle_bot_slay; - BotArgumentDispatch[EVENT_TARGET_CHANGE] = handle_bot_target_change; - BotArgumentDispatch[EVENT_TIMER] = handle_bot_timer; - BotArgumentDispatch[EVENT_TRADE] = handle_bot_trade; - BotArgumentDispatch[EVENT_USE_SKILL] = handle_bot_use_skill; - BotArgumentDispatch[EVENT_PAYLOAD] = handle_bot_payload; + BotArgumentDispatch[EVENT_CAST] = handle_bot_cast; + BotArgumentDispatch[EVENT_CAST_BEGIN] = handle_bot_cast; + BotArgumentDispatch[EVENT_CAST_ON] = handle_bot_cast; + BotArgumentDispatch[EVENT_COMBAT] = handle_bot_combat; + BotArgumentDispatch[EVENT_DEATH] = handle_bot_death; + BotArgumentDispatch[EVENT_DEATH_COMPLETE] = handle_bot_death; + BotArgumentDispatch[EVENT_POPUP_RESPONSE] = handle_bot_popup_response; + BotArgumentDispatch[EVENT_SAY] = handle_bot_say; + BotArgumentDispatch[EVENT_SIGNAL] = handle_bot_signal; + BotArgumentDispatch[EVENT_SLAY] = handle_bot_slay; + BotArgumentDispatch[EVENT_TARGET_CHANGE] = handle_bot_target_change; + BotArgumentDispatch[EVENT_TIMER] = handle_bot_timer; + BotArgumentDispatch[EVENT_TRADE] = handle_bot_trade; + BotArgumentDispatch[EVENT_USE_SKILL] = handle_bot_use_skill; + BotArgumentDispatch[EVENT_PAYLOAD] = handle_bot_payload; + BotArgumentDispatch[EVENT_EQUIP_ITEM_BOT] = handle_bot_equip_item; + BotArgumentDispatch[EVENT_UNEQUIP_ITEM_BOT] = handle_bot_equip_item; + BotArgumentDispatch[EVENT_DAMAGE_GIVEN] = handle_bot_damage; + BotArgumentDispatch[EVENT_DAMAGE_TAKEN] = handle_bot_damage; #endif L = nullptr; diff --git a/zone/lua_parser_events.cpp b/zone/lua_parser_events.cpp index f12f11159..88b45ff95 100644 --- a/zone/lua_parser_events.cpp +++ b/zone/lua_parser_events.cpp @@ -59,7 +59,7 @@ void handle_npc_event_trade( uint32 extra_data, std::vector *extra_pointers ) { - Lua_Client l_client(reinterpret_cast(init)); + Lua_Client l_client(reinterpret_cast(init)); luabind::adl::object l_client_o = luabind::adl::object(L, l_client); l_client_o.push(L); lua_setfield(L, -2, "other"); @@ -82,29 +82,33 @@ void handle_npc_event_trade( } auto money_string = fmt::format("platinum.{}", npc_id); - uint32 money_value = !parse->GetVar(money_string).empty() ? std::stoul(parse->GetVar(money_string)) : 0; + uint32 money_value = !parse->GetVar(money_string).empty() ? Strings::ToUnsignedInt(parse->GetVar(money_string)) : 0; lua_pushinteger(L, money_value); lua_setfield(L, -2, "platinum"); money_string = fmt::format("gold.{}", npc_id); - money_value = !parse->GetVar(money_string).empty() ? std::stoul(parse->GetVar(money_string)) : 0; + money_value = !parse->GetVar(money_string).empty() ? Strings::ToUnsignedInt(parse->GetVar(money_string)) : 0; lua_pushinteger(L, money_value); lua_setfield(L, -2, "gold"); money_string = fmt::format("silver.{}", npc_id); - money_value = !parse->GetVar(money_string).empty() ? std::stoul(parse->GetVar(money_string)) : 0; + money_value = !parse->GetVar(money_string).empty() ? Strings::ToUnsignedInt(parse->GetVar(money_string)) : 0; lua_pushinteger(L, money_value); lua_setfield(L, -2, "silver"); money_string = fmt::format("copper.{}", npc_id); - money_value = !parse->GetVar(money_string).empty() ? std::stoul(parse->GetVar(money_string)) : 0; + money_value = !parse->GetVar(money_string).empty() ? Strings::ToUnsignedInt(parse->GetVar(money_string)) : 0; lua_pushinteger(L, money_value); lua_setfield(L, -2, "copper"); + // set a reference to the client inside of the trade object as well for plugins to process + l_client_o.push(L); + lua_setfield(L, -2, "other"); + lua_setfield(L, -2, "trade"); } @@ -120,12 +124,12 @@ void handle_npc_event_hp( if(extra_data == 1) { lua_pushinteger(L, -1); lua_setfield(L, -2, "hp_event"); - lua_pushinteger(L, std::stoi(data)); + lua_pushinteger(L, Strings::ToInt(data)); lua_setfield(L, -2, "inc_hp_event"); } else { - lua_pushinteger(L, std::stoi(data)); + lua_pushinteger(L, Strings::ToInt(data)); lua_setfield(L, -2, "hp_event"); lua_pushinteger(L, -1); lua_setfield(L, -2, "inc_hp_event"); @@ -191,7 +195,7 @@ void handle_npc_task_accepted( l_client_o.push(L); lua_setfield(L, -2, "other"); - lua_pushinteger(L, std::stoi(data)); + lua_pushinteger(L, Strings::ToInt(data)); lua_setfield(L, -2, "task_id"); } @@ -209,7 +213,7 @@ void handle_npc_popup( l_mob_o.push(L); lua_setfield(L, -2, "other"); - lua_pushinteger(L, std::stoi(data)); + lua_pushinteger(L, Strings::ToInt(data)); lua_setfield(L, -2, "popup_id"); } @@ -227,7 +231,7 @@ void handle_npc_waypoint( l_mob_o.push(L); lua_setfield(L, -2, "other"); - lua_pushinteger(L, std::stoi(data)); + lua_pushinteger(L, Strings::ToInt(data, -1)); lua_setfield(L, -2, "wp"); } @@ -245,7 +249,7 @@ void handle_npc_hate( l_mob_o.push(L); lua_setfield(L, -2, "other"); - lua_pushboolean(L, std::stoi(data) == 0 ? false : true); + lua_pushboolean(L, Strings::ToInt(data) == 0 ? false : true); lua_setfield(L, -2, "joined"); } @@ -259,7 +263,7 @@ void handle_npc_signal( uint32 extra_data, std::vector *extra_pointers ) { - lua_pushinteger(L, std::stoi(data)); + lua_pushinteger(L, Strings::ToInt(data)); lua_setfield(L, -2, "signal"); } @@ -274,7 +278,7 @@ void handle_npc_payload( ) { Seperator sep(data.c_str()); - lua_pushinteger(L, std::stoi(sep.arg[0])); + lua_pushinteger(L, Strings::ToInt(sep.arg[0])); lua_setfield(L, -2, "payload_id"); lua_pushstring(L, sep.argplus[1]); @@ -309,13 +313,13 @@ void handle_npc_death( lua_setfield(L, -2, "other"); Seperator sep(data.c_str()); - lua_pushinteger(L, std::stoi(sep.arg[0])); + lua_pushinteger(L, Strings::ToInt(sep.arg[0])); lua_setfield(L, -2, "killer_id"); - lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_pushinteger(L, Strings::ToInt(sep.arg[1])); lua_setfield(L, -2, "damage"); - int spell_id = std::stoi(sep.arg[2]); + int spell_id = Strings::ToInt(sep.arg[2]); if(IsValidSpell(spell_id)) { Lua_Spell l_spell(&spells[spell_id]); luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); @@ -328,7 +332,7 @@ void handle_npc_death( lua_setfield(L, -2, "spell"); } - lua_pushinteger(L, std::stoi(sep.arg[3])); + lua_pushinteger(L, Strings::ToInt(sep.arg[3])); lua_setfield(L, -2, "skill_id"); if (extra_pointers && extra_pointers->size() >= 1) @@ -357,7 +361,7 @@ void handle_npc_cast( uint32 extra_data, std::vector *extra_pointers ) { - int spell_id = std::stoi(data); + int spell_id = Strings::ToInt(data); if(IsValidSpell(spell_id)) { Lua_Spell l_spell(&spells[spell_id]); luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); @@ -453,6 +457,50 @@ void handle_npc_despawn_zone( lua_setfield(L, -2, "other"); } +void handle_npc_damage( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob* init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Seperator sep(data.c_str()); + + lua_pushnumber(L, Strings::ToUnsignedInt(sep.arg[0])); + lua_setfield(L, -2, "entity_id"); + + lua_pushnumber(L, Strings::ToBigInt(sep.arg[1])); + lua_setfield(L, -2, "damage"); + + lua_pushnumber(L, Strings::ToInt(sep.arg[2])); + lua_setfield(L, -2, "spell_id"); + + lua_pushnumber(L, Strings::ToInt(sep.arg[3])); + lua_setfield(L, -2, "skill_id"); + + lua_pushboolean(L, Strings::ToInt(sep.arg[4]) == 0 ? false : true); + lua_setfield(L, -2, "is_damage_shield"); + + lua_pushboolean(L, Strings::ToInt(sep.arg[5]) == 0 ? false : true); + lua_setfield(L, -2, "is_avoidable"); + + lua_pushnumber(L, Strings::ToInt(sep.arg[6])); + lua_setfield(L, -2, "buff_slot"); + + lua_pushboolean(L, Strings::ToInt(sep.arg[7]) == 0 ? false : true); + lua_setfield(L, -2, "is_buff_tic"); + + lua_pushnumber(L, Strings::ToInt(sep.arg[8])); + lua_setfield(L, -2, "special_attack"); + + Lua_Mob l_mob(init); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); + l_mob_o.push(L); + lua_setfield(L, -2, "other"); +} + // Player void handle_player_say( QuestInterface *parse, @@ -478,13 +526,13 @@ void handle_player_environmental_damage( std::vector *extra_pointers ) { Seperator sep(data.c_str()); - lua_pushinteger(L, std::stoi(sep.arg[0])); + lua_pushinteger(L, Strings::ToInt(sep.arg[0])); lua_setfield(L, -2, "env_damage"); - lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_pushinteger(L, Strings::ToInt(sep.arg[1])); lua_setfield(L, -2, "env_damage_type"); - lua_pushinteger(L, std::stoi(sep.arg[2])); + lua_pushinteger(L, Strings::ToInt(sep.arg[2])); lua_setfield(L, -2, "env_final_damage"); } @@ -498,19 +546,19 @@ void handle_player_death( ) { Seperator sep(data.c_str()); - Mob *o = entity_list.GetMobID(std::stoi(sep.arg[0])); + Mob *o = entity_list.GetMobID(Strings::ToInt(sep.arg[0])); Lua_Mob l_mob(o); luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); l_mob_o.push(L); lua_setfield(L, -2, "other"); - lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_pushinteger(L, Strings::ToInt(sep.arg[1])); lua_setfield(L, -2, "killer_id"); - lua_pushinteger(L, std::stoi(sep.arg[2])); + lua_pushinteger(L, Strings::ToInt(sep.arg[2])); lua_setfield(L, -2, "damage"); - int spell_id = std::stoi(sep.arg[3]); + int spell_id = Strings::ToInt(sep.arg[3]); if(IsValidSpell(spell_id)) { Lua_Spell l_spell(&spells[spell_id]); luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); @@ -523,7 +571,7 @@ void handle_player_death( lua_setfield(L, -2, "spell"); } - lua_pushinteger(L, std::stoi(sep.arg[4])); + lua_pushinteger(L, Strings::ToInt(sep.arg[4])); lua_setfield(L, -2, "skill"); } @@ -611,7 +659,7 @@ void handle_player_signal( uint32 extra_data, std::vector *extra_pointers ) { - lua_pushinteger(L, std::stoi(data)); + lua_pushinteger(L, Strings::ToInt(data)); lua_setfield(L, -2, "signal"); } @@ -625,7 +673,7 @@ void handle_player_payload( ) { Seperator sep(data.c_str()); - lua_pushinteger(L, std::stoi(sep.arg[0])); + lua_pushinteger(L, Strings::ToInt(sep.arg[0])); lua_setfield(L, -2, "payload_id"); lua_pushstring(L, sep.argplus[1]); @@ -640,7 +688,7 @@ void handle_player_popup_response( uint32 extra_data, std::vector *extra_pointers ) { - lua_pushinteger(L, std::stoi(data)); + lua_pushinteger(L, Strings::ToInt(data)); lua_setfield(L, -2, "popup_id"); } @@ -668,7 +716,7 @@ void handle_player_cast( ) { Seperator sep(data.c_str()); - int spell_id = std::stoi(sep.arg[0]); + int spell_id = Strings::ToInt(sep.arg[0]); if(IsValidSpell(spell_id)) { Lua_Spell l_spell(&spells[spell_id]); luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); @@ -681,10 +729,10 @@ void handle_player_cast( lua_setfield(L, -2, "spell"); - lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_pushinteger(L, Strings::ToInt(sep.arg[1])); lua_setfield(L, -2, "caster_id"); - lua_pushinteger(L, std::stoi(sep.arg[2])); + lua_pushinteger(L, Strings::ToInt(sep.arg[2])); lua_setfield(L, -2, "caster_level"); } @@ -696,7 +744,7 @@ void handle_player_task_fail( uint32 extra_data, std::vector *extra_pointers ) { - lua_pushinteger(L, std::stoi(data)); + lua_pushinteger(L, Strings::ToInt(data)); lua_setfield(L, -2, "task_id"); } @@ -710,22 +758,22 @@ void handle_player_zone( ) { Seperator sep(data.c_str()); - lua_pushinteger(L, std::stoi(sep.arg[0])); + lua_pushinteger(L, Strings::ToInt(sep.arg[0])); lua_setfield(L, -2, "from_zone_id"); - lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_pushinteger(L, Strings::ToInt(sep.arg[1])); lua_setfield(L, -2, "from_instance_id"); - lua_pushinteger(L, std::stoi(sep.arg[2])); + lua_pushinteger(L, Strings::ToInt(sep.arg[2])); lua_setfield(L, -2, "from_instance_version"); - lua_pushinteger(L, std::stoi(sep.arg[3])); + lua_pushinteger(L, Strings::ToInt(sep.arg[3])); lua_setfield(L, -2, "zone_id"); - lua_pushinteger(L, std::stoi(sep.arg[4])); + lua_pushinteger(L, Strings::ToInt(sep.arg[4])); lua_setfield(L, -2, "instance_id"); - lua_pushinteger(L, std::stoi(sep.arg[5])); + lua_pushinteger(L, Strings::ToInt(sep.arg[5])); lua_setfield(L, -2, "instance_version"); } @@ -785,13 +833,25 @@ void handle_player_task_stage_complete( std::vector *extra_pointers ) { Seperator sep(data.c_str()); - lua_pushinteger(L, std::stoi(sep.arg[0])); + lua_pushinteger(L, Strings::ToInt(sep.arg[0])); lua_setfield(L, -2, "task_id"); - lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_pushinteger(L, Strings::ToInt(sep.arg[1])); lua_setfield(L, -2, "activity_id"); } +void handle_player_task_accepted( + QuestInterface* parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector* extra_pointers +) { + lua_pushinteger(L, Strings::ToInt(data)); + lua_setfield(L, -2, "task_id"); +} + void handle_player_task_update( QuestInterface *parse, lua_State* L, @@ -801,13 +861,13 @@ void handle_player_task_update( std::vector *extra_pointers ) { Seperator sep(data.c_str()); - lua_pushinteger(L, std::stoi(sep.arg[0])); + lua_pushinteger(L, Strings::ToInt(sep.arg[0])); lua_setfield(L, -2, "count"); - lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_pushinteger(L, Strings::ToInt(sep.arg[1])); lua_setfield(L, -2, "activity_id"); - lua_pushinteger(L, std::stoi(sep.arg[2])); + lua_pushinteger(L, Strings::ToInt(sep.arg[2])); lua_setfield(L, -2, "task_id"); } @@ -888,7 +948,7 @@ void handle_player_respawn( uint32 extra_data, std::vector *extra_pointers ) { - lua_pushinteger(L, std::stoi(data)); + lua_pushinteger(L, Strings::ToInt(data)); lua_setfield(L, -2, "option"); lua_pushboolean(L, extra_data == 1 ? true : false); @@ -931,10 +991,10 @@ void handle_player_use_skill( std::vector *extra_pointers ) { Seperator sep(data.c_str()); - lua_pushinteger(L, std::stoi(sep.arg[0])); + lua_pushinteger(L, Strings::ToInt(sep.arg[0])); lua_setfield(L, -2, "skill_id"); - lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_pushinteger(L, Strings::ToInt(sep.arg[1])); lua_setfield(L, -2, "skill_level"); } @@ -966,10 +1026,10 @@ void handle_player_combine_validate( int zone_id = -1; int tradeskill_id = -1; if (strcmp(sep.arg[0], "check_zone") == 0) { - zone_id = std::stoi(sep.arg[1]); + zone_id = Strings::ToInt(sep.arg[1]); } else if (strcmp(sep.arg[0], "check_tradeskill") == 0) { - tradeskill_id = std::stoi(sep.arg[1]); + tradeskill_id = Strings::ToInt(sep.arg[1]); } lua_pushinteger(L, zone_id); @@ -1013,13 +1073,13 @@ void handle_player_warp( std::vector *extra_pointers ) { Seperator sep(data.c_str()); - lua_pushnumber(L, std::stof(sep.arg[0])); + lua_pushnumber(L, Strings::ToFloat(sep.arg[0])); lua_setfield(L, -2, "from_x"); - lua_pushnumber(L, std::stof(sep.arg[1])); + lua_pushnumber(L, Strings::ToFloat(sep.arg[1])); lua_setfield(L, -2, "from_y"); - lua_pushnumber(L, std::stof(sep.arg[2])); + lua_pushnumber(L, Strings::ToFloat(sep.arg[2])); lua_setfield(L, -2, "from_z"); } @@ -1031,7 +1091,7 @@ void handle_player_quest_combine( uint32 extra_data, std::vector *extra_pointers ) { - lua_pushinteger(L, std::stoi(data)); + lua_pushinteger(L, Strings::ToInt(data)); lua_setfield(L, -2, "container_slot"); } @@ -1043,8 +1103,15 @@ void handle_player_consider( uint32 extra_data, std::vector *extra_pointers ) { - lua_pushinteger(L, std::stoi(data)); + lua_pushinteger(L, Strings::ToInt(data)); lua_setfield(L, -2, "entity_id"); + + if (extra_pointers && extra_pointers->size() == 1) { + Lua_NPC l_npc(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc); + l_npc_o.push(L); + lua_setfield(L, -2, "other"); + } } void handle_player_consider_corpse( @@ -1055,8 +1122,15 @@ void handle_player_consider_corpse( uint32 extra_data, std::vector *extra_pointers ) { - lua_pushinteger(L, std::stoi(data)); + lua_pushinteger(L, Strings::ToInt(data)); lua_setfield(L, -2, "corpse_entity_id"); + + if (extra_pointers && extra_pointers->size() == 1) { + Lua_Corpse l_corpse(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_corpse_o = luabind::adl::object(L, l_corpse); + l_corpse_o.push(L); + lua_setfield(L, -2, "corpse"); + } } void handle_player_inspect( @@ -1082,16 +1156,16 @@ void handle_player_aa_buy( std::vector *extra_pointers ) { Seperator sep(data.c_str()); - lua_pushinteger(L, std::stoi(sep.arg[0])); + lua_pushinteger(L, Strings::ToInt(sep.arg[0])); lua_setfield(L, -2, "aa_cost"); - lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_pushinteger(L, Strings::ToInt(sep.arg[1])); lua_setfield(L, -2, "aa_id"); - lua_pushinteger(L, std::stoi(sep.arg[2])); + lua_pushinteger(L, Strings::ToInt(sep.arg[2])); lua_setfield(L, -2, "aa_previous_id"); - lua_pushinteger(L, std::stoi(sep.arg[3])); + lua_pushinteger(L, Strings::ToInt(sep.arg[3])); lua_setfield(L, -2, "aa_next_id"); } @@ -1103,10 +1177,34 @@ void handle_player_aa_gain( uint32 extra_data, std::vector *extra_pointers ) { - lua_pushinteger(L, std::stoi(data)); + lua_pushinteger(L, Strings::ToInt(data)); lua_setfield(L, -2, "aa_gained"); } +void handle_player_aa_exp_gain( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + lua_pushinteger(L, Strings::ToUnsignedBigInt(data)); + lua_setfield(L, -2, "aa_exp_gained"); +} + +void handle_player_exp_gain( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + lua_pushinteger(L, Strings::ToUnsignedBigInt(data)); + lua_setfield(L, -2, "exp_gained"); +} + void handle_player_level_up( QuestInterface *parse, lua_State* L, @@ -1115,7 +1213,7 @@ void handle_player_level_up( uint32 extra_data, std::vector *extra_pointers ) { - lua_pushinteger(L, std::stoul(data)); + lua_pushinteger(L, Strings::ToUnsignedInt(data)); lua_setfield(L, -2, "levels_gained"); } @@ -1127,7 +1225,7 @@ void handle_player_level_down( uint32 extra_data, std::vector *extra_pointers ) { - lua_pushinteger(L, std::stoul(data)); + lua_pushinteger(L, Strings::ToUnsignedInt(data)); lua_setfield(L, -2, "levels_lost"); } @@ -1155,19 +1253,167 @@ void handle_player_bot_create( lua_pushstring(L, sep.arg[0]); lua_setfield(L, -2, "bot_name"); - lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_pushinteger(L, Strings::ToInt(sep.arg[1])); lua_setfield(L, -2, "bot_id"); - lua_pushinteger(L, std::stoi(sep.arg[2])); + lua_pushinteger(L, Strings::ToInt(sep.arg[2])); lua_setfield(L, -2, "bot_race"); - lua_pushinteger(L, std::stoi(sep.arg[3])); + lua_pushinteger(L, Strings::ToInt(sep.arg[3])); lua_setfield(L, -2, "bot_class"); - lua_pushinteger(L, std::stoi(sep.arg[4])); + lua_pushinteger(L, Strings::ToInt(sep.arg[4])); lua_setfield(L, -2, "bot_gender"); } +void handle_player_damage( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Seperator sep(data.c_str()); + + lua_pushnumber(L, Strings::ToUnsignedInt(sep.arg[0])); + lua_setfield(L, -2, "entity_id"); + + lua_pushnumber(L, Strings::ToBigInt(sep.arg[1])); + lua_setfield(L, -2, "damage"); + + lua_pushnumber(L, Strings::ToInt(sep.arg[2])); + lua_setfield(L, -2, "spell_id"); + + lua_pushnumber(L, Strings::ToInt(sep.arg[3])); + lua_setfield(L, -2, "skill_id"); + + lua_pushboolean(L, Strings::ToInt(sep.arg[4]) == 0 ? false : true); + lua_setfield(L, -2, "is_damage_shield"); + + lua_pushboolean(L, Strings::ToInt(sep.arg[5]) == 0 ? false : true); + lua_setfield(L, -2, "is_avoidable"); + + lua_pushnumber(L, Strings::ToInt(sep.arg[6])); + lua_setfield(L, -2, "buff_slot"); + + lua_pushboolean(L, Strings::ToInt(sep.arg[7]) == 0 ? false : true); + lua_setfield(L, -2, "is_buff_tic"); + + lua_pushnumber(L, Strings::ToInt(sep.arg[8])); + lua_setfield(L, -2, "special_attack"); + + if (extra_pointers && extra_pointers->size() >= 1) { + Lua_Mob l_mob(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); + l_mob_o.push(L); + lua_setfield(L, -2, "other"); + } +} + +void handle_player_item_click( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + lua_pushnumber(L, Strings::ToInt(data)); + lua_setfield(L, -2, "slot_id"); + + if (extra_pointers && extra_pointers->size() >= 1) { + lua_pushnumber(L, std::any_cast(extra_pointers->at(0))->GetID()); + lua_setfield(L, -2, "item_id"); + + lua_pushstring(L, std::any_cast(extra_pointers->at(0))->GetItem()->Name); + lua_setfield(L, -2, "item_name"); + + lua_pushnumber(L, std::any_cast(extra_pointers->at(0))->GetItem()->Click.Effect); + lua_setfield(L, -2, "spell_id"); + + Lua_ItemInst l_item(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_item_o = luabind::adl::object(L, l_item); + l_item_o.push(L); + lua_setfield(L, -2, "item"); + } +} + +void handle_player_destroy_item( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + if (extra_pointers && extra_pointers->size() >= 1) { + lua_pushnumber(L, std::any_cast(extra_pointers->at(0))->GetID()); + lua_setfield(L, -2, "item_id"); + + lua_pushstring(L, std::any_cast(extra_pointers->at(0))->GetItem()->Name); + lua_setfield(L, -2, "item_name"); + + lua_pushnumber(L, std::any_cast(extra_pointers->at(0))->IsStackable() ? std::any_cast(extra_pointers->at(0))->GetCharges() : 1); + lua_setfield(L, -2, "quantity"); + + Lua_ItemInst l_item(std::any_cast(extra_pointers->at(0))); + + luabind::adl::object l_item_o = luabind::adl::object(L, l_item); + l_item_o.push(L); + lua_setfield(L, -2, "item"); + } +} + +void handle_player_drop_item( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + lua_pushnumber(L, extra_data); + lua_setfield(L, -2, "slot_id"); + + if (extra_pointers && extra_pointers->size() == 1) { + EQ::ItemInstance* item_inst = std::any_cast(extra_pointers->at(0)); + + lua_pushnumber(L, item_inst->IsStackable() ? item_inst->GetCharges() : 1); + lua_setfield(L, -2, "quantity"); + + lua_pushnumber(L, item_inst->GetItem()->ID); + lua_setfield(L, -2, "item_id"); + + lua_pushstring(L, item_inst->GetItem()->Name); + lua_setfield(L, -2, "item_name"); + + lua_pushnumber(L, item_inst->GetItem()->Click.Effect); + lua_setfield(L, -2, "spell_id"); + + Lua_Item l_item(item_inst->GetItem()); + luabind::adl::object l_item_o = luabind::adl::object(L, l_item); + l_item_o.push(L); + lua_setfield(L, -2, "item"); + } +} + +void handle_player_target_change( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + if (extra_pointers && extra_pointers->size() == 1) { + Lua_Mob l_mob(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); + l_mob_o.push(L); + lua_setfield(L, -2, "other"); + } +} + // Item void handle_item_click( QuestInterface *parse, @@ -1366,16 +1612,16 @@ void handle_spell_event( Seperator sep(data.c_str()); - lua_pushinteger(L, std::stoi(sep.arg[0])); + lua_pushinteger(L, Strings::ToInt(sep.arg[0])); lua_setfield(L, -2, "caster_id"); - lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_pushinteger(L, Strings::ToInt(sep.arg[1])); lua_setfield(L, -2, "tics_remaining"); - lua_pushinteger(L, std::stoi(sep.arg[2])); + lua_pushinteger(L, Strings::ToInt(sep.arg[2])); lua_setfield(L, -2, "caster_level"); - lua_pushinteger(L, std::stoi(sep.arg[3])); + lua_pushinteger(L, Strings::ToInt(sep.arg[3])); lua_setfield(L, -2, "buff_slot"); Lua_Spell l_spell(spell_id); @@ -1424,10 +1670,10 @@ void handle_player_equip_item( Seperator sep(data.c_str()); - lua_pushnumber(L, std::stoi(sep.arg[0])); + lua_pushnumber(L, Strings::ToInt(sep.arg[0])); lua_setfield(L, -2, "item_quantity"); - lua_pushnumber(L, std::stoi(sep.arg[1])); + lua_pushnumber(L, Strings::ToInt(sep.arg[1])); lua_setfield(L, -2, "slot_id"); Lua_ItemInst l_item(extra_data); @@ -1515,16 +1761,16 @@ void handle_player_skill_up( std::vector *extra_pointers ) { Seperator sep(data.c_str()); - lua_pushinteger(L, std::stoi(sep.arg[0])); + lua_pushinteger(L, Strings::ToInt(sep.arg[0])); lua_setfield(L, -2, "skill_id"); - lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_pushinteger(L, Strings::ToInt(sep.arg[1])); lua_setfield(L, -2, "skill_value"); - lua_pushinteger(L, std::stoi(sep.arg[2])); + lua_pushinteger(L, Strings::ToInt(sep.arg[2])); lua_setfield(L, -2, "skill_max"); - lua_pushinteger(L, std::stoi(sep.arg[3])); + lua_pushinteger(L, Strings::ToInt(sep.arg[3])); lua_setfield(L, -2, "is_tradeskill"); } @@ -1537,13 +1783,13 @@ void handle_player_language_skill_up( std::vector *extra_pointers ) { Seperator sep(data.c_str()); - lua_pushinteger(L, std::stoi(sep.arg[0])); + lua_pushinteger(L, Strings::ToInt(sep.arg[0])); lua_setfield(L, -2, "skill_id"); - lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_pushinteger(L, Strings::ToInt(sep.arg[1])); lua_setfield(L, -2, "skill_value"); - lua_pushinteger(L, std::stoi(sep.arg[2])); + lua_pushinteger(L, Strings::ToInt(sep.arg[2])); lua_setfield(L, -2, "skill_max"); } @@ -1556,19 +1802,19 @@ void handle_player_alt_currency_merchant( std::vector *extra_pointers ) { Seperator sep(data.c_str()); - lua_pushinteger(L, std::stoi(sep.arg[0])); + lua_pushinteger(L, Strings::ToInt(sep.arg[0])); lua_setfield(L, -2, "currency_id"); - lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_pushinteger(L, Strings::ToInt(sep.arg[1])); lua_setfield(L, -2, "npc_id"); - lua_pushinteger(L, std::stoi(sep.arg[2])); + lua_pushinteger(L, Strings::ToInt(sep.arg[2])); lua_setfield(L, -2, "merchant_id"); - lua_pushinteger(L, std::stoi(sep.arg[3])); + lua_pushinteger(L, Strings::ToInt(sep.arg[3])); lua_setfield(L, -2, "item_id"); - lua_pushinteger(L, std::stoi(sep.arg[4])); + lua_pushinteger(L, Strings::ToInt(sep.arg[4])); lua_setfield(L, -2, "item_cost"); } @@ -1581,19 +1827,19 @@ void handle_player_merchant( std::vector *extra_pointers ) { Seperator sep(data.c_str()); - lua_pushinteger(L, std::stoi(sep.arg[0])); + lua_pushinteger(L, Strings::ToInt(sep.arg[0])); lua_setfield(L, -2, "npc_id"); - lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_pushinteger(L, Strings::ToInt(sep.arg[1])); lua_setfield(L, -2, "merchant_id"); - lua_pushinteger(L, std::stoi(sep.arg[2])); + lua_pushinteger(L, Strings::ToInt(sep.arg[2])); lua_setfield(L, -2, "item_id"); - lua_pushinteger(L, std::stoi(sep.arg[3])); + lua_pushinteger(L, Strings::ToInt(sep.arg[3])); lua_setfield(L, -2, "item_quantity"); - lua_pushinteger(L, std::stoi(sep.arg[4])); + lua_pushinteger(L, Strings::ToInt(sep.arg[4])); lua_setfield(L, -2, "item_cost"); } @@ -1616,16 +1862,16 @@ void handle_player_augment_insert( lua_setfield(L, -2, "augment"); Seperator sep(data.c_str()); - lua_pushinteger(L, std::stoul(sep.arg[0])); + lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[0])); lua_setfield(L, -2, "item_id"); - lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_pushinteger(L, Strings::ToInt(sep.arg[1])); lua_setfield(L, -2, "item_slot"); - lua_pushinteger(L, std::stoul(sep.arg[2])); + lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[2])); lua_setfield(L, -2, "augment_id"); - lua_pushinteger(L, std::stoul(sep.arg[3])); + lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[3])); lua_setfield(L, -2, "augment_slot"); } @@ -1648,16 +1894,16 @@ void handle_player_augment_remove( lua_setfield(L, -2, "augment"); Seperator sep(data.c_str()); - lua_pushinteger(L, std::stoul(sep.arg[0])); + lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[0])); lua_setfield(L, -2, "item_id"); - lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_pushinteger(L, Strings::ToInt(sep.arg[1])); lua_setfield(L, -2, "item_slot"); - lua_pushinteger(L, std::stoul(sep.arg[2])); + lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[2])); lua_setfield(L, -2, "augment_id"); - lua_pushinteger(L, std::stoul(sep.arg[3])); + lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[3])); lua_setfield(L, -2, "augment_slot"); lua_pushboolean(L, Strings::ToBool(sep.arg[4])); @@ -1688,7 +1934,7 @@ void handle_bot_cast( ) { Seperator sep(data.c_str()); - int spell_id = std::stoi(sep.arg[0]); + int spell_id = Strings::ToInt(sep.arg[0]); if (IsValidSpell(spell_id)) { Lua_Spell l_spell(&spells[spell_id]); luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); @@ -1701,10 +1947,10 @@ void handle_bot_cast( lua_setfield(L, -2, "spell"); - lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_pushinteger(L, Strings::ToInt(sep.arg[1])); lua_setfield(L, -2, "caster_id"); - lua_pushinteger(L, std::stoi(sep.arg[2])); + lua_pushinteger(L, Strings::ToInt(sep.arg[2])); lua_setfield(L, -2, "caster_level"); } @@ -1722,7 +1968,7 @@ void handle_bot_combat( l_mob_o.push(L); lua_setfield(L, -2, "other"); - lua_pushboolean(L, std::stoi(data) == 0 ? false : true); + lua_pushboolean(L, Strings::ToInt(data) == 0 ? false : true); lua_setfield(L, -2, "joined"); } @@ -1737,16 +1983,16 @@ void handle_bot_death( ) { Seperator sep(data.c_str()); - Mob *o = entity_list.GetMobID(std::stoi(sep.arg[0])); + Mob *o = entity_list.GetMobID(Strings::ToInt(sep.arg[0])); Lua_Mob l_mob(o); luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); l_mob_o.push(L); lua_setfield(L, -2, "other"); - lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_pushinteger(L, Strings::ToInt(sep.arg[1])); lua_setfield(L, -2, "damage"); - int spell_id = std::stoi(sep.arg[2]); + int spell_id = Strings::ToInt(sep.arg[2]); if (IsValidSpell(spell_id)) { Lua_Spell l_spell(&spells[spell_id]); luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); @@ -1759,7 +2005,7 @@ void handle_bot_death( lua_setfield(L, -2, "spell"); } - lua_pushinteger(L, std::stoi(sep.arg[3])); + lua_pushinteger(L, Strings::ToInt(sep.arg[3])); lua_setfield(L, -2, "skill"); } @@ -1777,7 +2023,7 @@ void handle_bot_popup_response( l_mob_o.push(L); lua_setfield(L, -2, "other"); - lua_pushinteger(L, std::stoi(data)); + lua_pushinteger(L, Strings::ToInt(data)); lua_setfield(L, -2, "popup_id"); } @@ -1811,7 +2057,7 @@ void handle_bot_signal( uint32 extra_data, std::vector *extra_pointers ) { - lua_pushinteger(L, std::stoi(data)); + lua_pushinteger(L, Strings::ToInt(data)); lua_setfield(L, -2, "signal"); } @@ -1826,7 +2072,7 @@ void handle_bot_payload( ) { Seperator sep(data.c_str()); - lua_pushinteger(L, std::stoi(sep.arg[0])); + lua_pushinteger(L, Strings::ToInt(sep.arg[0])); lua_setfield(L, -2, "payload_id"); lua_pushstring(L, sep.argplus[1]); @@ -1908,25 +2154,25 @@ void handle_bot_trade( } auto money_string = fmt::format("platinum.{}", bot_id); - uint32 money_value = !parse->GetVar(money_string).empty() ? std::stoul(parse->GetVar(money_string)) : 0; + uint32 money_value = !parse->GetVar(money_string).empty() ? Strings::ToUnsignedInt(parse->GetVar(money_string)) : 0; lua_pushinteger(L, money_value); lua_setfield(L, -2, "platinum"); money_string = fmt::format("gold.{}", bot_id); - money_value = !parse->GetVar(money_string).empty() ? std::stoul(parse->GetVar(money_string)) : 0; + money_value = !parse->GetVar(money_string).empty() ? Strings::ToUnsignedInt(parse->GetVar(money_string)) : 0; lua_pushinteger(L, money_value); lua_setfield(L, -2, "gold"); money_string = fmt::format("silver.{}", bot_id); - money_value = !parse->GetVar(money_string).empty() ? std::stoul(parse->GetVar(money_string)) : 0; + money_value = !parse->GetVar(money_string).empty() ? Strings::ToUnsignedInt(parse->GetVar(money_string)) : 0; lua_pushinteger(L, money_value); lua_setfield(L, -2, "silver"); money_string = fmt::format("copper.{}", bot_id); - money_value = !parse->GetVar(money_string).empty() ? std::stoul(parse->GetVar(money_string)) : 0; + money_value = !parse->GetVar(money_string).empty() ? Strings::ToUnsignedInt(parse->GetVar(money_string)) : 0; lua_pushinteger(L, money_value); lua_setfield(L, -2, "copper"); @@ -1944,11 +2190,81 @@ void handle_bot_use_skill( std::vector *extra_pointers ) { Seperator sep(data.c_str()); - lua_pushinteger(L, std::stoi(sep.arg[0])); + lua_pushinteger(L, Strings::ToInt(sep.arg[0])); lua_setfield(L, -2, "skill_id"); - lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_pushinteger(L, Strings::ToInt(sep.arg[1])); lua_setfield(L, -2, "skill_level"); } +void handle_bot_equip_item( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob* init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + lua_pushnumber(L, extra_data); + lua_setfield(L, -2, "item_id"); + + Seperator sep(data.c_str()); + + lua_pushnumber(L, Strings::ToInt(sep.arg[0])); + lua_setfield(L, -2, "item_quantity"); + + lua_pushnumber(L, Strings::ToInt(sep.arg[1])); + lua_setfield(L, -2, "slot_id"); + + Lua_ItemInst l_item(extra_data); + luabind::adl::object l_item_o = luabind::adl::object(L, l_item); + l_item_o.push(L); + lua_setfield(L, -2, "item"); +} + +void handle_bot_damage( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob* init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Seperator sep(data.c_str()); + + lua_pushnumber(L, Strings::ToUnsignedInt(sep.arg[0])); + lua_setfield(L, -2, "entity_id"); + + lua_pushnumber(L, Strings::ToBigInt(sep.arg[1])); + lua_setfield(L, -2, "damage"); + + lua_pushnumber(L, Strings::ToInt(sep.arg[2])); + lua_setfield(L, -2, "spell_id"); + + lua_pushnumber(L, Strings::ToInt(sep.arg[3])); + lua_setfield(L, -2, "skill_id"); + + lua_pushboolean(L, Strings::ToInt(sep.arg[4]) == 0 ? false : true); + lua_setfield(L, -2, "is_damage_shield"); + + lua_pushboolean(L, Strings::ToInt(sep.arg[5]) == 0 ? false : true); + lua_setfield(L, -2, "is_avoidable"); + + lua_pushnumber(L, Strings::ToInt(sep.arg[6])); + lua_setfield(L, -2, "buff_slot"); + + lua_pushboolean(L, Strings::ToInt(sep.arg[7]) == 0 ? false : true); + lua_setfield(L, -2, "is_buff_tic"); + + lua_pushnumber(L, Strings::ToInt(sep.arg[8])); + lua_setfield(L, -2, "special_attack"); + + Lua_Mob l_mob(init); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); + l_mob_o.push(L); + lua_setfield(L, -2, "other"); +} + #endif diff --git a/zone/lua_parser_events.h b/zone/lua_parser_events.h index b32683c7a..a85dbffe5 100644 --- a/zone/lua_parser_events.h +++ b/zone/lua_parser_events.h @@ -210,6 +210,16 @@ void handle_npc_despawn_zone( std::vector *extra_pointers ); +void handle_npc_damage( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + // Player void handle_player_say( QuestInterface *parse, @@ -373,6 +383,15 @@ void handle_player_task_stage_complete( std::vector *extra_pointers ); +void handle_player_task_accepted( + QuestInterface* parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector* extra_pointers +); + void handle_player_task_update( QuestInterface *parse, lua_State* L, @@ -589,6 +608,24 @@ void handle_player_aa_gain( std::vector *extra_pointers ); +void handle_player_aa_exp_gain( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_exp_gain( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + void handle_player_payload( QuestInterface *parse, lua_State* L, @@ -652,6 +689,50 @@ void handle_player_augment_remove( std::vector *extra_pointers ); +void handle_player_damage( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_item_click( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_destroy_item( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_target_change( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_player_drop_item( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); // Item void handle_item_click( @@ -955,5 +1036,25 @@ void handle_bot_payload( std::vector *extra_pointers ); +void handle_bot_equip_item( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob* init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_bot_damage( + QuestInterface *parse, + lua_State* L, + Bot* bot, + Mob* init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + #endif #endif diff --git a/zone/main.cpp b/zone/main.cpp index d8f8ed1af..cb16f13aa 100644 --- a/zone/main.cpp +++ b/zone/main.cpp @@ -85,10 +85,12 @@ volatile bool RunLoops = true; #endif extern volatile bool is_zone_loaded; +extern bool Critical = false; #include "zone_event_scheduler.h" #include "../common/file.h" #include "../common/path_manager.h" +#include "../common/events/player_event_logs.h" EntityList entity_list; WorldServer worldserver; @@ -107,6 +109,7 @@ EQEmuLogSys LogSys; ZoneEventScheduler event_scheduler; WorldContentService content_service; PathManager path; +PlayerEventLogs player_event_logs; const SPDat_Spell_Struct* spells; int32 SPDAT_RECORDS = -1; @@ -160,7 +163,7 @@ int main(int argc, char** argv) { uint32 instance_id = 0; std::string z_name; if (argc == 4) { - instance_id = atoi(argv[3]); + instance_id = Strings::ToInt(argv[3]); worldserver.SetLauncherName(argv[2]); auto zone_port = Strings::Split(argv[1], ':'); @@ -170,7 +173,7 @@ int main(int argc, char** argv) { if (zone_port.size() > 1) { std::string p_name = zone_port[1]; - Config->SetZonePort(atoi(p_name.c_str())); + Config->SetZonePort(Strings::ToInt(p_name.c_str())); } worldserver.SetLaunchedName(z_name.c_str()); @@ -191,7 +194,7 @@ int main(int argc, char** argv) { if (zone_port.size() > 1) { std::string p_name = zone_port[1]; - Config->SetZonePort(atoi(p_name.c_str())); + Config->SetZonePort(Strings::ToInt(p_name.c_str())); } worldserver.SetLaunchedName(z_name.c_str()); @@ -212,7 +215,7 @@ int main(int argc, char** argv) { if (zone_port.size() > 1) { std::string p_name = zone_port[1]; - Config->SetZonePort(atoi(p_name.c_str())); + Config->SetZonePort(Strings::ToInt(p_name.c_str())); } worldserver.SetLaunchedName(z_name.c_str()); @@ -229,6 +232,8 @@ int main(int argc, char** argv) { worldserver.SetLauncherName("NONE"); } + auto mutex = new Mutex; + LogInfo("Connecting to MySQL"); if (!database.Connect( Config->DatabaseHost.c_str(), @@ -240,9 +245,7 @@ int main(int argc, char** argv) { return 1; } - /** - * Multi-tenancy: Content Database - */ + // Multi-tenancy: Content Database if (!Config->ContentDbHost.empty()) { if (!content_db.Connect( Config->ContentDbHost.c_str() , @@ -256,7 +259,12 @@ int main(int argc, char** argv) { return 1; } } else { - content_db.SetMysql(database.getMySQL()); + content_db.SetMySQL(database); + // when database and content_db share the same underlying mysql connection + // it needs to be protected by a shared mutex otherwise we produce concurrency issues + // when database actions are occurring in different threads + database.SetMutex(mutex); + content_db.SetMutex(mutex); } /* Register Log System and Settings */ @@ -266,6 +274,8 @@ int main(int argc, char** argv) { ->SetGMSayHandler(&Zone::GMSayHookCallBackProcess) ->StartFileLogs(); + player_event_logs.SetDatabase(&database)->Init(); + /* Guilds */ guild_mgr.SetDatabase(&database); GuildBanks = nullptr; @@ -609,6 +619,9 @@ int main(int argc, char** argv) { safe_delete(parse); LogInfo("Proper zone shutdown complete."); LogSys.CloseFileLogs(); + + safe_delete(mutex); + return 0; } diff --git a/zone/merc.cpp b/zone/merc.cpp index 203bb33a4..558c2fc7b 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -563,11 +563,15 @@ void Merc::AddItemBonuses(const EQ::ItemData *item, StatBonuses* newbon) { } } - if (item->ExtraDmgSkill != 0 && item->ExtraDmgSkill <= EQ::skills::HIGHEST_SKILL) { - if((newbon->SkillDamageAmount[item->ExtraDmgSkill] + item->ExtraDmgAmt) > RuleI(Character, ItemExtraDmgCap)) + if (item->ExtraDmgAmt != 0 && item->ExtraDmgSkill <= EQ::skills::HIGHEST_SKILL) { + if ( + RuleI(Character, ItemExtraDmgCap) >= 0 && + (newbon->SkillDamageAmount[item->ExtraDmgSkill] + item->ExtraDmgAmt) > RuleI(Character, ItemExtraDmgCap) + ) { newbon->SkillDamageAmount[item->ExtraDmgSkill] = RuleI(Character, ItemExtraDmgCap); - else + } else { newbon->SkillDamageAmount[item->ExtraDmgSkill] += item->ExtraDmgAmt; + } } } @@ -1113,7 +1117,7 @@ void Merc::DoEnduranceUpkeep() { uint32 buffs_i; uint32 buff_count = GetMaxTotalSlots(); for (buffs_i = 0; buffs_i < buff_count; buffs_i++) { - if (buffs[buffs_i].spellid != SPELL_UNKNOWN) { + if (IsValidSpell(buffs[buffs_i].spellid)) { int upkeep = spells[buffs[buffs_i].spellid].endurance_upkeep; if(upkeep > 0) { has_effect = true; @@ -1158,7 +1162,7 @@ void Merc::CalcRestState() { uint32 buff_count = GetMaxTotalSlots(); for (unsigned int j = 0; j < buff_count; j++) { - if(buffs[j].spellid != SPELL_UNKNOWN) { + if(IsValidSpell(buffs[j].spellid)) { if(IsDetrimentalSpell(buffs[j].spellid) && (buffs[j].ticsremaining > 0)) if(!DetrimentalSpellAllowsRest(buffs[j].spellid)) return; @@ -1473,7 +1477,7 @@ void Merc::AI_Process() { return; } - if (!(m_PlayerState & static_cast(PlayerState::Aggressive))) + if (!(GetPlayerState() & static_cast(PlayerState::Aggressive))) SendAddPlayerState(PlayerState::Aggressive); bool atCombatRange = false; @@ -1716,7 +1720,7 @@ void Merc::AI_Process() { confidence_timer.Disable(); _check_confidence = false; - if (m_PlayerState & static_cast(PlayerState::Aggressive)) + if (GetPlayerState() & static_cast(PlayerState::Aggressive)) SendRemovePlayerState(PlayerState::Aggressive); if(!check_target_timer.Enabled()) @@ -2579,7 +2583,7 @@ int64 Merc::GetFocusEffect(focusType type, uint16 spell_id, bool from_buff_tic) if (equipment[x] == 0) continue; TempItem = database.GetItem(equipment[x]); - if (TempItem && TempItem->Focus.Effect > 0 && TempItem->Focus.Effect != SPELL_UNKNOWN) { + if (TempItem && IsValidSpell(TempItem->Focus.Effect)) { if(rand_effectiveness) { focus_max = CalcFocusEffect(type, TempItem->Focus.Effect, spell_id, true); if (focus_max > 0 && focus_max_real >= 0 && focus_max > focus_max_real) { @@ -3895,7 +3899,7 @@ bool Merc::GetNeedsCured(Mob *tar) { needCured = true; for (unsigned int j = 0; j < buff_count; j++) { - if(tar->GetBuffs()[j].spellid != SPELL_UNKNOWN) { + if (IsValidSpell(tar->GetBuffs()[j].spellid)) { if(CalculateCounters(tar->GetBuffs()[j].spellid) > 0) { buffsWithCounters++; @@ -4292,7 +4296,7 @@ void Merc::Stand() { SetAppearance(eaStanding); } -bool Merc::IsSitting() { +bool Merc::IsSitting() const { bool result = false; if(GetAppearance() == eaSitting && !IsMoving()) @@ -6121,8 +6125,8 @@ void NPC::LoadMercTypes() { { MercType tempMercType; - tempMercType.Type = atoi(row[0]); - tempMercType.ClientVersion = atoi(row[1]); + tempMercType.Type = Strings::ToInt(row[0]); + tempMercType.ClientVersion = Strings::ToInt(row[1]); mercTypeList.push_back(tempMercType); } @@ -6154,12 +6158,12 @@ void NPC::LoadMercs() { { MercData tempMerc; - tempMerc.MercTemplateID = atoi(row[0]); - tempMerc.MercType = atoi(row[1]); - tempMerc.MercSubType = atoi(row[2]); - tempMerc.CostFormula = atoi(row[3]); - tempMerc.ClientVersion = atoi(row[4]); - tempMerc.NPCID = atoi(row[5]); + tempMerc.MercTemplateID = Strings::ToInt(row[0]); + tempMerc.MercType = Strings::ToInt(row[1]); + tempMerc.MercSubType = Strings::ToInt(row[2]); + tempMerc.CostFormula = Strings::ToInt(row[3]); + tempMerc.ClientVersion = Strings::ToInt(row[4]); + tempMerc.NPCID = Strings::ToInt(row[5]); mercDataList.push_back(tempMerc); } diff --git a/zone/merc.h b/zone/merc.h index b05fa32d3..42fba3098 100644 --- a/zone/merc.h +++ b/zone/merc.h @@ -122,7 +122,8 @@ public: bool HasOrMayGetAggro(); bool UseDiscipline(int32 spell_id, int32 target); - virtual bool IsMerc() const { return true; } + bool IsMerc() const override { return true; } + bool IsOfClientBotMerc() const override { return true; } virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho); static Merc* LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id, bool updateFromDB = false); @@ -256,7 +257,7 @@ public: void Sit(); void Stand(); - bool IsSitting(); + bool IsSitting() const override; bool IsStanding(); // Merc-specific functions diff --git a/zone/mob.cpp b/zone/mob.cpp index 05a84fb99..2c20fc05e 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -103,6 +103,7 @@ Mob::Mob( attack_dw_timer(2000), ranged_timer(2000), hp_regen_per_second_timer(1000), + m_z_clip_check_timer(1000), tic_timer(6000), mana_timer(2000), spellend_timer(0), @@ -400,7 +401,6 @@ Mob::Mob( stunned = false; silenced = false; amnesiad = false; - inWater = false; shield_timer.Disable(); m_shield_target_id = 0; @@ -518,6 +518,8 @@ Mob::Mob( Mob::~Mob() { + quest_manager.stopalltimers(this); + mMovementManager->RemoveMob(this); AI_Stop(); @@ -1208,7 +1210,7 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) ns->spawn.class_ = class_; ns->spawn.gender = gender; ns->spawn.level = level; - ns->spawn.PlayerState = m_PlayerState; + ns->spawn.PlayerState = GetPlayerState(); ns->spawn.deity = deity; ns->spawn.animation = 0; ns->spawn.findable = findable?1:0; @@ -1378,23 +1380,23 @@ void Mob::CreateHPPacket(EQApplicationPacket* app) ds->hp = (int)GetHPRatio(); // hp event - if (IsNPC() && (GetNextHPEvent() > 0)) - { - if (ds->hp < GetNextHPEvent()) - { + if (IsNPC() && (GetNextHPEvent() > 0)) { + if (ds->hp < GetNextHPEvent()) { std::string export_string = fmt::format("{}", GetNextHPEvent()); SetNextHPEvent(-1); - parse->EventNPC(EVENT_HP, CastToNPC(), nullptr, export_string, 0); + if (parse->HasQuestSub(CastToNPC()->GetNPCTypeID(), EVENT_HP)) { + parse->EventNPC(EVENT_HP, CastToNPC(), nullptr, export_string, 0); + } } } - if (IsNPC() && (GetNextIncHPEvent() > 0)) - { - if (ds->hp > GetNextIncHPEvent()) - { + if (IsNPC() && (GetNextIncHPEvent() > 0)) { + if (ds->hp > GetNextIncHPEvent()) { std::string export_string = fmt::format("{}", GetNextIncHPEvent()); SetNextIncHPEvent(-1); - parse->EventNPC(EVENT_HP, CastToNPC(), nullptr, export_string, 1); + if (parse->HasQuestSub(CastToNPC()->GetNPCTypeID(), EVENT_HP)) { + parse->EventNPC(EVENT_HP, CastToNPC(), nullptr, export_string, 1); + } } } } @@ -2331,7 +2333,7 @@ void Mob::ShowBuffs(Client* client) { uint32 i; uint32 buff_count = GetMaxTotalSlots(); for (i=0; i < buff_count; i++) { - if (buffs[i].spellid != SPELL_UNKNOWN) { + if (IsValidSpell(buffs[i].spellid)) { if (spells[buffs[i].spellid].buff_duration_formula == DF_Permanent) client->Message(Chat::White, " %i: %s: Permanent", i, spells[buffs[i].spellid].name); else @@ -2365,7 +2367,7 @@ void Mob::ShowBuffList(Client* client) { uint32 i; uint32 buff_count = GetMaxTotalSlots(); for (i = 0; i < buff_count; i++) { - if (buffs[i].spellid != SPELL_UNKNOWN) { + if (IsValidSpell(buffs[i].spellid)) { if (spells[buffs[i].spellid].buff_duration_formula == DF_Permanent) client->Message(Chat::White, " %i: %s: Permanent", i, spells[buffs[i].spellid].name); else @@ -2374,14 +2376,14 @@ void Mob::ShowBuffList(Client* client) { } } -void Mob::GMMove(float x, float y, float z, float heading) { +void Mob::GMMove(float x, float y, float z, float heading, bool save_guard_spot) { m_Position.x = x; m_Position.y = y; m_Position.z = z; SetHeading(heading); mMovementManager->SendCommandToClients(this, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeAny); - if (IsNPC()) { + if (IsNPC() && save_guard_spot) { CastToNPC()->SaveGuardSpot(glm::vec4(x, y, z, heading)); } } @@ -2415,7 +2417,8 @@ void Mob::SendIllusionPacket( uint32 in_drakkin_tattoo, uint32 in_drakkin_details, float in_size, - bool send_appearance_effects + bool send_appearance_effects, + Client* target ) { uint8 new_texture = in_texture; @@ -2518,7 +2521,12 @@ void Mob::SendIllusionPacket( is->drakkin_details = new_drakkin_details; is->size = size; - entity_list.QueueClients(this, outapp); + if (!target) { + entity_list.QueueClients(this, outapp); + } else { + target->QueuePacket(outapp, false); + } + safe_delete(outapp); /* Refresh armor and tints after send illusion packet */ @@ -2529,7 +2537,7 @@ void Mob::SendIllusionPacket( } LogSpells( - "Illusion: Race [{}] Gender [{}] Texture [{}] HelmTexture [{}] HairColor [{}] BeardColor [{}] EyeColor1 [{}] EyeColor2 [{}] HairStyle [{}] Face [{}] DrakkinHeritage [{}] DrakkinTattoo [{}] DrakkinDetails [{}] Size [{}]", + "Illusion: Race [{}] Gender [{}] Texture [{}] HelmTexture [{}] HairColor [{}] BeardColor [{}] EyeColor1 [{}] EyeColor2 [{}] HairStyle [{}] Face [{}] DrakkinHeritage [{}] DrakkinTattoo [{}] DrakkinDetails [{}] Size [{}] Target [{}]", race, gender, new_texture, @@ -2543,7 +2551,8 @@ void Mob::SendIllusionPacket( new_drakkin_heritage, new_drakkin_tattoo, new_drakkin_details, - size + size, + target ? target->GetCleanName() : "No Target" ); } @@ -3063,16 +3072,30 @@ void Mob::SetAppearenceEffects(int32 slot, int32 value) } } -void Mob::GetAppearenceEffects() +void Mob::ListAppearanceEffects(Client* c) { - //used with GM command if (!appearance_effects_id[0]) { - Message(Chat::Red, "No Appearance Effects exist on this mob"); + c->Message( + Chat::White, + fmt::format( + "{} {} no appearance effects.", + c->GetTargetDescription(this, TargetDescriptionType::UCYou), + c == this ? "have" : "has" + ).c_str() + ); return; } for (int i = 0; i < MAX_APPEARANCE_EFFECTS; i++) { - Message(Chat::Red, "ID: %i :: App Effect ID %i :: Slot %i", i, appearance_effects_id[i], appearance_effects_slot[i]); + c->Message( + Chat::Red, + fmt::format( + "Effect {} | ID: {} Slot: {}", + i, + appearance_effects_id[i], + appearance_effects_slot[i] + ).c_str() + ); } } @@ -3700,10 +3723,32 @@ bool Mob::HateSummon() { // probably should be like half melee range, but we can't get melee range nicely because reasons :) new_pos = target->TryMoveAlong(new_pos, 5.0f, angle); - if (target->IsClient()) - target->CastToClient()->MovePC(zone->GetZoneID(), zone->GetInstanceID(), new_pos.x, new_pos.y, new_pos.z, new_pos.w, 0, SummonPC); - else - target->GMMove(new_pos.x, new_pos.y, new_pos.z, new_pos.w); + if (target->IsClient()) { + target->CastToClient()->MovePC( + zone->GetZoneID(), + zone->GetInstanceID(), + new_pos.x, + new_pos.y, + new_pos.z, + new_pos.w, + 0, + SummonPC + ); + } else { + bool target_is_client_pet = ( + target->IsPet() && + target->IsPetOwnerClient() + ); + bool set_new_guard_spot = !(IsNPC() && target_is_client_pet); + + target->GMMove( + new_pos.x, + new_pos.y, + new_pos.z, + new_pos.w, + set_new_guard_spot + ); + } return true; } else if(summon_level == 2) { @@ -3954,7 +3999,7 @@ void Mob::QuestJournalledSay(Client *QuestInitiator, const char *str, Journal::O const char *Mob::GetCleanName() { - if (!strlen(clean_name)) { + if (!strlen(clean_name)) { CleanMobName(GetName(), clean_name); } @@ -4089,7 +4134,7 @@ void Mob::ExecWeaponProc(const EQ::ItemInstance *inst, uint16 spell_id, Mob *on, return; } - if(spell_id == SPELL_UNKNOWN || on->GetSpecialAbility(NO_HARM_FROM_CLIENT)) { + if(!IsValidSpell(spell_id) || on->GetSpecialAbility(NO_HARM_FROM_CLIENT)) { //This is so 65535 doesn't get passed to the client message and to logs because it is not relavant information for debugging. return; } @@ -4125,9 +4170,19 @@ void Mob::ExecWeaponProc(const EQ::ItemInstance *inst, uint16 spell_id, Mob *on, //const cast is dirty but it would require redoing a ton of interfaces at this point //It should be safe as we don't have any truly const EQ::ItemInstance floating around anywhere. //So we'll live with it for now - int i = parse->EventItem(EVENT_WEAPON_PROC, CastToClient(), const_cast(inst), on, "", spell_id); - if(i != 0) { - return; + if (parse->ItemHasQuestSub(const_cast(inst), EVENT_WEAPON_PROC)) { + int i = parse->EventItem( + EVENT_WEAPON_PROC, + CastToClient(), + const_cast(inst), + on, + "", + spell_id + ); + + if (i != 0) { + return; + } } } @@ -4142,7 +4197,7 @@ void Mob::ExecWeaponProc(const EQ::ItemInstance *inst, uint16 spell_id, Mob *on, twinproc = true; } - if (IsBeneficialSpell(spell_id) && (!IsNPC() || (IsNPC() && CastToNPC()->GetInnateProcSpellID() != spell_id))) { // NPC innate procs don't take this path ever + if (IsBeneficialSpell(spell_id) && (!IsNPC() || (IsNPC() && CastToNPC()->GetInnateProcSpellID() != spell_id)) && spells[spell_id].target_type != ST_TargetsTarget) { // NPC innate procs don't take this path ever SpellFinished(spell_id, this, EQ::spells::CastingSlot::Item, 0, -1, spells[spell_id].resist_difficulty, true, level_override); if (twinproc) { SpellFinished(spell_id, this, EQ::spells::CastingSlot::Item, 0, -1, spells[spell_id].resist_difficulty, true, level_override); @@ -4158,7 +4213,11 @@ void Mob::ExecWeaponProc(const EQ::ItemInstance *inst, uint16 spell_id, Mob *on, } uint32 Mob::GetZoneID() const { - return(zone->GetZoneID()); + return zone->GetZoneID(); +} + +uint16 Mob::GetInstanceVersion() const { + return zone->GetInstanceVersion(); } int Mob::GetHaste() @@ -4231,19 +4290,36 @@ void Mob::SetTarget(Mob *mob) target = mob; entity_list.UpdateHoTT(this); - if (IsNPC()) { - parse->EventNPC(EVENT_TARGET_CHANGE, CastToNPC(), mob, "", 0); + const auto has_target_change_event = ( + parse->HasQuestSub(GetNPCTypeID(), EVENT_TARGET_CHANGE) || + parse->PlayerHasQuestSub(EVENT_TARGET_CHANGE) || + parse->BotHasQuestSub(EVENT_TARGET_CHANGE) + ); + + if (IsClient() && CastToClient()->admin > AccountStatus::GMMgmt) { + DisplayInfo(mob); } - else if (IsClient()) { - parse->EventPlayer(EVENT_TARGET_CHANGE, CastToClient(), "", 0); - if (CastToClient()->admin > AccountStatus::GMMgmt) { - DisplayInfo(mob); + if (has_target_change_event) { + std::vector args; + + args.emplace_back(mob); + + if (IsNPC()) { + if (parse->HasQuestSub(GetNPCTypeID(), EVENT_TARGET_CHANGE)) { + parse->EventNPC(EVENT_TARGET_CHANGE, CastToNPC(), mob, "", 0, &args); + } + } else if (IsClient()) { + if (parse->PlayerHasQuestSub(EVENT_TARGET_CHANGE)) { + parse->EventPlayer(EVENT_TARGET_CHANGE, CastToClient(), "", 0, &args); + } + + CastToClient()->SetBotPrecombat(false); // Any change in target will nullify this flag (target == mob checked above) + } else if (IsBot()) { + if (parse->BotHasQuestSub(EVENT_TARGET_CHANGE)) { + parse->EventBot(EVENT_TARGET_CHANGE, CastToBot(), mob, "", 0, &args); + } } - - CastToClient()->SetBotPrecombat(false); // Any change in target will nullify this flag (target == mob checked above) - } else if (IsBot()) { - parse->EventBot(EVENT_TARGET_CHANGE, CastToBot(), mob, "", 0); } if (IsPet() && GetOwner() && GetOwner()->IsClient()) { @@ -4323,8 +4399,9 @@ int Mob::CountDispellableBuffs() if(spells[buffs[x].spellid].good_effect == 0) continue; - if(buffs[x].spellid != SPELL_UNKNOWN && spells[buffs[x].spellid].buff_duration_formula != DF_Permanent) + if(IsValidSpell(buffs[x].spellid) && spells[buffs[x].spellid].buff_duration_formula != DF_Permanent) { val++; + } } return val; } @@ -4616,7 +4693,7 @@ void Mob::TryTwincast(Mob *caster, Mob *target, uint32 spell_id) return; } - if (IsClient() || IsBot()) + if (IsOfClientBot()) { int focus = GetFocusEffect(focusTwincast, spell_id); @@ -4885,9 +4962,9 @@ bool Mob::TryFadeEffect(int slot) if(spell_id) { - if(spell_id == SPELL_UNKNOWN) + if (!IsValidSpell(spell_id)) { return false; - + } if(IsValidSpell(spell_id)) { if (IsBeneficialSpell(spell_id)) { @@ -4910,7 +4987,7 @@ void Mob::TrySympatheticProc(Mob *target, uint32 spell_id) if(target == nullptr || !IsValidSpell(spell_id) || !IsClient()) return; - uint16 focus_spell = CastToClient()->GetSympatheticFocusEffect(focusSympatheticProc,spell_id); + uint16 focus_spell = GetSympatheticFocusEffect(focusSympatheticProc,spell_id); if(!IsValidSpell(focus_spell)) return; @@ -5161,7 +5238,7 @@ int Mob::QGVarDuration(const char *fmt) // Set val to value after type character // e.g., for "M3924", set to 3924 - int val = atoi(&fmt[0] + 1); + int val = Strings::ToInt(&fmt[0] + 1); switch (fmt[0]) { @@ -5244,7 +5321,7 @@ void Mob::DoKnockback(Mob *caster, uint32 push_back, uint32 push_up) void Mob::TrySpellOnKill(uint8 level, uint16 spell_id) { - if (spell_id != SPELL_UNKNOWN) + if (IsValidSpell(spell_id)) { if(IsEffectInSpell(spell_id, SE_ProcOnSpellKillShot)) { for (int i = 0; i < EFFECT_COUNT; i++) { @@ -5341,32 +5418,35 @@ int16 Mob::GetCritDmgMod(uint16 skill, Mob* owner) void Mob::SetGrouped(bool v) { - if(v) - { + if (v) { israidgrouped = false; } + isgrouped = v; - if(IsClient()) - { + if (IsClient()) { + if (parse->PlayerHasQuestSub(EVENT_GROUP_CHANGE)) { parse->EventPlayer(EVENT_GROUP_CHANGE, CastToClient(), "", 0); + } - if(!v) + if (!v) { CastToClient()->RemoveGroupXTargets(); + } } } void Mob::SetRaidGrouped(bool v) { - if(v) - { + if (v) { isgrouped = false; } + israidgrouped = v; - if(IsClient()) - { - parse->EventPlayer(EVENT_GROUP_CHANGE, CastToClient(), "", 0); + if (IsClient()) { + if (parse->PlayerHasQuestSub(EVENT_GROUP_CHANGE)) { + parse->EventPlayer(EVENT_GROUP_CHANGE, CastToClient(), "", 0); + } } } @@ -5555,7 +5635,7 @@ void Mob::DoGravityEffect() int buff_count = GetMaxTotalSlots(); for (int slot = 0; slot < buff_count; slot++) { - if (buffs[slot].spellid != SPELL_UNKNOWN && IsEffectInSpell(buffs[slot].spellid, SE_GravityEffect)) + if (IsValidSpell(buffs[slot].spellid) && IsEffectInSpell(buffs[slot].spellid, SE_GravityEffect)) { for (int i = 0; i < EFFECT_COUNT; i++) { @@ -6126,19 +6206,20 @@ FACTION_VALUE Mob::GetSpecialFactionCon(Mob* iOther) { bool Mob::HasSpellEffect(int effect_id) { - int i; + int i; - int buff_count = GetMaxTotalSlots(); - for(i = 0; i < buff_count; i++) - { - if(buffs[i].spellid == SPELL_UNKNOWN) { continue; } + int buff_count = GetMaxTotalSlots(); + for(i = 0; i < buff_count; i++) + { + if (!IsValidSpell(buffs[i].spellid)) { + continue; + } - if(IsEffectInSpell(buffs[i].spellid, effect_id)) - { - return(1); - } - } - return(0); + if (IsEffectInSpell(buffs[i].spellid, effect_id)) { + return(1); + } + } + return(0); } int Mob::GetSpecialAbility(int ability) @@ -6235,8 +6316,8 @@ void Mob::ProcessSpecialAbilities(const std::string &str) { Strings::IsNumber(sub_sp[0]) && Strings::IsNumber(sub_sp[1]) ) { - int ability_id = std::stoi(sub_sp[0]); - int value = std::stoi(sub_sp[1]); + int ability_id = Strings::ToInt(sub_sp[0]); + int value = Strings::ToInt(sub_sp[1]); SetSpecialAbility(ability_id, value); @@ -6263,7 +6344,7 @@ void Mob::ProcessSpecialAbilities(const std::string &str) { } if (Strings::IsNumber(sub_sp[i])) { - SetSpecialAbilityParam(ability_id, param_id, std::stoi(sub_sp[i])); + SetSpecialAbilityParam(ability_id, param_id, Strings::ToInt(sub_sp[i])); } } } @@ -6872,9 +6953,9 @@ std::string Mob::GetBucketKey() { std::string Mob::GetBucketRemaining(std::string bucket_name) { std::string full_bucket_name = fmt::format("{}-{}", GetBucketKey(), bucket_name); std::string bucket_remaining = DataBucket::GetDataRemaining(full_bucket_name); - if (!bucket_remaining.empty() && atoi(bucket_remaining.c_str()) > 0) { + if (!bucket_remaining.empty() && Strings::ToInt(bucket_remaining.c_str()) > 0) { return bucket_remaining; - } else if (atoi(bucket_remaining.c_str()) == 0) { + } else if (Strings::ToInt(bucket_remaining.c_str()) == 0) { return "0"; } return std::string(); diff --git a/zone/mob.h b/zone/mob.h index 556edbf63..1508e2998 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -42,7 +42,6 @@ char* strn0cpy(char* dest, const char* source, uint32 size); #define MAX_SPECIAL_ATTACK_PARAMS 8 -class EGNode; class Client; class EQApplicationPacket; class Group; @@ -327,7 +326,7 @@ public: int32 GetActSpellCost(uint16 spell_id, int32 cost); virtual int32 GetActSpellDuration(uint16 spell_id, int32 duration); int32 GetActSpellCasttime(uint16 spell_id, int32 casttime); - virtual int64 GetActReflectedSpellDamage(int32 spell_id, int64 value, int effectiveness); + virtual int64 GetActReflectedSpellDamage(uint16 spell_id, int64 value, int effectiveness); float ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use_resist_override = false, int resist_override = 0, bool CharismaCheck = false, bool CharmTick = false, bool IsRoot = false, int level_override = -1); @@ -417,7 +416,6 @@ public: void BuffFadeBySlot(int slot, bool iRecalcBonuses = true); void BuffFadeDetrimentalByCaster(Mob *caster); void BuffFadeBySitModifier(); - bool IsAffectedByBuff(uint16 spell_id); bool IsAffectedByBuffByGlobalGroup(GlobalGroup group); void BuffModifyDurationBySpellID(uint16 spell_id, int32 newDuration); int AddBuff(Mob *caster, const uint16 spell_id, int duration = 0, int32 level_override = -1, bool disable_buff_overwrite = false); @@ -434,7 +432,7 @@ public: bool HasDiscBuff(); virtual uint32 GetFirstBuffSlot(bool disc, bool song); virtual uint32 GetLastBuffSlot(bool disc, bool song); - virtual void InitializeBuffSlots() { buffs = nullptr; current_buff_count = 0; } + virtual void InitializeBuffSlots() { buffs = nullptr; } virtual void UninitializeBuffSlots() { } EQApplicationPacket *MakeBuffsPacket(bool for_target = true); void SendBuffsToClient(Client *c); @@ -472,7 +470,7 @@ public: inline void SetEndurUpkeep(bool val) { endur_upkeep = val; } bool HasBuffWithSpellGroup(int spell_group); void SetAppearenceEffects(int32 slot, int32 value); - void GetAppearenceEffects(); + void ListAppearanceEffects(Client* c); void ClearAppearenceEffects(); void SendSavedAppearenceEffects(Client *receiver); void SetBuffDuration(int spell_id, int duration = 0); @@ -514,8 +512,7 @@ public: virtual bool Death(Mob* killerMob, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill) = 0; virtual void Damage(Mob* from, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None) = 0; - virtual void SetHP(int64 hp); - bool ChangeHP(Mob* other, int32 amount, uint16 spell_id = 0, int8 buffslot = -1, bool iBuffTic = false); + void SetHP(int64 hp); inline void SetOOCRegen(int64 new_ooc_regen) { ooc_regen = new_ooc_regen; } virtual void Heal(); virtual void HealDamage(uint64 ammount, Mob* caster = nullptr, uint16 spell_id = SPELL_UNKNOWN); @@ -628,7 +625,7 @@ public: virtual void SetEndurance(int32 newEnd) { return; } int64 GetItemHPBonuses(); int64 GetSpellHPBonuses(); - virtual const int64& SetMana(int64 amount); + const int64& SetMana(int64 amount); inline float GetManaRatio() const { return max_mana == 0 ? 100 : ((static_cast(current_mana) / max_mana) * 100); } virtual int64 CalcMaxMana(); @@ -658,6 +655,10 @@ public: inline const bool GetKeepsSoldItems() const { return keeps_sold_items; } inline void SetKeepsSoldItems(bool in_keeps_sold_items) { keeps_sold_items = in_keeps_sold_items; } + virtual bool IsSitting() const { return false; } + + int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat); + void CopyHateList(Mob* to); //Group @@ -682,7 +683,7 @@ public: float GetMovespeed() const { return IsRunning() ? GetRunspeed() : GetWalkspeed(); } bool IsRunning() const { return m_is_running; } void SetRunning(bool val) { m_is_running = val; } - virtual void GMMove(float x, float y, float z, float heading = 0.01); + virtual void GMMove(float x, float y, float z, float heading = 0.01, bool save_guard_spot = true); virtual void GMMove(const glm::vec4 &position); void SetDelta(const glm::vec4& delta); void MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct* spu); @@ -896,7 +897,8 @@ public: uint32 in_drakkin_tattoo = 0xFFFFFFFF, uint32 in_drakkin_details = 0xFFFFFFFF, float in_size = -1.0f, - bool send_appearance_effects = true + bool send_appearance_effects = true, + Client* target = nullptr ); void CloneAppearance(Mob* other, bool clone_name = false); void SetFaceAppearance(const FaceChange_Struct& face, bool skip_sender = false); @@ -913,13 +915,13 @@ public: bool PassCharismaCheck(Mob* caster, uint16 spell_id); bool TryDeathSave(); bool TryDivineSave(); - void DoBuffWearOffEffect(uint32 index); void TryTriggerOnCastFocusEffect(focusType type, uint16 spell_id); bool TryTriggerOnCastProc(uint16 focusspellid, uint16 spell_id, uint16 proc_spellid); bool TrySpellTrigger(Mob *target, uint32 spell_id, int effect); void TryTriggerOnCastRequirement(); void TryTwincast(Mob *caster, Mob *target, uint32 spell_id); void TrySympatheticProc(Mob *target, uint32 spell_id); + uint16 GetSympatheticFocusEffect(focusType type, uint16 spell_id); bool TryFadeEffect(int slot); uint16 GetSpellEffectResistChance(uint16 spell_id); int32 GetVulnerability(Mob *caster, uint32 spell_id, uint32 ticsremaining, bool from_buff_tic = false); @@ -1234,6 +1236,7 @@ public: bool Charmed() const { return typeofpet == petCharmed; } static uint32 GetLevelHP(uint8 tlevel); uint32 GetZoneID() const; //for perl + uint16 GetInstanceVersion() const; //for perl virtual int32 CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc = false); virtual int32 CheckHealAggroAmount(uint16 spell_id, Mob *target, uint32 heal_possible = 0); @@ -1318,45 +1321,6 @@ public: inline uint32 GetEmoteID() { return emoteid; } bool HasSpellEffect(int effect_id); - int mod_effect_value(int effect_value, uint16 spell_id, int effect_type, Mob *caster, uint16 caster_id); - float mod_hit_chance(float chancetohit, EQ::skills::SkillType skillinuse, Mob *attacker); - float mod_riposte_chance(float ripostchance, Mob *attacker); - float mod_block_chance(float blockchance, Mob *attacker); - float mod_parry_chance(float parrychance, Mob *attacker); - float mod_dodge_chance(float dodgechance, Mob *attacker); - float mod_monk_weight(float monkweight, Mob *attacker); - float mod_mitigation_rating(float mitigation_rating, Mob *attacker); - float mod_attack_rating(float attack_rating, Mob *defender); - int64 mod_kick_damage(int64 dmg); - int64 mod_bash_damage(int64 dmg); - int64 mod_frenzy_damage(int64 dmg); - int64 mod_monk_special_damage(int64 ndamage, EQ::skills::SkillType skill_type); - int64 mod_backstab_damage(int64 ndamage); - int64 mod_archery_bonus_chance(int bonuschance, const EQ::ItemInstance *RangeWeapon); - uint64 mod_archery_bonus_damage(uint64 MaxDmg, const EQ::ItemInstance *RangeWeapon); - int64 mod_archery_damage(int64 TotalDmg, bool hasbonus, const EQ::ItemInstance *RangeWeapon); - uint64 mod_throwing_damage(uint64 MaxDmg); - int32 mod_cast_time(int32 cast_time); - int mod_buff_duration(int res, Mob *caster, Mob *target, uint16 spell_id); - int mod_spell_stack(uint16 spellid1, int caster_level1, Mob *caster1, uint16 spellid2, int caster_level2, Mob *caster2); - int mod_spell_resist( - int resist_chance, - int level_mod, - int resist_modifier, - int target_resist, - uint8 resist_type, - uint16 spell_id, - Mob *caster - ); - void mod_spell_cast( - uint16 spell_id, - Mob *spelltar, - bool reflect, - bool use_resist_adjust, - int16 resist_adjust, - bool isproc - ); - bool mod_will_aggro(Mob *attacker, Mob *on); //Command #Tune functions void TuneGetStats(Mob* defender, Mob *attacker); @@ -1416,6 +1380,7 @@ public: int64 DoDamageCaps(int64 base_damage); int64 GetHPRegen() const; + int64 GetHPRegenPerSecond() const; int64 GetManaRegen() const; bool CanOpenDoors() const; @@ -1451,6 +1416,8 @@ public: void SetManualFollow(bool flag) { m_manual_follow = flag; } bool GetManualFollow() const { return m_manual_follow; } + void DrawDebugCoordinateNode(std::string node_name, const glm::vec4 vec); + protected: void CommonDamage(Mob* other, int64 &damage, const uint16 spell_id, const EQ::skills::SkillType attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic, eSpecialAttacks specal = eSpecialAttacks::None); static uint16 GetProcID(uint16 spell_id, uint8 effect_index); @@ -1459,6 +1426,8 @@ protected: int _GetRunSpeed() const; int _GetFearSpeed() const; + Timer m_z_clip_check_timer; + virtual bool AI_EngagedCastCheck() { return(false); } virtual bool AI_PursueCastCheck() { return(false); } virtual bool AI_IdleCastCheck() { return(false); } @@ -1520,7 +1489,6 @@ protected: uint8 maxlevel; uint32 scalerate; Buffs_Struct *buffs; - uint32 current_buff_count; StatBonuses itembonuses; StatBonuses spellbonuses; StatBonuses aabonuses; @@ -1621,7 +1589,6 @@ protected: EQ::LightSourceProfile m_Light; - float fixedZ; EmuAppearance _appearance; uint8 pRunAnimSpeed; bool m_is_running; @@ -1672,7 +1639,6 @@ protected: uint32 casting_spell_inventory_slot; uint32 casting_spell_timer; uint32 casting_spell_timer_duration; - uint32 casting_spell_type; int16 casting_spell_resist_adjust; uint32 casting_spell_aa_id; uint32 casting_spell_recast_adjust; @@ -1714,7 +1680,6 @@ protected: bool rooted; bool silenced; bool amnesiad; - bool inWater; // Set to true or false by Water Detection code if enabled by rules bool offhand; bool has_shieldequiped; bool has_twohandbluntequiped; @@ -1735,7 +1700,9 @@ protected: bool spawned_in_water; bool is_boat; - CombatRecord combat_record{}; + CombatRecord m_combat_record{}; +public: + const CombatRecord &GetCombatRecord() const; public: bool GetWasSpawnedInWater() const; @@ -1798,7 +1765,6 @@ protected: int8 last_hp_percent; int32 last_hp; - int32 last_max_hp; int cur_wp; glm::vec4 m_CurrentWayPoint; @@ -1866,6 +1832,8 @@ private: EQ::InventoryProfile m_inv; std::shared_ptr m_target_of_heal_rotation; bool m_manual_follow; + + void DoSpellInterrupt(uint16 spell_id, int32 mana_cost, int my_curmana); }; #endif diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 6b8f85bba..685c65b26 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -369,7 +369,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes, bool bInnates return false; } -bool NPC::AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore) { +bool NPC::AIDoSpellCast(int32 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore) { LogAI("spellid [{}] tar [{}] mana [{}] Name [{}]", AIspells[i].spellid, tar->GetName(), mana_cost, spells[AIspells[i].spellid].name); casting_spell_AIindex = i; @@ -404,16 +404,16 @@ void NPC::AI_Init() AIautocastspell_timer.reset(nullptr); casting_spell_AIindex = static_cast(AIspells.size()); - roambox_max_x = 0; - roambox_max_y = 0; - roambox_min_x = 0; - roambox_min_y = 0; - roambox_distance = 0; - roambox_destination_x = 0; - roambox_destination_y = 0; - roambox_destination_z = 0; - roambox_min_delay = 2500; - roambox_delay = 2500; + m_roambox.max_x = 0; + m_roambox.max_y = 0; + m_roambox.min_x = 0; + m_roambox.min_y = 0; + m_roambox.distance = 0; + m_roambox.dest_x = 0; + m_roambox.dest_y = 0; + m_roambox.dest_z = 0; + m_roambox.delay = 2500; + m_roambox.min_delay = 2500; } void Client::AI_Init() @@ -999,7 +999,13 @@ void Mob::AI_Process() { } if (door->GetTriggerDoorID() > 0) { - continue; + auto trigger_door = entity_list.GetDoorsByDoorID(door->GetTriggerDoorID()); + if (trigger_door) { + if (Strings::RemoveNumbers(door->GetDoorName()) != + Strings::RemoveNumbers(trigger_door->GetDoorName())) { + continue; + } + } } if (door->GetDoorParam() > 0) { @@ -1065,7 +1071,21 @@ void Mob::AI_Process() { } if (engaged) { - if (!(m_PlayerState & static_cast(PlayerState::Aggressive))) + if (IsNPC() && m_z_clip_check_timer.Check()) { + auto t = GetTarget(); + if (t) { + float self_z = GetZ() - GetZOffset(); + float target_z = t->GetPosition().z - t->GetZOffset(); + if (DistanceNoZ(GetPosition(), t->GetPosition()) < 75 && + std::abs(self_z - target_z) >= 25 && !CheckLosFN(t)) { + float new_z = FindDestGroundZ(t->GetPosition()); + GMMove(t->GetPosition().x, t->GetPosition().y, new_z + GetZOffset(), t->GetPosition().w, false); + FaceTarget(t); + } + } + } + + if (!(GetPlayerState() & static_cast(PlayerState::Aggressive))) SendAddPlayerState(PlayerState::Aggressive); // NPCs will forget people after 10 mins of not interacting with them or out of range @@ -1361,7 +1381,7 @@ void Mob::AI_Process() { } } else { - if (m_PlayerState & static_cast(PlayerState::Aggressive)) + if (GetPlayerState() & static_cast(PlayerState::Aggressive)) SendRemovePlayerState(PlayerState::Aggressive); if (IsPetStop()) // pet stop won't be engaged, so we will always get here and we want the above branch to execute @@ -1578,123 +1598,9 @@ void NPC::AI_DoMovement() { return; } - /** - * Roambox logic sets precedence - */ - if (roambox_distance > 0) { - - // Check if we're already moving to a WP - // If so, if we're not moving we have arrived and need to set delay - - if (GetCWP() == EQ::WaypointStatus::RoamBoxPauseInProgress && !IsMoving()) { - // We have arrived - - int roambox_move_delay = EQ::ClampLower(GetRoamboxDelay(), GetRoamboxMinDelay()); - int move_delay_max = (roambox_move_delay > 0 ? roambox_move_delay : (int) GetRoamboxMinDelay() * 4); - int random_timer = RandomTimer( - GetRoamboxMinDelay(), - move_delay_max - ); - - LogNPCRoamBoxDetail( - "({}) Timer calc | random_timer [{}] roambox_move_delay [{}] move_min [{}] move_max [{}]", - GetCleanName(), - random_timer, - roambox_move_delay, - (int) GetRoamboxMinDelay(), - move_delay_max - ); - - time_until_can_move = Timer::GetCurrentTime() + random_timer; - SetCurrentWP(0); - return; - } - - // Set a new destination - if (!IsMoving() && time_until_can_move < Timer::GetCurrentTime()) { - auto move_x = static_cast(zone->random.Real(-roambox_distance, roambox_distance)); - auto move_y = static_cast(zone->random.Real(-roambox_distance, roambox_distance)); - - roambox_destination_x = EQ::Clamp((GetX() + move_x), roambox_min_x, roambox_max_x); - roambox_destination_y = EQ::Clamp((GetY() + move_y), roambox_min_y, roambox_max_y); - - /** - * If our roambox was configured with large distances, chances of hitting the min or max end of - * the clamp is high, this causes NPC's to gather on the border of a box, to reduce clustering - * either lower the roambox distance or the code will do a simple random between min - max when it - * hits the min or max of the clamp - */ - if (roambox_destination_x == roambox_min_x || roambox_destination_x == roambox_max_x) { - roambox_destination_x = static_cast(zone->random.Real(roambox_min_x, roambox_max_x)); - } - - if (roambox_destination_y == roambox_min_y || roambox_destination_y == roambox_max_y) { - roambox_destination_y = static_cast(zone->random.Real(roambox_min_y, roambox_max_y)); - } - - /** - * If mob was not spawned in water, let's not randomly roam them into water - * if the roam box was sloppily configured - */ - if (!GetWasSpawnedInWater()) { - roambox_destination_z = GetGroundZ(roambox_destination_x, roambox_destination_y); - if (zone->HasMap() && zone->HasWaterMap()) { - auto position = glm::vec3( - roambox_destination_x, - roambox_destination_y, - roambox_destination_z - ); - - /** - * If someone brought us into water when we naturally wouldn't path there, return to spawn - */ - if (zone->watermap->InLiquid(position) && zone->watermap->InLiquid(m_Position)) { - roambox_destination_x = m_SpawnPoint.x; - roambox_destination_y = m_SpawnPoint.y; - } - - if (zone->watermap->InLiquid(position)) { - LogNPCRoamBoxDetail("[{}] | My destination is in water and I don't belong there!", GetCleanName()); - - return; - } - } - } - else { // Mob was in water, make sure new spot is in water also - roambox_destination_z = m_Position.z; - auto position = glm::vec3( - roambox_destination_x, - roambox_destination_y, - m_Position.z + 15 - ); - if (zone->HasWaterMap() && !zone->watermap->InLiquid(position)) { - roambox_destination_x = m_SpawnPoint.x; - roambox_destination_y = m_SpawnPoint.y; - roambox_destination_z = m_SpawnPoint.z; - } - } - - LogNPCRoamBox("[{}] | Pathing to [{}] [{}] [{}]", GetCleanName(), - roambox_destination_x, roambox_destination_y, - roambox_destination_z); - - LogNPCRoamBox( - "NPC ({}) distance [{}] X (min/max) [{} / {}] Y (min/max) [{} / {}] | Dest x/y/z [{} / {} / {}]", - GetCleanName(), - roambox_distance, - roambox_min_x, - roambox_max_x, - roambox_min_y, - roambox_max_y, - roambox_destination_x, - roambox_destination_y, - roambox_destination_z - ); - - SetCurrentWP(EQ::WaypointStatus::RoamBoxPauseInProgress); - NavigateTo(roambox_destination_x, roambox_destination_y, roambox_destination_z); - } - + // Roambox logic sets precedence + if (m_roambox.distance > 0) { + HandleRoambox(); return; } else if (roamer) { @@ -1747,9 +1653,10 @@ void NPC::AI_DoMovement() { RotateTo(m_CurrentWayPoint.w); } - //kick off event_waypoint arrive - std::string export_string = fmt::format("{}", cur_wp); - parse->EventNPC(EVENT_WAYPOINT_ARRIVE, CastToNPC(), nullptr, export_string, 0); + if (parse->HasQuestSub(GetNPCTypeID(), EVENT_WAYPOINT_ARRIVE)) { + parse->EventNPC(EVENT_WAYPOINT_ARRIVE, CastToNPC(), nullptr, std::to_string(cur_wp), 0); + } + // No need to move as we are there. Next loop will // take care of normal grids, even at pause 0. // We do need to call and setup a wp if we're cur_wp=-2 @@ -1865,9 +1772,9 @@ void NPC::AI_SetupNextWaypoint() { entity_list.OpenDoorsNear(this); if (!DistractedFromGrid) { - //kick off event_waypoint depart - std::string export_string = fmt::format("{}", cur_wp); - parse->EventNPC(EVENT_WAYPOINT_DEPART, CastToNPC(), nullptr, export_string, 0); + if (parse->HasQuestSub(GetNPCTypeID(), EVENT_WAYPOINT_DEPART)) { + parse->EventNPC(EVENT_WAYPOINT_DEPART, CastToNPC(), nullptr, std::to_string(cur_wp), 0); + } //setup our next waypoint, if we are still on our normal grid //remember that the quest event above could have done anything it wanted with our grid @@ -1916,14 +1823,17 @@ void Mob::AI_Event_Engaged(Mob *attacker, bool yell_for_help) //if the target dies before it goes off if (attacker->GetHP() > 0) { if (!CastToNPC()->GetCombatEvent() && GetHP() > 0) { - parse->EventNPC(EVENT_COMBAT, CastToNPC(), attacker, "1", 0); + if (parse->HasQuestSub(GetNPCTypeID(), EVENT_COMBAT)) { + parse->EventNPC(EVENT_COMBAT, CastToNPC(), attacker, "1", 0); + } + auto emote_id = GetEmoteID(); if (emote_id) { CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::EnterCombat, emoteid); } std::string mob_name = GetCleanName(); - combat_record.Start(mob_name); + m_combat_record.Start(mob_name); CastToNPC()->SetCombatEvent(true); } } @@ -1931,7 +1841,9 @@ void Mob::AI_Event_Engaged(Mob *attacker, bool yell_for_help) } if (IsBot()) { - parse->EventBot(EVENT_COMBAT, CastToBot(), attacker, "1", 0); + if (parse->BotHasQuestSub(EVENT_COMBAT)) { + parse->EventBot(EVENT_COMBAT, CastToBot(), attacker, "1", 0); + } } } @@ -1959,17 +1871,23 @@ void Mob::AI_Event_NoLongerEngaged() { if (CastToNPC()->GetCombatEvent() && GetHP() > 0) { if (entity_list.GetNPCByID(GetID())) { auto emote_id = CastToNPC()->GetEmoteID(); - parse->EventNPC(EVENT_COMBAT, CastToNPC(), nullptr, "0", 0); + + if (parse->HasQuestSub(GetNPCTypeID(), EVENT_COMBAT)) { + parse->EventNPC(EVENT_COMBAT, CastToNPC(), nullptr, "0", 0); + } + if (emote_id) { CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::LeaveCombat, emoteid); } - combat_record.Stop(); + m_combat_record.Stop(); CastToNPC()->SetCombatEvent(false); } } } else if (IsBot()) { - parse->EventBot(EVENT_COMBAT, CastToBot(), nullptr, "0", 0); + if (parse->BotHasQuestSub(EVENT_COMBAT)) { + parse->EventBot(EVENT_COMBAT, CastToBot(), nullptr, "0", 0); + } } } @@ -2463,8 +2381,10 @@ void NPC::CheckSignal() { if (!signal_q.empty()) { int signal_id = signal_q.front(); signal_q.pop_front(); - const auto export_string = fmt::format("{}", signal_id); - parse->EventNPC(EVENT_SIGNAL, this, nullptr, export_string, 0); + + if (parse->HasQuestSub(GetNPCTypeID(), EVENT_SIGNAL)) { + parse->EventNPC(EVENT_SIGNAL, this, nullptr, std::to_string(signal_id), 0); + } } } @@ -2938,25 +2858,25 @@ DBnpcspells_Struct *ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) auto row = results.begin(); DBnpcspells_Struct spell_set; - spell_set.parent_list = atoi(row[1]); - spell_set.attack_proc = atoi(row[2]); - spell_set.proc_chance = atoi(row[3]); - spell_set.range_proc = atoi(row[4]); - spell_set.rproc_chance = atoi(row[5]); - spell_set.defensive_proc = atoi(row[6]); - spell_set.dproc_chance = atoi(row[7]); - spell_set.fail_recast = atoi(row[8]); - spell_set.engaged_no_sp_recast_min = atoi(row[9]); - spell_set.engaged_no_sp_recast_max = atoi(row[10]); - spell_set.engaged_beneficial_self_chance = atoi(row[11]); - spell_set.engaged_beneficial_other_chance = atoi(row[12]); - spell_set.engaged_detrimental_chance = atoi(row[13]); - spell_set.pursue_no_sp_recast_min = atoi(row[14]); - spell_set.pursue_no_sp_recast_max = atoi(row[15]); - spell_set.pursue_detrimental_chance = atoi(row[16]); - spell_set.idle_no_sp_recast_min = atoi(row[17]); - spell_set.idle_no_sp_recast_max = atoi(row[18]); - spell_set.idle_beneficial_chance = atoi(row[19]); + spell_set.parent_list = Strings::ToInt(row[1]); + spell_set.attack_proc = Strings::ToInt(row[2]); + spell_set.proc_chance = Strings::ToInt(row[3]); + spell_set.range_proc = Strings::ToInt(row[4]); + spell_set.rproc_chance = Strings::ToInt(row[5]); + spell_set.defensive_proc = Strings::ToInt(row[6]); + spell_set.dproc_chance = Strings::ToInt(row[7]); + spell_set.fail_recast = Strings::ToInt(row[8]); + spell_set.engaged_no_sp_recast_min = Strings::ToInt(row[9]); + spell_set.engaged_no_sp_recast_max = Strings::ToInt(row[10]); + spell_set.engaged_beneficial_self_chance = Strings::ToInt(row[11]); + spell_set.engaged_beneficial_other_chance = Strings::ToInt(row[12]); + spell_set.engaged_detrimental_chance = Strings::ToInt(row[13]); + spell_set.pursue_no_sp_recast_min = Strings::ToInt(row[14]); + spell_set.pursue_no_sp_recast_max = Strings::ToInt(row[15]); + spell_set.pursue_detrimental_chance = Strings::ToInt(row[16]); + spell_set.idle_no_sp_recast_min = Strings::ToInt(row[17]); + spell_set.idle_no_sp_recast_max = Strings::ToInt(row[18]); + spell_set.idle_beneficial_chance = Strings::ToInt(row[19]); // pulling fixed values from an auto-increment field is dangerous... query = StringFormat( @@ -2974,23 +2894,23 @@ DBnpcspells_Struct *ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) int entryIndex = 0; for (row = results.begin(); row != results.end(); ++row, ++entryIndex) { DBnpcspells_entries_Struct entry; - int spell_id = atoi(row[0]); + int spell_id = Strings::ToInt(row[0]); entry.spellid = spell_id; - entry.type = atoul(row[1]); - entry.minlevel = atoi(row[2]); - entry.maxlevel = atoi(row[3]); - entry.manacost = atoi(row[4]); - entry.recast_delay = atoi(row[5]); - entry.priority = atoi(row[6]); - entry.min_hp = atoi(row[7]); - entry.max_hp = atoi(row[8]); + entry.type = Strings::ToUnsignedInt(row[1]); + entry.minlevel = Strings::ToInt(row[2]); + entry.maxlevel = Strings::ToInt(row[3]); + entry.manacost = Strings::ToInt(row[4]); + entry.recast_delay = Strings::ToInt(row[5]); + entry.priority = Strings::ToInt(row[6]); + entry.min_hp = Strings::ToInt(row[7]); + entry.max_hp = Strings::ToInt(row[8]); // some spell types don't make much since to be priority 0, so fix that if (!(entry.type & SPELL_TYPES_INNATE) && entry.priority == 0) entry.priority = 1; if (row[9]) - entry.resist_adjust = atoi(row[9]); + entry.resist_adjust = Strings::ToInt(row[9]); else if (IsValidSpell(spell_id)) entry.resist_adjust = spells[spell_id].resist_difficulty; @@ -3021,7 +2941,7 @@ uint32 ZoneDatabase::GetMaxNPCSpellsID() { if (!row[0]) return 0; - return atoi(row[0]); + return Strings::ToInt(row[0]); } DBnpcspellseffects_Struct *ZoneDatabase::GetNPCSpellsEffects(uint32 iDBSpellsEffectsID) @@ -3061,7 +2981,7 @@ DBnpcspellseffects_Struct *ZoneDatabase::GetNPCSpellsEffects(uint32 iDBSpellsEff return nullptr; auto row = results.begin(); - uint32 tmpparent_list = atoi(row[1]); + uint32 tmpparent_list = Strings::ToInt(row[1]); query = StringFormat("SELECT spell_effect_id, minlevel, " "maxlevel,se_base, se_limit, se_max " @@ -3081,13 +3001,13 @@ DBnpcspellseffects_Struct *ZoneDatabase::GetNPCSpellsEffects(uint32 iDBSpellsEff int entryIndex = 0; for (row = results.begin(); row != results.end(); ++row, ++entryIndex) { - int spell_effect_id = atoi(row[0]); + int spell_effect_id = Strings::ToInt(row[0]); npc_spellseffects_cache[iDBSpellsEffectsID]->entries[entryIndex].spelleffectid = spell_effect_id; - npc_spellseffects_cache[iDBSpellsEffectsID]->entries[entryIndex].minlevel = atoi(row[1]); - npc_spellseffects_cache[iDBSpellsEffectsID]->entries[entryIndex].maxlevel = atoi(row[2]); - npc_spellseffects_cache[iDBSpellsEffectsID]->entries[entryIndex].base_value = atoi(row[3]); - npc_spellseffects_cache[iDBSpellsEffectsID]->entries[entryIndex].limit = atoi(row[4]); - npc_spellseffects_cache[iDBSpellsEffectsID]->entries[entryIndex].max_value = atoi(row[5]); + npc_spellseffects_cache[iDBSpellsEffectsID]->entries[entryIndex].minlevel = Strings::ToInt(row[1]); + npc_spellseffects_cache[iDBSpellsEffectsID]->entries[entryIndex].maxlevel = Strings::ToInt(row[2]); + npc_spellseffects_cache[iDBSpellsEffectsID]->entries[entryIndex].base_value = Strings::ToInt(row[3]); + npc_spellseffects_cache[iDBSpellsEffectsID]->entries[entryIndex].limit = Strings::ToInt(row[4]); + npc_spellseffects_cache[iDBSpellsEffectsID]->entries[entryIndex].max_value = Strings::ToInt(row[5]); } return npc_spellseffects_cache[iDBSpellsEffectsID]; @@ -3108,6 +3028,6 @@ uint32 ZoneDatabase::GetMaxNPCSpellsEffectsID() { if (!row[0]) return 0; - return atoi(row[0]); + return Strings::ToInt(row[0]); } diff --git a/zone/mob_appearance.cpp b/zone/mob_appearance.cpp index 192e5d002..4441d840a 100644 --- a/zone/mob_appearance.cpp +++ b/zone/mob_appearance.cpp @@ -239,7 +239,7 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const if (inst->GetOrnamentationAug(ornamentation_augment_type)) { item = inst->GetOrnamentationAug(ornamentation_augment_type)->GetItem(); if (item && strlen(item->IDFile) > 2 && Strings::IsNumber(&item->IDFile[2])) { - equipment_material = std::stoi(&item->IDFile[2]); + equipment_material = Strings::ToInt(&item->IDFile[2]); } } else if (inst->GetOrnamentationIDFile()) { equipment_material = inst->GetOrnamentationIDFile(); @@ -248,7 +248,7 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const } if (!equipment_material && strlen(item->IDFile) > 2 && Strings::IsNumber(&item->IDFile[2])) { - equipment_material = std::stoi(&item->IDFile[2]); + equipment_material = Strings::ToInt(&item->IDFile[2]); } } else { diff --git a/zone/mob_info.cpp b/zone/mob_info.cpp index ef5f58063..69693a8b0 100644 --- a/zone/mob_info.cpp +++ b/zone/mob_info.cpp @@ -46,7 +46,7 @@ inline std::string GetMobAttributeByString(Mob *mob, const std::string &attribut } if (attribute == "end") { - int endurance = 0; + int64 endurance = 0; if (mob->IsClient()) { endurance = mob->CastToClient()->GetEndurance(); } @@ -256,10 +256,10 @@ inline std::string GetMobAttributeByString(Mob *mob, const std::string &attribut return std::to_string((int)npc->GetSize()); } if (attribute == "runspeed") { - return std::to_string((int)npc->GetRunspeed()); + return std::to_string(npc->GetRunspeed()); } if (attribute == "walkspeed") { - return std::to_string((int)npc->GetWalkspeed()); + return std::to_string(npc->GetWalkspeed()); } if (attribute == "spawngroup") { return std::to_string(npc->GetSpawnGroupId()); @@ -349,7 +349,7 @@ inline std::string GetMobAttributeByString(Mob *mob, const std::string &attribut return std::to_string((int)npc->GetProximityMaxZ()); } if (attribute == "accuracy") { - return std::to_string((int)npc->GetAccuracyRating()) + scaling_modified; + return std::to_string(npc->GetAccuracyRating()) + scaling_modified; } if (attribute == "slow_mitigation") { if (mob->EntityVariableExists("modify_stat_slow_mitigation")) { @@ -377,8 +377,17 @@ inline std::string GetMobAttributeByString(Mob *mob, const std::string &attribut scaling_modified = " *"; } - return Strings::Commify(std::to_string((int) npc->GetHPRegen())) + scaling_modified; + return Strings::Commify(std::to_string(npc->GetHPRegen())) + scaling_modified; } + + if (attribute == "hp_regen_per_second") { + if (mob->EntityVariableExists("modify_stat_hp_regen_per_second")) { + scaling_modified = " *"; + } + + return Strings::Commify(std::to_string(npc->GetHPRegenPerSecond())) + scaling_modified; + } + if (attribute == "attack_delay") { if (mob->EntityVariableExists("modify_stat_attack_delay")) { scaling_modified = " *"; @@ -401,7 +410,19 @@ inline std::string GetMobAttributeByString(Mob *mob, const std::string &attribut return Strings::Commify(std::to_string((int) npc->GetHealScale())) + scaling_modified; } if (attribute == "avoidance") { - return Strings::Commify(std::to_string((int) npc->GetAvoidanceRating())) + scaling_modified; + if (mob->EntityVariableExists("modify_stat_avoidance")) { + scaling_modified = " *"; + } + + return Strings::Commify(std::to_string(npc->GetAvoidanceRating())) + scaling_modified; + } + + if (attribute == "heroic_strikethrough") { + if (mob->EntityVariableExists("modify_stat_heroic_strikethrough")) { + scaling_modified = " *"; + } + + return Strings::Commify(std::to_string(npc->GetHeroicStrikethrough())) + scaling_modified; } npc->GetNPCEmote(npc->GetEmoteID(), 0); @@ -411,63 +432,63 @@ inline std::string GetMobAttributeByString(Mob *mob, const std::string &attribut Client *client = mob->CastToClient(); if (attribute == "shielding") { - return Strings::Commify(std::to_string((int) client->GetShielding())) + " / " + - Strings::Commify(std::to_string((int) RuleI(Character, ItemShieldingCap))); + return Strings::Commify(std::to_string(client->GetShielding())) + " / " + + Strings::Commify(std::to_string(RuleI(Character, ItemShieldingCap))); } if (attribute == "spell_shielding") { - return Strings::Commify(std::to_string((int) client->GetSpellShield())) + " / " + - Strings::Commify(std::to_string((int) RuleI(Character, ItemSpellShieldingCap))); + return Strings::Commify(std::to_string(client->GetSpellShield())) + " / " + + Strings::Commify(std::to_string(RuleI(Character, ItemSpellShieldingCap))); } if (attribute == "dot_shielding") { - return Strings::Commify(std::to_string((int) client->GetDoTShield())) + " / " + - Strings::Commify(std::to_string((int) RuleI(Character, ItemDoTShieldingCap))); + return Strings::Commify(std::to_string(client->GetDoTShield())) + " / " + + Strings::Commify(std::to_string(RuleI(Character, ItemDoTShieldingCap))); } if (attribute == "stun_resist") { - return Strings::Commify(std::to_string((int) client->GetStunResist())) + " / " + - Strings::Commify(std::to_string((int) RuleI(Character, ItemStunResistCap))); + return Strings::Commify(std::to_string(client->GetStunResist())) + " / " + + Strings::Commify(std::to_string(RuleI(Character, ItemStunResistCap))); } if (attribute == "damage_shield") { - return Strings::Commify(std::to_string((int) client->GetDS())) + " / " + - Strings::Commify(std::to_string((int) RuleI(Character, ItemDamageShieldCap))); + return Strings::Commify(std::to_string(client->GetDS())) + " / " + + Strings::Commify(std::to_string(RuleI(Character, ItemDamageShieldCap))); } if (attribute == "avoidance") { - return Strings::Commify(std::to_string((int) client->GetAvoidance())) + " / " + - Strings::Commify(std::to_string((int) RuleI(Character, ItemAvoidanceCap))); + return Strings::Commify(std::to_string(client->GetAvoidance())) + " / " + + Strings::Commify(std::to_string(RuleI(Character, ItemAvoidanceCap))); } if (attribute == "strikethrough") { - return Strings::Commify(std::to_string((int) client->GetStrikeThrough())) + " / " + - Strings::Commify(std::to_string((int) RuleI(Character, ItemStrikethroughCap))); + return Strings::Commify(std::to_string(client->GetStrikeThrough())) + " / " + + Strings::Commify(std::to_string(RuleI(Character, ItemStrikethroughCap))); } if (attribute == "accuracy") { - return Strings::Commify(std::to_string((int) client->GetAccuracy())) + " / " + - Strings::Commify(std::to_string((int) RuleI(Character, ItemAccuracyCap))); + return Strings::Commify(std::to_string(client->GetAccuracy())) + " / " + + Strings::Commify(std::to_string(RuleI(Character, ItemAccuracyCap))); } if (attribute == "combat_effects") { - return Strings::Commify(std::to_string((int) client->GetCombatEffects())) + " / " + - Strings::Commify(std::to_string((int) RuleI(Character, ItemCombatEffectsCap))); + return Strings::Commify(std::to_string(client->GetCombatEffects())) + " / " + + Strings::Commify(std::to_string(RuleI(Character, ItemCombatEffectsCap))); } if (attribute == "heal_amount") { - return Strings::Commify(std::to_string((int) client->GetHealAmt())) + " / " + - Strings::Commify(std::to_string((int) RuleI(Character, ItemHealAmtCap))); + return Strings::Commify(std::to_string(client->GetHealAmt())) + " / " + + Strings::Commify(std::to_string(RuleI(Character, ItemHealAmtCap))); } if (attribute == "spell_dmg") { - return Strings::Commify(std::to_string((int) client->GetSpellDmg())) + " / " + - Strings::Commify(std::to_string((int) RuleI(Character, ItemSpellDmgCap))); + return Strings::Commify(std::to_string(client->GetSpellDmg())) + " / " + + Strings::Commify(std::to_string(RuleI(Character, ItemSpellDmgCap))); } if (attribute == "clairvoyance") { - return Strings::Commify(std::to_string((int) client->GetClair())) + " / " + - Strings::Commify(std::to_string((int) RuleI(Character, ItemClairvoyanceCap))); + return Strings::Commify(std::to_string(client->GetClair())) + " / " + + Strings::Commify(std::to_string(RuleI(Character, ItemClairvoyanceCap))); } if (attribute == "ds_mitigation") { - return Strings::Commify(std::to_string((int) client->GetDSMit())) + " / " + - Strings::Commify(std::to_string((int) RuleI(Character, ItemDSMitigationCap))); + return Strings::Commify(std::to_string(client->GetDSMit())) + " / " + + Strings::Commify(std::to_string(RuleI(Character, ItemDSMitigationCap))); } if (attribute == "hp_regen") { - return Strings::Commify(std::to_string((int64) client->GetHPRegen())) + " / " + - Strings::Commify(std::to_string((int) RuleI(Character, ItemHealthRegenCap))); + return Strings::Commify(std::to_string(client->GetHPRegen())) + " / " + + Strings::Commify(std::to_string(RuleI(Character, ItemHealthRegenCap))); } if (attribute == "mana_regen") { - return Strings::Commify(std::to_string((int64) client->GetManaRegen())) + " / " + + return Strings::Commify(std::to_string(client->GetManaRegen())) + " / " + Strings::Commify(std::to_string((int64) RuleI(Character, ItemManaRegenCap))); } if (attribute == "end_regen") { @@ -500,7 +521,7 @@ inline std::string GetMobAttributeByString(Mob *mob, const std::string &attribut inline std::string WriteDisplayInfoSection( Mob *mob, const std::string §ion_name, - std::vector attributes_list, + const std::vector& attributes_list, int column_count = 3, bool display_section_name = false ) @@ -539,7 +560,7 @@ inline std::string WriteDisplayInfoSection( if (attribute_name.find('_') != std::string::npos) { auto split_string = Strings::Split(attribute_name, '_'); std::string new_attribute_name; - for (std::string &string_value : split_string) { + for (const std::string &string_value : split_string) { new_attribute_name += Strings::UcFirst(string_value) + " "; } attribute_name = new_attribute_name; @@ -725,10 +746,12 @@ void Mob::DisplayInfo(Mob *mob) "min_hit", "max_hit", "hp_regen", + "hp_regen_per_second", "attack_delay", "spell_scale", "heal_scale", "avoidance", + "heroic_strikethrough", }; window_text += WriteDisplayInfoSection(mob, "NPC Stats", npc_stats, 1, true); @@ -795,21 +818,19 @@ void Mob::DisplayInfo(Mob *mob) window_text += WriteDisplayInfoSection(mob, "Proximity", npc_proximity, 1, true); } - int8 npc_type = npc_scale_manager->GetNPCScalingType(npc); - std::string npc_type_string = npc_scale_manager->GetNPCScalingTypeName(npc); - client->Message( - 0, - "| # Target: %s Type: %i (%s)", - npc->GetCleanName(), - npc_type, - npc_type_string.c_str()); + Chat::White, + fmt::format( + "| # Target: {} Type: {} ({})", + npc->GetCleanName(), + npc_scale_manager->GetNPCScalingType(npc), + npc_scale_manager->GetNPCScalingTypeName(npc) + ).c_str() + ); NPCCommandsMenu(client, npc); } - // std::cout << "Window Length: " << window_text.length() << std::endl; - if (client->GetDisplayMobInfoWindow()) { client->SendFullPopup( "GM: Entity Info", diff --git a/zone/mob_movement_manager.cpp b/zone/mob_movement_manager.cpp index 001bee9db..530fd3f5a 100644 --- a/zone/mob_movement_manager.cpp +++ b/zone/mob_movement_manager.cpp @@ -138,7 +138,7 @@ public: return true; } - //Send a movement packet when you start moving + //Send a movement packet when you start moving double current_time = static_cast(Timer::GetCurrentTime()) / 1000.0; int current_speed = 0; @@ -236,7 +236,7 @@ public: if (RuleB(Map, FixZWhenPathing)) { m_distance_moved_since_correction += distance_moved; - if (m_distance_moved_since_correction > RuleR(Map, DistanceCanTravelBeforeAdjustment)) { + if (m_distance_moved_since_correction > (mob->IsEngaged() ? 1 : 10)) { m_distance_moved_since_correction = 0.0; mob->FixZ(); } @@ -1053,6 +1053,13 @@ void MobMovementManager::FillCommandStruct( position_update->delta_z = FloatToEQ13(delta_z); position_update->delta_heading = FloatToEQ10(delta_heading); position_update->animation = (mob->IsBot() ? (int) ((float) anim / 1.785714f) : anim); + + if (RuleB(Map, MobPathingVisualDebug)) { + mob->DrawDebugCoordinateNode( + fmt::format("{} position update", mob->GetCleanName()), + mob->GetPosition() + ); + } } /** @@ -1093,7 +1100,7 @@ void MobMovementManager::UpdatePath(Mob *who, float x, float y, float z, MobMove } // Below for npcs that can traverse land or water so they don't sink else if (who->GetFlyMode() == GravityBehavior::Water && - zone->watermap->InLiquid(who->GetPosition()) && + zone->watermap->InLiquid(who->GetPosition()) && zone->watermap->InLiquid(glm::vec3(x, y, z)) && zone->zonemap->CheckLoS(who->GetPosition(), glm::vec3(x, y, z))) { auto iter = _impl->Entries.find(who); diff --git a/zone/mod_functions.cpp b/zone/mod_functions.cpp deleted file mode 100644 index 9b7520f67..000000000 --- a/zone/mod_functions.cpp +++ /dev/null @@ -1,188 +0,0 @@ -#include "client.h" -#include "entity.h" -#include "mob.h" -#include "npc.h" -#include "worldserver.h" -#include "zone.h" - -class Spawn2; -struct Consider_Struct; -struct DBTradeskillRecipe_Struct; - -namespace EQ -{ - class ItemInstance; -} - -extern EntityList entity_list; -extern Zone* zone; - -extern WorldServer worldserver; - -//All functions that modify a value are passed the value as it was computed by default formulas and bonuses. In most cases this should be the final value that will be used. - -//These are called when a zone boots or is repopped -void Zone::mod_init() { return; } -void Zone::mod_repop() { return; } - -//Pre-spawn hook called from the NPC object to be spawned -void NPC::mod_prespawn(Spawn2 *sp) { return; } - -//Base damage from NPC::Attack -int NPC::mod_npc_damage(int64 damage, EQ::skills::SkillType skillinuse, int hand, const EQ::ItemData* weapon, Mob* other) { return(damage); } - -//Mob c has been given credit for a kill. This is called after the regular EVENT_KILLED_MERIT event. -void NPC::mod_npc_killed_merit(Mob* c) { return; } - -//Mob oos has been given credit for a kill. This is called after the regular EVENT_DEATH event. -void NPC::mod_npc_killed(Mob* oos) { return; } - -//Base damage from Client::Attack - can cover myriad skill types -int Client::mod_client_damage(int64 damage, EQ::skills::SkillType skillinuse, int hand, const EQ::ItemInstance* weapon, Mob* other) { return(damage); } - -//message is char[4096], don't screw it up. Return true for normal behavior, false to return immediately. -// Channels: -// 0 - Guild Chat -// 2 - Group Chat -// 3 - Shout -// 4 - Auction -// 5 - Out of Character -// 6 - Broadcast -// 7 - Tell -// 8 - Say -// 11 - GMSay -// 15 - Raid Chat -// 20 - UCS Relay for UF client and later -// 22 - Emotes for UF and later -bool Client::mod_client_message(char* message, uint8 chan_num) { return(true); } - -//Skillup override. When this is called the regular skillup check has failed. Return false to proceed with default behavior. -//This will NOT allow a client to increase skill past a cap. -bool Client::mod_can_increase_skill(EQ::skills::SkillType skillid, Mob* against_who) { return(false); } - -//chance of general skill increase, rolled against 0-99 where higher chance is better. -double Client::mod_increase_skill_chance(double chance, Mob* against_who) { return(chance); } - -//Max percent of health you can bind wound starting with default value for class, item, and AA bonuses -int Client::mod_bindwound_percent(int max_percent, Mob* bindmob) { return(max_percent); } - -//Final bind HP value after bonuses -int Client::mod_bindwound_hp(int bindhps, Mob* bindmob) { return(bindhps); } - -//Client haste as calculated by default formulas - In percent from 0-100 -int Client::mod_client_haste(int h) { return(h); } - -//Haste cap override -int Client::mod_client_haste_cap(int cap) { return(cap); } - -//This is called when a client cons a mob -void Client::mod_consider(Mob* tmob, Consider_Struct* con) { return; } - -//Return true to continue with normal behavior, false returns in the parent function -bool Client::mod_saylink(const std::string& response, bool silentsaylink) { return(true); } - -//Client pet power as calculated by default formulas and bonuses -int16 Client::mod_pet_power(int16 act_power, uint16 spell_id) { return(act_power); } - -//Chance to combine rolled against a random 0-99 where higher is better. -float Client::mod_tradeskill_chance(float chance, DBTradeskillRecipe_Struct *spec) { return(chance); } - -//Chance to skillup rolled against a random 0-99 where higher is better. -float Client::mod_tradeskill_skillup(float chance_stage2) { return(chance_stage2); } - -//Tribute value override -int32 Client::mod_tribute_item_value(int32 pts, const EQ::ItemInstance* item) { return(pts); } - -//Death reporting -void Client::mod_client_death_npc(Mob* killerMob) { return; } -void Client::mod_client_death_duel(Mob* killerMob) { return; } -void Client::mod_client_death_env() { return; } - -//Calculated xp before consider modifier, called whenever a client gets XP for killing a mob. -int64 Client::mod_client_xp(int64 in_xp, NPC *npc) { return(in_xp); } - -//Client XP formula. Changes here will cause clients to change level after gaining or losing xp. -//Either modify this before your server goes live, or be prepared to write a quest script that fixes levels. -//To adjust how much XP is given per kill, use mod_client_xp -uint32 Client::mod_client_xp_for_level(uint32 xp, uint16 check_level) { return(xp); } - -//Food and drink values as computed by consume requests. Return < 0 to abort the request. -int Client::mod_food_value(const EQ::ItemData *item, int change) { return(change); } -int Client::mod_drink_value(const EQ::ItemData *item, int change) { return(change); } - -//effect_vallue - Spell effect value as calculated by default formulas. You will want to ignore effects that don't lend themselves to scaling - pet ID's, gate coords, etc. -int Mob::mod_effect_value(int effect_value, uint16 spell_id, int effect_type, Mob* caster, uint16 caster_id) { return(effect_value); } - -//chancetohit - 0 to 100 percent - set over 1000 for a guaranteed hit -float Mob::mod_hit_chance(float chancetohit, EQ::skills::SkillType skillinuse, Mob* attacker) { return(chancetohit); } - -//Final riposte chance -float Mob::mod_riposte_chance(float ripostechance, Mob* attacker) { return(ripostechance); } - -//Final block chance -float Mob::mod_block_chance(float blockchance, Mob* attacker) { return(blockchance); } - -//Final parry chance -float Mob::mod_parry_chance(float parrychance, Mob* attacker) { return(parrychance); } - -//Final dodge chance -float Mob::mod_dodge_chance(float dodgechance, Mob* attacker) { return(dodgechance); } - -//Usually 15, a monk under this weight threshold gets an AC bonus -float Mob::mod_monk_weight(float monkweight, Mob* attacker) { return(monkweight); } - -//Mitigation rating is compared to incoming attack rating. Higher is better. -float Mob::mod_mitigation_rating(float mitigation_rating, Mob* attacker) { return(mitigation_rating); } -float Mob::mod_attack_rating(float attack_rating, Mob* defender) { return(attack_rating); } - -//Kick damage after all other bonuses are applied -int64 Mob::mod_kick_damage(int64 dmg) { return(dmg); } - -//Slam and bash damage after all other bonuses are applied -int64 Mob::mod_bash_damage(int64 dmg) { return(dmg); } - -//Frenzy damage after all other bonuses are applied -int64 Mob::mod_frenzy_damage(int64 dmg) { return(dmg); } - -//Special attack damage after all other bonuses are applied. -int64 Mob::mod_monk_special_damage(int64 ndamage, EQ::skills::SkillType skill_type) { return(ndamage); } - -//ndamage - Backstab damage as calculated by default formulas -int64 Mob::mod_backstab_damage(int64 ndamage) { return(ndamage); } - -//Chance for 50+ archery bonus damage if Combat:UseArcheryBonusRoll is true. -int64 Mob::mod_archery_bonus_chance(int bonuschance, const EQ::ItemInstance* RangeWeapon) { return(bonuschance); } - -//Archery bonus damage -uint64 Mob::mod_archery_bonus_damage(uint64 MaxDmg, const EQ::ItemInstance* RangeWeapon) { return(MaxDmg); } - -//Final archery damage including bonus if it was applied. -int64 Mob::mod_archery_damage(int64 TotalDmg, bool hasbonus, const EQ::ItemInstance* RangeWeapon) { return(TotalDmg); } - -//Thrown weapon damage after all other calcs -uint64 Mob::mod_throwing_damage(uint64 MaxDmg) { return(MaxDmg); } - -//Spell cast time in milliseconds - will not sync with client cast time bar, but does work. -int32 Mob::mod_cast_time(int32 cast_time) { return(cast_time); } - -//res - Default buff duration formula -int Mob::mod_buff_duration(int res, Mob* caster, Mob* target, uint16 spell_id) { return(res); } - -//Spell stack override - If this returns anything < 2, it will ignore all other stacking rules. -// See spells.cpp: Mob::CheckStackConflict -// 0 - No conflict -// 1 - Overwrite, spellid1 is replaced by spellid2 -// -1 - Blocked, spellid2 will not land -// 2 - Default stacking behavior -int Mob::mod_spell_stack(uint16 spellid1, int caster_level1, Mob* caster1, uint16 spellid2, int caster_level2, Mob* caster2) { return(2); } - -//Sum of various resists rolled against a value of 200. -int Mob::mod_spell_resist(int resist_chance, int level_mod, int resist_modifier, int target_resist, uint8 resist_type, uint16 spell_id, Mob* caster) { - return(resist_chance); -} - -//Spell is cast by this on spelltar, called from spellontarget after the event_cast_on NPC event -void Mob::mod_spell_cast(uint16 spell_id, Mob* spelltar, bool reflect, bool use_resist_adjust, int16 resist_adjust, bool isproc) { return; } - -//At this point all applicable aggro checks have succeeded. Attacker should aggro unless we return false. -bool Mob::mod_will_aggro(Mob *attacker, Mob *on) { return(true); } diff --git a/zone/mod_functions_base.cpp b/zone/mod_functions_base.cpp deleted file mode 100644 index fc6d915c9..000000000 --- a/zone/mod_functions_base.cpp +++ /dev/null @@ -1,187 +0,0 @@ -#include "../common/debug.h" -#include "../common/timer.h" -#include -#include -#include "spawn2.h" -#include "entity.h" -#include "masterentity.h" -#include "zone.h" -#include "spawngroup.h" -#include "zonedb.h" -#include "../common/zone_store.h" -#include "npc.h" -#include "mob.h" -#include "client.h" -#include "worldserver.h" -#include "quest_parser_collection.h" -#include "event_codes.h" -#include "embparser.h" -#include -#include - -extern EntityList entity_list; -extern Zone* zone; - -extern WorldServer worldserver; - -//All functions that modify a value are passed the value as it was computed by default formulas and bonuses. In most cases this should be the final value that will be used. - -//These are called when a zone boots or is repopped -void Zone::mod_init() { return; } -void Zone::mod_repop() { return; } - -//Pre-spawn hook called from the NPC object to be spawned -void NPC::mod_prespawn(Spawn2 *sp) { return; } - -//Base damage from NPC::Attack -int NPC::mod_npc_damage(int64 damage, SkillType skillinuse, int hand, const Item_Struct* weapon, Mob* other) { return(damage); } - -//Mob c has been given credit for a kill. This is called after the regular EVENT_KILLED_MERIT event. -void NPC::mod_npc_killed_merit(Mob* c) { return; } - -//Mob oos has been given credit for a kill. This is called after the regular EVENT_DEATH event. -void NPC::mod_npc_killed(Mob* oos) { return; } - -//Base damage from Client::Attack - can cover myriad skill types -int Client::mod_client_damage(int64 damage, SkillType skillinuse, int hand, const ItemInst* weapon, Mob* other) { return(damage); } - -//message is char[4096], don't screw it up. Return true for normal behavior, false to return immediately. -// Channels: -// 0 - Guild Chat -// 2 - Group Chat -// 3 - Shout -// 4 - Auction -// 5 - Out of Character -// 6 - Broadcast -// 7 - Tell -// 8 - Say -// 11 - GMSay -// 15 - Raid Chat -// 20 - UCS Relay for UF client and later -// 22 - Emotes for UF and later -bool Client::mod_client_message(char* message, uint8 chan_num) { return(true); } - -//Skillup override. When this is called the regular skillup check has failed. Return false to proceed with default behavior. -//This will NOT allow a client to increase skill past a cap. -bool Client::mod_can_increase_skill(SkillType skillid, Mob* against_who) { return(false); } - -//chance of general skill increase, rolled against 0-99 where higher chance is better. -int16 Client::mod_increase_skill_chance(int16 chance, Mob* against_who) { return(chance); } - -//Max percent of health you can bind wound starting with default value for class, item, and AA bonuses -int Client::mod_bindwound_percent(int max_percent, Mob* bindmob) { return(max_percent); } - -//Final bind HP value after bonuses -int Client::mod_bindwound_hp(int bindhps, Mob* bindmob) { return(bindhps); } - -//Client haste as calculated by default formulas - In percent from 0-100 -int Client::mod_client_haste(int h) { return(h); } - -//Haste cap override -int Client::mod_client_haste_cap(int cap) { return(cap); } - -//This is called when a client cons a mob -void Client::mod_consider(Mob* tmob, Consider_Struct* con) { return; } - -//Return true to continue with normal behavior, false returns in the parent function -bool Client::mod_saylink(const std::string& response, bool silentsaylink) { return(true); } - -//Client pet power as calculated by default formulas and bonuses -int16 Client::mod_pet_power(int16 act_power, uint16 spell_id) { return(act_power); } - -//Chance to combine rolled against a random 0-99 where higher is better. -float Client::mod_tradeskill_chance(float chance, DBTradeskillRecipe_Struct *spec) { return(chance); } - -//Chance to skillup rolled against a random 0-99 where higher is better. -float Client::mod_tradeskill_skillup(float chance_stage2) { return(chance_stage2); } - -//Tribute value override -int32 Client::mod_tribute_item_value(int32 pts, const ItemInst* item) { return(pts); } - -//Death reporting -void Client::mod_client_death_npc(Mob* killerMob) { return; } -void Client::mod_client_death_duel(Mob* killerMob) { return; } -void Client::mod_client_death_env() { return; } - -//Calculated xp before consider modifier, called whenever a client gets XP for killing a mob. -int64 Client::mod_client_xp(int64 in_xp, NPC *npc) { return(in_xp); } - -//Client XP formula. Changes here will cause clients to change level after gaining or losing xp. -//Either modify this before your server goes live, or be prepared to write a quest script that fixes levels. -//To adjust how much XP is given per kill, use mod_client_xp -uint32 Client::mod_client_xp_for_level(uint32 xp, uint16 check_level) { return(xp); } - -//effect_vallue - Spell effect value as calculated by default formulas. You will want to ignore effects that don't lend themselves to scaling - pet ID's, gate coords, etc. -int Mob::mod_effect_value(int effect_value, uint16 spell_id, int effect_type, Mob* caster) { return(effect_value); } - -//chancetohit - 0 to 100 percent - set over 1000 for a guaranteed hit -float Mob::mod_hit_chance(float chancetohit, SkillType skillinuse, Mob* attacker) { return(chancetohit); } - -//Final riposte chance -float Mob::mod_riposte_chance(float ripostechance, Mob* attacker) { return(ripostechance); } - -//Final block chance -float Mob::mod_block_chance(float blockchance, Mob* attacker) { return(blockchance); } - -//Final parry chance -float Mob::mod_parry_chance(float parrychance, Mob* attacker) { return(parrychance); } - -//Final dodge chance -float Mob::mod_dodge_chance(float dodgechance, Mob* attacker) { return(dodgechance); } - -//Usually 15, a monk under this weight threshold gets an AC bonus -float Mob::mod_monk_weight(float monkweight, Mob* attacker) { return(monkweight); } - -//Mitigation rating is compared to incoming attack rating. Higher is better. -float Mob::mod_mitigation_rating(float mitigation_rating, Mob* attacker) { return(mitigation_rating); } -float Mob::mod_attack_rating(float attack_rating, Mob* defender) { return(attack_rating); } - -//Kick damage after all other bonuses are applied -int64 Mob::mod_kick_damage(int64 dmg) { return(dmg); } - -//Slam and bash damage after all other bonuses are applied -int64 Mob::mod_bash_damage(int64 dmg) { return(dmg); } - -//Frenzy damage after all other bonuses are applied -int64 Mob::mod_frenzy_damage(int64 dmg) { return(dmg); } - -//Special attack damage after all other bonuses are applied. -int64 Mob::mod_monk_special_damage(int64 ndamage, EQ::skills::SkillType skill_type) { return(ndamage); } - -//ndamage - Backstab damage as calculated by default formulas -int64 Mob::mod_backstab_damage(int64 ndamage) { return(ndamage); } - -//Chance for 50+ archery bonus damage if Combat:UseArcheryBonusRoll is true. -int64 Mob::mod_archery_bonus_chance(int bonuschance, const ItemInst* RangeWeapon) { return(bonuschance); } - -//Archery bonus damage -uint64 Mob::mod_archery_bonus_damage(uint64 MaxDmg, const ItemInst* RangeWeapon) { return(MaxDmg); } - -//Final archery damage including bonus if it was applied. -int64 Mob::mod_archery_damage(int64 TotalDmg, bool hasbonus, const ItemInst* RangeWeapon) { return(TotalDmg); } - -//Thrown weapon damage after all other calcs -uint64 Mob::mod_throwing_damage(uint64 MaxDmg) { return(MaxDmg); } - -//Spell cast time in milliseconds - will not sync with client cast time bar, but does work. -int32 Mob::mod_cast_time(int32 cast_time) { return(cast_time); } - -//res - Default buff duration formula -int Mob::mod_buff_duration(int res, Mob* caster, Mob* target, uint16 spell_id) { return(res); } - -//Spell stack override - If this returns anything < 2, it will ignore all other stacking rules. -// See spells.cpp: Mob::CheckStackConflict -// 0 - No conflict -// 1 - Overwrite, spellid1 is replaced by spellid2 -// -1 - Blocked, spellid2 will not land -// 2 - Default stacking behavior -int Mob::mod_spell_stack(uint16 spellid1, int caster_level1, Mob* caster1, uint16 spellid2, int caster_level2, Mob* caster2) { return(2); } - -//Sum of various resists rolled against a value of 200. -int Mob::mod_spell_resist(int resist_chance, int level_mod, int resist_modifier, int target_resist, uint8 resist_type, uint16 spell_id, Mob* caster) { - int final = resist_chance + level_mod + resist_modifier + target_resist; - return(final); -} - -//Spell is cast by this on spelltar, called from spellontarget after the event_cast_on NPC event -void Mob::mod_spell_cast(uint16 spell_id, Mob* spelltar, bool reflect, bool use_resist_adjust, int16 resist_adjust, bool isproc) { return; } diff --git a/zone/npc.cpp b/zone/npc.cpp index d09e1bd45..652017690 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #ifdef _WINDOWS #define snprintf _snprintf @@ -159,43 +160,47 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi if (race == RACE_LAVA_DRAGON_49) { size = 5; } + if (race == RACE_WURM_158) { + size = 15; + } - taunting = false; - proximity = nullptr; - copper = 0; - silver = 0; - gold = 0; - platinum = 0; - max_dmg = npc_type_data->max_dmg; - min_dmg = npc_type_data->min_dmg; - attack_count = npc_type_data->attack_count; - grid = 0; - wp_m = 0; - max_wp = 0; - save_wp = 0; - spawn_group_id = 0; - swarmInfoPtr = nullptr; - spellscale = npc_type_data->spellscale; - healscale = npc_type_data->healscale; - pAggroRange = npc_type_data->aggroradius; - pAssistRange = npc_type_data->assistradius; - findable = npc_type_data->findable; - trackable = npc_type_data->trackable; - MR = npc_type_data->MR; - CR = npc_type_data->CR; - DR = npc_type_data->DR; - FR = npc_type_data->FR; - PR = npc_type_data->PR; - Corrup = npc_type_data->Corrup; - PhR = npc_type_data->PhR; - STR = npc_type_data->STR; - STA = npc_type_data->STA; - AGI = npc_type_data->AGI; - DEX = npc_type_data->DEX; - INT = npc_type_data->INT; - WIS = npc_type_data->WIS; - CHA = npc_type_data->CHA; - npc_mana = npc_type_data->Mana; + taunting = false; + proximity = nullptr; + copper = 0; + silver = 0; + gold = 0; + platinum = 0; + max_dmg = npc_type_data->max_dmg; + min_dmg = npc_type_data->min_dmg; + attack_count = npc_type_data->attack_count; + grid = 0; + wp_m = 0; + max_wp = 0; + save_wp = 0; + spawn_group_id = 0; + swarmInfoPtr = nullptr; + spellscale = npc_type_data->spellscale; + healscale = npc_type_data->healscale; + pAggroRange = npc_type_data->aggroradius; + pAssistRange = npc_type_data->assistradius; + findable = npc_type_data->findable; + trackable = npc_type_data->trackable; + MR = npc_type_data->MR; + CR = npc_type_data->CR; + DR = npc_type_data->DR; + FR = npc_type_data->FR; + PR = npc_type_data->PR; + Corrup = npc_type_data->Corrup; + PhR = npc_type_data->PhR; + STR = npc_type_data->STR; + STA = npc_type_data->STA; + AGI = npc_type_data->AGI; + DEX = npc_type_data->DEX; + INT = npc_type_data->INT; + WIS = npc_type_data->WIS; + CHA = npc_type_data->CHA; + npc_mana = npc_type_data->Mana; + m_is_underwater_only = npc_type_data->underwater; //quick fix of ordering if they screwed it up in the DB if (max_dmg < min_dmg) { @@ -254,15 +259,18 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi } guard_anim = eaStanding; - roambox_distance = 0; - roambox_max_x = -2; - roambox_max_y = -2; - roambox_min_x = -2; - roambox_min_y = -2; - roambox_destination_x = -2; - roambox_destination_y = -2; - roambox_min_delay = 1000; - roambox_delay = 1000; + + m_roambox.max_x = -2; + m_roambox.max_y = -2; + m_roambox.min_x = -2; + m_roambox.min_y = -2; + m_roambox.distance = 0; + m_roambox.dest_x = -2; + m_roambox.dest_y = -2; + m_roambox.dest_z = 0; + m_roambox.delay = 1000; + m_roambox.min_delay = 1000; + p_depop = false; loottable_id = npc_type_data->loottable_id; skip_global_loot = npc_type_data->skip_global_loot; @@ -371,16 +379,16 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi } } - ldon_trapped = false; - ldon_trap_type = 0; - ldon_spell_id = 0; - ldon_locked = false; - ldon_locked_skill = 0; - ldon_trap_detected = false; + SetLDoNTrapped(false); + SetLDoNTrapType(0); + SetLDoNTrapSpellID(0); + SetLDoNLocked(false); + SetLDoNLockedSkill(0); + SetLDoNTrapDetected(false); if (npc_type_data->trap_template > 0) { std::map >::iterator trap_ent_iter; - std::list trap_list; + std::list trap_list; trap_ent_iter = zone->ldon_trap_entry_list.find(npc_type_data->trap_template); if (trap_ent_iter != zone->ldon_trap_entry_list.end()) { @@ -390,26 +398,25 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi std::advance(trap_list_iter, zone->random.Int(0, trap_list.size() - 1)); LDoNTrapTemplate *trap_template = (*trap_list_iter); if (trap_template) { - if ((uint8) trap_template->spell_id > 0) { - ldon_trapped = true; - ldon_spell_id = trap_template->spell_id; - } - else { - ldon_trapped = false; - ldon_spell_id = 0; + if (trap_template->spell_id > 0) { + SetLDoNTrapped(true); + SetLDoNTrapSpellID(trap_template->spell_id); + } else { + SetLDoNTrapped(false); + SetLDoNTrapSpellID(0); } - ldon_trap_type = (uint8) trap_template->type; + SetLDoNTrapType(static_cast(trap_template->type)); + if (trap_template->locked > 0) { - ldon_locked = true; - ldon_locked_skill = trap_template->skill; - } - else { - ldon_locked = false; - ldon_locked_skill = 0; + SetLDoNLocked(true); + SetLDoNLockedSkill(trap_template->skill); + } else { + SetLDoNLocked(false); + SetLDoNLockedSkill(0); } - ldon_trap_detected = 0; + SetLDoNTrapDetected(false); } } } @@ -440,52 +447,52 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi float NPC::GetRoamboxMaxX() const { - return roambox_max_x; + return m_roambox.max_x; } float NPC::GetRoamboxMaxY() const { - return roambox_max_y; + return m_roambox.max_y; } float NPC::GetRoamboxMinX() const { - return roambox_min_x; + return m_roambox.min_x; } float NPC::GetRoamboxMinY() const { - return roambox_min_y; + return m_roambox.min_y; } float NPC::GetRoamboxDistance() const { - return roambox_distance; + return m_roambox.distance; } float NPC::GetRoamboxDestinationX() const { - return roambox_destination_x; + return m_roambox.dest_x; } float NPC::GetRoamboxDestinationY() const { - return roambox_destination_y; + return m_roambox.dest_y; } float NPC::GetRoamboxDestinationZ() const { - return roambox_destination_z; + return m_roambox.dest_z; } uint32 NPC::GetRoamboxDelay() const { - return roambox_delay; + return m_roambox.delay; } uint32 NPC::GetRoamboxMinDelay() const { - return roambox_min_delay; + return m_roambox.min_delay; } NPC::~NPC() @@ -898,7 +905,10 @@ bool NPC::Process() } if (tic_timer.Check()) { - parse->EventNPC(EVENT_TICK, this, nullptr, "", 0); + if (parse->HasQuestSub(GetNPCTypeID(), EVENT_TICK)) { + parse->EventNPC(EVENT_TICK, this, nullptr, "", 0); + } + BuffProcess(); if (currently_fleeing) { @@ -1114,11 +1124,21 @@ void NPC::Depop(bool start_spawn_timer) { } if (IsNPC()) { - parse->EventNPC(EVENT_DESPAWN, this, nullptr, "", 0); - DispatchZoneControllerEvent(EVENT_DESPAWN_ZONE, this, "", 0, nullptr); + if (parse->HasQuestSub(GetNPCTypeID(), EVENT_DESPAWN)) { + parse->EventNPC(EVENT_DESPAWN, this, nullptr, "", 0); + } + + if (parse->HasQuestSub(ZONE_CONTROLLER_NPC_ID, EVENT_DESPAWN_ZONE)) { + DispatchZoneControllerEvent(EVENT_DESPAWN_ZONE, this, "", 0, nullptr); + } } else if (IsBot()) { - parse->EventBot(EVENT_DESPAWN, CastToBot(), nullptr, "", 0); - DispatchZoneControllerEvent(EVENT_DESPAWN_ZONE, this, "", 0, nullptr); + if (parse->BotHasQuestSub(EVENT_DESPAWN)) { + parse->EventBot(EVENT_DESPAWN, CastToBot(), nullptr, "", 0); + } + + if (parse->HasQuestSub(ZONE_CONTROLLER_NPC_ID, EVENT_DESPAWN_ZONE)) { + DispatchZoneControllerEvent(EVENT_DESPAWN_ZONE, this, "", 0, nullptr); + } } p_depop = true; @@ -1375,7 +1395,7 @@ NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client* if (!sep.IsNumber(3)) { sprintf(sep.arg[3], "0"); } - if (atoi(sep.arg[4]) > 2100000000 || atoi(sep.arg[4]) <= 0) { + if (Strings::ToInt(sep.arg[4]) > 2100000000 || Strings::ToInt(sep.arg[4]) <= 0) { sprintf(sep.arg[4], " "); } if (!strcmp(sep.arg[5], "-")) { @@ -1409,7 +1429,7 @@ NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client* // Autoselect NPC Gender if (sep.arg[5][0] == 0) { - sprintf(sep.arg[5], "%i", (int) Mob::GetDefaultGender(atoi(sep.arg[1]))); + sprintf(sep.arg[5], "%i", (int) Mob::GetDefaultGender(Strings::ToInt(sep.arg[1]))); } //Time to create the NPC!! @@ -1417,22 +1437,22 @@ NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client* memset(npc_type, 0, sizeof(NPCType)); strncpy(npc_type->name, sep.arg[0], 60); - npc_type->current_hp = atoi(sep.arg[4]); - npc_type->max_hp = atoi(sep.arg[4]); - npc_type->race = atoi(sep.arg[1]); - npc_type->gender = atoi(sep.arg[5]); - npc_type->class_ = atoi(sep.arg[6]); + npc_type->current_hp = Strings::ToInt(sep.arg[4]); + npc_type->max_hp = Strings::ToInt(sep.arg[4]); + npc_type->race = Strings::ToInt(sep.arg[1]); + npc_type->gender = Strings::ToInt(sep.arg[5]); + npc_type->class_ = Strings::ToInt(sep.arg[6]); npc_type->deity = 1; - npc_type->level = atoi(sep.arg[2]); + npc_type->level = Strings::ToInt(sep.arg[2]); npc_type->npc_id = 0; npc_type->loottable_id = 0; - npc_type->texture = atoi(sep.arg[3]); + npc_type->texture = Strings::ToInt(sep.arg[3]); npc_type->light = 0; // spawncommand needs update npc_type->runspeed = 1.25; - npc_type->d_melee_texture1 = atoi(sep.arg[7]); - npc_type->d_melee_texture2 = atoi(sep.arg[8]); - npc_type->merchanttype = atoi(sep.arg[9]); - npc_type->bodytype = atoi(sep.arg[10]); + npc_type->d_melee_texture1 = Strings::ToInt(sep.arg[7]); + npc_type->d_melee_texture2 = Strings::ToInt(sep.arg[8]); + npc_type->merchanttype = Strings::ToInt(sep.arg[9]); + npc_type->bodytype = Strings::ToInt(sep.arg[10]); npc_type->STR = 0; npc_type->STA = 0; @@ -1495,7 +1515,7 @@ uint32 ZoneDatabase::CreateNewNPCCommand( if (results.Success()) { if (results.RowCount() != 0) { auto row = results.begin(); - npc_type_id = atoi(row[0]) + 1; + npc_type_id = Strings::ToInt(row[0]) + 1; // Prevent the npc_type id from exceeding the range for this zone if (npc_type_id >= (starting_npc_id + 1000)) { npc_type_id = 0; @@ -1654,10 +1674,10 @@ uint32 ZoneDatabase::DeleteSpawnLeaveInNPCTypeTable(const char *zone, Client *cl auto row = results.begin(); if (row[0]) - id = atoi(row[0]); + id = Strings::ToInt(row[0]); if (row[1]) - spawngroupID = atoi(row[1]); + spawngroupID = Strings::ToInt(row[1]); query = StringFormat("DELETE FROM spawn2 WHERE id = '%i'", id); results = QueryDatabase(query); @@ -1696,10 +1716,10 @@ uint32 ZoneDatabase::DeleteSpawnRemoveFromNPCTypeTable(const char *zone, uint32 auto row = results.begin(); if (row[0]) - id = atoi(row[0]); + id = Strings::ToInt(row[0]); if (row[1]) - spawngroupID = atoi(row[1]); + spawngroupID = Strings::ToInt(row[1]); query = StringFormat("DELETE FROM spawn2 WHERE id = '%i'", id); results = QueryDatabase(query); @@ -2452,7 +2472,7 @@ void NPC::SetLevel(uint8 in_level, bool command) SendAppearancePacket(AT_WhoLevel, in_level); } -void NPC::ModifyNPCStat(std::string stat, std::string value) +void NPC::ModifyNPCStat(const std::string& stat, const std::string& value) { auto stat_lower = Strings::ToLower(stat); @@ -2466,43 +2486,43 @@ void NPC::ModifyNPCStat(std::string stat, std::string value) LogNPCScaling("NPC::ModifyNPCStat: Key [{}] Value [{}] ", variable_key, value); if (stat_lower == "ac") { - AC = atoi(value.c_str()); + AC = Strings::ToInt(value); CalcAC(); return; } else if (stat_lower == "str") { - STR = atoi(value.c_str()); + STR = Strings::ToInt(value); return; } else if (stat_lower == "sta") { - STA = atoi(value.c_str()); + STA = Strings::ToInt(value); return; } else if (stat_lower == "agi") { - AGI = atoi(value.c_str()); + AGI = Strings::ToInt(value); CalcAC(); return; } else if (stat_lower == "dex") { - DEX = atoi(value.c_str()); + DEX = Strings::ToInt(value); return; } else if (stat_lower == "wis") { - WIS = atoi(value.c_str()); + WIS = Strings::ToInt(value); CalcMaxMana(); return; } else if (stat_lower == "int" || stat_lower == "_int") { - INT = atoi(value.c_str()); + INT = Strings::ToInt(value); CalcMaxMana(); return; } else if (stat_lower == "cha") { - CHA = atoi(value.c_str()); + CHA = Strings::ToInt(value); return; } else if (stat_lower == "max_hp") { - base_hp = std::stoull(value.c_str()); + base_hp = Strings::ToBigInt(value); CalcMaxHP(); if (current_hp > max_hp) { @@ -2512,7 +2532,7 @@ void NPC::ModifyNPCStat(std::string stat, std::string value) return; } else if (stat_lower == "max_mana") { - npc_mana = std::stoull(value.c_str()); + npc_mana = Strings::ToUnsignedBigInt(value); CalcMaxMana(); if (current_mana > max_mana) { current_mana = max_mana; @@ -2520,36 +2540,36 @@ void NPC::ModifyNPCStat(std::string stat, std::string value) return; } else if (stat_lower == "mr") { - MR = atoi(value.c_str()); + MR = Strings::ToInt(value); return; } else if (stat_lower == "fr") { - FR = atoi(value.c_str()); + FR = Strings::ToInt(value); return; } else if (stat_lower == "cr") { - CR = atoi(value.c_str()); + CR = Strings::ToInt(value); return; } else if (stat_lower == "cor") { - Corrup = atoi(value.c_str()); + Corrup = Strings::ToInt(value); return; } else if (stat_lower == "pr") { - PR = atoi(value.c_str()); + PR = Strings::ToInt(value); return; } else if (stat_lower == "dr") { - DR = atoi(value.c_str()); + DR = Strings::ToInt(value); return; } else if (stat_lower == "phr") { - PhR = atoi(value.c_str()); + PhR = Strings::ToInt(value); return; } else if (stat_lower == "runspeed") { - runspeed = (float) atof(value.c_str()); - base_runspeed = (int) ((float) runspeed * 40.0f); + runspeed = Strings::ToFloat(value); + base_runspeed = (int) (runspeed * 40.0f); base_walkspeed = base_runspeed * 100 / 265; walkspeed = ((float) base_walkspeed) * 0.025f; base_fearspeed = base_runspeed * 100 / 127; @@ -2558,125 +2578,125 @@ void NPC::ModifyNPCStat(std::string stat, std::string value) return; } else if (stat_lower == "special_attacks") { - NPCSpecialAttacks(value.c_str(), 0, 1); + NPCSpecialAttacks(value.c_str(), 0, true); return; } else if (stat_lower == "special_abilities") { - ProcessSpecialAbilities(value.c_str()); + ProcessSpecialAbilities(value); return; } else if (stat_lower == "attack_speed") { - attack_speed = (float) atof(value.c_str()); + attack_speed = Strings::ToFloat(value); CalcBonuses(); return; } else if (stat_lower == "attack_delay") { /* TODO: fix DB */ - attack_delay = atoi(value.c_str()) * 100; + attack_delay = Strings::ToInt(value) * 100; CalcBonuses(); return; } else if (stat_lower == "atk") { - ATK = atoi(value.c_str()); + ATK = Strings::ToInt(value); return; } else if (stat_lower == "accuracy") { - accuracy_rating = atoi(value.c_str()); + accuracy_rating = Strings::ToInt(value); return; } else if (stat_lower == "avoidance") { - avoidance_rating = atoi(value.c_str()); + avoidance_rating = Strings::ToInt(value); return; } else if (stat_lower == "trackable") { - trackable = atoi(value.c_str()); + trackable = Strings::ToInt(value); return; } else if (stat_lower == "min_hit") { - min_dmg = atoi(value.c_str()); + min_dmg = Strings::ToInt(value); // TODO: fix DB base_damage = round((max_dmg - min_dmg) / 1.9); min_damage = min_dmg - round(base_damage / 10.0); return; } else if (stat_lower == "max_hit") { - max_dmg = atoi(value.c_str()); + max_dmg = Strings::ToInt(value); // TODO: fix DB base_damage = round((max_dmg - min_dmg) / 1.9); min_damage = min_dmg - round(base_damage / 10.0); return; } else if (stat_lower == "attack_count") { - attack_count = atoi(value.c_str()); + attack_count = Strings::ToInt(value); return; } else if (stat_lower == "see_invis") { - see_invis = atoi(value.c_str()); + see_invis = Strings::ToInt(value); return; } else if (stat_lower == "see_invis_undead") { - see_invis_undead = atoi(value.c_str()); + see_invis_undead = Strings::ToInt(value); return; } else if (stat_lower == "see_hide") { - see_hide = atoi(value.c_str()); + see_hide = Strings::ToInt(value); return; } else if (stat_lower == "see_improved_hide") { - see_improved_hide = atoi(value.c_str()); + see_improved_hide = Strings::ToInt(value); return; } else if (stat_lower == "hp_regen") { - hp_regen = strtoll(value.c_str(), nullptr, 10); + hp_regen = Strings::ToBigInt(value); return; } else if (stat_lower == "hp_regen_per_second") { - hp_regen_per_second = strtoll(value.c_str(), nullptr, 10); + hp_regen_per_second = Strings::ToBigInt(value); return; } else if (stat_lower == "mana_regen") { - mana_regen = strtoll(value.c_str(), nullptr, 10); + mana_regen = Strings::ToBigInt(value); return; } else if (stat_lower == "level") { - SetLevel(atoi(value.c_str())); + SetLevel(Strings::ToInt(value)); return; } else if (stat_lower == "aggro") { - pAggroRange = atof(value.c_str()); + pAggroRange = Strings::ToFloat(value); return; } else if (stat_lower == "assist") { - pAssistRange = atof(value.c_str()); + pAssistRange = Strings::ToFloat(value); return; } else if (stat_lower == "slow_mitigation") { - slow_mitigation = atoi(value.c_str()); + slow_mitigation = Strings::ToInt(value); return; } else if (stat_lower == "loottable_id") { - loottable_id = atof(value.c_str()); + loottable_id = Strings::ToFloat(value); return; } else if (stat_lower == "healscale") { - healscale = atof(value.c_str()); + healscale = Strings::ToFloat(value); return; } else if (stat_lower == "spellscale") { - spellscale = atof(value.c_str()); + spellscale = Strings::ToFloat(value); return; } else if (stat_lower == "npc_spells_id") { - AI_AddNPCSpells(atoi(value.c_str())); + AI_AddNPCSpells(Strings::ToInt(value)); return; } else if (stat_lower == "npc_spells_effects_id") { - AI_AddNPCSpellsEffects(atoi(value.c_str())); + AI_AddNPCSpellsEffects(Strings::ToInt(value)); CalcBonuses(); return; } else if (stat_lower == "heroic_strikethrough") { - heroic_strikethrough = atoi(value.c_str()); + heroic_strikethrough = Strings::ToInt(value); return; } else if (stat_lower == "keeps_sold_items") { @@ -2685,11 +2705,10 @@ void NPC::ModifyNPCStat(std::string stat, std::string value) } } -float NPC::GetNPCStat(std::string stat) +float NPC::GetNPCStat(const std::string& stat) { - auto stat_lower = Strings::ToLower(stat); - if (stat_lower == "ac") { + if (auto stat_lower = Strings::ToLower(stat); stat_lower == "ac") { return AC; } else if (stat_lower == "str") { @@ -2740,9 +2759,6 @@ float NPC::GetNPCStat(std::string stat) else if (stat_lower == "dr") { return DR; } - else if (stat_lower == "phr") { - return PhR; - } else if (stat_lower == "runspeed") { return runspeed; } @@ -2956,7 +2972,6 @@ void NPC::LevelScale() { } level = random_level; - return; } uint32 NPC::GetSpawnPointID() const @@ -3004,7 +3019,6 @@ void NPC::SetSwarmTarget(int target_id) { GetSwarmInfo()->target = target_id; } - return; } int64 NPC::CalcMaxMana() @@ -3017,7 +3031,6 @@ int64 NPC::CalcMaxMana() case 'W': max_mana = (((GetWIS() / 2) + 1) * GetLevel()) + spellbonuses.Mana + itembonuses.Mana; break; - case 'N': default: max_mana = 0; break; @@ -3036,7 +3049,6 @@ int64 NPC::CalcMaxMana() case 'W': max_mana = npc_mana + spellbonuses.Mana + itembonuses.Mana; break; - case 'N': default: max_mana = 0; break; @@ -3056,8 +3068,11 @@ void NPC::SignalNPC(int _signal_id) void NPC::SendPayload(int payload_id, std::string payload_value) { - const auto export_string = fmt::format("{} {}", payload_id, payload_value); - parse->EventNPC(EVENT_PAYLOAD, this, nullptr, export_string, 0); + if (parse->HasQuestSub(GetNPCTypeID(), EVENT_PAYLOAD)) { + const auto& export_string = fmt::format("{} {}", payload_id, payload_value); + + parse->EventNPC(EVENT_PAYLOAD, this, nullptr, export_string, 0); + } } NPC_Emote_Struct* NPC::GetNPCEmote(uint32 emoteid, uint8 event_) { @@ -3067,16 +3082,16 @@ NPC_Emote_Struct* NPC::GetNPCEmote(uint32 emoteid, uint8 event_) { { NPC_Emote_Struct* nes = iterator.GetData(); if (emoteid == nes->emoteid && event_ == nes->event_) { - return (nes); + return nes; } iterator.Advance(); } - return (nullptr); + return nullptr; } void NPC::DoNPCEmote(uint8 event_, uint32 emoteid) { - if(this == nullptr || emoteid == 0) + if (emoteid == 0) { return; } @@ -3692,7 +3707,7 @@ void NPC::ReloadSpells() { AI_AddNPCSpellsEffects(GetNPCSpellsEffectsID()); } -void NPC::ScaleNPC(uint8 npc_level) { +void NPC::ScaleNPC(uint8 npc_level, bool always_scale, bool override_special_abilities) { if (GetLevel() != npc_level) { SetLevel(npc_level); RecalculateSkills(); @@ -3700,7 +3715,7 @@ void NPC::ScaleNPC(uint8 npc_level) { } npc_scale_manager->ResetNPCScaling(this); - npc_scale_manager->ScaleNPC(this); + npc_scale_manager->ScaleNPC(this, always_scale, override_special_abilities); } bool NPC::IsGuard() @@ -3763,11 +3778,6 @@ void NPC::SetRecordLootStats(bool record_loot_stats) NPC::m_record_loot_stats = record_loot_stats; } -void NPC::FlushLootStats() -{ - m_rolled_items = {}; -} - const std::vector &NPC::GetRolledItems() const { return m_rolled_items; @@ -3784,3 +3794,168 @@ int NPC::GetRolledItemCount(uint32 item_id) return rolled_count; } + +void NPC::SendPositionToClients() +{ + auto p = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); + auto *s = (PlayerPositionUpdateServer_Struct *) p->pBuffer; + for (auto &c: entity_list.GetClientList()) { + MakeSpawnUpdate(s); + c.second->QueuePacket(p, false); + } + safe_delete(p); +} + +void NPC::HandleRoambox() +{ + bool has_arrived = GetCWP() == EQ::WaypointStatus::RoamBoxPauseInProgress && !IsMoving(); + if (has_arrived) { + int roambox_move_delay = EQ::ClampLower(GetRoamboxDelay(), GetRoamboxMinDelay()); + int move_delay_max = (roambox_move_delay > 0 ? roambox_move_delay : (int) GetRoamboxMinDelay() * 4); + int random_timer = RandomTimer( + GetRoamboxMinDelay(), + move_delay_max + ); + + LogNPCRoamBoxDetail( + "({}) random_timer [{}] roambox_move_delay [{}] move_min [{}] move_max [{}]", + GetCleanName(), + random_timer, + roambox_move_delay, + (int) GetRoamboxMinDelay(), + move_delay_max + ); + + time_until_can_move = Timer::GetCurrentTime() + random_timer; + SetCurrentWP(0); + return; + } + + bool ready_to_set_new_destination = !IsMoving() && time_until_can_move < Timer::GetCurrentTime(); + if (ready_to_set_new_destination) { + // make several attempts to find a valid next move in the box + bool can_path = false; + for (int i = 0; i < 10; i++) { + auto move_x = static_cast(zone->random.Real(-m_roambox.distance, m_roambox.distance)); + auto move_y = static_cast(zone->random.Real(-m_roambox.distance, m_roambox.distance)); + auto requested_x = EQ::Clamp((GetX() + move_x), m_roambox.min_x, m_roambox.max_x); + auto requested_y = EQ::Clamp((GetY() + move_y), m_roambox.min_y, m_roambox.max_y); + auto requested_z = GetGroundZ(requested_x, requested_y); + + std::vector heights = {0, 250, -250}; + for (auto &h: heights) { + if (CheckLosFN(requested_x, requested_y, requested_z + h, GetSize())) { + LogNPCRoamBox("[{}] Found line of sight to path attempt [{}] at height [{}]", GetCleanName(), i, h); + can_path = true; + break; + } + } + + if (!can_path) { + LogNPCRoamBox("[{}] | Failed line of sight to path attempt [{}]", GetCleanName(), i); + continue; + } + + m_roambox.dest_x = requested_x; + m_roambox.dest_y = requested_y; + + /** + * If our roambox was configured with large distances, chances of hitting the min or max end of + * the clamp is high, this causes NPC's to gather on the border of a box, to reduce clustering + * either lower the roambox distance or the code will do a simple random between min - max when it + * hits the min or max of the clamp + */ + if (m_roambox.dest_x == m_roambox.min_x || m_roambox.dest_x == m_roambox.max_x) { + m_roambox.dest_x = static_cast(zone->random.Real(m_roambox.min_x, m_roambox.max_x)); + } + + if (m_roambox.dest_y == m_roambox.min_y || m_roambox.dest_y == m_roambox.max_y) { + m_roambox.dest_y = static_cast(zone->random.Real(m_roambox.min_y, m_roambox.max_y)); + } + + // If mob was not spawned in water, let's not randomly roam them into water + // if the roam box was sloppily configured + if (!GetWasSpawnedInWater()) { + m_roambox.dest_z = GetGroundZ(m_roambox.dest_x, m_roambox.dest_y); + if (zone->HasMap() && zone->HasWaterMap()) { + auto position = glm::vec3( + m_roambox.dest_x, + m_roambox.dest_y, + m_roambox.dest_z + ); + + // If someone brought us into water when we naturally wouldn't path there, return to spawn + if (zone->watermap->InLiquid(position) && zone->watermap->InLiquid(m_Position)) { + m_roambox.dest_x = m_SpawnPoint.x; + m_roambox.dest_y = m_SpawnPoint.y; + } + + if (zone->watermap->InLiquid(position)) { + LogNPCRoamBoxDetail("[{}] | My destination is in water and I don't belong there!", GetCleanName()); + + return; + } + } + } + else { // Mob was in water, make sure new spot is in water also + m_roambox.dest_z = m_Position.z; + auto position = glm::vec3( + m_roambox.dest_x, + m_roambox.dest_y, + m_Position.z + 15 + ); + if (zone->HasWaterMap() && !zone->watermap->InLiquid(position)) { + m_roambox.dest_x = m_SpawnPoint.x; + m_roambox.dest_y = m_SpawnPoint.y; + m_roambox.dest_z = m_SpawnPoint.z; + } + } + + LogNPCRoamBox( + "[{}] | Pathing to [{}] [{}] [{}]", + GetCleanName(), + m_roambox.dest_x, + m_roambox.dest_y, + m_roambox.dest_z + ); + + LogNPCRoamBox( + "NPC ({}) distance [{}] X (min/max) [{} / {}] Y (min/max) [{} / {}] | Dest x/y/z [{} / {} / {}]", + GetCleanName(), + m_roambox.distance, + m_roambox.min_x, + m_roambox.max_x, + m_roambox.min_y, + m_roambox.max_y, + m_roambox.dest_x, + m_roambox.dest_y, + m_roambox.dest_z + ); + + if (can_path) { + SetCurrentWP(EQ::WaypointStatus::RoamBoxPauseInProgress); + NavigateTo(m_roambox.dest_x, m_roambox.dest_y, m_roambox.dest_z); + return; + } + } + + // failed to find path, reset timer + int roambox_move_delay = EQ::ClampLower(GetRoamboxDelay(), GetRoamboxMinDelay()); + int move_delay_max = (roambox_move_delay > 0 ? roambox_move_delay : (int) GetRoamboxMinDelay() * 4); + int random_timer = RandomTimer( + GetRoamboxMinDelay(), + move_delay_max + ); + time_until_can_move = Timer::GetCurrentTime() + random_timer; + } + + return; +} + +void NPC::SetTaunting(bool is_taunting) { + taunting = is_taunting; + + if (IsPet() && IsPetOwnerClient()) { + GetOwner()->CastToClient()->SetPetCommandState(PET_BUTTON_TAUNT, is_taunting); + } +} diff --git a/zone/npc.h b/zone/npc.h index aeaa2de1b..a33f649ad 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -80,6 +80,19 @@ struct AISpellsVar_Struct { uint8 idle_beneficial_chance; }; +struct Roambox { + float max_x; + float max_y; + float min_x; + float min_y; + float distance; + float dest_x; + float dest_y; + float dest_z; + uint32 delay; + uint32 min_delay; +}; + class SwarmPet; class Client; class Group; @@ -97,12 +110,10 @@ class NPC : public Mob public: static NPC* SpawnNPC(const char* spawncommand, const glm::vec4& position, Client* client = nullptr); static bool SpawnZoneController(); - static int8 GetAILevel(bool iForceReRead = false); // loot recording / simulator bool IsRecordLootStats() const; void SetRecordLootStats(bool record_loot_stats); - void FlushLootStats(); const std::vector &GetRolledItems() const; int GetRolledItemCount(uint32 item_id); @@ -119,7 +130,7 @@ public: virtual void Damage(Mob* from, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None); bool Attack(Mob* other, int Hand = EQ::invslot::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) override; - virtual bool HasRaid() { return false; } + virtual bool HasRaid() { return false; } virtual bool HasGroup() { return false; } virtual Raid* GetRaid() { return 0; } virtual Group* GetGroup() { return 0; } @@ -297,7 +308,7 @@ public: uint16 GetPetSpellID() const {return pet_spell_id;} void SetPetSpellID(uint16 amt) {pet_spell_id = amt;} uint32 GetMaxDamage(uint8 tlevel); - void SetTaunting(bool tog) {taunting = tog;} + void SetTaunting(bool is_taunting); bool IsTaunting() const { return taunting; } void PickPocket(Client* thief); void Disarm(Client* client, int chance); @@ -409,26 +420,26 @@ public: void SetAvoidanceRating(int32 d) { avoidance_rating = d;} int32 GetRawAC() const { return AC; } - float GetNPCStat(std::string stat); - void ModifyNPCStat(std::string stat, std::string value); + float GetNPCStat(const std::string& stat); + void ModifyNPCStat(const std::string& stat, const std::string& value); virtual void SetLevel(uint8 in_level, bool command = false); - bool IsLDoNTrapped() const { return (ldon_trapped); } + bool IsLDoNTrapped() const { return ldon_trapped; } void SetLDoNTrapped(bool n) { ldon_trapped = n; } - uint8 GetLDoNTrapType() const { return (ldon_trap_type); } + uint8 GetLDoNTrapType() const { return ldon_trap_type; } void SetLDoNTrapType(uint8 n) { ldon_trap_type = n; } - uint16 GetLDoNTrapSpellID() const { return (ldon_spell_id); } + uint16 GetLDoNTrapSpellID() const { return ldon_spell_id; } void SetLDoNTrapSpellID(uint16 n) { ldon_spell_id = n; } - bool IsLDoNLocked() const { return (ldon_locked); } + bool IsLDoNLocked() const { return ldon_locked; } void SetLDoNLocked(bool n) { ldon_locked = n; } - uint16 GetLDoNLockedSkill() const { return (ldon_locked_skill); } + uint16 GetLDoNLockedSkill() const { return ldon_locked_skill; } void SetLDoNLockedSkill(uint16 n) { ldon_locked_skill = n; } - bool IsLDoNTrapDetected() const { return (ldon_trap_detected); } + bool IsLDoNTrapDetected() const { return ldon_trap_detected; } void SetLDoNTrapDetected(bool n) { ldon_trap_detected = n; } const bool GetCombatEvent() const { return combat_event; } @@ -437,7 +448,7 @@ public: /* Only allows players that killed corpse to loot */ const bool HasPrivateCorpse() const { return NPCTypedata_ours ? NPCTypedata_ours->private_corpse : NPCTypedata->private_corpse; } - virtual const bool IsUnderwaterOnly() const { return NPCTypedata_ours ? NPCTypedata_ours->underwater : NPCTypedata->underwater; } + virtual const bool IsUnderwaterOnly() const { return m_is_underwater_only; } const char* GetRawNPCTypeName() const { return NPCTypedata_ours ? NPCTypedata_ours->name : NPCTypedata->name; } virtual int GetKillExpMod() const { return NPCTypedata_ours ? NPCTypedata_ours->exp_mod : NPCTypedata->exp_mod; } @@ -477,10 +488,6 @@ public: uint32 GetSpawnKillCount(); int GetScore(); - void mod_prespawn(Spawn2 *sp); - int mod_npc_damage(int64 damage, EQ::skills::SkillType skillinuse, int hand, const EQ::ItemData* weapon, Mob* other); - void mod_npc_killed_merit(Mob* c); - void mod_npc_killed(Mob* oos); void AISpellsList(Client *c); uint16 GetInnateProcSpellID() const { return innate_proc_spell_id; } @@ -531,15 +538,19 @@ public: inline bool IsSkipAutoScale() const { return skip_auto_scale; } - void ScaleNPC(uint8 npc_level); + void ScaleNPC(uint8 npc_level, bool always_scale = false, bool override_special_abilities = false); void RecalculateSkills(); void ReloadSpells(); + void SendPositionToClients(); + static LootDropEntries_Struct NewLootDropEntry(); protected: + void HandleRoambox(); + const NPCType* NPCTypedata; NPCType* NPCTypedata_ours; //special case for npcs with uniquely created data. @@ -578,7 +589,7 @@ protected: std::vector AIspells; bool HasAISpell; virtual bool AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes, bool bInnates = false); - virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0); + virtual bool AIDoSpellCast(int32 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0); AISpellsVar_Struct AISpellVar; int64 GetFocusEffect(focusType type, uint16 spell_id, Mob *caster = nullptr, bool from_buff_tic = false) override; uint16 innate_proc_spell_id; @@ -637,16 +648,8 @@ protected: glm::vec4 m_GuardPoint; glm::vec4 m_GuardPointSaved; EmuAppearance guard_anim; - float roambox_max_x; - float roambox_max_y; - float roambox_min_x; - float roambox_min_y; - float roambox_distance; - float roambox_destination_x; - float roambox_destination_y; - float roambox_destination_z; - uint32 roambox_delay; - uint32 roambox_min_delay; + + Roambox m_roambox = {}; uint16 skills[EQ::skills::HIGHEST_SKILL + 1]; @@ -672,6 +675,8 @@ protected: QGlobalCache *qGlobals; uint32 adventure_template_id; + bool m_is_underwater_only = false; + //mercenary stuff std::list mercTypeList; std::list mercDataList; diff --git a/zone/npc_ai.cpp b/zone/npc_ai.cpp deleted file mode 100644 index e69de29bb..000000000 diff --git a/zone/npc_ai.h b/zone/npc_ai.h deleted file mode 100644 index 21d5cbc4e..000000000 --- a/zone/npc_ai.h +++ /dev/null @@ -1,41 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef NPCAI_H -#define NPCAI_H -#include "../common/types.h" - - - -/* -Even con color is wrong and so is the message but i can't seem to find it with a for loop. -Seems more like a bitwise comparison client side.. - con->level = 2; // GREEN - con->level = 18; // LIGHT BLUE - con->level = 4; // BLUE - con->level = 20; // EVEN - con->level = 15; // YELLOW - con->level = 13; // RED -*/ -#define DEFAULT_AGGRORADIUS 70 -#define DEFAULT_FRENYRADIUS 70 -#define MAX_SHIELDRADIUS 20 - -uint32 GetLevelCon(uint8 PlayerLevel, uint8 NPCLevel); - -#endif diff --git a/zone/npc_scale_manager.cpp b/zone/npc_scale_manager.cpp index ac9cd3bee..191c76694 100644 --- a/zone/npc_scale_manager.cpp +++ b/zone/npc_scale_manager.cpp @@ -26,21 +26,31 @@ /** * @param npc */ -void NpcScaleManager::ScaleNPC(NPC *npc) -{ +void NpcScaleManager::ScaleNPC( + NPC *npc, + bool always_scale, + bool override_special_abilities +) { if (npc->IsSkipAutoScale() || npc->GetNPCTypeID() == 0) { return; } - int8 npc_type = GetNPCScalingType(npc); - int npc_level = npc->GetLevel(); - bool is_auto_scaled = IsAutoScaled(npc); + auto npc_type = GetNPCScalingType(npc); + auto npc_level = npc->GetLevel(); + auto is_auto_scaled = IsAutoScaled(npc); + auto zone_id = zone->GetZoneID(); + auto instance_version = zone->GetInstanceVersion(); - global_npc_scale scale_data = GetGlobalScaleDataForTypeLevel(npc_type, npc_level); + global_npc_scale scale_data = GetGlobalScaleDataForTypeLevel( + npc_type, + npc_level, + zone_id, + instance_version + ); if (!scale_data.level) { LogNPCScaling( - "NPC: [{}] - scaling data not found for type: [{}] level: [{}]", + "NPC: [{}] - scaling data not found for type [{}] level [{}]", npc->GetCleanName(), npc_type, npc_level @@ -49,100 +59,137 @@ void NpcScaleManager::ScaleNPC(NPC *npc) return; } - if (npc->GetAC() == 0 && is_auto_scaled) { - npc->ModifyNPCStat("ac", std::to_string(scale_data.ac).c_str()); + if (always_scale || (npc->GetAC() == 0 && is_auto_scaled)) { + npc->ModifyNPCStat("ac", std::to_string(scale_data.ac)); } - if (npc->GetMaxHP() == 0) { - npc->ModifyNPCStat("max_hp", std::to_string(scale_data.hp).c_str()); + + if (always_scale || npc->GetMaxHP() == 0) { + npc->ModifyNPCStat("max_hp", std::to_string(scale_data.hp)); npc->Heal(); } - if (npc->GetAccuracyRating() == 0) { - npc->ModifyNPCStat("accuracy", std::to_string(scale_data.accuracy).c_str()); + + if (always_scale || npc->GetAccuracyRating() == 0) { + npc->ModifyNPCStat("accuracy", std::to_string(scale_data.accuracy)); } - if (npc->GetSlowMitigation() == 0) { - npc->ModifyNPCStat("slow_mitigation", std::to_string(scale_data.slow_mitigation).c_str()); + + if (always_scale || npc->GetSlowMitigation() == 0) { + npc->ModifyNPCStat("slow_mitigation", std::to_string(scale_data.slow_mitigation)); } - if (npc->GetATK() == 0) { - npc->ModifyNPCStat("atk", std::to_string(scale_data.attack).c_str()); + + if (always_scale || npc->GetATK() == 0) { + npc->ModifyNPCStat("atk", std::to_string(scale_data.attack)); } - if (npc->GetSTR() == 0) { - npc->ModifyNPCStat("str", std::to_string(scale_data.strength).c_str()); + + if (always_scale || npc->GetSTR() == 0) { + npc->ModifyNPCStat("str", std::to_string(scale_data.strength)); } - if (npc->GetSTA() == 0) { - npc->ModifyNPCStat("sta", std::to_string(scale_data.stamina).c_str()); + + if (always_scale || npc->GetSTA() == 0) { + npc->ModifyNPCStat("sta", std::to_string(scale_data.stamina)); } - if (npc->GetDEX() == 0) { - npc->ModifyNPCStat("dex", std::to_string(scale_data.dexterity).c_str()); + + if (always_scale || npc->GetDEX() == 0) { + npc->ModifyNPCStat("dex", std::to_string(scale_data.dexterity)); } - if (npc->GetAGI() == 0) { - npc->ModifyNPCStat("agi", std::to_string(scale_data.agility).c_str()); + + if (always_scale || npc->GetAGI() == 0) { + npc->ModifyNPCStat("agi", std::to_string(scale_data.agility)); } - if (npc->GetINT() == 0) { - npc->ModifyNPCStat("int", std::to_string(scale_data.intelligence).c_str()); + + if (always_scale || npc->GetINT() == 0) { + npc->ModifyNPCStat("int", std::to_string(scale_data.intelligence)); } - if (npc->GetWIS() == 0) { - npc->ModifyNPCStat("wis", std::to_string(scale_data.wisdom).c_str()); + + if (always_scale || npc->GetWIS() == 0) { + npc->ModifyNPCStat("wis", std::to_string(scale_data.wisdom)); } - if (npc->GetCHA() == 0) { - npc->ModifyNPCStat("cha", std::to_string(scale_data.charisma).c_str()); + + if (always_scale || npc->GetCHA() == 0) { + npc->ModifyNPCStat("cha", std::to_string(scale_data.charisma)); } - if (npc->GetMR() == 0) { - npc->ModifyNPCStat("mr", std::to_string(scale_data.magic_resist).c_str()); + + if (always_scale || npc->GetMR() == 0) { + npc->ModifyNPCStat("mr", std::to_string(scale_data.magic_resist)); } - if (npc->GetCR() == 0) { - npc->ModifyNPCStat("cr", std::to_string(scale_data.cold_resist).c_str()); + + if (always_scale || npc->GetCR() == 0) { + npc->ModifyNPCStat("cr", std::to_string(scale_data.cold_resist)); } - if (npc->GetFR() == 0) { - npc->ModifyNPCStat("fr", std::to_string(scale_data.fire_resist).c_str()); + + if (always_scale || npc->GetFR() == 0) { + npc->ModifyNPCStat("fr", std::to_string(scale_data.fire_resist)); } - if (npc->GetPR() == 0) { - npc->ModifyNPCStat("pr", std::to_string(scale_data.poison_resist).c_str()); + + if (always_scale || npc->GetPR() == 0) { + npc->ModifyNPCStat("pr", std::to_string(scale_data.poison_resist)); } - if (npc->GetDR() == 0) { - npc->ModifyNPCStat("dr", std::to_string(scale_data.disease_resist).c_str()); + + if (always_scale || npc->GetDR() == 0) { + npc->ModifyNPCStat("dr", std::to_string(scale_data.disease_resist)); } - if (npc->GetCorrup() == 0 && is_auto_scaled) { - npc->ModifyNPCStat("cor", std::to_string(scale_data.corruption_resist).c_str()); + + if (always_scale || (npc->GetCorrup() == 0 && is_auto_scaled)) { + npc->ModifyNPCStat("cor", std::to_string(scale_data.corruption_resist)); } - if (npc->GetPhR() == 0 && is_auto_scaled) { - npc->ModifyNPCStat("phr", std::to_string(scale_data.physical_resist).c_str()); + + if (always_scale || (npc->GetPhR() == 0 && is_auto_scaled)) { + npc->ModifyNPCStat("phr", std::to_string(scale_data.physical_resist)); } - if (npc->GetMinDMG() == 0 && npc->GetMaxDMG() == 0) { - int min_dmg = scale_data.min_dmg; + + if (always_scale || npc->GetMinDMG() == 0) { + int64 min_dmg = scale_data.min_dmg; if (RuleB(Combat, UseNPCDamageClassLevelMods)) { - int32 class_level_damage_mod = GetClassLevelDamageMod(npc->GetLevel(), npc->GetClass()); + uint32 class_level_damage_mod = GetClassLevelDamageMod(npc->GetLevel(), npc->GetClass()); min_dmg = (min_dmg * class_level_damage_mod) / 220; LogNPCScaling("ClassLevelDamageMod::min_dmg base: [{}] calc: [{}]", scale_data.min_dmg, min_dmg); } - npc->ModifyNPCStat("min_hit", std::to_string(min_dmg).c_str()); + npc->ModifyNPCStat("min_hit", std::to_string(min_dmg)); } - if (npc->GetMaxDMG() == 0) { - int max_dmg = scale_data.max_dmg; + + if (always_scale || npc->GetMaxDMG() == 0) { + int64 max_dmg = scale_data.max_dmg; if (RuleB(Combat, UseNPCDamageClassLevelMods)) { - int32 class_level_damage_mod = GetClassLevelDamageMod(npc->GetLevel(), npc->GetClass()); + uint32 class_level_damage_mod = GetClassLevelDamageMod(npc->GetLevel(), npc->GetClass()); max_dmg = (scale_data.max_dmg * class_level_damage_mod) / 220; LogNPCScaling("ClassLevelDamageMod::max_dmg base: [{}] calc: [{}]", scale_data.max_dmg, max_dmg); } - npc->ModifyNPCStat("max_hit", std::to_string(max_dmg).c_str()); + npc->ModifyNPCStat("max_hit", std::to_string(max_dmg)); } - if (npc->GetHPRegen() == 0 && is_auto_scaled) { - npc->ModifyNPCStat("hp_regen", std::to_string(scale_data.hp_regen_rate).c_str()); + + if (always_scale || (npc->GetHPRegen() == 0 && is_auto_scaled)) { + npc->ModifyNPCStat("hp_regen", std::to_string(scale_data.hp_regen_rate)); } - if (npc->GetAttackDelay() == 0) { - npc->ModifyNPCStat("attack_delay", std::to_string(scale_data.attack_delay).c_str()); + + if (always_scale || (npc->GetHPRegenPerSecond() == 0 && is_auto_scaled)) { + npc->ModifyNPCStat("hp_regen_per_second", std::to_string(scale_data.hp_regen_per_second)); } - if (npc->GetSpellScale() == 0) { - npc->ModifyNPCStat("spell_scale", std::to_string(scale_data.spell_scale).c_str()); + + if (always_scale || npc->GetAttackDelay() == 0) { + npc->ModifyNPCStat("attack_delay", std::to_string(scale_data.attack_delay)); } - if (npc->GetHealScale() == 0) { - npc->ModifyNPCStat("heal_scale", std::to_string(scale_data.heal_scale).c_str()); + + if (always_scale || npc->GetSpellScale() == 0) { + npc->ModifyNPCStat("spellscale", std::to_string(scale_data.spell_scale)); } - if (!npc->HasSpecialAbilities() && is_auto_scaled) { - npc->ModifyNPCStat("special_abilities", scale_data.special_abilities.c_str()); + + if (always_scale || npc->GetHealScale() == 0) { + npc->ModifyNPCStat("healscale", std::to_string(scale_data.heal_scale)); + } + + if (always_scale || npc->GetAvoidanceRating() == 0) { + npc->ModifyNPCStat("avoidance", std::to_string(scale_data.avoidance)); + } + + if (always_scale || npc->GetHeroicStrikethrough() == 0) { + npc->ModifyNPCStat("heroic_strikethrough", std::to_string(scale_data.heroic_strikethrough)); + } + + if (override_special_abilities || (!npc->HasSpecialAbilities() && is_auto_scaled)) { + npc->ModifyNPCStat("special_abilities", scale_data.special_abilities); } if (LogSys.log_settings[Logs::NPCScaling].is_category_enabled == 1) { @@ -161,18 +208,18 @@ void NpcScaleManager::ScaleNPC(NPC *npc) npc_level, npc_type, (is_auto_scaled ? "true" : "false"), - scale_log.c_str() + scale_log ); } } -void NpcScaleManager::ResetNPCScaling(NPC *npc) +void NpcScaleManager::ResetNPCScaling(NPC* npc) { for (const auto &scaling_stat : scaling_stats) { auto stat_name = fmt::format("modify_stat_{}", scaling_stat); auto reset_value = std::to_string(0); if (npc->EntityVariableExists(stat_name)) { - npc->ModifyNPCStat(scaling_stat.c_str(), reset_value.c_str()); + npc->ModifyNPCStat(scaling_stat, reset_value); } } } @@ -180,47 +227,133 @@ void NpcScaleManager::ResetNPCScaling(NPC *npc) bool NpcScaleManager::LoadScaleData() { auto rows = NpcScaleGlobalBaseRepository::All(content_db); - for (auto &s: rows) { + for (const auto &s : rows) { + if ( + s.zone_id_list.empty() || + s.instance_version_list.empty() + ) { + continue; + } + global_npc_scale scale_data; - scale_data.type = s.type; - scale_data.level = s.level; - scale_data.ac = s.ac; - scale_data.hp = s.hp; - scale_data.accuracy = s.accuracy; - scale_data.slow_mitigation = s.slow_mitigation; - scale_data.attack = s.attack; - scale_data.strength = s.strength; - scale_data.stamina = s.stamina; - scale_data.dexterity = s.dexterity; - scale_data.agility = s.agility; - scale_data.intelligence = s.intelligence; - scale_data.wisdom = s.wisdom; - scale_data.charisma = s.charisma; - scale_data.magic_resist = s.magic_resist; - scale_data.cold_resist = s.cold_resist; - scale_data.fire_resist = s.fire_resist; - scale_data.poison_resist = s.poison_resist; - scale_data.disease_resist = s.disease_resist; - scale_data.corruption_resist = s.corruption_resist; - scale_data.physical_resist = s.physical_resist; - scale_data.min_dmg = s.min_dmg; - scale_data.max_dmg = s.max_dmg; - scale_data.hp_regen_rate = s.hp_regen_rate; - scale_data.attack_delay = s.attack_delay; - scale_data.spell_scale = s.spell_scale; - scale_data.heal_scale = s.heal_scale; + scale_data.type = s.type; + scale_data.level = s.level; + scale_data.ac = s.ac; + scale_data.hp = s.hp; + scale_data.accuracy = s.accuracy; + scale_data.slow_mitigation = s.slow_mitigation; + scale_data.attack = s.attack; + scale_data.strength = s.strength; + scale_data.stamina = s.stamina; + scale_data.dexterity = s.dexterity; + scale_data.agility = s.agility; + scale_data.intelligence = s.intelligence; + scale_data.wisdom = s.wisdom; + scale_data.charisma = s.charisma; + scale_data.magic_resist = s.magic_resist; + scale_data.cold_resist = s.cold_resist; + scale_data.fire_resist = s.fire_resist; + scale_data.poison_resist = s.poison_resist; + scale_data.disease_resist = s.disease_resist; + scale_data.corruption_resist = s.corruption_resist; + scale_data.physical_resist = s.physical_resist; + scale_data.min_dmg = s.min_dmg; + scale_data.max_dmg = s.max_dmg; + scale_data.hp_regen_rate = s.hp_regen_rate; + scale_data.hp_regen_per_second = s.hp_regen_per_second; + scale_data.attack_delay = s.attack_delay; + scale_data.spell_scale = s.spell_scale; + scale_data.heal_scale = s.heal_scale; + scale_data.avoidance = s.avoidance; + scale_data.heroic_strikethrough = s.heroic_strikethrough; if (!s.special_abilities.empty()) { scale_data.special_abilities = s.special_abilities; } - npc_global_base_scaling_data.insert( - std::make_pair( - std::make_pair(scale_data.type, scale_data.level), - scale_data - ) - ); + const auto has_multiple_zones = Strings::Contains(s.zone_id_list, "|"); + const auto has_multiple_versions = Strings::Contains(s.instance_version_list, "|"); + + if (!has_multiple_zones && !has_multiple_versions) { + scale_data.zone_id = Strings::ToUnsignedInt(s.zone_id_list); + scale_data.instance_version = static_cast(Strings::ToUnsignedInt(s.instance_version_list)); + + npc_global_base_scaling_data.insert( + std::make_pair( + std::make_tuple( + scale_data.type, + scale_data.level, + scale_data.zone_id, + scale_data.instance_version + ), + scale_data + ) + ); + } else if (has_multiple_zones && !has_multiple_versions) { + scale_data.instance_version = static_cast(Strings::ToUnsignedInt(s.instance_version_list)); + + const auto zones = Strings::Split(s.zone_id_list, "|"); + + for (const auto &z : zones) { + scale_data.zone_id = Strings::ToUnsignedInt(z); + + npc_global_base_scaling_data.insert( + std::make_pair( + std::make_tuple( + scale_data.type, + scale_data.level, + scale_data.zone_id, + scale_data.instance_version + ), + scale_data + ) + ); + } + } else if (!has_multiple_zones) { + scale_data.zone_id = Strings::ToUnsignedInt(s.zone_id_list); + + const auto versions = Strings::Split(s.instance_version_list, "|"); + + for (const auto &v : versions) { + scale_data.instance_version = static_cast(Strings::ToUnsignedInt(v)); + + npc_global_base_scaling_data.insert( + std::make_pair( + std::make_tuple( + scale_data.type, + scale_data.level, + scale_data.zone_id, + scale_data.instance_version + ), + scale_data + ) + ); + } + } else { + const auto zones = Strings::Split(s.zone_id_list, "|"); + const auto versions = Strings::Split(s.instance_version_list, "|"); + + for (const auto &z : zones) { + scale_data.zone_id = Strings::ToUnsignedInt(z); + + for (const auto &v : versions) { + scale_data.instance_version = static_cast(Strings::ToUnsignedInt(v)); + + npc_global_base_scaling_data.insert( + std::make_pair( + std::make_tuple( + scale_data.type, + scale_data.level, + scale_data.zone_id, + scale_data.instance_version + ), + scale_data + ) + ); + } + } + } } LogInfo("Loaded [{}] global scaling data entries", Strings::Commify(rows.size())); @@ -233,9 +366,45 @@ bool NpcScaleManager::LoadScaleData() * @param npc_level * @return NpcScaleManager::global_npc_scale */ -NpcScaleManager::global_npc_scale NpcScaleManager::GetGlobalScaleDataForTypeLevel(int8 npc_type, int npc_level) -{ - auto iter = npc_global_base_scaling_data.find(std::make_pair(npc_type, npc_level)); +NpcScaleManager::global_npc_scale NpcScaleManager::GetGlobalScaleDataForTypeLevel( + int8 npc_type, + uint8 npc_level, + uint32 zone_id, + uint16 instance_version +) { + auto iter = npc_global_base_scaling_data.find( + std::make_tuple( + npc_type, + npc_level, + zone_id, + instance_version + ) + ); + + if (iter != npc_global_base_scaling_data.end()) { + return iter->second; + } + + iter = npc_global_base_scaling_data.find( + std::make_tuple( + npc_type, + npc_level, + zone_id, + 0 + ) + ); + if (iter != npc_global_base_scaling_data.end()) { + return iter->second; + } + + iter = npc_global_base_scaling_data.find( + std::make_tuple( + npc_type, + npc_level, + 0, + 0 + ) + ); if (iter != npc_global_base_scaling_data.end()) { return iter->second; } @@ -250,7 +419,7 @@ NpcScaleManager::global_npc_scale NpcScaleManager::GetGlobalScaleDataForTypeLeve */ uint32 NpcScaleManager::GetClassLevelDamageMod(uint32 level, uint32 npc_class) { - uint32 multiplier = 0; + uint32 multiplier; switch (npc_class) { case WARRIOR: { @@ -410,9 +579,8 @@ int8 NpcScaleManager::GetNPCScalingType(NPC *&npc) */ std::string NpcScaleManager::GetNPCScalingTypeName(NPC *&npc) { - int8 scaling_type = GetNPCScalingType(npc); - if (scaling_type == 1) { + if (int8 scaling_type = GetNPCScalingType(npc); scaling_type == 1) { return "Named"; } @@ -430,24 +598,25 @@ std::string NpcScaleManager::GetNPCScalingTypeName(NPC *&npc) * @param npc * @return */ -bool NpcScaleManager::IsAutoScaled(NPC *npc) +bool NpcScaleManager::IsAutoScaled(NPC* npc) { - return - (npc->GetHP() == 0 && - npc->GetMaxDMG() == 0 && - npc->GetMinDMG() == 0 && - npc->GetSTR() == 0 && - npc->GetSTA() == 0 && - npc->GetDEX() == 0 && - npc->GetAGI() == 0 && - npc->GetINT() == 0 && - npc->GetWIS() == 0 && - npc->GetCHA() == 0 && - npc->GetMR() == 0 && - npc->GetFR() == 0 && - npc->GetCR() == 0 && - npc->GetPR() == 0 && - npc->GetDR() == 0); + return ( + npc->GetHP() == 0 && + npc->GetMaxDMG() == 0 && + npc->GetMinDMG() == 0 && + npc->GetSTR() == 0 && + npc->GetSTA() == 0 && + npc->GetDEX() == 0 && + npc->GetAGI() == 0 && + npc->GetINT() == 0 && + npc->GetWIS() == 0 && + npc->GetCHA() == 0 && + npc->GetMR() == 0 && + npc->GetFR() == 0 && + npc->GetCR() == 0 && + npc->GetPR() == 0 && + npc->GetDR() == 0 + ); } /** @@ -457,14 +626,21 @@ bool NpcScaleManager::IsAutoScaled(NPC *npc) */ bool NpcScaleManager::ApplyGlobalBaseScalingToNPCStatically(NPC *&npc) { - int8 npc_type = GetNPCScalingType(npc); - int npc_level = npc->GetLevel(); + auto npc_type = GetNPCScalingType(npc); + auto npc_level = npc->GetLevel(); + auto zone_id = zone->GetZoneID(); + auto instance_version = zone->GetInstanceVersion(); - global_npc_scale g = GetGlobalScaleDataForTypeLevel(npc_type, npc_level); + global_npc_scale g = GetGlobalScaleDataForTypeLevel( + npc_type, + npc_level, + zone_id, + instance_version + ); if (!g.level) { LogNPCScaling( - "NPC: [{}] - scaling data not found for type: [{}] level: [{}]", + "NPC: [{}] - scaling data not found for type [{}] level [{}]", npc->GetCleanName(), npc_type, npc_level @@ -473,34 +649,37 @@ bool NpcScaleManager::ApplyGlobalBaseScalingToNPCStatically(NPC *&npc) return false; } - auto n = NpcTypesRepository::FindOne(content_db, (int) npc->GetNPCTypeID()); + auto n = NpcTypesRepository::FindOne(content_db, static_cast(npc->GetNPCTypeID())); if (n.id > 0) { - n.AC = g.ac; - n.hp = g.hp; - n.Accuracy = g.accuracy; - n.slow_mitigation = g.slow_mitigation; - n.ATK = g.attack; - n.STR = g.strength; - n.STA = g.stamina; - n.DEX = g.dexterity; - n.AGI = g.agility; - n._INT = g.intelligence; - n.WIS = g.wisdom; - n.CHA = g.charisma; - n.MR = g.magic_resist; - n.CR = g.cold_resist; - n.FR = g.fire_resist; - n.PR = g.poison_resist; - n.DR = g.disease_resist; - n.Corrup = g.corruption_resist; - n.PhR = g.physical_resist; - n.mindmg = g.min_dmg; - n.maxdmg = g.max_dmg; - n.hp_regen_rate = g.hp_regen_rate; - n.attack_delay = g.attack_delay; - n.spellscale = (float) g.spell_scale; - n.healscale = (float) g.heal_scale; - n.special_abilities = g.special_abilities; + n.AC = g.ac; + n.hp = g.hp; + n.Accuracy = g.accuracy; + n.slow_mitigation = g.slow_mitigation; + n.ATK = g.attack; + n.STR = g.strength; + n.STA = g.stamina; + n.DEX = g.dexterity; + n.AGI = g.agility; + n._INT = g.intelligence; + n.WIS = g.wisdom; + n.CHA = g.charisma; + n.MR = g.magic_resist; + n.CR = g.cold_resist; + n.FR = g.fire_resist; + n.PR = g.poison_resist; + n.DR = g.disease_resist; + n.Corrup = g.corruption_resist; + n.PhR = g.physical_resist; + n.mindmg = g.min_dmg; + n.maxdmg = g.max_dmg; + n.hp_regen_rate = g.hp_regen_rate; + n.hp_regen_per_second = g.hp_regen_per_second; + n.attack_delay = g.attack_delay; + n.spellscale = static_cast(g.spell_scale); + n.healscale = static_cast(g.heal_scale); + n.Avoidance = g.avoidance; + n.heroic_strikethrough = g.heroic_strikethrough; + n.special_abilities = g.special_abilities; return NpcTypesRepository::UpdateOne(content_db, n); } @@ -515,14 +694,21 @@ bool NpcScaleManager::ApplyGlobalBaseScalingToNPCStatically(NPC *&npc) */ bool NpcScaleManager::ApplyGlobalBaseScalingToNPCDynamically(NPC *&npc) { - int8 npc_type = GetNPCScalingType(npc); - int npc_level = npc->GetLevel(); + auto npc_type = GetNPCScalingType(npc); + auto npc_level = npc->GetLevel(); + auto zone_id = zone->GetZoneID(); + auto instance_version = zone->GetInstanceVersion(); - global_npc_scale d = GetGlobalScaleDataForTypeLevel(npc_type, npc_level); + global_npc_scale d = GetGlobalScaleDataForTypeLevel( + npc_type, + npc_level, + zone_id, + instance_version + ); if (!d.level) { LogNPCScaling( - "NPC: [{}] - scaling data not found for type: [{}] level: [{}]", + "NPC: [{}] - scaling data not found for type [{}] level [{}]", npc->GetCleanName(), npc_type, npc_level @@ -531,34 +717,37 @@ bool NpcScaleManager::ApplyGlobalBaseScalingToNPCDynamically(NPC *&npc) return false; } - auto n = NpcTypesRepository::FindOne(content_db, (int) npc->GetNPCTypeID()); + auto n = NpcTypesRepository::FindOne(content_db, static_cast(npc->GetNPCTypeID())); if (n.id > 0) { - n.AC = 0; - n.hp = 0; - n.Accuracy = 0; - n.slow_mitigation = 0; - n.ATK = 0; - n.STR = 0; - n.STA = 0; - n.DEX = 0; - n.AGI = 0; - n._INT = 0; - n.WIS = 0; - n.CHA = 0; - n.MR = 0; - n.CR = 0; - n.FR = 0; - n.PR = 0; - n.DR = 0; - n.Corrup = 0; - n.PhR = 0; - n.mindmg = 0; - n.maxdmg = 0; - n.hp_regen_rate = 0; - n.attack_delay = 0; - n.spellscale = 0; - n.healscale = 0; - n.special_abilities = ""; + n.AC = 0; + n.hp = 0; + n.Accuracy = 0; + n.slow_mitigation = 0; + n.ATK = 0; + n.STR = 0; + n.STA = 0; + n.DEX = 0; + n.AGI = 0; + n._INT = 0; + n.WIS = 0; + n.CHA = 0; + n.MR = 0; + n.CR = 0; + n.FR = 0; + n.PR = 0; + n.DR = 0; + n.Corrup = 0; + n.PhR = 0; + n.mindmg = 0; + n.maxdmg = 0; + n.hp_regen_rate = 0; + n.hp_regen_per_second = 0; + n.attack_delay = 0; + n.spellscale = 0; + n.healscale = 0; + n.Avoidance = 0; + n.heroic_strikethrough = 0; + n.special_abilities = ""; return NpcTypesRepository::UpdateOne(content_db, n); } diff --git a/zone/npc_scale_manager.h b/zone/npc_scale_manager.h index 2748f5a61..2c37b3d7b 100644 --- a/zone/npc_scale_manager.h +++ b/zone/npc_scale_manager.h @@ -22,37 +22,44 @@ #define EQEMU_NPC_SCALE_MANAGER_H #include "npc.h" +#include "zone.h" +extern Zone* zone; class NpcScaleManager { public: struct global_npc_scale { - int type; - int level; - int ac; - int64 hp; - int accuracy; - int slow_mitigation; - int attack; - int strength; - int stamina; - int dexterity; - int agility; - int intelligence; - int wisdom; - int charisma; - int magic_resist; - int cold_resist; - int fire_resist; - int poison_resist; - int disease_resist; - int corruption_resist; - int physical_resist; - int min_dmg; - int max_dmg; - int64 hp_regen_rate; - int attack_delay; - int spell_scale; - int heal_scale; + int8 type; + uint8 level; + uint32 zone_id; + uint16 instance_version; + int ac; + int64 hp; + int accuracy; + int slow_mitigation; + int attack; + int strength; + int stamina; + int dexterity; + int agility; + int intelligence; + int wisdom; + int charisma; + int magic_resist; + int cold_resist; + int fire_resist; + int poison_resist; + int disease_resist; + int corruption_resist; + int physical_resist; + int min_dmg; + int max_dmg; + int64 hp_regen_rate; + int64 hp_regen_per_second; + int attack_delay; + int spell_scale; + int heal_scale; + uint32 avoidance; + int heroic_strikethrough; std::string special_abilities; }; @@ -80,20 +87,28 @@ public: "min_hit", "max_hit", "hp_regen", + "hp_regen_per_second", "attack_delay", "spell_scale", "heal_scale", + "avoidance", + "heroic_strikethrough", "special_abilities" }; - void ScaleNPC(NPC * npc); - void ResetNPCScaling(NPC * npc); - bool IsAutoScaled(NPC * npc); + void ScaleNPC(NPC* npc, bool always_scale = false, bool override_special_abilities = false); + void ResetNPCScaling(NPC* npc); + bool IsAutoScaled(NPC* npc); bool LoadScaleData(); - global_npc_scale GetGlobalScaleDataForTypeLevel(int8 npc_type, int npc_level); + global_npc_scale GetGlobalScaleDataForTypeLevel( + int8 npc_type, + uint8 npc_level, + uint32 zone_id, + uint16 instance_version + ); - std::map, global_npc_scale> npc_global_base_scaling_data; + std::map, global_npc_scale> npc_global_base_scaling_data; int8 GetNPCScalingType(NPC * &npc); std::string GetNPCScalingTypeName(NPC * &npc); diff --git a/zone/object.cpp b/zone/object.cpp index be6974934..4b78eff26 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -25,9 +25,11 @@ #include "object.h" #include "quest_parser_collection.h" +#include "worldserver.h" #include "zonedb.h" #include "../common/zone_store.h" #include "../common/repositories/criteria/content_filter_criteria.h" +#include "../common/events/player_event_logs.h" #include @@ -37,6 +39,7 @@ const char DEFAULT_OBJECT_NAME_SUFFIX[] = "_ACTORDEF"; extern Zone* zone; extern EntityList entity_list; +extern WorldServer worldserver; // Loading object from database Object::Object(uint32 id, uint32 type, uint32 icon, const Object_Struct& object, const EQ::ItemInstance* inst) @@ -50,7 +53,6 @@ Object::Object(uint32 id, uint32 type, uint32 icon, const Object_Struct& object, m_id = id; m_type = type; m_icon = icon; - m_inuse = false; m_inst = nullptr; m_ground_spawn=false; // Copy object data @@ -68,6 +70,8 @@ Object::Object(uint32 id, uint32 type, uint32 icon, const Object_Struct& object, m_data.size = object.size; m_data.tilt_x = object.tilt_x; m_data.tilt_y = object.tilt_y; + + FixZ(); } //creating a re-ocurring ground spawn. @@ -85,7 +89,6 @@ Object::Object(const EQ::ItemInstance* inst, char* name,float max_x,float min_x, m_inst = (inst) ? inst->Clone() : nullptr; m_type = OT_DROPPEDITEM; m_icon = 0; - m_inuse = false; m_ground_spawn = true; decay_timer.Disable(); // Set as much struct data as we can @@ -97,6 +100,8 @@ Object::Object(const EQ::ItemInstance* inst, char* name,float max_x,float min_x, strcpy(m_data.object_name, name); RandomSpawn(false); + FixZ(); + // Hardcoded portion for unknown members m_data.unknown024 = 0x7f001194; m_data.unknown076 = 0x0000d5fe; @@ -115,7 +120,6 @@ Object::Object(Client* client, const EQ::ItemInstance* inst) m_inst = (inst) ? inst->Clone() : nullptr; m_type = OT_DROPPEDITEM; m_icon = 0; - m_inuse = false; m_ground_spawn = false; // Set as much struct data as we can memset(&m_data, 0, sizeof(Object_Struct)); @@ -164,6 +168,8 @@ Object::Object(Client* client, const EQ::ItemInstance* inst) strcpy(m_data.object_name, DEFAULT_OBJECT_NAME); } } + + FixZ(); } Object::Object(const EQ::ItemInstance *inst, float x, float y, float z, float heading, uint32 decay_time) @@ -177,7 +183,6 @@ Object::Object(const EQ::ItemInstance *inst, float x, float y, float z, float he m_inst = (inst) ? inst->Clone() : nullptr; m_type = OT_DROPPEDITEM; m_icon = 0; - m_inuse = false; m_ground_spawn = false; // Set as much struct data as we can memset(&m_data, 0, sizeof(Object_Struct)); @@ -220,6 +225,8 @@ Object::Object(const EQ::ItemInstance *inst, float x, float y, float z, float he strcpy(m_data.object_name, DEFAULT_OBJECT_NAME); } } + + FixZ(); } Object::Object(const char *model, float x, float y, float z, float heading, uint8 type, uint32 decay_time) @@ -234,7 +241,6 @@ Object::Object(const char *model, float x, float y, float z, float heading, uint m_inst = (inst) ? inst->Clone() : nullptr; m_type = type; m_icon = 0; - m_inuse = false; m_ground_spawn = false; // Set as much struct data as we can memset(&m_data, 0, sizeof(Object_Struct)); @@ -244,6 +250,8 @@ Object::Object(const char *model, float x, float y, float z, float heading, uint m_data.z = z; m_data.zone_id = zone->GetZoneID(); + FixZ(); + if (decay_time) decay_timer.Start(); @@ -359,7 +367,6 @@ void Object::PutItem(uint8 index, const EQ::ItemInstance* inst) } void Object::Close() { - m_inuse = false; if(user != nullptr) { last_user = user; @@ -449,7 +456,6 @@ bool Object::Process(){ } if (user != nullptr && !entity_list.GetClientByCharID(user->CharacterID())) { - m_inuse = false; last_user = user; user->SetTradeskillObject(nullptr); user = nullptr; @@ -490,62 +496,80 @@ void Object::RandomSpawn(bool send_packet) { bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) { - if(m_ground_spawn){//This is a Cool Groundspawn + if(m_ground_spawn) {//This is a Cool Groundspawn respawn_timer.Start(); } if (m_type == OT_DROPPEDITEM) { bool cursordelete = false; + bool duplicate_lore = false; if (m_inst && sender) { // if there is a lore conflict, delete the offending item from the server inventory // the client updates itself and takes care of sending "duplicate lore item" messages auto item = m_inst->GetItem(); - if(sender->CheckLoreConflict(item)) { + if (sender->CheckLoreConflict(item)) { + duplicate_lore = true; int16 loreslot = sender->GetInv().HasItem(item->ID, 0, invWhereBank); - if (loreslot != INVALID_INDEX) // if the duplicate is in the bank, delete it. + if (loreslot != INVALID_INDEX) { // if the duplicate is in the bank, delete it. sender->DeleteItemInInventory(loreslot); - else - cursordelete = true; // otherwise, we delete the new one + } + else { + cursordelete = true; + } // otherwise, we delete the new one } - if (item->RecastDelay) - m_inst->SetRecastTimestamp( - database.GetItemRecastTimestamp(sender->CharacterID(), item->RecastType)); - - std::string export_string = fmt::format("{}", item->ID); - std::vector args; - args.push_back(m_inst); - if(parse->EventPlayer(EVENT_PLAYER_PICKUP, sender, export_string, GetID(), &args)) - { - auto outapp = new EQApplicationPacket(OP_ClickObject, sizeof(ClickObject_Struct)); - memcpy(outapp->pBuffer, click_object, sizeof(ClickObject_Struct)); - ClickObject_Struct* co = (ClickObject_Struct*)outapp->pBuffer; - co->drop_id = 0; - entity_list.QueueClients(nullptr, outapp, false); - safe_delete(outapp); - - // No longer using a tradeskill object - sender->SetTradeskillObject(nullptr); - user = nullptr; - - return true; + if (item->RecastDelay) { + if (item->RecastType != RECAST_TYPE_UNLINKED_ITEM) { + m_inst->SetRecastTimestamp( + database.GetItemRecastTimestamp(sender->CharacterID(), item->RecastType)); + } else { + m_inst->SetRecastTimestamp( + database.GetItemRecastTimestamp(sender->CharacterID(), item->ID)); + } } + if (player_event_logs.IsEventEnabled(PlayerEvent::GROUNDSPAWN_PICKUP)) { + auto e = PlayerEvent::GroundSpawnPickupEvent{ + .item_id = item->ID, + .item_name = item->Name, + }; + RecordPlayerEventLogWithClient(sender, PlayerEvent::GROUNDSPAWN_PICKUP, e); + } + + if (parse->PlayerHasQuestSub(EVENT_PLAYER_PICKUP)) { + std::vector args = { m_inst }; + + if (parse->EventPlayer(EVENT_PLAYER_PICKUP, sender, std::to_string(item->ID), GetID(), &args)) { + auto outapp = new EQApplicationPacket(OP_ClickObject, sizeof(ClickObject_Struct)); + memcpy(outapp->pBuffer, click_object, sizeof(ClickObject_Struct)); + auto* co = (ClickObject_Struct*) outapp->pBuffer; + co->drop_id = 0; + entity_list.QueueClients(nullptr, outapp, false); + safe_delete(outapp); + + sender->SetTradeskillObject(nullptr); + user = nullptr; + + return true; + } + } // Transfer item to client sender->PutItemInInventory(EQ::invslot::slotCursor, *m_inst, false); sender->SendItemPacket(EQ::invslot::slotCursor, m_inst, ItemPacketTrade); // Could be an undiscovered ground_spawn - if (m_ground_spawn && (RuleB(Character, EnableDiscoveredItems))) - { - if (!sender->GetGM() && !sender->IsDiscovered(item->ID)) - { - sender->DiscoverItem(item->ID); - } + if ( + m_ground_spawn && + RuleB(Character, EnableDiscoveredItems) && + !sender->GetGM() && + !sender->IsDiscovered(item->ID) + ) { + sender->DiscoverItem(item->ID); } - if(cursordelete) // delete the item if it's a duplicate lore. We have to do this because the client expects the item packet - sender->DeleteItemInInventory(EQ::invslot::slotCursor); + if (cursordelete) { // delete the item if it's a duplicate lore. We have to do this because the client expects the item packet + sender->DeleteItemInInventory(EQ::invslot::slotCursor, 1, true); + } sender->DropItemQS(m_inst, true); @@ -565,8 +589,18 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) // Remove object content_db.DeleteObject(m_id); - if(!m_ground_spawn) + if (!m_ground_spawn) { entity_list.RemoveEntity(GetID()); + } + + // we have to delete the entity on click or the client desyncs + // this is a way to immediately respawn the groundspawn after killing it and + // deleting the item from the player + // I believe older clients somehow sent this automatically but we are no longer with ROF2+ + if (duplicate_lore) { + sender->Message(Chat::Yellow, "Duplicate lore item detected"); + respawn_timer.Trigger(); + } } else { // Tradeskill item auto outapp = new EQApplicationPacket(OP_ClickObjectAction, sizeof(ClickObjectAction_Struct)); @@ -602,7 +636,6 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) return(false); // Starting to use this object - m_inuse = true; sender->SetTradeskillObject(this); user = sender; @@ -733,16 +766,16 @@ Ground_Spawns* ZoneDatabase::LoadGroundSpawns(uint32 zone_id, int16 version, Gro int spawnIndex=0; for (auto row = results.begin(); row != results.end(); ++row, ++spawnIndex) { - gs->spawn[spawnIndex].max_x=atof(row[0]); - gs->spawn[spawnIndex].max_y=atof(row[1]); - gs->spawn[spawnIndex].max_z=atof(row[2]); - gs->spawn[spawnIndex].min_x=atof(row[3]); - gs->spawn[spawnIndex].min_y=atof(row[4]); - gs->spawn[spawnIndex].heading=atof(row[5]); + gs->spawn[spawnIndex].max_x=Strings::ToFloat(row[0]); + gs->spawn[spawnIndex].max_y=Strings::ToFloat(row[1]); + gs->spawn[spawnIndex].max_z=Strings::ToFloat(row[2]); + gs->spawn[spawnIndex].min_x=Strings::ToFloat(row[3]); + gs->spawn[spawnIndex].min_y=Strings::ToFloat(row[4]); + gs->spawn[spawnIndex].heading=Strings::ToFloat(row[5]); strcpy(gs->spawn[spawnIndex].name,row[6]); - gs->spawn[spawnIndex].item=atoi(row[7]); - gs->spawn[spawnIndex].max_allowed=atoi(row[8]); - gs->spawn[spawnIndex].respawntimer=atoi(row[9]); + gs->spawn[spawnIndex].item=Strings::ToInt(row[7]); + gs->spawn[spawnIndex].max_allowed=Strings::ToInt(row[8]); + gs->spawn[spawnIndex].respawntimer=Strings::ToInt(row[9]); } return gs; } @@ -1141,3 +1174,15 @@ void Object::SetEntityVariable(std::string variable_name, std::string variable_v o_EntityVariables[variable_name] = variable_value; } + +void Object::FixZ() +{ + float best_z = BEST_Z_INVALID; + if (zone->zonemap != nullptr) { + auto dest = glm::vec3(m_data.x, m_data.y, m_data.z + 5); + best_z = zone->zonemap->FindBestZ(dest, nullptr); + if (best_z != BEST_Z_INVALID) { + m_data.z = best_z; + } + } +} diff --git a/zone/object.h b/zone/object.h index 13232dc24..4cff5c397 100644 --- a/zone/object.h +++ b/zone/object.h @@ -140,7 +140,6 @@ public: uint32 GetDBID(); uint32 GetType(); void SetType(uint32 type); - void SetDBID(uint32 dbid); uint32 GetIcon(); void SetIcon(uint32 icon); uint32 GetItemID(); @@ -184,7 +183,6 @@ protected: Object_Struct m_data; // Packet data EQ::ItemInstance *m_inst; // Item representing object - bool m_inuse; // Currently in use by a client? uint32 m_id; // Database key, different than drop_id uint32 m_type; // Object Type, ie, forge, oven, dropped item, etc (ref: ContainerUseTypes) uint32 m_icon; // Icon to use for forge, oven, etc @@ -192,8 +190,6 @@ protected: float m_max_y; float m_min_x; float m_min_y; - float m_z; - float m_heading; bool m_ground_spawn; char m_display_name[64]; @@ -204,6 +200,7 @@ protected: Timer respawn_timer; Timer decay_timer; + void FixZ(); }; #endif diff --git a/zone/oriented_bounding_box.h b/zone/oriented_bounding_box.h index b662af84b..4d8a77fb3 100644 --- a/zone/oriented_bounding_box.h +++ b/zone/oriented_bounding_box.h @@ -12,9 +12,6 @@ public: ~OrientedBoundingBox() { } bool ContainsPoint(const glm::vec3 &p) const; - - glm::mat4& GetTransformation() { return transformation; } - glm::mat4& GetInvertedTransformation() { return inverted_transformation; } private: float min_x, max_x; float min_y, max_y; diff --git a/zone/perl_bot.cpp b/zone/perl_bot.cpp index ccbb0a936..99f37b3ef 100644 --- a/zone/perl_bot.cpp +++ b/zone/perl_bot.cpp @@ -90,7 +90,7 @@ uint32 Perl_Bot_CountBotItem(Bot* self, uint32 item_id) return self->CountBotItem(item_id); } -bool Perl_Bot_HasBotItem(Bot* self, uint32 item_id) +int16 Perl_Bot_HasBotItem(Bot* self, uint32 item_id) { return self->HasBotItem(item_id); } @@ -385,6 +385,66 @@ void Perl_Bot_Camp(Bot* self, bool save_to_database) // @categories Script Utili self->Camp(save_to_database); } +perl::array Perl_Bot_GetAugmentIDsBySlotID(Bot* self, int16 slot_id) +{ + perl::array result; + auto augments = self->GetInv().GetAugmentIDsBySlotID(slot_id); + + for (int i = 0; i < augments.size(); ++i) { + result.push_back(augments[i]); + } + + return result; +} + +void Perl_Bot_AddItem(Bot *self, perl::reference table_ref) +{ + perl::hash table = table_ref; + if (!table.exists("item_id") || !table.exists("charges")) + { + return; + } + + uint32 item_id = table["item_id"]; + int16 charges = table["charges"]; + uint32 augment_one = table.exists("augment_one") ? table["augment_one"] : 0; + uint32 augment_two = table.exists("augment_two") ? table["augment_two"] : 0; + uint32 augment_three = table.exists("augment_three") ? table["augment_three"] : 0; + uint32 augment_four = table.exists("augment_four") ? table["augment_four"] : 0; + uint32 augment_five = table.exists("augment_five") ? table["augment_five"] : 0; + uint32 augment_six = table.exists("augment_six") ? table["augment_six"] : 0; + bool attuned = table.exists("attuned") && table["attuned"]; + uint16 slot_id = table.exists("slot_id") ? table["slot_id"] : EQ::invslot::slotCursor; + + if (slot_id <= EQ::invslot::slotAmmo) { + self->AddBotItem( + slot_id, + item_id, + charges, + attuned, + augment_one, + augment_two, + augment_three, + augment_four, + augment_five, + augment_six + ); + } else { + self->GetOwner()->CastToClient()->SummonItem( + item_id, + charges, + augment_one, + augment_two, + augment_three, + augment_four, + augment_five, + augment_six, + attuned, + slot_id + ); + } +} + void perl_register_bot() { perl::interpreter state(PERL_GET_THX); @@ -400,6 +460,7 @@ void perl_register_bot() package.add("AddBotItem", (void(*)(Bot*, uint16, uint32, uint16, bool, uint32, uint32, uint32, uint32))&Perl_Bot_AddBotItem); package.add("AddBotItem", (void(*)(Bot*, uint16, uint32, uint16, bool, uint32, uint32, uint32, uint32, uint32))&Perl_Bot_AddBotItem); package.add("AddBotItem", (void(*)(Bot*, uint16, uint32, uint16, bool, uint32, uint32, uint32, uint32, uint32, uint32))&Perl_Bot_AddBotItem); + package.add("AddItem", &Perl_Bot_AddItem); package.add("ApplySpell", (void(*)(Bot*, int))&Perl_Bot_ApplySpell); package.add("ApplySpell", (void(*)(Bot*, int, int))&Perl_Bot_ApplySpell); package.add("ApplySpell", (void(*)(Bot*, int, int, bool))&Perl_Bot_ApplySpell); @@ -420,6 +481,7 @@ void perl_register_bot() package.add("Fling", (void(*)(Bot*, float, float, float, float, bool, bool))&Perl_Bot_Fling); package.add("GetAugmentAt", &Perl_Bot_GetAugmentAt); package.add("GetAugmentIDAt", &Perl_Bot_GetAugmentIDAt); + package.add("GetAugmentIDsBySlotID", &Perl_Bot_GetAugmentIDsBySlotID); package.add("GetBaseAGI", &Perl_Bot_GetBaseAGI); package.add("GetBaseCHA", &Perl_Bot_GetBaseCHA); package.add("GetBaseDEX", &Perl_Bot_GetBaseDEX); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 117437e90..2f2ccaa46 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -19,11 +19,6 @@ bool Perl_Client_Save(Client* self, uint8 commit_now) // @categories Script Util return self->Save(commit_now); } -void Perl_Client_SaveBackup(Client* self) // @categories Script Utility -{ - self->SaveBackup(); -} - bool Perl_Client_Connected(Client* self) // @categories Script Utility { return self->Connected(); @@ -2755,6 +2750,11 @@ void Perl_Client_Signal(Client* self, int signal_id) self->Signal(signal_id); } +void Perl_Client_SignalClient(Client* self, int signal_id) // @categories Script Utility +{ + self->Signal(signal_id); +} + std::string Perl_Client_GetGuildPublicNote(Client* self) { return self->GetGuildPublicNote(); @@ -2872,6 +2872,36 @@ void Perl_Client_CampAllBots(Client* self, uint8 class_id) self->CampAllBots(class_id); } +void Perl_Client_ResetItemCooldown(Client* self, uint32 item_id) +{ + self->ResetItemCooldown(item_id); +} + +void Perl_Client_SetItemCooldown(Client* self, uint32 item_id, uint32 in_time) +{ + self->SetItemCooldown(item_id, false, in_time); +} + +uint32 Perl_Client_GetItemCooldown(Client* self, uint32 item_id) +{ + return self->GetItemCooldown(item_id); +} + +void Perl_Client_UseAugmentContainer(Client* self, int container_slot) +{ + self->UseAugmentContainer(container_slot); +} + +bool Perl_Client_IsAutoAttackEnabled(Client* self) +{ + return self->AutoAttackEnabled(); +} + +bool Perl_Client_IsAutoFireEnabled(Client* self) +{ + return self->AutoFireEnabled(); +} + void perl_register_client() { perl::interpreter perl(PERL_GET_THX); @@ -3066,6 +3096,7 @@ void perl_register_client() package.add("GetInventory", &Perl_Client_GetInventory); package.add("GetInvulnerableEnvironmentDamage", &Perl_Client_GetInvulnerableEnvironmentDamage); package.add("GetItemAt", &Perl_Client_GetItemAt); + package.add("GetItemCooldown", &Perl_Client_GetItemCooldown); package.add("GetItemIDAt", &Perl_Client_GetItemIDAt); package.add("GetItemInInventory", &Perl_Client_GetItemInInventory); package.add("GetLDoNLosses", &Perl_Client_GetLDoNLosses); @@ -3133,6 +3164,8 @@ void perl_register_client() package.add("IncreaseSkill", (void(*)(Client*, int))&Perl_Client_IncreaseSkill); package.add("IncreaseSkill", (void(*)(Client*, int, int))&Perl_Client_IncreaseSkill); package.add("IncrementAA", &Perl_Client_IncrementAA); + package.add("IsAutoAttackEnabled", &Perl_Client_IsAutoAttackEnabled); + package.add("IsAutoFireEnabled", &Perl_Client_IsAutoFireEnabled); package.add("IsBecomeNPC", &Perl_Client_IsBecomeNPC); package.add("IsCrouching", &Perl_Client_IsCrouching); package.add("IsDueling", &Perl_Client_IsDueling); @@ -3231,9 +3264,9 @@ void perl_register_client() package.add("ResetCastbarCooldownBySlot", &Perl_Client_ResetCastbarCooldownBySlot); package.add("ResetCastbarCooldownBySpellID", &Perl_Client_ResetCastbarCooldownBySpellID); package.add("ResetDisciplineTimer", &Perl_Client_ResetDisciplineTimer); + package.add("ResetItemCooldown", &Perl_Client_ResetItemCooldown); package.add("ResetTrade", &Perl_Client_ResetTrade); package.add("Save", &Perl_Client_Save); - package.add("SaveBackup", &Perl_Client_SaveBackup); package.add("ScribeSpell", (void(*)(Client*, uint16, int))&Perl_Client_ScribeSpell); package.add("ScribeSpell", (void(*)(Client*, uint16, int, bool))&Perl_Client_ScribeSpell); package.add("ScribeSpells", &Perl_Client_ScribeSpells); @@ -3307,6 +3340,7 @@ void perl_register_client() package.add("SetHunger", &Perl_Client_SetHunger); package.add("SetIPExemption", &Perl_Client_SetIPExemption); package.add("SetInvulnerableEnvironmentDamage", &Perl_Client_SetInvulnerableEnvironmentDamage); + package.add("SetItemCooldown", &Perl_Client_SetItemCooldown); package.add("SetLanguageSkill", &Perl_Client_SetLanguageSkill); package.add("SetMaterial", &Perl_Client_SetMaterial); package.add("SetPEQZoneFlag", &Perl_Client_SetPEQZoneFlag); @@ -3339,6 +3373,7 @@ void perl_register_client() package.add("SetTitleSuffix", (void(*)(Client*, std::string, bool))&Perl_Client_SetTitleSuffix); package.add("SetZoneFlag", &Perl_Client_SetZoneFlag); package.add("Signal", &Perl_Client_Signal); + package.add("SignalClient", &Perl_Client_SignalClient); package.add("SilentMessage", &Perl_Client_SilentMessage); package.add("Sit", &Perl_Client_Sit); package.add("SlotConvert2", &Perl_Client_SlotConvert2); @@ -3396,6 +3431,7 @@ void perl_register_client() package.add("UpdateWho", (void(*)(Client*))&Perl_Client_UpdateWho); package.add("UpdateWho", (void(*)(Client*, uint8))&Perl_Client_UpdateWho); package.add("UseDiscipline", &Perl_Client_UseDiscipline); + package.add("UseAugmentContainer", &Perl_Client_UseAugmentContainer); package.add("WorldKick", &Perl_Client_WorldKick); } diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index a97719b3d..4ce5df213 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -731,11 +731,36 @@ int64_t Perl_Mob_GetActSpellDamage(Mob* self, uint16 spell_id, int64 value) // @ return self->GetActSpellDamage(spell_id, value); } +int64_t Perl_Mob_GetActSpellDamage(Mob* self, uint16 spell_id, int64 value, Mob* target) // @categories Spells and Disciplines +{ + return self->GetActSpellDamage(spell_id, value, target); +} + +int64_t Perl_Mob_GetActDoTDamage(Mob* self, uint16 spell_id, int64 value, Mob* target) // @categories Spells and Disciplines +{ + return self->GetActDoTDamage(spell_id, value, target); +} + +int64_t Perl_Mob_GetActDoTDamage(Mob* self, uint16 spell_id, int64 value, Mob* target, bool from_buff_tic) // @categories Spells and Disciplines +{ + return self->GetActDoTDamage(spell_id, value, target, from_buff_tic); +} + int64_t Perl_Mob_GetActSpellHealing(Mob* self, uint16 spell_id, int64 value) // @categories Spells and Disciplines { return self->GetActSpellHealing(spell_id, value); } +int64_t Perl_Mob_GetActSpellHealing(Mob* self, uint16 spell_id, int64 value, Mob* target) // @categories Spells and Disciplines +{ + return self->GetActSpellHealing(spell_id, value, target); +} + +int64_t Perl_Mob_GetActSpellHealing(Mob* self, uint16 spell_id, int64 value, Mob* target, bool from_buff_tic) // @categories Spells and Disciplines +{ + return self->GetActSpellHealing(spell_id, value, target, from_buff_tic); +} + int Perl_Mob_GetActSpellCost(Mob* self, uint16 spell_id, int32 cost) // @categories Spells and Disciplines { return self->GetActSpellCost(spell_id, cost); @@ -751,6 +776,11 @@ int Perl_Mob_GetActSpellCasttime(Mob* self, uint16 spell_id, uint32 cast_time) / return self->GetActSpellCasttime(spell_id, cast_time); } +int64 Perl_Mob_GetActReflectedSpellDamage(Mob* self, uint16 spell_id, int64 value, int effectiveness) // @categories Spells and Disciplines +{ + return self->GetActReflectedSpellDamage(spell_id, value, effectiveness); +} + float Perl_Mob_ResistSpell(Mob* self, uint8 resist_type, uint16 spell_id, Mob* caster) // @categories Spells and Disciplines, Script Utility { return self->ResistSpell(resist_type, spell_id, caster); @@ -1831,6 +1861,56 @@ void Perl_Mob_SendIllusion(Mob* self, uint16 race, uint8 gender, uint8 texture, self->SendIllusionPacket(race, gender, texture, helmtexture, haircolor, beardcolor, 0xFF, 0xFF, hairstyle, face, beard, 0xFF, drakkin_heritage, drakkin_tattoo, drakkin_details, size); } +void Perl_Mob_SendIllusion(Mob* self, uint16 race, uint8 gender, uint8 texture, uint8 helmtexture, uint8 face, uint8 hairstyle, uint8 haircolor, uint8 beard, uint8 beardcolor, uint32 drakkin_heritage, uint32 drakkin_tattoo, uint32 drakkin_details, float size, Client* target) // @categories Script Utility +{ + self->SendIllusionPacket(race, gender, texture, helmtexture, haircolor, beardcolor, 0xFF, 0xFF, hairstyle, face, beard, 0xFF, drakkin_heritage, drakkin_tattoo, drakkin_details, size, true, target); +} + +void Perl_Mob_SendIllusionPacket(Mob* self, perl::reference table_ref) +{ + perl::hash table = table_ref; + + uint16 race = table.exists("race") ? table["race"] : self->GetRace(); + uint8 gender = table.exists("gender") ? table["gender"] : self->GetGender(); + uint8 texture = table.exists("texture") ? table["texture"] : self->GetTexture(); + uint8 helmtexture = table.exists("helmtexture") ? table["helmtexture"] : self->GetHelmTexture(); + uint8 haircolor = table.exists("haircolor") ? table["haircolor"] : self->GetHairColor(); + uint8 beardcolor = table.exists("beardcolor") ? table["beardcolor"] : self->GetBeardColor(); + uint8 eyecolor1 = table.exists("eyecolor1") ? table["eyecolor1"] : self->GetEyeColor1(); + uint8 eyecolor2 = table.exists("eyecolor2") ? table["eyecolor2"] : self->GetEyeColor2(); + uint8 hairstyle = table.exists("hairstyle") ? table["hairstyle"] : self->GetHairStyle(); + uint8 luclinface = table.exists("luclinface") ? table["luclinface"] : self->GetLuclinFace(); + uint8 beard = table.exists("beard") ? table["beard"] : self->GetBeard(); + uint8 aa_title = table.exists("aa_title") ? table["aa_title"] : 255; + uint32 drakkin_heritage = table.exists("drakkin_heritage") ? table["drakkin_heritage"] : self->GetDrakkinHeritage(); + uint32 drakkin_tattoo = table.exists("drakkin_tattoo") ? table["drakkin_tattoo"] : self->GetDrakkinTattoo(); + uint32 drakkin_details = table.exists("drakkin_details") ? table["drakkin_details"] : self->GetDrakkinDetails(); + float size = table.exists("size") ? table["size"] : self->GetSize(); + bool send_appearance_effects = table.exists("send_appearance_effects") ? table["send_appearance_effects"] : true; + Client* target = table.exists("target") ? static_cast(table["target"]) : nullptr; + + self->SendIllusionPacket( + race, + gender, + texture, + helmtexture, + haircolor, + beardcolor, + eyecolor1, + eyecolor2, + hairstyle, + luclinface, + beard, + aa_title, + drakkin_heritage, + drakkin_tattoo, + drakkin_details, + size, + send_appearance_effects, + target + ); +} + void Perl_Mob_CameraEffect(Mob* self, uint32 duration) // @categories Script Utility { self->CameraEffect(duration, 0.03125f); @@ -2786,6 +2866,26 @@ Bot* Perl_Mob_GetHateRandomBot(Mob* self) // @categories Hate and Aggro return self->GetHateRandomBot(); } +bool Perl_Mob_IsFindable(Mob* self) // @categories Script Utility +{ + return self->IsFindable(); +} + +bool Perl_Mob_IsTrackable(Mob* self) // @categories Script Utility +{ + return self->IsTrackable(); +} + +bool Perl_Mob_IsBerserk(Mob* self) // @categories Script Utility +{ + return self->IsBerserk(); +} + +float Perl_Mob_GetDefaultRaceSize(Mob* self) // @categories Script Utility +{ + return self->GetDefaultRaceSize(); +} + void perl_register_mob() { perl::interpreter perl(PERL_GET_THX); @@ -2938,11 +3038,17 @@ void perl_register_mob() package.add("GetAC", &Perl_Mob_GetAC); package.add("GetAGI", &Perl_Mob_GetAGI); package.add("GetATK", &Perl_Mob_GetATK); + package.add("GetActDoTDamage", (int64_t(*)(Mob*, uint16, int64, Mob*))&Perl_Mob_GetActDoTDamage); + package.add("GetActDoTDamage", (int64_t(*)(Mob*, uint16, int64, Mob*, bool))&Perl_Mob_GetActDoTDamage); + package.add("GetActReflectedSpellDamage", &Perl_Mob_GetActReflectedSpellDamage); package.add("GetActSpellCasttime", &Perl_Mob_GetActSpellCasttime); package.add("GetActSpellCost", &Perl_Mob_GetActSpellCost); - package.add("GetActSpellDamage", &Perl_Mob_GetActSpellDamage); + package.add("GetActSpellDamage", (int64_t(*)(Mob*, uint16, int64))&Perl_Mob_GetActSpellDamage); + package.add("GetActSpellDamage", (int64_t(*)(Mob*, uint16, int64, Mob*))&Perl_Mob_GetActSpellDamage); package.add("GetActSpellDuration", &Perl_Mob_GetActSpellDuration); - package.add("GetActSpellHealing", &Perl_Mob_GetActSpellHealing); + package.add("GetActSpellHealing", (int64_t(*)(Mob*, uint16, int64))&Perl_Mob_GetActSpellHealing); + package.add("GetActSpellHealing", (int64_t(*)(Mob*, uint16, int64, Mob*))&Perl_Mob_GetActSpellHealing); + package.add("GetActSpellHealing", (int64_t(*)(Mob*, uint16, int64, Mob*, bool))&Perl_Mob_GetActSpellHealing); package.add("GetActSpellRange", &Perl_Mob_GetActSpellRange); package.add("GetAggroRange", &Perl_Mob_GetAggroRange); package.add("GetAllowBeneficial", &Perl_Mob_GetAllowBeneficial); @@ -2970,6 +3076,7 @@ void perl_register_mob() package.add("GetClassName", &Perl_Mob_GetClassName); package.add("GetCleanName", &Perl_Mob_GetCleanName); package.add("GetCorruption", &Perl_Mob_GetCorruption); + package.add("GetDefaultRaceSize", &Perl_Mob_GetDefaultRaceSize); package.add("GetDEX", &Perl_Mob_GetDEX); package.add("GetDR", &Perl_Mob_GetDR); package.add("GetDamageAmount", &Perl_Mob_GetDamageAmount); @@ -3112,6 +3219,7 @@ void perl_register_mob() package.add("IsAttackAllowed", (bool(*)(Mob*, Mob*, bool))&Perl_Mob_IsAttackAllowed); package.add("IsBeacon", &Perl_Mob_IsBeacon); package.add("IsBeneficialAllowed", &Perl_Mob_IsBeneficialAllowed); + package.add("IsBerserk", &Perl_Mob_IsBerserk); package.add("IsBlind", &Perl_Mob_IsBlind); package.add("IsBot", &Perl_Mob_IsBot); package.add("IsCasting", &Perl_Mob_IsCasting); @@ -3122,6 +3230,7 @@ void perl_register_mob() package.add("IsEngaged", &Perl_Mob_IsEngaged); package.add("IsEnraged", &Perl_Mob_IsEnraged); package.add("IsFeared", &Perl_Mob_IsFeared); + package.add("IsFindable", &Perl_Mob_IsFindable); package.add("IsHorse", &Perl_Mob_IsHorse); package.add("IsImmuneToSpell", &Perl_Mob_IsImmuneToSpell); package.add("IsInvisible", (bool(*)(Mob*))&Perl_Mob_IsInvisible); @@ -3142,6 +3251,7 @@ void perl_register_mob() package.add("IsStunned", &Perl_Mob_IsStunned); package.add("IsTargetable", &Perl_Mob_IsTargetable); package.add("IsTargeted", &Perl_Mob_IsTargeted); + package.add("IsTrackable", &Perl_Mob_IsTrackable); package.add("IsTrap", &Perl_Mob_IsTrap); package.add("IsWarriorClass", &Perl_Mob_IsWarriorClass); package.add("Kill", &Perl_Mob_Kill); @@ -3232,6 +3342,8 @@ void perl_register_mob() package.add("SendIllusion", (void(*)(Mob*, uint16, uint8, uint8, uint8, uint8, uint8, uint8, uint8, uint8, uint32, uint32))&Perl_Mob_SendIllusion); package.add("SendIllusion", (void(*)(Mob*, uint16, uint8, uint8, uint8, uint8, uint8, uint8, uint8, uint8, uint32, uint32, uint32))&Perl_Mob_SendIllusion); package.add("SendIllusion", (void(*)(Mob*, uint16, uint8, uint8, uint8, uint8, uint8, uint8, uint8, uint8, uint32, uint32, uint32, float))&Perl_Mob_SendIllusion); + package.add("SendIllusion", (void(*)(Mob*, uint16, uint8, uint8, uint8, uint8, uint8, uint8, uint8, uint8, uint32, uint32, uint32, float, Client*))&Perl_Mob_SendIllusion); + package.add("SendIllusionPacket", (void(*)(Mob*, perl::reference))&Perl_Mob_SendIllusionPacket); package.add("SendTo", &Perl_Mob_SendTo); package.add("SendToFixZ", &Perl_Mob_SendToFixZ); package.add("SendWearChange", &Perl_Mob_SendWearChange); diff --git a/zone/perl_npc.cpp b/zone/perl_npc.cpp index a5fc52d12..d5ba5c86a 100644 --- a/zone/perl_npc.cpp +++ b/zone/perl_npc.cpp @@ -584,6 +584,16 @@ bool Perl_NPC_GetCombatState(NPC* self) // @categories Script Utility return self->GetCombatEvent(); } +void Perl_NPC_SetSimpleRoamBox(NPC* self, float box_size) // @categories Script Utility +{ + self->SetSimpleRoamBox(box_size); +} + +void Perl_NPC_SetSimpleRoamBox(NPC* self, float box_size, float move_distance) // @categories Script Utility +{ + self->SetSimpleRoamBox(box_size, move_distance); +} + void Perl_NPC_SetSimpleRoamBox(NPC* self, float box_size, float move_distance, int move_delay) // @categories Script Utility { self->SetSimpleRoamBox(box_size, move_distance, move_delay); @@ -594,11 +604,6 @@ void Perl_NPC_RecalculateSkills(NPC* self) // @categories Skills and Recipes self->RecalculateSkills(); } -void Perl_NPC_ScaleNPC(NPC* self, uint8 npc_level) -{ - return self->ScaleNPC(npc_level); -} - bool Perl_NPC_IsRaidTarget(NPC* self) { return self->IsRaidTarget(); @@ -690,6 +695,86 @@ void Perl_NPC_SetKeepsSoldItems(NPC* self, bool keeps_sold_items) self->SetKeepsSoldItems(keeps_sold_items); } +bool Perl_NPC_IsLDoNTrapped(NPC* self) +{ + return self->IsLDoNTrapped(); +} + +void Perl_NPC_SetLDoNTrapped(NPC* self, bool is_trapped) +{ + self->SetLDoNTrapped(is_trapped); +} + +uint8 Perl_NPC_GetLDoNTrapType(NPC* self) +{ + return self->GetLDoNTrapType(); +} + +void Perl_NPC_SetLDoNTrapType(NPC* self, uint8 trap_type) +{ + self->SetLDoNTrapType(trap_type); +} + +uint16 Perl_NPC_GetLDoNTrapSpellID(NPC* self) +{ + return self->GetLDoNTrapSpellID(); +} + +void Perl_NPC_SetLDoNTrapSpellID(NPC* self, uint16 spell_id) +{ + self->SetLDoNTrapSpellID(spell_id); +} + +bool Perl_NPC_IsLDoNLocked(NPC* self) +{ + return self->IsLDoNLocked(); +} + +void Perl_NPC_SetLDoNLocked(NPC* self, bool is_locked) +{ + self->SetLDoNLocked(is_locked); +} + +uint16 Perl_NPC_GetLDoNLockedSkill(NPC* self) +{ + return self->GetLDoNLockedSkill(); +} + +void Perl_NPC_SetLDoNLockedSkill(NPC* self, uint16 skill_value) +{ + self->SetLDoNLockedSkill(skill_value); +} + +bool Perl_NPC_IsLDoNTrapDetected(NPC* self) +{ + return self->IsLDoNTrapDetected(); +} + +void Perl_NPC_SetLDoNTrapDetected(NPC* self, bool is_detected) +{ + self->SetLDoNTrapDetected(is_detected); +} + +void Perl_NPC_ScaleNPC(NPC* self, uint8 npc_level) +{ + return self->ScaleNPC(npc_level); +} + +void Perl_NPC_ScaleNPC(NPC* self, uint8 npc_level, bool override_special_abilities) +{ + return self->ScaleNPC(npc_level, override_special_abilities); +} + +bool Perl_NPC_IsUnderwaterOnly(NPC* self) // @categories Script Utility +{ + return self->IsUnderwaterOnly(); +} + +bool Perl_NPC_HasSpecialAbilities(NPC* self) // @categories Script Utility +{ + return self->HasSpecialAbilities(); +} + void perl_register_npc() { perl::interpreter perl(PERL_GET_THX); @@ -742,6 +827,9 @@ void perl_register_npc() package.add("GetHealScale", &Perl_NPC_GetHealScale); package.add("GetItemIDBySlot", &Perl_NPC_GetItemIDBySlot); package.add("GetKeepsSoldItems", &Perl_NPC_GetKeepsSoldItems); + package.add("GetLDoNLockedSkill", &Perl_NPC_GetLDoNLockedSkill); + package.add("GetLDoNTrapType", &Perl_NPC_GetLDoNTrapType); + package.add("GetLDoNTrapSpellID", &Perl_NPC_GetLDoNTrapSpellID); package.add("GetLootList", &Perl_NPC_GetLootList); package.add("GetLoottableID", &Perl_NPC_GetLoottableID); package.add("GetMaxDMG", &Perl_NPC_GetMaxDMG); @@ -774,13 +862,18 @@ void perl_register_npc() package.add("GetSwarmTarget", &Perl_NPC_GetSwarmTarget); package.add("GetWaypointMax", &Perl_NPC_GetWaypointMax); package.add("HasAISpellEffect", &Perl_NPC_HasAISpellEffect); + package.add("HasSpecialAbilities", &Perl_NPC_HasSpecialAbilities); package.add("HasItem", &Perl_NPC_HasItem); package.add("IsAnimal", &Perl_NPC_IsAnimal); package.add("IsGuarding", &Perl_NPC_IsGuarding); + package.add("IsLDoNLocked", &Perl_NPC_IsLDoNLocked); + package.add("IsLDoNTrapped", &Perl_NPC_IsLDoNTrapped); + package.add("IsLDoNTrapDetected", &Perl_NPC_IsLDoNTrapDetected);; package.add("IsOnHatelist", &Perl_NPC_IsOnHatelist); package.add("IsRaidTarget", &Perl_NPC_IsRaidTarget); package.add("IsRareSpawn", &Perl_NPC_IsRareSpawn); package.add("IsTaunting", &Perl_NPC_IsTaunting); + package.add("IsUnderwaterOnly", (bool(*)(NPC*))&Perl_NPC_IsUnderwaterOnly); package.add("MerchantCloseShop", &Perl_NPC_MerchantCloseShop); package.add("MerchantOpenShop", &Perl_NPC_MerchantOpenShop); package.add("ModifyNPCStat", &Perl_NPC_ModifyNPCStat); @@ -806,11 +899,18 @@ void perl_register_npc() package.add("SaveGuardSpot", (void(*)(NPC*))&Perl_NPC_SaveGuardSpot); package.add("SaveGuardSpot", (void(*)(NPC*, bool))&Perl_NPC_SaveGuardSpot); package.add("SaveGuardSpot", (void(*)(NPC*, float, float, float, float))&Perl_NPC_SaveGuardSpot); - package.add("ScaleNPC", &Perl_NPC_ScaleNPC); + package.add("ScaleNPC", (void(*)(NPC*, uint8))&Perl_NPC_ScaleNPC); + package.add("ScaleNPC", (void(*)(NPC*, uint8, bool))&Perl_NPC_ScaleNPC); package.add("SendPayload", (void(*)(NPC*, int))&Perl_NPC_SendPayload); package.add("SendPayload", (void(*)(NPC*, int, std::string))&Perl_NPC_SendPayload); package.add("SetCopper", &Perl_NPC_SetCopper); package.add("SetKeepsSoldItems", &Perl_NPC_SetKeepsSoldItems); + package.add("SetLDoNLocked", &Perl_NPC_SetLDoNLocked); + package.add("SetLDoNLockedSkill", &Perl_NPC_SetLDoNLockedSkill); + package.add("SetLDoNTrapped", &Perl_NPC_SetLDoNTrapped); + package.add("SetLDoNTrapDetected", &Perl_NPC_SetLDoNTrapDetected); + package.add("SetLDoNTrapSpellID", &Perl_NPC_SetLDoNTrapSpellID); + package.add("SetLDoNTrapType", &Perl_NPC_SetLDoNTrapType); package.add("SetGold", &Perl_NPC_SetGold); package.add("SetGrid", &Perl_NPC_SetGrid); package.add("SetNPCFactionID", &Perl_NPC_SetNPCFactionID); @@ -820,7 +920,9 @@ void perl_register_npc() package.add("SetSaveWaypoint", &Perl_NPC_SetSaveWaypoint); package.add("SetSecSkill", &Perl_NPC_SetSecSkill); package.add("SetSilver", &Perl_NPC_SetSilver); - package.add("SetSimpleRoamBox", &Perl_NPC_SetSimpleRoamBox); + package.add("SetSimpleRoamBox", (void(*)(NPC*, float))&Perl_NPC_SetSimpleRoamBox); + package.add("SetSimpleRoamBox", (void(*)(NPC*, float, float))&Perl_NPC_SetSimpleRoamBox); + package.add("SetSimpleRoamBox", (void(*)(NPC*, float, float, int))&Perl_NPC_SetSimpleRoamBox); package.add("SetSp2", &Perl_NPC_SetSp2); package.add("SetSpellFocusDMG", &Perl_NPC_SetSpellFocusDMG); package.add("SetSpellFocusHeal", &Perl_NPC_SetSpellFocusHeal); diff --git a/zone/petitions.cpp b/zone/petitions.cpp index d5accbbd3..41c5e3e02 100644 --- a/zone/petitions.cpp +++ b/zone/petitions.cpp @@ -270,22 +270,22 @@ void ZoneDatabase::RefreshPetitionsFromDB() } for (auto row = results.begin(); row != results.end(); ++row) { - newpet = new Petition(atoi(row[0])); + newpet = new Petition(Strings::ToInt(row[0])); newpet->SetCName(row[1]); newpet->SetAName(row[2]); newpet->SetLastGM(row[3]); newpet->SetPetitionText(row[4]); - newpet->SetZone(atoi(row[5])); - newpet->SetUrgency(atoi(row[6])); - newpet->SetClass(atoi(row[7])); - newpet->SetRace(atoi(row[8])); - newpet->SetLevel(atoi(row[9])); - newpet->SetCheckouts(atoi(row[10])); - newpet->SetUnavails(atoi(row[11])); - newpet->SetSentTime2(atol(row[13])); + newpet->SetZone(Strings::ToInt(row[5])); + newpet->SetUrgency(Strings::ToInt(row[6])); + newpet->SetClass(Strings::ToInt(row[7])); + newpet->SetRace(Strings::ToInt(row[8])); + newpet->SetLevel(Strings::ToInt(row[9])); + newpet->SetCheckouts(Strings::ToInt(row[10])); + newpet->SetUnavails(Strings::ToInt(row[11])); + newpet->SetSentTime(atol(row[13])); newpet->SetGMText(row[14]); - if (atoi(row[12]) == 1) + if (Strings::ToInt(row[12]) == 1) newpet->SetCheckedOut(true); else newpet->SetCheckedOut(false); diff --git a/zone/petitions.h b/zone/petitions.h index 2e8ee96a6..b3a0dc5fd 100644 --- a/zone/petitions.h +++ b/zone/petitions.h @@ -73,8 +73,7 @@ public: void SetPetID(uint32 id_in) { petid = id_in; } void SetCheckouts(uint32 checks_in) { checkouts = checks_in; } void SetUnavails(uint32 unavails_in) { unavailables = unavails_in; } - void SetSentTime() { time(&senttime); } - void SetSentTime2(time_t senttime_in) { senttime = senttime_in; } + void SetSentTime(time_t senttime_in) { senttime = senttime_in; } protected: @@ -115,7 +114,6 @@ public: private: LinkedList list; - uint32 last_insert_id; Mutex PList_Mutex; }; diff --git a/zone/pets.cpp b/zone/pets.cpp index 691ef8ebd..8c5018518 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -194,7 +194,6 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, if (petpower == -1) { if (IsClient()) { act_power = CastToClient()->GetFocusEffect(focusPetPower, spell_id);//Client only - act_power = CastToClient()->mod_pet_power(act_power, spell_id); } else if (IsBot()) act_power = CastToBot()->GetFocusEffect(focusPetPower, spell_id); @@ -328,7 +327,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, if (results.RowCount() != 0) { auto row = results.begin(); - monsterid = atoi(row[0]); + monsterid = Strings::ToInt(row[0]); } // since we don't have any monsters, just make it look like an earth pet for now @@ -492,13 +491,13 @@ bool ZoneDatabase::GetPoweredPetEntry(const char *pet_type, int16 petpower, PetR auto row = results.begin(); - into->npc_type = atoi(row[0]); - into->temporary = atoi(row[1]); - into->petpower = atoi(row[2]); - into->petcontrol = atoi(row[3]); - into->petnaming = atoi(row[4]); - into->monsterflag = atoi(row[5]); - into->equipmentset = atoi(row[6]); + into->npc_type = Strings::ToInt(row[0]); + into->temporary = Strings::ToInt(row[1]); + into->petpower = Strings::ToInt(row[2]); + into->petcontrol = Strings::ToInt(row[3]); + into->petnaming = Strings::ToInt(row[4]); + into->monsterflag = Strings::ToInt(row[5]); + into->equipmentset = Strings::ToInt(row[6]); return true; } @@ -575,7 +574,7 @@ void NPC::GetPetState(SpellBuff_Struct *pet_buffs, uint32 *items, char *name) { //save their buffs. for (int i=EQ::invslot::EQUIPMENT_BEGIN; i < GetPetMaxTotalSlots(); i++) { - if (buffs[i].spellid != SPELL_UNKNOWN) { + if (IsValidSpell(buffs[i].spellid)) { pet_buffs[i].spellid = buffs[i].spellid; pet_buffs[i].effect_type = i+1; pet_buffs[i].duration = buffs[i].ticsremaining; @@ -601,7 +600,7 @@ void NPC::SetPetState(SpellBuff_Struct *pet_buffs, uint32 *items) { for (i = 0; i < GetPetMaxTotalSlots(); i++) { for(int z = 0; z < GetPetMaxTotalSlots(); z++) { // check for duplicates - if(buffs[z].spellid != SPELL_UNKNOWN && buffs[z].spellid == pet_buffs[i].spellid) { + if(IsValidSpell(buffs[z].spellid) && buffs[z].spellid == pet_buffs[i].spellid) { buffs[z].spellid = SPELL_UNKNOWN; pet_buffs[i].spellid = 0xFFFFFFFF; } @@ -720,20 +719,20 @@ bool ZoneDatabase::GetBasePetItems(int32 equipmentset, uint32 *items) { } auto row = results.begin(); - nextset = atoi(row[0]); + nextset = Strings::ToInt(row[0]); query = StringFormat("SELECT slot, item_id FROM pets_equipmentset_entries WHERE set_id='%d'", curset); results = QueryDatabase(query); if (results.Success()) { for (row = results.begin(); row != results.end(); ++row) { - slot = atoi(row[0]); + slot = Strings::ToInt(row[0]); if (slot > EQ::invslot::EQUIPMENT_END) continue; if (items[slot] == 0) - items[slot] = atoi(row[1]); + items[slot] = Strings::ToInt(row[1]); } } @@ -769,11 +768,11 @@ BeastlordPetData::PetStruct ZoneDatabase::GetBeastlordPetData(uint16 race_id) { } auto row = results.begin(); - beastlord_pet_data.race_id = atoi(row[0]); - beastlord_pet_data.texture = atoi(row[1]); - beastlord_pet_data.helm_texture = atoi(row[2]); - beastlord_pet_data.gender = atoi(row[3]); - beastlord_pet_data.size_modifier = atof(row[4]); - beastlord_pet_data.face = atoi(row[5]); + beastlord_pet_data.race_id = Strings::ToInt(row[0]); + beastlord_pet_data.texture = Strings::ToInt(row[1]); + beastlord_pet_data.helm_texture = Strings::ToInt(row[2]); + beastlord_pet_data.gender = Strings::ToInt(row[3]); + beastlord_pet_data.size_modifier = Strings::ToFloat(row[4]); + beastlord_pet_data.face = Strings::ToInt(row[5]); return beastlord_pet_data; } diff --git a/zone/position.cpp b/zone/position.cpp index c2da54be8..18577afd8 100644 --- a/zone/position.cpp +++ b/zone/position.cpp @@ -19,10 +19,6 @@ std::string to_string(const glm::vec2 &position){ return StringFormat("(%.3f, %.3f)", position.x,position.y); } -bool IsOrigin(const glm::vec2 &position) { - return glm::dot(position, position) == 0; -} - bool IsOrigin(const glm::vec3 &position) { return glm::dot(position, position) == 0; } diff --git a/zone/position.h b/zone/position.h index 8dcf42c3c..dbafdc911 100644 --- a/zone/position.h +++ b/zone/position.h @@ -31,7 +31,6 @@ std::string to_string(const glm::vec2 &position); bool IsWithinAxisAlignedBox(const glm::vec3 &position, const glm::vec3 &minimum, const glm::vec3 &maximum); bool IsWithinAxisAlignedBox(const glm::vec2 &position, const glm::vec2 &minimum, const glm::vec2 &maximum); -bool IsOrigin(const glm::vec2 &position); bool IsOrigin(const glm::vec3 &position); bool IsOrigin(const glm::vec4 &position); diff --git a/zone/qglobals.cpp b/zone/qglobals.cpp index fee93765d..ce65598c3 100644 --- a/zone/qglobals.cpp +++ b/zone/qglobals.cpp @@ -171,5 +171,5 @@ void QGlobalCache::LoadBy(const std::string &query) return; for (auto row = results.begin(); row != results.end(); ++row) - AddGlobal(0, QGlobal(row[0], atoi(row[1]), atoi(row[2]), atoi(row[3]), row[4], row[5] ? atoi(row[5]) : 0xFFFFFFFF)); + AddGlobal(0, QGlobal(row[0], Strings::ToInt(row[1]), Strings::ToInt(row[2]), Strings::ToInt(row[3]), row[4], row[5] ? Strings::ToInt(row[5]) : 0xFFFFFFFF)); } diff --git a/zone/quest_parser_collection.cpp b/zone/quest_parser_collection.cpp index 7cedb1e96..acd850d40 100644 --- a/zone/quest_parser_collection.cpp +++ b/zone/quest_parser_collection.cpp @@ -103,8 +103,8 @@ void QuestParserCollection::RemoveEncounter(const std::string name) { } } -bool QuestParserCollection::HasQuestSub(uint32 npcid, QuestEventID evt, bool check_encounters) { - return HasQuestSubLocal(npcid, evt) || HasQuestSubGlobal(evt) || (check_encounters && NPCHasEncounterSub(npcid, evt)); +bool QuestParserCollection::HasQuestSub(uint32 npcid, QuestEventID evt) { + return HasQuestSubLocal(npcid, evt) || HasQuestSubGlobal(evt) || NPCHasEncounterSub(npcid, evt); } bool QuestParserCollection::NPCHasEncounterSub(uint32 npc_id, QuestEventID evt) { @@ -162,8 +162,8 @@ bool QuestParserCollection::HasQuestSubGlobal(QuestEventID evt) { return false; } -bool QuestParserCollection::PlayerHasQuestSub(QuestEventID evt, bool check_encounters) { - return PlayerHasQuestSubLocal(evt) || PlayerHasQuestSubGlobal(evt) || (check_encounters && PlayerHasEncounterSub(evt)); +bool QuestParserCollection::PlayerHasQuestSub(QuestEventID evt) { + return PlayerHasQuestSubLocal(evt) || PlayerHasQuestSubGlobal(evt) || PlayerHasEncounterSub(evt); } bool QuestParserCollection::PlayerHasEncounterSub(QuestEventID evt) { @@ -207,8 +207,8 @@ bool QuestParserCollection::SpellHasEncounterSub(uint32 spell_id, QuestEventID e return HasEncounterSub(evt, package_name); } -bool QuestParserCollection::SpellHasQuestSub(uint32 spell_id, QuestEventID evt, bool check_encounters) { - if (check_encounters && SpellHasEncounterSub(spell_id, evt)) { +bool QuestParserCollection::SpellHasQuestSub(uint32 spell_id, QuestEventID evt) { + if (SpellHasEncounterSub(spell_id, evt)) { return true; } @@ -241,11 +241,11 @@ bool QuestParserCollection::ItemHasEncounterSub(EQ::ItemInstance* item, QuestEve return false; } -bool QuestParserCollection::ItemHasQuestSub(EQ::ItemInstance *itm, QuestEventID evt, bool check_encounters) { +bool QuestParserCollection::ItemHasQuestSub(EQ::ItemInstance *itm, QuestEventID evt) { if (itm == nullptr) return false; - if (check_encounters && ItemHasEncounterSub(itm, evt)) { + if (ItemHasEncounterSub(itm, evt)) { return true; } diff --git a/zone/quest_parser_collection.h b/zone/quest_parser_collection.h index bc2b1d51e..1c68eab51 100644 --- a/zone/quest_parser_collection.h +++ b/zone/quest_parser_collection.h @@ -67,10 +67,10 @@ public: void ReloadQuests(bool reset_timers = true); void RemoveEncounter(const std::string name); - bool HasQuestSub(uint32 npcid, QuestEventID evt, bool check_encounters = false); - bool PlayerHasQuestSub(QuestEventID evt, bool check_encounters = false); - bool SpellHasQuestSub(uint32 spell_id, QuestEventID evt, bool check_encounters = false); - bool ItemHasQuestSub(EQ::ItemInstance *itm, QuestEventID evt, bool check_encounters = false); + bool HasQuestSub(uint32 npcid, QuestEventID evt); + bool PlayerHasQuestSub(QuestEventID evt); + bool SpellHasQuestSub(uint32 spell_id, QuestEventID evt); + bool ItemHasQuestSub(EQ::ItemInstance *itm, QuestEventID evt); bool BotHasQuestSub(QuestEventID evt); int EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 9e6b4859d..ea41f1e63 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -23,6 +23,7 @@ #include "../common/spdat.h" #include "../common/strings.h" #include "../common/say_link.h" +#include "../common/events/player_event_logs.h" #include "entity.h" #include "event_codes.h" @@ -87,28 +88,45 @@ void QuestManager::Process() { end = QTimerList.end(); while (cur != end) { if (cur->Timer_.Enabled() && cur->Timer_.Check()) { - if(entity_list.IsMobInZone(cur->mob)) { - if(cur->mob->IsNPC()) { - parse->EventNPC(EVENT_TIMER, cur->mob->CastToNPC(), nullptr, cur->name, 0); - } else if (cur->mob->IsEncounter()) { - parse->EventEncounter(EVENT_TIMER, cur->mob->CastToEncounter()->GetEncounterName(), cur->name, 0, nullptr); - } else if (cur->mob->IsClient()) { - //this is inheriently unsafe if we ever make it so more than npc/client start timers - parse->EventPlayer(EVENT_TIMER, cur->mob->CastToClient(), cur->name, 0); + if (cur->mob) { + if (cur->mob->IsNPC()) { + if (parse->HasQuestSub(cur->mob->GetNPCTypeID(), EVENT_TIMER)) { + parse->EventNPC(EVENT_TIMER, cur->mob->CastToNPC(), nullptr, cur->name, 0); + } + } + else if (cur->mob->IsEncounter()) { + parse->EventEncounter( + EVENT_TIMER, + cur->mob->CastToEncounter()->GetEncounterName(), + cur->name, + 0, + nullptr + ); + } + else if (cur->mob->IsClient()) { + if (parse->PlayerHasQuestSub(EVENT_TIMER)) { + //this is inheriently unsafe if we ever make it so more than npc/client start timers + parse->EventPlayer(EVENT_TIMER, cur->mob->CastToClient(), cur->name, 0); + } } else if (cur->mob->IsBot()) { - parse->EventBot(EVENT_TIMER, cur->mob->CastToBot(), nullptr, cur->name, 0); + if (parse->BotHasQuestSub(EVENT_TIMER)) { + parse->EventBot(EVENT_TIMER, cur->mob->CastToBot(), nullptr, cur->name, 0); + } } //we MUST reset our iterator since the quest could have removed/added any //number of timers... worst case we have to check a bunch of timers twice cur = QTimerList.begin(); - end = QTimerList.end(); //dunno if this is needed, cant hurt... - } else { + end = QTimerList.end(); //dunno if this is needed, cant hurt... + } + else { cur = QTimerList.erase(cur); } - } else + } + else { ++cur; + } } auto cur_iter = STimerList.begin(); @@ -1642,7 +1660,7 @@ int QuestManager::QGVarDuration(const char *fmt) // Set val to value after type character // e.g., for "M3924", set to 3924 - int val = atoi(&fmt[0] + 1); + int val = Strings::ToInt(&fmt[0] + 1); switch (fmt[0]) { @@ -1907,9 +1925,9 @@ void QuestManager::showgrid(int grid) { } for(auto row = results.begin(); row != results.end(); ++row) { - pt.x = atof(row[0]); - pt.y = atof(row[1]); - pt.z = atof(row[2]); + pt.x = Strings::ToFloat(row[0]); + pt.y = Strings::ToFloat(row[1]); + pt.z = Strings::ToFloat(row[2]); pts.push_back(pt); } @@ -2112,7 +2130,7 @@ void QuestManager::playertexture(int newtexture) initiator->SendIllusionPacket(initiator->GetRace(), 0xFF, newtexture); } -void QuestManager::playerfeature(char *feature, int setting) +void QuestManager::playerfeature(const char* feature, int setting) { QuestManagerCurrentQuestVars(); uint16 Race = initiator->GetRace(); @@ -2169,7 +2187,7 @@ void QuestManager::playerfeature(char *feature, int setting) DrakkinHeritage, DrakkinTattoo, DrakkinDetails, Size); } -void QuestManager::npcfeature(char *feature, int setting) +void QuestManager::npcfeature(const char* feature, int setting) { QuestManagerCurrentQuestVars(); uint16 Race = owner->GetRace(); @@ -2421,16 +2439,19 @@ bool QuestManager::createBot(const char *name, const char *lastname, uint8 level ).c_str() ); - const auto export_string = fmt::format( - "{} {} {} {} {}", - name, - new_bot->GetBotID(), - race, - botclass, - gender - ); + if (parse->PlayerHasQuestSub(EVENT_BOT_CREATE)) { + const auto& export_string = fmt::format( + "{} {} {} {} {}", + name, + new_bot->GetBotID(), + race, + botclass, + gender + ); + + parse->EventPlayer(EVENT_BOT_CREATE, initiator, export_string, 0); + } - parse->EventPlayer(EVENT_BOT_CREATE, initiator, export_string, 0); return true; } } @@ -2940,7 +2961,6 @@ std::string QuestManager::varlink( return linker.GenerateLink(); } - std::string QuestManager::getitemname(uint32 item_id) { const EQ::ItemData* item_data = database.GetItem(item_id); if (!item_data) { @@ -3034,7 +3054,7 @@ uint32 QuestManager::GetInstanceTimerByID(uint16 instance_id) { if (results.Success()) { auto row = results.begin(); - uint32 timer = atoi(row[0]); + uint32 timer = Strings::ToInt(row[0]); return timer; } return 0; @@ -3514,71 +3534,71 @@ std::string QuestManager::GetEncounter() const { void QuestManager::UpdateZoneHeader(std::string type, std::string value) { if (strcasecmp(type.c_str(), "ztype") == 0) - zone->newzone_data.ztype = atoi(value.c_str()); + zone->newzone_data.ztype = Strings::ToInt(value.c_str()); else if (strcasecmp(type.c_str(), "fog_red") == 0) { for (int i = 0; i < 4; i++) { - zone->newzone_data.fog_red[i] = atoi(value.c_str()); + zone->newzone_data.fog_red[i] = Strings::ToInt(value.c_str()); } } else if (strcasecmp(type.c_str(), "fog_green") == 0) { for (int i = 0; i < 4; i++) { - zone->newzone_data.fog_green[i] = atoi(value.c_str()); + zone->newzone_data.fog_green[i] = Strings::ToInt(value.c_str()); } } else if (strcasecmp(type.c_str(), "fog_blue") == 0) { for (int i = 0; i < 4; i++) { - zone->newzone_data.fog_blue[i] = atoi(value.c_str()); + zone->newzone_data.fog_blue[i] = Strings::ToInt(value.c_str()); } } else if (strcasecmp(type.c_str(), "fog_minclip") == 0) { for (int i = 0; i < 4; i++) { - zone->newzone_data.fog_minclip[i] = atof(value.c_str()); + zone->newzone_data.fog_minclip[i] = Strings::ToFloat(value.c_str()); } } else if (strcasecmp(type.c_str(), "fog_maxclip") == 0) { for (int i = 0; i < 4; i++) { - zone->newzone_data.fog_maxclip[i] = atof(value.c_str()); + zone->newzone_data.fog_maxclip[i] = Strings::ToFloat(value.c_str()); } } else if (strcasecmp(type.c_str(), "gravity") == 0) { - zone->newzone_data.gravity = atof(value.c_str()); + zone->newzone_data.gravity = Strings::ToFloat(value.c_str()); } else if (strcasecmp(type.c_str(), "time_type") == 0) { - zone->newzone_data.time_type = atoi(value.c_str()); + zone->newzone_data.time_type = Strings::ToInt(value.c_str()); } else if (strcasecmp(type.c_str(), "rain_chance") == 0) { for (int i = 0; i < 4; i++) { - zone->newzone_data.rain_chance[i] = atoi(value.c_str()); + zone->newzone_data.rain_chance[i] = Strings::ToInt(value.c_str()); } } else if (strcasecmp(type.c_str(), "rain_duration") == 0) { for (int i = 0; i < 4; i++) { - zone->newzone_data.rain_duration[i] = atoi(value.c_str()); + zone->newzone_data.rain_duration[i] = Strings::ToInt(value.c_str()); } } else if (strcasecmp(type.c_str(), "snow_chance") == 0) { for (int i = 0; i < 4; i++) { - zone->newzone_data.snow_chance[i] = atoi(value.c_str()); + zone->newzone_data.snow_chance[i] = Strings::ToInt(value.c_str()); } } else if (strcasecmp(type.c_str(), "snow_duration") == 0) { for (int i = 0; i < 4; i++) { - zone->newzone_data.snow_duration[i] = atoi(value.c_str()); + zone->newzone_data.snow_duration[i] = Strings::ToInt(value.c_str()); } } else if (strcasecmp(type.c_str(), "sky") == 0) { - zone->newzone_data.sky = atoi(value.c_str()); + zone->newzone_data.sky = Strings::ToInt(value.c_str()); } else if (strcasecmp(type.c_str(), "safe_x") == 0) { - zone->newzone_data.safe_x = atof(value.c_str()); + zone->newzone_data.safe_x = Strings::ToFloat(value.c_str()); } else if (strcasecmp(type.c_str(), "safe_y") == 0) { - zone->newzone_data.safe_y = atof(value.c_str()); + zone->newzone_data.safe_y = Strings::ToFloat(value.c_str()); } else if (strcasecmp(type.c_str(), "safe_z") == 0) { - zone->newzone_data.safe_z = atof(value.c_str()); + zone->newzone_data.safe_z = Strings::ToFloat(value.c_str()); } else if (strcasecmp(type.c_str(), "max_z") == 0) { - zone->newzone_data.max_z = atof(value.c_str()); + zone->newzone_data.max_z = Strings::ToFloat(value.c_str()); } else if (strcasecmp(type.c_str(), "underworld") == 0) { - zone->newzone_data.underworld = atof(value.c_str()); + zone->newzone_data.underworld = Strings::ToFloat(value.c_str()); } else if (strcasecmp(type.c_str(), "minclip") == 0) { - zone->newzone_data.minclip = atof(value.c_str()); + zone->newzone_data.minclip = Strings::ToFloat(value.c_str()); } else if (strcasecmp(type.c_str(), "maxclip") == 0) { - zone->newzone_data.maxclip = atof(value.c_str()); + zone->newzone_data.maxclip = Strings::ToFloat(value.c_str()); } else if (strcasecmp(type.c_str(), "fog_density") == 0) { - zone->newzone_data.fog_density = atof(value.c_str()); + zone->newzone_data.fog_density = Strings::ToFloat(value.c_str()); } else if (strcasecmp(type.c_str(), "suspendbuffs") == 0) { - zone->newzone_data.suspend_buffs = atoi(value.c_str()); + zone->newzone_data.suspend_buffs = Strings::ToInt(value.c_str()); } else if (strcasecmp(type.c_str(), "lavadamage") == 0) { - zone->newzone_data.lava_damage = atoi(value.c_str()); + zone->newzone_data.lava_damage = Strings::ToInt(value.c_str()); } else if (strcasecmp(type.c_str(), "minlavadamage") == 0) { - zone->newzone_data.min_lava_damage = atoi(value.c_str()); + zone->newzone_data.min_lava_damage = Strings::ToInt(value.c_str()); } auto outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct)); @@ -3969,7 +3989,7 @@ bool QuestManager::DoAugmentSlotsMatch(uint32 item_one, uint32 item_two) return true; } -int8 QuestManager::DoesAugmentFit(EQ::ItemInstance* inst, uint32 augment_id) +int8 QuestManager::DoesAugmentFit(EQ::ItemInstance* inst, uint32 augment_id, uint8 augment_slot) { if (!inst) { return INVALID_INDEX; @@ -3980,5 +4000,185 @@ int8 QuestManager::DoesAugmentFit(EQ::ItemInstance* inst, uint32 augment_id) return INVALID_INDEX; } + if (augment_slot != 255) { + return !inst->IsAugmentSlotAvailable(aug_inst->AugType, augment_slot) ? INVALID_INDEX : augment_slot; + } + return inst->AvailableAugmentSlot(aug_inst->AugType); } + +void QuestManager::SendPlayerHandinEvent() { + QuestManagerCurrentQuestVars(); + if (!owner || !owner->IsNPC() || !initiator) { + return; + } + + if ( + !initiator->EntityVariableExists("HANDIN_ITEMS") && + !initiator->EntityVariableExists("HANDIN_MONEY") && + !initiator->EntityVariableExists("RETURN_ITEMS") && + !initiator->EntityVariableExists("RETURN_MONEY") + ) { + return; + } + + auto handin_items = initiator->GetEntityVariable("HANDIN_ITEMS"); + auto return_items = initiator->GetEntityVariable("RETURN_ITEMS"); + auto handin_money = initiator->GetEntityVariable("HANDIN_MONEY"); + auto return_money = initiator->GetEntityVariable("RETURN_MONEY"); + + std::vector hi = {}; + std::vector ri = {}; + PlayerEvent::HandinMoney hm{}; + PlayerEvent::HandinMoney rm{}; + + // Handin Items + if (!handin_items.empty()) { + if (Strings::Contains(handin_items, ",")) { + const auto handin_data = Strings::Split(handin_items, ","); + for (const auto &h: handin_data) { + const auto item_data = Strings::Split(h, "|"); + if ( + item_data.size() == 3 && + Strings::IsNumber(item_data[0]) && + Strings::IsNumber(item_data[1]) && + Strings::IsNumber(item_data[2]) + ) { + const auto item_id = static_cast(Strings::ToUnsignedInt(item_data[0])); + if (item_id != 0) { + const auto *item = database.GetItem(item_id); + + if (item) { + hi.emplace_back( + PlayerEvent::HandinEntry{ + .item_id = item_id, + .item_name = item->Name, + .charges = static_cast(Strings::ToUnsignedInt(item_data[1])), + .attuned = Strings::ToInt(item_data[2]) ? true : false + } + ); + } + } + } + } + } + else if (Strings::Contains(handin_items, "|")) { + const auto item_data = Strings::Split(handin_items, "|"); + if ( + item_data.size() == 3 && + Strings::IsNumber(item_data[0]) && + Strings::IsNumber(item_data[1]) && + Strings::IsNumber(item_data[2]) + ) { + const auto item_id = static_cast(Strings::ToUnsignedInt(item_data[0])); + const auto *item = database.GetItem(item_id); + + if (item) { + hi.emplace_back( + PlayerEvent::HandinEntry{ + .item_id = item_id, + .item_name = item->Name, + .charges = static_cast(Strings::ToUnsignedInt(item_data[1])), + .attuned = Strings::ToInt(item_data[2]) ? true : false + } + ); + } + } + } + } + + // Handin Money + if (!handin_money.empty()) { + const auto hms = Strings::Split(handin_money, "|"); + hm.copper = static_cast(Strings::ToUnsignedInt(hms[0])); + hm.silver = static_cast(Strings::ToUnsignedInt(hms[1])); + hm.gold = static_cast(Strings::ToUnsignedInt(hms[2])); + hm.platinum = static_cast(Strings::ToUnsignedInt(hms[3])); + } + + // Return Items + if (!return_items.empty()) { + if (Strings::Contains(return_items, ",")) { + const auto return_data = Strings::Split(return_items, ","); + for (const auto &r: return_data) { + const auto item_data = Strings::Split(r, "|"); + if ( + item_data.size() == 3 && + Strings::IsNumber(item_data[0]) && + Strings::IsNumber(item_data[1]) && + Strings::IsNumber(item_data[2]) + ) { + const auto item_id = static_cast(Strings::ToUnsignedInt(item_data[0])); + const auto *item = database.GetItem(item_id); + + if (item) { + ri.emplace_back( + PlayerEvent::HandinEntry{ + .item_id = item_id, + .item_name = item->Name, + .charges = static_cast(Strings::ToUnsignedInt(item_data[1])), + .attuned = Strings::ToInt(item_data[2]) ? true : false + } + ); + } + } + } + } + else if (Strings::Contains(return_items, "|")) { + const auto item_data = Strings::Split(return_items, "|"); + if ( + item_data.size() == 3 && + Strings::IsNumber(item_data[0]) && + Strings::IsNumber(item_data[1]) && + Strings::IsNumber(item_data[2]) + ) { + const auto item_id = static_cast(Strings::ToUnsignedInt(item_data[0])); + const auto *item = database.GetItem(item_id); + + if (item) { + ri.emplace_back( + PlayerEvent::HandinEntry{ + .item_id = item_id, + .item_name = item->Name, + .charges = static_cast(Strings::ToUnsignedInt(item_data[1])), + .attuned = Strings::ToInt(item_data[2]) ? true : false + } + ); + } + } + } + } + + // Return Money + if (!return_money.empty()) { + const auto rms = Strings::Split(return_money, "|"); + rm.copper = static_cast(Strings::ToUnsignedInt(rms[0])); + rm.silver = static_cast(Strings::ToUnsignedInt(rms[1])); + rm.gold = static_cast(Strings::ToUnsignedInt(rms[2])); + rm.platinum = static_cast(Strings::ToUnsignedInt(rms[3])); + } + + initiator->DeleteEntityVariable("HANDIN_ITEMS"); + initiator->DeleteEntityVariable("HANDIN_MONEY"); + initiator->DeleteEntityVariable("RETURN_ITEMS"); + initiator->DeleteEntityVariable("RETURN_MONEY"); + + bool handed_in_money = hm.platinum > 0 || hm.gold > 0 || hm.silver > 0 || hm.copper > 0; + + bool event_has_data_to_record = ( + !hi.empty() || handed_in_money + ); + + if (player_event_logs.IsEventEnabled(PlayerEvent::NPC_HANDIN) && event_has_data_to_record) { + auto e = PlayerEvent::HandinEvent{ + .npc_id = owner->CastToNPC()->GetNPCTypeID(), + .npc_name = owner->GetCleanName(), + .handin_items = hi, + .handin_money = hm, + .return_items = ri, + .return_money = rm + }; + + RecordPlayerEventLogWithClient(initiator, PlayerEvent::NPC_HANDIN, e); + } +} diff --git a/zone/questmgr.h b/zone/questmgr.h index ed7899fbd..5d9f81636 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -140,7 +140,7 @@ public: void movepc(int zone_id, float x, float y, float z, float heading); void gmmove(float x, float y, float z); void movegrp(int zoneid, float x, float y, float z); - void doanim(int animation_id, int animation_speed = 1, bool ackreq = true, eqFilterType filter = FilterNone); + void doanim(int animation_id, int animation_speed = 0, bool ackreq = true, eqFilterType filter = FilterNone); void addskill(int skill_id, int value); void setlanguage(int skill_id, int value); void setskill(int skill_id, int value); @@ -208,8 +208,8 @@ public: void playergender(int gender_id); void playersize(int newsize); void playertexture(int newtexture); - void playerfeature(char *feature, int setting); - void npcfeature(char *feature, int setting); + void playerfeature(const char* feature, int setting); + void npcfeature(const char* feature, int setting); void popup(const char *title, const char *text, uint32 popupid, uint32 buttons, uint32 Duration); void taskselector(const std::vector& tasks, bool ignore_cooldown = false); void tasksetselector(int tasksettid, bool ignore_cooldown = false); @@ -346,7 +346,8 @@ public: std::string GetRecipeName(uint32 recipe_id); bool HasRecipeLearned(uint32 recipe_id); bool DoAugmentSlotsMatch(uint32 item_one, uint32 item_two); - int8 DoesAugmentFit(EQ::ItemInstance* inst, uint32 augment_id); + int8 DoesAugmentFit(EQ::ItemInstance* inst, uint32 augment_id, uint8 augment_slot = 255); + void SendPlayerHandinEvent(); Bot *GetBot() const; Client *GetInitiator() const; diff --git a/zone/queues.h b/zone/queues.h deleted file mode 100644 index 474d7d898..000000000 --- a/zone/queues.h +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ - -/* - Code for generell handling of priority Queues. - Implemention of queues from "Algoritms in C" by Robert Sedgewick. - Copyright Monty Program KB. - By monty. -*/ - -#ifndef _queues_h -#define _queues_h -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct st_queue { - byte **root; - void *first_cmp_arg; - uint elements; - uint max_elements; - uint offset_to_key; /* compare is done on element+offset */ - int max_at_top; /* Set if queue_top gives max */ - int (*compare)(void *, byte *,byte *); -} QUEUE; - -#define queue_top(queue) ((queue)->root[1]) -#define queue_element(queue,index) ((queue)->root[index+1]) -#define queue_end(queue) ((queue)->root[(queue)->elements]) -#define queue_replaced(queue) _downheap(queue,1) - -int init_queue(QUEUE *queue,uint max_elements,uint offset_to_key, - pbool max_at_top, int (*compare)(void *,byte *, byte *), - void *first_cmp_arg); -int reinit_queue(QUEUE *queue,uint max_elements,uint offset_to_key, - pbool max_at_top, int (*compare)(void *,byte *, byte *), - void *first_cmp_arg); -void delete_queue(QUEUE *queue); -void queue_insert(QUEUE *queue,byte *element); -byte *queue_remove(QUEUE *queue,uint idx); -void _downheap(QUEUE *queue,uint idx); -#define is_queue_inited(queue) ((queue)->root != 0) - -#ifdef __cplusplus -} -#endif -#endif diff --git a/zone/raids.cpp b/zone/raids.cpp index b27cae0e0..91f44d962 100644 --- a/zone/raids.cpp +++ b/zone/raids.cpp @@ -17,6 +17,7 @@ */ #include "../common/strings.h" +#include "../common/events/player_event_logs.h" #include "client.h" #include "entity.h" @@ -25,6 +26,7 @@ #include "mob.h" #include "raids.h" #include "string_ids.h" +#include "bot.h" #include "worldserver.h" @@ -93,41 +95,57 @@ bool Raid::Process() } void Raid::AddMember(Client *c, uint32 group, bool rleader, bool groupleader, bool looter){ - if(!c) + if (!c) { return; + } - std::string query = StringFormat("INSERT INTO raid_members SET raidid = %lu, charid = %lu, " - "groupid = %lu, _class = %d, level = %d, name = '%s', " - "isgroupleader = %d, israidleader = %d, islooter = %d", - (unsigned long)GetID(), (unsigned long)c->CharacterID(), - (unsigned long)group, c->GetClass(), c->GetLevel(), - c->GetName(), groupleader, rleader, looter); - auto results = database.QueryDatabase(query); + const auto query = fmt::format( + "REPLACE INTO raid_members SET raidid = {}, charid = {}, bot_id = 0, " + "groupid = {}, _class = {}, level = {}, name = '{}', " + "isgroupleader = {}, israidleader = {}, islooter = {}", + GetID(), + c->CharacterID(), + group, + c->GetClass(), + c->GetLevel(), + c->GetName(), + groupleader, + rleader, + looter + ); + auto results = database.QueryDatabase(query); if(!results.Success()) { LogError("Error inserting into raid members: [{}]", results.ErrorMessage().c_str()); } LearnMembers(); VerifyRaid(); + if (rleader) { + database.SetRaidGroupLeaderInfo(group, GetID()); + UpdateRaidAAs(); + } else if (rleader) { database.SetRaidGroupLeaderInfo(RAID_GROUPLESS, GetID()); UpdateRaidAAs(); } + if (group != RAID_GROUPLESS && groupleader) { database.SetRaidGroupLeaderInfo(group, GetID()); UpdateGroupAAs(group); } - if(group < 12) + + if (group < MAX_RAID_GROUPS) { GroupUpdate(group); - else // get raid AAs, GroupUpdate will handles it otherwise + } else { // get raid AAs, GroupUpdate will handles it otherwise SendGroupLeadershipAA(c, RAID_GROUPLESS); + } + SendRaidAddAll(c->GetName()); c->SetRaidGrouped(true); SendRaidMOTD(c); - // xtarget shit .......... if (group == RAID_GROUPLESS) { if (rleader) { GetXTargetAutoMgr()->merge(*c->GetXTargetAutoMgr()); @@ -147,54 +165,115 @@ void Raid::AddMember(Client *c, uint32 group, bool rleader, bool groupleader, bo } } - Raid *raid_update = nullptr; - raid_update = c->GetRaid(); + auto* raid_update = c->GetRaid(); if (raid_update) { raid_update->SendHPManaEndPacketsTo(c); raid_update->SendHPManaEndPacketsFrom(c); } auto pack = new ServerPacket(ServerOP_RaidAdd, sizeof(ServerRaidGeneralAction_Struct)); - ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; - rga->rid = GetID(); - strn0cpy(rga->playername, c->GetName(), 64); - rga->zoneid = zone->GetZoneID(); + auto* rga = (ServerRaidGeneralAction_Struct*) pack->pBuffer; + strn0cpy(rga->playername, c->GetName(), sizeof(rga->playername)); + rga->rid = GetID(); + rga->zoneid = zone->GetZoneID(); rga->instance_id = zone->GetInstanceID(); worldserver.SendPacket(pack); safe_delete(pack); } + + +void Raid::AddBot(Bot* b, uint32 group, bool rleader, bool groupleader, bool looter) { + if (!b) { + return; + } + + const auto query = fmt::format( + "REPLACE INTO raid_members SET raidid = {}, " + "charid = 0, bot_id = {}, groupid = {}, _class = {}, level = {}, name = '{}', " + "isgroupleader = {}, israidleader = {}, islooter = {}", + GetID(), + b->GetBotID(), + group, + b->GetClass(), + b->GetLevel(), + b->GetName(), + groupleader, + rleader, + looter + ); + + auto results = database.QueryDatabase(query); + + LearnMembers(); + VerifyRaid(); + + if (group < MAX_RAID_GROUPS) { + GroupUpdate(group); + } else { // get raid AAs, GroupUpdate will handle it otherwise + SendGroupLeadershipAA(b->GetOwner()->CastToClient(), RAID_GROUPLESS); + } + + SendRaidAddAll(b->GetName()); + + b->SetRaidGrouped(true); + b->p_raid_instance = this; + + + auto pack = new ServerPacket(ServerOP_RaidAdd, sizeof(ServerRaidGeneralAction_Struct)); + auto* rga = (ServerRaidGeneralAction_Struct*) pack->pBuffer; + strn0cpy(rga->playername, b->GetName(), sizeof(rga->playername)); + rga->rid = GetID(); + rga->zoneid = zone->GetZoneID(); + rga->instance_id = zone->GetInstanceID(); + worldserver.SendPacket(pack); + safe_delete(pack); +} + + void Raid::RemoveMember(const char *characterName) { std::string query = StringFormat("DELETE FROM raid_members where name='%s'", characterName); auto results = database.QueryDatabase(query); - Client *client = entity_list.GetClientByName(characterName); + auto* b = entity_list.GetBotByBotName(characterName); + auto* c = entity_list.GetClientByName(characterName); + + if (RuleB(Bots, Enabled) && b) { + b = entity_list.GetBotByBotName(characterName); + b->SetFollowID(b->GetOwner()->CastToClient()->GetID()); + b->SetTarget(nullptr); + b->SetRaidGrouped(false); + } + disbandCheck = true; SendRaidRemoveAll(characterName); - SendRaidDisband(client); + SendRaidDisband(c); LearnMembers(); VerifyRaid(); - if(client) { - client->SetRaidGrouped(false); - client->LeaveRaidXTargets(this); - client->p_raid_instance = nullptr; + if (c) { + c->SetRaidGrouped(false); + c->LeaveRaidXTargets(this); + c->p_raid_instance = nullptr; } auto pack = new ServerPacket(ServerOP_RaidRemove, sizeof(ServerRaidGeneralAction_Struct)); - ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; - rga->rid = GetID(); + auto* rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; + rga->rid = GetID(); rga->instance_id = zone->GetInstanceID(); - strn0cpy(rga->playername, characterName, 64); - rga->zoneid = zone->GetZoneID(); + rga->zoneid = zone->GetZoneID(); + strn0cpy(rga->playername, characterName, sizeof(rga->playername)); worldserver.SendPacket(pack); safe_delete(pack); } void Raid::DisbandRaid() { - std::string query = StringFormat("DELETE FROM raid_members WHERE raidid = %lu", (unsigned long)GetID()); + const auto query = fmt::format( + "DELETE FROM raid_members WHERE raidid = {}", + GetID() + ); auto results = database.QueryDatabase(query); LearnMembers(); @@ -202,11 +281,11 @@ void Raid::DisbandRaid() SendRaidDisbandAll(); auto pack = new ServerPacket(ServerOP_RaidDisband, sizeof(ServerRaidGeneralAction_Struct)); - ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; - rga->rid = GetID(); - strn0cpy(rga->playername, " ", 64); - rga->zoneid = zone->GetZoneID(); + auto* rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; + rga->rid = GetID(); + rga->zoneid = zone->GetZoneID(); rga->instance_id = zone->GetInstanceID(); + strn0cpy(rga->playername, " ", sizeof(rga->playername)); worldserver.SendPacket(pack); safe_delete(pack); @@ -215,19 +294,23 @@ void Raid::DisbandRaid() void Raid::MoveMember(const char *name, uint32 newGroup) { - std::string query = StringFormat("UPDATE raid_members SET groupid = %lu WHERE name = '%s'", - (unsigned long)newGroup, name); - auto results = database.QueryDatabase(query); + + const auto query = fmt::format( + "UPDATE raid_members SET groupid = {} WHERE name = '{}'", + newGroup, + name + ); + auto results = database.QueryDatabase(query); LearnMembers(); VerifyRaid(); SendRaidMoveAll(name); - + auto pack = new ServerPacket(ServerOP_RaidChangeGroup, sizeof(ServerRaidGeneralAction_Struct)); - ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; - rga->rid = GetID(); - strn0cpy(rga->playername, name, 64); - rga->zoneid = zone->GetZoneID(); + auto* rga = (ServerRaidGeneralAction_Struct*) pack->pBuffer; + strn0cpy(rga->playername, name, sizeof(rga->playername)); + rga->rid = GetID(); + rga->zoneid = zone->GetZoneID(); rga->instance_id = zone->GetInstanceID(); worldserver.SendPacket(pack); safe_delete(pack); @@ -235,18 +318,21 @@ void Raid::MoveMember(const char *name, uint32 newGroup) void Raid::SetGroupLeader(const char *who, bool glFlag) { - std::string query = StringFormat("UPDATE raid_members SET isgroupleader = %lu WHERE name = '%s'", - (unsigned long)glFlag, who); - auto results = database.QueryDatabase(query); + const auto query = fmt::format( + "UPDATE raid_members SET isgroupleader = {} WHERE name = '{}'", + glFlag, + who + ); + auto results = database.QueryDatabase(query); LearnMembers(); VerifyRaid(); auto pack = new ServerPacket(ServerOP_RaidGroupLeader, sizeof(ServerRaidGeneralAction_Struct)); - ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; - rga->rid = GetID(); - strn0cpy(rga->playername, who, 64); - rga->zoneid = zone->GetZoneID(); + auto* rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; + strn0cpy(rga->playername, who, sizeof(rga->playername)); + rga->rid = GetID(); + rga->zoneid = zone->GetZoneID(); rga->instance_id = zone->GetInstanceID(); worldserver.SendPacket(pack); safe_delete(pack); @@ -405,13 +491,13 @@ uint32 Raid::GetFreeGroup() return x; } //if we get to here then there were no free groups so we added the group as free floating members. - return 0xFFFFFFFF; + return RAID_GROUPLESS; } uint8 Raid::GroupCount(uint32 gid) { uint8 count = 0; - if(gid < 12) + if(gid < MAX_RAID_GROUPS) { for(int x = 0; x < MAX_RAID_MEMBERS; x++) { @@ -452,7 +538,7 @@ uint32 Raid::GetGroup(const char *name) if(strcmp(members[x].membername, name) == 0) return members[x].GroupNumber; } - return 0xFFFFFFFF; + return RAID_GROUPLESS; } uint32 Raid::GetGroup(Client *c) @@ -462,7 +548,7 @@ uint32 Raid::GetGroup(Client *c) if(members[x].member == c) return members[x].GroupNumber; } - return 0xFFFFFFFF; + return RAID_GROUPLESS; } void Raid::RaidSay(const char *msg, Client *c, uint8 language, uint8 lang_skill) @@ -473,7 +559,7 @@ void Raid::RaidSay(const char *msg, Client *c, uint8 language, uint8 lang_skill) auto pack = new ServerPacket(ServerOP_RaidSay, sizeof(ServerRaidMessage_Struct) + strlen(msg) + 1); ServerRaidMessage_Struct *rga = (ServerRaidMessage_Struct*)pack->pBuffer; rga->rid = GetID(); - rga->gid = 0xFFFFFFFF; + rga->gid = RAID_GROUPLESS; rga->language = language; rga->lang_skill = lang_skill; strn0cpy(rga->from, c->GetName(), 64); @@ -701,8 +787,8 @@ void Raid::BalanceMana(int32 penalty, uint32 gid, float range, Mob* caster, int3 int gi = 0; for(; gi < MAX_RAID_MEMBERS; gi++) { - if(members[gi].member){ - if(members[gi].GroupNumber == gid) + if (members[gi].member && !members[gi].IsBot) { + if (members[gi].GroupNumber == gid) { if (members[gi].member->GetMaxMana() > 0) { distance = DistanceSquared(caster->GetPosition(), members[gi].member->GetPosition()); @@ -725,17 +811,17 @@ void Raid::BalanceMana(int32 penalty, uint32 gid, float range, Mob* caster, int3 for(gi = 0; gi < MAX_RAID_MEMBERS; gi++) { - if(members[gi].member){ - if(members[gi].GroupNumber == gid) + if (members[gi].member) { + if (members[gi].GroupNumber == gid) { distance = DistanceSquared(caster->GetPosition(), members[gi].member->GetPosition()); - if(distance <= range2){ - if((members[gi].member->GetMaxMana() - manataken) < 1){ + if (distance <= range2){ + if ((members[gi].member->GetMaxMana() - manataken) < 1) { members[gi].member->SetMana(1); if (members[gi].member->IsClient()) members[gi].member->CastToClient()->SendManaUpdate(); } - else{ + else { members[gi].member->SetMana(members[gi].member->GetMaxMana() - manataken); if (members[gi].member->IsClient()) members[gi].member->CastToClient()->SendManaUpdate(); @@ -766,7 +852,7 @@ void Raid::SplitMoney(uint32 gid, uint32 copper, uint32 silver, uint32 gold, uin uint8 member_count = 0; for (uint32 i = 0; i < MAX_RAID_MEMBERS; i++) { - if (members[i].member && members[i].GroupNumber == gid) { + if (members[i].member && members[i].GroupNumber == gid && members[i].member->IsClient()) { member_count++; } } @@ -805,7 +891,7 @@ void Raid::SplitMoney(uint32 gid, uint32 copper, uint32 silver, uint32 gold, uin auto platinum_split = platinum / member_count; for (uint32 i = 0; i < MAX_RAID_MEMBERS; i++) { - if (members[i].member && members[i].GroupNumber == gid) { // If Group Member is Client + if (members[i].member && members[i].GroupNumber == gid && members[i].member->IsClient()) { // If Group Member is Client members[i].member->AddMoneyToPP( copper_split, silver_split, @@ -814,6 +900,18 @@ void Raid::SplitMoney(uint32 gid, uint32 copper, uint32 silver, uint32 gold, uin true ); + if (player_event_logs.IsEventEnabled(PlayerEvent::SPLIT_MONEY)) { + auto e = PlayerEvent::SplitMoneyEvent{ + .copper = copper_split, + .silver = silver_split, + .gold = gold_split, + .platinum = platinum_split, + .player_money_balance = members[i].member->GetCarriedMoney(), + }; + + RecordPlayerEventLogWithClient(members[i].member, PlayerEvent::SPLIT_MONEY, e); + } + members[i].member->MessageString( Chat::MoneySplit, YOU_RECEIVE_AS_SPLIT, @@ -830,26 +928,21 @@ void Raid::SplitMoney(uint32 gid, uint32 copper, uint32 silver, uint32 gold, uin void Raid::TeleportGroup(Mob* sender, uint32 zoneID, uint16 instance_id, float x, float y, float z, float heading, uint32 gid) { - for(int i = 0; i < MAX_RAID_MEMBERS; i++) + for (const auto& m : members) { - if(members[i].member) - { - if(members[i].GroupNumber == gid) - { - members[i].member->MovePC(zoneID, instance_id, x, y, z, heading, 0, ZoneSolicited); - } + if (m.member && m.GroupNumber == gid && m.member->IsClient()) { + m.member->MovePC(zoneID, instance_id, x, y, z, heading, 0, ZoneSolicited); } - } } void Raid::TeleportRaid(Mob* sender, uint32 zoneID, uint16 instance_id, float x, float y, float z, float heading) { - for(int i = 0; i < MAX_RAID_MEMBERS; i++) + for (const auto& m : members) { - if(members[i].member) + if (m.member && m.member->IsClient()) { - members[i].member->MovePC(zoneID, instance_id, x, y, z, heading, 0, ZoneSolicited); + m.member->MovePC(zoneID, instance_id, x, y, z, heading, 0, ZoneSolicited); } } } @@ -979,19 +1072,21 @@ void Raid::SendRaidAdd(const char *who, Client *to) if(!to) return; - for(int x = 0; x < MAX_RAID_MEMBERS; x++) + std::vector rm = GetMembers(); + + for (const auto& m : rm) { - if(strcmp(members[x].membername, who) == 0) + if (strcmp(m.membername, who) == 0) { auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidAddMember_Struct)); - RaidAddMember_Struct *ram = (RaidAddMember_Struct*)outapp->pBuffer; + RaidAddMember_Struct* ram = (RaidAddMember_Struct*)outapp->pBuffer; ram->raidGen.action = raidAdd; - ram->raidGen.parameter = members[x].GroupNumber; - strn0cpy(ram->raidGen.leader_name, members[x].membername, 64); - strn0cpy(ram->raidGen.player_name, members[x].membername, 64); - ram->_class = members[x]._class; - ram->level = members[x].level; - ram->isGroupLeader = members[x].IsGroupLeader; + ram->raidGen.parameter = m.GroupNumber; + strn0cpy(ram->raidGen.leader_name, m.membername, 64); + strn0cpy(ram->raidGen.player_name, m.membername, 64); + ram->_class = m._class; + ram->level = m.level; + ram->isGroupLeader = m.IsGroupLeader; to->QueuePacket(outapp); safe_delete(outapp); return; @@ -1001,19 +1096,21 @@ void Raid::SendRaidAdd(const char *who, Client *to) void Raid::SendRaidAddAll(const char *who) { - for(int x = 0; x < MAX_RAID_MEMBERS; x++) - { - if(strcmp(members[x].membername, who) == 0) + std::vector rm = GetMembers(); + + for (const auto& m : rm) { + if (strcmp(m.membername, who) == 0) { auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidAddMember_Struct)); - RaidAddMember_Struct *ram = (RaidAddMember_Struct*)outapp->pBuffer; + RaidAddMember_Struct* ram = (RaidAddMember_Struct*)outapp->pBuffer; ram->raidGen.action = raidAdd; - ram->raidGen.parameter = members[x].GroupNumber; - strcpy(ram->raidGen.leader_name, members[x].membername); - strcpy(ram->raidGen.player_name, members[x].membername); - ram->_class = members[x]._class; - ram->level = members[x].level; - ram->isGroupLeader = members[x].IsGroupLeader; + ram->raidGen.parameter = m.GroupNumber; + strcpy(ram->raidGen.leader_name, m.membername); + strcpy(ram->raidGen.player_name, m.membername); + ram->isGroupLeader = m.IsGroupLeader; + ram->_class = m._class; + ram->level = m.level; + QueuePacket(outapp); safe_delete(outapp); return; @@ -1116,12 +1213,13 @@ void Raid::SendRaidMoveAll(const char* who) SendRaidRemoveAll(who); if(c) SendRaidCreate(c); - SendMakeLeaderPacket(leadername); - SendRaidAddAll(who); if(c){ SendBulkRaid(c); if(IsLocked()) { SendRaidLockTo(c); } } + SendRaidAddAll(who); + SendMakeLeaderPacket(leadername); + } void Raid::SendBulkRaid(Client *to) @@ -1131,7 +1229,7 @@ void Raid::SendBulkRaid(Client *to) for(int x = 0; x < MAX_RAID_MEMBERS; x++) { - if(strlen(members[x].membername) > 0 && (strcmp(members[x].membername, to->GetName()) != 0)) //don't send ourself + if (strlen(members[x].membername) > 0 && (strcmp(members[x].membername, to->GetName()) != 0)) //don't send ourself { SendRaidAdd(members[x].membername, to); } @@ -1140,9 +1238,9 @@ void Raid::SendBulkRaid(Client *to) void Raid::QueuePacket(const EQApplicationPacket *app, bool ack_req) { - for(int x = 0; x < MAX_RAID_MEMBERS; x++) + for (int x = 0; x < MAX_RAID_MEMBERS; x++) { - if(members[x].member) + if (members[x].member && members[x].member->IsClient()) { members[x].member->QueuePacket(app, ack_req); } @@ -1151,6 +1249,11 @@ void Raid::QueuePacket(const EQApplicationPacket *app, bool ack_req) void Raid::SendMakeLeaderPacket(const char *who) //30 { + + if (RuleB(Bots, Enabled) && entity_list.GetBotByBotName(who) && members[GetPlayerIndex(who)].IsBot) { + return; + } + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidLeadershipUpdate_Struct)); RaidLeadershipUpdate_Struct *rg = (RaidLeadershipUpdate_Struct*)outapp->pBuffer; rg->action = raidMakeLeader; @@ -1163,8 +1266,13 @@ void Raid::SendMakeLeaderPacket(const char *who) //30 void Raid::SendMakeLeaderPacketTo(const char *who, Client *to) { - if(!to) + if (!to) { return; + } + + if (RuleB(Bots, Enabled) && members[GetPlayerIndex(who)].IsBot) { + return; + } auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidLeadershipUpdate_Struct)); RaidLeadershipUpdate_Struct *rg = (RaidLeadershipUpdate_Struct*)outapp->pBuffer; @@ -1193,8 +1301,13 @@ void Raid::SendMakeGroupLeaderPacketTo(const char *who, Client *to) void Raid::SendGroupUpdate(Client *to) { - if(!to) + if (!to) { return; + } + + if (RuleB(Bots, Enabled) && members[GetPlayerIndex(to)].IsBot) { + return; + } auto outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupUpdate2_Struct)); GroupUpdate2_Struct* gu = (GroupUpdate2_Struct*)outapp->pBuffer; @@ -1236,13 +1349,14 @@ void Raid::SendGroupUpdate(Client *to) void Raid::GroupUpdate(uint32 gid, bool initial) { - if(gid > 11) //ungrouped member doesn't need grouping. + if(gid > 11) {//ungrouped member doesn't need grouping. return; - for(int x = 0; x < MAX_RAID_MEMBERS; x++) + } + for (int x = 0; x < MAX_RAID_MEMBERS; x++) { if(strlen(members[x].membername) > 0){ if(members[x].GroupNumber == gid){ - if(members[x].member) { + if (members[x].member) { SendGroupUpdate(members[x].member); SendGroupLeadershipAA(members[x].member, gid); } @@ -1349,6 +1463,10 @@ void Raid::SendRaidMOTD(Client *c) if (!c || motd.empty()) return; + if (members[GetPlayerIndex(c)].IsBot) { + return; + } + size_t size = motd.size() + 1; auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidMOTD_Struct) + size); RaidMOTD_Struct *rmotd = (RaidMOTD_Struct *)outapp->pBuffer; @@ -1384,6 +1502,10 @@ void Raid::SendRaidMOTDToWorld() void Raid::SendGroupLeadershipAA(Client *c, uint32 gid) { + if (RuleB(Bots, Enabled) && members[GetPlayerIndex(c)].IsBot) { + return; + } + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidLeadershipUpdate_Struct)); RaidLeadershipUpdate_Struct *rlaa = (RaidLeadershipUpdate_Struct *)outapp->pBuffer; rlaa->action = raidSetLeaderAbilities; @@ -1398,18 +1520,23 @@ void Raid::SendGroupLeadershipAA(Client *c, uint32 gid) void Raid::SendGroupLeadershipAA(uint32 gid) { - for (uint32 i = 0; i < MAX_RAID_MEMBERS; i++) - if (members[i].member && members[i].GroupNumber == gid) - SendGroupLeadershipAA(members[i].member, gid); + for (const auto& m : members) { + if (m.member && m.GroupNumber == gid && !m.IsBot) { + SendGroupLeadershipAA(m.member, gid); + } + } } void Raid::SendAllRaidLeadershipAA() { - for (uint32 i = 0; i < MAX_RAID_MEMBERS; i++) - if (members[i].member) - SendGroupLeadershipAA(members[i].member, members[i].GroupNumber); + for (const auto& m : members) { + if (m.member && !m.IsBot) { + SendGroupLeadershipAA(m.member, m.GroupNumber); + } + } } + void Raid::LockRaid(bool lockFlag) { std::string query = StringFormat("UPDATE raid_details SET locked = %d WHERE raidid = %lu", @@ -1458,8 +1585,8 @@ void Raid::GetRaidDetails() auto row = results.begin(); - locked = atoi(row[0]); - LootType = atoi(row[1]); + locked = Strings::ToInt(row[0]); + LootType = Strings::ToInt(row[1]); motd = std::string(row[2]); } @@ -1473,70 +1600,84 @@ void Raid::SaveRaidMOTD() bool Raid::LearnMembers() { - memset(members, 0, (sizeof(RaidMember)*MAX_RAID_MEMBERS)); + memset(members, 0, (sizeof(RaidMember) * MAX_RAID_MEMBERS)); - std::string query = StringFormat("SELECT name, groupid, _class, level, " - "isgroupleader, israidleader, islooter " - "FROM raid_members WHERE raidid = %lu", - (unsigned long)GetID()); - auto results = database.QueryDatabase(query); - if (!results.Success()) - return false; + const auto query = fmt::format( + "SELECT name, groupid, _class, level, " + "isgroupleader, israidleader, islooter, bot_id " + "FROM raid_members WHERE raidid = {} ORDER BY groupid", + GetID() + ); - if(results.RowCount() == 0) { - LogError("Error getting raid members for raid [{}]: [{}]", (unsigned long)GetID(), results.ErrorMessage().c_str()); - disbandCheck = true; - return false; - } + auto results = database.QueryDatabase(query); + if (!results.Success()) { + return false; + } - int index = 0; - for(auto row = results.begin(); row != results.end(); ++row) { - if(!row[0]) - continue; + if (!results.RowCount()) { + LogError("Error getting raid members for raid [{}]: [{}]", GetID(), results.ErrorMessage()); + disbandCheck = true; + return false; + } - members[index].member = nullptr; - strn0cpy(members[index].membername, row[0], 64); - int groupNum = atoi(row[1]); - if(groupNum > 11) - members[index].GroupNumber = 0xFFFFFFFF; - else - members[index].GroupNumber = groupNum; + int index = 0; + for (auto row: results) { + if (!row[0]) { + continue; + } - members[index]._class = atoi(row[2]); - members[index].level = atoi(row[3]); - members[index].IsGroupLeader = atoi(row[4]); - members[index].IsRaidLeader = atoi(row[5]); - members[index].IsLooter = atoi(row[6]); - ++index; - } + members[index].member = nullptr; + strn0cpy(members[index].membername, row[0], sizeof(members[index].membername)); + uint32 group_id = Strings::ToUnsignedInt(row[1]); + if (group_id > 11) { + members[index].GroupNumber = RAID_GROUPLESS; + } else { + members[index].GroupNumber = group_id; + } + + members[index]._class = Strings::ToUnsignedInt(row[2]); + members[index].level = Strings::ToUnsignedInt(row[3]); + members[index].IsGroupLeader = Strings::ToBool(row[4]); + members[index].IsRaidLeader = Strings::ToBool(row[5]); + members[index].IsLooter = Strings::ToBool(row[6]); + members[index].IsBot = Strings::ToBool(row[7]) > 0; + ++index; + } + return true; } void Raid::VerifyRaid() { - for(int x = 0; x < MAX_RAID_MEMBERS; x++) - { - if(strlen(members[x].membername) == 0){ - members[x].member = nullptr; - } - else{ - Client *c = entity_list.GetClientByName(members[x].membername); - if(c){ - members[x].member = c; - } - else{ - members[x].member = nullptr; + for (auto& m : members) { + if(strlen(m.membername) == 0){ + m.member = nullptr; + } else { + auto* c = entity_list.GetClientByName(m.membername); + auto* b = entity_list.GetBotByBotName(m.membername); + + if (c) { + m.member = c; + m.IsBot = false; + } else if(RuleB(Bots, Enabled) && b){ + //Raid requires client* we are forcing it here to be a BOT. Care is needed here as any client function that + //does not exist within the Bot Class will likely corrupt memory for the member object. Good practice to test the IsBot + //attribute before calling a client function or casting to client. + b = entity_list.GetBotByBotName(m.membername); + m.member = b->CastToClient(); + m.IsBot = true; //Used to identify those members who are Bots + } else { + m.member = nullptr; + m.IsBot = false; } } - if(members[x].IsRaidLeader){ - if(strlen(members[x].membername) > 0){ - SetLeader(members[x].member); - strn0cpy(leadername, members[x].membername, 64); - } - else - { - //should never happen, but maybe it is? + + if (m.IsRaidLeader) { + if (strlen(m.membername) > 0){ + SetLeader(m.member); + strn0cpy(leadername, m.membername, sizeof(leadername)); + } else { SetLeader(nullptr); } } @@ -1564,7 +1705,7 @@ void Raid::MemberZoned(Client *c) } } - if (gid < 12 && group_mentor[gid].mentoree == c) + if (gid < MAX_RAID_GROUPS && group_mentor[gid].mentoree == c) group_mentor[gid].mentoree = nullptr; } @@ -1579,7 +1720,7 @@ void Raid::SendHPManaEndPacketsTo(Client *client) EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); for(int x = 0; x < MAX_RAID_MEMBERS; x++) { - if(members[x].member) { + if(members[x].member && !members[x].IsBot) { if((members[x].member != client) && (members[x].GroupNumber == group_id)) { members[x].member->CreateHPPacket(&hp_packet); @@ -1621,7 +1762,7 @@ void Raid::SendHPManaEndPacketsFrom(Mob *mob) mob->CreateHPPacket(&hpapp); for(int x = 0; x < MAX_RAID_MEMBERS; x++) { - if(members[x].member) { + if(members[x].member && !members[x].IsBot) { if(!mob->IsClient() || ((members[x].member != mob->CastToClient()) && (members[x].GroupNumber == group_id))) { members[x].member->QueuePacket(&hpapp, false); if (members[x].member->ClientVersion() >= EQ::versions::ClientVersion::SoD) { @@ -1654,7 +1795,7 @@ void Raid::SendManaPacketFrom(Mob *mob) EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); for (int x = 0; x < MAX_RAID_MEMBERS; x++) { - if (members[x].member) { + if (members[x].member && !members[x].IsBot) { if (!mob->IsClient() || ((members[x].member != mob->CastToClient()) && (members[x].GroupNumber == group_id))) { if (members[x].member->ClientVersion() >= EQ::versions::ClientVersion::SoD) { outapp.SetOpcode(OP_MobManaUpdate); @@ -1681,7 +1822,7 @@ void Raid::SendEndurancePacketFrom(Mob *mob) EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); for (int x = 0; x < MAX_RAID_MEMBERS; x++) { - if (members[x].member) { + if (members[x].member && !members[x].IsBot) { if (!mob->IsClient() || ((members[x].member != mob->CastToClient()) && (members[x].GroupNumber == group_id))) { if (members[x].member->ClientVersion() >= EQ::versions::ClientVersion::SoD) { outapp.SetOpcode(OP_MobEnduranceUpdate); @@ -1721,7 +1862,7 @@ const char *Raid::GetClientNameByIndex(uint8 index) void Raid::RaidMessageString(Mob* sender, uint32 type, uint32 string_id, const char* message,const char* message2,const char* message3,const char* message4,const char* message5,const char* message6,const char* message7,const char* message8,const char* message9, uint32 distance) { uint32 i; for (i = 0; i < MAX_RAID_MEMBERS; i++) { - if(members[i].member) { + if(members[i].member && members[i].member->IsClient()) { if(members[i].member != sender) members[i].member->MessageString(type, string_id, message, message2, message3, message4, message5, message6, message7, message8, message9, distance); } @@ -1788,9 +1929,14 @@ void Raid::CheckGroupMentor(uint32 group_id, Client *c) void Raid::SetDirtyAutoHaters() { for (int i = 0; i < MAX_RAID_MEMBERS; ++i) - if (members[i].member) + if (members[i].member && members[i].IsBot) + { + members[i].member->CastToBot()->SetDirtyAutoHaters(); + } + else if (members[i].member && !members[i].IsBot) + { members[i].member->SetDirtyAutoHaters(); - + } } void Raid::QueueClients(Mob *sender, const EQApplicationPacket *app, bool ack_required /*= true*/, bool ignore_sender /*= true*/, float distance /*= 0*/, bool group_only /*= true*/) { @@ -1799,22 +1945,25 @@ void Raid::QueueClients(Mob *sender, const EQApplicationPacket *app, bool ack_re uint32 group_id = GetGroup(sender->CastToClient()); /* If this is a group only packet and we're not in a group -- return */ - if (group_id == 0xFFFFFFFF && group_only) + if (group_id == RAID_GROUPLESS && group_only) return; for (uint32 i = 0; i < MAX_RAID_MEMBERS; i++) { - if (!members[i].member) + if (!members[i].member) { continue; - - if (!members[i].member->IsClient()) + } + if (members[i].IsBot) { continue; - - if (ignore_sender && members[i].member == sender) + } + if (!members[i].member->IsClient()) { continue; - - if (group_only && members[i].GroupNumber != group_id) + } + if (ignore_sender && members[i].member == sender) { continue; - + } + if (group_only && members[i].GroupNumber != group_id) { + continue; + } /* If we don't have a distance requirement - send to all members */ if (distance == 0) { members[i].member->CastToClient()->QueuePacket(app, ack_required); @@ -1871,3 +2020,84 @@ bool Raid::DoesAnyMemberHaveExpeditionLockout( return Expedition::HasLockoutByCharacterName(raid_member.membername, expedition_name, event_name); }); } + +Mob* Raid::GetRaidMainAssistOneByName(const char* name) +{ + Raid* raid = entity_list.GetRaidByBotName(name); + std::vector raid_members = raid->GetMembers(); + + for (RaidMember iter : raid_members) + { + if (iter.IsRaidMainAssistOne) { + return iter.member->CastToMob(); + } + } + return nullptr; +} +bool Raid::IsEngaged() { + + std::vector rm = GetMembers(); + for (const auto& m : rm) { + if (m.member && !m.IsBot && (m.member->IsEngaged() || m.member->GetAggroCount() > 0)) { + return 1; + } + } + return 0; +} +void Raid::RaidGroupSay(const char* msg, const char* from, uint8 language, uint8 lang_skill) +{ + if (!from) + return; + + uint32 groupToUse = GetGroup(from); + + if (groupToUse > 11) + return; + + auto pack = new ServerPacket(ServerOP_RaidGroupSay, sizeof(ServerRaidMessage_Struct) + strlen(msg) + 1); + ServerRaidMessage_Struct* rga = (ServerRaidMessage_Struct*)pack->pBuffer; + rga->rid = GetID(); + rga->gid = groupToUse; + rga->language = language; + rga->lang_skill = lang_skill; + strn0cpy(rga->from, from, 64); + + strcpy(rga->message, msg); // this is safe because we are allocating enough space for the entire msg above + + worldserver.SendPacket(pack); + safe_delete(pack); +} +void Raid::RaidSay(const char* msg, const char* from, uint8 language, uint8 lang_skill) +{ + if (!from) + return; + + auto pack = new ServerPacket(ServerOP_RaidSay, sizeof(ServerRaidMessage_Struct) + strlen(msg) + 1); + ServerRaidMessage_Struct* rga = (ServerRaidMessage_Struct*)pack->pBuffer; + rga->rid = GetID(); + rga->gid = RAID_GROUPLESS; + rga->language = language; + rga->lang_skill = lang_skill; + strn0cpy(rga->from, from, 64); + + strcpy(rga->message, msg); + + worldserver.SendPacket(pack); + safe_delete(pack); +} + +void Raid::SetNewRaidLeader(uint32 i) +{ + if (members[i].IsRaidLeader) { + for (int x = 0; x < MAX_RAID_MEMBERS; x++) { + if (!members[x].IsBot) { + if (strlen(members[x].membername) > 0 && strcmp(members[x].membername, members[i].membername) != 0) { + SetRaidLeader(members[i].membername, members[x].membername); + UpdateRaidAAs(); + SendAllRaidLeadershipAA(); + break; + } + } + } + } +} \ No newline at end of file diff --git a/zone/raids.h b/zone/raids.h index 885dd2fa1..52bbc3b3a 100644 --- a/zone/raids.h +++ b/zone/raids.h @@ -88,6 +88,8 @@ struct RaidMember{ bool IsGroupLeader; bool IsRaidLeader; bool IsLooter; + bool IsBot = false; + bool IsRaidMainAssistOne = false; }; struct GroupMentor { @@ -113,6 +115,11 @@ public: bool IsRaid() { return true; } void AddMember(Client *c, uint32 group = 0xFFFFFFFF, bool rleader=false, bool groupleader=false, bool looter=false); + void AddBot(Bot* b, uint32 group = 0xFFFFFFFF, bool rleader=false, bool groupleader=false, bool looter=false); + void RaidGroupSay(const char* msg, const char* from, uint8 language, uint8 lang_skill); + void RaidSay(const char* msg, const char* from, uint8 language, uint8 lang_skill); + bool IsEngaged(); + Mob* GetRaidMainAssistOneByName(const char* name); void RemoveMember(const char *c); void DisbandRaid(); void MoveMember(const char *name, uint32 newGroup); @@ -124,6 +131,7 @@ public: bool IsRaidMember(const char* name); bool IsRaidMember(Client *c); void UpdateLevel(const char *name, int newLevel); + void SetNewRaidLeader(uint32 i); uint32 GetFreeGroup(); uint8 GroupCount(uint32 gid); @@ -244,6 +252,10 @@ public: bool DoesAnyMemberHaveExpeditionLockout(const std::string& expedition_name, const std::string& event_name, int max_check_count = 0); std::vector GetMembers() const; + std::vector GetRaidGroupMembers(uint32 gid); + std::vector GetRaidGroupBotMembers(uint32 gid); + std::vector GetRaidBotMembers(uint32 owner = 0); + void HandleBotGroupDisband(uint32 owner, uint32 gid = RAID_GROUPLESS); RaidMember members[MAX_RAID_MEMBERS]; char leadername[64]; diff --git a/zone/skills.h b/zone/skills.h deleted file mode 100644 index 8c994a378..000000000 --- a/zone/skills.h +++ /dev/null @@ -1,101 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#ifndef SKILLS_H -#define SKILLS_H - -#define HIGHEST_SKILL_UNUSED 74 - - -// Correct Skill Numbers as of 4-14-2002 -#define _1H_BLUNT_UNUSED 0 -#define _1H_SLASHING_UNUSED 1 -#define _2H_BLUNT_UNUSED 2 -#define _2H_SLASHING_UNUSED 3 -#define ABJURE_UNUSED 4 -#define ALTERATION_UNUSED 5 -#define APPLY_POISON_UNUSED 6 -#define ARCHERY_UNUSED 7 -#define BACKSTAB_UNUSED 8 -#define BIND_WOUND_UNUSED 9 -#define BASH_UNUSED 10 -#define BLOCKSKILL_UNUSED 11 -#define BRASS_INSTRUMENTS_UNUSED 12 -#define CHANNELING_UNUSED 13 -#define CONJURATION_UNUSED 14 -#define DEFENSE_UNUSED 15 -#define DISARM_UNUSED 16 -#define DISARM_TRAPS_UNUSED 17 -#define DIVINATION_UNUSED 18 -#define DODGE_UNUSED 19 -#define DOUBLE_ATTACK_UNUSED 20 -#define DRAGON_PUNCH_UNUSED 21 -#define DUAL_WIELD_UNUSED 22 -#define EAGLE_STRIKE_UNUSED 23 -#define EVOCATION_UNUSED 24 -#define FEIGN_DEATH_UNUSED 25 -#define FLYING_KICK_UNUSED 26 -#define FORAGE_UNUSED 27 -#define HAND_TO_HAND_UNUSED 28 -#define HIDE_UNUSED 29 -#define KICK_UNUSED 30 -#define MEDITATE_UNUSED 31 -#define MEND_UNUSED 32 -#define OFFENSE_UNUSED 33 -#define PARRY_UNUSED 34 -#define PICK_LOCK_UNUSED 35 -#define PIERCING_UNUSED 36 -#define RIPOSTE_UNUSED 37 -#define ROUND_KICK_UNUSED 38 -#define SAFE_FALL_UNUSED 39 -#define SENSE_HEADING_UNUSED 40 -#define SINGING_UNUSED 41 -#define SNEAK_UNUSED 42 -#define SPECIALIZE_ABJURE_UNUSED 43 -#define SPECIALIZE_ALTERATION_UNUSED 44 -#define SPECIALIZE_CONJURATION_UNUSED 45 -#define SPECIALIZE_DIVINATION_UNUSED 46 -#define SPECIALIZE_EVOCATION_UNUSED 47 -#define PICK_POCKETS_UNUSED 48 -#define STRINGED_INSTRUMENTS_UNUSED 49 -#define SWIMMING_UNUSED 50 -#define THROWING_UNUSED 51 -#define TIGER_CLAW_UNUSED 52 -#define TRACKING_UNUSED 53 -#define WIND_INSTRUMENTS_UNUSED 54 -#define FISHING_UNUSED 55 -#define MAKE_POISON_UNUSED 56 -#define TINKERING_UNUSED 57 -#define RESEARCH_UNUSED 58 -#define ALCHEMY_UNUSED 59 -#define BAKING_UNUSED 60 -#define TAILORING_UNUSED 61 -#define SENSE_TRAPS_UNUSED 62 -#define BLACKSMITHING_UNUSED 63 -#define FLETCHING_UNUSED 64 -#define BREWING_UNUSED 65 -#define ALCOHOL_TOLERANCE_UNUSED 66 -#define BEGGING_UNUSED 67 -#define JEWELRY_MAKING_UNUSED 68 -#define POTTERY_UNUSED 69 -#define PERCUSSION_INSTRUMENTS_UNUSED 70 -#define INTIMIDATION_UNUSED 71 -#define BERSERKING_UNUSED 72 -#define TAUNT_UNUSED 73 -#define FRENZY_UNUSED 74 - -#endif diff --git a/zone/spawn2.cpp b/zone/spawn2.cpp index be0971953..5c98fcd9a 100644 --- a/zone/spawn2.cpp +++ b/zone/spawn2.cpp @@ -260,8 +260,6 @@ bool Spawn2::Process() { NPC *npc = new NPC(tmp, this, glm::vec4(x, y, z, heading), GravityBehavior::Water); - npc->mod_prespawn(this); - npcthis = npc; npc->AddLootTable(); if (npc->DropsGlobalLoot()) { @@ -456,16 +454,16 @@ bool ZoneDatabase::PopulateZoneSpawnListClose(uint32 zoneid, LinkedList ); auto results = QueryDatabase(spawn_query); for (auto row = results.begin(); row != results.end(); ++row) { - uint32 start_duration = atoi(row[1]) > 0 ? atoi(row[1]) : 0; - uint32 end_duration = atoi(row[2]) > 0 ? atoi(row[2]) : 0; + uint32 start_duration = Strings::ToInt(row[1]) > 0 ? Strings::ToInt(row[1]) : 0; + uint32 end_duration = Strings::ToInt(row[2]) > 0 ? Strings::ToInt(row[2]) : 0; /* Our current time was expired */ if ((start_duration + end_duration) <= tv.tv_sec) { - spawn_times[atoi(row[0])] = 0; + spawn_times[Strings::ToInt(row[0])] = 0; } /* We still have time left on this timer */ else { - spawn_times[atoi(row[0])] = ((start_duration + end_duration) - tv.tv_sec) * 1000; + spawn_times[Strings::ToInt(row[0])] = ((start_duration + end_duration) - tv.tv_sec) * 1000; } } @@ -502,14 +500,14 @@ bool ZoneDatabase::PopulateZoneSpawnListClose(uint32 zoneid, LinkedList uint32 spawn_time_left = 0; Spawn2* new_spawn = 0; - bool perl_enabled = atoi(row[12]) == 1 ? true : false; + bool perl_enabled = Strings::ToInt(row[12]) == 1 ? true : false; - if (spawn_times.count(atoi(row[0])) != 0) - spawn_time_left = spawn_times[atoi(row[0])]; + if (spawn_times.count(Strings::ToInt(row[0])) != 0) + spawn_time_left = spawn_times[Strings::ToInt(row[0])]; glm::vec4 point; - point.x = atof(row[2]); - point.y = atof(row[3]); + point.x = Strings::ToFloat(row[2]); + point.y = Strings::ToFloat(row[3]); mob_distance = DistanceNoZ(client_position, point); @@ -517,21 +515,21 @@ bool ZoneDatabase::PopulateZoneSpawnListClose(uint32 zoneid, LinkedList continue; new_spawn = new Spawn2( - atoi(row[0]), // uint32 in_spawn2_id - atoi(row[1]), // uint32 spawngroup_id - atof(row[2]), // float in_x - atof(row[3]), // float in_y - atof(row[4]), // float in_z - atof(row[5]), // float in_heading - atoi(row[6]), // uint32 respawn - atoi(row[7]), // uint32 variance + Strings::ToInt(row[0]), // uint32 in_spawn2_id + Strings::ToInt(row[1]), // uint32 spawngroup_id + Strings::ToFloat(row[2]), // float in_x + Strings::ToFloat(row[3]), // float in_y + Strings::ToFloat(row[4]), // float in_z + Strings::ToFloat(row[5]), // float in_heading + Strings::ToInt(row[6]), // uint32 respawn + Strings::ToInt(row[7]), // uint32 variance spawn_time_left, // uint32 timeleft - atoi(row[8]), // uint32 grid - (bool)atoi(row[9]), // bool path_when_zone_idle - atoi(row[10]), // uint16 in_cond_id - atoi(row[11]), // int16 in_min_value + Strings::ToInt(row[8]), // uint32 grid + (bool)Strings::ToInt(row[9]), // bool path_when_zone_idle + Strings::ToInt(row[10]), // uint16 in_cond_id + Strings::ToInt(row[11]), // int16 in_min_value perl_enabled, // bool in_enabled - (EmuAppearance)atoi(row[13]) // EmuAppearance anim + (EmuAppearance)Strings::ToInt(row[13]) // EmuAppearance anim ); spawn2_list.Insert(new_spawn); @@ -562,16 +560,16 @@ bool ZoneDatabase::PopulateZoneSpawnList(uint32 zoneid, LinkedList &spa ); auto results = database.QueryDatabase(spawn_query); for (auto row = results.begin(); row != results.end(); ++row) { - uint32 start_duration = atoi(row[1]) > 0 ? atoi(row[1]) : 0; - uint32 end_duration = atoi(row[2]) > 0 ? atoi(row[2]) : 0; + uint32 start_duration = Strings::ToInt(row[1]) > 0 ? Strings::ToInt(row[1]) : 0; + uint32 end_duration = Strings::ToInt(row[2]) > 0 ? Strings::ToInt(row[2]) : 0; /* Our current time was expired */ if ((start_duration + end_duration) <= tv.tv_sec) { - spawn_times[atoi(row[0])] = 0; + spawn_times[Strings::ToInt(row[0])] = 0; } /* We still have time left on this timer */ else { - spawn_times[atoi(row[0])] = ((start_duration + end_duration) - tv.tv_sec) * 1000; + spawn_times[Strings::ToInt(row[0])] = ((start_duration + end_duration) - tv.tv_sec) * 1000; } } @@ -610,27 +608,27 @@ bool ZoneDatabase::PopulateZoneSpawnList(uint32 zoneid, LinkedList &spa uint32 spawn_time_left = 0; Spawn2* new_spawn = 0; - bool perl_enabled = atoi(row[12]) == 1 ? true : false; + bool perl_enabled = Strings::ToInt(row[12]) == 1 ? true : false; - if (spawn_times.count(atoi(row[0])) != 0) - spawn_time_left = spawn_times[atoi(row[0])]; + if (spawn_times.count(Strings::ToInt(row[0])) != 0) + spawn_time_left = spawn_times[Strings::ToInt(row[0])]; new_spawn = new Spawn2( - atoi(row[0]), // uint32 in_spawn2_id - atoi(row[1]), // uint32 spawngroup_id - atof(row[2]), // float in_x - atof(row[3]), // float in_y - atof(row[4]), // float in_z - atof(row[5]), // float in_heading - atoi(row[6]), // uint32 respawn - atoi(row[7]), // uint32 variance + Strings::ToInt(row[0]), // uint32 in_spawn2_id + Strings::ToInt(row[1]), // uint32 spawngroup_id + Strings::ToFloat(row[2]), // float in_x + Strings::ToFloat(row[3]), // float in_y + Strings::ToFloat(row[4]), // float in_z + Strings::ToFloat(row[5]), // float in_heading + Strings::ToInt(row[6]), // uint32 respawn + Strings::ToInt(row[7]), // uint32 variance spawn_time_left, // uint32 timeleft - atoi(row[8]), // uint32 grid - (bool)atoi(row[9]), // bool path_when_zone_idle - atoi(row[10]), // uint16 in_cond_id - atoi(row[11]), // int16 in_min_value + Strings::ToInt(row[8]), // uint32 grid + (bool)Strings::ToInt(row[9]), // bool path_when_zone_idle + Strings::ToInt(row[10]), // uint16 in_cond_id + Strings::ToInt(row[11]), // int16 in_min_value perl_enabled, // bool in_enabled - (EmuAppearance)atoi(row[13]) // EmuAppearance anim + (EmuAppearance)Strings::ToInt(row[13]) // EmuAppearance anim ); spawn2_list.Insert(new_spawn); @@ -662,12 +660,12 @@ Spawn2* ZoneDatabase::LoadSpawn2(LinkedList &spawn2_list, uint32 spawn2 auto row = results.begin(); - bool perl_enabled = atoi(row[12]) == 1 ? true : false; + bool perl_enabled = Strings::ToInt(row[12]) == 1 ? true : false; - auto newSpawn = new Spawn2(atoi(row[0]), atoi(row[1]), atof(row[2]), - atof(row[3]), atof(row[4]), atof(row[5]), atoi(row[6]), atoi(row[7]), - timeleft, atoi(row[8]), (bool) atoi(row[9]), atoi(row[10]), - atoi(row[11]), perl_enabled, (EmuAppearance)atoi(row[13])); + auto newSpawn = new Spawn2(Strings::ToInt(row[0]), Strings::ToInt(row[1]), Strings::ToFloat(row[2]), + Strings::ToFloat(row[3]), Strings::ToFloat(row[4]), Strings::ToFloat(row[5]), Strings::ToInt(row[6]), Strings::ToInt(row[7]), + timeleft, Strings::ToInt(row[8]), (bool) Strings::ToInt(row[9]), Strings::ToInt(row[10]), + Strings::ToInt(row[11]), perl_enabled, (EmuAppearance)Strings::ToInt(row[13])); spawn2_list.Insert(newSpawn); @@ -961,20 +959,20 @@ bool SpawnConditionManager::LoadDBEvent(uint32 event_id, SpawnEvent &event, std: auto row = results.begin(); - event.id = atoi(row[0]); - event.condition_id = atoi(row[1]); - event.period = atoi(row[2]); + event.id = Strings::ToInt(row[0]); + event.condition_id = Strings::ToInt(row[1]); + event.period = Strings::ToInt(row[2]); - event.next.minute = atoi(row[3]); - event.next.hour = atoi(row[4]); - event.next.day = atoi(row[5]); - event.next.month = atoi(row[6]); - event.next.year = atoi(row[7]); + event.next.minute = Strings::ToInt(row[3]); + event.next.hour = Strings::ToInt(row[4]); + event.next.day = Strings::ToInt(row[5]); + event.next.month = Strings::ToInt(row[6]); + event.next.year = Strings::ToInt(row[7]); - event.enabled = atoi(row[8]) != 0; - event.action = (SpawnEvent::Action) atoi(row[9]); - event.argument = atoi(row[10]); - event.strict = atoi(row[11]) != 0; + event.enabled = Strings::ToInt(row[8]) != 0; + event.action = (SpawnEvent::Action) Strings::ToInt(row[9]); + event.argument = Strings::ToInt(row[10]); + event.strict = Strings::ToInt(row[11]) != 0; zone_name = row[12]; std::string timeAsString; @@ -1002,9 +1000,9 @@ bool SpawnConditionManager::LoadSpawnConditions(const char* zone_name, uint32 in //load spawn conditions SpawnCondition cond; - cond.condition_id = atoi(row[0]); - cond.value = atoi(row[2]); - cond.on_change = (SpawnCondition::OnChange) atoi(row[1]); + cond.condition_id = Strings::ToInt(row[0]); + cond.value = Strings::ToInt(row[2]); + cond.on_change = (SpawnCondition::OnChange) Strings::ToInt(row[1]); spawn_conditions[cond.condition_id] = cond; LogSpawns("Loaded spawn condition [{}] with value [{}] and on_change [{}]", cond.condition_id, cond.value, cond.on_change); @@ -1023,10 +1021,10 @@ bool SpawnConditionManager::LoadSpawnConditions(const char* zone_name, uint32 in } for (auto row = results.begin(); row != results.end(); ++row) { - auto iter = spawn_conditions.find(atoi(row[0])); + auto iter = spawn_conditions.find(Strings::ToInt(row[0])); if(iter != spawn_conditions.end()) - iter->second.value = atoi(row[1]); + iter->second.value = Strings::ToInt(row[1]); } //load spawn events @@ -1043,25 +1041,25 @@ bool SpawnConditionManager::LoadSpawnConditions(const char* zone_name, uint32 in for (auto row = results.begin(); row != results.end(); ++row) { SpawnEvent event; - event.id = atoi(row[0]); - event.condition_id = atoi(row[1]); - event.period = atoi(row[2]); + event.id = Strings::ToInt(row[0]); + event.condition_id = Strings::ToInt(row[1]); + event.period = Strings::ToInt(row[2]); if (event.period == 0) { LogError("Refusing to load spawn event #[{}] because it has a period of 0\n", event.id); continue; } - event.next.minute = atoi(row[3]); - event.next.hour = atoi(row[4]); - event.next.day = atoi(row[5]); - event.next.month = atoi(row[6]); - event.next.year = atoi(row[7]); + event.next.minute = Strings::ToInt(row[3]); + event.next.hour = Strings::ToInt(row[4]); + event.next.day = Strings::ToInt(row[5]); + event.next.month = Strings::ToInt(row[6]); + event.next.year = Strings::ToInt(row[7]); - event.enabled = atoi(row[8]) == 0 ? false : true; - event.action = (SpawnEvent::Action) atoi(row[9]); - event.argument = atoi(row[10]); - event.strict = atoi(row[11]) == 0 ? false : true; + event.enabled = Strings::ToInt(row[8]) == 0 ? false : true; + event.action = (SpawnEvent::Action) Strings::ToInt(row[9]); + event.argument = Strings::ToInt(row[10]); + event.strict = Strings::ToInt(row[11]) == 0 ? false : true; spawn_events.push_back(event); @@ -1418,7 +1416,7 @@ int16 SpawnConditionManager::GetCondition(const char *zone_short, uint32 instanc auto row = results.begin(); - return atoi(row[0]); + return Strings::ToInt(row[0]); } bool SpawnConditionManager::Check(uint16 condition, int16 min_value) { diff --git a/zone/spawngroup.cpp b/zone/spawngroup.cpp index f20f19977..3763caf89 100644 --- a/zone/spawngroup.cpp +++ b/zone/spawngroup.cpp @@ -145,17 +145,6 @@ SpawnGroup *SpawnGroupList::GetSpawnGroup(uint32 in_id) return (m_spawn_groups[in_id].get()); } -bool SpawnGroupList::RemoveSpawnGroup(uint32 in_id) -{ - if (m_spawn_groups.count(in_id) != 1) { - return (false); - } - - m_spawn_groups.erase(in_id); - - return (true); -} - void SpawnGroupList::ReloadSpawnGroups() { ClearSpawnGroups(); @@ -207,19 +196,19 @@ bool ZoneDatabase::LoadSpawnGroups(const char *zone_name, uint16 version, SpawnG for (auto row = results.begin(); row != results.end(); ++row) { auto new_spawn_group = std::make_unique( - atoi(row[0]), + Strings::ToInt(row[0]), row[1], - atoi(row[2]), - atof(row[3]), - atof(row[4]), - atof(row[5]), - atof(row[6]), - atof(row[7]), - atoi(row[8]), - atoi(row[9]), - atoi(row[10]), - atoi(row[11]), - atoi(row[12]) + Strings::ToInt(row[2]), + Strings::ToFloat(row[3]), + Strings::ToFloat(row[4]), + Strings::ToFloat(row[5]), + Strings::ToFloat(row[6]), + Strings::ToFloat(row[7]), + Strings::ToInt(row[8]), + Strings::ToInt(row[9]), + Strings::ToInt(row[10]), + Strings::ToInt(row[11]), + Strings::ToInt(row[12]) ); spawn_group_list->AddSpawnGroup(new_spawn_group); @@ -260,13 +249,13 @@ bool ZoneDatabase::LoadSpawnGroups(const char *zone_name, uint16 version, SpawnG for (auto row = results.begin(); row != results.end(); ++row) { auto new_spawn_entry = std::make_unique( - atoi(row[1]), - atoi(row[2]), - atoi(row[3]), - (row[4] ? atoi(row[4]) : 0) + Strings::ToInt(row[1]), + Strings::ToInt(row[2]), + Strings::ToInt(row[3]), + (row[4] ? Strings::ToInt(row[4]) : 0) ); - SpawnGroup *spawn_group = spawn_group_list->GetSpawnGroup(atoi(row[0])); + SpawnGroup *spawn_group = spawn_group_list->GetSpawnGroup(Strings::ToInt(row[0])); if (!spawn_group) { continue; @@ -327,19 +316,19 @@ bool ZoneDatabase::LoadSpawnGroupsByID(int spawn_group_id, SpawnGroupList *spawn ); auto new_spawn_group = std::make_unique( - atoi(row[0]), + Strings::ToInt(row[0]), row[1], - atoi(row[2]), - atof(row[3]), - atof(row[4]), - atof(row[5]), - atof(row[6]), - atof(row[7]), - atoi(row[8]), - atoi(row[9]), - atoi(row[10]), - atoi(row[11]), - atoi(row[12]) + Strings::ToInt(row[2]), + Strings::ToFloat(row[3]), + Strings::ToFloat(row[4]), + Strings::ToFloat(row[5]), + Strings::ToFloat(row[6]), + Strings::ToFloat(row[7]), + Strings::ToInt(row[8]), + Strings::ToInt(row[9]), + Strings::ToInt(row[10]), + Strings::ToInt(row[11]), + Strings::ToInt(row[12]) ); spawn_group_list->AddSpawnGroup(new_spawn_group); @@ -370,10 +359,10 @@ bool ZoneDatabase::LoadSpawnGroupsByID(int spawn_group_id, SpawnGroupList *spawn for (auto row = results.begin(); row != results.end(); ++row) { auto new_spawn_entry = std::make_unique( - atoi(row[1]), - atoi(row[2]), - atoi(row[3]), - (row[4] ? atoi(row[4]) : 0) + Strings::ToInt(row[1]), + Strings::ToInt(row[2]), + Strings::ToInt(row[3]), + (row[4] ? Strings::ToInt(row[4]) : 0) ); LogSpawnsDetail( @@ -385,7 +374,7 @@ bool ZoneDatabase::LoadSpawnGroupsByID(int spawn_group_id, SpawnGroupList *spawn row[4] ); - SpawnGroup *spawn_group = spawn_group_list->GetSpawnGroup(atoi(row[0])); + SpawnGroup *spawn_group = spawn_group_list->GetSpawnGroup(Strings::ToInt(row[0])); if (!spawn_group) { continue; } diff --git a/zone/spawngroup.h b/zone/spawngroup.h index 20b84b734..f5cf437df 100644 --- a/zone/spawngroup.h +++ b/zone/spawngroup.h @@ -78,7 +78,6 @@ public: void AddSpawnGroup(std::unique_ptr &new_group); SpawnGroup *GetSpawnGroup(uint32 id); - bool RemoveSpawnGroup(uint32 in_id); void ClearSpawnGroups(); void ReloadSpawnGroups(); private: diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index bec56cf1f..1243d0eb6 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -34,110 +34,169 @@ int Mob::GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target) int base = EQ::skills::GetBaseDamage(skill); auto skill_level = GetSkill(skill); switch (skill) { - case EQ::skills::SkillDragonPunch: - case EQ::skills::SkillEagleStrike: - case EQ::skills::SkillTigerClaw: - case EQ::skills::SkillRoundKick: - if (skill_level >= 25) - base++; - if (skill_level >= 75) - base++; - if (skill_level >= 125) - base++; - if (skill_level >= 175) - base++; - return base; - case EQ::skills::SkillFrenzy: - if (IsClient() && CastToClient()->GetInv().GetItem(EQ::invslot::slotPrimary)) { - if (GetLevel() > 15) - base += GetLevel() - 15; - if (base > 23) - base = 23; - if (GetLevel() > 50) - base += 2; - if (GetLevel() > 54) + case EQ::skills::SkillDragonPunch: + case EQ::skills::SkillEagleStrike: + case EQ::skills::SkillTigerClaw: + case EQ::skills::SkillRoundKick: + if (skill_level >= 25) { base++; - if (GetLevel() > 59) + } + + if (skill_level >= 75) { base++; - } - return base; - case EQ::skills::SkillFlyingKick: { - float skill_bonus = skill_level / 9.0f; - float ac_bonus = 0.0f; - if (IsClient()) { - auto inst = CastToClient()->GetInv().GetItem(EQ::invslot::slotFeet); - if (inst) - ac_bonus = inst->GetItemArmorClass(true) / 25.0f; - } - if (ac_bonus > skill_bonus) - ac_bonus = skill_bonus; - return static_cast(ac_bonus + skill_bonus); - } - case EQ::skills::SkillKick: { - // there is some base *= 4 case in here? - float skill_bonus = skill_level / 10.0f; - float ac_bonus = 0.0f; - if (IsClient()) { - auto inst = CastToClient()->GetInv().GetItem(EQ::invslot::slotFeet); - if (inst) - ac_bonus = inst->GetItemArmorClass(true) / 25.0f; - } - if (ac_bonus > skill_bonus) - ac_bonus = skill_bonus; - return static_cast(ac_bonus + skill_bonus); - } - case EQ::skills::SkillBash: { - float skill_bonus = skill_level / 10.0f; - float ac_bonus = 0.0f; - const EQ::ItemInstance *inst = nullptr; - if (IsClient()) { - if (HasShieldEquiped()) - inst = CastToClient()->GetInv().GetItem(EQ::invslot::slotSecondary); - else if (HasTwoHanderEquipped()) - inst = CastToClient()->GetInv().GetItem(EQ::invslot::slotPrimary); - } - if (inst) - ac_bonus = inst->GetItemArmorClass(true) / 25.0f; - else - return 0; // return 0 in cases where we don't have an item - if (ac_bonus > skill_bonus) - ac_bonus = skill_bonus; - return static_cast(ac_bonus + skill_bonus); - } - case EQ::skills::SkillBackstab: { - float skill_bonus = static_cast(skill_level) * 0.02f; - base = 3; // There seems to be a base 3 for NPCs or some how BS w/o weapon? - // until we get a better inv system for NPCs they get nerfed! - if (IsClient()) { - auto *inst = CastToClient()->GetInv().GetItem(EQ::invslot::slotPrimary); - if (inst && inst->GetItem() && inst->GetItem()->ItemType == EQ::item::ItemType1HPiercing) { - base = inst->GetItemBackstabDamage(true); - if (!inst->GetItemBackstabDamage()) { - base += inst->GetItemWeaponDamage(true); + } + + if (skill_level >= 125) { + base++; + } + + if (skill_level >= 175) { + base++; + } + + if (RuleB(Character, ItemExtraSkillDamageCalcAsPercent) && GetSkillDmgAmt(skill) > 0) { + base *= std::abs(GetSkillDmgAmt(skill) / 100); + } + + return base; + case EQ::skills::SkillFrenzy: + if (IsClient() && CastToClient()->GetInv().GetItem(EQ::invslot::slotPrimary)) { + if (GetLevel() > 15) { + base += GetLevel() - 15; } - if (target) { - if (inst->GetItemElementalFlag(true) && inst->GetItemElementalDamage(true) && !RuleB(Combat, BackstabIgnoresElemental)) { - base += target->ResistElementalWeaponDmg(inst); - } + if (base > 23) { + base = 23; + } - if ((inst->GetItemBaneDamageBody(true) || inst->GetItemBaneDamageRace(true)) && !RuleB(Combat, BackstabIgnoresBane)) { - base += target->CheckBaneDamage(inst); - } + if (GetLevel() > 50) { + base += 2; + } + + if (GetLevel() > 54) { + base++; + } + + if (GetLevel() > 59) { + base++; } } - } else if (IsNPC()) { - auto *npc = CastToNPC(); - base = std::max(base, npc->GetBaseDamage()); - // parses show relatively low BS mods from lots of NPCs, so either their BS skill is super low - // or their mod is divided again, this is probably not the right mod, but it's better - skill_bonus /= 3.0f; + + if (RuleB(Character, ItemExtraSkillDamageCalcAsPercent) && GetSkillDmgAmt(skill) > 0) { + base *= std::abs(GetSkillDmgAmt(skill) / 100); + } + + return base; + case EQ::skills::SkillFlyingKick: { + float skill_bonus = skill_level / 9.0f; + float ac_bonus = 0.0f; + if (IsClient()) { + auto inst = CastToClient()->GetInv().GetItem(EQ::invslot::slotFeet); + if (inst) { + ac_bonus = inst->GetItemArmorClass(true) / 25.0f; + } + } + + if (ac_bonus > skill_bonus) { + ac_bonus = skill_bonus; + } + + if (RuleB(Character, ItemExtraSkillDamageCalcAsPercent) && GetSkillDmgAmt(skill) > 0) { + return static_cast(ac_bonus + skill_bonus) * std::abs(GetSkillDmgAmt(skill) / 100); + } + + return static_cast(ac_bonus + skill_bonus); + } + case EQ::skills::SkillKick: { + // there is some base *= 4 case in here? + float skill_bonus = skill_level / 10.0f; + float ac_bonus = 0.0f; + if (IsClient()) { + auto inst = CastToClient()->GetInv().GetItem(EQ::invslot::slotFeet); + if (inst) { + ac_bonus = inst->GetItemArmorClass(true) / 25.0f; + } + } + + if (ac_bonus > skill_bonus) { + ac_bonus = skill_bonus; + } + + if (RuleB(Character, ItemExtraSkillDamageCalcAsPercent) && GetSkillDmgAmt(skill) > 0) { + return static_cast(ac_bonus + skill_bonus) * std::abs(GetSkillDmgAmt(skill) / 100); + } + + return static_cast(ac_bonus + skill_bonus); + } + case EQ::skills::SkillBash: { + float skill_bonus = skill_level / 10.0f; + float ac_bonus = 0.0f; + const EQ::ItemInstance *inst = nullptr; + if (IsClient()) { + if (HasShieldEquiped()) { + inst = CastToClient()->GetInv().GetItem(EQ::invslot::slotSecondary); + } else if (HasTwoHanderEquipped()) { + inst = CastToClient()->GetInv().GetItem(EQ::invslot::slotPrimary); + } + } + + if (inst) { + ac_bonus = inst->GetItemArmorClass(true) / 25.0f; + } else { + return 0; + } // return 0 in cases where we don't have an item + + if (ac_bonus > skill_bonus) { + ac_bonus = skill_bonus; + } + + if (RuleB(Character, ItemExtraSkillDamageCalcAsPercent) && GetSkillDmgAmt(skill) > 0) { + return static_cast(ac_bonus + skill_bonus) * std::abs(GetSkillDmgAmt(skill) / 100); + } + + return static_cast(ac_bonus + skill_bonus); + } + case EQ::skills::SkillBackstab: { + float skill_bonus = static_cast(skill_level) * 0.02f; + base = 3; // There seems to be a base 3 for NPCs or some how BS w/o weapon? + // until we get a better inv system for NPCs they get nerfed! + if (IsClient()) { + auto *inst = CastToClient()->GetInv().GetItem(EQ::invslot::slotPrimary); + if (inst && inst->GetItem() && inst->GetItem()->ItemType == EQ::item::ItemType1HPiercing) { + base = inst->GetItemBackstabDamage(true); + if (!inst->GetItemBackstabDamage()) { + base += inst->GetItemWeaponDamage(true); + } + + if (target) { + if (inst->GetItemElementalFlag(true) && inst->GetItemElementalDamage(true) && + !RuleB(Combat, BackstabIgnoresElemental)) { + base += target->ResistElementalWeaponDmg(inst); + } + + if ((inst->GetItemBaneDamageBody(true) || inst->GetItemBaneDamageRace(true)) && + !RuleB(Combat, BackstabIgnoresBane)) { + base += target->CheckBaneDamage(inst); + } + } + } + } else if (IsNPC()) { + auto *npc = CastToNPC(); + base = std::max(base, npc->GetBaseDamage()); + // parses show relatively low BS mods from lots of NPCs, so either their BS skill is super low + // or their mod is divided again, this is probably not the right mod, but it's better + skill_bonus /= 3.0f; + } + + if (RuleB(Character, ItemExtraSkillDamageCalcAsPercent) && GetSkillDmgAmt(skill) > 0) { + return static_cast(static_cast(base) * (skill_bonus + 2.0f)) * std::abs(GetSkillDmgAmt(skill) / 100); + } + + return static_cast(static_cast(base) * (skill_bonus + 2.0f)); + } + default: { + return 0; } - // ahh lets make sure everything is casted right :P ugly but w/e - return static_cast(static_cast(base) * (skill_bonus + 2.0f)); - } - default: - return 0; } } @@ -332,8 +391,6 @@ void Client::OPCombatAbility(const CombatAbility_Struct *ca_atk) int32 max_dmg = GetBaseSkillDamage(EQ::skills::SkillFrenzy, GetTarget()); DoAnim(anim1HWeapon, 0, false); - max_dmg = mod_frenzy_damage(max_dmg); - if (GetClass() == BERSERKER) { int chance = GetLevel() * 2 + GetSkill(EQ::skills::SkillFrenzy); if (zone->random.Roll0(450) < chance) @@ -528,9 +585,6 @@ int Mob::MonkSpecialAttack(Mob *other, uint8 unchecked_type) if (max_dmg > 0) ht = max_dmg; - // This can potentially stack with changes to kick damage - ht = ndamage = mod_monk_special_damage(ndamage, skill_type); - DoSpecialAttackDamage(other, skill_type, max_dmg, min_dmg, ht, reuse); return reuse; @@ -2173,8 +2227,9 @@ int Mob::TryHeadShot(Mob *defender, EQ::skills::SkillType skillInUse) if (HeadShot_Dmg && HeadShot_Level && (defender->GetLevel() <= HeadShot_Level)) { int chance = GetDEX(); chance = 100 * chance / (chance + 3500); - if (IsClient()) - chance += CastToClient()->GetHeroicDEX() / 25; + if (IsClient() || IsBot()) { + chance += GetHeroicDEX() / 25; + } chance *= 10; int norm = aabonuses.HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_CHANCE_BONUS]; if (norm > 0) @@ -2204,8 +2259,9 @@ int Mob::TryAssassinate(Mob *defender, EQ::skills::SkillType skillInUse) int chance = GetDEX(); if (skillInUse == EQ::skills::SkillBackstab) { chance = 100 * chance / (chance + 3500); - if (IsClient()) - chance += CastToClient()->GetHeroicDEX(); + if (IsClient() || IsBot()) { + chance += GetHeroicDEX(); + } chance *= 10; int norm = aabonuses.AssassinateLevel[SBIndex::FINISHING_EFFECT_LEVEL_CHANCE_BONUS]; if (norm > 0) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 42e94134b..096fa2e63 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -27,6 +27,7 @@ #include "../common/data_verification.h" #include "../common/misc_functions.h" +#include "bot.h" #include "quest_parser_collection.h" #include "lua_parser.h" #include "string_ids.h" @@ -162,28 +163,47 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } } - std::string export_string = fmt::format( - "{} {} {} {}", - caster ? caster->GetID() : 0, - buffslot >= 0 ? buffs[buffslot].ticsremaining : 0, - caster ? caster->GetLevel() : 0, - buffslot - ); - if (IsClient()) { - if (parse->EventSpell(EVENT_SPELL_EFFECT_CLIENT, nullptr, CastToClient(), spell_id, export_string, 0) != 0) { - CalcBonuses(); - return true; + if (parse->SpellHasQuestSub(spell_id, EVENT_SPELL_EFFECT_CLIENT)) { + const auto &export_string = fmt::format( + "{} {} {} {}", + caster ? caster->GetID() : 0, + buffslot >= 0 ? buffs[buffslot].ticsremaining : 0, + caster ? caster->GetLevel() : 0, + buffslot + ); + if (parse->EventSpell(EVENT_SPELL_EFFECT_CLIENT, nullptr, CastToClient(), spell_id, export_string, 0) != 0) { + CalcBonuses(); + return true; + } } } else if (IsNPC()) { - if (parse->EventSpell(EVENT_SPELL_EFFECT_NPC, this, nullptr, spell_id, export_string, 0) != 0) { - CalcBonuses(); - return true; + if (parse->SpellHasQuestSub(spell_id, EVENT_SPELL_EFFECT_NPC)) { + const auto &export_string = fmt::format( + "{} {} {} {}", + caster ? caster->GetID() : 0, + buffslot >= 0 ? buffs[buffslot].ticsremaining : 0, + caster ? caster->GetLevel() : 0, + buffslot + ); + if (parse->EventSpell(EVENT_SPELL_EFFECT_NPC, this, nullptr, spell_id, export_string, 0) != 0) { + CalcBonuses(); + return true; + } } } else if (IsBot()) { - if (parse->EventSpell(EVENT_SPELL_EFFECT_BOT, this, nullptr, spell_id, export_string, 0) != 0) { - CalcBonuses(); - return true; + if (parse->SpellHasQuestSub(spell_id, EVENT_SPELL_EFFECT_BOT)) { + const auto &export_string = fmt::format( + "{} {} {} {}", + caster ? caster->GetID() : 0, + buffslot >= 0 ? buffs[buffslot].ticsremaining : 0, + caster ? caster->GetLevel() : 0, + buffslot + ); + if (parse->EventSpell(EVENT_SPELL_EFFECT_BOT, this, nullptr, spell_id, export_string, 0) != 0) { + CalcBonuses(); + return true; + } } } @@ -1059,7 +1079,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } int buff_count = GetMaxTotalSlots(); for(int slot = 0; slot < buff_count; slot++) { - if( buffs[slot].spellid != SPELL_UNKNOWN && + if(IsValidSpell(buffs[slot].spellid) && spells[buffs[slot].spellid].dispel_flag == 0 && !IsDiscipline(buffs[slot].spellid)) { @@ -1090,7 +1110,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove int chance = spells[spell_id].base_value[i]; int buff_count = GetMaxTotalSlots(); for(int slot = 0; slot < buff_count; slot++) { - if (buffs[slot].spellid != SPELL_UNKNOWN && + if (IsValidSpell(buffs[slot].spellid) && IsDetrimentalSpell(buffs[slot].spellid) && spells[buffs[slot].spellid].dispel_flag == 0) { @@ -1117,7 +1137,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove int chance = spells[spell_id].base_value[i]; int buff_count = GetMaxTotalSlots(); for(int slot = 0; slot < buff_count; slot++) { - if (buffs[slot].spellid != SPELL_UNKNOWN && + if (IsValidSpell(buffs[slot].spellid) && IsBeneficialSpell(buffs[slot].spellid) && spells[buffs[slot].spellid].dispel_flag == 0) { @@ -1316,7 +1336,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if (BeneficialSpell(spell_id) && spells[spell_id].buff_duration == 0) { int buff_count = GetMaxBuffSlots(); for (int slot = 0; slot < buff_count; slot++) { - if (buffs[slot].spellid != SPELL_UNKNOWN && IsEffectInSpell(buffs[slot].spellid, SE_Blind)) { + if (IsValidSpell(buffs[slot].spellid) && IsEffectInSpell(buffs[slot].spellid, SE_Blind)) { if (caster && TryDispel(caster->GetCasterLevel(spell_id), buffs[slot].casterlevel, 1)) { BuffFadeBySlot(slot); slot = buff_count; @@ -2901,14 +2921,16 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove since effect can potentially kill caster. */ case SE_Health_Transfer: { - effect_value = spells[spell_id].limit_value[i]; - int64 amt = std::abs(caster->GetMaxHP() * effect_value / 1000); + if (caster) { + effect_value = spells[spell_id].limit_value[i]; + int64 amt = std::abs(caster->GetMaxHP() * effect_value / 1000); - if (effect_value < 0) { - Damage(caster, amt, spell_id, spell.skill, false, buffslot, false); - } - else { - HealDamage(amt, caster); + if (effect_value < 0) { + Damage(caster, amt, spell_id, spell.skill, false, buffslot, false); + } + else { + HealDamage(amt, caster); + } } break; } @@ -3406,8 +3428,6 @@ int64 Mob::CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level } } - effect_value = mod_effect_value(effect_value, spell_id, spells[spell_id].effect_id[effect_id], caster, caster_id); - return effect_value; } @@ -3735,12 +3755,13 @@ void Mob::BuffProcess() for (int buffs_i = 0; buffs_i < buff_count; ++buffs_i) { - if (buffs[buffs_i].spellid != SPELL_UNKNOWN) + if (IsValidSpell(buffs[buffs_i].spellid)) { DoBuffTic(buffs[buffs_i], buffs_i, entity_list.GetMob(buffs[buffs_i].casterid)); // If the Mob died during DoBuffTic, then the buff we are currently processing will have been removed - if(buffs[buffs_i].spellid == SPELL_UNKNOWN) + if(!IsValidSpell(buffs[buffs_i].spellid)) { continue; + } // DF_Permanent uses -1 DF_Aura uses -4 but we need to check negatives for some spells for some reason? if (spells[buffs[buffs_i].spellid].buff_duration_formula != DF_Permanent && @@ -3789,7 +3810,7 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) const SPDat_Spell_Struct &spell = spells[buff.spellid]; - std::string export_string = fmt::format( + const auto& export_string = fmt::format( "{} {} {} {}", caster ? caster->GetID() : 0, buffs[slot].ticsremaining, @@ -3798,16 +3819,22 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) ); if (IsClient()) { - if (parse->EventSpell(EVENT_SPELL_EFFECT_BUFF_TIC_CLIENT, nullptr, CastToClient(), buff.spellid, export_string, 0) != 0) { - return; + if (parse->SpellHasQuestSub(buff.spellid, EVENT_SPELL_EFFECT_BUFF_TIC_CLIENT)) { + if (parse->EventSpell(EVENT_SPELL_EFFECT_BUFF_TIC_CLIENT, nullptr, CastToClient(), buff.spellid, export_string, 0) != 0) { + return; + } } } else if (IsNPC()) { - if (parse->EventSpell(EVENT_SPELL_EFFECT_BUFF_TIC_NPC, this, nullptr, buff.spellid, export_string, 0) != 0) { - return; + if (parse->SpellHasQuestSub(buff.spellid, EVENT_SPELL_EFFECT_BUFF_TIC_NPC)) { + if (parse->EventSpell(EVENT_SPELL_EFFECT_BUFF_TIC_NPC, this, nullptr, buff.spellid, export_string, 0) != 0) { + return; + } } } else if (IsBot()) { - if (parse->EventSpell(EVENT_SPELL_EFFECT_BUFF_TIC_BOT, this, nullptr, buff.spellid, export_string, 0) != 0) { - return; + if (parse->SpellHasQuestSub(buff.spellid, EVENT_SPELL_EFFECT_BUFF_TIC_BOT)) { + if (parse->EventSpell(EVENT_SPELL_EFFECT_BUFF_TIC_BOT, this, nullptr, buff.spellid, export_string, 0) != 0) { + return; + } } } @@ -4140,25 +4167,35 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) LogSpells("Fading buff [{}] from slot [{}]", buffs[slot].spellid, slot); - std::string export_string = fmt::format( - "{} {} {} {}", - buffs[slot].casterid, - buffs[slot].ticsremaining, - buffs[slot].casterlevel, - slot - ); + const auto has_fade_event = parse->SpellHasQuestSub(buffs[slot].spellid, EVENT_SPELL_FADE); + std::string export_string = ""; + if (has_fade_event) { + export_string = fmt::format( + "{} {} {} {}", + buffs[slot].casterid, + buffs[slot].ticsremaining, + buffs[slot].casterlevel, + slot + ); + } if (IsClient()) { - if (parse->EventSpell(EVENT_SPELL_FADE, nullptr, CastToClient(), buffs[slot].spellid, export_string, 0) != 0) { - return; + if (has_fade_event) { + if (parse->EventSpell(EVENT_SPELL_FADE, nullptr, CastToClient(), buffs[slot].spellid, export_string, 0) != 0) { + return; + } } } else if (IsNPC()) { - if (parse->EventSpell(EVENT_SPELL_FADE, this, nullptr, buffs[slot].spellid, export_string, 0) != 0) { - return; + if (has_fade_event) { + if (parse->EventSpell(EVENT_SPELL_FADE, this, nullptr, buffs[slot].spellid, export_string, 0) != 0) { + return; + } } } else if (IsBot()) { - if (parse->EventSpell(EVENT_SPELL_FADE, this, nullptr, buffs[slot].spellid, export_string, 0) != 0) { - return; + if (has_fade_event) { + if (parse->EventSpell(EVENT_SPELL_FADE, this, nullptr, buffs[slot].spellid, export_string, 0) != 0) { + return; + } } } @@ -4207,27 +4244,8 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) case SE_Illusion: { SendIllusionPacket(0, GetBaseGender()); - if (GetRace() == OGRE) { - SendAppearancePacket(AT_Size, 9); - } - else if (GetRace() == TROLL) { - SendAppearancePacket(AT_Size, 8); - } - else if (GetRace() == VAHSHIR || GetRace() == FROGLOK || GetRace() == BARBARIAN) { - SendAppearancePacket(AT_Size, 7); - } - else if (GetRace() == HALF_ELF || GetRace() == WOOD_ELF || GetRace() == DARK_ELF) { - SendAppearancePacket(AT_Size, 5); - } - else if (GetRace() == DWARF) { - SendAppearancePacket(AT_Size, 4); - } - else if (GetRace() == HALFLING || GetRace() == GNOME) { - SendAppearancePacket(AT_Size, 3); - } - else { - SendAppearancePacket(AT_Size, 6); - } + // The GetSize below works because the above setting race to zero sets size back. + SendAppearancePacket(AT_Size, GetSize()); for (int x = EQ::textures::textureBegin; x <= EQ::textures::LastTintableTexture; x++) { SendWearChange(x); @@ -6128,12 +6146,12 @@ void Mob::TryTriggerOnCastFocusEffect(focusType type, uint16 spell_id) int32 proc_spellid = 0; // item focus - if (IsClient() && itembonuses.FocusEffects[type]) { + if (IsOfClientBot() && itembonuses.FocusEffects[type]) { const EQ::ItemData *temp_item = nullptr; for (int x = EQ::invslot::EQUIPMENT_BEGIN; x <= EQ::invslot::EQUIPMENT_END; x++) { temp_item = nullptr; - EQ::ItemInstance *ins = CastToClient()->GetInv().GetItem(x); + EQ::ItemInstance const *ins = (IsClient()) ? CastToClient()->GetInv().GetItem(x) : CastToBot()->GetBotItem(x); if (!ins) { continue; } @@ -6193,7 +6211,7 @@ void Mob::TryTriggerOnCastFocusEffect(focusType type, uint16 spell_id) } // Only use one of this focus per AA effect. - if (IsClient() && aabonuses.FocusEffects[type]) { + if (IsOfClientBot() && aabonuses.FocusEffects[type]) { for (const auto &aa : aa_ranks) { auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(aa.first, aa.second.first); auto ability = ability_rank.first; @@ -6207,7 +6225,7 @@ void Mob::TryTriggerOnCastFocusEffect(focusType type, uint16 spell_id) continue; } - proc_spellid = CastToClient()->CalcAAFocus(type, *rank, spell_id); + proc_spellid = CalcAAFocus(type, *rank, spell_id); if (proc_spellid) { TryTriggerOnCastProc(0, spell_id, proc_spellid); } @@ -6233,7 +6251,7 @@ bool Mob::TryTriggerOnCastProc(uint16 focusspellid, uint16 spell_id, uint16 proc return false; } -uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { +uint16 Mob::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { if (IsBardSong(spell_id)) return 0; @@ -6244,21 +6262,21 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { std::vector SympatheticProcList; //item focus - if (itembonuses.FocusEffects[type]){ + if (IsOfClientBot() && itembonuses.FocusEffects[type]) { - const EQ::ItemData* TempItem = nullptr; for (int x = EQ::invslot::EQUIPMENT_BEGIN; x <= EQ::invslot::EQUIPMENT_END; x++) { if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS) continue; - TempItem = nullptr; - EQ::ItemInstance* ins = GetInv().GetItem(x); + EQ::ItemInstance const* ins = GetInv().GetItem(x); if (!ins) continue; - TempItem = ins->GetItem(); - if (TempItem && TempItem->Focus.Effect > 0 && IsValidSpell(TempItem->Focus.Effect)) { + if ( + auto TempItem = ins->GetItem(); + TempItem && TempItem->Focus.Effect > 0 && IsValidSpell(TempItem->Focus.Effect) + ) { proc_spellid = CalcFocusEffect(type, TempItem->Focus.Effect, spell_id); if (IsValidSpell(proc_spellid)){ @@ -6273,11 +6291,10 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS) continue; - EQ::ItemInstance *aug = nullptr; - aug = ins->GetAugment(y); - if(aug) + auto aug = ins->GetAugment(y); + if (aug) { - const EQ::ItemData* TempItemAug = aug->GetItem(); + auto TempItemAug = aug->GetItem(); if (TempItemAug && TempItemAug->Focus.Effect > 0 && IsValidSpell(TempItemAug->Focus.Effect)) { proc_spellid = CalcFocusEffect(type, TempItemAug->Focus.Effect, spell_id); if (IsValidSpell(proc_spellid)){ @@ -6293,52 +6310,56 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { //Spell Focus if (spellbonuses.FocusEffects[type]){ - int buff_slot = 0; uint16 focusspellid = 0; int buff_max = GetMaxTotalSlots(); - for (buff_slot = 0; buff_slot < buff_max; buff_slot++) { + for (int buff_slot = 0; buff_slot < buff_max; buff_slot++) { - if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS) + if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS) { continue; + } focusspellid = buffs[buff_slot].spellid; - if (!IsValidSpell(focusspellid)) + if (!IsValidSpell(focusspellid)) { continue; + } proc_spellid = CalcFocusEffect(type, focusspellid, spell_id); - if (IsValidSpell(proc_spellid)){ + if (IsValidSpell(proc_spellid)) { ProcChance = GetSympatheticProcChances(spell_id, GetSympatheticSpellProcRate(proc_spellid)); - if(zone->random.Roll(ProcChance)) - SympatheticProcList.push_back(proc_spellid); + if (zone->random.Roll(ProcChance)) { + SympatheticProcList.push_back(proc_spellid); + } } } } /*Note: At present, ff designing custom AA to have a sympathetic proc effect, only use one focus effect within the aa_effects data for each AA*[No live AA's use this effect to my knowledge]*/ - if (aabonuses.FocusEffects[type]) { + if (IsOfClientBot() && aabonuses.FocusEffects[type]) { for (const auto &aa : aa_ranks) { - if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS) + if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS) { break; + } auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(aa.first, aa.second.first); auto ability = ability_rank.first; auto rank = ability_rank.second; - if(!ability) { + if (!ability) { continue; } - if (rank->effects.empty()) + if (rank->effects.empty()) { continue; - + } proc_spellid = CalcAAFocus(type, *rank, spell_id); if (IsValidSpell(proc_spellid)) { ProcChance = GetSympatheticProcChances(spell_id, rank->effects[0].base_value); - if (zone->random.Roll(ProcChance)) + if (zone->random.Roll(ProcChance)) { SympatheticProcList.push_back(proc_spellid); + } } } } @@ -6350,7 +6371,6 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { SympatheticProcList.clear(); return FinalSympatheticProc; } - return 0; } @@ -6391,7 +6411,7 @@ int64 Mob::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster, bool fro } TempItem = ins->GetItem(); - if (TempItem && TempItem->Focus.Effect > 0 && TempItem->Focus.Effect != SPELL_UNKNOWN) { + if (TempItem && IsValidSpell(TempItem->Focus.Effect)) { if(rand_effectiveness) { focus_max = CalcFocusEffect(type, TempItem->Focus.Effect, spell_id, true); if (focus_max > 0 && focus_max_real >= 0 && focus_max > focus_max_real) { @@ -6423,7 +6443,7 @@ int64 Mob::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster, bool fro aug = ins->GetAugment(y); if (aug) { const EQ::ItemData* TempItemAug = aug->GetItem(); - if (TempItemAug && TempItemAug->Focus.Effect > 0 && TempItemAug->Focus.Effect != SPELL_UNKNOWN) { + if (TempItemAug && IsValidSpell(TempItemAug->Focus.Effect)) { if(rand_effectiveness) { focus_max = CalcFocusEffect(type, TempItemAug->Focus.Effect, spell_id, true); if (focus_max > 0 && focus_max_real >= 0 && focus_max > focus_max_real) { @@ -6463,7 +6483,7 @@ int64 Mob::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster, bool fro } TempItem = ins->GetItem(); - if (TempItem && TempItem->Focus.Effect > 0 && TempItem->Focus.Effect != SPELL_UNKNOWN) { + if (TempItem && IsValidSpell(TempItem->Focus.Effect)) { if (rand_effectiveness) { focus_max = CalcFocusEffect(type, TempItem->Focus.Effect, spell_id, true); if (focus_max > 0 && focus_max_real >= 0 && focus_max > focus_max_real) { @@ -6673,7 +6693,7 @@ int64 NPC::GetFocusEffect(focusType type, uint16 spell_id, Mob* caster, bool fro TempItem = cur; - if (TempItem && TempItem->Focus.Effect > 0 && TempItem->Focus.Effect != SPELL_UNKNOWN) { + if (TempItem && IsValidSpell(TempItem->Focus.Effect)) { if(rand_effectiveness) { focus_max = CalcFocusEffect(type, TempItem->Focus.Effect, spell_id, true); if (focus_max > 0 && focus_max_real >= 0 && focus_max > focus_max_real) { @@ -9716,7 +9736,7 @@ bool Mob::PassLimitToSkill(EQ::skills::SkillType skill, int32 spell_id, int proc if (!aa_id && spellbonuses.LimitToSkill[EQ::skills::HIGHEST_SKILL + 2]) { - if (spell_id == SPELL_UNKNOWN) { + if (!IsValidSpell(spell_id)) { return false; } @@ -10323,13 +10343,13 @@ void Mob::SetBuffDuration(int spell_id, int duration) { for (int slot = 0; slot < buff_count; slot++) { if (!adjust_all_buffs) { - if (buffs[slot].spellid != SPELL_UNKNOWN && buffs[slot].spellid == spell_id) { + if (IsValidSpell(buffs[slot].spellid) && buffs[slot].spellid == spell_id) { SpellOnTarget(buffs[slot].spellid, this, 0, false, 0, false, -1, duration, true); return; } } else { - if (buffs[slot].spellid != SPELL_UNKNOWN) { + if (IsValidSpell(buffs[slot].spellid)) { SpellOnTarget(buffs[slot].spellid, this, 0, false, 0, false, -1, duration, true); } } @@ -10371,7 +10391,7 @@ int Mob::GetBuffStatValueBySpell(int32 spell_id, const char* stat_identifier) int buff_count = GetMaxTotalSlots(); for (int slot = 0; slot < buff_count; slot++) { - if (buffs[slot].spellid != SPELL_UNKNOWN && buffs[slot].spellid == spell_id) { + if (IsValidSpell(buffs[slot].spellid) && buffs[slot].spellid == spell_id) { return GetBuffStatValueBySlot(slot, stat_identifier); } } diff --git a/zone/spells.cpp b/zone/spells.cpp index c15d48491..c8fdf9f08 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -77,6 +77,7 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) #include "../common/strings.h" #include "../common/data_verification.h" #include "../common/misc_functions.h" +#include "../common/events/player_event_logs.h" #include "data_bucket.h" #include "quest_parser_collection.h" @@ -237,25 +238,44 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, } } - std::string export_string = fmt::format( - "{} {} {}", - spell_id, - GetID(), - GetCasterLevel(spell_id) - ); if (IsClient()) { - if (parse->EventPlayer(EVENT_CAST_BEGIN, CastToClient(), export_string, 0) != 0) { - if (IsDiscipline(spell_id)) { - CastToClient()->SendDisciplineTimer(spells[spell_id].timer_id, 0); - } else { - CastToClient()->SendSpellBarEnable(spell_id); + if (parse->PlayerHasQuestSub(EVENT_CAST_BEGIN)) { + const auto& export_string = fmt::format( + "{} {} {}", + spell_id, + GetID(), + GetCasterLevel(spell_id) + ); + if (parse->EventPlayer(EVENT_CAST_BEGIN, CastToClient(), export_string, 0) != 0) { + if (IsDiscipline(spell_id)) { + CastToClient()->SendDisciplineTimer(spells[spell_id].timer_id, 0); + } + else { + CastToClient()->SendSpellBarEnable(spell_id); + } + return false; } - return false; } } else if (IsNPC()) { - parse->EventNPC(EVENT_CAST_BEGIN, CastToNPC(), nullptr, export_string, 0); + if (parse->HasQuestSub(GetNPCTypeID(), EVENT_CAST_BEGIN)) { + const auto& export_string = fmt::format( + "{} {} {}", + spell_id, + GetID(), + GetCasterLevel(spell_id) + ); + parse->EventNPC(EVENT_CAST_BEGIN, CastToNPC(), nullptr, export_string, 0); + } } else if (IsBot()) { - parse->EventBot(EVENT_CAST_BEGIN, CastToBot(), nullptr, export_string, 0); + if (parse->BotHasQuestSub(EVENT_CAST_BEGIN)) { + const auto& export_string = fmt::format( + "{} {} {}", + spell_id, + GetID(), + GetCasterLevel(spell_id) + ); + parse->EventBot(EVENT_CAST_BEGIN, CastToBot(), nullptr, export_string, 0); + } } //To prevent NPC ghosting when spells are cast from scripts @@ -410,26 +430,16 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, // If you're at full mana, let it cast even if you dont have enough mana // we calculated this above, now enforce it - if (mana_cost > 0 && slot != CastingSlot::Item) { + if (mana_cost > 0 && slot != CastingSlot::Item || (IsBot() && !CastToBot()->IsBotNonSpellFighter())) { int my_curmana = GetMana(); int my_maxmana = GetMaxMana(); if (my_curmana < mana_cost) {// not enough mana //this is a special case for NPCs with no mana... - if (IsNPC() && my_curmana == my_maxmana){ + if (IsNPC() && my_curmana == my_maxmana) { mana_cost = 0; - } else { - //The client will prevent spell casting if insufficient mana, this is only for serverside enforcement. - LogSpells("Spell Error not enough mana spell=[{}] mymana=[{}] cost=[{}]\n", spell_id, my_curmana, mana_cost); - if (IsClient()) { - //clients produce messages... npcs should not for this case - MessageString(Chat::Red, INSUFFICIENT_MANA); - InterruptSpell(); - } else { - InterruptSpell(0, 0, 0); //the 0 args should cause no messages - } - ZeroCastingVars(); - return(false); } + DoSpellInterrupt(spell_id, mana_cost, my_curmana); + return false; } } @@ -455,11 +465,9 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, // cast time is 0, just finish it right now and be done with it if(cast_time == 0) { CastedSpellFinished(spell_id, target_id, slot, mana_cost, item_slot, resist_adjust); // - return(true); + return true; } - cast_time = mod_cast_time(cast_time); - // ok we know it has a cast time so we can start the timer now spellend_timer.Start(cast_time); @@ -483,7 +491,20 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, } } - return(true); + return true; +} + +void Mob::DoSpellInterrupt(uint16 spell_id, int32 mana_cost, int my_curmana) { + //The client will prevent spell casting if insufficient mana, this is only for serverside enforcement. + LogSpells("Spell Error not enough mana spell=[{}] mymana=[{}] cost=[{}]\n", spell_id, my_curmana, mana_cost); + if (IsClient()) { + //clients produce messages... npcs should not for this case + MessageString(Chat::Red, INSUFFICIENT_MANA); + InterruptSpell(); + } else { + InterruptSpell(0, 0, 0); //the 0 args should cause no messages + } + ZeroCastingVars(); } void Mob::SendBeginCast(uint16 spell_id, uint32 casttime) @@ -1126,8 +1147,9 @@ void Mob::ZeroBardPulseVars() void Mob::InterruptSpell(uint16 spellid) { - if (spellid == SPELL_UNKNOWN) + if (!IsValidSpell(spellid)) { spellid = casting_spell_id; + } InterruptSpell(0, 0x121, spellid); } @@ -1138,11 +1160,17 @@ void Mob::InterruptSpell(uint16 message, uint16 color, uint16 spellid) EQApplicationPacket *outapp = nullptr; uint16 message_other; bool bard_song_mode = false; //has the bard song gone to auto repeat mode - if (spellid == SPELL_UNKNOWN) { - if(bardsong) { + if (!IsValidSpell(spellid)) { + if (bardsong) { spellid = bardsong; bard_song_mode = true; - } else { + } + else { + if (IsBot() && !message && !color && !spellid) { // this is to prevent bots from spamming interrupts messages when trying to cast while OOM + ZeroCastingVars(); // resets all the state keeping stuff + LogSpells("Spell [{}] has been interrupted - Bot [{}] doesn't have enough mana", spellid, GetCleanName()); + return; + } spellid = casting_spell_id; } } @@ -1390,35 +1418,18 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo float channelchance, distance_moved, d_x, d_y, distancemod; - if(IsClient()) - { + if (IsOfClientBot()) { float channelbonuses = 0.0f; //AA that effect Spell channel chance are no longer on live. http://everquest.allakhazam.com/history/patches-2006-2.html //No harm in maintaining the effects regardless, since we do check for channel chance. - if (IsFromItem) - channelbonuses += spellbonuses.ChannelChanceItems + itembonuses.ChannelChanceItems + aabonuses.ChannelChanceItems; - else - channelbonuses += spellbonuses.ChannelChanceSpells + itembonuses.ChannelChanceSpells + aabonuses.ChannelChanceSpells; - + channelbonuses += IsFromItem ? + spellbonuses.ChannelChanceItems + itembonuses.ChannelChanceItems + aabonuses.ChannelChanceItems : + spellbonuses.ChannelChanceSpells + itembonuses.ChannelChanceSpells + aabonuses.ChannelChanceSpells; // max 93% chance at 252 skill channelchance = 30 + GetSkill(EQ::skills::SkillChanneling) / 400.0f * 100; channelchance -= attacked_count * 2; channelchance += channelchance * channelbonuses / 100.0f; - } - else if(IsBot()) { - float channelbonuses = 0.0f; - - if (IsFromItem) - channelbonuses += spellbonuses.ChannelChanceItems + itembonuses.ChannelChanceItems + aabonuses.ChannelChanceItems; - else - channelbonuses += spellbonuses.ChannelChanceSpells + itembonuses.ChannelChanceSpells + aabonuses.ChannelChanceSpells; - - // max 93% chance at 252 skill - channelchance = 30 + GetSkill(EQ::skills::SkillChanneling) / 400.0f * 100; - channelchance -= attacked_count * 2; - channelchance += channelchance * channelbonuses / 100.0f; - } - else { + } else { // NPCs are just hard to interrupt, otherwise they get pwned channelchance = 85; channelchance -= attacked_count; @@ -1635,7 +1646,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo return; } - if(IsClient()) { + if(IsOfClientBotMerc()) { TrySympatheticProc(target, spell_id); } @@ -1651,18 +1662,25 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo // at this point the spell has successfully been cast // - std::string export_string = fmt::format( + const auto& export_string = fmt::format( "{} {} {}", spell_id, GetID(), GetCasterLevel(spell_id) ); + if (IsClient()) { - parse->EventPlayer(EVENT_CAST, CastToClient(), export_string, 0); + if (parse->PlayerHasQuestSub(EVENT_CAST)) { + parse->EventPlayer(EVENT_CAST, CastToClient(), export_string, 0); + } } else if (IsNPC()) { - parse->EventNPC(EVENT_CAST, CastToNPC(), nullptr, export_string, 0); + if (parse->HasQuestSub(GetNPCTypeID(), EVENT_CAST)) { + parse->EventNPC(EVENT_CAST, CastToNPC(), nullptr, export_string, 0); + } } else if (IsBot()) { - parse->EventBot(EVENT_CAST, CastToBot(), nullptr, export_string, 0); + if (parse->BotHasQuestSub(EVENT_CAST)) { + parse->EventBot(EVENT_CAST, CastToBot(), nullptr, export_string, 0); + } } if(bard_song_mode) @@ -2560,7 +2578,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, in case CAHateList: { - if(!IsClient()) + if(!IsOfClientBotMerc()) { hate_list.SpellCast(this, spell_id, spells[spell_id].range > spells[spell_id].aoe_range ? spells[spell_id].range : spells[spell_id].aoe_range); } @@ -2809,9 +2827,6 @@ int Mob::CalcBuffDuration(Mob *caster, Mob *target, uint16 spell_id, int32 caste res = 10000; // ~16h override } - - res = mod_buff_duration(res, caster, target, spell_id); - LogSpells("Spell [{}]: Casting level [{}], formula [{}], base_duration [{}]: result [{}]", spell_id, castlevel, formula, duration, res); @@ -2936,9 +2951,6 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, } } - int modval = mod_spell_stack(spellid1, caster_level1, caster1, spellid2, caster_level2, caster2); - if(modval < 2) { return(modval); } - /* One of these is a bard song and one isn't and they're both beneficial so they should stack. */ @@ -3158,6 +3170,11 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, } if (sp2_value != sp1_value) values_equal = false; + + if (RuleB(Spells, ResurrectionEffectsBlock) && IsResurrectionEffects(spellid1)) { + LogSpells("ResurrectionEffectsBlock triggered -- [{}] is blocked by [{}]", sp2.name, sp1.name); + return -1; // can't stack + } //we dont return here... a better value on this one effect dosent mean they are //all better... @@ -3190,8 +3207,10 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, // 66+ Group Spells 62, Single Target 61 bool Mob::CheckSpellLevelRestriction(Mob *caster, uint16 spell_id) { - bool check_for_restrictions = false; - bool can_cast = true; + if (spells[spell_id].target_type == ST_Self) { + LogSpells("[CheckSpellLevelRestriction] Self Only spell - no restrictions"); + return true; + } if (!caster) { LogSpells("[CheckSpellLevelRestriction] No caster"); @@ -3203,10 +3222,15 @@ bool Mob::CheckSpellLevelRestriction(Mob *caster, uint16 spell_id) return true; } + bool check_for_restrictions = false; + bool can_cast = true; + // NON GM clients might be restricted by rule setting if (caster->IsClient()) { - if (RuleB(Spells, BuffLevelRestrictions)) { - check_for_restrictions = true; + if (IsClient()) { // Only restrict client on client for this rule + if (RuleB(Spells, BuffLevelRestrictions)) { + check_for_restrictions = true; + } } } // NPCS might be restricted by rule setting @@ -3275,7 +3299,7 @@ uint32 Client::GetLastBuffSlot(bool disc, bool song) bool Mob::HasDiscBuff() { int slot = GetFirstBuffSlot(true, false); - return buffs[slot].spellid != SPELL_UNKNOWN; + return IsValidSpell(buffs[slot].spellid); } // returns the slot the buff was added to, -1 if it wasn't added due to @@ -3320,7 +3344,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid for (buffslot = 0; buffslot < buff_count; buffslot++) { const Buffs_Struct &curbuf = buffs[buffslot]; - if (curbuf.spellid != SPELL_UNKNOWN) { + if (IsValidSpell(curbuf.spellid)) { // there's a buff in this slot ret = CheckStackConflict(curbuf.spellid, curbuf.casterlevel, spell_id, caster_level, entity_list.GetMobID(curbuf.casterid), caster, buffslot); @@ -3471,7 +3495,7 @@ int Mob::CanBuffStack(uint16 spellid, uint8 caster_level, bool iFailIfOverwrite) const Buffs_Struct &curbuf = buffs[i]; // no buff in this slot - if (curbuf.spellid == SPELL_UNKNOWN) + if (!IsValidSpell(curbuf.spellid)) { // if we haven't found a free slot, this is the first one so save it if(firstfree == -2) @@ -3574,17 +3598,13 @@ bool Mob::SpellOnTarget( ) { if ( spells[spell_id].pcnpc_only_flag == 1 && - !spelltar->IsClient() && - !spelltar->IsMerc() && - !spelltar->IsBot() + !spelltar->IsOfClientBotMerc() ) { return false; } else if ( spells[spell_id].pcnpc_only_flag == 2 && ( - spelltar->IsClient() || - spelltar->IsMerc() || - spelltar->IsBot() + spelltar->IsOfClientBotMerc() ) ) { return false; @@ -3657,24 +3677,38 @@ bool Mob::SpellOnTarget( (spellOwner->IsClient() ? FilterPCSpells : FilterNPCSpells) /* EQ Filter Type: (8 or 9) */ ); - /* Send the EVENT_CAST_ON event */ - const auto export_string = fmt::format( - "{} {} {}", - spell_id, - GetID(), - caster_level - ); - if (spelltar->IsNPC()) { - parse->EventNPC(EVENT_CAST_ON, spelltar->CastToNPC(), this, export_string, 0); + if (parse->HasQuestSub(spelltar->GetNPCTypeID(), EVENT_CAST_ON)) { + const auto& export_string = fmt::format( + "{} {} {}", + spell_id, + GetID(), + caster_level + ); + parse->EventNPC(EVENT_CAST_ON, spelltar->CastToNPC(), this, export_string, 0); + } } else if (spelltar->IsClient()) { - parse->EventPlayer(EVENT_CAST_ON, spelltar->CastToClient(), export_string, 0); + if (parse->PlayerHasQuestSub(EVENT_CAST_ON)) { + const auto& export_string = fmt::format( + "{} {} {}", + spell_id, + GetID(), + caster_level + ); + parse->EventPlayer(EVENT_CAST_ON, spelltar->CastToClient(), export_string, 0); + } } else if (spelltar->IsBot()) { - parse->EventBot(EVENT_CAST_ON, spelltar->CastToBot(), this, export_string, 0); + if (parse->BotHasQuestSub(EVENT_CAST_ON)) { + const auto& export_string = fmt::format( + "{} {} {}", + spell_id, + GetID(), + caster_level + ); + parse->EventBot(EVENT_CAST_ON, spelltar->CastToBot(), this, export_string, 0); + } } - mod_spell_cast(spell_id, spelltar, reflect_effectiveness, use_resist_adjust, resist_adjust, isproc); - if (!DoCastingChecksOnTarget(false, spell_id, spelltar)) { safe_delete(action_packet); return false; @@ -4122,7 +4156,6 @@ bool Mob::SpellOnTarget( return false; } } - if (spelltar->IsClient()){ spelltar->CastToClient()->BreakSneakWhenCastOn(this, false); spelltar->CastToClient()->BreakFeignDeathWhenCastOn(false); @@ -4578,11 +4611,6 @@ void Mob::BuffFadeByEffect(int effect_id, int slot_to_skip) } } -bool Mob::IsAffectedByBuff(uint16 spell_id) -{ - return FindBuff(spell_id); -} - bool Mob::IsAffectedByBuffByGlobalGroup(GlobalGroup group) { int buff_count = GetMaxTotalSlots(); @@ -4954,7 +4982,7 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use } } - if(IsClient() && level >= 21 && temp_level_diff > 15) + if(IsOfClientBot()&& level >= 21 && temp_level_diff > 15) { temp_level_diff = 15; } @@ -5043,8 +5071,6 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use resist_chance += resist_modifier; resist_chance += target_resist; - resist_chance = mod_spell_resist(resist_chance, level_mod, resist_modifier, target_resist, resist_type, spell_id, caster); - //Do our min and max resist checks. if(resist_chance > spells[spell_id].max_resist && spells[spell_id].max_resist != 0) { @@ -5179,7 +5205,7 @@ int16 Mob::CalcResistChanceBonus() { int resistchance = spellbonuses.ResistSpellChance + itembonuses.ResistSpellChance; - if (IsClient() || IsBot()) { + if (IsOfClientBot()) { resistchance += aabonuses.ResistSpellChance; } return resistchance; @@ -5188,7 +5214,7 @@ int16 Mob::CalcResistChanceBonus() int16 Mob::CalcFearResistChance() { int resistchance = spellbonuses.ResistFearChance + itembonuses.ResistFearChance; - if (IsClient() || IsBot()) { + if (IsOfClientBot()) { resistchance += aabonuses.ResistFearChance; if (aabonuses.Fearless == true) { resistchance = 100; @@ -5683,11 +5709,11 @@ std::unordered_map> Client::LoadSpellGroupCache(uint "SELECT a.spellgroup, a.id, a.rank " "FROM spells_new a " "INNER JOIN (" - "SELECT spellgroup, MAX(rank) rank " + "SELECT spellgroup, MAX(`rank`) `rank` " "FROM spells_new " "GROUP BY spellgroup) " "b ON a.spellgroup = b.spellgroup AND a.rank = b.rank " - "WHERE a.spellgroup IN (SELECT DISTINCT spellgroup FROM spells_new WHERE spellgroup != 0 and classes{} BETWEEN {} AND {}) ORDER BY rank DESC", + "WHERE a.spellgroup IN (SELECT DISTINCT spellgroup FROM spells_new WHERE spellgroup != 0 and classes{} BETWEEN {} AND {}) ORDER BY `rank` DESC", m_pp.class_, min_level, max_level ); @@ -5697,7 +5723,7 @@ std::unordered_map> Client::LoadSpellGroupCache(uint } for (auto row : results) { - spell_group_cache[std::stoul(row[0])].push_back(static_cast(std::stoul(row[1]))); + spell_group_cache[Strings::ToUnsignedInt(row[0])].push_back(static_cast(Strings::ToUnsignedInt(row[1]))); } return spell_group_cache; @@ -5758,7 +5784,7 @@ bool Client::SpellGlobalCheck(uint16 spell_id, uint32 character_id) { row = results.begin(); std::string global_value = row[0]; if (Strings::IsNumber(global_value) && Strings::IsNumber(spell_global_value)) { - if (std::stoi(global_value) >= std::stoi(spell_global_value)) { + if (Strings::ToInt(global_value) >= Strings::ToInt(spell_global_value)) { return true; // If value is greater than or equal to spell global value, allow scribing. } } else { @@ -5812,7 +5838,7 @@ bool Client::SpellBucketCheck(uint16 spell_id, uint32 character_id) { auto bucket_value = DataBucket::GetData(new_bucket_name); if (!bucket_value.empty()) { if (Strings::IsNumber(bucket_value) && Strings::IsNumber(spell_bucket_value)) { - if (std::stoi(bucket_value) >= std::stoi(spell_bucket_value)) { + if (Strings::ToInt(bucket_value) >= Strings::ToInt(spell_bucket_value)) { return true; // If value is greater than or equal to spell bucket value, allow scribing. } } else { @@ -5831,7 +5857,7 @@ bool Client::SpellBucketCheck(uint16 spell_id, uint32 character_id) { bucket_value = DataBucket::GetData(old_bucket_name); if (!bucket_value.empty()) { if (Strings::IsNumber(bucket_value) && Strings::IsNumber(spell_bucket_value)) { - if (std::stoi(bucket_value) >= std::stoi(spell_bucket_value)) { + if (Strings::ToInt(bucket_value) >= Strings::ToInt(spell_bucket_value)) { return true; // If value is greater than or equal to spell bucket value, allow scribing. } } else { @@ -5848,7 +5874,7 @@ bool Client::SpellBucketCheck(uint16 spell_id, uint32 character_id) { int16 Mob::GetBuffSlotFromType(uint16 type) { uint32 buff_count = GetMaxTotalSlots(); for (int i = 0; i < buff_count; i++) { - if (buffs[i].spellid != SPELL_UNKNOWN) { + if (IsValidSpell(buffs[i].spellid)) { for (int j = 0; j < EFFECT_COUNT; j++) { if (spells[buffs[i].spellid].effect_id[j] == type ) return i; @@ -5860,16 +5886,16 @@ int16 Mob::GetBuffSlotFromType(uint16 type) { uint16 Mob::GetSpellIDFromSlot(uint8 slot) { - if (buffs[slot].spellid != SPELL_UNKNOWN) + if (IsValidSpell(buffs[slot].spellid)) { return buffs[slot].spellid; + } return 0; } bool Mob::FindType(uint16 type, bool bOffensive, uint16 threshold) { int buff_count = GetMaxTotalSlots(); for (int i = 0; i < buff_count; i++) { - if (buffs[i].spellid != SPELL_UNKNOWN) { - + if (IsValidSpell(buffs[i].spellid)) { for (int j = 0; j < EFFECT_COUNT; j++) { // adjustments necessary for offensive npc casting behavior if (bOffensive) { @@ -5904,7 +5930,7 @@ bool Mob::IsCombatProc(uint16 spell_id) { return false; } - if (spell_id == SPELL_UNKNOWN) { + if (!IsValidSpell(spell_id)) { return(false); } /* @@ -5919,7 +5945,7 @@ bool Mob::IsCombatProc(uint16 spell_id) { } } - if (IsClient() || IsBot()) { + if (IsOfClientBot()) { for (int i = 0; i < MAX_AA_PROCS; i += 4) { if (aabonuses.SpellProc[i + 1] == spell_id || aabonuses.RangedProc[i + 1] == spell_id || @@ -5932,13 +5958,13 @@ bool Mob::IsCombatProc(uint16 spell_id) { } bool Mob::AddProcToWeapon(uint16 spell_id, bool bPerma, uint16 iChance, uint16 base_spell_id, int level_override, uint32 proc_reuse_time) { - if(spell_id == SPELL_UNKNOWN) + if(!IsValidSpell(spell_id)) return(false); int i; if (bPerma) { for (i = 0; i < MAX_PROCS; i++) { - if (PermaProcs[i].spellID == SPELL_UNKNOWN) { + if (!IsValidSpell(PermaProcs[i].spellID)) { PermaProcs[i].spellID = spell_id; PermaProcs[i].chance = iChance; PermaProcs[i].base_spellID = base_spell_id; @@ -5970,7 +5996,7 @@ bool Mob::AddProcToWeapon(uint16 spell_id, bool bPerma, uint16 iChance, uint16 b // Find a slot and use it as normal. for (i = 0; i < MAX_PROCS; i++) { - if (SpellProcs[i].spellID == SPELL_UNKNOWN) { + if (!IsValidSpell(SpellProcs[i].spellID)) { SpellProcs[i].spellID = spell_id; SpellProcs[i].chance = iChance; SpellProcs[i].base_spellID = base_spell_id;; @@ -6001,12 +6027,12 @@ bool Mob::RemoveProcFromWeapon(uint16 spell_id, bool bAll) { bool Mob::AddDefensiveProc(uint16 spell_id, uint16 iChance, uint16 base_spell_id, uint32 proc_reuse_time) { - if(spell_id == SPELL_UNKNOWN) + if(!IsValidSpell(spell_id)) return(false); int i; for (i = 0; i < MAX_PROCS; i++) { - if (DefensiveProcs[i].spellID == SPELL_UNKNOWN) { + if (!IsValidSpell(DefensiveProcs[i].spellID)) { DefensiveProcs[i].spellID = spell_id; DefensiveProcs[i].chance = iChance; DefensiveProcs[i].base_spellID = base_spell_id; @@ -6035,12 +6061,12 @@ bool Mob::RemoveDefensiveProc(uint16 spell_id, bool bAll) bool Mob::AddRangedProc(uint16 spell_id, uint16 iChance, uint16 base_spell_id, uint32 proc_reuse_time) { - if(spell_id == SPELL_UNKNOWN) + if(!IsValidSpell(spell_id)) return(false); int i; for (i = 0; i < MAX_PROCS; i++) { - if (RangedProcs[i].spellID == SPELL_UNKNOWN) { + if (!IsValidSpell(RangedProcs[i].spellID)) { RangedProcs[i].spellID = spell_id; RangedProcs[i].chance = iChance; RangedProcs[i].base_spellID = base_spell_id; @@ -6071,17 +6097,16 @@ bool Mob::RemoveRangedProc(uint16 spell_id, bool bAll) // behavior should be used. bool Mob::UseBardSpellLogic(uint16 spell_id, int slot) { - if(spell_id == SPELL_UNKNOWN) + if (!IsValidSpell(spell_id)) { spell_id = casting_spell_id; - - if(slot == -1) + } + if (slot == -1) { slot = static_cast(casting_spell_slot); - + } // should we treat this as a bard singing? return ( - spell_id != 0 && - spell_id != SPELL_UNKNOWN && + IsValidSpell(spell_id) && slot != -1 && GetClass() == BARD && slot <= EQ::spells::SPELL_GEM_COUNT && @@ -6177,7 +6202,7 @@ void Mob::SendPetBuffsToClient() for(int buffslot = 0; buffslot < MaxSlots; buffslot++) { - if(buffs[buffslot].spellid != SPELL_UNKNOWN) { + if (IsValidSpell(buffs[buffslot].spellid)) { pbs->spellid[buffslot] = buffs[buffslot].spellid; pbs->ticsremaining[buffslot] = buffs[buffslot].ticsremaining; PetBuffCount++; @@ -6209,7 +6234,7 @@ EQApplicationPacket *Mob::MakeBuffsPacket(bool for_target) uint32 buff_count = for_target ? GetMaxBuffSlots() : GetMaxTotalSlots(); for(int i = 0; i < buff_count; ++i) { - if(buffs[i].spellid != SPELL_UNKNOWN) + if (IsValidSpell(buffs[i].spellid)) { ++count; } @@ -6242,7 +6267,7 @@ EQApplicationPacket *Mob::MakeBuffsPacket(bool for_target) uint32 index = 0; for(int i = 0; i < buff_count; ++i) { - if(buffs[i].spellid != SPELL_UNKNOWN) + if (IsValidSpell(buffs[i].spellid)) { buff->entries[index].buff_slot = i; buff->entries[index].spell_id = buffs[i].spellid; @@ -6299,7 +6324,6 @@ void Client::InitializeBuffSlots() buffs[x].spellid = SPELL_UNKNOWN; buffs[x].UpdateClient = false; } - current_buff_count = 0; } void Client::UninitializeBuffSlots() @@ -6315,7 +6339,6 @@ void NPC::InitializeBuffSlots() buffs[x].spellid = SPELL_UNKNOWN; buffs[x].UpdateClient = false; } - current_buff_count = 0; } void NPC::UninitializeBuffSlots() @@ -6342,9 +6365,9 @@ void Client::SendSpellAnim(uint16 target_id, uint16 spell_id) entity_list.QueueCloseClients(this, &app, false, RuleI(Range, SpellParticles)); } -void Client::SendItemRecastTimer(int32 recast_type, uint32 recast_delay) +void Client::SendItemRecastTimer(int32 recast_type, uint32 recast_delay, bool in_ignore_casting_requirement) { - if (recast_type == -1) { + if (recast_type == RECAST_TYPE_UNLINKED_ITEM) { return; } @@ -6357,6 +6380,7 @@ void Client::SendItemRecastTimer(int32 recast_type, uint32 recast_delay) ItemRecastDelay_Struct *ird = (ItemRecastDelay_Struct *)outapp->pBuffer; ird->recast_delay = recast_delay; ird->recast_type = static_cast(recast_type); + ird->ignore_casting_requirement = in_ignore_casting_requirement; //True allows reset of item cast timers QueuePacket(outapp); safe_delete(outapp); } @@ -6369,10 +6393,12 @@ void Client::SetItemRecastTimer(int32 spell_id, uint32 inventory_slot) int recast_delay = 0; int recast_type = 0; bool from_augment = false; + int item_casting = 0; if (!item) { return; } + item_casting = item->GetItem()->ID; //Check primary item. if (item->GetItem()->RecastDelay > 0) { @@ -6396,6 +6422,7 @@ void Client::SetItemRecastTimer(int32 spell_id, uint32 inventory_slot) recast_delay = aug_i->GetItem()->RecastDelay; recast_type = aug_i->GetItem()->RecastType; from_augment = true; + item_casting = aug_i->GetItem()->ID; break; } } @@ -6410,13 +6437,20 @@ void Client::SetItemRecastTimer(int32 spell_id, uint32 inventory_slot) if (recast_delay > 0) { - GetPTimers().Start((pTimerItemStart + recast_type), static_cast(recast_delay)); - if (recast_type != -1) { - database.UpdateItemRecastTimestamps( + if (recast_type != RECAST_TYPE_UNLINKED_ITEM) { + GetPTimers().Start((pTimerItemStart + recast_type), static_cast(recast_delay)); + database.UpdateItemRecast( CharacterID(), recast_type, GetPTimers().Get(pTimerItemStart + recast_type)->GetReadyTimestamp() ); + } else if (recast_type == RECAST_TYPE_UNLINKED_ITEM) { + GetPTimers().Start((pTimerNegativeItemReuse * item_casting), static_cast(recast_delay)); + database.UpdateItemRecast( + CharacterID(), + item_casting, + GetPTimers().Get(pTimerNegativeItemReuse * item_casting)->GetReadyTimestamp() + ); } if (!from_augment) { @@ -6425,12 +6459,32 @@ void Client::SetItemRecastTimer(int32 spell_id, uint32 inventory_slot) } } +void Client::DeleteItemRecastTimer(uint32 item_id) +{ + const auto* d = database.GetItem(item_id); + + if (!d) { + return; + } + + const auto recast_type = d->RecastType != RECAST_TYPE_UNLINKED_ITEM ? d->RecastType : item_id; + const int timer_id = d->RecastType != RECAST_TYPE_UNLINKED_ITEM ? (pTimerItemStart + recast_type) : (pTimerNegativeItemReuse * item_id); + + database.DeleteItemRecast(CharacterID(), recast_type); + GetPTimers().Clear(&database, timer_id); + + if (recast_type != RECAST_TYPE_UNLINKED_ITEM) { + SendItemRecastTimer(recast_type, 1, true); + } +} + bool Client::HasItemRecastTimer(int32 spell_id, uint32 inventory_slot) { EQ::ItemInstance *item = CastToClient()->GetInv().GetItem(inventory_slot); int recast_delay = 0; int recast_type = 0; + int item_id = 0; bool from_augment = false; if (!item) { @@ -6445,6 +6499,7 @@ bool Client::HasItemRecastTimer(int32 spell_id, uint32 inventory_slot) if (item->GetItem()->RecastDelay > 0) { recast_type = item->GetItem()->RecastType; recast_delay = item->GetItem()->RecastDelay; + item_id = item->GetItem()->ID; } //Check augmenent else { @@ -6463,6 +6518,7 @@ bool Client::HasItemRecastTimer(int32 spell_id, uint32 inventory_slot) if (aug_i->GetItem() && aug_i->GetItem()->RecastDelay > 0) { recast_delay = aug_i->GetItem()->RecastDelay; recast_type = aug_i->GetItem()->RecastType; + item_id = aug_i->GetItem()->ID; } break; } @@ -6473,7 +6529,9 @@ bool Client::HasItemRecastTimer(int32 spell_id, uint32 inventory_slot) return false; } //if time is not expired, then it exists and therefore we have a recast on this item. - if (!CastToClient()->GetPTimers().Expired(&database, (pTimerItemStart + recast_type), false)) { + if (recast_type != RECAST_TYPE_UNLINKED_ITEM && !CastToClient()->GetPTimers().Expired(&database, (pTimerItemStart + recast_type), false)) { + return true; + } else if (recast_type == RECAST_TYPE_UNLINKED_ITEM && !CastToClient()->GetPTimers().Expired(&database, (pTimerNegativeItemReuse * item_id), false)) { return true; } @@ -6898,10 +6956,13 @@ bool Mob::CheckItemRaceClassDietyRestrictionsOnCast(uint32 inventory_slot) { if (itm && itm->GetItem()->Classes != 65535) { if ((itm->GetItem()->Click.Type == EQ::item::ItemEffectEquipClick) && !(itm->GetItem()->Classes & bitmask)) { if (CastToClient()->ClientVersion() < EQ::versions::ClientVersion::SoF) { - // They are casting a spell from an item that requires equipping but shouldn't let them equip it - LogError("HACKER: [{}] (account: [{}]) attempted to click an equip-only effect on item [{}] (id: [{}]) which they shouldn't be able to equip!", - CastToClient()->GetCleanName(), CastToClient()->AccountName(), itm->GetItem()->Name, itm->GetItem()->ID); - database.SetHackerFlag(CastToClient()->AccountName(), CastToClient()->GetCleanName(), "Clicking equip-only item with an invalid class"); + std::string message = fmt::format( + "Attempted to click an equip-only effect on item_name [{}] item_id [{}] which they shouldn't be able to equip!", + itm->GetItem()->Name, + itm->GetItem()->ID + ); + + RecordPlayerEventLogWithClient(CastToClient(), PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); } else { MessageString(Chat::Red, MUST_EQUIP_ITEM); @@ -6910,10 +6971,13 @@ bool Mob::CheckItemRaceClassDietyRestrictionsOnCast(uint32 inventory_slot) { } if ((itm->GetItem()->Click.Type == EQ::item::ItemEffectClick2) && !(itm->GetItem()->Classes & bitmask)) { if (CastToClient()->ClientVersion() < EQ::versions::ClientVersion::SoF) { - // They are casting a spell from an item that they don't meet the race/class requirements to cast - LogError("HACKER: [{}] (account: [{}]) attempted to click a race/class restricted effect on item [{}] (id: [{}]) which they shouldn't be able to click!", - CastToClient()->GetCleanName(), CastToClient()->AccountName(), itm->GetItem()->Name, itm->GetItem()->ID); - database.SetHackerFlag(CastToClient()->AccountName(), CastToClient()->GetCleanName(), "Clicking race/class restricted item with an invalid class"); + std::string message = fmt::format( + "Attempted to click a race/class restricted effect on item_name [{}] item_id [{}] which they shouldn't be able to click!", + itm->GetItem()->Name, + itm->GetItem()->ID + ); + + RecordPlayerEventLogWithClient(CastToClient(), PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); } else { if (CastToClient()->ClientVersion() >= EQ::versions::ClientVersion::RoF) @@ -6931,9 +6995,13 @@ bool Mob::CheckItemRaceClassDietyRestrictionsOnCast(uint32 inventory_slot) { } if (itm && (itm->GetItem()->Click.Type == EQ::item::ItemEffectEquipClick) && inventory_slot > EQ::invslot::EQUIPMENT_END) { if (CastToClient()->ClientVersion() < EQ::versions::ClientVersion::SoF) { - // They are attempting to cast a must equip clicky without having it equipped - LogError("HACKER: [{}] (account: [{}]) attempted to click an equip-only effect on item [{}] (id: [{}]) without equiping it!", CastToClient()->GetCleanName(), CastToClient()->AccountName(), itm->GetItem()->Name, itm->GetItem()->ID); - database.SetHackerFlag(CastToClient()->AccountName(), CastToClient()->GetCleanName(), "Clicking equip-only item without equiping it"); + std::string message = fmt::format( + "Attempted to click an equip-only effect on item_name [{}] item_id [{}] without equipping it!", + itm->GetItem()->Name, + itm->GetItem()->ID + ); + + RecordPlayerEventLogWithClient(CastToClient(), PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message}); } else { MessageString(Chat::Red, MUST_EQUIP_ITEM); @@ -6959,9 +7027,28 @@ void Mob::SetHP(int64 hp) return; } - if (combat_record.InCombat()) { - combat_record.ProcessHPEvent(hp, current_hp); + if (m_combat_record.InCombat()) { + m_combat_record.ProcessHPEvent(hp, current_hp); } current_hp = hp; } + +void Mob::DrawDebugCoordinateNode(std::string node_name, const glm::vec4 vec) +{ + NPC *node = nullptr; + for (const auto &n: entity_list.GetNPCList()) { + if (n.second->GetCleanName() == node_name) { + node = n.second; + break; + } + } + if (!node) { + node = NPC::SpawnNodeNPC(node_name, "", GetPosition()); + } +} + +const CombatRecord &Mob::GetCombatRecord() const +{ + return m_combat_record; +} diff --git a/zone/string_ids.h b/zone/string_ids.h index 8f44cb48c..cc3e1bad7 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -362,6 +362,7 @@ #define PETITION_NO_DELETE 5053 //You do not have a petition in the queue. #define PETITION_DELETED 5054 //Your petition was successfully deleted. #define ALREADY_IN_RAID 5060 //%1 is already in a raid. +#define ALREADY_IN_YOUR_RAID 5077 //%1 is already in your raid. #define GAIN_RAIDEXP 5085 //You gained raid experience! #define DUNGEON_SEALED 5141 //The gateway to the dungeon is sealed off to you. Perhaps you would be able to enter if you needed to adventure there. #define ADVENTURE_COMPLETE 5147 //You received %1 points for successfully completing the adventure. @@ -383,8 +384,9 @@ #define FORAGE_MASTERY 6012 //Your forage mastery has enabled you to find something else! #define GUILD_BANK_CANNOT_DEPOSIT 6097 // Cannot deposit this item. Containers must be empty, and only one of each LORE and no NO TRADE or TEMPORARY items may be deposited. #define GUILD_BANK_FULL 6098 // There is no more room in the Guild Bank. -#define GUILD_BANK_TRANSFERRED 6100 // '%1' transferred to Guild Bank from Deposits. -#define GUILD_BANK_EMPTY_HANDS 6108 // You must empty your hands to withdraw from the Guild Bank. +#define GUILD_BANK_TRANSFERRED 6100 // '%1' transferred to Guild Bank from Deposits. +#define GUILD_BANK_EMPTY_HANDS 6108 // You must empty your hands to withdraw from the Guild Bank. +#define TRADESKILL_COMBINE_LORE 6199 // Combine would result in a LORE item (%1) you already possess. #define TRANSFORM_FAILED 6326 //This mold cannot be applied to your %1. #define TRANSFORM_COMPLETE 6327 //You have successfully transformed your %1. #define DETRANSFORM_FAILED 6341 //%1 has no transformation that can be removed. diff --git a/zone/task_client_state.cpp b/zone/task_client_state.cpp index ca7456f04..fefeabab7 100644 --- a/zone/task_client_state.cpp +++ b/zone/task_client_state.cpp @@ -14,6 +14,7 @@ #include "worldserver.h" #include "dynamic_zone.h" #include "string_ids.h" +#include "../common/events/player_event_logs.h" #define EBON_CRYSTAL 40902 #define RADIANT_CRYSTAL 40903 @@ -564,17 +565,33 @@ int ClientTaskState::UpdateTasks(Client* client, const TaskUpdateFilter& filter, if (CanUpdate(client, filter, client_task.task_id, activity, client_activity)) { - auto args = fmt::format("{} {} {}", count, client_activity.activity_id, client_task.task_id); - if (parse->EventPlayer(EVENT_TASK_BEFORE_UPDATE, client, args, 0) != 0) - { - LogTasks("client [{}] task [{}]-[{}] update prevented by quest", - client->GetName(), client_task.task_id, client_activity.activity_id); + if (parse->PlayerHasQuestSub(EVENT_TASK_BEFORE_UPDATE)) { + const auto& export_string = fmt::format( + "{} {} {}", + count, + client_activity.activity_id, + client_task.task_id + ); - continue; + if (parse->EventPlayer(EVENT_TASK_BEFORE_UPDATE, client, export_string, 0) != 0) { + LogTasks( + "client [{}] task [{}]-[{}] update prevented by quest", + client->GetName(), + client_task.task_id, + client_activity.activity_id + ); + + continue; + } } - LogTasks("client [{}] task [{}] activity [{}] increment [{}]", - client->GetName(), client_task.task_id, client_activity.activity_id, count); + LogTasks( + "client [{}] task [{}] activity [{}] increment [{}]", + client->GetName(), + client_task.task_id, + client_activity.activity_id, + count + ); int updated = IncrementDoneCount(client, task, client_task.slot, client_activity.activity_id, count); max_updated = std::max(max_updated, updated); @@ -853,13 +870,16 @@ int ClientTaskState::IncrementDoneCount( info->activity[activity_id].done_count += count; if (!ignore_quest_update) { - std::string export_string = fmt::format( - "{} {} {}", - info->activity[activity_id].done_count, - info->activity[activity_id].activity_id, - info->task_id - ); - parse->EventPlayer(EVENT_TASK_UPDATE, client, export_string, 0); + if (parse->PlayerHasQuestSub(EVENT_TASK_UPDATE)) { + const auto& export_string = fmt::format( + "{} {} {}", + info->activity[activity_id].done_count, + info->activity[activity_id].activity_id, + info->task_id + ); + + parse->EventPlayer(EVENT_TASK_UPDATE, client, export_string, 0); + } } if (task_data->type != TaskType::Shared) { @@ -895,12 +915,15 @@ int ClientTaskState::IncrementDoneCount( task_manager->SendSingleActiveTaskToClient(client, *info, task_complete, false); if (!ignore_quest_update) { - std::string export_string = fmt::format( - "{} {}", - info->task_id, - info->activity[activity_id].activity_id - ); - parse->EventPlayer(EVENT_TASK_STAGE_COMPLETE, client, export_string, 0); + if (parse->PlayerHasQuestSub(EVENT_TASK_STAGE_COMPLETE)) { + const auto& export_string = fmt::format( + "{} {}", + info->task_id, + info->activity[activity_id].activity_id + ); + + parse->EventPlayer(EVENT_TASK_STAGE_COMPLETE, client, export_string, 0); + } } /* QS: PlayerLogTaskUpdates :: Update */ if (RuleB(QueryServ, PlayerLogTaskUpdates)) { @@ -925,6 +948,16 @@ int ClientTaskState::IncrementDoneCount( int event_res = DispatchEventTaskComplete(client, *info, activity_id); + if (player_event_logs.IsEventEnabled(PlayerEvent::TASK_COMPLETE)) { + auto e = PlayerEvent::TaskCompleteEvent{ + .task_id = static_cast(info->task_id), + .task_name = task_manager->GetTaskName(static_cast(info->task_id)), + .activity_id = static_cast(info->activity[activity_id].activity_id), + .done_count = static_cast(info->activity[activity_id].done_count) + }; + RecordPlayerEventLogWithClient(client, PlayerEvent::TASK_COMPLETE, e); + } + /* QS: PlayerLogTaskUpdates :: Complete */ if (RuleB(QueryServ, PlayerLogTaskUpdates)) { std::string event_desc = StringFormat( @@ -963,6 +996,16 @@ int ClientTaskState::IncrementDoneCount( activity_id, task_index ); + + if (player_event_logs.IsEventEnabled(PlayerEvent::TASK_UPDATE)) { + auto e = PlayerEvent::TaskUpdateEvent{ + .task_id = static_cast(info->task_id), + .task_name = task_manager->GetTaskName(static_cast(info->task_id)), + .activity_id = static_cast(info->activity[activity_id].activity_id), + .done_count = static_cast(info->activity[activity_id].done_count) + }; + RecordPlayerEventLogWithClient(client, PlayerEvent::TASK_UPDATE, e); + } } task_manager->SaveClientState(client, this); @@ -972,13 +1015,18 @@ int ClientTaskState::IncrementDoneCount( int ClientTaskState::DispatchEventTaskComplete(Client* client, ClientTaskInformation& info, int activity_id) { - std::string export_string = fmt::format( - "{} {} {}", - info.activity[activity_id].done_count, - info.activity[activity_id].activity_id, - info.task_id - ); - return parse->EventPlayer(EVENT_TASK_COMPLETE, client, export_string, 0); + if (parse->PlayerHasQuestSub(EVENT_TASK_COMPLETE)) { + const auto& export_string = fmt::format( + "{} {} {}", + info.activity[activity_id].done_count, + info.activity[activity_id].activity_id, + info.task_id + ); + + return parse->EventPlayer(EVENT_TASK_COMPLETE, client, export_string, 0); + } + + return 0; } void ClientTaskState::RewardTask(Client *c, const TaskInformation *ti, ClientTaskInformation& client_task) @@ -1000,12 +1048,12 @@ void ClientTaskState::RewardTask(Client *c, const TaskInformation *ti, ClientTas for (const auto &i: Strings::Split(ti->reward_id_list, "|")) { // handle charges int16 charges = -1; - uint32 item_id = Strings::IsNumber(i) ? std::stoi(i) : 0; + uint32 item_id = Strings::IsNumber(i) ? Strings::ToInt(i) : 0; if (Strings::Contains(i, ",")) { auto s = Strings::Split(i, ","); if (!s.empty() && s.size() == 2) { - item_id = Strings::IsNumber(s[0]) ? std::stoi(s[0]) : 0; - charges = Strings::IsNumber(s[1]) ? std::stoi(s[1]) : 0; + item_id = Strings::IsNumber(s[0]) ? Strings::ToInt(s[0]) : 0; + charges = Strings::IsNumber(s[1]) ? Strings::ToInt(s[1]) : 0; } } @@ -1063,7 +1111,7 @@ void ClientTaskState::RewardTask(Client *c, const TaskInformation *ti, ClientTas if (pos_reward > 100 && pos_reward < 25700) { uint8 max_level = pos_reward / 100; uint8 exp_percent = pos_reward - (max_level * 100); - c->AddLevelBasedExp(exp_percent, max_level); + c->AddLevelBasedExp(exp_percent, max_level, RuleB(TaskSystem, ExpRewardsIgnoreLevelBasedEXPMods)); } } @@ -1072,6 +1120,16 @@ void ClientTaskState::RewardTask(Client *c, const TaskInformation *ti, ClientTas c->AddCrystals(ti->reward_points, 0); } else if (ti->reward_point_type == static_cast(zone->GetCurrencyID(EBON_CRYSTAL))) { c->AddCrystals(0, ti->reward_points); + } else { + for (const auto& ac : zone->AlternateCurrencies) { + if (ti->reward_point_type == ac.id) { + const EQ::ItemData *item = database.GetItem(ac.item_id); + if (item) { + c->AddAlternateCurrencyValue(ti->reward_point_type, ti->reward_points); + c->Message(Chat::Yellow, fmt::format("You have received ({}) {}!", ti->reward_points, item->Name).c_str()); + } + } + } } } } @@ -2119,11 +2177,36 @@ void ClientTaskState::AcceptNewTask( client->MessageString(Chat::DefaultText, YOU_ASSIGNED_TASK, task->title.c_str()); task_manager->SaveClientState(client, this); - std::string export_string = std::to_string(task_id); NPC *npc = entity_list.GetID(npc_type_id)->CastToNPC(); if (npc) { - parse->EventNPC(EVENT_TASK_ACCEPTED, npc, client, export_string, 0); + if (player_event_logs.IsEventEnabled(PlayerEvent::TASK_ACCEPT)) { + auto e = PlayerEvent::TaskAcceptEvent{ + .npc_id = static_cast(npc_type_id), + .npc_name = npc->GetCleanName(), + .task_id = static_cast(task_id), + .task_name = task_manager->GetTaskName(static_cast(task_id)), + }; + RecordPlayerEventLogWithClient(client, PlayerEvent::TASK_ACCEPT, e); + } + + if (parse->HasQuestSub(npc->GetNPCTypeID(), EVENT_TASK_ACCEPTED)) { + parse->EventNPC(EVENT_TASK_ACCEPTED, npc, client, std::to_string(task_id), 0); + } + } else { + if (player_event_logs.IsEventEnabled(PlayerEvent::TASK_ACCEPT)) { + auto e = PlayerEvent::TaskAcceptEvent{ + .npc_id = 0, + .npc_name = "No NPC", + .task_id = static_cast(task_id), + .task_name = task_manager->GetTaskName(static_cast(task_id)), + }; + RecordPlayerEventLogWithClient(client, PlayerEvent::TASK_ACCEPT, e); + } + } + + if (parse->PlayerHasQuestSub(EVENT_TASK_ACCEPTED)) { + parse->EventPlayer(EVENT_TASK_ACCEPTED, client, std::to_string(task_id), 0); } } diff --git a/zone/task_manager.cpp b/zone/task_manager.cpp index 2d61f6b7d..0711b0977 100644 --- a/zone/task_manager.cpp +++ b/zone/task_manager.cpp @@ -199,9 +199,9 @@ bool TaskManager::LoadTasks(int single_task) ad->target_name = a.target_name; ad->item_list = a.item_list; ad->skill_list = a.skill_list; - ad->skill_id = Strings::IsNumber(a.skill_list) ? std::stoi(a.skill_list) : 0; // for older clients + ad->skill_id = Strings::IsNumber(a.skill_list) ? Strings::ToInt(a.skill_list) : 0; // for older clients ad->spell_list = a.spell_list; - ad->spell_id = Strings::IsNumber(a.spell_list) ? std::stoi(a.spell_list) : 0; // for older clients + ad->spell_id = Strings::IsNumber(a.spell_list) ? Strings::ToInt(a.spell_list) : 0; // for older clients ad->description_override = a.description_override; ad->npc_match_list = a.npc_match_list; ad->item_id_list = a.item_id_list; @@ -233,7 +233,7 @@ bool TaskManager::LoadTasks(int single_task) for (auto &&e : zones) { if (Strings::IsNumber(e)) { - ad->zone_ids.push_back(std::stoi(e)); + ad->zone_ids.push_back(Strings::ToInt(e)); } } @@ -700,15 +700,15 @@ void TaskManager::SharedTaskSelector(Client* client, Mob* mob, const std::vector if (request.group_type != SharedTaskRequestGroupType::Solo) { auto shared_task_members = SharedTaskMembersRepository::GetWhere( database, - fmt::format("character_id IN ({}) LIMIT 1", fmt::join(request.character_ids, ","))); + fmt::format("character_id IN ({}) LIMIT 1", Strings::Join(request.character_ids, ","))); if (!shared_task_members.empty()) { validation_failed = true; auto it = std::find_if(request.members.begin(), request.members.end(), - [&](const SharedTaskMember& member) { - return member.character_id == shared_task_members.front().character_id; - }); + [&](const SharedTaskMember& member) { + return member.character_id == shared_task_members.front().character_id; + }); if (it != request.members.end()) { if (request.group_type == SharedTaskRequestGroupType::Group) { @@ -761,14 +761,14 @@ bool TaskManager::CanOfferSharedTask(int task_id, const SharedTaskRequest& reque if (task->min_level > 0 && request.lowest_level < task->min_level) { LogTasksDetail("lowest level [{}] is below task [{}] min level [{}]", - request.lowest_level, task_id, task->min_level); + request.lowest_level, task_id, task->min_level); return false; } if (task->max_level > 0 && request.highest_level > task->max_level) { LogTasksDetail("highest level [{}] exceeds task [{}] max level [{}]", - request.highest_level, task_id, task->max_level); + request.highest_level, task_id, task->max_level); return false; } @@ -1154,13 +1154,17 @@ void TaskManager::SendActiveTaskDescription( + sizeof(TaskDescriptionData1_Struct) + t->description.length() + 1 + sizeof(TaskDescriptionData2_Struct) + 1 + sizeof(TaskDescriptionTrailer_Struct); + std::string reward = t->reward; + bool is_don_reward = (t->reward_point_type == ALT_CURRENCY_ID_RADIANT || + t->reward_point_type == ALT_CURRENCY_ID_EBON); + // If there is an item make the reward text into a link to the item (only the first item if a list // is specified). I have been unable to get multiple item links to work. // if (!t->reward_id_list.empty() && t->item_link.empty()) { auto items = Strings::Split(t->reward_id_list, "|"); auto item = items.front(); - int item_id = Strings::IsNumber(items.front()) ? std::stoi(items.front()) : 0; + int item_id = Strings::IsNumber(items.front()) ? Strings::ToInt(items.front()) : 0; if (item_id) { const EQ::ItemData *reward_item = database.GetItem(item_id); @@ -1173,7 +1177,34 @@ void TaskManager::SendActiveTaskDescription( } } - packet_length += t->reward.length() + 1 + t->item_link.length() + 1; + // display alternate currency in reward window manually + // there may be a more formal packet structure for displaying this but this is what it is for + // now to have bare minimum support + if (t->reward_point_type > 0 && t->reward_points > 0 && !is_don_reward) { + for (const auto& ac : zone->AlternateCurrencies) { + if (t->reward_point_type == ac.id) { + const EQ::ItemData *item = database.GetItem(ac.item_id); + if (item) { + std::string currency_description = fmt::format( + "{} ({})", + item->Name, + t->reward_points + ); + + reward = currency_description; + + EQ::SayLinkEngine l; + l.SetLinkType(EQ::saylink::SayLinkItemData); + l.SetItemData(item); + l.SetTaskUse(); + l.SetProxyText(currency_description.c_str()); + t->item_link = l.GenerateLink(); + } + } + } + } + + packet_length += reward.length() + 1 + t->item_link.length() + 1; char *Ptr; TaskDescriptionHeader_Struct *task_description_header; @@ -1190,7 +1221,7 @@ void TaskManager::SendActiveTaskDescription( task_description_header->open_window = bring_up_task_journal; task_description_header->task_type = static_cast(t->type); - task_description_header->reward_type = t->reward_point_type; + task_description_header->reward_type = is_don_reward ? t->reward_point_type : 0; Ptr = (char *) task_description_header + sizeof(TaskDescriptionHeader_Struct); @@ -1224,16 +1255,17 @@ void TaskManager::SendActiveTaskDescription( // we actually have 2 strings here. One is max length 96 and not parsed for item links // We actually skipped past that string incorrectly before, so TODO: fix item link string - sprintf(Ptr, "%s", t->reward.c_str()); - Ptr += t->reward.length() + 1; + sprintf(Ptr, "%s", reward.c_str()); + Ptr += reward.length() + 1; // second string is parsed for item links sprintf(Ptr, "%s", t->item_link.c_str()); Ptr += t->item_link.length() + 1; tdt = (TaskDescriptionTrailer_Struct *) Ptr; + // shared tasks show radiant/ebon crystal reward, non-shared tasks show generic points - tdt->Points = t->reward_points; + tdt->Points = is_don_reward ? t->reward_points : 0; tdt->has_reward_selection = 0; // TODO: new rewards window @@ -1485,7 +1517,7 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *cts) auto results = database.QueryDatabase(query); if (results.Success()) { for (auto row = results.begin(); row != results.end(); ++row) { - int task_id = atoi(row[0]); + int task_id = Strings::ToInt(row[0]); cts->m_enabled_tasks.push_back(task_id); LogTasksDetail("Adding task_id [{}] to enabled tasks", task_id); } @@ -1720,7 +1752,7 @@ void TaskManager::SyncClientSharedTaskRemoveLocalIfNotExists(Client *c, ClientTa CharacterActivitiesRepository::DeleteWhere(database, delete_where); c->MessageString(Chat::Yellow, TaskStr::NO_LONGER_MEMBER_TITLE, - m_task_data[cts->m_active_shared_task.task_id].title.c_str()); + m_task_data[cts->m_active_shared_task.task_id].title.c_str()); // remove as active task if doesn't exist cts->m_active_shared_task = {}; @@ -1830,7 +1862,7 @@ bool TaskManager::IsActiveTaskComplete(ClientTaskInformation& client_task) for (int i = 0; i < task_data->activity_count; ++i) { if (client_task.activity[i].activity_state != ActivityCompleted && - !task_data->activity_information[i].optional) + !task_data->activity_information[i].optional) { return false; } diff --git a/zone/tasks.cpp b/zone/tasks.cpp index a7232e67c..114594482 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -96,9 +96,9 @@ void Client::SendTaskActivityComplete( void Client::SendTaskFailed(int task_id, int task_index, TaskType task_type) { - // 0x54eb - std::string export_string = fmt::format("{}", task_id); - parse->EventPlayer(EVENT_TASK_FAIL, this, export_string, 0); + if (parse->PlayerHasQuestSub(EVENT_TASK_FAIL)) { + parse->EventPlayer(EVENT_TASK_FAIL, this, std::to_string(task_id), 0); + } TaskActivityComplete_Struct *task_activity_complete; diff --git a/zone/titles.cpp b/zone/titles.cpp index 085243e33..bb4e185fc 100644 --- a/zone/titles.cpp +++ b/zone/titles.cpp @@ -47,20 +47,20 @@ bool TitleManager::LoadTitles() for (auto row : results) { TitleEntry title; - title.title_id = std::stoi(row[0]); - title.skill_id = (EQ::skills::SkillType) std::stoi(row[1]); - title.min_skill_value = std::stoi(row[2]); - title.max_skill_value = std::stoi(row[3]); - title.min_aa_points = std::stoi(row[4]); - title.max_aa_points = std::stoi(row[5]); - title.class_id = std::stoi(row[6]); - title.gender_id = std::stoi(row[7]); - title.character_id = std::stoi(row[8]); - title.status = std::stoi(row[9]); - title.item_id = std::stoi(row[10]); + title.title_id = Strings::ToInt(row[0]); + title.skill_id = (EQ::skills::SkillType) Strings::ToInt(row[1]); + title.min_skill_value = Strings::ToInt(row[2]); + title.max_skill_value = Strings::ToInt(row[3]); + title.min_aa_points = Strings::ToInt(row[4]); + title.max_aa_points = Strings::ToInt(row[5]); + title.class_id = Strings::ToInt(row[6]); + title.gender_id = Strings::ToInt(row[7]); + title.character_id = Strings::ToInt(row[8]); + title.status = Strings::ToInt(row[9]); + title.item_id = Strings::ToInt(row[10]); title.prefix = row[11]; title.suffix = row[12]; - title.titleset = std::stoi(row[13]); + title.titleset = Strings::ToInt(row[13]); titles.push_back(title); } @@ -93,18 +93,6 @@ EQApplicationPacket *TitleManager::MakeTitlesPacket(Client *client) return(outapp); } -int TitleManager::NumberOfAvailableTitles(Client *client) -{ - int count = 0; - for (const auto& title : titles) { - if (IsClientEligibleForTitle(client, title)) { - ++count; - } - } - - return count; -} - std::string TitleManager::GetPrefix(int title_id) { if (!title_id) { diff --git a/zone/titles.h b/zone/titles.h index 5e29e512c..b5e12de8f 100644 --- a/zone/titles.h +++ b/zone/titles.h @@ -51,7 +51,6 @@ public: EQApplicationPacket *MakeTitlesPacket(Client *client); std::string GetPrefix(int title_id); std::string GetSuffix(int title_id); - int NumberOfAvailableTitles(Client *client); bool IsClientEligibleForTitle(Client *client, TitleEntry title); bool IsNewAATitleAvailable(int aa_points, int class_id); bool IsNewTradeSkillTitleAvailable(int skill_id, int skill_value); diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index e782dfce5..2d8e03002 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -17,6 +17,7 @@ */ #include "../common/global_define.h" +#include "../common/events/player_event_logs.h" #include #include @@ -33,11 +34,14 @@ #include "string_ids.h" #include "titles.h" #include "zonedb.h" +#include "worldserver.h" #include "../common/repositories/char_recipe_list_repository.h" #include "../common/zone_store.h" #include "../common/repositories/tradeskill_recipe_repository.h" +#include "../common/repositories/tradeskill_recipe_entries_repository.h" extern QueryServ* QServ; +extern WorldServer worldserver; static const EQ::skills::SkillType TradeskillUnknown = EQ::skills::Skill1HBlunt; /* an arbitrary non-tradeskill */ @@ -59,7 +63,7 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme inst = user_inv.GetItem(in_augment->container_slot); if (inst) { const EQ::ItemData* item = inst->GetItem(); - if (item && inst->IsType(EQ::item::ItemClassBag) && item->BagType == EQ::item::BagTypeAugmentationSealer) { // We have found an appropriate inventory augmentation sealer + if (item && inst->IsType(EQ::item::ItemClassBag) && (item->BagType == EQ::item::BagTypeAugmentationSealer || item->BagType == RuleI(Inventory, AlternateAugmentationSealer))) { // We have found an appropriate inventory augmentation sealer container = inst; // Verify that no more than two items are in container to guarantee no inadvertant wipes. @@ -136,22 +140,30 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme if(aug) { std::vector args; args.push_back(aug); - parse->EventItem(EVENT_AUGMENT_ITEM, user, tobe_auged, nullptr, "", slot, &args); + + if (parse->ItemHasQuestSub(tobe_auged, EVENT_AUGMENT_ITEM)) { + parse->EventItem(EVENT_AUGMENT_ITEM, user, tobe_auged, nullptr, "", slot, &args); + } args.assign(1, tobe_auged); - parse->EventItem(EVENT_AUGMENT_INSERT, user, aug, nullptr, "", slot, &args); + + if (parse->ItemHasQuestSub(aug, EVENT_AUGMENT_INSERT)) { + parse->EventItem(EVENT_AUGMENT_INSERT, user, aug, nullptr, "", slot, &args); + } args.push_back(aug); - const auto export_string = fmt::format( - "{} {} {} {}", - tobe_auged->GetID(), - -1, - aug->GetID(), - slot - ); + if (parse->PlayerHasQuestSub(EVENT_AUGMENT_INSERT_CLIENT)) { + const auto& export_string = fmt::format( + "{} {} {} {}", + tobe_auged->GetID(), + -1, + aug->GetID(), + slot + ); - parse->EventPlayer(EVENT_AUGMENT_INSERT_CLIENT, user, export_string, 0, &args); + parse->EventPlayer(EVENT_AUGMENT_INSERT_CLIENT, user, export_string, 0, &args); + } } item_one_to_push = tobe_auged->Clone(); @@ -178,12 +190,17 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme } std::vector args; args.push_back(aug); - parse->EventItem(EVENT_UNAUGMENT_ITEM, user, tobe_auged, nullptr, "", slot, &args); + + if (parse->ItemHasQuestSub(tobe_auged, EVENT_UNAUGMENT_ITEM)) { + parse->EventItem(EVENT_UNAUGMENT_ITEM, user, tobe_auged, nullptr, "", slot, &args); + } args.assign(1, tobe_auged); args.push_back(&is_solvent); - parse->EventItem(EVENT_AUGMENT_REMOVE, user, aug, nullptr, "", slot, &args); + if (parse->ItemHasQuestSub(aug, EVENT_AUGMENT_REMOVE)) { + parse->EventItem(EVENT_AUGMENT_REMOVE, user, aug, nullptr, "", slot, &args); + } } if (is_solvent) { @@ -236,6 +253,9 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob { if (!user || !in_combine) { LogError("Client or NewCombine_Struct not set in Object::HandleCombine"); + auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); + user->QueuePacket(outapp); + safe_delete(outapp); return; } @@ -261,6 +281,9 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob Chat::Red, "Error: Server is not aware of the tradeskill container you are attempting to use" ); + auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); + user->QueuePacket(outapp); + safe_delete(outapp); return; } c_type = worldo->m_type; @@ -287,6 +310,9 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob if (!inst || !inst->IsType(EQ::item::ItemClassBag)) { user->Message(Chat::Red, "Error: Server does not recognize specified tradeskill container"); + auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); + user->QueuePacket(outapp); + safe_delete(outapp); return; } @@ -310,7 +336,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob inst->IsAttuned(), EQ::invslot::slotCursor, container->GetItem()->Icon, - atoi(container->GetItem()->IDFile + 2) + Strings::ToInt(container->GetItem()->IDFile + 2) ); user->MessageString(Chat::LightBlue, TRANSFORM_COMPLETE, inst->GetItem()->Name); @@ -356,11 +382,13 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob DBTradeskillRecipe_Struct spec; - if (parse->EventPlayer(EVENT_COMBINE, user, std::to_string(in_combine->container_slot), 0) == 1) { - auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); - user->QueuePacket(outapp); - safe_delete(outapp); - return; + if (parse->PlayerHasQuestSub(EVENT_COMBINE)) { + if (parse->EventPlayer(EVENT_COMBINE, user, std::to_string(in_combine->container_slot), 0) == 1) { + auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); + user->QueuePacket(outapp); + safe_delete(outapp); + return; + } } if (!content_db.GetTradeRecipe(container, c_type, some_id, user->CharacterID(), &spec)) { @@ -408,36 +436,60 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob if (spec.tradeskill == EQ::skills::SkillAlchemy) { if (user_pp.class_ != SHAMAN) { user->Message(Chat::Red, "This tradeskill can only be performed by a shaman."); + auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); + user->QueuePacket(outapp); + safe_delete(outapp); return; } else if (user_pp.level < MIN_LEVEL_ALCHEMY) { user->Message(Chat::Red, "You cannot perform alchemy until you reach level %i.", MIN_LEVEL_ALCHEMY); + auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); + user->QueuePacket(outapp); + safe_delete(outapp); return; } } else if (spec.tradeskill == EQ::skills::SkillTinkering) { if (user_pp.race != GNOME) { user->Message(Chat::Red, "Only gnomes can tinker."); + auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); + user->QueuePacket(outapp); + safe_delete(outapp); return; } } else if (spec.tradeskill == EQ::skills::SkillMakePoison) { if (user_pp.class_ != ROGUE) { user->Message(Chat::Red, "Only rogues can mix poisons."); + auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); + user->QueuePacket(outapp); + safe_delete(outapp); return; } } - // final check for any additional quest requirements .. "check_zone" in this case - exported as variable [validate_type] - std::string export_string = fmt::format("check_zone {}", zone->GetZoneID()); - if (parse->EventPlayer(EVENT_COMBINE_VALIDATE, user, export_string, spec.recipe_id) != 0) { - user->Message(Chat::Emote, "You cannot make this combine because the location requirement has not been met."); + // Check if Combine would result in Lore conflict + if (user->CheckTradeskillLoreConflict(spec.recipe_id)) { auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); user->QueuePacket(outapp); safe_delete(outapp); return; } + // final check for any additional quest requirements .. "check_zone" in this case - exported as variable [validate_type] + if (parse->PlayerHasQuestSub(EVENT_COMBINE_VALIDATE)) { + if (parse->EventPlayer(EVENT_COMBINE_VALIDATE, user, fmt::format("check_zone {}", zone->GetZoneID()), spec.recipe_id) != 0) { + user->Message( + Chat::Emote, + "You cannot make this combine because the location requirement has not been met." + ); + auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); + user->QueuePacket(outapp); + safe_delete(outapp); + return; + } + } + // Send acknowledgement packets to client auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); user->QueuePacket(outapp); @@ -487,9 +539,34 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob } if (success) { - parse->EventPlayer(EVENT_COMBINE_SUCCESS, user, spec.name, spec.recipe_id); - } else { - parse->EventPlayer(EVENT_COMBINE_FAILURE, user, spec.name, spec.recipe_id); + if (player_event_logs.IsEventEnabled(PlayerEvent::COMBINE_SUCCESS)) { + auto e = PlayerEvent::CombineEvent{ + .recipe_id = spec.recipe_id, + .recipe_name = spec.name, + .made_count = spec.madecount, + .tradeskill_id = (uint32) spec.tradeskill + }; + RecordPlayerEventLogWithClient(user, PlayerEvent::COMBINE_SUCCESS, e); + } + + if (parse->PlayerHasQuestSub(EVENT_COMBINE_SUCCESS)) { + parse->EventPlayer(EVENT_COMBINE_SUCCESS, user, spec.name, spec.recipe_id); + } + } + else { + if (player_event_logs.IsEventEnabled(PlayerEvent::COMBINE_FAILURE)) { + auto e = PlayerEvent::CombineEvent{ + .recipe_id = spec.recipe_id, + .recipe_name = spec.name, + .made_count = spec.madecount, + .tradeskill_id = (uint32) spec.tradeskill + }; + RecordPlayerEventLogWithClient(user, PlayerEvent::COMBINE_FAILURE, e); + } + + if (parse->PlayerHasQuestSub(EVENT_COMBINE_FAILURE)) { + parse->EventPlayer(EVENT_COMBINE_FAILURE, user, spec.name, spec.recipe_id); + } } } @@ -534,9 +611,9 @@ void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac } //pull the list of components - std::string query = StringFormat("SELECT tre.item_id, tre.componentcount " - "FROM tradeskill_recipe_entries AS tre " - "WHERE tre.componentcount > 0 AND tre.recipe_id = %u", + const auto query = fmt::format("SELECT item_id, componentcount " + "FROM tradeskill_recipe_entries " + "WHERE componentcount > 0 AND recipe_id = {}", rac->recipe_id); auto results = content_db.QueryDatabase(query); if (!results.Success()) { @@ -573,8 +650,8 @@ void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac uint8 needItemIndex = 0; for (auto row = results.begin(); row != results.end(); ++row, ++needItemIndex) { - uint32 item = (uint32)atoi(row[0]); - uint8 num = (uint8) atoi(row[1]); + uint32 item = (uint32)Strings::ToInt(row[0]); + uint8 num = (uint8) Strings::ToInt(row[1]); needcount += num; @@ -610,6 +687,13 @@ void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac return; } + // Check if Combine would result in Lore conflict + if (user->CheckTradeskillLoreConflict(rac->recipe_id)) { + user->QueuePacket(outapp); + safe_delete(outapp); + return; + } + //now we know they have everything... //remove all the items from the players inventory, with updates... @@ -664,9 +748,13 @@ void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac } if (success) { - parse->EventPlayer(EVENT_COMBINE_SUCCESS, user, spec.name, spec.recipe_id); + if (parse->PlayerHasQuestSub(EVENT_COMBINE_SUCCESS)) { + parse->EventPlayer(EVENT_COMBINE_SUCCESS, user, spec.name, spec.recipe_id); + } } else { - parse->EventPlayer(EVENT_COMBINE_FAILURE, user, spec.name, spec.recipe_id); + if (parse->PlayerHasQuestSub(EVENT_COMBINE_FAILURE)) { + parse->EventPlayer(EVENT_COMBINE_FAILURE, user, spec.name, spec.recipe_id); + } } } @@ -782,12 +870,12 @@ void Client::SendTradeskillSearchResults( continue; } - uint32 recipe_id = (uint32) atoi(row[0]); + uint32 recipe_id = (uint32) Strings::ToInt(row[0]); const char *name = row[1]; - uint32 trivial = (uint32) atoi(row[2]); - uint32 comp_count = (uint32) atoi(row[3]); - uint32 tradeskill = (uint16) atoi(row[4]); - uint32 must_learn = (uint16) atoi(row[5]); + uint32 trivial = (uint32) Strings::ToInt(row[2]); + uint32 comp_count = (uint32) Strings::ToInt(row[3]); + uint32 tradeskill = (uint16) Strings::ToInt(row[4]); + uint32 must_learn = (uint16) Strings::ToInt(row[5]); // Skip the recipes that exceed the threshold in skill difference @@ -884,9 +972,9 @@ void Client::SendTradeskillDetails(uint32 recipe_id) { if(row[2] == nullptr || row[3] == nullptr) continue; - uint32 item = (uint32)atoi(row[0]); - uint8 num = (uint8) atoi(row[1]); - uint32 icon = (uint32) atoi(row[2]); + uint32 item = (uint32)Strings::ToInt(row[0]); + uint8 num = (uint8) Strings::ToInt(row[1]); + uint32 icon = (uint32) Strings::ToInt(row[2]); const char *name = row[3]; len = strlen(name); @@ -1058,8 +1146,6 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) { const EQ::ItemData* item = nullptr; - chance = mod_tradeskill_chance(chance, spec); - if (((spec->tradeskill==75) || GetGM() || (chance > res)) || zone->random.Roll(aa_chance)) { success_modifier = 1; @@ -1196,8 +1282,6 @@ void Client::CheckIncreaseTradeskill(int16 bonusstat, int16 stat_modifier, float } } - chance_stage2 = mod_tradeskill_skillup(chance_stage2); - if (chance_stage2 > zone->random.Real(0, 99)) { //Only if stage1 and stage2 succeeded you get a skillup. SetSkill(tradeskill, current_raw_skill + 1); @@ -1306,7 +1390,7 @@ bool ZoneDatabase::GetTradeRecipe( uint32 index = 0; buf2 = ""; for (auto row = results.begin(); row != results.end(); ++row, ++index) { - uint32 recipeid = (uint32)atoi(row[0]); + uint32 recipeid = (uint32)Strings::ToInt(row[0]); if(first) { buf2 += StringFormat("%u", recipeid); first = false; @@ -1379,7 +1463,7 @@ bool ZoneDatabase::GetTradeRecipe( } auto row = results.begin(); - uint32 recipe_id = (uint32)atoi(row[0]); + uint32 recipe_id = (uint32)Strings::ToInt(row[0]); //Right here we verify that we actually have ALL of the tradeskill components.. //instead of part which is possible with experimentation. @@ -1410,7 +1494,7 @@ bool ZoneDatabase::GetTradeRecipe( if (!item) continue; - if (item->ID == atoi(row[0])) { + if (item->ID == Strings::ToInt(row[0])) { component_count++; } @@ -1418,11 +1502,11 @@ bool ZoneDatabase::GetTradeRecipe( "Component count loop [{}] item [{}] recipe component_count [{}]", component_count, item->ID, - atoi(row[1]) + Strings::ToInt(row[1]) ); } - if (component_count != atoi(row[1])) { + if (component_count != Strings::ToInt(row[1])) { return false; } } @@ -1487,14 +1571,14 @@ bool ZoneDatabase::GetTradeRecipe( auto row = results.begin(); - spec->tradeskill = (EQ::skills::SkillType) atoi(row[1]); - spec->skill_needed = (int16) atoi(row[2]); - spec->trivial = (uint16) atoi(row[3]); - spec->nofail = atoi(row[4]) ? true : false; - spec->replace_container = atoi(row[5]) ? true : false; + spec->tradeskill = (EQ::skills::SkillType) Strings::ToInt(row[1]); + spec->skill_needed = (int16) Strings::ToInt(row[2]); + spec->trivial = (uint16) Strings::ToInt(row[3]); + spec->nofail = Strings::ToInt(row[4]) ? true : false; + spec->replace_container = Strings::ToInt(row[5]) ? true : false; spec->name = row[6]; - spec->must_learn = (uint8) atoi(row[7]); - spec->quest = atoi(row[8]) ? true : false; + spec->must_learn = (uint8) Strings::ToInt(row[7]); + spec->quest = Strings::ToInt(row[8]) ? true : false; spec->has_learnt = false; spec->madecount = 0; spec->recipe_id = recipe_id; @@ -1526,8 +1610,8 @@ bool ZoneDatabase::GetTradeRecipe( spec->onsuccess.clear(); for(auto row = results.begin(); row != results.end(); ++row) { - uint32 item = (uint32)atoi(row[0]); - uint8 num = (uint8) atoi(row[1]); + uint32 item = (uint32)Strings::ToInt(row[0]); + uint8 num = (uint8) Strings::ToInt(row[1]); spec->onsuccess.push_back(std::pair(item, num)); } @@ -1540,8 +1624,8 @@ bool ZoneDatabase::GetTradeRecipe( results = QueryDatabase(query); if (results.Success()) { for (auto row = results.begin(); row != results.end(); ++row) { - uint32 item = (uint32) atoi(row[0]); - uint8 num = (uint8) atoi(row[1]); + uint32 item = (uint32) Strings::ToInt(row[0]); + uint8 num = (uint8) Strings::ToInt(row[1]); spec->onfail.push_back(std::pair(item, num)); } } @@ -1563,8 +1647,8 @@ bool ZoneDatabase::GetTradeRecipe( results = QueryDatabase(query); if (results.Success()) { for (auto row = results.begin(); row != results.end(); ++row) { - uint32 item = (uint32) atoi(row[0]); - uint8 num = (uint8) atoi(row[1]); + uint32 item = (uint32) Strings::ToInt(row[0]); + uint8 num = (uint8) Strings::ToInt(row[1]); spec->salvage.push_back(std::pair(item, num)); } } @@ -1634,6 +1718,86 @@ void Client::LearnRecipe(uint32 recipe_id) ); } +std::vector ZoneDatabase::GetRecipeComponentItemIDs(RecipeCountType count_type, uint32 recipe_id) +{ + std::vector l; + + const auto& tr = TradeskillRecipeRepository::FindOne(content_db, recipe_id); + if (!tr.id) { + return l; + } + + std::string c; + switch (count_type) { + case RecipeCountType::Success: + c = "successcount"; + break; + case RecipeCountType::Fail: + c = "failcount"; + break; + case RecipeCountType::Component: + c = "componentcount"; + break; + case RecipeCountType::Salvage: + c = "salvagecount"; + break; + case RecipeCountType::Container: + c = "iscontainer"; + break; + } + + const auto& tre = TradeskillRecipeEntriesRepository::GetWhere( + content_db, + fmt::format( + "recipe_id = {} AND {} >= 1 ORDER BY id ASC", + recipe_id, + c + ) + ); + if (tre.empty()) { + return l; + } + + for (const auto& e : tre) { + l.emplace_back(e.item_id); + } + + return l; +} + +int8 ZoneDatabase::GetRecipeComponentCount(RecipeCountType count_type, uint32 recipe_id, uint32 item_id) +{ + const auto& tr = TradeskillRecipeRepository::FindOne(content_db, recipe_id); + if (!tr.id) { + return -1; + } + + const auto& tre = TradeskillRecipeEntriesRepository::GetWhere( + content_db, + fmt::format( + "recipe_id = {} AND item_id = {} ORDER BY id ASC LIMIT 1", + recipe_id, + item_id + ) + ); + if (tre.empty()) { + return -1; + } + + switch (count_type) { + case RecipeCountType::Success: + return tre[0].successcount; + case RecipeCountType::Fail: + return tre[0].failcount; + case RecipeCountType::Component: + return tre[0].componentcount; + case RecipeCountType::Salvage: + return tre[0].salvagecount; + default: + return -1; + } +} + bool Client::CanIncreaseTradeskill(EQ::skills::SkillType tradeskill) { uint32 rawskill = GetRawSkill(tradeskill); uint16 maxskill = MaxSkill(tradeskill); @@ -1698,3 +1862,66 @@ bool ZoneDatabase::DisableRecipe(uint32 recipe_id) return false; } + +bool Client::CheckTradeskillLoreConflict(int32 recipe_id) +{ + auto recipe_entries = TradeskillRecipeEntriesRepository::GetWhere( + content_db, + fmt::format( + "recipe_id = {} ORDER BY componentcount DESC", + recipe_id + ) + ); + if (recipe_entries.empty()) { + return false; + } + + // validate which items from the recipe we will call CheckLoreConflict on + for (const auto &tre : recipe_entries) { + if (tre.item_id) { + auto tre_inst = database.GetItem(tre.item_id); + + // To compare items we iterate against each item in the recipe that have a loregroup. + for (auto &tre_update_item : recipe_entries) { + bool fi_is_valid = tre_update_item.item_id && tre_inst && tre_inst->LoreGroup != 0; + + if (fi_is_valid) { + auto tre_update_item_inst = database.GetItem(tre_update_item.item_id); + bool ei_is_valid = tre_update_item_inst && tre_update_item_inst->LoreGroup != 0; + + if (ei_is_valid) { + bool unique_lore_group_match = tre_inst->LoreGroup > 0 && tre_inst->LoreGroup == tre_update_item_inst->LoreGroup; + bool component_count_is_valid = tre_update_item.componentcount == 0 && tre.componentcount > 0; + + // If the recipe item is a component, and matches a unique lore group (> 0) or the item_id matches another entry in the recipe + // zero out the item_id, this will prevent us from doing a lore check inadvertently where + // the item is a component, and returned on success, fail, salvage. + // or uses an item that is part of a unique loregroup that returns an item of the same unique loregroup + if (ei_is_valid && (tre_update_item.item_id == tre.item_id || unique_lore_group_match) && component_count_is_valid) { + tre_update_item.item_id = 0; + } + } + } + } + + if (tre_inst) { + if (tre_inst->LoreGroup == 0 || tre.componentcount > 0 || tre.iscontainer) { + continue; + } + + if (CheckLoreConflict(tre_inst)) { + EQ::SayLinkEngine linker; + linker.SetLinkType(EQ::saylink::SayLinkItemData); + linker.SetItemData(tre_inst); + auto item_link = linker.GenerateLink(); + MessageString(Chat::Red, TRADESKILL_COMBINE_LORE, item_link.c_str()); + return true; + } + } + } + } + + return false; +} + + diff --git a/zone/trading.cpp b/zone/trading.cpp index 63c8f51a5..9500f9a23 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -21,6 +21,7 @@ #include "../common/rulesys.h" #include "../common/strings.h" #include "../common/misc_functions.h" +#include "../common/events/player_event_logs.h" #include "client.h" #include "entity.h" @@ -187,149 +188,9 @@ void Trade::SendItemData(const EQ::ItemInstance* inst, int16 dest_slot_id) } } -// Audit trade: The part logged is what travels owner -> with -void Trade::LogTrade() +Mob *Trade::GetOwner() const { - Mob* with = With(); - if (!owner->IsClient() || !with) - return; // Should never happen - - Client* trader = owner->CastToClient(); - bool logtrade = false; - int admin_level = 0; - uint8 item_count = 0; - - if (zone->tradevar != 0) { - for (uint16 i = EQ::invslot::TRADE_BEGIN; i <= EQ::invslot::TRADE_END; i++) { - if (trader->GetInv().GetItem(i)) - item_count++; - } - - if ((cp + sp + gp + pp) || item_count) { - admin_level = trader->Admin(); - } else { - admin_level = (AccountStatus::Max + 1); - } - - if (zone->tradevar == 7) { - logtrade = true; - } else if ( - admin_level >= AccountStatus::Steward && - admin_level < AccountStatus::ApprenticeGuide - ) { - if (zone->tradevar < 8 && zone->tradevar > 5) { - logtrade = true; - } - } else if (admin_level <= AccountStatus::ApprenticeGuide) { - if (zone->tradevar < 8 && zone->tradevar > 4) { - logtrade = true; - } - } else if (admin_level <= AccountStatus::QuestTroupe) { - if (zone->tradevar < 8 && zone->tradevar > 3) { - logtrade = true; - } - } else if (admin_level <= AccountStatus::GMAdmin) { - if (zone->tradevar < 9 && zone->tradevar > 2) { - logtrade = true; - } - } else if (admin_level <= AccountStatus::GMLeadAdmin) { - if ((zone->tradevar < 8 && zone->tradevar > 1) || zone->tradevar == 9) { - logtrade = true; - } - } else if (admin_level <= AccountStatus::Max){ - if (zone->tradevar < 8 && zone->tradevar > 0) { - logtrade = true; - } - } - } - - if (logtrade) { - char logtext[1000] = {0}; - uint32 cash = 0; - bool comma = false; - - // Log items offered by owner - cash = cp + sp + gp + pp; - if ((cash>0) || (item_count>0)) { - sprintf(logtext, "%s gave %s ", trader->GetName(), with->GetName()); - - if (item_count > 0) { - strcat(logtext, "items {"); - - for (uint16 i = EQ::invslot::TRADE_BEGIN; i <= EQ::invslot::TRADE_END; i++) { - const EQ::ItemInstance* inst = trader->GetInv().GetItem(i); - - if (!comma) - comma = true; - else { - if (inst) - strcat(logtext, ","); - } - - if (inst) { - char item_num[15] = {0}; - sprintf(item_num, "%i", inst->GetItem()->ID); - strcat(logtext, item_num); - - if (inst->IsClassBag()) { - for (uint8 j = EQ::invbag::SLOT_BEGIN; j <= EQ::invbag::SLOT_END; j++) { - inst = trader->GetInv().GetItem(i, j); - if (inst) { - strcat(logtext, ","); - sprintf(item_num, "%i", inst->GetItem()->ID); - strcat(logtext, item_num); - } - } - } - } - } - } - - if (cash > 0) { - char money[100] = {0}; - sprintf(money, " %ipp, %igp, %isp, %icp", trader->trade->pp, trader->trade->gp, trader->trade->sp, trader->trade->cp); - strcat(logtext, money); - } - - database.logevents(trader->AccountName(), trader->AccountID(), - trader->Admin(), trader->GetName(), with->GetName(), "Trade", logtext, 6); - } - } -} - - -void Trade::DumpTrade() -{ - Mob* with = With(); - LogTrading("Dumping trade data: [{}] in TradeState [{}] with [{}]", - owner->GetName(), state, ((with==nullptr)?"(null)":with->GetName())); - - if (!owner->IsClient()) - return; - - Client* trader = owner->CastToClient(); - for (uint16 i = EQ::invslot::TRADE_BEGIN; i <= EQ::invslot::TRADE_END; i++) { - const EQ::ItemInstance* inst = trader->GetInv().GetItem(i); - - if (inst) { - LogTrading("Item [{}] (Charges=[{}], Slot=[{}], IsBag=[{}])", - inst->GetItem()->ID, inst->GetCharges(), - i, ((inst->IsClassBag()) ? "True" : "False")); - - if (inst->IsClassBag()) { - for (uint8 j = EQ::invbag::SLOT_BEGIN; j <= EQ::invbag::SLOT_END; j++) { - inst = trader->GetInv().GetItem(i, j); - if (inst) { - LogTrading("\tBagItem [{}] (Charges=[{}], Slot=[{}])", - inst->GetItem()->ID, inst->GetCharges(), - EQ::InventoryProfile::CalcSlotId(i, j)); - } - } - } - } - } - - LogTrading("\tpp:[{}], gp:[{}], sp:[{}], cp:[{}]", pp, gp, sp, cp); + return owner; } @@ -458,8 +319,8 @@ void Client::ResetTrade() { void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, std::list* event_details) { if(tradingWith && tradingWith->IsClient()) { - Client* other = tradingWith->CastToClient(); - QSPlayerLogTrade_Struct* qs_audit = nullptr; + Client * other = tradingWith->CastToClient(); + PlayerLogTrade_Struct * qs_audit = nullptr; bool qs_log = false; if(other) { @@ -470,24 +331,24 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st // step 0: pre-processing // QS code if (RuleB(QueryServ, PlayerLogTrades) && event_entry && event_details) { - qs_audit = (QSPlayerLogTrade_Struct*)event_entry; + qs_audit = (PlayerLogTrade_Struct*)event_entry; qs_log = true; if (finalizer) { - qs_audit->char2_id = character_id; + qs_audit->character_2_id = character_id; - qs_audit->char2_money.platinum = trade->pp; - qs_audit->char2_money.gold = trade->gp; - qs_audit->char2_money.silver = trade->sp; - qs_audit->char2_money.copper = trade->cp; + qs_audit->character_2_money.platinum = trade->pp; + qs_audit->character_2_money.gold = trade->gp; + qs_audit->character_2_money.silver = trade->sp; + qs_audit->character_2_money.copper = trade->cp; } else { - qs_audit->char1_id = character_id; + qs_audit->character_1_id = character_id; - qs_audit->char1_money.platinum = trade->pp; - qs_audit->char1_money.gold = trade->gp; - qs_audit->char1_money.silver = trade->sp; - qs_audit->char1_money.copper = trade->cp; + qs_audit->character_1_money.platinum = trade->pp; + qs_audit->character_1_money.gold = trade->gp; + qs_audit->character_1_money.silver = trade->sp; + qs_audit->character_1_money.copper = trade->cp; } } @@ -510,12 +371,12 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st if (other->PutItemInInventory(free_slot, *inst, true)) { LogTrading("Container [{}] ([{}]) successfully transferred, deleting from trade slot", inst->GetItem()->Name, inst->GetItem()->ID); if (qs_log) { - auto detail = new QSTradeItems_Struct; + auto detail = new PlayerLogTradeItemsEntry_Struct; - detail->from_id = character_id; - detail->from_slot = trade_slot; - detail->to_id = other->CharacterID(); - detail->to_slot = free_slot; + detail->from_character_id = character_id; + detail->from_slot = trade_slot; + detail->to_character_id = other->CharacterID(); + detail->to_slot = free_slot; detail->item_id = inst->GetID(); detail->charges = 1; detail->aug_1 = inst->GetAugmentItemID(1); @@ -527,20 +388,20 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st event_details->push_back(detail); if (finalizer) - qs_audit->char2_count += detail->charges; + qs_audit->character_2_item_count += detail->charges; else - qs_audit->char1_count += detail->charges; + qs_audit->character_1_item_count += detail->charges; for (uint8 sub_slot = EQ::invbag::SLOT_BEGIN; (sub_slot <= EQ::invbag::SLOT_END); ++sub_slot) { // this is to catch ALL items const EQ::ItemInstance* bag_inst = inst->GetItem(sub_slot); if (bag_inst) { - detail = new QSTradeItems_Struct; + detail = new PlayerLogTradeItemsEntry_Struct; - detail->from_id = character_id; - detail->from_slot = EQ::InventoryProfile::CalcSlotId(trade_slot, sub_slot); - detail->to_id = other->CharacterID(); - detail->to_slot = EQ::InventoryProfile::CalcSlotId(free_slot, sub_slot); + detail->from_character_id = character_id; + detail->from_slot = EQ::InventoryProfile::CalcSlotId(trade_slot, sub_slot); + detail->to_character_id = other->CharacterID(); + detail->to_slot = EQ::InventoryProfile::CalcSlotId(free_slot, sub_slot); detail->item_id = bag_inst->GetID(); detail->charges = (!bag_inst->IsStackable() ? 1 : bag_inst->GetCharges()); detail->aug_1 = bag_inst->GetAugmentItemID(1); @@ -552,9 +413,9 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st event_details->push_back(detail); if (finalizer) - qs_audit->char2_count += detail->charges; + qs_audit->character_2_item_count += detail->charges; else - qs_audit->char1_count += detail->charges; + qs_audit->character_1_item_count += detail->charges; } } } @@ -620,12 +481,12 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st LogTrading("Partial stack [{}] ([{}]) successfully transferred, deleting [{}] charges from trade slot", inst->GetItem()->Name, inst->GetItem()->ID, (old_charges - inst->GetCharges())); if (qs_log) { - auto detail = new QSTradeItems_Struct; + auto detail = new PlayerLogTradeItemsEntry_Struct; - detail->from_id = character_id; - detail->from_slot = trade_slot; - detail->to_id = other->CharacterID(); - detail->to_slot = partial_slot; + detail->from_character_id = character_id; + detail->from_slot = trade_slot; + detail->to_character_id = other->CharacterID(); + detail->to_slot = partial_slot; detail->item_id = inst->GetID(); detail->charges = (old_charges - inst->GetCharges()); detail->aug_1 = 0; @@ -637,9 +498,9 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st event_details->push_back(detail); if (finalizer) - qs_audit->char2_count += detail->charges; + qs_audit->character_2_item_count += detail->charges; else - qs_audit->char1_count += detail->charges; + qs_audit->character_1_item_count += detail->charges; } } else { @@ -688,12 +549,12 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st } if (qs_log) { - auto detail = new QSTradeItems_Struct; + auto detail = new PlayerLogTradeItemsEntry_Struct; - detail->from_id = character_id; - detail->from_slot = trade_slot; - detail->to_id = character_id; - detail->to_slot = bias_slot; + detail->from_character_id = character_id; + detail->from_slot = trade_slot; + detail->to_character_id = character_id; + detail->to_slot = bias_slot; detail->item_id = inst->GetID(); detail->charges = (old_charges - inst->GetCharges()); detail->aug_1 = 0; @@ -728,12 +589,12 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st if (other->PutItemInInventory(free_slot, *inst, true)) { LogTrading("Item [{}] ([{}]) successfully transferred, deleting from trade slot", inst->GetItem()->Name, inst->GetItem()->ID); if (qs_log) { - auto detail = new QSTradeItems_Struct; + auto detail = new PlayerLogTradeItemsEntry_Struct; - detail->from_id = character_id; - detail->from_slot = trade_slot; - detail->to_id = other->CharacterID(); - detail->to_slot = free_slot; + detail->from_character_id = character_id; + detail->from_slot = trade_slot; + detail->to_character_id = other->CharacterID(); + detail->to_slot = free_slot; detail->item_id = inst->GetID(); detail->charges = (!inst->IsStackable() ? 1 : inst->GetCharges()); detail->aug_1 = inst->GetAugmentItemID(1); @@ -745,21 +606,21 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st event_details->push_back(detail); if (finalizer) - qs_audit->char2_count += detail->charges; + qs_audit->character_2_item_count += detail->charges; else - qs_audit->char1_count += detail->charges; + qs_audit->character_1_item_count += detail->charges; // 'step 3' should never really see containers..but, just in case... for (uint8 sub_slot = EQ::invbag::SLOT_BEGIN; (sub_slot <= EQ::invbag::SLOT_END); ++sub_slot) { // this is to catch ALL items const EQ::ItemInstance* bag_inst = inst->GetItem(sub_slot); if (bag_inst) { - detail = new QSTradeItems_Struct; + detail = new PlayerLogTradeItemsEntry_Struct; - detail->from_id = character_id; - detail->from_slot = trade_slot; - detail->to_id = other->CharacterID(); - detail->to_slot = free_slot; + detail->from_character_id = character_id; + detail->from_slot = trade_slot; + detail->to_character_id = other->CharacterID(); + detail->to_slot = free_slot; detail->item_id = bag_inst->GetID(); detail->charges = (!bag_inst->IsStackable() ? 1 : bag_inst->GetCharges()); detail->aug_1 = bag_inst->GetAugmentItemID(1); @@ -771,9 +632,9 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st event_details->push_back(detail); if (finalizer) - qs_audit->char2_count += detail->charges; + qs_audit->character_2_item_count += detail->charges; else - qs_audit->char1_count += detail->charges; + qs_audit->character_1_item_count += detail->charges; } } } @@ -875,7 +736,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st } bool quest_npc = false; - if (parse->HasQuestSub(tradingWith->GetNPCTypeID(), EVENT_TRADE, true)) { + if (parse->HasQuestSub(tradingWith->GetNPCTypeID(), EVENT_TRADE)) { // This is a quest NPC quest_npc = true; } @@ -990,8 +851,10 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st tradingWith->FaceTarget(this); } - std::vector item_list(items.begin(), items.end()); - parse->EventNPC(EVENT_TRADE, tradingWith->CastToNPC(), this, "", 0, &item_list); + if (parse->HasQuestSub(tradingWith->GetNPCTypeID(), EVENT_TRADE)) { + std::vector item_list(items.begin(), items.end()); + parse->EventNPC(EVENT_TRADE, tradingWith->CastToNPC(), this, "", 0, &item_list); + } for(int i = 0; i < 4; ++i) { if(insts[i]) { @@ -1697,7 +1560,7 @@ void Client::BuyTraderItem(TraderBuy_Struct* tbs, Client* Trader, const EQApplic } if(!TakeMoneyFromPP(TotalCost)) { - database.SetHackerFlag(account_name, name, "Attempted to buy something in bazaar but did not have enough money."); + RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Attempted to buy something in bazaar but did not have enough money."}); TradeRequestFailed(app); safe_delete(outapp); return; @@ -1715,6 +1578,37 @@ void Client::BuyTraderItem(TraderBuy_Struct* tbs, Client* Trader, const EQApplic Trader->AddMoneyToPP(copper, silver, gold, platinum, true); + + if (player_event_logs.IsEventEnabled(PlayerEvent::TRADER_PURCHASE)) { + auto e = PlayerEvent::TraderPurchaseEvent{ + .item_id = BuyItem->GetID(), + .item_name = BuyItem->GetItem()->Name, + .trader_id = Trader->CharacterID(), + .trader_name = Trader->GetCleanName(), + .price = tbs->Price, + .charges = outtbs->Quantity, + .total_cost = (tbs->Price * outtbs->Quantity), + .player_money_balance = GetCarriedMoney(), + }; + + RecordPlayerEventLog(PlayerEvent::TRADER_PURCHASE, e); + } + + if (player_event_logs.IsEventEnabled(PlayerEvent::TRADER_SELL)) { + auto e = PlayerEvent::TraderSellEvent{ + .item_id = BuyItem->GetID(), + .item_name = BuyItem->GetItem()->Name, + .buyer_id = CharacterID(), + .buyer_name = GetCleanName(), + .price = tbs->Price, + .charges = outtbs->Quantity, + .total_cost = (tbs->Price * outtbs->Quantity), + .player_money_balance = Trader->GetCarriedMoney(), + }; + + RecordPlayerEventLogWithClient(Trader, PlayerEvent::TRADER_SELL, e); + } + LogTrading("Trader Received: [{}] Platinum, [{}] Gold, [{}] Silver, [{}] Copper", platinum, gold, silver, copper); ReturnTraderReq(app, outtbs->Quantity, ItemID); @@ -1770,8 +1664,8 @@ void Client::SendBazaarWelcome() bws->Beginning.Action = BazaarWelcome; - bws->Traders = atoi(row[0]); - bws->Items = atoi(row[1]); + bws->Traders = Strings::ToInt(row[0]); + bws->Items = Strings::ToInt(row[1]); if (ClientVersion() >= EQ::versions::ClientVersion::RoF) { @@ -1790,7 +1684,7 @@ void Client::SendBazaarWelcome() auto row = results.begin(); Message(Chat::NPCQuestSay, "There are %i Buyers waiting to purchase your loot. Type /barter to search for them, " - "or use /buyer to set up your own Buy Lines.", atoi(row[0])); + "or use /buyer to set up your own Buy Lines.", Strings::ToInt(row[0])); } void Client::SendBazaarResults( @@ -2034,26 +1928,26 @@ void Client::SendBazaarResults( for (auto row = results.begin(); row != results.end(); ++row) { VARSTRUCT_ENCODE_TYPE(uint32, bufptr, Action); - Count = atoi(row[0]); + Count = Strings::ToInt(row[0]); VARSTRUCT_ENCODE_TYPE(uint32, bufptr, Count); - SerialNumber = atoi(row[3]); + SerialNumber = Strings::ToInt(row[3]); VARSTRUCT_ENCODE_TYPE(int32, bufptr, SerialNumber); - Client *Trader2 = entity_list.GetClientByCharID(atoi(row[1])); + Client *Trader2 = entity_list.GetClientByCharID(Strings::ToInt(row[1])); if (Trader2) { ID = Trader2->GetID(); VARSTRUCT_ENCODE_TYPE(uint32, bufptr, ID); } else { - LogTrading("Unable to find trader: [{}]\n", atoi(row[1])); + LogTrading("Unable to find trader: [{}]\n", Strings::ToInt(row[1])); VARSTRUCT_ENCODE_TYPE(uint32, bufptr, 0); } - Cost = atoi(row[5]); + Cost = Strings::ToInt(row[5]); VARSTRUCT_ENCODE_TYPE(uint32, bufptr, Cost); - StatValue = atoi(row[8]); + StatValue = Strings::ToInt(row[8]); VARSTRUCT_ENCODE_TYPE(uint32, bufptr, StatValue); - bool Stackable = atoi(row[10]); + bool Stackable = Strings::ToInt(row[10]); if (Stackable) { - int Charges = atoi(row[9]); + int Charges = Strings::ToInt(row[9]); sprintf(temp_buffer, "%s(%i)", row[7], Charges); } else { @@ -2077,7 +1971,7 @@ void Client::SendBazaarResults( bufptr += 64; - VARSTRUCT_ENCODE_TYPE(uint32, bufptr, atoi(row[1])); // ItemID + VARSTRUCT_ENCODE_TYPE(uint32, bufptr, Strings::ToInt(row[1])); // ItemID } auto outapp = new EQApplicationPacket(OP_BazaarSearch, Size); @@ -2466,12 +2360,12 @@ void Client::SendBuyerResults(char* searchString, uint32 searchID) { for (auto row = results.begin(); row != results.end(); ++row) { char itemName[64]; - uint32 charID = atoi(row[0]); - uint32 buySlot = atoi(row[1]); - uint32 itemID = atoi(row[2]); + uint32 charID = Strings::ToInt(row[0]); + uint32 buySlot = Strings::ToInt(row[1]); + uint32 itemID = Strings::ToInt(row[2]); strcpy(itemName, row[3]); - uint32 quantity = atoi(row[4]); - uint32 price = atoi(row[5]); + uint32 quantity = Strings::ToInt(row[4]); + uint32 price = Strings::ToInt(row[5]); // Each item in the search results is sent as a single fixed length packet, although the position of // the fields varies due to the use of variable length strings. The reason the packet is so big, is @@ -2568,11 +2462,11 @@ void Client::ShowBuyLines(const EQApplicationPacket *app) { for (auto row = results.begin(); row != results.end(); ++row) { char ItemName[64]; - uint32 BuySlot = atoi(row[1]); - uint32 ItemID = atoi(row[2]); + uint32 BuySlot = Strings::ToInt(row[1]); + uint32 ItemID = Strings::ToInt(row[2]); strcpy(ItemName, row[3]); - uint32 Quantity = atoi(row[4]); - uint32 Price = atoi(row[5]); + uint32 Quantity = Strings::ToInt(row[4]); + uint32 Price = Strings::ToInt(row[5]); auto outapp = new EQApplicationPacket(OP_Barter, 936); diff --git a/zone/trap.cpp b/zone/trap.cpp index 37436fa3a..947a325e5 100644 --- a/zone/trap.cpp +++ b/zone/trap.cpp @@ -72,8 +72,7 @@ Trap::Trap() : disarmed = false; respawn_time = 0; respawn_var = 0; - hiddenTrigger = nullptr; - ownHiddenTrigger = false; + SetHiddenTrigger(nullptr); chance = 0; triggered_number = 0; times_triggered = 0; @@ -460,8 +459,8 @@ bool ZoneDatabase::LoadTraps(const char* zonename, int16 version) { } for (auto row = results.begin(); row != results.end(); ++row) { - uint32 tid = atoi(row[0]); - uint8 grp = atoi(row[15]); + uint32 tid = Strings::ToInt(row[0]); + uint8 grp = Strings::ToInt(row[15]); if (grp > 0) { @@ -474,20 +473,20 @@ bool ZoneDatabase::LoadTraps(const char* zonename, int16 version) { auto trap = new Trap(); trap->trap_id = tid; trap->db_id = tid; - trap->m_Position = glm::vec3(atof(row[1]), atof(row[2]), atof(row[3])); - trap->effect = atoi(row[4]); - trap->effectvalue = atoi(row[5]); - trap->effectvalue2 = atoi(row[6]); - trap->skill = atoi(row[7]); - trap->maxzdiff = atof(row[8]); - trap->radius = atof(row[9]); - trap->chance = atoi(row[10]); + trap->m_Position = glm::vec3(Strings::ToFloat(row[1]), Strings::ToFloat(row[2]), Strings::ToFloat(row[3])); + trap->effect = Strings::ToInt(row[4]); + trap->effectvalue = Strings::ToInt(row[5]); + trap->effectvalue2 = Strings::ToInt(row[6]); + trap->skill = Strings::ToInt(row[7]); + trap->maxzdiff = Strings::ToFloat(row[8]); + trap->radius = Strings::ToFloat(row[9]); + trap->chance = Strings::ToInt(row[10]); trap->message = row[11]; - trap->respawn_time = atoi(row[12]); - trap->respawn_var = atoi(row[13]); - trap->level = atoi(row[14]); + trap->respawn_time = Strings::ToInt(row[12]); + trap->respawn_var = Strings::ToInt(row[13]); + trap->level = Strings::ToInt(row[14]); trap->group = grp; - trap->triggered_number = atoi(row[16]); + trap->triggered_number = Strings::ToInt(row[16]); trap->despawn_when_triggered = atobool(row[17]); trap->undetectable = atobool(row[18]); entity_list.AddTrap(trap); @@ -526,9 +525,9 @@ void Trap::CreateHiddenTrigger() npca->GiveNPCTypeData(make_npc); entity_list.AddNPC(npca); - hiddenTrigger = npca; - ownHiddenTrigger = true; + SetHiddenTrigger(npca); } + bool ZoneDatabase::SetTrapData(Trap* trap, bool repopnow) { uint32 dbid = trap->db_id; @@ -555,20 +554,20 @@ bool ZoneDatabase::SetTrapData(Trap* trap, bool repopnow) { for (auto row = results.begin(); row != results.end(); ++row) { - trap->db_id = atoi(row[0]); - trap->m_Position = glm::vec3(atof(row[1]), atof(row[2]), atof(row[3])); - trap->effect = atoi(row[4]); - trap->effectvalue = atoi(row[5]); - trap->effectvalue2 = atoi(row[6]); - trap->skill = atoi(row[7]); - trap->maxzdiff = atof(row[8]); - trap->radius = atof(row[9]); - trap->chance = atoi(row[10]); + trap->db_id = Strings::ToInt(row[0]); + trap->m_Position = glm::vec3(Strings::ToFloat(row[1]), Strings::ToFloat(row[2]), Strings::ToFloat(row[3])); + trap->effect = Strings::ToInt(row[4]); + trap->effectvalue = Strings::ToInt(row[5]); + trap->effectvalue2 = Strings::ToInt(row[6]); + trap->skill = Strings::ToInt(row[7]); + trap->maxzdiff = Strings::ToFloat(row[8]); + trap->radius = Strings::ToFloat(row[9]); + trap->chance = Strings::ToInt(row[10]); trap->message = row[11]; - trap->respawn_time = atoi(row[12]); - trap->respawn_var = atoi(row[13]); - trap->level = atoi(row[14]); - trap->triggered_number = atoi(row[15]); + trap->respawn_time = Strings::ToInt(row[12]); + trap->respawn_var = Strings::ToInt(row[13]); + trap->level = Strings::ToInt(row[14]); + trap->triggered_number = Strings::ToInt(row[15]); trap->despawn_when_triggered = atobool(row[16]); trap->undetectable = atobool(row[17]); trap->CreateHiddenTrigger(); @@ -599,7 +598,7 @@ void Trap::UpdateTrap(bool respawn, bool repopnow) if (hiddenTrigger) { hiddenTrigger->Depop(); - hiddenTrigger = nullptr; + SetHiddenTrigger(nullptr); } times_triggered = 0; Client* trigger = entity_list.GetClientByCharID(charid); diff --git a/zone/trap.h b/zone/trap.h index e20e2314f..4c7e7daa1 100644 --- a/zone/trap.h +++ b/zone/trap.h @@ -80,7 +80,6 @@ public: std::string message; protected: NPC *hiddenTrigger; - bool ownHiddenTrigger; }; #endif diff --git a/zone/tribute.cpp b/zone/tribute.cpp index 3e0011049..4f6588e40 100644 --- a/zone/tribute.cpp +++ b/zone/tribute.cpp @@ -247,8 +247,6 @@ int32 Client::TributeItem(uint32 slot, uint32 quantity) { //figure out what its worth int32 pts = inst->GetItem()->Favor; - pts = mod_tribute_item_value(pts, m_inv[slot]); - if(pts < 1) { Message(Chat::Red, "This item is worthless for favor."); return(0); @@ -394,7 +392,7 @@ bool ZoneDatabase::LoadTributes() { } for (auto row = results.begin(); row != results.end(); ++row) { - uint32 id = atoul(row[0]); + uint32 id = Strings::ToUnsignedInt(row[0]); tributeData.name = row[1]; tributeData.description = row[2]; tributeData.unknown = strtoul(row[3], nullptr, 10); @@ -412,7 +410,7 @@ bool ZoneDatabase::LoadTributes() { } for (auto row = results.begin(); row != results.end(); ++row) { - uint32 id = atoul(row[0]); + uint32 id = Strings::ToUnsignedInt(row[0]); if (tribute_list.count(id) != 1) { LogError("Error in LoadTributes: unknown tribute [{}] in tribute_levels", (unsigned long) id); @@ -428,9 +426,9 @@ bool ZoneDatabase::LoadTributes() { TributeLevel_Struct &s = cur.tiers[cur.tier_count]; - s.level = atoul(row[1]); - s.cost = atoul(row[2]); - s.tribute_item_id = atoul(row[3]); + s.level = Strings::ToUnsignedInt(row[1]); + s.cost = Strings::ToUnsignedInt(row[2]); + s.tribute_item_id = Strings::ToUnsignedInt(row[3]); cur.tier_count++; } diff --git a/zone/tune.cpp b/zone/tune.cpp index dcd51a0cc..beb428f10 100644 --- a/zone/tune.cpp +++ b/zone/tune.cpp @@ -1040,16 +1040,16 @@ int64 Mob::TuneACSum(bool skip_caps, int ac_override, int add_ac) } int shield_ac = 0; - if (HasShieldEquiped() && IsClient()) { - auto client = CastToClient(); - auto inst = client->GetInv().GetItem(EQ::invslot::slotSecondary); + if (HasShieldEquiped() && IsOfClientBot()) { + auto inst = (IsClient()) ? GetInv().GetItem(EQ::invslot::slotSecondary) : CastToBot()->GetBotItem(EQ::invslot::slotSecondary); if (inst) { - if (inst->GetItemRecommendedLevel(true) <= GetLevel()) + if (inst->GetItemRecommendedLevel(true) <= GetLevel()) { shield_ac = inst->GetItemArmorClass(true); - else - shield_ac = client->CalcRecommendedLevelBonus(GetLevel(), inst->GetItemRecommendedLevel(true), inst->GetItemArmorClass(true)); + } else { + shield_ac = CalcRecommendedLevelBonus(GetLevel(), inst->GetItemRecommendedLevel(true),inst->GetItemArmorClass(true)); + } } - shield_ac += client->GetHeroicSTR() / 10; + shield_ac += GetHeroicSTR() * RuleR(Character, HeroicStrengthMultiplier) / 10; } // EQ math ac = (ac * 4) / 3; @@ -1348,12 +1348,12 @@ int64 Mob::Tunecompute_defense(int avoidance_override, int add_avoidance) { int defense = GetSkill(EQ::skills::SkillDefense) * 400 / 225; defense += (8000 * (GetAGI() - 40)) / 36000; - if (IsClient()) { + if (IsOfClientBot()) { if (avoidance_override) { defense = avoidance_override; } else { - defense += CastToClient()->GetHeroicAGI() / 10; + defense += GetHeroicAGI() * RuleR(Character, HeroicAgilityMultiplier) / 10; } defense += add_avoidance; //1 pt = 10 heroic agi } @@ -1490,16 +1490,16 @@ void Mob::TuneCommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraA hit.damage_done = min_mod; hit.damage_done += hit.min_damage; - if (IsClient()) { + if (IsOfClientBot()) { int extra = 0; switch (hit.skill) { - case EQ::skills::SkillThrowing: - case EQ::skills::SkillArchery: - extra = CastToClient()->GetHeroicDEX() / 10; - break; - default: - extra = CastToClient()->GetHeroicSTR() / 10; - break; + case EQ::skills::SkillThrowing: + case EQ::skills::SkillArchery: + extra = GetHeroicDEX() * RuleR(Character, HeroicDexterityMultiplier) / 10; + break; + default: + extra = GetHeroicSTR() * RuleR(Character, HeroicStrengthMultiplier) / 10; + break; } hit.damage_done += extra; } diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index f92cc6a26..6ef49d924 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -66,14 +66,14 @@ void NPC::AI_SetRoambox( uint32 min_delay ) { - roambox_distance = distance; - roambox_max_x = max_x; - roambox_min_x = min_x; - roambox_max_y = max_y; - roambox_min_y = min_y; - roambox_destination_x = roambox_max_x + 1; // this will trigger a recalc - roambox_delay = delay; - roambox_min_delay = min_delay; + m_roambox.distance = distance; + m_roambox.max_x = max_x; + m_roambox.min_x = min_x; + m_roambox.max_y = max_y; + m_roambox.min_y = min_y; + m_roambox.dest_x = max_x + 1; // this will trigger a recalc + m_roambox.delay = delay; + m_roambox.min_delay = min_delay; } void NPC::DisplayWaypointInfo(Client *client) { @@ -165,10 +165,12 @@ void NPC::ResumeWandering() if (m_CurrentWayPoint.x == GetX() && m_CurrentWayPoint.y == GetY()) { // are we we at a waypoint? if so, trigger event and start to next - std::string export_string = fmt::format("{}", cur_wp); CalculateNewWaypoint(); SetAppearance(eaStanding, false); - parse->EventNPC(EVENT_WAYPOINT_DEPART, this, nullptr, export_string, 0); + + if (parse->HasQuestSub(GetNPCTypeID(), EVENT_WAYPOINT_DEPART)) { + parse->EventNPC(EVENT_WAYPOINT_DEPART, this, nullptr, std::to_string(cur_wp), 0); + } } // if not currently at a waypoint, we continue on to the one we were headed to before the stop } else @@ -771,17 +773,27 @@ float Mob::GetFixedZ(const glm::vec3 &destination, int32 z_find_offset) { float new_z = destination.z; if (zone->HasMap()) { - - if (flymode == GravityBehavior::Flying) + if (flymode == GravityBehavior::Flying) { return new_z; + } - if (zone->HasWaterMap() && zone->watermap->InLiquid(glm::vec3(m_Position))) + if (zone->HasWaterMap() && zone->watermap->InLiquid(glm::vec3(m_Position))) { return new_z; + } - /* - * Any more than 5 in the offset makes NPC's hop/snap to ceiling in small corridors - */ - new_z = FindDestGroundZ(destination, z_find_offset); + new_z = FindDestGroundZ(destination, ((-GetZOffset() / 2) + z_find_offset)); + + if (RuleB(Map, MobPathingVisualDebug)) { + DrawDebugCoordinateNode( + fmt::format("{} search z node", GetCleanName()), + glm::vec4{ + m_Position.x, + m_Position.y, + ((-GetZOffset() / 2) + z_find_offset), + m_Position.w + } + ); + } if (new_z != BEST_Z_INVALID) { new_z += GetZOffset(); @@ -833,6 +845,10 @@ void Mob::FixZ(int32 z_find_offset /*= 5*/, bool fix_client_z /*= false*/) { } m_Position.z = new_z; + + if (RuleB(Map, MobPathingVisualDebug)) { + DrawDebugCoordinateNode(fmt::format("{} new fixed z node", GetCleanName()), GetPosition()); + } } else { if (RuleB(Map, MobZVisualDebug)) { @@ -918,6 +934,7 @@ float Mob::GetZOffset() const { case RACE_AMYGDALAN_663: offset = 5.0f; break; + case RACE_SPECTRAL_IKSAR_147: case RACE_SANDMAN_664: offset = 4.0f; break; @@ -928,6 +945,7 @@ float Mob::GetZOffset() const { case RACE_RABBIT_668: offset = 5.0f; break; + case RACE_WURM_158: case RACE_BLIND_DREAMER_669: offset = 7.0f; break; @@ -1029,7 +1047,7 @@ int ZoneDatabase::GetHighestGrid(uint32 zoneid) { return 0; auto row = results.begin(); - return atoi(row[0]); + return Strings::ToInt(row[0]); } uint8 ZoneDatabase::GetGridType2(uint32 grid, uint16 zoneid) { @@ -1046,7 +1064,7 @@ uint8 ZoneDatabase::GetGridType2(uint32 grid, uint16 zoneid) { auto row = results.begin(); - return atoi(row[0]); + return Strings::ToInt(row[0]); } bool ZoneDatabase::GetWaypoints(uint32 grid, uint16 zoneid, uint32 num, wplist* wp) { @@ -1066,11 +1084,11 @@ bool ZoneDatabase::GetWaypoints(uint32 grid, uint16 zoneid, uint32 num, wplist* auto row = results.begin(); - wp->x = atof(row[0]); - wp->y = atof(row[1]); - wp->z = atof(row[2]); - wp->pause = atoi(row[3]); - wp->heading = atof(row[4]); + wp->x = Strings::ToFloat(row[0]); + wp->y = Strings::ToFloat(row[1]); + wp->z = Strings::ToFloat(row[2]); + wp->pause = Strings::ToInt(row[3]); + wp->heading = Strings::ToFloat(row[4]); return true; } @@ -1211,7 +1229,7 @@ uint32 ZoneDatabase::AddWPForSpawn(Client *client, uint32 spawn2id, const glm::v return 0; auto row = results.begin(); - grid_num = atoi(row[0]); + grid_num = Strings::ToInt(row[0]); if (grid_num == 0) { // Our spawn doesn't have a grid assigned to it -- we need to create a new grid and assign it to the spawn @@ -1241,7 +1259,7 @@ uint32 ZoneDatabase::AddWPForSpawn(Client *client, uint32 spawn2id, const glm::v row = results.begin(); if (row[0] != 0) - next_wp_num = atoi(row[0]) + 1; + next_wp_num = Strings::ToInt(row[0]) + 1; else // No waypoints in this grid yet next_wp_num = 1; @@ -1265,7 +1283,7 @@ uint32 ZoneDatabase::GetFreeGrid(uint16 zoneid) { return 0; auto row = results.begin(); - uint32 freeGridID = row[0] ? atoi(row[0]) + 1 : 1; + uint32 freeGridID = row[0] ? Strings::ToInt(row[0]) + 1 : 1; return freeGridID; } @@ -1283,7 +1301,7 @@ int ZoneDatabase::GetHighestWaypoint(uint32 zoneid, uint32 gridid) { return 0; auto row = results.begin(); - return atoi(row[0]); + return Strings::ToInt(row[0]); } int ZoneDatabase::GetRandomWaypointLocFromGrid(glm::vec4 &loc, uint16 zoneid, int grid) @@ -1308,10 +1326,10 @@ int ZoneDatabase::GetRandomWaypointLocFromGrid(glm::vec4 &loc, uint16 zoneid, in row++; i++; } - loc.x = atof(row[0]); - loc.y = atof(row[1]); - loc.z = atof(row[2]); - loc.w = atof(row[3]); + loc.x = Strings::ToFloat(row[0]); + loc.y = Strings::ToFloat(row[1]); + loc.z = Strings::ToFloat(row[2]); + loc.w = Strings::ToFloat(row[3]); return i; } return 0; diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 90aa34f66..5a5025ac4 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -22,7 +22,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include #include #include -#include #ifdef _WINDOWS #include @@ -54,11 +53,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "worldserver.h" #include "zone.h" #include "zone_config.h" -#include "zone_reload.h" #include "../common/shared_tasks.h" #include "shared_task_zone_messaging.h" #include "dialogue_window.h" +#include "bot_command.h" #include "queryserv.h" +#include "../common/events/player_event_logs.h" extern EntityList entity_list; extern Zone* zone; @@ -1500,7 +1500,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) if (strcmp(rmsg->from, r->members[x].member->GetName()) != 0) { if (r->members[x].GroupNumber == rmsg->gid) { - if (r->members[x].member->GetFilter(FilterGroupChat) != 0) + if (!r->members[x].IsBot && r->members[x].member->GetFilter(FilterGroupChat) != 0) { r->members[x].member->ChannelMessageSend(rmsg->from, r->members[x].member->GetName(), ChatChannel_Group, rmsg->language, rmsg->lang_skill, rmsg->message); } @@ -1524,7 +1524,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) if (r->members[x].member) { if (strcmp(rmsg->from, r->members[x].member->GetName()) != 0) { - if (r->members[x].member->GetFilter(FilterGroupChat) != 0) + if (!r->members[x].IsBot && r->members[x].member->GetFilter(FilterGroupChat) != 0) { r->members[x].member->ChannelMessageSend(rmsg->from, r->members[x].member->GetName(), ChatChannel_Raid, rmsg->language, rmsg->lang_skill, rmsg->message); } @@ -1906,6 +1906,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) if (zone && zone->IsLoaded()) { zone->SendReloadMessage("Alternate Advancement Data"); zone->LoadAlternateAdvancement(); + entity_list.SendAlternateAdvancementStats(); } break; } @@ -1929,6 +1930,9 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { zone->SendReloadMessage("Commands"); command_init(); + if (RuleB(Bots, Enabled) && database.DoesTableExist("bot_command_settings")) { + bot_command_init(); + } break; } case ServerOP_ReloadContentFlags: @@ -1937,16 +1941,6 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) content_service.SetExpansionContext()->ReloadContentFlags(); break; } - case ServerOP_ReloadDoors: - { - if (zone && zone->IsLoaded()) { - zone->SendReloadMessage("Doors"); - entity_list.RemoveAllDoors(); - zone->LoadZoneDoors(); - entity_list.RespawnAllDoors(); - } - break; - } case ServerOP_ReloadDzTemplates: { if (zone) @@ -1956,14 +1950,6 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } break; } - case ServerOP_ReloadGroundSpawns: - { - if (zone && zone->IsLoaded()) { - zone->SendReloadMessage("Ground Spawns"); - zone->LoadGroundSpawns(); - } - break; - } case ServerOP_ReloadLevelEXPMods: { if (zone && zone->IsLoaded()) { @@ -1974,8 +1960,9 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } case ServerOP_ReloadLogs: { - zone->SendReloadMessage("Log Settings"); - LogSys.LoadLogDatabaseSettings(); + zone->SendReloadMessage("Log Settings"); + LogSys.LoadLogDatabaseSettings(); + player_event_logs.ReloadSettings(); break; } case ServerOP_ReloadMerchants: { @@ -1993,15 +1980,6 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } break; } - case ServerOP_ReloadObjects: - { - if (zone && zone->IsLoaded()) { - zone->SendReloadMessage("Objects"); - entity_list.RemoveAllObjects(); - zone->LoadZoneObjects(); - } - break; - } case ServerOP_ReloadPerlExportSettings: { zone->SendReloadMessage("Perl Event Export Settings"); @@ -2014,6 +1992,9 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) RuleManager::Instance()->LoadRules(&database, RuleManager::Instance()->GetActiveRuleset(), true); break; } + case ServerOP_ReloadDoors: + case ServerOP_ReloadGroundSpawns: + case ServerOP_ReloadObjects: case ServerOP_ReloadStaticZoneData: { if (zone && zone->IsLoaded()) { zone->SendReloadMessage("Static Zone Data"); @@ -3170,7 +3151,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } case ServerOP_UpdateSchedulerEvents: { LogScheduler("Received signal from world to update"); - if (m_zone_scheduler) { + if (GetScheduler()) { m_zone_scheduler->LoadScheduledEvents(); } diff --git a/zone/zone.cpp b/zone/zone.cpp index 8005c6537..287856f82 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -59,6 +59,7 @@ #include "zone_reload.h" #include "../common/repositories/criteria/content_filter_criteria.h" #include "../common/repositories/content_flags_repository.h" +#include "../common/repositories/merchantlist_repository.h" #include "../common/repositories/rule_sets_repository.h" #include "../common/repositories/zone_points_repository.h" #include "../common/serverinfo.h" @@ -115,7 +116,7 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool is_static) { std::string tmp; if (database.GetVariable("loglevel", tmp)) { int log_levels[4]; - int tmp_i = atoi(tmp.c_str()); + int tmp_i = Strings::ToInt(tmp.c_str()); if (tmp_i>9){ //Server is using the new code for(int i=0;i<4;i++){ if (((int)tmp[i]>=48) && ((int)tmp[i]<=57)) @@ -194,9 +195,9 @@ bool Zone::LoadZoneObjects() } for (auto row = results.begin(); row != results.end(); ++row) { - if (atoi(row[9]) == 0) { + if (Strings::ToInt(row[9]) == 0) { // Type == 0 - Static Object - const char *shortname = ZoneName(atoi(row[1]), false); // zoneid -> zone_shortname + const char *shortname = ZoneName(Strings::ToInt(row[1]), false); // zoneid -> zone_shortname if (!shortname) continue; @@ -205,12 +206,12 @@ bool Zone::LoadZoneObjects() auto d = DoorsRepository::NewEntity(); d.zone = shortname; - d.id = 1000000000 + atoi(row[0]); // Out of range of normal use for doors.id + d.id = 1000000000 + Strings::ToInt(row[0]); // Out of range of normal use for doors.id d.doorid = -1; // Client doesn't care if these are all the same door_id - d.pos_x = atof(row[2]); // xpos - d.pos_y = atof(row[3]); // ypos - d.pos_z = atof(row[4]); // zpos - d.heading = atof(row[5]); // heading + d.pos_x = Strings::ToFloat(row[2]); // xpos + d.pos_y = Strings::ToFloat(row[3]); // ypos + d.pos_z = Strings::ToFloat(row[4]); // zpos + d.heading = Strings::ToFloat(row[5]); // heading d.name = row[8]; // objectname @@ -223,10 +224,10 @@ bool Zone::LoadZoneObjects() d.dest_zone = "NONE"; - if ((d.size = atoi(row[11])) == 0) // unknown08 = optional size percentage + if ((d.size = Strings::ToInt(row[11])) == 0) // unknown08 = optional size percentage d.size = 100; - switch (d.opentype = atoi(row[12])) // unknown10 = optional request_nonsolid (0 or 1 or experimental number) + switch (d.opentype = Strings::ToInt(row[12])) // unknown10 = optional request_nonsolid (0 or 1 or experimental number) { case 0: d.opentype = 31; @@ -236,7 +237,7 @@ bool Zone::LoadZoneObjects() break; } - d.incline = atoi(row[13]); // unknown20 = optional model incline value + d.incline = Strings::ToInt(row[13]); // unknown20 = optional model incline value d.client_version_mask = 0xFFFFFFFF; // We should load the mask from the zone. auto door = new Doors(d); @@ -251,28 +252,28 @@ bool Zone::LoadZoneObjects() uint32 idx = 0; int16 charges = 0; - id = (uint32)atoi(row[0]); - data.zone_id = atoi(row[1]); - data.x = atof(row[2]); - data.y = atof(row[3]); - data.z = atof(row[4]); - data.heading = atof(row[5]); - itemid = (uint32)atoi(row[6]); - charges = (int16)atoi(row[7]); + id = (uint32)Strings::ToInt(row[0]); + data.zone_id = Strings::ToInt(row[1]); + data.x = Strings::ToFloat(row[2]); + data.y = Strings::ToFloat(row[3]); + data.z = Strings::ToFloat(row[4]); + data.heading = Strings::ToFloat(row[5]); + itemid = (uint32)Strings::ToInt(row[6]); + charges = (int16)Strings::ToInt(row[7]); strcpy(data.object_name, row[8]); - type = (uint8)atoi(row[9]); - icon = (uint32)atoi(row[10]); + type = (uint8)Strings::ToInt(row[9]); + icon = (uint32)Strings::ToInt(row[10]); data.object_type = type; data.linked_list_addr[0] = 0; data.linked_list_addr[1] = 0; - data.solidtype = (uint32)atoi(row[12]); - data.unknown020 = (uint32)atoi(row[13]); - data.unknown024 = (uint32)atoi(row[14]); - data.unknown076 = (uint32)atoi(row[15]); - data.size = atof(row[16]); - data.tilt_x = atof(row[17]); - data.tilt_y = atof(row[18]); + data.solidtype = (uint32)Strings::ToInt(row[12]); + data.unknown020 = (uint32)Strings::ToInt(row[13]); + data.unknown024 = (uint32)Strings::ToInt(row[14]); + data.unknown076 = (uint32)Strings::ToInt(row[15]); + data.size = Strings::ToFloat(row[16]); + data.tilt_x = Strings::ToFloat(row[17]); + data.tilt_y = Strings::ToFloat(row[18]); data.unknown084 = 0; @@ -578,7 +579,7 @@ void Zone::LoadTempMerchantData() uint32 npc_id = 0; for (auto row = results.begin(); row != results.end(); ++row) { TempMerchantList temp_merchant_list; - temp_merchant_list.npcid = atoul(row[0]); + temp_merchant_list.npcid = Strings::ToUnsignedInt(row[0]); if (npc_id != temp_merchant_list.npcid) { temp_merchant_table_entry = tmpmerchanttable.find(temp_merchant_list.npcid); if (temp_merchant_table_entry == tmpmerchanttable.end()) { @@ -589,9 +590,9 @@ void Zone::LoadTempMerchantData() npc_id = temp_merchant_list.npcid; } - temp_merchant_list.slot = atoul(row[1]); - temp_merchant_list.charges = atoul(row[2]); - temp_merchant_list.item = atoul(row[3]); + temp_merchant_list.slot = Strings::ToUnsignedInt(row[1]); + temp_merchant_list.charges = Strings::ToUnsignedInt(row[2]); + temp_merchant_list.item = Strings::ToUnsignedInt(row[3]); temp_merchant_list.origslot = temp_merchant_list.slot; LogMerchants( @@ -611,45 +612,34 @@ void Zone::LoadNewMerchantData(uint32 merchantid) { std::list merchant_list; - auto query = fmt::format( - SQL( - SELECT - item, - slot, - faction_required, - level_required, - alt_currency_cost, - classes_required, - probability, - bucket_name, - bucket_value, - bucket_comparison - FROM merchantlist - WHERE merchantid = {} {} - ORDER BY slot - ), - merchantid, - ContentFilterCriteria::apply() + const auto& l = MerchantlistRepository::GetWhere( + content_db, + fmt::format( + "merchantid = {} {} ORDER BY slot", + merchantid, + ContentFilterCriteria::apply() + ) ); - auto results = content_db.QueryDatabase(query); - if (!results.Success()) { - return; + if (l.empty()) { + return; } - for (auto row : results) { + for (const auto& e : l) { MerchantList ml; - ml.id = merchantid; - ml.item = std::stoul(row[0]); - ml.slot = std::stoul(row[1]); - ml.faction_required = static_cast(std::stoi(row[2])); - ml.level_required = static_cast(std::stoul(row[3])); - ml.alt_currency_cost = static_cast(std::stoul(row[4])); - ml.classes_required = std::stoul(row[5]); - ml.probability = static_cast(std::stoul(row[6])); - ml.bucket_name = row[7]; - ml.bucket_value = row[8]; - ml.bucket_comparison = static_cast(std::stoul(row[9])); + ml.id = merchantid; + ml.item = e.item; + ml.slot = e.slot; + ml.faction_required = e.faction_required; + ml.level_required = e.level_required; + ml.min_status = e.min_status; + ml.max_status = e.max_status; + ml.alt_currency_cost = e.alt_currency_cost; + ml.classes_required = e.classes_required; + ml.probability = e.probability; + ml.bucket_name = e.bucket_name; + ml.bucket_value = e.bucket_value; + ml.bucket_comparison = e.bucket_comparison; merchant_list.push_back(ml); } @@ -665,6 +655,8 @@ void Zone::GetMerchantDataForZoneLoad() { item, faction_required, level_required, + min_status, + max_status, alt_currency_cost, classes_required, probability, @@ -701,7 +693,7 @@ void Zone::GetMerchantDataForZoneLoad() { for (auto row : results) { MerchantList mle{}; - mle.id = std::stoul(row[0]); + mle.id = Strings::ToUnsignedInt(row[0]); if (npc_id != mle.id) { merchant_list = merchanttable.find(mle.id); if (merchant_list == merchanttable.end()) { @@ -725,16 +717,18 @@ void Zone::GetMerchantDataForZoneLoad() { continue; } - mle.slot = std::stoul(row[1]); - mle.item = std::stoul(row[2]); - mle.faction_required = static_cast(std::stoi(row[3])); - mle.level_required = static_cast(std::stoul(row[4])); - mle.alt_currency_cost = static_cast(std::stoul(row[5])); - mle.classes_required = std::stoul(row[6]); - mle.probability = static_cast(std::stoul(row[7])); - mle.bucket_name = row[8]; - mle.bucket_value = row[9]; - mle.bucket_comparison = static_cast(std::stoul(row[10])); + mle.slot = Strings::ToUnsignedInt(row[1]); + mle.item = Strings::ToUnsignedInt(row[2]); + mle.faction_required = static_cast(Strings::ToInt(row[3])); + mle.level_required = static_cast(Strings::ToUnsignedInt(row[4])); + mle.min_status = static_cast(Strings::ToUnsignedInt(row[5])); + mle.max_status = static_cast(Strings::ToUnsignedInt(row[6])); + mle.alt_currency_cost = static_cast(Strings::ToUnsignedInt(row[7])); + mle.classes_required = Strings::ToUnsignedInt(row[8]); + mle.probability = static_cast(Strings::ToUnsignedInt(row[9])); + mle.bucket_name = row[10]; + mle.bucket_value = row[11]; + mle.bucket_comparison = static_cast(Strings::ToUnsignedInt(row[12])); merchant_list->second.push_back(mle); } @@ -754,10 +748,10 @@ void Zone::LoadMercTemplates(){ for (auto row = results.begin(); row != results.end(); ++row) { MercStanceInfo tempMercStanceInfo; - tempMercStanceInfo.ClassID = atoi(row[0]); - tempMercStanceInfo.ProficiencyID = atoi(row[1]); - tempMercStanceInfo.StanceID = atoi(row[2]); - tempMercStanceInfo.IsDefault = atoi(row[3]); + tempMercStanceInfo.ClassID = Strings::ToInt(row[0]); + tempMercStanceInfo.ProficiencyID = Strings::ToInt(row[1]); + tempMercStanceInfo.StanceID = Strings::ToInt(row[2]); + tempMercStanceInfo.IsDefault = Strings::ToInt(row[3]); merc_stances.push_back(tempMercStanceInfo); } @@ -780,16 +774,16 @@ void Zone::LoadMercTemplates(){ MercTemplate tempMercTemplate; - tempMercTemplate.MercTemplateID = atoi(row[0]); - tempMercTemplate.MercType = atoi(row[1]); - tempMercTemplate.MercSubType = atoi(row[2]); - tempMercTemplate.RaceID = atoi(row[3]); - tempMercTemplate.ClassID = atoi(row[4]); - tempMercTemplate.ProficiencyID = atoi(row[5]); - tempMercTemplate.TierID = atoi(row[6]); - tempMercTemplate.CostFormula = atoi(row[7]); - tempMercTemplate.ClientVersion = atoi(row[8]); - tempMercTemplate.MercNPCID = atoi(row[9]); + tempMercTemplate.MercTemplateID = Strings::ToInt(row[0]); + tempMercTemplate.MercType = Strings::ToInt(row[1]); + tempMercTemplate.MercSubType = Strings::ToInt(row[2]); + tempMercTemplate.RaceID = Strings::ToInt(row[3]); + tempMercTemplate.ClassID = Strings::ToInt(row[4]); + tempMercTemplate.ProficiencyID = Strings::ToInt(row[5]); + tempMercTemplate.TierID = Strings::ToInt(row[6]); + tempMercTemplate.CostFormula = Strings::ToInt(row[7]); + tempMercTemplate.ClientVersion = Strings::ToInt(row[8]); + tempMercTemplate.MercNPCID = Strings::ToInt(row[9]); for(int i = 0; i < MaxMercStanceID; i++) tempMercTemplate.Stances[i] = 0; @@ -821,9 +815,9 @@ void Zone::LoadLevelEXPMods(){ } for (auto row = results.begin(); row != results.end(); ++row) { - uint32 index = atoi(row[0]); - float exp_mod = atof(row[1]); - float aa_exp_mod = atof(row[2]); + uint32 index = Strings::ToInt(row[0]); + float exp_mod = Strings::ToFloat(row[1]); + float aa_exp_mod = Strings::ToFloat(row[2]); level_exp_mod[index].ExpMod = exp_mod; level_exp_mod[index].AAExpMod = aa_exp_mod; } @@ -848,15 +842,15 @@ void Zone::LoadMercSpells(){ uint32 classid; MercSpellEntry tempMercSpellEntry; - classid = atoi(row[0]); - tempMercSpellEntry.proficiencyid = atoi(row[1]); - tempMercSpellEntry.spellid = atoi(row[2]); - tempMercSpellEntry.type = atoi(row[3]); - tempMercSpellEntry.stance = atoi(row[4]); - tempMercSpellEntry.minlevel = atoi(row[5]); - tempMercSpellEntry.maxlevel = atoi(row[6]); - tempMercSpellEntry.slot = atoi(row[7]); - tempMercSpellEntry.proc_chance = atoi(row[8]); + classid = Strings::ToInt(row[0]); + tempMercSpellEntry.proficiencyid = Strings::ToInt(row[1]); + tempMercSpellEntry.spellid = Strings::ToInt(row[2]); + tempMercSpellEntry.type = Strings::ToInt(row[3]); + tempMercSpellEntry.stance = Strings::ToInt(row[4]); + tempMercSpellEntry.minlevel = Strings::ToInt(row[5]); + tempMercSpellEntry.maxlevel = Strings::ToInt(row[6]); + tempMercSpellEntry.slot = Strings::ToInt(row[7]); + tempMercSpellEntry.proc_chance = Strings::ToInt(row[8]); merc_spells_list[classid].push_back(tempMercSpellEntry); } @@ -1224,8 +1218,7 @@ bool Zone::Init(bool is_static) { LoadGrids(); LoadTickItems(); - //MODDING HOOK FOR ZONE INIT - mod_init(); + npc_scale_manager->LoadScaleData(); // logging origination information LogSys.origination_info.zone_short_name = zone->short_name; @@ -1237,6 +1230,8 @@ bool Zone::Init(bool is_static) { void Zone::ReloadStaticData() { LogInfo("Reloading Zone Static Data"); + entity_list.RemoveAllObjects(); //Ground spawns are also objects we clear list then fill it + entity_list.RemoveAllDoors(); //Some objects are also doors so clear list before filling if (!content_db.LoadStaticZonePoints(&zone_point_list, GetShortName(), GetInstanceVersion())) { LogError("Loading static zone points failed"); @@ -1255,14 +1250,12 @@ void Zone::ReloadStaticData() { LogError("Reloading ground spawns failed. continuing"); } - entity_list.RemoveAllObjects(); LogInfo("Reloading World Objects from DB"); if (!LoadZoneObjects()) { LogError("Reloading World Objects failed. continuing"); } - entity_list.RemoveAllDoors(); LoadZoneDoors(); entity_list.RespawnAllDoors(); @@ -1933,9 +1926,6 @@ void Zone::Repop() initgrids_timer.Start(); entity_list.UpdateAllTraps(true, true); - - //MODDING HOOK FOR REPOP - mod_repop(); } void Zone::GetTimeSync() @@ -2178,10 +2168,10 @@ bool ZoneDatabase::GetDecayTimes(npcDecayTimes_Struct *npcCorpseDecayTimes) int index = 0; for (auto row = results.begin(); row != results.end(); ++row, ++index) { Seperator sep(row[0]); - npcCorpseDecayTimes[index].minlvl = atoi(sep.arg[1]); - npcCorpseDecayTimes[index].maxlvl = atoi(sep.arg[2]); + npcCorpseDecayTimes[index].minlvl = Strings::ToInt(sep.arg[1]); + npcCorpseDecayTimes[index].maxlvl = Strings::ToInt(sep.arg[2]); - npcCorpseDecayTimes[index].seconds = std::min(24 * 60 * 60, atoi(row[1])); + npcCorpseDecayTimes[index].seconds = std::min(24 * 60 * 60, Strings::ToInt(row[1])); } LogInfo("Loaded [{}] decay timers", Strings::Commify(results.RowCount())); @@ -2350,11 +2340,11 @@ void Zone::LoadLDoNTraps() for (auto row = results.begin(); row != results.end(); ++row) { auto lt = new LDoNTrapTemplate; - lt->id = atoi(row[0]); - lt->type = (LDoNChestTypes) atoi(row[1]); - lt->spell_id = atoi(row[2]); - lt->skill = atoi(row[3]); - lt->locked = atoi(row[4]); + lt->id = Strings::ToInt(row[0]); + lt->type = (LDoNChestTypes) Strings::ToInt(row[1]); + lt->spell_id = Strings::ToInt(row[2]); + lt->skill = Strings::ToInt(row[3]); + lt->locked = Strings::ToInt(row[4]); ldon_trap_list[lt->id] = lt; } @@ -2370,8 +2360,8 @@ void Zone::LoadLDoNTrapEntries() for (auto row = results.begin(); row != results.end(); ++row) { - uint32 id = atoi(row[0]); - uint32 trap_id = atoi(row[1]); + uint32 id = Strings::ToInt(row[0]); + uint32 trap_id = Strings::ToInt(row[1]); LDoNTrapTemplate *trapTemplate = nullptr; auto it = ldon_trap_list.find(trap_id); @@ -2414,7 +2404,7 @@ void Zone::LoadVeteranRewards() int index = 0; for (auto row = results.begin(); row != results.end(); ++row, ++index) { - uint32 claim = atoi(row[0]); + uint32 claim = Strings::ToInt(row[0]); if(claim != current_reward.claim_id) { @@ -2431,8 +2421,8 @@ void Zone::LoadVeteranRewards() } strcpy(current_reward.items[index].item_name, row[1]); - current_reward.items[index].item_id = atoi(row[2]); - current_reward.items[index].charges = atoi(row[3]); + current_reward.items[index].item_id = Strings::ToInt(row[2]); + current_reward.items[index].charges = Strings::ToInt(row[3]); } if(current_reward.claim_id != 0) @@ -2457,8 +2447,8 @@ void Zone::LoadAlternateCurrencies() } for (auto row : results) { - current_currency.id = std::stoul(row[0]); - current_currency.item_id = std::stoul(row[1]); + current_currency.id = Strings::ToUnsignedInt(row[0]); + current_currency.item_id = Strings::ToUnsignedInt(row[1]); AlternateCurrencies.push_back(current_currency); } @@ -2504,7 +2494,7 @@ void Zone::LoadAdventureFlavor() } for (auto row = results.begin(); row != results.end(); ++row) { - uint32 id = atoi(row[0]); + uint32 id = Strings::ToInt(row[0]); adventure_entry_list_flavor[id] = row[1]; } @@ -2587,9 +2577,9 @@ void Zone::LoadNPCEmotes(LinkedList* NPCEmoteList) for (auto row = results.begin(); row != results.end(); ++row) { auto nes = new NPC_Emote_Struct; - nes->emoteid = atoi(row[0]); - nes->event_ = atoi(row[1]); - nes->type = atoi(row[2]); + nes->emoteid = Strings::ToInt(row[0]); + nes->event_ = Strings::ToInt(row[1]); + nes->type = Strings::ToInt(row[2]); strn0cpy(nes->text, row[3], sizeof(nes->text)); NPCEmoteList->Insert(nes); } @@ -2672,16 +2662,16 @@ void Zone::LoadTickItems() for (auto row = results.begin(); row != results.end(); ++row) { - if(atoi(row[0]) == 0) + if(Strings::ToInt(row[0]) == 0) continue; item_tick_struct ti_tmp; - ti_tmp.itemid = atoi(row[0]); - ti_tmp.chance = atoi(row[1]); - ti_tmp.level = atoi(row[2]); - ti_tmp.bagslot = (int16)atoi(row[4]); + ti_tmp.itemid = Strings::ToInt(row[0]); + ti_tmp.chance = Strings::ToInt(row[1]); + ti_tmp.level = Strings::ToInt(row[2]); + ti_tmp.bagslot = (int16)Strings::ToInt(row[4]); ti_tmp.qglobal = std::string(row[3]); - tick_items[atoi(row[0])] = ti_tmp; + tick_items[Strings::ToInt(row[0])] = ti_tmp; } @@ -2984,6 +2974,12 @@ std::string Zone::GetAAName(int aa_id) const auto& a = aa_abilities.find(current_aa_id); if (a != aa_abilities.end()) { return a->second.get()->name; + } else { + for (const auto& b : aa_abilities) { + if (b.second.get()->first->id == aa_id) { + return b.second.get()->name; + } + } } } @@ -3021,7 +3017,7 @@ bool Zone::CheckDataBucket(uint8 bucket_comparison, std::string bucket_value, st break; } - if (std::stoll(player_value) < std::stoll(bucket_value)) { + if (Strings::ToBigInt(player_value) < Strings::ToBigInt(bucket_value)) { break; } @@ -3034,7 +3030,7 @@ bool Zone::CheckDataBucket(uint8 bucket_comparison, std::string bucket_value, st break; } - if (std::stoll(player_value) > std::stoll(bucket_value)) { + if (Strings::ToBigInt(player_value) > Strings::ToBigInt(bucket_value)) { break; } @@ -3047,7 +3043,7 @@ bool Zone::CheckDataBucket(uint8 bucket_comparison, std::string bucket_value, st break; } - if (std::stoll(player_value) <= std::stoll(bucket_value)) { + if (Strings::ToBigInt(player_value) <= Strings::ToBigInt(bucket_value)) { break; } @@ -3060,7 +3056,7 @@ bool Zone::CheckDataBucket(uint8 bucket_comparison, std::string bucket_value, st break; } - if (std::stoll(player_value) >= std::stoll(bucket_value)) { + if (Strings::ToBigInt(player_value) >= Strings::ToBigInt(bucket_value)) { break; } @@ -3121,9 +3117,9 @@ bool Zone::CheckDataBucket(uint8 bucket_comparison, std::string bucket_value, st if ( !EQ::ValueWithin( - std::stoll(player_value), - std::stoll(bucket_checks[0]), - std::stoll(bucket_checks[1]) + Strings::ToBigInt(player_value), + Strings::ToBigInt(bucket_checks[0]), + Strings::ToBigInt(bucket_checks[1]) ) ) { break; @@ -3149,9 +3145,9 @@ bool Zone::CheckDataBucket(uint8 bucket_comparison, std::string bucket_value, st if ( EQ::ValueWithin( - std::stoll(player_value), - std::stoll(bucket_checks[0]), - std::stoll(bucket_checks[1]) + Strings::ToBigInt(player_value), + Strings::ToBigInt(bucket_checks[0]), + Strings::ToBigInt(bucket_checks[1]) ) ) { break; diff --git a/zone/zone.h b/zone/zone.h index 3d404397c..aa95a0e6c 100755 --- a/zone/zone.h +++ b/zone/zone.h @@ -395,11 +395,6 @@ public: double GetMaxMovementUpdateRange() const { return max_movement_update_range; } - /** - * Modding hooks - */ - void mod_init(); - void mod_repop(); void SetIsHotzone(bool is_hotzone); private: @@ -420,7 +415,7 @@ private: char *long_name; char *map_name; char *short_name; - char file_name[16]; + char file_name[32]; glm::vec4 m_safe_points; glm::vec4 m_graveyard; int default_ruleset; diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index b81eef4c5..734b70677 100755 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -13,6 +13,7 @@ #include "zonedb.h" #include "aura.h" #include "../common/repositories/criteria/content_filter_criteria.h" +#include "../common/repositories/character_disciplines_repository.h" #include "../common/repositories/npc_types_repository.h" #include @@ -150,8 +151,8 @@ uint32 ZoneDatabase::GetSpawnTimeLeft(uint32 id, uint16 instance_id) timeval tv; gettimeofday(&tv, nullptr); - uint32 resStart = atoi(row[0]); - uint32 resDuration = atoi(row[1]); + uint32 resStart = Strings::ToInt(row[0]); + uint32 resDuration = Strings::ToInt(row[1]); //compare our values to current time if((resStart + resDuration) <= tv.tv_sec) { @@ -170,34 +171,6 @@ void ZoneDatabase::UpdateSpawn2Status(uint32 id, uint8 new_status) QueryDatabase(query); } -bool ZoneDatabase::logevents(const char* accountname,uint32 accountid,uint8 status,const char* charname, const char* target,const char* descriptiontype, const char* description,int event_nid){ - - uint32 len = strlen(description); - uint32 len2 = strlen(target); - auto descriptiontext = new char[2 * len + 1]; - auto targetarr = new char[2 * len2 + 1]; - memset(descriptiontext, 0, 2*len+1); - memset(targetarr, 0, 2*len2+1); - DoEscapeString(descriptiontext, description, len); - DoEscapeString(targetarr, target, len2); - - std::string query = StringFormat("INSERT INTO eventlog (accountname, accountid, status, " - "charname, target, descriptiontype, description, event_nid) " - "VALUES('%s', %i, %i, '%s', '%s', '%s', '%s', '%i')", - accountname, accountid, status, charname, targetarr, - descriptiontype, descriptiontext, event_nid); - safe_delete_array(descriptiontext); - safe_delete_array(targetarr); - auto results = QueryDatabase(query); - if (!results.Success()) { - return false; - } - - return true; -} - - - bool ZoneDatabase::SetSpecialAttkFlag(uint8 id, const char* flag) { std::string query = StringFormat("UPDATE npc_types SET npcspecialattks='%s' WHERE id = %i;", flag, id); @@ -228,16 +201,16 @@ void ZoneDatabase::LoadWorldContainer(uint32 parentid, EQ::ItemInstance* contain } for (auto& row = results.begin(); row != results.end(); ++row) { - uint8 index = (uint8)atoi(row[0]); - uint32 item_id = (uint32)atoi(row[1]); - int8 charges = (int8)atoi(row[2]); + uint8 index = (uint8)Strings::ToInt(row[0]); + uint32 item_id = (uint32)Strings::ToInt(row[1]); + int8 charges = (int8)Strings::ToInt(row[2]); uint32 aug[EQ::invaug::SOCKET_COUNT]; - aug[0] = (uint32)atoi(row[3]); - aug[1] = (uint32)atoi(row[4]); - aug[2] = (uint32)atoi(row[5]); - aug[3] = (uint32)atoi(row[6]); - aug[4] = (uint32)atoi(row[7]); - aug[5] = (uint32)atoi(row[8]); + aug[0] = (uint32)Strings::ToInt(row[3]); + aug[1] = (uint32)Strings::ToInt(row[4]); + aug[2] = (uint32)Strings::ToInt(row[5]); + aug[3] = (uint32)Strings::ToInt(row[6]); + aug[4] = (uint32)Strings::ToInt(row[7]); + aug[5] = (uint32)Strings::ToInt(row[8]); EQ::ItemInstance* inst = database.CreateItem(item_id, charges); if (inst && inst->GetItem()->IsClassCommon()) { @@ -328,13 +301,13 @@ Trader_Struct* ZoneDatabase::LoadTraderItem(uint32 char_id) loadti->Code = BazaarTrader_ShowItems; for (auto& row = results.begin(); row != results.end(); ++row) { - if (atoi(row[5]) >= 80 || atoi(row[4]) < 0) { + if (Strings::ToInt(row[5]) >= 80 || Strings::ToInt(row[4]) < 0) { LogTrading("Bad Slot number when trying to load trader information!\n"); continue; } - loadti->Items[atoi(row[5])] = atoi(row[1]); - loadti->ItemCost[atoi(row[5])] = atoi(row[4]); + loadti->Items[Strings::ToInt(row[5])] = Strings::ToInt(row[1]); + loadti->ItemCost[Strings::ToInt(row[5])] = Strings::ToInt(row[4]); } return loadti; } @@ -352,15 +325,15 @@ TraderCharges_Struct* ZoneDatabase::LoadTraderItemWithCharges(uint32 char_id) } for (auto& row = results.begin(); row != results.end(); ++row) { - if (atoi(row[5]) >= 80 || atoi(row[5]) < 0) { + if (Strings::ToInt(row[5]) >= 80 || Strings::ToInt(row[5]) < 0) { LogTrading("Bad Slot number when trying to load trader information!\n"); continue; } - loadti->ItemID[atoi(row[5])] = atoi(row[1]); - loadti->SerialNumber[atoi(row[5])] = atoi(row[2]); - loadti->Charges[atoi(row[5])] = atoi(row[3]); - loadti->ItemCost[atoi(row[5])] = atoi(row[4]); + loadti->ItemID[Strings::ToInt(row[5])] = Strings::ToInt(row[1]); + loadti->SerialNumber[Strings::ToInt(row[5])] = Strings::ToInt(row[2]); + loadti->Charges[Strings::ToInt(row[5])] = Strings::ToInt(row[3]); + loadti->ItemCost[Strings::ToInt(row[5])] = Strings::ToInt(row[4]); } return loadti; } @@ -379,9 +352,9 @@ EQ::ItemInstance* ZoneDatabase::LoadSingleTraderItem(uint32 CharID, int SerialNu auto& row = results.begin(); - int ItemID = atoi(row[1]); - int Charges = atoi(row[3]); - int Cost = atoi(row[4]); + int ItemID = Strings::ToInt(row[1]); + int Charges = Strings::ToInt(row[3]); + int Cost = Strings::ToInt(row[4]); const EQ::ItemData *item = database.GetItem(ItemID); @@ -649,96 +622,96 @@ bool ZoneDatabase::LoadCharacterData(uint32 character_id, PlayerProfile_Struct* for (auto& row = results.begin(); row != results.end(); ++row) { strcpy(pp->name, row[r]); r++; // "`name`, " strcpy(pp->last_name, row[r]); r++; // "last_name, " - pp->gender = atoi(row[r]); r++; // "gender, " - pp->race = atoi(row[r]); r++; // "race, " - pp->class_ = atoi(row[r]); r++; // "class, " - pp->level = atoi(row[r]); r++; // "`level`, " - pp->deity = atoi(row[r]); r++; // "deity, " - pp->birthday = atoi(row[r]); r++; // "birthday, " - pp->lastlogin = atoi(row[r]); r++; // "last_login, " - pp->timePlayedMin = atoi(row[r]); r++; // "time_played, " - pp->pvp = atoi(row[r]); r++; // "pvp_status, " - pp->level2 = atoi(row[r]); r++; // "level2, " - pp->anon = atoi(row[r]); r++; // "anon, " - pp->gm = atoi(row[r]); r++; // "gm, " - pp->intoxication = atoi(row[r]); r++; // "intoxication, " - pp->haircolor = atoi(row[r]); r++; // "hair_color, " - pp->beardcolor = atoi(row[r]); r++; // "beard_color, " - pp->eyecolor1 = atoi(row[r]); r++; // "eye_color_1, " - pp->eyecolor2 = atoi(row[r]); r++; // "eye_color_2, " - pp->hairstyle = atoi(row[r]); r++; // "hair_style, " - pp->beard = atoi(row[r]); r++; // "beard, " - pp->ability_time_seconds = atoi(row[r]); r++; // "ability_time_seconds, " - pp->ability_number = atoi(row[r]); r++; // "ability_number, " - pp->ability_time_minutes = atoi(row[r]); r++; // "ability_time_minutes, " - pp->ability_time_hours = atoi(row[r]); r++; // "ability_time_hours, " + pp->gender = Strings::ToInt(row[r]); r++; // "gender, " + pp->race = Strings::ToInt(row[r]); r++; // "race, " + pp->class_ = Strings::ToInt(row[r]); r++; // "class, " + pp->level = Strings::ToInt(row[r]); r++; // "`level`, " + pp->deity = Strings::ToInt(row[r]); r++; // "deity, " + pp->birthday = Strings::ToInt(row[r]); r++; // "birthday, " + pp->lastlogin = Strings::ToInt(row[r]); r++; // "last_login, " + pp->timePlayedMin = Strings::ToInt(row[r]); r++; // "time_played, " + pp->pvp = Strings::ToInt(row[r]); r++; // "pvp_status, " + pp->level2 = Strings::ToInt(row[r]); r++; // "level2, " + pp->anon = Strings::ToInt(row[r]); r++; // "anon, " + pp->gm = Strings::ToInt(row[r]); r++; // "gm, " + pp->intoxication = Strings::ToInt(row[r]); r++; // "intoxication, " + pp->haircolor = Strings::ToInt(row[r]); r++; // "hair_color, " + pp->beardcolor = Strings::ToInt(row[r]); r++; // "beard_color, " + pp->eyecolor1 = Strings::ToInt(row[r]); r++; // "eye_color_1, " + pp->eyecolor2 = Strings::ToInt(row[r]); r++; // "eye_color_2, " + pp->hairstyle = Strings::ToInt(row[r]); r++; // "hair_style, " + pp->beard = Strings::ToInt(row[r]); r++; // "beard, " + pp->ability_time_seconds = Strings::ToInt(row[r]); r++; // "ability_time_seconds, " + pp->ability_number = Strings::ToInt(row[r]); r++; // "ability_number, " + pp->ability_time_minutes = Strings::ToInt(row[r]); r++; // "ability_time_minutes, " + pp->ability_time_hours = Strings::ToInt(row[r]); r++; // "ability_time_hours, " strcpy(pp->title, row[r]); r++; // "title, " strcpy(pp->suffix, row[r]); r++; // "suffix, " - pp->exp = atoi(row[r]); r++; // "exp, " - pp->points = atoi(row[r]); r++; // "points, " - pp->mana = atoi(row[r]); r++; // "mana, " - pp->cur_hp = atoi(row[r]); r++; // "cur_hp, " - pp->STR = atoi(row[r]); r++; // "str, " - pp->STA = atoi(row[r]); r++; // "sta, " - pp->CHA = atoi(row[r]); r++; // "cha, " - pp->DEX = atoi(row[r]); r++; // "dex, " - pp->INT = atoi(row[r]); r++; // "`int`, " - pp->AGI = atoi(row[r]); r++; // "agi, " - pp->WIS = atoi(row[r]); r++; // "wis, " - pp->face = atoi(row[r]); r++; // "face, " - pp->y = atof(row[r]); r++; // "y, " - pp->x = atof(row[r]); r++; // "x, " - pp->z = atof(row[r]); r++; // "z, " - pp->heading = atof(row[r]); r++; // "heading, " - pp->pvp2 = atoi(row[r]); r++; // "pvp2, " - pp->pvptype = atoi(row[r]); r++; // "pvp_type, " - pp->autosplit = atoi(row[r]); r++; // "autosplit_enabled, " - pp->zone_change_count = atoi(row[r]); r++; // "zone_change_count, " - pp->drakkin_heritage = atoi(row[r]); r++; // "drakkin_heritage, " - pp->drakkin_tattoo = atoi(row[r]); r++; // "drakkin_tattoo, " - pp->drakkin_details = atoi(row[r]); r++; // "drakkin_details, " - pp->toxicity = atoi(row[r]); r++; // "toxicity, " - pp->hunger_level = atoi(row[r]); r++; // "hunger_level, " - pp->thirst_level = atoi(row[r]); r++; // "thirst_level, " - pp->ability_up = atoi(row[r]); r++; // "ability_up, " - pp->zone_id = atoi(row[r]); r++; // "zone_id, " - pp->zoneInstance = atoi(row[r]); r++; // "zone_instance, " - pp->leadAAActive = atoi(row[r]); r++; // "leadership_exp_on, " - pp->ldon_points_guk = atoi(row[r]); r++; // "ldon_points_guk, " - pp->ldon_points_mir = atoi(row[r]); r++; // "ldon_points_mir, " - pp->ldon_points_mmc = atoi(row[r]); r++; // "ldon_points_mmc, " - pp->ldon_points_ruj = atoi(row[r]); r++; // "ldon_points_ruj, " - pp->ldon_points_tak = atoi(row[r]); r++; // "ldon_points_tak, " - pp->ldon_points_available = atoi(row[r]); r++; // "ldon_points_available, " - pp->tribute_time_remaining = atoi(row[r]); r++; // "tribute_time_remaining, " - pp->showhelm = atoi(row[r]); r++; // "show_helm, " - pp->career_tribute_points = atoi(row[r]); r++; // "career_tribute_points, " - pp->tribute_points = atoi(row[r]); r++; // "tribute_points, " - pp->tribute_active = atoi(row[r]); r++; // "tribute_active, " - pp->endurance = atoi(row[r]); r++; // "endurance, " - pp->group_leadership_exp = atoi(row[r]); r++; // "group_leadership_exp, " - pp->raid_leadership_exp = atoi(row[r]); r++; // "raid_leadership_exp, " - pp->group_leadership_points = atoi(row[r]); r++; // "group_leadership_points, " - pp->raid_leadership_points = atoi(row[r]); r++; // "raid_leadership_points, " - pp->air_remaining = atoi(row[r]); r++; // "air_remaining, " - pp->PVPKills = atoi(row[r]); r++; // "pvp_kills, " - pp->PVPDeaths = atoi(row[r]); r++; // "pvp_deaths, " - pp->PVPCurrentPoints = atoi(row[r]); r++; // "pvp_current_points, " - pp->PVPCareerPoints = atoi(row[r]); r++; // "pvp_career_points, " - pp->PVPBestKillStreak = atoi(row[r]); r++; // "pvp_best_kill_streak, " - pp->PVPWorstDeathStreak = atoi(row[r]); r++; // "pvp_worst_death_streak, " - pp->PVPCurrentKillStreak = atoi(row[r]); r++; // "pvp_current_kill_streak, " - pp->aapoints_spent = atoi(row[r]); r++; // "aa_points_spent, " - pp->expAA = atoi(row[r]); r++; // "aa_exp, " - pp->aapoints = atoi(row[r]); r++; // "aa_points, " - pp->groupAutoconsent = atoi(row[r]); r++; // "group_auto_consent, " - pp->raidAutoconsent = atoi(row[r]); r++; // "raid_auto_consent, " - pp->guildAutoconsent = atoi(row[r]); r++; // "guild_auto_consent, " - pp->RestTimer = atoi(row[r]); r++; // "RestTimer, " - m_epp->aa_effects = atoi(row[r]); r++; // "`e_aa_effects`, " - m_epp->perAA = atoi(row[r]); r++; // "`e_percent_to_aa`, " - m_epp->expended_aa = atoi(row[r]); r++; // "`e_expended_aa_spent`, " - m_epp->last_invsnapshot_time = atoul(row[r]); r++; // "`e_last_invsnapshot` " + pp->exp = Strings::ToInt(row[r]); r++; // "exp, " + pp->points = Strings::ToInt(row[r]); r++; // "points, " + pp->mana = Strings::ToInt(row[r]); r++; // "mana, " + pp->cur_hp = Strings::ToInt(row[r]); r++; // "cur_hp, " + pp->STR = Strings::ToInt(row[r]); r++; // "str, " + pp->STA = Strings::ToInt(row[r]); r++; // "sta, " + pp->CHA = Strings::ToInt(row[r]); r++; // "cha, " + pp->DEX = Strings::ToInt(row[r]); r++; // "dex, " + pp->INT = Strings::ToInt(row[r]); r++; // "`int`, " + pp->AGI = Strings::ToInt(row[r]); r++; // "agi, " + pp->WIS = Strings::ToInt(row[r]); r++; // "wis, " + pp->face = Strings::ToInt(row[r]); r++; // "face, " + pp->y = Strings::ToFloat(row[r]); r++; // "y, " + pp->x = Strings::ToFloat(row[r]); r++; // "x, " + pp->z = Strings::ToFloat(row[r]); r++; // "z, " + pp->heading = Strings::ToFloat(row[r]); r++; // "heading, " + pp->pvp2 = Strings::ToInt(row[r]); r++; // "pvp2, " + pp->pvptype = Strings::ToInt(row[r]); r++; // "pvp_type, " + pp->autosplit = Strings::ToInt(row[r]); r++; // "autosplit_enabled, " + pp->zone_change_count = Strings::ToInt(row[r]); r++; // "zone_change_count, " + pp->drakkin_heritage = Strings::ToInt(row[r]); r++; // "drakkin_heritage, " + pp->drakkin_tattoo = Strings::ToInt(row[r]); r++; // "drakkin_tattoo, " + pp->drakkin_details = Strings::ToInt(row[r]); r++; // "drakkin_details, " + pp->toxicity = Strings::ToInt(row[r]); r++; // "toxicity, " + pp->hunger_level = Strings::ToInt(row[r]); r++; // "hunger_level, " + pp->thirst_level = Strings::ToInt(row[r]); r++; // "thirst_level, " + pp->ability_up = Strings::ToInt(row[r]); r++; // "ability_up, " + pp->zone_id = Strings::ToInt(row[r]); r++; // "zone_id, " + pp->zoneInstance = Strings::ToInt(row[r]); r++; // "zone_instance, " + pp->leadAAActive = Strings::ToInt(row[r]); r++; // "leadership_exp_on, " + pp->ldon_points_guk = Strings::ToInt(row[r]); r++; // "ldon_points_guk, " + pp->ldon_points_mir = Strings::ToInt(row[r]); r++; // "ldon_points_mir, " + pp->ldon_points_mmc = Strings::ToInt(row[r]); r++; // "ldon_points_mmc, " + pp->ldon_points_ruj = Strings::ToInt(row[r]); r++; // "ldon_points_ruj, " + pp->ldon_points_tak = Strings::ToInt(row[r]); r++; // "ldon_points_tak, " + pp->ldon_points_available = Strings::ToInt(row[r]); r++; // "ldon_points_available, " + pp->tribute_time_remaining = Strings::ToInt(row[r]); r++; // "tribute_time_remaining, " + pp->showhelm = Strings::ToInt(row[r]); r++; // "show_helm, " + pp->career_tribute_points = Strings::ToInt(row[r]); r++; // "career_tribute_points, " + pp->tribute_points = Strings::ToInt(row[r]); r++; // "tribute_points, " + pp->tribute_active = Strings::ToInt(row[r]); r++; // "tribute_active, " + pp->endurance = Strings::ToInt(row[r]); r++; // "endurance, " + pp->group_leadership_exp = Strings::ToInt(row[r]); r++; // "group_leadership_exp, " + pp->raid_leadership_exp = Strings::ToInt(row[r]); r++; // "raid_leadership_exp, " + pp->group_leadership_points = Strings::ToInt(row[r]); r++; // "group_leadership_points, " + pp->raid_leadership_points = Strings::ToInt(row[r]); r++; // "raid_leadership_points, " + pp->air_remaining = Strings::ToInt(row[r]); r++; // "air_remaining, " + pp->PVPKills = Strings::ToInt(row[r]); r++; // "pvp_kills, " + pp->PVPDeaths = Strings::ToInt(row[r]); r++; // "pvp_deaths, " + pp->PVPCurrentPoints = Strings::ToInt(row[r]); r++; // "pvp_current_points, " + pp->PVPCareerPoints = Strings::ToInt(row[r]); r++; // "pvp_career_points, " + pp->PVPBestKillStreak = Strings::ToInt(row[r]); r++; // "pvp_best_kill_streak, " + pp->PVPWorstDeathStreak = Strings::ToInt(row[r]); r++; // "pvp_worst_death_streak, " + pp->PVPCurrentKillStreak = Strings::ToInt(row[r]); r++; // "pvp_current_kill_streak, " + pp->aapoints_spent = Strings::ToInt(row[r]); r++; // "aa_points_spent, " + pp->expAA = Strings::ToInt(row[r]); r++; // "aa_exp, " + pp->aapoints = Strings::ToInt(row[r]); r++; // "aa_points, " + pp->groupAutoconsent = Strings::ToInt(row[r]); r++; // "group_auto_consent, " + pp->raidAutoconsent = Strings::ToInt(row[r]); r++; // "raid_auto_consent, " + pp->guildAutoconsent = Strings::ToInt(row[r]); r++; // "guild_auto_consent, " + pp->RestTimer = Strings::ToInt(row[r]); r++; // "RestTimer, " + m_epp->aa_effects = Strings::ToInt(row[r]); r++; // "`e_aa_effects`, " + m_epp->perAA = Strings::ToInt(row[r]); r++; // "`e_percent_to_aa`, " + m_epp->expended_aa = Strings::ToInt(row[r]); r++; // "`e_expended_aa_spent`, " + m_epp->last_invsnapshot_time = Strings::ToUnsignedInt(row[r]); r++; // "`e_last_invsnapshot` " m_epp->next_invsnapshot_time = m_epp->last_invsnapshot_time + (RuleI(Character, InvSnapshotMinIntervalM) * 60); } return true; @@ -747,7 +720,7 @@ bool ZoneDatabase::LoadCharacterData(uint32 character_id, PlayerProfile_Struct* bool ZoneDatabase::LoadCharacterFactionValues(uint32 character_id, faction_map & val_list) { std::string query = StringFormat("SELECT `faction_id`, `current_value` FROM `faction_values` WHERE `char_id` = %i", character_id); auto results = database.QueryDatabase(query); - for (auto& row = results.begin(); row != results.end(); ++row) { val_list[atoi(row[0])] = atoi(row[1]); } + for (auto& row = results.begin(); row != results.end(); ++row) { val_list[Strings::ToInt(row[0])] = Strings::ToInt(row[1]); } return true; } @@ -766,9 +739,9 @@ bool ZoneDatabase::LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_ pp->mem_spells[i] = 0xFFFFFFFF; } for (auto& row = results.begin(); row != results.end(); ++row) { - i = atoi(row[0]); - if (i < EQ::spells::SPELL_GEM_COUNT && atoi(row[1]) <= SPDAT_RECORDS){ - pp->mem_spells[i] = atoi(row[1]); + i = Strings::ToInt(row[0]); + if (i < EQ::spells::SPELL_GEM_COUNT && Strings::ToInt(row[1]) <= SPDAT_RECORDS){ + pp->mem_spells[i] = Strings::ToInt(row[1]); } } return true; @@ -794,8 +767,8 @@ bool ZoneDatabase::LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Str // Load them all so that server actions are valid..but, nix them in translators. for (auto& row = results.begin(); row != results.end(); ++row) { - int idx = atoi(row[0]); - int id = atoi(row[1]); + int idx = Strings::ToInt(row[0]); + int id = Strings::ToInt(row[1]); if (idx < 0 || idx >= EQ::spells::SPELLBOOK_SIZE) continue; @@ -822,9 +795,9 @@ bool ZoneDatabase::LoadCharacterLanguages(uint32 character_id, PlayerProfile_Str pp->languages[i] = 0; for (auto& row = results.begin(); row != results.end(); ++row) { - i = atoi(row[0]); + i = Strings::ToInt(row[0]); if (i < MAX_PP_LANGUAGE){ - pp->languages[i] = atoi(row[1]); + pp->languages[i] = Strings::ToInt(row[1]); } } @@ -835,29 +808,32 @@ bool ZoneDatabase::LoadCharacterLeadershipAA(uint32 character_id, PlayerProfile_ std::string query = StringFormat("SELECT slot, `rank` FROM character_leadership_abilities WHERE `id` = %u", character_id); auto results = database.QueryDatabase(query); uint32 slot = 0; for (auto& row = results.begin(); row != results.end(); ++row) { - slot = atoi(row[0]); - pp->leader_abilities.ranks[slot] = atoi(row[1]); + slot = Strings::ToInt(row[0]); + pp->leader_abilities.ranks[slot] = Strings::ToInt(row[1]); } return true; } bool ZoneDatabase::LoadCharacterDisciplines(uint32 character_id, PlayerProfile_Struct* pp){ - std::string query = StringFormat( - "SELECT " - "disc_id " - "FROM " - "`character_disciplines`" - "WHERE `id` = %u ORDER BY `slot_id`", character_id); - auto results = database.QueryDatabase(query); - int i = 0; + + auto character_disciplines = CharacterDisciplinesRepository::GetWhere( + database, fmt::format( + "`id` = {} ORDER BY `slot_id`", + character_id + ) + ); + + if (character_disciplines.empty()) { + return false; + } /* Initialize Disciplines */ memset(pp->disciplines.values, 0, (sizeof(pp->disciplines.values[0]) * MAX_PP_DISCIPLINES)); - for (auto& row = results.begin(); row != results.end(); ++row) { - if (i < MAX_PP_DISCIPLINES) - pp->disciplines.values[i] = atoi(row[0]); - ++i; - } + for (auto& row : character_disciplines) { + if (row.slot_id < MAX_PP_DISCIPLINES && IsValidSpell(row.disc_id)) { + pp->disciplines.values[row.slot_id] = row.disc_id; + } + } return true; } @@ -876,9 +852,9 @@ bool ZoneDatabase::LoadCharacterSkills(uint32 character_id, PlayerProfile_Struct pp->skills[i] = 0; for (auto& row = results.begin(); row != results.end(); ++row) { - i = atoi(row[0]); + i = Strings::ToInt(row[0]); if (i < MAX_PP_SKILL) - pp->skills[i] = atoi(row[1]); + pp->skills[i] = Strings::ToInt(row[1]); } return true; @@ -908,22 +884,22 @@ bool ZoneDatabase::LoadCharacterCurrency(uint32 character_id, PlayerProfile_Stru "WHERE `id` = %i ", character_id); auto results = database.QueryDatabase(query); for (auto& row = results.begin(); row != results.end(); ++row) { - pp->platinum = atoi(row[0]); - pp->gold = atoi(row[1]); - pp->silver = atoi(row[2]); - pp->copper = atoi(row[3]); - pp->platinum_bank = atoi(row[4]); - pp->gold_bank = atoi(row[5]); - pp->silver_bank = atoi(row[6]); - pp->copper_bank = atoi(row[7]); - pp->platinum_cursor = atoi(row[8]); - pp->gold_cursor = atoi(row[9]); - pp->silver_cursor = atoi(row[10]); - pp->copper_cursor = atoi(row[11]); - pp->currentRadCrystals = atoi(row[12]); - pp->careerRadCrystals = atoi(row[13]); - pp->currentEbonCrystals = atoi(row[14]); - pp->careerEbonCrystals = atoi(row[15]); + pp->platinum = Strings::ToInt(row[0]); + pp->gold = Strings::ToInt(row[1]); + pp->silver = Strings::ToInt(row[2]); + pp->copper = Strings::ToInt(row[3]); + pp->platinum_bank = Strings::ToInt(row[4]); + pp->gold_bank = Strings::ToInt(row[5]); + pp->silver_bank = Strings::ToInt(row[6]); + pp->copper_bank = Strings::ToInt(row[7]); + pp->platinum_cursor = Strings::ToInt(row[8]); + pp->gold_cursor = Strings::ToInt(row[9]); + pp->silver_cursor = Strings::ToInt(row[10]); + pp->copper_cursor = Strings::ToInt(row[11]); + pp->currentRadCrystals = Strings::ToInt(row[12]); + pp->careerRadCrystals = Strings::ToInt(row[13]); + pp->currentEbonCrystals = Strings::ToInt(row[14]); + pp->careerEbonCrystals = Strings::ToInt(row[15]); } return true; } @@ -933,11 +909,11 @@ bool ZoneDatabase::LoadCharacterMaterialColor(uint32 character_id, PlayerProfile auto results = database.QueryDatabase(query); int i = 0; int r = 0; for (auto& row = results.begin(); row != results.end(); ++row) { r = 0; - i = atoi(row[r]); /* Slot */ r++; - pp->item_tint.Slot[i].Blue = atoi(row[r]); r++; - pp->item_tint.Slot[i].Green = atoi(row[r]); r++; - pp->item_tint.Slot[i].Red = atoi(row[r]); r++; - pp->item_tint.Slot[i].UseTint = atoi(row[r]); + i = Strings::ToInt(row[r]); /* Slot */ r++; + pp->item_tint.Slot[i].Blue = Strings::ToInt(row[r]); r++; + pp->item_tint.Slot[i].Green = Strings::ToInt(row[r]); r++; + pp->item_tint.Slot[i].Red = Strings::ToInt(row[r]); r++; + pp->item_tint.Slot[i].UseTint = Strings::ToInt(row[r]); } return true; } @@ -958,13 +934,13 @@ bool ZoneDatabase::LoadCharacterBandolier(uint32 character_id, PlayerProfile_Str for (auto& row = results.begin(); row != results.end(); ++row) { r = 0; - i = atoi(row[r]); /* Bandolier ID */ r++; - si = atoi(row[r]); /* Bandolier Slot */ r++; + i = Strings::ToInt(row[r]); /* Bandolier ID */ r++; + si = Strings::ToInt(row[r]); /* Bandolier Slot */ r++; - const EQ::ItemData* item_data = database.GetItem(atoi(row[r])); + const EQ::ItemData* item_data = database.GetItem(Strings::ToInt(row[r])); if (item_data) { pp->bandoliers[i].Items[si].ID = item_data->ID; r++; - pp->bandoliers[i].Items[si].Icon = atoi(row[r]); r++; // Must use db value in case an Ornamentation is assigned + pp->bandoliers[i].Items[si].Icon = Strings::ToInt(row[r]); r++; // Must use db value in case an Ornamentation is assigned strncpy(pp->bandoliers[i].Items[si].Name, item_data->Name, 64); } else { @@ -989,9 +965,9 @@ bool ZoneDatabase::LoadCharacterTribute(uint32 character_id, PlayerProfile_Struc } i = 0; for (auto& row = results.begin(); row != results.end(); ++row) { - if(atoi(row[1]) != TRIBUTE_NONE){ - pp->tributes[i].tier = atoi(row[0]); - pp->tributes[i].tribute = atoi(row[1]); + if(Strings::ToInt(row[1]) != TRIBUTE_NONE){ + pp->tributes[i].tier = Strings::ToInt(row[0]); + pp->tributes[i].tribute = Strings::ToInt(row[1]); i++; } } @@ -1012,12 +988,12 @@ bool ZoneDatabase::LoadCharacterPotions(uint32 character_id, PlayerProfile_Struc } for (auto& row = results.begin(); row != results.end(); ++row) { - i = atoi(row[0]); - const EQ::ItemData *item_data = database.GetItem(atoi(row[1])); + i = Strings::ToInt(row[0]); + const EQ::ItemData *item_data = database.GetItem(Strings::ToInt(row[1])); if (!item_data) continue; pp->potionbelt.Items[i].ID = item_data->ID; - pp->potionbelt.Items[i].Icon = atoi(row[2]); + pp->potionbelt.Items[i].Icon = Strings::ToInt(row[2]); strncpy(pp->potionbelt.Items[i].Name, item_data->Name, 64); } @@ -1035,16 +1011,16 @@ bool ZoneDatabase::LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Str return true; for (auto& row = results.begin(); row != results.end(); ++row) { - int index = atoi(row[0]); + int index = Strings::ToInt(row[0]); if (index < 0 || index > 4) continue; - pp->binds[index].zone_id = atoi(row[1]); - pp->binds[index].instance_id = atoi(row[2]); - pp->binds[index].x = atoi(row[3]); - pp->binds[index].y = atoi(row[4]); - pp->binds[index].z = atoi(row[5]); - pp->binds[index].heading = atoi(row[6]); + pp->binds[index].zone_id = Strings::ToInt(row[1]); + pp->binds[index].instance_id = Strings::ToInt(row[2]); + pp->binds[index].x = Strings::ToInt(row[3]); + pp->binds[index].y = Strings::ToInt(row[4]); + pp->binds[index].z = Strings::ToInt(row[5]); + pp->binds[index].heading = Strings::ToInt(row[6]); } return true; @@ -1580,7 +1556,7 @@ bool ZoneDatabase::NoRentExpired(const char* name){ return false; auto& row = results.begin(); - uint32 seconds = atoi(row[0]); + uint32 seconds = Strings::ToInt(row[0]); return (seconds>1800); } @@ -1661,7 +1637,7 @@ int ZoneDatabase::CountCharacterInvSnapshots(uint32 character_id) { auto& row = results.begin(); - int64 count = atoll(row[0]); + int64 count = Strings::ToBigInt(row[0]); if (count > 2147483647) return -2; if (count < 0) @@ -1710,7 +1686,7 @@ void ZoneDatabase::ListCharacterInvSnapshots(uint32 character_id, std::list(atoul(row[0]), atoi(row[1]))); + is_list.push_back(std::pair(Strings::ToUnsignedInt(row[0]), Strings::ToInt(row[1]))); } bool ZoneDatabase::ValidateCharacterInvSnapshotTimestamp(uint32 character_id, uint32 timestamp) { @@ -1760,7 +1736,7 @@ void ZoneDatabase::ParseCharacterInvSnapshot(uint32 character_id, uint32 timesta return; for (auto row : results) - parse_list.push_back(std::pair(atoi(row[0]), atoul(row[1]))); + parse_list.push_back(std::pair(Strings::ToInt(row[0]), Strings::ToUnsignedInt(row[1]))); } void ZoneDatabase::DivergeCharacterInvSnapshotFromInventory(uint32 character_id, uint32 timestamp, std::list> &compare_list) { @@ -1804,7 +1780,7 @@ void ZoneDatabase::DivergeCharacterInvSnapshotFromInventory(uint32 character_id, return; for (auto row : results) - compare_list.push_back(std::pair(atoi(row[0]), atoul(row[1]))); + compare_list.push_back(std::pair(Strings::ToInt(row[0]), Strings::ToUnsignedInt(row[1]))); } void ZoneDatabase::DivergeCharacterInventoryFromInvSnapshot(uint32 character_id, uint32 timestamp, std::list> &compare_list) { @@ -1845,7 +1821,7 @@ void ZoneDatabase::DivergeCharacterInventoryFromInvSnapshot(uint32 character_id, return; for (auto row : results) - compare_list.push_back(std::pair(atoi(row[0]), atoul(row[1]))); + compare_list.push_back(std::pair(Strings::ToInt(row[0]), Strings::ToUnsignedInt(row[1]))); } bool ZoneDatabase::RestoreCharacterInvSnapshot(uint32 character_id, uint32 timestamp) { @@ -2079,9 +2055,9 @@ const NPCType *ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load auto& armorTint_row = armortint_results.begin(); for (int index = EQ::textures::textureBegin; index <= EQ::textures::LastTexture; index++) { - t->armor_tint.Slot[index].Color = atoi(armorTint_row[index * 3]) << 16; - t->armor_tint.Slot[index].Color |= atoi(armorTint_row[index * 3 + 1]) << 8; - t->armor_tint.Slot[index].Color |= atoi(armorTint_row[index * 3 + 2]); + t->armor_tint.Slot[index].Color = Strings::ToInt(armorTint_row[index * 3]) << 16; + t->armor_tint.Slot[index].Color |= Strings::ToInt(armorTint_row[index * 3 + 1]) << 8; + t->armor_tint.Slot[index].Color |= Strings::ToInt(armorTint_row[index * 3 + 2]); t->armor_tint.Slot[index].Color |= (t->armor_tint.Slot[index].Color) ? (0xFF << 24) : 0; } @@ -2094,7 +2070,7 @@ const NPCType *ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load } } - t->see_invis = n.see_invis != 0; + t->see_invis = n.see_invis; t->see_invis_undead = n.see_invis_undead != 0; // Set see_invis_undead flag if (!RuleB(NPC, DisableLastNames) && !n.lastname.empty()) { @@ -2257,62 +2233,62 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client tmpNPCType = new NPCType; memset(tmpNPCType, 0, sizeof *tmpNPCType); - tmpNPCType->npc_id = atoi(row[0]); + tmpNPCType->npc_id = Strings::ToInt(row[0]); strn0cpy(tmpNPCType->name, row[1], 50); - tmpNPCType->level = atoi(row[2]); - tmpNPCType->race = atoi(row[3]); - tmpNPCType->class_ = atoi(row[4]); - tmpNPCType->max_hp = atoi(row[5]); + tmpNPCType->level = Strings::ToInt(row[2]); + tmpNPCType->race = Strings::ToInt(row[3]); + tmpNPCType->class_ = Strings::ToInt(row[4]); + tmpNPCType->max_hp = Strings::ToInt(row[5]); tmpNPCType->current_hp = tmpNPCType->max_hp; - tmpNPCType->Mana = atoi(row[6]); - tmpNPCType->gender = atoi(row[7]); - tmpNPCType->texture = atoi(row[8]); - tmpNPCType->helmtexture = atoi(row[9]); - tmpNPCType->attack_delay = atoi(row[10]) * 100; // TODO: fix DB - tmpNPCType->STR = atoi(row[11]); - tmpNPCType->STA = atoi(row[12]); - tmpNPCType->DEX = atoi(row[13]); - tmpNPCType->AGI = atoi(row[14]); - tmpNPCType->INT = atoi(row[15]); - tmpNPCType->WIS = atoi(row[16]); - tmpNPCType->CHA = atoi(row[17]); - tmpNPCType->MR = atoi(row[18]); - tmpNPCType->CR = atoi(row[19]); - tmpNPCType->DR = atoi(row[20]); - tmpNPCType->FR = atoi(row[21]); - tmpNPCType->PR = atoi(row[22]); - tmpNPCType->Corrup = atoi(row[23]); - tmpNPCType->min_dmg = atoi(row[24]); - tmpNPCType->max_dmg = atoi(row[25]); - tmpNPCType->attack_count = atoi(row[26]); + tmpNPCType->Mana = Strings::ToInt(row[6]); + tmpNPCType->gender = Strings::ToInt(row[7]); + tmpNPCType->texture = Strings::ToInt(row[8]); + tmpNPCType->helmtexture = Strings::ToInt(row[9]); + tmpNPCType->attack_delay = Strings::ToInt(row[10]) * 100; // TODO: fix DB + tmpNPCType->STR = Strings::ToInt(row[11]); + tmpNPCType->STA = Strings::ToInt(row[12]); + tmpNPCType->DEX = Strings::ToInt(row[13]); + tmpNPCType->AGI = Strings::ToInt(row[14]); + tmpNPCType->INT = Strings::ToInt(row[15]); + tmpNPCType->WIS = Strings::ToInt(row[16]); + tmpNPCType->CHA = Strings::ToInt(row[17]); + tmpNPCType->MR = Strings::ToInt(row[18]); + tmpNPCType->CR = Strings::ToInt(row[19]); + tmpNPCType->DR = Strings::ToInt(row[20]); + tmpNPCType->FR = Strings::ToInt(row[21]); + tmpNPCType->PR = Strings::ToInt(row[22]); + tmpNPCType->Corrup = Strings::ToInt(row[23]); + tmpNPCType->min_dmg = Strings::ToInt(row[24]); + tmpNPCType->max_dmg = Strings::ToInt(row[25]); + tmpNPCType->attack_count = Strings::ToInt(row[26]); if (row[27] != nullptr) strn0cpy(tmpNPCType->special_abilities, row[27], 512); else tmpNPCType->special_abilities[0] = '\0'; - tmpNPCType->d_melee_texture1 = atoi(row[28]); - tmpNPCType->d_melee_texture2 = atoi(row[29]); - tmpNPCType->prim_melee_type = atoi(row[30]); - tmpNPCType->sec_melee_type = atoi(row[31]); - tmpNPCType->runspeed = atof(row[32]); + tmpNPCType->d_melee_texture1 = Strings::ToInt(row[28]); + tmpNPCType->d_melee_texture2 = Strings::ToInt(row[29]); + tmpNPCType->prim_melee_type = Strings::ToInt(row[30]); + tmpNPCType->sec_melee_type = Strings::ToInt(row[31]); + tmpNPCType->runspeed = Strings::ToFloat(row[32]); - tmpNPCType->hp_regen = atoi(row[33]); - tmpNPCType->mana_regen = atoi(row[34]); + tmpNPCType->hp_regen = Strings::ToInt(row[33]); + tmpNPCType->mana_regen = Strings::ToInt(row[34]); tmpNPCType->aggroradius = RuleI(Mercs, AggroRadius); if (row[35] && strlen(row[35])) - tmpNPCType->bodytype = (uint8)atoi(row[35]); + tmpNPCType->bodytype = (uint8)Strings::ToInt(row[35]); else tmpNPCType->bodytype = 1; - uint32 armor_tint_id = atoi(row[36]); - tmpNPCType->armor_tint.Slot[0].Color = (atoi(row[37]) & 0xFF) << 16; - tmpNPCType->armor_tint.Slot[0].Color |= (atoi(row[38]) & 0xFF) << 8; - tmpNPCType->armor_tint.Slot[0].Color |= (atoi(row[39]) & 0xFF); + uint32 armor_tint_id = Strings::ToInt(row[36]); + tmpNPCType->armor_tint.Slot[0].Color = (Strings::ToInt(row[37]) & 0xFF) << 16; + tmpNPCType->armor_tint.Slot[0].Color |= (Strings::ToInt(row[38]) & 0xFF) << 8; + tmpNPCType->armor_tint.Slot[0].Color |= (Strings::ToInt(row[39]) & 0xFF); tmpNPCType->armor_tint.Slot[0].Color |= (tmpNPCType->armor_tint.Slot[0].Color) ? (0xFF << 24) : 0; if (armor_tint_id == 0) @@ -2337,21 +2313,21 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client auto& armorTint_row = results.begin(); for (int index = EQ::textures::textureBegin; index <= EQ::textures::LastTexture; index++) { - tmpNPCType->armor_tint.Slot[index].Color = atoi(armorTint_row[index * 3]) << 16; - tmpNPCType->armor_tint.Slot[index].Color |= atoi(armorTint_row[index * 3 + 1]) << 8; - tmpNPCType->armor_tint.Slot[index].Color |= atoi(armorTint_row[index * 3 + 2]); + tmpNPCType->armor_tint.Slot[index].Color = Strings::ToInt(armorTint_row[index * 3]) << 16; + tmpNPCType->armor_tint.Slot[index].Color |= Strings::ToInt(armorTint_row[index * 3 + 1]) << 8; + tmpNPCType->armor_tint.Slot[index].Color |= Strings::ToInt(armorTint_row[index * 3 + 2]); tmpNPCType->armor_tint.Slot[index].Color |= (tmpNPCType->armor_tint.Slot[index].Color) ? (0xFF << 24) : 0; } } } else armor_tint_id = 0; - tmpNPCType->AC = atoi(row[40]); - tmpNPCType->ATK = atoi(row[41]); - tmpNPCType->accuracy_rating = atoi(row[42]); - tmpNPCType->scalerate = atoi(row[43]); - tmpNPCType->spellscale = atoi(row[44]); - tmpNPCType->healscale = atoi(row[45]); + tmpNPCType->AC = Strings::ToInt(row[40]); + tmpNPCType->ATK = Strings::ToInt(row[41]); + tmpNPCType->accuracy_rating = Strings::ToInt(row[42]); + tmpNPCType->scalerate = Strings::ToInt(row[43]); + tmpNPCType->spellscale = Strings::ToInt(row[44]); + tmpNPCType->healscale = Strings::ToInt(row[45]); tmpNPCType->skip_global_loot = true; tmpNPCType->skip_auto_scale = true; @@ -2385,35 +2361,35 @@ bool ZoneDatabase::LoadMercInfo(Client *client) { return false; for (auto& row = results.begin(); row != results.end(); ++row) { - uint8 slot = atoi(row[1]); + uint8 slot = Strings::ToInt(row[1]); if(slot >= MAXMERCS) continue; - client->GetMercInfo(slot).mercid = atoi(row[0]); + client->GetMercInfo(slot).mercid = Strings::ToInt(row[0]); client->GetMercInfo(slot).slot = slot; snprintf(client->GetMercInfo(slot).merc_name, 64, "%s", row[2]); - client->GetMercInfo(slot).MercTemplateID = atoi(row[3]); - client->GetMercInfo(slot).SuspendedTime = atoi(row[4]); - client->GetMercInfo(slot).IsSuspended = atoi(row[5]) == 1 ? true : false; - client->GetMercInfo(slot).MercTimerRemaining = atoi(row[6]); - client->GetMercInfo(slot).Gender = atoi(row[7]); - client->GetMercInfo(slot).MercSize = atof(row[8]); + client->GetMercInfo(slot).MercTemplateID = Strings::ToInt(row[3]); + client->GetMercInfo(slot).SuspendedTime = Strings::ToInt(row[4]); + client->GetMercInfo(slot).IsSuspended = Strings::ToInt(row[5]) == 1 ? true : false; + client->GetMercInfo(slot).MercTimerRemaining = Strings::ToInt(row[6]); + client->GetMercInfo(slot).Gender = Strings::ToInt(row[7]); + client->GetMercInfo(slot).MercSize = Strings::ToFloat(row[8]); client->GetMercInfo(slot).State = 5; - client->GetMercInfo(slot).Stance = atoi(row[9]); - client->GetMercInfo(slot).hp = atoi(row[10]); - client->GetMercInfo(slot).mana = atoi(row[11]); - client->GetMercInfo(slot).endurance = atoi(row[12]); - client->GetMercInfo(slot).face = atoi(row[13]); - client->GetMercInfo(slot).luclinHairStyle = atoi(row[14]); - client->GetMercInfo(slot).luclinHairColor = atoi(row[15]); - client->GetMercInfo(slot).luclinEyeColor = atoi(row[16]); - client->GetMercInfo(slot).luclinEyeColor2 = atoi(row[17]); - client->GetMercInfo(slot).luclinBeardColor = atoi(row[18]); - client->GetMercInfo(slot).luclinBeard = atoi(row[19]); - client->GetMercInfo(slot).drakkinHeritage = atoi(row[20]); - client->GetMercInfo(slot).drakkinTattoo = atoi(row[21]); - client->GetMercInfo(slot).drakkinDetails = atoi(row[22]); + client->GetMercInfo(slot).Stance = Strings::ToInt(row[9]); + client->GetMercInfo(slot).hp = Strings::ToInt(row[10]); + client->GetMercInfo(slot).mana = Strings::ToInt(row[11]); + client->GetMercInfo(slot).endurance = Strings::ToInt(row[12]); + client->GetMercInfo(slot).face = Strings::ToInt(row[13]); + client->GetMercInfo(slot).luclinHairStyle = Strings::ToInt(row[14]); + client->GetMercInfo(slot).luclinHairColor = Strings::ToInt(row[15]); + client->GetMercInfo(slot).luclinEyeColor = Strings::ToInt(row[16]); + client->GetMercInfo(slot).luclinEyeColor2 = Strings::ToInt(row[17]); + client->GetMercInfo(slot).luclinBeardColor = Strings::ToInt(row[18]); + client->GetMercInfo(slot).luclinBeard = Strings::ToInt(row[19]); + client->GetMercInfo(slot).drakkinHeritage = Strings::ToInt(row[20]); + client->GetMercInfo(slot).drakkinTattoo = Strings::ToInt(row[21]); + client->GetMercInfo(slot).drakkinDetails = Strings::ToInt(row[22]); } return true; @@ -2443,29 +2419,29 @@ bool ZoneDatabase::LoadCurrentMerc(Client *client) { for (auto& row = results.begin(); row != results.end(); ++row) { - client->GetMercInfo(slot).mercid = atoi(row[0]); + client->GetMercInfo(slot).mercid = Strings::ToInt(row[0]); client->GetMercInfo(slot).slot = slot; snprintf(client->GetMercInfo(slot).merc_name, 64, "%s", row[1]); - client->GetMercInfo(slot).MercTemplateID = atoi(row[2]); - client->GetMercInfo(slot).SuspendedTime = atoi(row[3]); - client->GetMercInfo(slot).IsSuspended = atoi(row[4]) == 1? true: false; - client->GetMercInfo(slot).MercTimerRemaining = atoi(row[5]); - client->GetMercInfo(slot).Gender = atoi(row[6]); - client->GetMercInfo(slot).MercSize = atof(row[7]); - client->GetMercInfo(slot).State = atoi(row[8]); - client->GetMercInfo(slot).hp = atoi(row[9]); - client->GetMercInfo(slot).mana = atoi(row[10]); - client->GetMercInfo(slot).endurance = atoi(row[11]); - client->GetMercInfo(slot).face = atoi(row[12]); - client->GetMercInfo(slot).luclinHairStyle = atoi(row[13]); - client->GetMercInfo(slot).luclinHairColor = atoi(row[14]); - client->GetMercInfo(slot).luclinEyeColor = atoi(row[15]); - client->GetMercInfo(slot).luclinEyeColor2 = atoi(row[16]); - client->GetMercInfo(slot).luclinBeardColor = atoi(row[17]); - client->GetMercInfo(slot).luclinBeard = atoi(row[18]); - client->GetMercInfo(slot).drakkinHeritage = atoi(row[19]); - client->GetMercInfo(slot).drakkinTattoo = atoi(row[20]); - client->GetMercInfo(slot).drakkinDetails = atoi(row[21]); + client->GetMercInfo(slot).MercTemplateID = Strings::ToInt(row[2]); + client->GetMercInfo(slot).SuspendedTime = Strings::ToInt(row[3]); + client->GetMercInfo(slot).IsSuspended = Strings::ToInt(row[4]) == 1? true: false; + client->GetMercInfo(slot).MercTimerRemaining = Strings::ToInt(row[5]); + client->GetMercInfo(slot).Gender = Strings::ToInt(row[6]); + client->GetMercInfo(slot).MercSize = Strings::ToFloat(row[7]); + client->GetMercInfo(slot).State = Strings::ToInt(row[8]); + client->GetMercInfo(slot).hp = Strings::ToInt(row[9]); + client->GetMercInfo(slot).mana = Strings::ToInt(row[10]); + client->GetMercInfo(slot).endurance = Strings::ToInt(row[11]); + client->GetMercInfo(slot).face = Strings::ToInt(row[12]); + client->GetMercInfo(slot).luclinHairStyle = Strings::ToInt(row[13]); + client->GetMercInfo(slot).luclinHairColor = Strings::ToInt(row[14]); + client->GetMercInfo(slot).luclinEyeColor = Strings::ToInt(row[15]); + client->GetMercInfo(slot).luclinEyeColor2 = Strings::ToInt(row[16]); + client->GetMercInfo(slot).luclinBeardColor = Strings::ToInt(row[17]); + client->GetMercInfo(slot).luclinBeard = Strings::ToInt(row[18]); + client->GetMercInfo(slot).drakkinHeritage = Strings::ToInt(row[19]); + client->GetMercInfo(slot).drakkinTattoo = Strings::ToInt(row[20]); + client->GetMercInfo(slot).drakkinDetails = Strings::ToInt(row[21]); } return true; @@ -2563,8 +2539,9 @@ void ZoneDatabase::SaveMercBuffs(Merc *merc) { } for (int buffCount = 0; buffCount <= BUFF_COUNT; buffCount++) { - if(buffs[buffCount].spellid == 0 || buffs[buffCount].spellid == SPELL_UNKNOWN) - continue; + if (!IsValidSpell(buffs[buffCount].spellid)) { + continue; + } int IsPersistent = buffs[buffCount].persistant_buff? 1: 0; @@ -2612,34 +2589,34 @@ void ZoneDatabase::LoadMercBuffs(Merc *merc) { if(buffCount == BUFF_COUNT) break; - buffs[buffCount].spellid = atoi(row[0]); - buffs[buffCount].casterlevel = atoi(row[1]); - buffs[buffCount].ticsremaining = atoi(row[3]); + buffs[buffCount].spellid = Strings::ToInt(row[0]); + buffs[buffCount].casterlevel = Strings::ToInt(row[1]); + buffs[buffCount].ticsremaining = Strings::ToInt(row[3]); if(CalculatePoisonCounters(buffs[buffCount].spellid) > 0) - buffs[buffCount].counters = atoi(row[4]); + buffs[buffCount].counters = Strings::ToInt(row[4]); if(CalculateDiseaseCounters(buffs[buffCount].spellid) > 0) - buffs[buffCount].counters = atoi(row[5]); + buffs[buffCount].counters = Strings::ToInt(row[5]); if(CalculateCurseCounters(buffs[buffCount].spellid) > 0) - buffs[buffCount].counters = atoi(row[6]); + buffs[buffCount].counters = Strings::ToInt(row[6]); if(CalculateCorruptionCounters(buffs[buffCount].spellid) > 0) - buffs[buffCount].counters = atoi(row[7]); + buffs[buffCount].counters = Strings::ToInt(row[7]); - buffs[buffCount].hit_number = atoi(row[8]); - buffs[buffCount].melee_rune = atoi(row[9]); - buffs[buffCount].magic_rune = atoi(row[10]); - buffs[buffCount].dot_rune = atoi(row[11]); - buffs[buffCount].caston_x = atoi(row[12]); + buffs[buffCount].hit_number = Strings::ToInt(row[8]); + buffs[buffCount].melee_rune = Strings::ToInt(row[9]); + buffs[buffCount].magic_rune = Strings::ToInt(row[10]); + buffs[buffCount].dot_rune = Strings::ToInt(row[11]); + buffs[buffCount].caston_x = Strings::ToInt(row[12]); buffs[buffCount].casterid = 0; - bool IsPersistent = atoi(row[13])? true: false; + bool IsPersistent = Strings::ToInt(row[13])? true: false; - buffs[buffCount].caston_y = atoi(row[13]); - buffs[buffCount].caston_z = atoi(row[14]); - buffs[buffCount].ExtraDIChance = atoi(row[15]); + buffs[buffCount].caston_y = Strings::ToInt(row[13]); + buffs[buffCount].caston_z = Strings::ToInt(row[14]); + buffs[buffCount].ExtraDIChance = Strings::ToInt(row[15]); buffs[buffCount].persistant_buff = IsPersistent; @@ -2698,10 +2675,10 @@ void ZoneDatabase::LoadMercEquipment(Merc *merc) { if (itemCount == EQ::invslot::EQUIPMENT_COUNT) break; - if(atoi(row[0]) == 0) + if(Strings::ToInt(row[0]) == 0) continue; - merc->AddItem(itemCount, atoi(row[0])); + merc->AddItem(itemCount, Strings::ToInt(row[0])); itemCount++; } } @@ -2719,7 +2696,7 @@ uint8 ZoneDatabase::GetGridType(uint32 grid, uint32 zoneid ) { auto& row = results.begin(); - return atoi(row[0]); + return Strings::ToInt(row[0]); } void ZoneDatabase::SaveMerchantTemp(uint32 npcid, uint32 slot, uint32 zone_id, uint32 instance_id, uint32 item, uint32 charges){ @@ -2750,7 +2727,7 @@ uint32 ZoneDatabase::GetZoneTZ(uint32 zoneid, uint32 version) { return 0; auto& row = results.begin(); - return atoi(row[0]); + return Strings::ToInt(row[0]); } bool ZoneDatabase::SetZoneTZ(uint32 zoneid, uint32 version, uint32 tz) { @@ -2837,7 +2814,7 @@ uint8 ZoneDatabase::GroupCount(uint32 groupid) { auto& row = results.begin(); - return atoi(row[0]); + return Strings::ToInt(row[0]); } uint8 ZoneDatabase::RaidGroupCount(uint32 raidid, uint32 groupid) { @@ -2855,7 +2832,7 @@ uint8 ZoneDatabase::RaidGroupCount(uint32 raidid, uint32 groupid) { auto& row = results.begin(); - return atoi(row[0]); + return Strings::ToInt(row[0]); } int32 ZoneDatabase::GetBlockedSpellsCount(uint32 zoneid) @@ -2871,7 +2848,7 @@ int32 ZoneDatabase::GetBlockedSpellsCount(uint32 zoneid) auto& row = results.begin(); - return atoi(row[0]); + return Strings::ToInt(row[0]); } bool ZoneDatabase::LoadBlockedSpells(int32 blockedSpellsCount, ZoneSpellsBlocked* into, uint32 zoneid) @@ -2896,10 +2873,10 @@ bool ZoneDatabase::LoadBlockedSpells(int32 blockedSpellsCount, ZoneSpellsBlocked } memset(&into[index], 0, sizeof(ZoneSpellsBlocked)); - into[index].spellid = atoi(row[1]); - into[index].type = atoi(row[2]); - into[index].m_Location = glm::vec3(atof(row[3]), atof(row[4]), atof(row[5])); - into[index].m_Difference = glm::vec3(atof(row[6]), atof(row[7]), atof(row[8])); + into[index].spellid = Strings::ToInt(row[1]); + into[index].type = Strings::ToInt(row[2]); + into[index].m_Location = glm::vec3(Strings::ToFloat(row[3]), Strings::ToFloat(row[4]), Strings::ToFloat(row[5])); + into[index].m_Difference = glm::vec3(Strings::ToFloat(row[6]), Strings::ToFloat(row[7]), Strings::ToFloat(row[8])); strn0cpy(into[index].message, row[9], 255); } @@ -2921,7 +2898,7 @@ uint32 ZoneDatabase::GetKarma(uint32 acct_id) return 0; for (auto& row = results.begin(); row != results.end(); ++row) { - return atoi(row[0]); + return Strings::ToInt(row[0]); } return 0; @@ -3001,12 +2978,12 @@ void ZoneDatabase::ListAllInstances(Client* client, uint32 character_id) uint32 instance_count = 0; for (auto row : results) { - auto instance_id = std::stoul(row[0]); - auto zone_id = std::stoul(row[1]); - auto version = std::stoul(row[2]); - auto start_time = std::stoul(row[3]); - auto duration = std::stoul(row[4]); - auto never_expires = std::stoi(row[5]) ? true : false; + auto instance_id = Strings::ToUnsignedInt(row[0]); + auto zone_id = Strings::ToUnsignedInt(row[1]); + auto version = Strings::ToUnsignedInt(row[2]); + auto start_time = Strings::ToUnsignedInt(row[3]); + auto duration = Strings::ToUnsignedInt(row[4]); + auto never_expires = Strings::ToInt(row[5]) ? true : false; std::string remaining_time_string = "Never"; timeval time_value; gettimeofday(&time_value, nullptr); @@ -3075,53 +3052,6 @@ void ZoneDatabase::QGlobalPurge() database.QueryDatabase(query); } -void ZoneDatabase::InsertDoor( - uint32 database_id, - uint8 id, - std::string name, - const glm::vec4 &position, - uint8 open_type, - uint16 guild_id, - uint32 lockpick, - uint32 key_item_id, - uint8 door_param, - uint8 invert, - int incline, - uint16 size, - bool disable_timer -) { - auto e = DoorsRepository::NewEntity(); - - e.id = database_id; - e.doorid = id; - e.zone = zone->GetShortName(); - e.version = zone->GetInstanceVersion(); - e.name = name; - e.pos_x = position.x; - e.pos_y = position.y; - e.pos_z = position.z; - e.opentype = open_type; - e.guild = guild_id; - e.lockpick = lockpick; - e.keyitem = key_item_id; - e.disable_timer = static_cast(disable_timer); - e.door_param = door_param; - e.invert_state = invert; - e.incline = incline; - e.size = size; - - const auto& n = DoorsRepository::InsertOne(*this, e); - if (!n.id) { - LogError( - "Failed to create door in Zone [{}] Version [{}] Database ID [{}] ID [{}]", - zone->GetShortName(), - zone->GetInstanceVersion(), - database_id, - id - ); - } -} - void ZoneDatabase::LoadAltCurrencyValues(uint32 char_id, std::map ¤cy) { std::string query = StringFormat("SELECT currency_id, amount " @@ -3133,7 +3063,7 @@ void ZoneDatabase::LoadAltCurrencyValues(uint32 char_id, std::mapGetBuffs(); for (int index = 0; index < buff_count; index++) { - if(buffs[index].spellid == SPELL_UNKNOWN) - continue; + if (!IsValidSpell(buffs[index].spellid)) { + continue; + } query = StringFormat("INSERT INTO `character_buffs` (character_id, slot_id, spell_id, " "caster_level, caster_name, ticsremaining, counters, numhits, melee_rune, " @@ -3192,28 +3123,28 @@ void ZoneDatabase::LoadBuffs(Client *client) } for (auto& row = results.begin(); row != results.end(); ++row) { - uint32 slot_id = atoul(row[1]); + uint32 slot_id = Strings::ToUnsignedInt(row[1]); if (slot_id >= client->GetMaxBuffSlots()) continue; - uint32 spell_id = atoul(row[0]); + uint32 spell_id = Strings::ToUnsignedInt(row[0]); if (!IsValidSpell(spell_id)) continue; Client *caster = entity_list.GetClientByName(row[3]); - uint32 caster_level = atoi(row[2]); - int32 ticsremaining = atoi(row[4]); - uint32 counters = atoul(row[5]); - uint32 hit_number = atoul(row[6]); - uint32 melee_rune = atoul(row[7]); - uint32 magic_rune = atoul(row[8]); - uint8 persistent = atoul(row[9]); - uint32 dot_rune = atoul(row[10]); - int32 caston_x = atoul(row[11]); - int32 caston_y = atoul(row[12]); - int32 caston_z = atoul(row[13]); - int32 ExtraDIChance = atoul(row[14]); - uint32 instrument_mod = atoul(row[15]); + uint32 caster_level = Strings::ToInt(row[2]); + int32 ticsremaining = Strings::ToInt(row[4]); + uint32 counters = Strings::ToUnsignedInt(row[5]); + uint32 hit_number = Strings::ToUnsignedInt(row[6]); + uint32 melee_rune = Strings::ToUnsignedInt(row[7]); + uint32 magic_rune = Strings::ToUnsignedInt(row[8]); + uint8 persistent = Strings::ToUnsignedInt(row[9]); + uint32 dot_rune = Strings::ToUnsignedInt(row[10]); + int32 caston_x = Strings::ToUnsignedInt(row[11]); + int32 caston_y = Strings::ToUnsignedInt(row[12]); + int32 caston_z = Strings::ToUnsignedInt(row[13]); + int32 ExtraDIChance = Strings::ToUnsignedInt(row[14]); + uint32 instrument_mod = Strings::ToUnsignedInt(row[15]); buffs[slot_id].spellid = spell_id; buffs[slot_id].casterlevel = caster_level; @@ -3297,7 +3228,7 @@ void ZoneDatabase::LoadAuras(Client *c) return; for (auto& row = results.begin(); row != results.end(); ++row) - c->MakeAura(atoi(row[0])); + c->MakeAura(Strings::ToInt(row[0])); } void ZoneDatabase::SavePetInfo(Client *client) @@ -3336,8 +3267,9 @@ void ZoneDatabase::SavePetInfo(Client *client) // pet buffs! int max_slots = RuleI(Spells, MaxTotalSlotsPET); for (int index = 0; index < max_slots; index++) { - if (petinfo->Buffs[index].spellid == SPELL_UNKNOWN || petinfo->Buffs[index].spellid == 0) + if (!IsValidSpell(petinfo->Buffs[index].spellid)) { continue; + } if (query.length() == 0) query = StringFormat("INSERT INTO `character_pet_buffs` " "(`char_id`, `pet`, `slot`, `spell_id`, `caster_level`, " @@ -3380,11 +3312,24 @@ void ZoneDatabase::RemoveTempFactions(Client *client) { QueryDatabase(query); } -void ZoneDatabase::UpdateItemRecastTimestamps(uint32 char_id, uint32 recast_type, uint32 timestamp) +void ZoneDatabase::UpdateItemRecast(uint32 character_id, uint32 recast_type, uint32 timestamp) { - std::string query = - StringFormat("REPLACE INTO character_item_recast (id, recast_type, timestamp) VALUES (%u, %u, %u)", char_id, - recast_type, timestamp); + const auto query = fmt::format( + "REPLACE INTO character_item_recast (id, recast_type, timestamp) VALUES ({}, {}, {})", + character_id, + recast_type, + timestamp + ); + QueryDatabase(query); +} + +void ZoneDatabase::DeleteItemRecast(uint32 character_id, uint32 recast_type) +{ + const auto query = fmt::format( + "DELETE FROM character_item_recast WHERE id = {} AND recast_type = {}", + character_id, + recast_type + ); QueryDatabase(query); } @@ -3409,7 +3354,7 @@ void ZoneDatabase::LoadPetInfo(Client *client) PetInfo *pi; for (auto& row = results.begin(); row != results.end(); ++row) { - uint16 pet = atoi(row[0]); + uint16 pet = Strings::ToInt(row[0]); if (pet == 0) pi = petinfo; @@ -3419,12 +3364,12 @@ void ZoneDatabase::LoadPetInfo(Client *client) continue; strncpy(pi->Name, row[1], 64); - pi->petpower = atoi(row[2]); - pi->SpellID = atoi(row[3]); - pi->HP = atoul(row[4]); - pi->Mana = atoul(row[5]); - pi->size = atof(row[6]); - pi->taunting = (bool) atoi(row[7]); + pi->petpower = Strings::ToInt(row[2]); + pi->SpellID = Strings::ToInt(row[3]); + pi->HP = Strings::ToUnsignedInt(row[4]); + pi->Mana = Strings::ToUnsignedInt(row[5]); + pi->size = Strings::ToFloat(row[6]); + pi->taunting = (bool) Strings::ToInt(row[7]); } query = StringFormat("SELECT `pet`, `slot`, `spell_id`, `caster_level`, `castername`, " @@ -3437,7 +3382,7 @@ void ZoneDatabase::LoadPetInfo(Client *client) } for (auto& row = results.begin(); row != results.end(); ++row) { - uint16 pet = atoi(row[0]); + uint16 pet = Strings::ToInt(row[0]); if (pet == 0) pi = petinfo; else if (pet == 1) @@ -3445,20 +3390,20 @@ void ZoneDatabase::LoadPetInfo(Client *client) else continue; - uint32 slot_id = atoul(row[1]); + uint32 slot_id = Strings::ToUnsignedInt(row[1]); if (slot_id >= RuleI(Spells, MaxTotalSlotsPET)) continue; - uint32 spell_id = atoul(row[2]); + uint32 spell_id = Strings::ToUnsignedInt(row[2]); if (!IsValidSpell(spell_id)) continue; - uint32 caster_level = atoi(row[3]); + uint32 caster_level = Strings::ToInt(row[3]); int caster_id = 0; // The castername field is currently unused - int32 ticsremaining = atoi(row[5]); - uint32 counters = atoul(row[6]); - uint8 bard_mod = atoul(row[7]); + int32 ticsremaining = Strings::ToInt(row[5]); + uint32 counters = Strings::ToUnsignedInt(row[6]); + uint8 bard_mod = Strings::ToUnsignedInt(row[7]); pi->Buffs[slot_id].spellid = spell_id; pi->Buffs[slot_id].level = caster_level; @@ -3480,7 +3425,7 @@ void ZoneDatabase::LoadPetInfo(Client *client) } for (auto& row = results.begin(); row != results.end(); ++row) { - uint16 pet = atoi(row[0]); + uint16 pet = Strings::ToInt(row[0]); if (pet == 0) pi = petinfo; else if (pet == 1) @@ -3488,11 +3433,11 @@ void ZoneDatabase::LoadPetInfo(Client *client) else continue; - int slot = atoi(row[1]); + int slot = Strings::ToInt(row[1]); if (slot < EQ::invslot::EQUIPMENT_BEGIN || slot > EQ::invslot::EQUIPMENT_END) continue; - pi->Items[slot] = atoul(row[2]); + pi->Items[slot] = Strings::ToUnsignedInt(row[2]); } } @@ -3651,7 +3596,7 @@ bool ZoneDatabase::LoadFactionData() auto& fmr_row = faction_max_results.begin(); - max_faction = atoul(fmr_row[0]); + max_faction = Strings::ToUnsignedInt(fmr_row[0]); faction_array = new Faction *[max_faction + 1]; memset(faction_array, 0, (sizeof(Faction*) * (max_faction + 1))); @@ -3668,7 +3613,7 @@ bool ZoneDatabase::LoadFactionData() for (auto fr_row : faction_results) { - uint32 index = atoul(fr_row[0]); + uint32 index = Strings::ToUnsignedInt(fr_row[0]); if (index > max_faction) { Log(Logs::General, Logs::Error, "Faction '%u' is out-of-bounds for faction array size!", index); continue; @@ -3682,7 +3627,7 @@ bool ZoneDatabase::LoadFactionData() faction_array[index] = new Faction; strn0cpy(faction_array[index]->name, fr_row[1], 50); - faction_array[index]->base = atoi(fr_row[2]); + faction_array[index]->base = Strings::ToInt(fr_row[2]); faction_array[index]->min = MIN_PERSONAL_FACTION; faction_array[index]->max = MAX_PERSONAL_FACTION; @@ -3701,7 +3646,7 @@ bool ZoneDatabase::LoadFactionData() for (auto br_row : base_results) { - uint32 index = atoul(br_row[0]); + uint32 index = Strings::ToUnsignedInt(br_row[0]); if (index > max_faction) { LogError("Faction [{}] is out-of-bounds for faction array size in Base adjustment!", index); continue; @@ -3712,8 +3657,8 @@ bool ZoneDatabase::LoadFactionData() continue; } - faction_array[index]->min = atoi(br_row[1]); - faction_array[index]->max = atoi(br_row[2]); + faction_array[index]->min = Strings::ToInt(br_row[1]); + faction_array[index]->max = Strings::ToInt(br_row[2]); } LogInfo("Loaded [{}] faction base(s)", Strings::Commify(std::to_string(base_results.RowCount()))); @@ -3730,7 +3675,7 @@ bool ZoneDatabase::LoadFactionData() for (auto mr_row : modifier_results) { - uint32 index = atoul(mr_row[0]); + uint32 index = Strings::ToUnsignedInt(mr_row[0]); if (index > max_faction) { Log(Logs::General, Logs::Error, "Faction '%u' is out-of-bounds for faction array size in Modifier adjustment!", index); continue; @@ -3741,7 +3686,7 @@ bool ZoneDatabase::LoadFactionData() continue; } - faction_array[index]->mods[mr_row[2]] = atoi(mr_row[1]); + faction_array[index]->mods[mr_row[2]] = Strings::ToInt(mr_row[1]); } LogInfo("Loaded [{}] faction modifier(s)", Strings::Commify(std::to_string(modifier_results.RowCount()))); @@ -3830,7 +3775,7 @@ uint32 ZoneDatabase::GetCharacterCorpseDecayTimer(uint32 corpse_db_id){ auto results = QueryDatabase(query); auto& row = results.begin(); if (results.Success() && results.RowsAffected() != 0) - return atoul(row[0]); + return Strings::ToUnsignedInt(row[0]); return 0; } @@ -4021,7 +3966,7 @@ uint32 ZoneDatabase::GetCharacterBuriedCorpseCount(uint32 char_id) { auto results = QueryDatabase(query); for (auto& row = results.begin(); row != results.end(); ++row) { - return atoi(row[0]); + return Strings::ToInt(row[0]); } return 0; } @@ -4031,7 +3976,7 @@ uint32 ZoneDatabase::GetCharacterCorpseCount(uint32 char_id) { auto results = QueryDatabase(query); for (auto& row = results.begin(); row != results.end(); ++row) { - return atoi(row[0]); + return Strings::ToInt(row[0]); } return 0; } @@ -4043,7 +3988,7 @@ uint32 ZoneDatabase::GetCharacterCorpseID(uint32 char_id, uint8 corpse) { auto& row = results.begin(); if (row != results.end()) - return atoul(row[0]); + return Strings::ToUnsignedInt(row[0]); else return 0; } @@ -4055,7 +4000,7 @@ uint32 ZoneDatabase::GetCharacterCorpseItemCount(uint32 corpse_id){ auto results = QueryDatabase(query); auto& row = results.begin(); if (results.Success() && results.RowsAffected() != 0){ - return atoi(row[0]); + return Strings::ToInt(row[0]); } return 0; } @@ -4115,39 +4060,39 @@ bool ZoneDatabase::LoadCharacterCorpseData(uint32 corpse_id, PlayerCorpse_Struct auto results = QueryDatabase(query); uint16 i = 0; for (auto& row = results.begin(); row != results.end(); ++row) { - pcs->locked = atoi(row[i++]); // is_locked, - pcs->exp = atoul(row[i++]); // exp, - pcs->size = atoi(row[i++]); // size, - pcs->level = atoi(row[i++]); // `level`, - pcs->race = atoi(row[i++]); // race, - pcs->gender = atoi(row[i++]); // gender, - pcs->class_ = atoi(row[i++]); // class, - pcs->deity = atoi(row[i++]); // deity, - pcs->texture = atoi(row[i++]); // texture, - pcs->helmtexture = atoi(row[i++]); // helm_texture, - pcs->copper = atoul(row[i++]); // copper, - pcs->silver = atoul(row[i++]); // silver, - pcs->gold = atoul(row[i++]); // gold, - pcs->plat = atoul(row[i++]); // platinum, - pcs->haircolor = atoi(row[i++]); // hair_color, - pcs->beardcolor = atoi(row[i++]); // beard_color, - pcs->eyecolor1 = atoi(row[i++]); // eye_color_1, - pcs->eyecolor2 = atoi(row[i++]); // eye_color_2, - pcs->hairstyle = atoi(row[i++]); // hair_style, - pcs->face = atoi(row[i++]); // face, - pcs->beard = atoi(row[i++]); // beard, - pcs->drakkin_heritage = atoul(row[i++]); // drakkin_heritage, - pcs->drakkin_tattoo = atoul(row[i++]); // drakkin_tattoo, - pcs->drakkin_details = atoul(row[i++]); // drakkin_details, - pcs->item_tint.Head.Color = atoul(row[i++]); // wc_1, - pcs->item_tint.Chest.Color = atoul(row[i++]); // wc_2, - pcs->item_tint.Arms.Color = atoul(row[i++]); // wc_3, - pcs->item_tint.Wrist.Color = atoul(row[i++]); // wc_4, - pcs->item_tint.Hands.Color = atoul(row[i++]); // wc_5, - pcs->item_tint.Legs.Color = atoul(row[i++]); // wc_6, - pcs->item_tint.Feet.Color = atoul(row[i++]); // wc_7, - pcs->item_tint.Primary.Color = atoul(row[i++]); // wc_8, - pcs->item_tint.Secondary.Color = atoul(row[i++]); // wc_9 + pcs->locked = Strings::ToInt(row[i++]); // is_locked, + pcs->exp = Strings::ToUnsignedInt(row[i++]); // exp, + pcs->size = Strings::ToInt(row[i++]); // size, + pcs->level = Strings::ToInt(row[i++]); // `level`, + pcs->race = Strings::ToInt(row[i++]); // race, + pcs->gender = Strings::ToInt(row[i++]); // gender, + pcs->class_ = Strings::ToInt(row[i++]); // class, + pcs->deity = Strings::ToInt(row[i++]); // deity, + pcs->texture = Strings::ToInt(row[i++]); // texture, + pcs->helmtexture = Strings::ToInt(row[i++]); // helm_texture, + pcs->copper = Strings::ToUnsignedInt(row[i++]); // copper, + pcs->silver = Strings::ToUnsignedInt(row[i++]); // silver, + pcs->gold = Strings::ToUnsignedInt(row[i++]); // gold, + pcs->plat = Strings::ToUnsignedInt(row[i++]); // platinum, + pcs->haircolor = Strings::ToInt(row[i++]); // hair_color, + pcs->beardcolor = Strings::ToInt(row[i++]); // beard_color, + pcs->eyecolor1 = Strings::ToInt(row[i++]); // eye_color_1, + pcs->eyecolor2 = Strings::ToInt(row[i++]); // eye_color_2, + pcs->hairstyle = Strings::ToInt(row[i++]); // hair_style, + pcs->face = Strings::ToInt(row[i++]); // face, + pcs->beard = Strings::ToInt(row[i++]); // beard, + pcs->drakkin_heritage = Strings::ToUnsignedInt(row[i++]); // drakkin_heritage, + pcs->drakkin_tattoo = Strings::ToUnsignedInt(row[i++]); // drakkin_tattoo, + pcs->drakkin_details = Strings::ToUnsignedInt(row[i++]); // drakkin_details, + pcs->item_tint.Head.Color = Strings::ToUnsignedInt(row[i++]); // wc_1, + pcs->item_tint.Chest.Color = Strings::ToUnsignedInt(row[i++]); // wc_2, + pcs->item_tint.Arms.Color = Strings::ToUnsignedInt(row[i++]); // wc_3, + pcs->item_tint.Wrist.Color = Strings::ToUnsignedInt(row[i++]); // wc_4, + pcs->item_tint.Hands.Color = Strings::ToUnsignedInt(row[i++]); // wc_5, + pcs->item_tint.Legs.Color = Strings::ToUnsignedInt(row[i++]); // wc_6, + pcs->item_tint.Feet.Color = Strings::ToUnsignedInt(row[i++]); // wc_7, + pcs->item_tint.Primary.Color = Strings::ToUnsignedInt(row[i++]); // wc_8, + pcs->item_tint.Secondary.Color = Strings::ToUnsignedInt(row[i++]); // wc_9 } query = StringFormat( "SELECT \n" @@ -4174,16 +4119,16 @@ bool ZoneDatabase::LoadCharacterCorpseData(uint32 corpse_id, PlayerCorpse_Struct uint16 r = 0; for (auto& row = results.begin(); row != results.end(); ++row) { memset(&pcs->items[i], 0, sizeof (player_lootitem::ServerLootItem_Struct)); - pcs->items[i].equip_slot = atoi(row[r++]); // equip_slot, - pcs->items[i].item_id = atoul(row[r++]); // item_id, - pcs->items[i].charges = atoi(row[r++]); // charges, - pcs->items[i].aug_1 = atoi(row[r++]); // aug_1, - pcs->items[i].aug_2 = atoi(row[r++]); // aug_2, - pcs->items[i].aug_3 = atoi(row[r++]); // aug_3, - pcs->items[i].aug_4 = atoi(row[r++]); // aug_4, - pcs->items[i].aug_5 = atoi(row[r++]); // aug_5, - pcs->items[i].aug_6 = atoi(row[r++]); // aug_6, - pcs->items[i].attuned = atoi(row[r++]); // attuned, + pcs->items[i].equip_slot = Strings::ToInt(row[r++]); // equip_slot, + pcs->items[i].item_id = Strings::ToUnsignedInt(row[r++]); // item_id, + pcs->items[i].charges = Strings::ToInt(row[r++]); // charges, + pcs->items[i].aug_1 = Strings::ToInt(row[r++]); // aug_1, + pcs->items[i].aug_2 = Strings::ToInt(row[r++]); // aug_2, + pcs->items[i].aug_3 = Strings::ToInt(row[r++]); // aug_3, + pcs->items[i].aug_4 = Strings::ToInt(row[r++]); // aug_4, + pcs->items[i].aug_5 = Strings::ToInt(row[r++]); // aug_5, + pcs->items[i].aug_6 = Strings::ToInt(row[r++]); // aug_6, + pcs->items[i].attuned = Strings::ToInt(row[r++]); // attuned, r = 0; i++; } @@ -4202,14 +4147,14 @@ Corpse* ZoneDatabase::SummonBuriedCharacterCorpses(uint32 char_id, uint32 dest_z for (auto& row = results.begin(); row != results.end(); ++row) { corpse = Corpse::LoadCharacterCorpseEntity( - atoul(row[0]), // uint32 in_dbid + Strings::ToUnsignedInt(row[0]), // uint32 in_dbid char_id, // uint32 in_charid row[1], // char* in_charname position, row[2], // char* time_of_death - atoi(row[3]) == 1, // bool rezzed + Strings::ToInt(row[3]) == 1, // bool rezzed false, // bool was_at_graveyard - atoul(row[4]) // uint32 guild_consent_id + Strings::ToUnsignedInt(row[4]) // uint32 guild_consent_id ); if (!corpse) continue; @@ -4242,14 +4187,14 @@ bool ZoneDatabase::SummonAllCharacterCorpses(uint32 char_id, uint32 dest_zone_id for (auto& row = results.begin(); row != results.end(); ++row) { corpse = Corpse::LoadCharacterCorpseEntity( - atoul(row[0]), + Strings::ToUnsignedInt(row[0]), char_id, row[1], position, row[2], - atoi(row[3]) == 1, + Strings::ToInt(row[3]) == 1, false, - atoul(row[4])); + Strings::ToUnsignedInt(row[4])); if (corpse) { entity_list.AddCorpse(corpse); @@ -4279,7 +4224,7 @@ int ZoneDatabase::CountCharacterCorpses(uint32 char_id) { ); auto results = QueryDatabase(query); for (auto& row = results.begin(); row != results.end(); ++row) { - return atoi(row[0]); + return Strings::ToInt(row[0]); } return 0; } @@ -4301,7 +4246,7 @@ int ZoneDatabase::CountCharacterCorpsesByZoneID(uint32 char_id, uint32 zone_id) ); auto results = QueryDatabase(query); for (auto& row = results.begin(); row != results.end(); ++row) { - return atoi(row[0]); + return Strings::ToInt(row[0]); } return 0; } @@ -4329,16 +4274,16 @@ Corpse* ZoneDatabase::LoadCharacterCorpse(uint32 player_corpse_id) { ); auto results = QueryDatabase(query); for (auto& row = results.begin(); row != results.end(); ++row) { - auto position = glm::vec4(atof(row[3]), atof(row[4]), atof(row[5]), atof(row[6])); + auto position = glm::vec4(Strings::ToFloat(row[3]), Strings::ToFloat(row[4]), Strings::ToFloat(row[5]), Strings::ToFloat(row[6])); NewCorpse = Corpse::LoadCharacterCorpseEntity( - atoul(row[0]), // id uint32 in_dbid - atoul(row[1]), // charid uint32 in_charid + Strings::ToUnsignedInt(row[0]), // id uint32 in_dbid + Strings::ToUnsignedInt(row[1]), // charid uint32 in_charid row[2], // char_name position, row[7], // time_of_death char* time_of_death - atoi(row[8]) == 1, // is_rezzed bool rezzed - atoi(row[9]), // was_at_graveyard bool was_at_graveyard - atoul(row[10]) // guild_consent_id uint32 guild_consent_id + Strings::ToInt(row[8]) == 1, // is_rezzed bool rezzed + Strings::ToInt(row[9]), // was_at_graveyard bool was_at_graveyard + Strings::ToUnsignedInt(row[10]) // guild_consent_id uint32 guild_consent_id ); entity_list.AddCorpse(NewCorpse); } @@ -4356,17 +4301,17 @@ bool ZoneDatabase::LoadCharacterCorpses(uint32 zone_id, uint16 instance_id) { auto results = QueryDatabase(query); for (auto& row = results.begin(); row != results.end(); ++row) { - auto position = glm::vec4(atof(row[3]), atof(row[4]), atof(row[5]), atof(row[6])); + auto position = glm::vec4(Strings::ToFloat(row[3]), Strings::ToFloat(row[4]), Strings::ToFloat(row[5]), Strings::ToFloat(row[6])); entity_list.AddCorpse( Corpse::LoadCharacterCorpseEntity( - atoul(row[0]), // id uint32 in_dbid - atoul(row[1]), // charid uint32 in_charid + Strings::ToUnsignedInt(row[0]), // id uint32 in_dbid + Strings::ToUnsignedInt(row[1]), // charid uint32 in_charid row[2], // char_name position, row[7], // time_of_death char* time_of_death - atoi(row[8]) == 1, // is_rezzed bool rezzed - atoi(row[9]), - atoul(row[10])) // guild_consent_id uint32 guild_consent_id + Strings::ToInt(row[8]) == 1, // is_rezzed bool rezzed + Strings::ToInt(row[9]), + Strings::ToUnsignedInt(row[10])) // guild_consent_id uint32 guild_consent_id ); } @@ -4379,7 +4324,7 @@ uint32 ZoneDatabase::GetFirstCorpseID(uint32 char_id) { std::string query = StringFormat("SELECT `id` FROM `character_corpses` WHERE `charid` = '%u' AND `is_buried` = 0 ORDER BY `time_of_death` LIMIT 1", char_id); auto results = QueryDatabase(query); for (auto& row = results.begin(); row != results.end(); ++row) { - return atoi(row[0]); + return Strings::ToInt(row[0]); } return 0; } @@ -4406,7 +4351,7 @@ bool ZoneDatabase::BuryAllCharacterCorpses(uint32 char_id) { std::string query = StringFormat("SELECT `id` FROM `character_corpses` WHERE `charid` = %u", char_id); auto results = QueryDatabase(query); for (auto& row = results.begin(); row != results.end(); ++row) { - BuryCharacterCorpse(atoi(row[0])); + BuryCharacterCorpse(Strings::ToInt(row[0])); return true; } return false; @@ -4438,7 +4383,7 @@ uint32 ZoneDatabase::LoadSaylinkID(const char* saylink_text, bool auto_insert) } auto& row = results.begin(); - return atoi(row[0]); + return Strings::ToInt(row[0]); } uint32 ZoneDatabase::SaveSaylinkID(const char* saylink_text) @@ -4476,7 +4421,7 @@ double ZoneDatabase::GetAAEXPModifier(uint32 character_id, uint32 zone_id, int16 auto results = database.QueryDatabase(query); for (auto& row = results.begin(); row != results.end(); ++row) { - return atof(row[0]); + return Strings::ToFloat(row[0]); } return 1.0f; @@ -4504,7 +4449,7 @@ double ZoneDatabase::GetEXPModifier(uint32 character_id, uint32 zone_id, int16 i auto results = database.QueryDatabase(query); for (auto& row = results.begin(); row != results.end(); ++row) { - return atof(row[0]); + return Strings::ToFloat(row[0]); } return 1.0f; diff --git a/zone/zonedb.h b/zone/zonedb.h index 3903bd3a8..b7c196a78 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -369,7 +369,8 @@ public: void LoadPetInfo(Client *c); void SavePetInfo(Client *c); void RemoveTempFactions(Client *c); - void UpdateItemRecastTimestamps(uint32 char_id, uint32 recast_type, uint32 timestamp); + void UpdateItemRecast(uint32 char_id, uint32 recast_type, uint32 timestamp); + void DeleteItemRecast(uint32 char_id, uint32 recast_type); bool DeleteCharacterAAs(uint32 character_id); bool DeleteCharacterBandolier(uint32 character_id, uint32 band_id); @@ -562,6 +563,8 @@ public: void UpdateRecipeMadecount(uint32 recipe_id, uint32 char_id, uint32 madecount); bool EnableRecipe(uint32 recipe_id); bool DisableRecipe(uint32 recipe_id); + std::vector GetRecipeComponentItemIDs(RecipeCountType count_type, uint32 recipe_id); + int8 GetRecipeComponentCount(RecipeCountType count_type, uint32 recipe_id, uint32 item_id); /* Tribute */ bool LoadTributes(); @@ -570,21 +573,6 @@ public: std::vector LoadDoors(const std::string& zone_name, int16 version); uint32 GetDoorsCountPlusOne(); int GetDoorsDBCountPlusOne(std::string zone_short_name, int16 version); - void InsertDoor( - uint32 database_id, - uint8 id, - std::string name, - const glm::vec4 &position, - uint8 open_type, - uint16 guild_id, - uint32 ockpick, - uint32 key_item_id, - uint8 door_param, - uint8 invert, - int incline, - uint16 size, - bool disable_timer = false - ); /* Blocked Spells */ int32 GetBlockedSpellsCount(uint32 zoneid); @@ -624,13 +612,9 @@ public: * PLEASE DO NOT ADD TO THIS COLLECTION OF CRAP UNLESS YOUR METHOD * REALLY HAS NO BETTER SECTION */ - bool logevents(const char* accountname,uint32 accountid,uint8 status,const char* charname,const char* target, const char* descriptiontype, const char* description,int event_nid); uint32 GetKarma(uint32 acct_id); void UpdateKarma(uint32 acct_id, uint32 amount); - /* Things which really dont belong here... */ - int16 CommandRequirement(const char* commandname); - // bot database add-on to eliminate the need for a second database connection BotDatabase botdb; diff --git a/zone/zoning.cpp b/zone/zoning.cpp index f2ea57e1b..560e35758 100644 --- a/zone/zoning.cpp +++ b/zone/zoning.cpp @@ -38,6 +38,7 @@ extern Zone* zone; #include "../common/repositories/character_peqzone_flags_repository.h" #include "../common/repositories/zone_repository.h" +#include "../common/events/player_event_logs.h" void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) { @@ -201,19 +202,37 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) { min_status = zone_data->min_status; min_level = zone_data->min_level; - const auto& export_string = fmt::format( - "{} {} {} {} {} {}", - zone->GetZoneID(), - zone->GetInstanceID(), - zone->GetInstanceVersion(), - target_zone_id, - target_instance_id, - target_instance_version - ); + if (parse->PlayerHasQuestSub(EVENT_ZONE)) { + const auto& export_string = fmt::format( + "{} {} {} {} {} {}", + zone->GetZoneID(), + zone->GetInstanceID(), + zone->GetInstanceVersion(), + target_zone_id, + target_instance_id, + target_instance_version + ); - if (parse->EventPlayer(EVENT_ZONE, this, export_string, 0) != 0) { - SendZoneCancel(zc); - return; + if (parse->EventPlayer(EVENT_ZONE, this, export_string, 0) != 0) { + SendZoneCancel(zc); + return; + } + } + + if (player_event_logs.IsEventEnabled(PlayerEvent::ZONING)) { + auto e = PlayerEvent::ZoningEvent{}; + e.from_zone_long_name = zone->GetLongName(); + e.from_zone_short_name = zone->GetShortName(); + e.from_zone_id = zone->GetZoneID(); + e.from_instance_id = zone->GetInstanceID(); + e.from_instance_version = zone->GetInstanceVersion(); + e.to_zone_long_name = ZoneLongName(target_zone_id); + e.to_zone_short_name = ZoneName(target_zone_id); + e.to_zone_id = target_zone_id; + e.to_instance_id = target_instance_id; + e.to_instance_version = target_instance_version; + + RecordPlayerEventLog(PlayerEvent::ZONING, e); } //handle circumvention of zone restrictions @@ -999,7 +1018,7 @@ void Client::LoadZoneFlags() { zone_flags.clear(); for (auto row : results) { - zone_flags.insert(std::stoul(row[0])); + zone_flags.insert(Strings::ToUnsignedInt(row[0])); } } @@ -1243,7 +1262,7 @@ bool Client::CanEnterZone(const std::string& zone_short_name, int16 instance_ver return false; } - if (!z->flag_needed.empty() && Strings::IsNumber(z->flag_needed) && std::stoi(z->flag_needed) == 1) { + if (!z->flag_needed.empty() && Strings::IsNumber(z->flag_needed) && Strings::ToInt(z->flag_needed) == 1) { if (Admin() < minStatusToIgnoreZoneFlags && !HasZoneFlag(z->zoneidnumber)) { LogInfo( "Character [{}] does not have the flag to be in this zone [{}]!",