From 1481fe1ccedf50745bc02bb00b1b164695b0de81 Mon Sep 17 00:00:00 2001 From: Ben Carter Date: Fri, 18 Jul 2025 19:49:02 -0400 Subject: [PATCH] Major overhauls of key systems and scripts --- .../upgrade_ranks/generate_stat_upgrades.sql | 1003 +++++++++-------- scripts/upgrade_ranks/main.go | 155 ++- src/AdvancementMgr.cpp | 251 +++-- src/AdvancementMgr.h | 2 +- src/Event/MpEvent.h | 2 +- src/Event/MpEventHandlers.cpp | 38 +- src/Event/MpEventProcessor.cpp | 2 +- src/MpConstants.h | 105 +- src/MpDataStore.cpp | 99 +- src/MpDataStore.h | 42 +- src/MythicPlus.cpp | 166 ++- src/MythicPlus_loader.cpp | 11 +- src/Scripts/CommandScript.cpp | 10 +- src/Scripts/GlobalScript.cpp | 29 +- src/Scripts/PlayerScript.cpp | 7 + src/Scripts/UnitScript.cpp | 13 +- src/Scripts/WorldScript.cpp | 3 + src/Spells/Toughness.cpp | 70 -- 18 files changed, 1171 insertions(+), 837 deletions(-) delete mode 100644 src/Spells/Toughness.cpp diff --git a/scripts/upgrade_ranks/generate_stat_upgrades.sql b/scripts/upgrade_ranks/generate_stat_upgrades.sql index 4bfbd8a..b310a0d 100644 --- a/scripts/upgrade_ranks/generate_stat_upgrades.sql +++ b/scripts/upgrade_ranks/generate_stat_upgrades.sql @@ -1,502 +1,503 @@ -- SQL Script to Insert 50 Ranks for Each Stat -INSERT INTO mp_upgrade_ranks (upgradeRank, advancementId, materialId1, materialCost1, materialId2, materialCost2, materialId3, materialCost3, minIncrease1, maxIncrease1, minIncrease2, maxIncrease2, minIncrease3, maxIncrease3, chanceCost1, chanceCost2, chanceCost3) VALUES -(1, 0, 1, 100, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 20, 50, 75), -(2, 0, 1, 150, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 23, 53, 78), -(3, 0, 1, 200, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 26, 56, 81), -(4, 0, 1, 250, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 29, 59, 84), -(5, 0, 1, 300, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 32, 62, 87), -(6, 0, 1, 350, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 35, 65, 90), -(7, 0, 1, 400, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 38, 68, 93), -(8, 0, 1, 450, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 41, 71, 96), -(9, 0, 1, 500, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 44, 74, 99), -(10, 0, 1, 550, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 47, 77, 102), -(11, 0, 1, 500, 2, 0, 0, 0, 3, 12, 7, 12, 12, 15, 50, 80, 105), -(12, 0, 1, 525, 2, 10, 0, 0, 3, 12, 7, 12, 12, 15, 53, 83, 108), -(13, 0, 1, 550, 2, 20, 0, 0, 3, 12, 7, 12, 12, 15, 56, 86, 111), -(14, 0, 1, 575, 2, 30, 0, 0, 3, 12, 7, 12, 12, 15, 59, 89, 114), -(15, 0, 1, 600, 2, 40, 0, 0, 3, 12, 7, 12, 12, 15, 62, 92, 117), -(16, 0, 1, 625, 2, 50, 0, 0, 3, 12, 7, 12, 12, 15, 65, 95, 120), -(17, 0, 1, 650, 2, 60, 0, 0, 3, 12, 7, 12, 12, 15, 68, 98, 123), -(18, 0, 1, 675, 2, 70, 0, 0, 3, 12, 7, 12, 12, 15, 71, 101, 126), -(19, 0, 1, 700, 2, 80, 0, 0, 3, 12, 7, 12, 12, 15, 74, 104, 129), -(20, 0, 1, 725, 2, 90, 0, 0, 3, 12, 7, 12, 12, 15, 77, 107, 132), -(21, 0, 1, 750, 2, 100, 0, 0, 5, 14, 9, 14, 16, 19, 80, 110, 135), -(22, 0, 1, 775, 2, 110, 0, 0, 5, 14, 9, 14, 16, 19, 83, 113, 138), -(23, 0, 1, 800, 2, 120, 0, 0, 5, 14, 9, 14, 16, 19, 86, 116, 141), -(24, 0, 1, 825, 2, 130, 0, 0, 5, 14, 9, 14, 16, 19, 89, 119, 144), -(25, 0, 1, 850, 2, 140, 0, 0, 5, 14, 9, 14, 16, 19, 92, 122, 147), -(26, 0, 1, 875, 2, 150, 0, 0, 5, 14, 9, 14, 16, 19, 95, 125, 150), -(27, 0, 1, 900, 2, 160, 0, 0, 5, 14, 9, 14, 16, 19, 98, 128, 153), -(28, 0, 1, 925, 2, 170, 0, 0, 5, 14, 9, 14, 16, 19, 101, 131, 156), -(29, 0, 1, 950, 2, 180, 0, 0, 5, 14, 9, 14, 16, 19, 104, 134, 159), -(30, 0, 1, 1000, 2, 190, 20, 3, 5, 14, 9, 14, 16, 19, 107, 137, 162), -(31, 0, 1, 1018, 2, 200, 20, 6, 7, 16, 11, 16, 20, 23, 110, 140, 165), -(32, 0, 1, 1036, 2, 210, 20, 9, 7, 16, 11, 16, 20, 23, 113, 143, 168), -(33, 0, 1, 1054, 2, 220, 20, 12, 7, 16, 11, 16, 20, 23, 116, 146, 171), -(34, 0, 1, 1072, 2, 230, 20, 15, 7, 16, 11, 16, 20, 23, 119, 149, 174), -(35, 0, 1, 1090, 2, 240, 20, 18, 7, 16, 11, 16, 20, 23, 122, 152, 177), -(36, 0, 1, 1108, 2, 250, 20, 21, 7, 16, 11, 16, 20, 23, 125, 155, 180), -(37, 0, 1, 1126, 2, 260, 20, 24, 7, 16, 11, 16, 20, 23, 128, 158, 183), -(38, 0, 1, 1144, 2, 270, 20, 27, 7, 16, 11, 16, 20, 23, 131, 161, 186), -(39, 0, 1, 1162, 2, 280, 20, 30, 7, 16, 11, 16, 20, 23, 134, 164, 189), -(40, 0, 1, 1180, 2, 290, 20, 33, 7, 16, 11, 16, 20, 23, 137, 167, 192), -(41, 0, 1, 1198, 2, 300, 20, 36, 9, 18, 13, 18, 24, 27, 140, 170, 195), -(42, 0, 1, 1216, 2, 310, 20, 39, 9, 18, 13, 18, 24, 27, 143, 173, 198), -(43, 0, 1, 1234, 2, 320, 20, 42, 9, 18, 13, 18, 24, 27, 146, 176, 201), -(44, 0, 1, 1252, 2, 330, 20, 45, 9, 18, 13, 18, 24, 27, 149, 179, 204), -(45, 0, 1, 1270, 2, 340, 20, 48, 9, 18, 13, 18, 24, 27, 152, 182, 207), -(46, 0, 1, 1288, 2, 350, 20, 51, 9, 18, 13, 18, 24, 27, 155, 185, 210), -(47, 0, 1, 1306, 2, 360, 20, 54, 9, 18, 13, 18, 24, 27, 158, 188, 213), -(48, 0, 1, 1324, 2, 370, 20, 57, 9, 18, 13, 18, 24, 27, 161, 191, 216), -(49, 0, 1, 1342, 2, 380, 20, 60, 9, 18, 13, 18, 24, 27, 164, 194, 219), -(50, 0, 1, 1360, 2, 390, 20, 63, 9, 18, 13, 18, 24, 27, 167, 197, 222), -(1, 1, 3, 100, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 20, 50, 75), -(2, 1, 3, 150, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 23, 53, 78), -(3, 1, 3, 200, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 26, 56, 81), -(4, 1, 3, 250, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 29, 59, 84), -(5, 1, 3, 300, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 32, 62, 87), -(6, 1, 3, 350, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 35, 65, 90), -(7, 1, 3, 400, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 38, 68, 93), -(8, 1, 3, 450, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 41, 71, 96), -(9, 1, 3, 500, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 44, 74, 99), -(10, 1, 3, 550, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 47, 77, 102), -(11, 1, 3, 500, 4, 0, 0, 0, 3, 12, 7, 12, 12, 15, 50, 80, 105), -(12, 1, 3, 525, 4, 10, 0, 0, 3, 12, 7, 12, 12, 15, 53, 83, 108), -(13, 1, 3, 550, 4, 20, 0, 0, 3, 12, 7, 12, 12, 15, 56, 86, 111), -(14, 1, 3, 575, 4, 30, 0, 0, 3, 12, 7, 12, 12, 15, 59, 89, 114), -(15, 1, 3, 600, 4, 40, 0, 0, 3, 12, 7, 12, 12, 15, 62, 92, 117), -(16, 1, 3, 625, 4, 50, 0, 0, 3, 12, 7, 12, 12, 15, 65, 95, 120), -(17, 1, 3, 650, 4, 60, 0, 0, 3, 12, 7, 12, 12, 15, 68, 98, 123), -(18, 1, 3, 675, 4, 70, 0, 0, 3, 12, 7, 12, 12, 15, 71, 101, 126), -(19, 1, 3, 700, 4, 80, 0, 0, 3, 12, 7, 12, 12, 15, 74, 104, 129), -(20, 1, 3, 725, 4, 90, 0, 0, 3, 12, 7, 12, 12, 15, 77, 107, 132), -(21, 1, 3, 750, 4, 100, 0, 0, 5, 14, 9, 14, 16, 19, 80, 110, 135), -(22, 1, 3, 775, 4, 110, 0, 0, 5, 14, 9, 14, 16, 19, 83, 113, 138), -(23, 1, 3, 800, 4, 120, 0, 0, 5, 14, 9, 14, 16, 19, 86, 116, 141), -(24, 1, 3, 825, 4, 130, 0, 0, 5, 14, 9, 14, 16, 19, 89, 119, 144), -(25, 1, 3, 850, 4, 140, 0, 0, 5, 14, 9, 14, 16, 19, 92, 122, 147), -(26, 1, 3, 875, 4, 150, 0, 0, 5, 14, 9, 14, 16, 19, 95, 125, 150), -(27, 1, 3, 900, 4, 160, 0, 0, 5, 14, 9, 14, 16, 19, 98, 128, 153), -(28, 1, 3, 925, 4, 170, 0, 0, 5, 14, 9, 14, 16, 19, 101, 131, 156), -(29, 1, 3, 950, 4, 180, 0, 0, 5, 14, 9, 14, 16, 19, 104, 134, 159), -(30, 1, 3, 1000, 4, 190, 20, 3, 5, 14, 9, 14, 16, 19, 107, 137, 162), -(31, 1, 3, 1018, 4, 200, 20, 6, 7, 16, 11, 16, 20, 23, 110, 140, 165), -(32, 1, 3, 1036, 4, 210, 20, 9, 7, 16, 11, 16, 20, 23, 113, 143, 168), -(33, 1, 3, 1054, 4, 220, 20, 12, 7, 16, 11, 16, 20, 23, 116, 146, 171), -(34, 1, 3, 1072, 4, 230, 20, 15, 7, 16, 11, 16, 20, 23, 119, 149, 174), -(35, 1, 3, 1090, 4, 240, 20, 18, 7, 16, 11, 16, 20, 23, 122, 152, 177), -(36, 1, 3, 1108, 4, 250, 20, 21, 7, 16, 11, 16, 20, 23, 125, 155, 180), -(37, 1, 3, 1126, 4, 260, 20, 24, 7, 16, 11, 16, 20, 23, 128, 158, 183), -(38, 1, 3, 1144, 4, 270, 20, 27, 7, 16, 11, 16, 20, 23, 131, 161, 186), -(39, 1, 3, 1162, 4, 280, 20, 30, 7, 16, 11, 16, 20, 23, 134, 164, 189), -(40, 1, 3, 1180, 4, 290, 20, 33, 7, 16, 11, 16, 20, 23, 137, 167, 192), -(41, 1, 3, 1198, 4, 300, 20, 36, 9, 18, 13, 18, 24, 27, 140, 170, 195), -(42, 1, 3, 1216, 4, 310, 20, 39, 9, 18, 13, 18, 24, 27, 143, 173, 198), -(43, 1, 3, 1234, 4, 320, 20, 42, 9, 18, 13, 18, 24, 27, 146, 176, 201), -(44, 1, 3, 1252, 4, 330, 20, 45, 9, 18, 13, 18, 24, 27, 149, 179, 204), -(45, 1, 3, 1270, 4, 340, 20, 48, 9, 18, 13, 18, 24, 27, 152, 182, 207), -(46, 1, 3, 1288, 4, 350, 20, 51, 9, 18, 13, 18, 24, 27, 155, 185, 210), -(47, 1, 3, 1306, 4, 360, 20, 54, 9, 18, 13, 18, 24, 27, 158, 188, 213), -(48, 1, 3, 1324, 4, 370, 20, 57, 9, 18, 13, 18, 24, 27, 161, 191, 216), -(49, 1, 3, 1342, 4, 380, 20, 60, 9, 18, 13, 18, 24, 27, 164, 194, 219), -(50, 1, 3, 1360, 4, 390, 20, 63, 9, 18, 13, 18, 24, 27, 167, 197, 222), -(1, 2, 5, 100, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 20, 50, 75), -(2, 2, 5, 150, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 23, 53, 78), -(3, 2, 5, 200, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 26, 56, 81), -(4, 2, 5, 250, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 29, 59, 84), -(5, 2, 5, 300, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 32, 62, 87), -(6, 2, 5, 350, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 35, 65, 90), -(7, 2, 5, 400, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 38, 68, 93), -(8, 2, 5, 450, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 41, 71, 96), -(9, 2, 5, 500, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 44, 74, 99), -(10, 2, 5, 550, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 47, 77, 102), -(11, 2, 5, 500, 6, 0, 0, 0, 3, 12, 7, 12, 12, 15, 50, 80, 105), -(12, 2, 5, 525, 6, 10, 0, 0, 3, 12, 7, 12, 12, 15, 53, 83, 108), -(13, 2, 5, 550, 6, 20, 0, 0, 3, 12, 7, 12, 12, 15, 56, 86, 111), -(14, 2, 5, 575, 6, 30, 0, 0, 3, 12, 7, 12, 12, 15, 59, 89, 114), -(15, 2, 5, 600, 6, 40, 0, 0, 3, 12, 7, 12, 12, 15, 62, 92, 117), -(16, 2, 5, 625, 6, 50, 0, 0, 3, 12, 7, 12, 12, 15, 65, 95, 120), -(17, 2, 5, 650, 6, 60, 0, 0, 3, 12, 7, 12, 12, 15, 68, 98, 123), -(18, 2, 5, 675, 6, 70, 0, 0, 3, 12, 7, 12, 12, 15, 71, 101, 126), -(19, 2, 5, 700, 6, 80, 0, 0, 3, 12, 7, 12, 12, 15, 74, 104, 129), -(20, 2, 5, 725, 6, 90, 0, 0, 3, 12, 7, 12, 12, 15, 77, 107, 132), -(21, 2, 5, 750, 6, 100, 0, 0, 5, 14, 9, 14, 16, 19, 80, 110, 135), -(22, 2, 5, 775, 6, 110, 0, 0, 5, 14, 9, 14, 16, 19, 83, 113, 138), -(23, 2, 5, 800, 6, 120, 0, 0, 5, 14, 9, 14, 16, 19, 86, 116, 141), -(24, 2, 5, 825, 6, 130, 0, 0, 5, 14, 9, 14, 16, 19, 89, 119, 144), -(25, 2, 5, 850, 6, 140, 0, 0, 5, 14, 9, 14, 16, 19, 92, 122, 147), -(26, 2, 5, 875, 6, 150, 0, 0, 5, 14, 9, 14, 16, 19, 95, 125, 150), -(27, 2, 5, 900, 6, 160, 0, 0, 5, 14, 9, 14, 16, 19, 98, 128, 153), -(28, 2, 5, 925, 6, 170, 0, 0, 5, 14, 9, 14, 16, 19, 101, 131, 156), -(29, 2, 5, 950, 6, 180, 0, 0, 5, 14, 9, 14, 16, 19, 104, 134, 159), -(30, 2, 5, 1000, 6, 190, 20, 3, 5, 14, 9, 14, 16, 19, 107, 137, 162), -(31, 2, 5, 1018, 6, 200, 20, 6, 7, 16, 11, 16, 20, 23, 110, 140, 165), -(32, 2, 5, 1036, 6, 210, 20, 9, 7, 16, 11, 16, 20, 23, 113, 143, 168), -(33, 2, 5, 1054, 6, 220, 20, 12, 7, 16, 11, 16, 20, 23, 116, 146, 171), -(34, 2, 5, 1072, 6, 230, 20, 15, 7, 16, 11, 16, 20, 23, 119, 149, 174), -(35, 2, 5, 1090, 6, 240, 20, 18, 7, 16, 11, 16, 20, 23, 122, 152, 177), -(36, 2, 5, 1108, 6, 250, 20, 21, 7, 16, 11, 16, 20, 23, 125, 155, 180), -(37, 2, 5, 1126, 6, 260, 20, 24, 7, 16, 11, 16, 20, 23, 128, 158, 183), -(38, 2, 5, 1144, 6, 270, 20, 27, 7, 16, 11, 16, 20, 23, 131, 161, 186), -(39, 2, 5, 1162, 6, 280, 20, 30, 7, 16, 11, 16, 20, 23, 134, 164, 189), -(40, 2, 5, 1180, 6, 290, 20, 33, 7, 16, 11, 16, 20, 23, 137, 167, 192), -(41, 2, 5, 1198, 6, 300, 20, 36, 9, 18, 13, 18, 24, 27, 140, 170, 195), -(42, 2, 5, 1216, 6, 310, 20, 39, 9, 18, 13, 18, 24, 27, 143, 173, 198), -(43, 2, 5, 1234, 6, 320, 20, 42, 9, 18, 13, 18, 24, 27, 146, 176, 201), -(44, 2, 5, 1252, 6, 330, 20, 45, 9, 18, 13, 18, 24, 27, 149, 179, 204), -(45, 2, 5, 1270, 6, 340, 20, 48, 9, 18, 13, 18, 24, 27, 152, 182, 207), -(46, 2, 5, 1288, 6, 350, 20, 51, 9, 18, 13, 18, 24, 27, 155, 185, 210), -(47, 2, 5, 1306, 6, 360, 20, 54, 9, 18, 13, 18, 24, 27, 158, 188, 213), -(48, 2, 5, 1324, 6, 370, 20, 57, 9, 18, 13, 18, 24, 27, 161, 191, 216), -(49, 2, 5, 1342, 6, 380, 20, 60, 9, 18, 13, 18, 24, 27, 164, 194, 219), -(50, 2, 5, 1360, 6, 390, 20, 63, 9, 18, 13, 18, 24, 27, 167, 197, 222), -(1, 3, 7, 100, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 20, 50, 75), -(2, 3, 7, 150, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 23, 53, 78), -(3, 3, 7, 200, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 26, 56, 81), -(4, 3, 7, 250, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 29, 59, 84), -(5, 3, 7, 300, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 32, 62, 87), -(6, 3, 7, 350, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 35, 65, 90), -(7, 3, 7, 400, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 38, 68, 93), -(8, 3, 7, 450, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 41, 71, 96), -(9, 3, 7, 500, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 44, 74, 99), -(10, 3, 7, 550, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 47, 77, 102), -(11, 3, 7, 500, 8, 0, 0, 0, 3, 12, 7, 12, 12, 15, 50, 80, 105), -(12, 3, 7, 525, 8, 10, 0, 0, 3, 12, 7, 12, 12, 15, 53, 83, 108), -(13, 3, 7, 550, 8, 20, 0, 0, 3, 12, 7, 12, 12, 15, 56, 86, 111), -(14, 3, 7, 575, 8, 30, 0, 0, 3, 12, 7, 12, 12, 15, 59, 89, 114), -(15, 3, 7, 600, 8, 40, 0, 0, 3, 12, 7, 12, 12, 15, 62, 92, 117), -(16, 3, 7, 625, 8, 50, 0, 0, 3, 12, 7, 12, 12, 15, 65, 95, 120), -(17, 3, 7, 650, 8, 60, 0, 0, 3, 12, 7, 12, 12, 15, 68, 98, 123), -(18, 3, 7, 675, 8, 70, 0, 0, 3, 12, 7, 12, 12, 15, 71, 101, 126), -(19, 3, 7, 700, 8, 80, 0, 0, 3, 12, 7, 12, 12, 15, 74, 104, 129), -(20, 3, 7, 725, 8, 90, 0, 0, 3, 12, 7, 12, 12, 15, 77, 107, 132), -(21, 3, 7, 750, 8, 100, 0, 0, 5, 14, 9, 14, 16, 19, 80, 110, 135), -(22, 3, 7, 775, 8, 110, 0, 0, 5, 14, 9, 14, 16, 19, 83, 113, 138), -(23, 3, 7, 800, 8, 120, 0, 0, 5, 14, 9, 14, 16, 19, 86, 116, 141), -(24, 3, 7, 825, 8, 130, 0, 0, 5, 14, 9, 14, 16, 19, 89, 119, 144), -(25, 3, 7, 850, 8, 140, 0, 0, 5, 14, 9, 14, 16, 19, 92, 122, 147), -(26, 3, 7, 875, 8, 150, 0, 0, 5, 14, 9, 14, 16, 19, 95, 125, 150), -(27, 3, 7, 900, 8, 160, 0, 0, 5, 14, 9, 14, 16, 19, 98, 128, 153), -(28, 3, 7, 925, 8, 170, 0, 0, 5, 14, 9, 14, 16, 19, 101, 131, 156), -(29, 3, 7, 950, 8, 180, 0, 0, 5, 14, 9, 14, 16, 19, 104, 134, 159), -(30, 3, 7, 1000, 8, 190, 20, 3, 5, 14, 9, 14, 16, 19, 107, 137, 162), -(31, 3, 7, 1018, 8, 200, 20, 6, 7, 16, 11, 16, 20, 23, 110, 140, 165), -(32, 3, 7, 1036, 8, 210, 20, 9, 7, 16, 11, 16, 20, 23, 113, 143, 168), -(33, 3, 7, 1054, 8, 220, 20, 12, 7, 16, 11, 16, 20, 23, 116, 146, 171), -(34, 3, 7, 1072, 8, 230, 20, 15, 7, 16, 11, 16, 20, 23, 119, 149, 174), -(35, 3, 7, 1090, 8, 240, 20, 18, 7, 16, 11, 16, 20, 23, 122, 152, 177), -(36, 3, 7, 1108, 8, 250, 20, 21, 7, 16, 11, 16, 20, 23, 125, 155, 180), -(37, 3, 7, 1126, 8, 260, 20, 24, 7, 16, 11, 16, 20, 23, 128, 158, 183), -(38, 3, 7, 1144, 8, 270, 20, 27, 7, 16, 11, 16, 20, 23, 131, 161, 186), -(39, 3, 7, 1162, 8, 280, 20, 30, 7, 16, 11, 16, 20, 23, 134, 164, 189), -(40, 3, 7, 1180, 8, 290, 20, 33, 7, 16, 11, 16, 20, 23, 137, 167, 192), -(41, 3, 7, 1198, 8, 300, 20, 36, 9, 18, 13, 18, 24, 27, 140, 170, 195), -(42, 3, 7, 1216, 8, 310, 20, 39, 9, 18, 13, 18, 24, 27, 143, 173, 198), -(43, 3, 7, 1234, 8, 320, 20, 42, 9, 18, 13, 18, 24, 27, 146, 176, 201), -(44, 3, 7, 1252, 8, 330, 20, 45, 9, 18, 13, 18, 24, 27, 149, 179, 204), -(45, 3, 7, 1270, 8, 340, 20, 48, 9, 18, 13, 18, 24, 27, 152, 182, 207), -(46, 3, 7, 1288, 8, 350, 20, 51, 9, 18, 13, 18, 24, 27, 155, 185, 210), -(47, 3, 7, 1306, 8, 360, 20, 54, 9, 18, 13, 18, 24, 27, 158, 188, 213), -(48, 3, 7, 1324, 8, 370, 20, 57, 9, 18, 13, 18, 24, 27, 161, 191, 216), -(49, 3, 7, 1342, 8, 380, 20, 60, 9, 18, 13, 18, 24, 27, 164, 194, 219), -(50, 3, 7, 1360, 8, 390, 20, 63, 9, 18, 13, 18, 24, 27, 167, 197, 222), -(1, 4, 9, 100, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 20, 50, 75), -(2, 4, 9, 150, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 23, 53, 78), -(3, 4, 9, 200, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 26, 56, 81), -(4, 4, 9, 250, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 29, 59, 84), -(5, 4, 9, 300, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 32, 62, 87), -(6, 4, 9, 350, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 35, 65, 90), -(7, 4, 9, 400, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 38, 68, 93), -(8, 4, 9, 450, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 41, 71, 96), -(9, 4, 9, 500, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 44, 74, 99), -(10, 4, 9, 550, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 47, 77, 102), -(11, 4, 9, 500, 10, 0, 0, 0, 3, 12, 7, 12, 12, 15, 50, 80, 105), -(12, 4, 9, 525, 10, 10, 0, 0, 3, 12, 7, 12, 12, 15, 53, 83, 108), -(13, 4, 9, 550, 10, 20, 0, 0, 3, 12, 7, 12, 12, 15, 56, 86, 111), -(14, 4, 9, 575, 10, 30, 0, 0, 3, 12, 7, 12, 12, 15, 59, 89, 114), -(15, 4, 9, 600, 10, 40, 0, 0, 3, 12, 7, 12, 12, 15, 62, 92, 117), -(16, 4, 9, 625, 10, 50, 0, 0, 3, 12, 7, 12, 12, 15, 65, 95, 120), -(17, 4, 9, 650, 10, 60, 0, 0, 3, 12, 7, 12, 12, 15, 68, 98, 123), -(18, 4, 9, 675, 10, 70, 0, 0, 3, 12, 7, 12, 12, 15, 71, 101, 126), -(19, 4, 9, 700, 10, 80, 0, 0, 3, 12, 7, 12, 12, 15, 74, 104, 129), -(20, 4, 9, 725, 10, 90, 0, 0, 3, 12, 7, 12, 12, 15, 77, 107, 132), -(21, 4, 9, 750, 10, 100, 0, 0, 5, 14, 9, 14, 16, 19, 80, 110, 135), -(22, 4, 9, 775, 10, 110, 0, 0, 5, 14, 9, 14, 16, 19, 83, 113, 138), -(23, 4, 9, 800, 10, 120, 0, 0, 5, 14, 9, 14, 16, 19, 86, 116, 141), -(24, 4, 9, 825, 10, 130, 0, 0, 5, 14, 9, 14, 16, 19, 89, 119, 144), -(25, 4, 9, 850, 10, 140, 0, 0, 5, 14, 9, 14, 16, 19, 92, 122, 147), -(26, 4, 9, 875, 10, 150, 0, 0, 5, 14, 9, 14, 16, 19, 95, 125, 150), -(27, 4, 9, 900, 10, 160, 0, 0, 5, 14, 9, 14, 16, 19, 98, 128, 153), -(28, 4, 9, 925, 10, 170, 0, 0, 5, 14, 9, 14, 16, 19, 101, 131, 156), -(29, 4, 9, 950, 10, 180, 0, 0, 5, 14, 9, 14, 16, 19, 104, 134, 159), -(30, 4, 9, 1000, 10, 190, 20, 3, 5, 14, 9, 14, 16, 19, 107, 137, 162), -(31, 4, 9, 1018, 10, 200, 20, 6, 7, 16, 11, 16, 20, 23, 110, 140, 165), -(32, 4, 9, 1036, 10, 210, 20, 9, 7, 16, 11, 16, 20, 23, 113, 143, 168), -(33, 4, 9, 1054, 10, 220, 20, 12, 7, 16, 11, 16, 20, 23, 116, 146, 171), -(34, 4, 9, 1072, 10, 230, 20, 15, 7, 16, 11, 16, 20, 23, 119, 149, 174), -(35, 4, 9, 1090, 10, 240, 20, 18, 7, 16, 11, 16, 20, 23, 122, 152, 177), -(36, 4, 9, 1108, 10, 250, 20, 21, 7, 16, 11, 16, 20, 23, 125, 155, 180), -(37, 4, 9, 1126, 10, 260, 20, 24, 7, 16, 11, 16, 20, 23, 128, 158, 183), -(38, 4, 9, 1144, 10, 270, 20, 27, 7, 16, 11, 16, 20, 23, 131, 161, 186), -(39, 4, 9, 1162, 10, 280, 20, 30, 7, 16, 11, 16, 20, 23, 134, 164, 189), -(40, 4, 9, 1180, 10, 290, 20, 33, 7, 16, 11, 16, 20, 23, 137, 167, 192), -(41, 4, 9, 1198, 10, 300, 20, 36, 9, 18, 13, 18, 24, 27, 140, 170, 195), -(42, 4, 9, 1216, 10, 310, 20, 39, 9, 18, 13, 18, 24, 27, 143, 173, 198), -(43, 4, 9, 1234, 10, 320, 20, 42, 9, 18, 13, 18, 24, 27, 146, 176, 201), -(44, 4, 9, 1252, 10, 330, 20, 45, 9, 18, 13, 18, 24, 27, 149, 179, 204), -(45, 4, 9, 1270, 10, 340, 20, 48, 9, 18, 13, 18, 24, 27, 152, 182, 207), -(46, 4, 9, 1288, 10, 350, 20, 51, 9, 18, 13, 18, 24, 27, 155, 185, 210), -(47, 4, 9, 1306, 10, 360, 20, 54, 9, 18, 13, 18, 24, 27, 158, 188, 213), -(48, 4, 9, 1324, 10, 370, 20, 57, 9, 18, 13, 18, 24, 27, 161, 191, 216), -(49, 4, 9, 1342, 10, 380, 20, 60, 9, 18, 13, 18, 24, 27, 164, 194, 219), -(50, 4, 9, 1360, 10, 390, 20, 63, 9, 18, 13, 18, 24, 27, 167, 197, 222), -(1, 7, 15, 75, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 20, 50, 75), -(2, 7, 15, 110, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 23, 53, 78), -(3, 7, 15, 145, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 26, 56, 81), -(4, 7, 15, 180, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 29, 59, 84), -(5, 7, 15, 215, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 32, 62, 87), -(6, 7, 15, 250, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 35, 65, 90), -(7, 7, 15, 285, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 38, 68, 93), -(8, 7, 15, 320, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 41, 71, 96), -(9, 7, 15, 355, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 44, 74, 99), -(10, 7, 15, 390, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 47, 77, 102), -(11, 7, 15, 350, 16, 0, 0, 0, 5, 9, 7, 9, 12, 14, 50, 80, 105), -(12, 7, 15, 375, 16, 10, 0, 0, 5, 9, 7, 9, 12, 14, 53, 83, 108), -(13, 7, 15, 400, 16, 20, 0, 0, 5, 9, 7, 9, 12, 14, 56, 86, 111), -(14, 7, 15, 425, 16, 30, 0, 0, 5, 9, 7, 9, 12, 14, 59, 89, 114), -(15, 7, 15, 450, 16, 40, 0, 0, 5, 9, 7, 9, 12, 14, 62, 92, 117), -(16, 7, 15, 475, 16, 50, 0, 0, 7, 11, 9, 11, 16, 18, 65, 95, 120), -(17, 7, 15, 500, 16, 60, 0, 0, 7, 11, 9, 11, 16, 18, 68, 98, 123), -(18, 7, 15, 525, 16, 70, 0, 0, 7, 11, 9, 11, 16, 18, 71, 101, 126), -(19, 7, 15, 550, 16, 80, 0, 0, 7, 11, 9, 11, 16, 18, 74, 104, 129), -(20, 7, 15, 575, 16, 90, 0, 0, 7, 11, 9, 11, 16, 18, 77, 107, 132), -(21, 7, 15, 600, 16, 100, 0, 0, 9, 13, 11, 13, 20, 22, 80, 110, 135), -(22, 7, 15, 625, 16, 110, 0, 0, 9, 13, 11, 13, 20, 22, 83, 113, 138), -(23, 7, 15, 650, 16, 120, 0, 0, 9, 13, 11, 13, 20, 22, 86, 116, 141), -(24, 7, 15, 675, 16, 130, 0, 0, 9, 13, 11, 13, 20, 22, 89, 119, 144), -(25, 7, 15, 700, 16, 140, 0, 0, 9, 13, 11, 13, 20, 22, 92, 122, 147), -(26, 7, 15, 725, 16, 150, 0, 0, 11, 15, 13, 15, 24, 26, 95, 125, 150), -(27, 7, 15, 750, 16, 160, 0, 0, 11, 15, 13, 15, 24, 26, 98, 128, 153), -(28, 7, 15, 775, 16, 170, 0, 0, 11, 15, 13, 15, 24, 26, 101, 131, 156), -(29, 7, 15, 800, 16, 180, 0, 0, 11, 15, 13, 15, 24, 26, 104, 134, 159), -(30, 7, 15, 700, 16, 190, 20, 3, 11, 15, 13, 15, 24, 26, 107, 137, 162), -(31, 7, 15, 718, 16, 200, 20, 6, 13, 17, 15, 17, 28, 30, 110, 140, 165), -(32, 7, 15, 736, 16, 210, 20, 9, 13, 17, 15, 17, 28, 30, 113, 143, 168), -(33, 7, 15, 754, 16, 220, 20, 12, 13, 17, 15, 17, 28, 30, 116, 146, 171), -(34, 7, 15, 772, 16, 230, 20, 15, 13, 17, 15, 17, 28, 30, 119, 149, 174), -(35, 7, 15, 790, 16, 240, 20, 18, 13, 17, 15, 17, 28, 30, 122, 152, 177), -(36, 7, 15, 808, 16, 250, 20, 21, 15, 19, 17, 19, 32, 34, 125, 155, 180), -(37, 7, 15, 826, 16, 260, 20, 24, 15, 19, 17, 19, 32, 34, 128, 158, 183), -(38, 7, 15, 844, 16, 270, 20, 27, 15, 19, 17, 19, 32, 34, 131, 161, 186), -(39, 7, 15, 862, 16, 280, 20, 30, 15, 19, 17, 19, 32, 34, 134, 164, 189), -(40, 7, 15, 880, 16, 290, 20, 33, 15, 19, 17, 19, 32, 34, 137, 167, 192), -(41, 7, 15, 898, 16, 300, 20, 36, 17, 21, 19, 21, 36, 38, 140, 170, 195), -(42, 7, 15, 916, 16, 310, 20, 39, 17, 21, 19, 21, 36, 38, 143, 173, 198), -(43, 7, 15, 934, 16, 320, 20, 42, 17, 21, 19, 21, 36, 38, 146, 176, 201), -(44, 7, 15, 952, 16, 330, 20, 45, 17, 21, 19, 21, 36, 38, 149, 179, 204), -(45, 7, 15, 970, 16, 340, 20, 48, 17, 21, 19, 21, 36, 38, 152, 182, 207), -(46, 7, 15, 988, 16, 350, 20, 51, 19, 23, 21, 23, 40, 42, 155, 185, 210), -(47, 7, 15, 1006, 16, 360, 20, 54, 19, 23, 21, 23, 40, 42, 158, 188, 213), -(48, 7, 15, 1024, 16, 370, 20, 57, 19, 23, 21, 23, 40, 42, 161, 191, 216), -(49, 7, 15, 1042, 16, 380, 20, 60, 19, 23, 21, 23, 40, 42, 164, 194, 219), -(50, 7, 15, 1060, 16, 390, 20, 63, 19, 23, 21, 23, 40, 42, 167, 197, 222), -(1, 8, 17, 75, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 20, 50, 75), -(2, 8, 17, 110, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 23, 53, 78), -(3, 8, 17, 145, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 26, 56, 81), -(4, 8, 17, 180, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 29, 59, 84), -(5, 8, 17, 215, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 32, 62, 87), -(6, 8, 17, 250, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 35, 65, 90), -(7, 8, 17, 285, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 38, 68, 93), -(8, 8, 17, 320, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 41, 71, 96), -(9, 8, 17, 355, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 44, 74, 99), -(10, 8, 17, 390, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 47, 77, 102), -(11, 8, 17, 350, 18, 0, 0, 0, 5, 9, 7, 9, 12, 14, 50, 80, 105), -(12, 8, 17, 375, 18, 10, 0, 0, 5, 9, 7, 9, 12, 14, 53, 83, 108), -(13, 8, 17, 400, 18, 20, 0, 0, 5, 9, 7, 9, 12, 14, 56, 86, 111), -(14, 8, 17, 425, 18, 30, 0, 0, 5, 9, 7, 9, 12, 14, 59, 89, 114), -(15, 8, 17, 450, 18, 40, 0, 0, 5, 9, 7, 9, 12, 14, 62, 92, 117), -(16, 8, 17, 475, 18, 50, 0, 0, 7, 11, 9, 11, 16, 18, 65, 95, 120), -(17, 8, 17, 500, 18, 60, 0, 0, 7, 11, 9, 11, 16, 18, 68, 98, 123), -(18, 8, 17, 525, 18, 70, 0, 0, 7, 11, 9, 11, 16, 18, 71, 101, 126), -(19, 8, 17, 550, 18, 80, 0, 0, 7, 11, 9, 11, 16, 18, 74, 104, 129), -(20, 8, 17, 575, 18, 90, 0, 0, 7, 11, 9, 11, 16, 18, 77, 107, 132), -(21, 8, 17, 600, 18, 100, 0, 0, 9, 13, 11, 13, 20, 22, 80, 110, 135), -(22, 8, 17, 625, 18, 110, 0, 0, 9, 13, 11, 13, 20, 22, 83, 113, 138), -(23, 8, 17, 650, 18, 120, 0, 0, 9, 13, 11, 13, 20, 22, 86, 116, 141), -(24, 8, 17, 675, 18, 130, 0, 0, 9, 13, 11, 13, 20, 22, 89, 119, 144), -(25, 8, 17, 700, 18, 140, 0, 0, 9, 13, 11, 13, 20, 22, 92, 122, 147), -(26, 8, 17, 725, 18, 150, 0, 0, 11, 15, 13, 15, 24, 26, 95, 125, 150), -(27, 8, 17, 750, 18, 160, 0, 0, 11, 15, 13, 15, 24, 26, 98, 128, 153), -(28, 8, 17, 775, 18, 170, 0, 0, 11, 15, 13, 15, 24, 26, 101, 131, 156), -(29, 8, 17, 800, 18, 180, 0, 0, 11, 15, 13, 15, 24, 26, 104, 134, 159), -(30, 8, 17, 700, 18, 190, 20, 3, 11, 15, 13, 15, 24, 26, 107, 137, 162), -(31, 8, 17, 718, 18, 200, 20, 6, 13, 17, 15, 17, 28, 30, 110, 140, 165), -(32, 8, 17, 736, 18, 210, 20, 9, 13, 17, 15, 17, 28, 30, 113, 143, 168), -(33, 8, 17, 754, 18, 220, 20, 12, 13, 17, 15, 17, 28, 30, 116, 146, 171), -(34, 8, 17, 772, 18, 230, 20, 15, 13, 17, 15, 17, 28, 30, 119, 149, 174), -(35, 8, 17, 790, 18, 240, 20, 18, 13, 17, 15, 17, 28, 30, 122, 152, 177), -(36, 8, 17, 808, 18, 250, 20, 21, 15, 19, 17, 19, 32, 34, 125, 155, 180), -(37, 8, 17, 826, 18, 260, 20, 24, 15, 19, 17, 19, 32, 34, 128, 158, 183), -(38, 8, 17, 844, 18, 270, 20, 27, 15, 19, 17, 19, 32, 34, 131, 161, 186), -(39, 8, 17, 862, 18, 280, 20, 30, 15, 19, 17, 19, 32, 34, 134, 164, 189), -(40, 8, 17, 880, 18, 290, 20, 33, 15, 19, 17, 19, 32, 34, 137, 167, 192), -(41, 8, 17, 898, 18, 300, 20, 36, 17, 21, 19, 21, 36, 38, 140, 170, 195), -(42, 8, 17, 916, 18, 310, 20, 39, 17, 21, 19, 21, 36, 38, 143, 173, 198), -(43, 8, 17, 934, 18, 320, 20, 42, 17, 21, 19, 21, 36, 38, 146, 176, 201), -(44, 8, 17, 952, 18, 330, 20, 45, 17, 21, 19, 21, 36, 38, 149, 179, 204), -(45, 8, 17, 970, 18, 340, 20, 48, 17, 21, 19, 21, 36, 38, 152, 182, 207), -(46, 8, 17, 988, 18, 350, 20, 51, 19, 23, 21, 23, 40, 42, 155, 185, 210), -(47, 8, 17, 1006, 18, 360, 20, 54, 19, 23, 21, 23, 40, 42, 158, 188, 213), -(48, 8, 17, 1024, 18, 370, 20, 57, 19, 23, 21, 23, 40, 42, 161, 191, 216), -(49, 8, 17, 1042, 18, 380, 20, 60, 19, 23, 21, 23, 40, 42, 164, 194, 219), -(50, 8, 17, 1060, 18, 390, 20, 63, 19, 23, 21, 23, 40, 42, 167, 197, 222), -(1, 9, 19, 75, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 20, 50, 75), -(2, 9, 19, 110, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 23, 53, 78), -(3, 9, 19, 145, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 26, 56, 81), -(4, 9, 19, 180, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 29, 59, 84), -(5, 9, 19, 215, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 32, 62, 87), -(6, 9, 19, 250, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 35, 65, 90), -(7, 9, 19, 285, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 38, 68, 93), -(8, 9, 19, 320, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 41, 71, 96), -(9, 9, 19, 355, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 44, 74, 99), -(10, 9, 19, 390, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 47, 77, 102), -(11, 9, 19, 350, 20, 0, 0, 0, 5, 9, 7, 9, 12, 14, 50, 80, 105), -(12, 9, 19, 375, 20, 10, 0, 0, 5, 9, 7, 9, 12, 14, 53, 83, 108), -(13, 9, 19, 400, 20, 20, 0, 0, 5, 9, 7, 9, 12, 14, 56, 86, 111), -(14, 9, 19, 425, 20, 30, 0, 0, 5, 9, 7, 9, 12, 14, 59, 89, 114), -(15, 9, 19, 450, 20, 40, 0, 0, 5, 9, 7, 9, 12, 14, 62, 92, 117), -(16, 9, 19, 475, 20, 50, 0, 0, 7, 11, 9, 11, 16, 18, 65, 95, 120), -(17, 9, 19, 500, 20, 60, 0, 0, 7, 11, 9, 11, 16, 18, 68, 98, 123), -(18, 9, 19, 525, 20, 70, 0, 0, 7, 11, 9, 11, 16, 18, 71, 101, 126), -(19, 9, 19, 550, 20, 80, 0, 0, 7, 11, 9, 11, 16, 18, 74, 104, 129), -(20, 9, 19, 575, 20, 90, 0, 0, 7, 11, 9, 11, 16, 18, 77, 107, 132), -(21, 9, 19, 600, 20, 100, 0, 0, 9, 13, 11, 13, 20, 22, 80, 110, 135), -(22, 9, 19, 625, 20, 110, 0, 0, 9, 13, 11, 13, 20, 22, 83, 113, 138), -(23, 9, 19, 650, 20, 120, 0, 0, 9, 13, 11, 13, 20, 22, 86, 116, 141), -(24, 9, 19, 675, 20, 130, 0, 0, 9, 13, 11, 13, 20, 22, 89, 119, 144), -(25, 9, 19, 700, 20, 140, 0, 0, 9, 13, 11, 13, 20, 22, 92, 122, 147), -(26, 9, 19, 725, 20, 150, 0, 0, 11, 15, 13, 15, 24, 26, 95, 125, 150), -(27, 9, 19, 750, 20, 160, 0, 0, 11, 15, 13, 15, 24, 26, 98, 128, 153), -(28, 9, 19, 775, 20, 170, 0, 0, 11, 15, 13, 15, 24, 26, 101, 131, 156), -(29, 9, 19, 800, 20, 180, 0, 0, 11, 15, 13, 15, 24, 26, 104, 134, 159), -(30, 9, 19, 700, 20, 190, 20, 3, 11, 15, 13, 15, 24, 26, 107, 137, 162), -(31, 9, 19, 718, 20, 200, 20, 6, 13, 17, 15, 17, 28, 30, 110, 140, 165), -(32, 9, 19, 736, 20, 210, 20, 9, 13, 17, 15, 17, 28, 30, 113, 143, 168), -(33, 9, 19, 754, 20, 220, 20, 12, 13, 17, 15, 17, 28, 30, 116, 146, 171), -(34, 9, 19, 772, 20, 230, 20, 15, 13, 17, 15, 17, 28, 30, 119, 149, 174), -(35, 9, 19, 790, 20, 240, 20, 18, 13, 17, 15, 17, 28, 30, 122, 152, 177), -(36, 9, 19, 808, 20, 250, 20, 21, 15, 19, 17, 19, 32, 34, 125, 155, 180), -(37, 9, 19, 826, 20, 260, 20, 24, 15, 19, 17, 19, 32, 34, 128, 158, 183), -(38, 9, 19, 844, 20, 270, 20, 27, 15, 19, 17, 19, 32, 34, 131, 161, 186), -(39, 9, 19, 862, 20, 280, 20, 30, 15, 19, 17, 19, 32, 34, 134, 164, 189), -(40, 9, 19, 880, 20, 290, 20, 33, 15, 19, 17, 19, 32, 34, 137, 167, 192), -(41, 9, 19, 898, 20, 300, 20, 36, 17, 21, 19, 21, 36, 38, 140, 170, 195), -(42, 9, 19, 916, 20, 310, 20, 39, 17, 21, 19, 21, 36, 38, 143, 173, 198), -(43, 9, 19, 934, 20, 320, 20, 42, 17, 21, 19, 21, 36, 38, 146, 176, 201), -(44, 9, 19, 952, 20, 330, 20, 45, 17, 21, 19, 21, 36, 38, 149, 179, 204), -(45, 9, 19, 970, 20, 340, 20, 48, 17, 21, 19, 21, 36, 38, 152, 182, 207), -(46, 9, 19, 988, 20, 350, 20, 51, 19, 23, 21, 23, 40, 42, 155, 185, 210), -(47, 9, 19, 1006, 20, 360, 20, 54, 19, 23, 21, 23, 40, 42, 158, 188, 213), -(48, 9, 19, 1024, 20, 370, 20, 57, 19, 23, 21, 23, 40, 42, 161, 191, 216), -(49, 9, 19, 1042, 20, 380, 20, 60, 19, 23, 21, 23, 40, 42, 164, 194, 219), -(50, 9, 19, 1060, 20, 390, 20, 63, 19, 23, 21, 23, 40, 42, 167, 197, 222), -(1, 5, 11, 75, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 20, 50, 75), -(2, 5, 11, 110, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 23, 53, 78), -(3, 5, 11, 145, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 26, 56, 81), -(4, 5, 11, 180, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 29, 59, 84), -(5, 5, 11, 215, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 32, 62, 87), -(6, 5, 11, 250, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 35, 65, 90), -(7, 5, 11, 285, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 38, 68, 93), -(8, 5, 11, 320, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 41, 71, 96), -(9, 5, 11, 355, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 44, 74, 99), -(10, 5, 11, 390, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 47, 77, 102), -(11, 5, 11, 350, 12, 0, 0, 0, 5, 9, 7, 9, 12, 14, 50, 80, 105), -(12, 5, 11, 375, 12, 10, 0, 0, 5, 9, 7, 9, 12, 14, 53, 83, 108), -(13, 5, 11, 400, 12, 20, 0, 0, 5, 9, 7, 9, 12, 14, 56, 86, 111), -(14, 5, 11, 425, 12, 30, 0, 0, 5, 9, 7, 9, 12, 14, 59, 89, 114), -(15, 5, 11, 450, 12, 40, 0, 0, 5, 9, 7, 9, 12, 14, 62, 92, 117), -(16, 5, 11, 475, 12, 50, 0, 0, 7, 11, 9, 11, 16, 18, 65, 95, 120), -(17, 5, 11, 500, 12, 60, 0, 0, 7, 11, 9, 11, 16, 18, 68, 98, 123), -(18, 5, 11, 525, 12, 70, 0, 0, 7, 11, 9, 11, 16, 18, 71, 101, 126), -(19, 5, 11, 550, 12, 80, 0, 0, 7, 11, 9, 11, 16, 18, 74, 104, 129), -(20, 5, 11, 575, 12, 90, 0, 0, 7, 11, 9, 11, 16, 18, 77, 107, 132), -(21, 5, 11, 600, 12, 100, 0, 0, 9, 13, 11, 13, 20, 22, 80, 110, 135), -(22, 5, 11, 625, 12, 110, 0, 0, 9, 13, 11, 13, 20, 22, 83, 113, 138), -(23, 5, 11, 650, 12, 120, 0, 0, 9, 13, 11, 13, 20, 22, 86, 116, 141), -(24, 5, 11, 675, 12, 130, 0, 0, 9, 13, 11, 13, 20, 22, 89, 119, 144), -(25, 5, 11, 700, 12, 140, 0, 0, 9, 13, 11, 13, 20, 22, 92, 122, 147), -(26, 5, 11, 725, 12, 150, 0, 0, 11, 15, 13, 15, 24, 26, 95, 125, 150), -(27, 5, 11, 750, 12, 160, 0, 0, 11, 15, 13, 15, 24, 26, 98, 128, 153), -(28, 5, 11, 775, 12, 170, 0, 0, 11, 15, 13, 15, 24, 26, 101, 131, 156), -(29, 5, 11, 800, 12, 180, 0, 0, 11, 15, 13, 15, 24, 26, 104, 134, 159), -(30, 5, 11, 700, 12, 190, 20, 3, 11, 15, 13, 15, 24, 26, 107, 137, 162), -(31, 5, 11, 718, 12, 200, 20, 6, 13, 17, 15, 17, 28, 30, 110, 140, 165), -(32, 5, 11, 736, 12, 210, 20, 9, 13, 17, 15, 17, 28, 30, 113, 143, 168), -(33, 5, 11, 754, 12, 220, 20, 12, 13, 17, 15, 17, 28, 30, 116, 146, 171), -(34, 5, 11, 772, 12, 230, 20, 15, 13, 17, 15, 17, 28, 30, 119, 149, 174), -(35, 5, 11, 790, 12, 240, 20, 18, 13, 17, 15, 17, 28, 30, 122, 152, 177), -(36, 5, 11, 808, 12, 250, 20, 21, 15, 19, 17, 19, 32, 34, 125, 155, 180), -(37, 5, 11, 826, 12, 260, 20, 24, 15, 19, 17, 19, 32, 34, 128, 158, 183), -(38, 5, 11, 844, 12, 270, 20, 27, 15, 19, 17, 19, 32, 34, 131, 161, 186), -(39, 5, 11, 862, 12, 280, 20, 30, 15, 19, 17, 19, 32, 34, 134, 164, 189), -(40, 5, 11, 880, 12, 290, 20, 33, 15, 19, 17, 19, 32, 34, 137, 167, 192), -(41, 5, 11, 898, 12, 300, 20, 36, 17, 21, 19, 21, 36, 38, 140, 170, 195), -(42, 5, 11, 916, 12, 310, 20, 39, 17, 21, 19, 21, 36, 38, 143, 173, 198), -(43, 5, 11, 934, 12, 320, 20, 42, 17, 21, 19, 21, 36, 38, 146, 176, 201), -(44, 5, 11, 952, 12, 330, 20, 45, 17, 21, 19, 21, 36, 38, 149, 179, 204), -(45, 5, 11, 970, 12, 340, 20, 48, 17, 21, 19, 21, 36, 38, 152, 182, 207), -(46, 5, 11, 988, 12, 350, 20, 51, 19, 23, 21, 23, 40, 42, 155, 185, 210), -(47, 5, 11, 1006, 12, 360, 20, 54, 19, 23, 21, 23, 40, 42, 158, 188, 213), -(48, 5, 11, 1024, 12, 370, 20, 57, 19, 23, 21, 23, 40, 42, 161, 191, 216), -(49, 5, 11, 1042, 12, 380, 20, 60, 19, 23, 21, 23, 40, 42, 164, 194, 219), -(50, 5, 11, 1060, 12, 390, 20, 63, 19, 23, 21, 23, 40, 42, 167, 197, 222), -(1, 6, 13, 75, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 20, 50, 75), -(2, 6, 13, 110, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 23, 53, 78), -(3, 6, 13, 145, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 26, 56, 81), -(4, 6, 13, 180, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 29, 59, 84), -(5, 6, 13, 215, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 32, 62, 87), -(6, 6, 13, 250, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 35, 65, 90), -(7, 6, 13, 285, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 38, 68, 93), -(8, 6, 13, 320, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 41, 71, 96), -(9, 6, 13, 355, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 44, 74, 99), -(10, 6, 13, 390, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 47, 77, 102), -(11, 6, 13, 350, 14, 0, 0, 0, 5, 9, 7, 9, 12, 14, 50, 80, 105), -(12, 6, 13, 375, 14, 10, 0, 0, 5, 9, 7, 9, 12, 14, 53, 83, 108), -(13, 6, 13, 400, 14, 20, 0, 0, 5, 9, 7, 9, 12, 14, 56, 86, 111), -(14, 6, 13, 425, 14, 30, 0, 0, 5, 9, 7, 9, 12, 14, 59, 89, 114), -(15, 6, 13, 450, 14, 40, 0, 0, 5, 9, 7, 9, 12, 14, 62, 92, 117), -(16, 6, 13, 475, 14, 50, 0, 0, 7, 11, 9, 11, 16, 18, 65, 95, 120), -(17, 6, 13, 500, 14, 60, 0, 0, 7, 11, 9, 11, 16, 18, 68, 98, 123), -(18, 6, 13, 525, 14, 70, 0, 0, 7, 11, 9, 11, 16, 18, 71, 101, 126), -(19, 6, 13, 550, 14, 80, 0, 0, 7, 11, 9, 11, 16, 18, 74, 104, 129), -(20, 6, 13, 575, 14, 90, 0, 0, 7, 11, 9, 11, 16, 18, 77, 107, 132), -(21, 6, 13, 600, 14, 100, 0, 0, 9, 13, 11, 13, 20, 22, 80, 110, 135), -(22, 6, 13, 625, 14, 110, 0, 0, 9, 13, 11, 13, 20, 22, 83, 113, 138), -(23, 6, 13, 650, 14, 120, 0, 0, 9, 13, 11, 13, 20, 22, 86, 116, 141), -(24, 6, 13, 675, 14, 130, 0, 0, 9, 13, 11, 13, 20, 22, 89, 119, 144), -(25, 6, 13, 700, 14, 140, 0, 0, 9, 13, 11, 13, 20, 22, 92, 122, 147), -(26, 6, 13, 725, 14, 150, 0, 0, 11, 15, 13, 15, 24, 26, 95, 125, 150), -(27, 6, 13, 750, 14, 160, 0, 0, 11, 15, 13, 15, 24, 26, 98, 128, 153), -(28, 6, 13, 775, 14, 170, 0, 0, 11, 15, 13, 15, 24, 26, 101, 131, 156), -(29, 6, 13, 800, 14, 180, 0, 0, 11, 15, 13, 15, 24, 26, 104, 134, 159), -(30, 6, 13, 700, 14, 190, 20, 3, 11, 15, 13, 15, 24, 26, 107, 137, 162), -(31, 6, 13, 718, 14, 200, 20, 6, 13, 17, 15, 17, 28, 30, 110, 140, 165), -(32, 6, 13, 736, 14, 210, 20, 9, 13, 17, 15, 17, 28, 30, 113, 143, 168), -(33, 6, 13, 754, 14, 220, 20, 12, 13, 17, 15, 17, 28, 30, 116, 146, 171), -(34, 6, 13, 772, 14, 230, 20, 15, 13, 17, 15, 17, 28, 30, 119, 149, 174), -(35, 6, 13, 790, 14, 240, 20, 18, 13, 17, 15, 17, 28, 30, 122, 152, 177), -(36, 6, 13, 808, 14, 250, 20, 21, 15, 19, 17, 19, 32, 34, 125, 155, 180), -(37, 6, 13, 826, 14, 260, 20, 24, 15, 19, 17, 19, 32, 34, 128, 158, 183), -(38, 6, 13, 844, 14, 270, 20, 27, 15, 19, 17, 19, 32, 34, 131, 161, 186), -(39, 6, 13, 862, 14, 280, 20, 30, 15, 19, 17, 19, 32, 34, 134, 164, 189), -(40, 6, 13, 880, 14, 290, 20, 33, 15, 19, 17, 19, 32, 34, 137, 167, 192), -(41, 6, 13, 898, 14, 300, 20, 36, 17, 21, 19, 21, 36, 38, 140, 170, 195), -(42, 6, 13, 916, 14, 310, 20, 39, 17, 21, 19, 21, 36, 38, 143, 173, 198), -(43, 6, 13, 934, 14, 320, 20, 42, 17, 21, 19, 21, 36, 38, 146, 176, 201), -(44, 6, 13, 952, 14, 330, 20, 45, 17, 21, 19, 21, 36, 38, 149, 179, 204), -(45, 6, 13, 970, 14, 340, 20, 48, 17, 21, 19, 21, 36, 38, 152, 182, 207), -(46, 6, 13, 988, 14, 350, 20, 51, 19, 23, 21, 23, 40, 42, 155, 185, 210), -(47, 6, 13, 1006, 14, 360, 20, 54, 19, 23, 21, 23, 40, 42, 158, 188, 213), -(48, 6, 13, 1024, 14, 370, 20, 57, 19, 23, 21, 23, 40, 42, 161, 191, 216), -(49, 6, 13, 1042, 14, 380, 20, 60, 19, 23, 21, 23, 40, 42, 164, 194, 219), -(50, 6, 13, 1060, 14, 390, 20, 63, 19, 23, 21, 23, 40, 42, 167, 197, 222); +INSERT INTO mp_upgrade_ranks (upgradeRank, advancementId, itemEntry1, itemCost1, itemEntry2, itemCost2, itemEntry3, itemCost3, minIncrease1, maxIncrease1, minIncrease2, maxIncrease2, minIncrease3, maxIncrease3, chanceCost1, chanceCost2, chanceCost3) VALUES +(1, 0, 911005, 5, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 20, 50, 75), +(2, 0, 911005, 8, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 23, 53, 78), +(3, 0, 911005, 10, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 26, 56, 81), +(4, 0, 911005, 13, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 29, 59, 84), +(5, 0, 911005, 15, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 32, 62, 87), +(6, 0, 911005, 18, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 35, 65, 90), +(7, 0, 911005, 20, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 38, 68, 93), +(8, 0, 911005, 23, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 41, 71, 96), +(9, 0, 911005, 25, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 44, 74, 99), +(10, 0, 911005, 28, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 47, 77, 102), +(11, 0, 911005, 25, 911006, 0, 0, 0, 3, 12, 7, 12, 12, 15, 50, 80, 105), +(12, 0, 911005, 27, 911006, 2, 0, 0, 3, 12, 7, 12, 12, 15, 53, 83, 108), +(13, 0, 911005, 28, 911006, 4, 0, 0, 3, 12, 7, 12, 12, 15, 56, 86, 111), +(14, 0, 911005, 29, 911006, 6, 0, 0, 3, 12, 7, 12, 12, 15, 59, 89, 114), +(15, 0, 911005, 30, 911006, 8, 0, 0, 3, 12, 7, 12, 12, 15, 62, 92, 117), +(16, 0, 911005, 32, 911006, 10, 0, 0, 3, 12, 7, 12, 12, 15, 65, 95, 120), +(17, 0, 911005, 33, 911006, 12, 0, 0, 3, 12, 7, 12, 12, 15, 68, 98, 123), +(18, 0, 911005, 34, 911006, 14, 0, 0, 3, 12, 7, 12, 12, 15, 71, 101, 126), +(19, 0, 911005, 35, 911006, 16, 0, 0, 3, 12, 7, 12, 12, 15, 74, 104, 129), +(20, 0, 911005, 37, 911006, 18, 0, 0, 3, 12, 7, 12, 12, 15, 77, 107, 132), +(21, 0, 911005, 38, 911006, 20, 0, 0, 5, 14, 9, 14, 16, 19, 80, 110, 135), +(22, 0, 911005, 39, 911006, 22, 0, 0, 5, 14, 9, 14, 16, 19, 83, 113, 138), +(23, 0, 911005, 40, 911006, 24, 0, 0, 5, 14, 9, 14, 16, 19, 86, 116, 141), +(24, 0, 911005, 42, 911006, 26, 0, 0, 5, 14, 9, 14, 16, 19, 89, 119, 144), +(25, 0, 911005, 43, 911006, 28, 0, 0, 5, 14, 9, 14, 16, 19, 92, 122, 147), +(26, 0, 911005, 44, 911006, 30, 0, 0, 5, 14, 9, 14, 16, 19, 95, 125, 150), +(27, 0, 911005, 45, 911006, 32, 0, 0, 5, 14, 9, 14, 16, 19, 98, 128, 153), +(28, 0, 911005, 47, 911006, 34, 0, 0, 5, 14, 9, 14, 16, 19, 101, 131, 156), +(29, 0, 911005, 48, 911006, 36, 0, 0, 5, 14, 9, 14, 16, 19, 104, 134, 159), +(30, 0, 911005, 50, 911006, 38, 911002, 3, 5, 14, 9, 14, 16, 19, 107, 137, 162), +(31, 0, 911005, 51, 911006, 40, 911002, 6, 7, 16, 11, 16, 20, 23, 110, 140, 165), +(32, 0, 911005, 52, 911006, 42, 911002, 9, 7, 16, 11, 16, 20, 23, 113, 143, 168), +(33, 0, 911005, 53, 911006, 44, 911002, 12, 7, 16, 11, 16, 20, 23, 116, 146, 171), +(34, 0, 911005, 54, 911006, 46, 911002, 15, 7, 16, 11, 16, 20, 23, 119, 149, 174), +(35, 0, 911005, 55, 911006, 48, 911002, 15, 7, 16, 11, 16, 20, 23, 122, 152, 177), +(36, 0, 911005, 56, 911006, 50, 911002, 15, 7, 16, 11, 16, 20, 23, 125, 155, 180), +(37, 0, 911005, 57, 911006, 52, 911002, 15, 7, 16, 11, 16, 20, 23, 128, 158, 183), +(38, 0, 911005, 58, 911006, 54, 911002, 15, 7, 16, 11, 16, 20, 23, 131, 161, 186), +(39, 0, 911005, 59, 911006, 56, 911002, 15, 7, 16, 11, 16, 20, 23, 134, 164, 189), +(40, 0, 911005, 59, 911006, 58, 911002, 15, 7, 16, 11, 16, 20, 23, 137, 167, 192), +(41, 0, 911005, 60, 911006, 60, 911002, 15, 9, 18, 13, 18, 24, 27, 140, 170, 195), +(42, 0, 911005, 61, 911006, 62, 911002, 15, 9, 18, 13, 18, 24, 27, 143, 173, 198), +(43, 0, 911005, 62, 911006, 64, 911002, 15, 9, 18, 13, 18, 24, 27, 146, 176, 201), +(44, 0, 911005, 63, 911006, 66, 911002, 15, 9, 18, 13, 18, 24, 27, 149, 179, 204), +(45, 0, 911005, 64, 911006, 68, 911002, 15, 9, 18, 13, 18, 24, 27, 152, 182, 207), +(46, 0, 911005, 65, 911006, 70, 911002, 15, 9, 18, 13, 18, 24, 27, 155, 185, 210), +(47, 0, 911005, 66, 911006, 72, 911002, 15, 9, 18, 13, 18, 24, 27, 158, 188, 213), +(48, 0, 911005, 67, 911006, 74, 911002, 15, 9, 18, 13, 18, 24, 27, 161, 191, 216), +(49, 0, 911005, 68, 911006, 76, 911002, 15, 9, 18, 13, 18, 24, 27, 164, 194, 219), +(50, 0, 911005, 68, 911006, 78, 911002, 15, 9, 18, 13, 18, 24, 27, 167, 197, 222), +(1, 1, 911009, 5, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 20, 50, 75), +(2, 1, 911009, 8, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 23, 53, 78), +(3, 1, 911009, 10, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 26, 56, 81), +(4, 1, 911009, 13, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 29, 59, 84), +(5, 1, 911009, 15, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 32, 62, 87), +(6, 1, 911009, 18, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 35, 65, 90), +(7, 1, 911009, 20, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 38, 68, 93), +(8, 1, 911009, 23, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 41, 71, 96), +(9, 1, 911009, 25, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 44, 74, 99), +(10, 1, 911009, 28, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 47, 77, 102), +(11, 1, 911009, 25, 911010, 0, 0, 0, 3, 12, 7, 12, 12, 15, 50, 80, 105), +(12, 1, 911009, 27, 911010, 2, 0, 0, 3, 12, 7, 12, 12, 15, 53, 83, 108), +(13, 1, 911009, 28, 911010, 4, 0, 0, 3, 12, 7, 12, 12, 15, 56, 86, 111), +(14, 1, 911009, 29, 911010, 6, 0, 0, 3, 12, 7, 12, 12, 15, 59, 89, 114), +(15, 1, 911009, 30, 911010, 8, 0, 0, 3, 12, 7, 12, 12, 15, 62, 92, 117), +(16, 1, 911009, 32, 911010, 10, 0, 0, 3, 12, 7, 12, 12, 15, 65, 95, 120), +(17, 1, 911009, 33, 911010, 12, 0, 0, 3, 12, 7, 12, 12, 15, 68, 98, 123), +(18, 1, 911009, 34, 911010, 14, 0, 0, 3, 12, 7, 12, 12, 15, 71, 101, 126), +(19, 1, 911009, 35, 911010, 16, 0, 0, 3, 12, 7, 12, 12, 15, 74, 104, 129), +(20, 1, 911009, 37, 911010, 18, 0, 0, 3, 12, 7, 12, 12, 15, 77, 107, 132), +(21, 1, 911009, 38, 911010, 20, 0, 0, 5, 14, 9, 14, 16, 19, 80, 110, 135), +(22, 1, 911009, 39, 911010, 22, 0, 0, 5, 14, 9, 14, 16, 19, 83, 113, 138), +(23, 1, 911009, 40, 911010, 24, 0, 0, 5, 14, 9, 14, 16, 19, 86, 116, 141), +(24, 1, 911009, 42, 911010, 26, 0, 0, 5, 14, 9, 14, 16, 19, 89, 119, 144), +(25, 1, 911009, 43, 911010, 28, 0, 0, 5, 14, 9, 14, 16, 19, 92, 122, 147), +(26, 1, 911009, 44, 911010, 30, 0, 0, 5, 14, 9, 14, 16, 19, 95, 125, 150), +(27, 1, 911009, 45, 911010, 32, 0, 0, 5, 14, 9, 14, 16, 19, 98, 128, 153), +(28, 1, 911009, 47, 911010, 34, 0, 0, 5, 14, 9, 14, 16, 19, 101, 131, 156), +(29, 1, 911009, 48, 911010, 36, 0, 0, 5, 14, 9, 14, 16, 19, 104, 134, 159), +(30, 1, 911009, 50, 911010, 38, 911002, 3, 5, 14, 9, 14, 16, 19, 107, 137, 162), +(31, 1, 911009, 51, 911010, 40, 911002, 6, 7, 16, 11, 16, 20, 23, 110, 140, 165), +(32, 1, 911009, 52, 911010, 42, 911002, 9, 7, 16, 11, 16, 20, 23, 113, 143, 168), +(33, 1, 911009, 53, 911010, 44, 911002, 12, 7, 16, 11, 16, 20, 23, 116, 146, 171), +(34, 1, 911009, 54, 911010, 46, 911002, 15, 7, 16, 11, 16, 20, 23, 119, 149, 174), +(35, 1, 911009, 55, 911010, 48, 911002, 15, 7, 16, 11, 16, 20, 23, 122, 152, 177), +(36, 1, 911009, 56, 911010, 50, 911002, 15, 7, 16, 11, 16, 20, 23, 125, 155, 180), +(37, 1, 911009, 57, 911010, 52, 911002, 15, 7, 16, 11, 16, 20, 23, 128, 158, 183), +(38, 1, 911009, 58, 911010, 54, 911002, 15, 7, 16, 11, 16, 20, 23, 131, 161, 186), +(39, 1, 911009, 59, 911010, 56, 911002, 15, 7, 16, 11, 16, 20, 23, 134, 164, 189), +(40, 1, 911009, 59, 911010, 58, 911002, 15, 7, 16, 11, 16, 20, 23, 137, 167, 192), +(41, 1, 911009, 60, 911010, 60, 911002, 15, 9, 18, 13, 18, 24, 27, 140, 170, 195), +(42, 1, 911009, 61, 911010, 62, 911002, 15, 9, 18, 13, 18, 24, 27, 143, 173, 198), +(43, 1, 911009, 62, 911010, 64, 911002, 15, 9, 18, 13, 18, 24, 27, 146, 176, 201), +(44, 1, 911009, 63, 911010, 66, 911002, 15, 9, 18, 13, 18, 24, 27, 149, 179, 204), +(45, 1, 911009, 64, 911010, 68, 911002, 15, 9, 18, 13, 18, 24, 27, 152, 182, 207), +(46, 1, 911009, 65, 911010, 70, 911002, 15, 9, 18, 13, 18, 24, 27, 155, 185, 210), +(47, 1, 911009, 66, 911010, 72, 911002, 15, 9, 18, 13, 18, 24, 27, 158, 188, 213), +(48, 1, 911009, 67, 911010, 74, 911002, 15, 9, 18, 13, 18, 24, 27, 161, 191, 216), +(49, 1, 911009, 68, 911010, 76, 911002, 15, 9, 18, 13, 18, 24, 27, 164, 194, 219), +(50, 1, 911009, 68, 911010, 78, 911002, 15, 9, 18, 13, 18, 24, 27, 167, 197, 222), +(1, 2, 911003, 5, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 20, 50, 75), +(2, 2, 911003, 8, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 23, 53, 78), +(3, 2, 911003, 10, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 26, 56, 81), +(4, 2, 911003, 13, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 29, 59, 84), +(5, 2, 911003, 15, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 32, 62, 87), +(6, 2, 911003, 18, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 35, 65, 90), +(7, 2, 911003, 20, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 38, 68, 93), +(8, 2, 911003, 23, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 41, 71, 96), +(9, 2, 911003, 25, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 44, 74, 99), +(10, 2, 911003, 28, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 47, 77, 102), +(11, 2, 911003, 25, 911004, 0, 0, 0, 3, 12, 7, 12, 12, 15, 50, 80, 105), +(12, 2, 911003, 27, 911004, 2, 0, 0, 3, 12, 7, 12, 12, 15, 53, 83, 108), +(13, 2, 911003, 28, 911004, 4, 0, 0, 3, 12, 7, 12, 12, 15, 56, 86, 111), +(14, 2, 911003, 29, 911004, 6, 0, 0, 3, 12, 7, 12, 12, 15, 59, 89, 114), +(15, 2, 911003, 30, 911004, 8, 0, 0, 3, 12, 7, 12, 12, 15, 62, 92, 117), +(16, 2, 911003, 32, 911004, 10, 0, 0, 3, 12, 7, 12, 12, 15, 65, 95, 120), +(17, 2, 911003, 33, 911004, 12, 0, 0, 3, 12, 7, 12, 12, 15, 68, 98, 123), +(18, 2, 911003, 34, 911004, 14, 0, 0, 3, 12, 7, 12, 12, 15, 71, 101, 126), +(19, 2, 911003, 35, 911004, 16, 0, 0, 3, 12, 7, 12, 12, 15, 74, 104, 129), +(20, 2, 911003, 37, 911004, 18, 0, 0, 3, 12, 7, 12, 12, 15, 77, 107, 132), +(21, 2, 911003, 38, 911004, 20, 0, 0, 5, 14, 9, 14, 16, 19, 80, 110, 135), +(22, 2, 911003, 39, 911004, 22, 0, 0, 5, 14, 9, 14, 16, 19, 83, 113, 138), +(23, 2, 911003, 40, 911004, 24, 0, 0, 5, 14, 9, 14, 16, 19, 86, 116, 141), +(24, 2, 911003, 42, 911004, 26, 0, 0, 5, 14, 9, 14, 16, 19, 89, 119, 144), +(25, 2, 911003, 43, 911004, 28, 0, 0, 5, 14, 9, 14, 16, 19, 92, 122, 147), +(26, 2, 911003, 44, 911004, 30, 0, 0, 5, 14, 9, 14, 16, 19, 95, 125, 150), +(27, 2, 911003, 45, 911004, 32, 0, 0, 5, 14, 9, 14, 16, 19, 98, 128, 153), +(28, 2, 911003, 47, 911004, 34, 0, 0, 5, 14, 9, 14, 16, 19, 101, 131, 156), +(29, 2, 911003, 48, 911004, 36, 0, 0, 5, 14, 9, 14, 16, 19, 104, 134, 159), +(30, 2, 911003, 50, 911004, 38, 911002, 3, 5, 14, 9, 14, 16, 19, 107, 137, 162), +(31, 2, 911003, 51, 911004, 40, 911002, 6, 7, 16, 11, 16, 20, 23, 110, 140, 165), +(32, 2, 911003, 52, 911004, 42, 911002, 9, 7, 16, 11, 16, 20, 23, 113, 143, 168), +(33, 2, 911003, 53, 911004, 44, 911002, 12, 7, 16, 11, 16, 20, 23, 116, 146, 171), +(34, 2, 911003, 54, 911004, 46, 911002, 15, 7, 16, 11, 16, 20, 23, 119, 149, 174), +(35, 2, 911003, 55, 911004, 48, 911002, 15, 7, 16, 11, 16, 20, 23, 122, 152, 177), +(36, 2, 911003, 56, 911004, 50, 911002, 15, 7, 16, 11, 16, 20, 23, 125, 155, 180), +(37, 2, 911003, 57, 911004, 52, 911002, 15, 7, 16, 11, 16, 20, 23, 128, 158, 183), +(38, 2, 911003, 58, 911004, 54, 911002, 15, 7, 16, 11, 16, 20, 23, 131, 161, 186), +(39, 2, 911003, 59, 911004, 56, 911002, 15, 7, 16, 11, 16, 20, 23, 134, 164, 189), +(40, 2, 911003, 59, 911004, 58, 911002, 15, 7, 16, 11, 16, 20, 23, 137, 167, 192), +(41, 2, 911003, 60, 911004, 60, 911002, 15, 9, 18, 13, 18, 24, 27, 140, 170, 195), +(42, 2, 911003, 61, 911004, 62, 911002, 15, 9, 18, 13, 18, 24, 27, 143, 173, 198), +(43, 2, 911003, 62, 911004, 64, 911002, 15, 9, 18, 13, 18, 24, 27, 146, 176, 201), +(44, 2, 911003, 63, 911004, 66, 911002, 15, 9, 18, 13, 18, 24, 27, 149, 179, 204), +(45, 2, 911003, 64, 911004, 68, 911002, 15, 9, 18, 13, 18, 24, 27, 152, 182, 207), +(46, 2, 911003, 65, 911004, 70, 911002, 15, 9, 18, 13, 18, 24, 27, 155, 185, 210), +(47, 2, 911003, 66, 911004, 72, 911002, 15, 9, 18, 13, 18, 24, 27, 158, 188, 213), +(48, 2, 911003, 67, 911004, 74, 911002, 15, 9, 18, 13, 18, 24, 27, 161, 191, 216), +(49, 2, 911003, 68, 911004, 76, 911002, 15, 9, 18, 13, 18, 24, 27, 164, 194, 219), +(50, 2, 911003, 68, 911004, 78, 911002, 15, 9, 18, 13, 18, 24, 27, 167, 197, 222), +(1, 3, 911007, 5, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 20, 50, 75), +(2, 3, 911007, 8, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 23, 53, 78), +(3, 3, 911007, 10, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 26, 56, 81), +(4, 3, 911007, 13, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 29, 59, 84), +(5, 3, 911007, 15, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 32, 62, 87), +(6, 3, 911007, 18, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 35, 65, 90), +(7, 3, 911007, 20, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 38, 68, 93), +(8, 3, 911007, 23, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 41, 71, 96), +(9, 3, 911007, 25, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 44, 74, 99), +(10, 3, 911007, 28, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 47, 77, 102), +(11, 3, 911007, 25, 911008, 0, 0, 0, 3, 12, 7, 12, 12, 15, 50, 80, 105), +(12, 3, 911007, 27, 911008, 2, 0, 0, 3, 12, 7, 12, 12, 15, 53, 83, 108), +(13, 3, 911007, 28, 911008, 4, 0, 0, 3, 12, 7, 12, 12, 15, 56, 86, 111), +(14, 3, 911007, 29, 911008, 6, 0, 0, 3, 12, 7, 12, 12, 15, 59, 89, 114), +(15, 3, 911007, 30, 911008, 8, 0, 0, 3, 12, 7, 12, 12, 15, 62, 92, 117), +(16, 3, 911007, 32, 911008, 10, 0, 0, 3, 12, 7, 12, 12, 15, 65, 95, 120), +(17, 3, 911007, 33, 911008, 12, 0, 0, 3, 12, 7, 12, 12, 15, 68, 98, 123), +(18, 3, 911007, 34, 911008, 14, 0, 0, 3, 12, 7, 12, 12, 15, 71, 101, 126), +(19, 3, 911007, 35, 911008, 16, 0, 0, 3, 12, 7, 12, 12, 15, 74, 104, 129), +(20, 3, 911007, 37, 911008, 18, 0, 0, 3, 12, 7, 12, 12, 15, 77, 107, 132), +(21, 3, 911007, 38, 911008, 20, 0, 0, 5, 14, 9, 14, 16, 19, 80, 110, 135), +(22, 3, 911007, 39, 911008, 22, 0, 0, 5, 14, 9, 14, 16, 19, 83, 113, 138), +(23, 3, 911007, 40, 911008, 24, 0, 0, 5, 14, 9, 14, 16, 19, 86, 116, 141), +(24, 3, 911007, 42, 911008, 26, 0, 0, 5, 14, 9, 14, 16, 19, 89, 119, 144), +(25, 3, 911007, 43, 911008, 28, 0, 0, 5, 14, 9, 14, 16, 19, 92, 122, 147), +(26, 3, 911007, 44, 911008, 30, 0, 0, 5, 14, 9, 14, 16, 19, 95, 125, 150), +(27, 3, 911007, 45, 911008, 32, 0, 0, 5, 14, 9, 14, 16, 19, 98, 128, 153), +(28, 3, 911007, 47, 911008, 34, 0, 0, 5, 14, 9, 14, 16, 19, 101, 131, 156), +(29, 3, 911007, 48, 911008, 36, 0, 0, 5, 14, 9, 14, 16, 19, 104, 134, 159), +(30, 3, 911007, 50, 911008, 38, 911002, 3, 5, 14, 9, 14, 16, 19, 107, 137, 162), +(31, 3, 911007, 51, 911008, 40, 911002, 6, 7, 16, 11, 16, 20, 23, 110, 140, 165), +(32, 3, 911007, 52, 911008, 42, 911002, 9, 7, 16, 11, 16, 20, 23, 113, 143, 168), +(33, 3, 911007, 53, 911008, 44, 911002, 12, 7, 16, 11, 16, 20, 23, 116, 146, 171), +(34, 3, 911007, 54, 911008, 46, 911002, 15, 7, 16, 11, 16, 20, 23, 119, 149, 174), +(35, 3, 911007, 55, 911008, 48, 911002, 15, 7, 16, 11, 16, 20, 23, 122, 152, 177), +(36, 3, 911007, 56, 911008, 50, 911002, 15, 7, 16, 11, 16, 20, 23, 125, 155, 180), +(37, 3, 911007, 57, 911008, 52, 911002, 15, 7, 16, 11, 16, 20, 23, 128, 158, 183), +(38, 3, 911007, 58, 911008, 54, 911002, 15, 7, 16, 11, 16, 20, 23, 131, 161, 186), +(39, 3, 911007, 59, 911008, 56, 911002, 15, 7, 16, 11, 16, 20, 23, 134, 164, 189), +(40, 3, 911007, 59, 911008, 58, 911002, 15, 7, 16, 11, 16, 20, 23, 137, 167, 192), +(41, 3, 911007, 60, 911008, 60, 911002, 15, 9, 18, 13, 18, 24, 27, 140, 170, 195), +(42, 3, 911007, 61, 911008, 62, 911002, 15, 9, 18, 13, 18, 24, 27, 143, 173, 198), +(43, 3, 911007, 62, 911008, 64, 911002, 15, 9, 18, 13, 18, 24, 27, 146, 176, 201), +(44, 3, 911007, 63, 911008, 66, 911002, 15, 9, 18, 13, 18, 24, 27, 149, 179, 204), +(45, 3, 911007, 64, 911008, 68, 911002, 15, 9, 18, 13, 18, 24, 27, 152, 182, 207), +(46, 3, 911007, 65, 911008, 70, 911002, 15, 9, 18, 13, 18, 24, 27, 155, 185, 210), +(47, 3, 911007, 66, 911008, 72, 911002, 15, 9, 18, 13, 18, 24, 27, 158, 188, 213), +(48, 3, 911007, 67, 911008, 74, 911002, 15, 9, 18, 13, 18, 24, 27, 161, 191, 216), +(49, 3, 911007, 68, 911008, 76, 911002, 15, 9, 18, 13, 18, 24, 27, 164, 194, 219), +(50, 3, 911007, 68, 911008, 78, 911002, 15, 9, 18, 13, 18, 24, 27, 167, 197, 222), +(1, 4, 911011, 5, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 20, 50, 75), +(2, 4, 911011, 8, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 23, 53, 78), +(3, 4, 911011, 10, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 26, 56, 81), +(4, 4, 911011, 13, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 29, 59, 84), +(5, 4, 911011, 15, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 32, 62, 87), +(6, 4, 911011, 18, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 35, 65, 90), +(7, 4, 911011, 20, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 38, 68, 93), +(8, 4, 911011, 23, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 41, 71, 96), +(9, 4, 911011, 25, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 44, 74, 99), +(10, 4, 911011, 28, 0, 0, 0, 0, 1, 10, 5, 10, 8, 11, 47, 77, 102), +(11, 4, 911011, 25, 911012, 0, 0, 0, 3, 12, 7, 12, 12, 15, 50, 80, 105), +(12, 4, 911011, 27, 911012, 2, 0, 0, 3, 12, 7, 12, 12, 15, 53, 83, 108), +(13, 4, 911011, 28, 911012, 4, 0, 0, 3, 12, 7, 12, 12, 15, 56, 86, 111), +(14, 4, 911011, 29, 911012, 6, 0, 0, 3, 12, 7, 12, 12, 15, 59, 89, 114), +(15, 4, 911011, 30, 911012, 8, 0, 0, 3, 12, 7, 12, 12, 15, 62, 92, 117), +(16, 4, 911011, 32, 911012, 10, 0, 0, 3, 12, 7, 12, 12, 15, 65, 95, 120), +(17, 4, 911011, 33, 911012, 12, 0, 0, 3, 12, 7, 12, 12, 15, 68, 98, 123), +(18, 4, 911011, 34, 911012, 14, 0, 0, 3, 12, 7, 12, 12, 15, 71, 101, 126), +(19, 4, 911011, 35, 911012, 16, 0, 0, 3, 12, 7, 12, 12, 15, 74, 104, 129), +(20, 4, 911011, 37, 911012, 18, 0, 0, 3, 12, 7, 12, 12, 15, 77, 107, 132), +(21, 4, 911011, 38, 911012, 20, 0, 0, 5, 14, 9, 14, 16, 19, 80, 110, 135), +(22, 4, 911011, 39, 911012, 22, 0, 0, 5, 14, 9, 14, 16, 19, 83, 113, 138), +(23, 4, 911011, 40, 911012, 24, 0, 0, 5, 14, 9, 14, 16, 19, 86, 116, 141), +(24, 4, 911011, 42, 911012, 26, 0, 0, 5, 14, 9, 14, 16, 19, 89, 119, 144), +(25, 4, 911011, 43, 911012, 28, 0, 0, 5, 14, 9, 14, 16, 19, 92, 122, 147), +(26, 4, 911011, 44, 911012, 30, 0, 0, 5, 14, 9, 14, 16, 19, 95, 125, 150), +(27, 4, 911011, 45, 911012, 32, 0, 0, 5, 14, 9, 14, 16, 19, 98, 128, 153), +(28, 4, 911011, 47, 911012, 34, 0, 0, 5, 14, 9, 14, 16, 19, 101, 131, 156), +(29, 4, 911011, 48, 911012, 36, 0, 0, 5, 14, 9, 14, 16, 19, 104, 134, 159), +(30, 4, 911011, 50, 911012, 38, 911002, 3, 5, 14, 9, 14, 16, 19, 107, 137, 162), +(31, 4, 911011, 51, 911012, 40, 911002, 6, 7, 16, 11, 16, 20, 23, 110, 140, 165), +(32, 4, 911011, 52, 911012, 42, 911002, 9, 7, 16, 11, 16, 20, 23, 113, 143, 168), +(33, 4, 911011, 53, 911012, 44, 911002, 12, 7, 16, 11, 16, 20, 23, 116, 146, 171), +(34, 4, 911011, 54, 911012, 46, 911002, 15, 7, 16, 11, 16, 20, 23, 119, 149, 174), +(35, 4, 911011, 55, 911012, 48, 911002, 15, 7, 16, 11, 16, 20, 23, 122, 152, 177), +(36, 4, 911011, 56, 911012, 50, 911002, 15, 7, 16, 11, 16, 20, 23, 125, 155, 180), +(37, 4, 911011, 57, 911012, 52, 911002, 15, 7, 16, 11, 16, 20, 23, 128, 158, 183), +(38, 4, 911011, 58, 911012, 54, 911002, 15, 7, 16, 11, 16, 20, 23, 131, 161, 186), +(39, 4, 911011, 59, 911012, 56, 911002, 15, 7, 16, 11, 16, 20, 23, 134, 164, 189), +(40, 4, 911011, 59, 911012, 58, 911002, 15, 7, 16, 11, 16, 20, 23, 137, 167, 192), +(41, 4, 911011, 60, 911012, 60, 911002, 15, 9, 18, 13, 18, 24, 27, 140, 170, 195), +(42, 4, 911011, 61, 911012, 62, 911002, 15, 9, 18, 13, 18, 24, 27, 143, 173, 198), +(43, 4, 911011, 62, 911012, 64, 911002, 15, 9, 18, 13, 18, 24, 27, 146, 176, 201), +(44, 4, 911011, 63, 911012, 66, 911002, 15, 9, 18, 13, 18, 24, 27, 149, 179, 204), +(45, 4, 911011, 64, 911012, 68, 911002, 15, 9, 18, 13, 18, 24, 27, 152, 182, 207), +(46, 4, 911011, 65, 911012, 70, 911002, 15, 9, 18, 13, 18, 24, 27, 155, 185, 210), +(47, 4, 911011, 66, 911012, 72, 911002, 15, 9, 18, 13, 18, 24, 27, 158, 188, 213), +(48, 4, 911011, 67, 911012, 74, 911002, 15, 9, 18, 13, 18, 24, 27, 161, 191, 216), +(49, 4, 911011, 68, 911012, 76, 911002, 15, 9, 18, 13, 18, 24, 27, 164, 194, 219), +(50, 4, 911011, 68, 911012, 78, 911002, 15, 9, 18, 13, 18, 24, 27, 167, 197, 222), +(1, 5, 911019, 4, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 20, 50, 75), +(2, 5, 911019, 6, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 23, 53, 78), +(3, 5, 911019, 8, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 26, 56, 81), +(4, 5, 911019, 9, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 29, 59, 84), +(5, 5, 911019, 11, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 32, 62, 87), +(6, 5, 911019, 13, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 35, 65, 90), +(7, 5, 911019, 15, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 38, 68, 93), +(8, 5, 911019, 16, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 41, 71, 96), +(9, 5, 911019, 18, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 44, 74, 99), +(10, 5, 911019, 20, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 47, 77, 102), +(11, 5, 911019, 18, 911020, 0, 0, 0, 5, 9, 7, 9, 12, 14, 50, 80, 105), +(12, 5, 911019, 19, 911020, 2, 0, 0, 5, 9, 7, 9, 12, 14, 53, 83, 108), +(13, 5, 911019, 20, 911020, 4, 0, 0, 5, 9, 7, 9, 12, 14, 56, 86, 111), +(14, 5, 911019, 22, 911020, 6, 0, 0, 5, 9, 7, 9, 12, 14, 59, 89, 114), +(15, 5, 911019, 23, 911020, 8, 0, 0, 5, 9, 7, 9, 12, 14, 62, 92, 117), +(16, 5, 911019, 24, 911020, 10, 0, 0, 7, 11, 9, 11, 16, 18, 65, 95, 120), +(17, 5, 911019, 25, 911020, 12, 0, 0, 7, 11, 9, 11, 16, 18, 68, 98, 123), +(18, 5, 911019, 27, 911020, 14, 0, 0, 7, 11, 9, 11, 16, 18, 71, 101, 126), +(19, 5, 911019, 28, 911020, 16, 0, 0, 7, 11, 9, 11, 16, 18, 74, 104, 129), +(20, 5, 911019, 29, 911020, 18, 0, 0, 7, 11, 9, 11, 16, 18, 77, 107, 132), +(21, 5, 911019, 30, 911020, 20, 0, 0, 9, 13, 11, 13, 20, 22, 80, 110, 135), +(22, 5, 911019, 32, 911020, 22, 0, 0, 9, 13, 11, 13, 20, 22, 83, 113, 138), +(23, 5, 911019, 33, 911020, 24, 0, 0, 9, 13, 11, 13, 20, 22, 86, 116, 141), +(24, 5, 911019, 34, 911020, 26, 0, 0, 9, 13, 11, 13, 20, 22, 89, 119, 144), +(25, 5, 911019, 35, 911020, 28, 0, 0, 9, 13, 11, 13, 20, 22, 92, 122, 147), +(26, 5, 911019, 37, 911020, 30, 0, 0, 11, 15, 13, 15, 24, 26, 95, 125, 150), +(27, 5, 911019, 38, 911020, 32, 0, 0, 11, 15, 13, 15, 24, 26, 98, 128, 153), +(28, 5, 911019, 39, 911020, 34, 0, 0, 11, 15, 13, 15, 24, 26, 101, 131, 156), +(29, 5, 911019, 40, 911020, 36, 0, 0, 11, 15, 13, 15, 24, 26, 104, 134, 159), +(30, 5, 911019, 35, 911020, 38, 911002, 3, 11, 15, 13, 15, 24, 26, 107, 137, 162), +(31, 5, 911019, 36, 911020, 40, 911002, 6, 13, 17, 15, 17, 28, 30, 110, 140, 165), +(32, 5, 911019, 37, 911020, 42, 911002, 9, 13, 17, 15, 17, 28, 30, 113, 143, 168), +(33, 5, 911019, 38, 911020, 44, 911002, 12, 13, 17, 15, 17, 28, 30, 116, 146, 171), +(34, 5, 911019, 39, 911020, 46, 911002, 15, 13, 17, 15, 17, 28, 30, 119, 149, 174), +(35, 5, 911019, 40, 911020, 48, 911002, 18, 13, 17, 15, 17, 28, 30, 122, 152, 177), +(36, 5, 911019, 41, 911020, 50, 911002, 21, 15, 19, 17, 19, 32, 34, 125, 155, 180), +(37, 5, 911019, 42, 911020, 52, 911002, 24, 15, 19, 17, 19, 32, 34, 128, 158, 183), +(38, 5, 911019, 43, 911020, 54, 911002, 27, 15, 19, 17, 19, 32, 34, 131, 161, 186), +(39, 5, 911019, 44, 911020, 56, 911002, 30, 15, 19, 17, 19, 32, 34, 134, 164, 189), +(40, 5, 911019, 44, 911020, 58, 911002, 33, 15, 19, 17, 19, 32, 34, 137, 167, 192), +(41, 5, 911019, 45, 911020, 60, 911002, 36, 17, 21, 19, 21, 36, 38, 140, 170, 195), +(42, 5, 911019, 46, 911020, 62, 911002, 39, 17, 21, 19, 21, 36, 38, 143, 173, 198), +(43, 5, 911019, 47, 911020, 64, 911002, 42, 17, 21, 19, 21, 36, 38, 146, 176, 201), +(44, 5, 911019, 48, 911020, 66, 911002, 45, 17, 21, 19, 21, 36, 38, 149, 179, 204), +(45, 5, 911019, 49, 911020, 68, 911002, 48, 17, 21, 19, 21, 36, 38, 152, 182, 207), +(46, 5, 911019, 50, 911020, 70, 911002, 51, 19, 23, 21, 23, 40, 42, 155, 185, 210), +(47, 5, 911019, 51, 911020, 72, 911002, 54, 19, 23, 21, 23, 40, 42, 158, 188, 213), +(48, 5, 911019, 52, 911020, 74, 911002, 57, 19, 23, 21, 23, 40, 42, 161, 191, 216), +(49, 5, 911019, 53, 911020, 76, 911002, 60, 19, 23, 21, 23, 40, 42, 164, 194, 219), +(50, 5, 911019, 53, 911020, 78, 911002, 63, 19, 23, 21, 23, 40, 42, 167, 197, 222) +(1, 6, 911017, 4, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 20, 50, 75), +(2, 6, 911017, 6, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 23, 53, 78), +(3, 6, 911017, 8, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 26, 56, 81), +(4, 6, 911017, 9, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 29, 59, 84), +(5, 6, 911017, 11, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 32, 62, 87), +(6, 6, 911017, 13, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 35, 65, 90), +(7, 6, 911017, 15, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 38, 68, 93), +(8, 6, 911017, 16, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 41, 71, 96), +(9, 6, 911017, 18, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 44, 74, 99), +(10, 6, 911017, 20, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 47, 77, 102), +(11, 6, 911017, 18, 911018, 0, 0, 0, 5, 9, 7, 9, 12, 14, 50, 80, 105), +(12, 6, 911017, 19, 911018, 2, 0, 0, 5, 9, 7, 9, 12, 14, 53, 83, 108), +(13, 6, 911017, 20, 911018, 4, 0, 0, 5, 9, 7, 9, 12, 14, 56, 86, 111), +(14, 6, 911017, 22, 911018, 6, 0, 0, 5, 9, 7, 9, 12, 14, 59, 89, 114), +(15, 6, 911017, 23, 911018, 8, 0, 0, 5, 9, 7, 9, 12, 14, 62, 92, 117), +(16, 6, 911017, 24, 911018, 10, 0, 0, 7, 11, 9, 11, 16, 18, 65, 95, 120), +(17, 6, 911017, 25, 911018, 12, 0, 0, 7, 11, 9, 11, 16, 18, 68, 98, 123), +(18, 6, 911017, 27, 911018, 14, 0, 0, 7, 11, 9, 11, 16, 18, 71, 101, 126), +(19, 6, 911017, 28, 911018, 16, 0, 0, 7, 11, 9, 11, 16, 18, 74, 104, 129), +(20, 6, 911017, 29, 911018, 18, 0, 0, 7, 11, 9, 11, 16, 18, 77, 107, 132), +(21, 6, 911017, 30, 911018, 20, 0, 0, 9, 13, 11, 13, 20, 22, 80, 110, 135), +(22, 6, 911017, 32, 911018, 22, 0, 0, 9, 13, 11, 13, 20, 22, 83, 113, 138), +(23, 6, 911017, 33, 911018, 24, 0, 0, 9, 13, 11, 13, 20, 22, 86, 116, 141), +(24, 6, 911017, 34, 911018, 26, 0, 0, 9, 13, 11, 13, 20, 22, 89, 119, 144), +(25, 6, 911017, 35, 911018, 28, 0, 0, 9, 13, 11, 13, 20, 22, 92, 122, 147), +(26, 6, 911017, 37, 911018, 30, 0, 0, 11, 15, 13, 15, 24, 26, 95, 125, 150), +(27, 6, 911017, 38, 911018, 32, 0, 0, 11, 15, 13, 15, 24, 26, 98, 128, 153), +(28, 6, 911017, 39, 911018, 34, 0, 0, 11, 15, 13, 15, 24, 26, 101, 131, 156), +(29, 6, 911017, 40, 911018, 36, 0, 0, 11, 15, 13, 15, 24, 26, 104, 134, 159), +(30, 6, 911017, 35, 911018, 38, 911002, 3, 11, 15, 13, 15, 24, 26, 107, 137, 162), +(31, 6, 911017, 36, 911018, 40, 911002, 6, 13, 17, 15, 17, 28, 30, 110, 140, 165), +(32, 6, 911017, 37, 911018, 42, 911002, 9, 13, 17, 15, 17, 28, 30, 113, 143, 168), +(33, 6, 911017, 38, 911018, 44, 911002, 12, 13, 17, 15, 17, 28, 30, 116, 146, 171), +(34, 6, 911017, 39, 911018, 46, 911002, 15, 13, 17, 15, 17, 28, 30, 119, 149, 174), +(35, 6, 911017, 40, 911018, 48, 911002, 18, 13, 17, 15, 17, 28, 30, 122, 152, 177), +(36, 6, 911017, 41, 911018, 50, 911002, 21, 15, 19, 17, 19, 32, 34, 125, 155, 180), +(37, 6, 911017, 42, 911018, 52, 911002, 24, 15, 19, 17, 19, 32, 34, 128, 158, 183), +(38, 6, 911017, 43, 911018, 54, 911002, 27, 15, 19, 17, 19, 32, 34, 131, 161, 186), +(39, 6, 911017, 44, 911018, 56, 911002, 30, 15, 19, 17, 19, 32, 34, 134, 164, 189), +(40, 6, 911017, 44, 911018, 58, 911002, 33, 15, 19, 17, 19, 32, 34, 137, 167, 192), +(41, 6, 911017, 45, 911018, 60, 911002, 36, 17, 21, 19, 21, 36, 38, 140, 170, 195), +(42, 6, 911017, 46, 911018, 62, 911002, 39, 17, 21, 19, 21, 36, 38, 143, 173, 198), +(43, 6, 911017, 47, 911018, 64, 911002, 42, 17, 21, 19, 21, 36, 38, 146, 176, 201), +(44, 6, 911017, 48, 911018, 66, 911002, 45, 17, 21, 19, 21, 36, 38, 149, 179, 204), +(45, 6, 911017, 49, 911018, 68, 911002, 48, 17, 21, 19, 21, 36, 38, 152, 182, 207), +(46, 6, 911017, 50, 911018, 70, 911002, 51, 19, 23, 21, 23, 40, 42, 155, 185, 210), +(47, 6, 911017, 51, 911018, 72, 911002, 54, 19, 23, 21, 23, 40, 42, 158, 188, 213), +(48, 6, 911017, 52, 911018, 74, 911002, 57, 19, 23, 21, 23, 40, 42, 161, 191, 216), +(49, 6, 911017, 53, 911018, 76, 911002, 60, 19, 23, 21, 23, 40, 42, 164, 194, 219), +(50, 6, 911017, 53, 911018, 78, 911002, 63, 19, 23, 21, 23, 40, 42, 167, 197, 222), +(1, 7, 911023, 4, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 20, 50, 75), +(2, 7, 911023, 6, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 23, 53, 78), +(3, 7, 911023, 8, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 26, 56, 81), +(4, 7, 911023, 9, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 29, 59, 84), +(5, 7, 911023, 11, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 32, 62, 87), +(6, 7, 911023, 13, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 35, 65, 90), +(7, 7, 911023, 15, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 38, 68, 93), +(8, 7, 911023, 16, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 41, 71, 96), +(9, 7, 911023, 18, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 44, 74, 99), +(10, 7, 911023, 20, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 47, 77, 102), +(11, 7, 911023, 18, 911024, 0, 0, 0, 5, 9, 7, 9, 12, 14, 50, 80, 105), +(12, 7, 911023, 19, 911024, 2, 0, 0, 5, 9, 7, 9, 12, 14, 53, 83, 108), +(13, 7, 911023, 20, 911024, 4, 0, 0, 5, 9, 7, 9, 12, 14, 56, 86, 111), +(14, 7, 911023, 22, 911024, 6, 0, 0, 5, 9, 7, 9, 12, 14, 59, 89, 114), +(15, 7, 911023, 23, 911024, 8, 0, 0, 5, 9, 7, 9, 12, 14, 62, 92, 117), +(16, 7, 911023, 24, 911024, 10, 0, 0, 7, 11, 9, 11, 16, 18, 65, 95, 120), +(17, 7, 911023, 25, 911024, 12, 0, 0, 7, 11, 9, 11, 16, 18, 68, 98, 123), +(18, 7, 911023, 27, 911024, 14, 0, 0, 7, 11, 9, 11, 16, 18, 71, 101, 126), +(19, 7, 911023, 28, 911024, 16, 0, 0, 7, 11, 9, 11, 16, 18, 74, 104, 129), +(20, 7, 911023, 29, 911024, 18, 0, 0, 7, 11, 9, 11, 16, 18, 77, 107, 132), +(21, 7, 911023, 30, 911024, 20, 0, 0, 9, 13, 11, 13, 20, 22, 80, 110, 135), +(22, 7, 911023, 32, 911024, 22, 0, 0, 9, 13, 11, 13, 20, 22, 83, 113, 138), +(23, 7, 911023, 33, 911024, 24, 0, 0, 9, 13, 11, 13, 20, 22, 86, 116, 141), +(24, 7, 911023, 34, 911024, 26, 0, 0, 9, 13, 11, 13, 20, 22, 89, 119, 144), +(25, 7, 911023, 35, 911024, 28, 0, 0, 9, 13, 11, 13, 20, 22, 92, 122, 147), +(26, 7, 911023, 37, 911024, 30, 0, 0, 11, 15, 13, 15, 24, 26, 95, 125, 150), +(27, 7, 911023, 38, 911024, 32, 0, 0, 11, 15, 13, 15, 24, 26, 98, 128, 153), +(28, 7, 911023, 39, 911024, 34, 0, 0, 11, 15, 13, 15, 24, 26, 101, 131, 156), +(29, 7, 911023, 40, 911024, 36, 0, 0, 11, 15, 13, 15, 24, 26, 104, 134, 159), +(30, 7, 911023, 35, 911024, 38, 911002, 3, 11, 15, 13, 15, 24, 26, 107, 137, 162), +(31, 7, 911023, 36, 911024, 40, 911002, 6, 13, 17, 15, 17, 28, 30, 110, 140, 165), +(32, 7, 911023, 37, 911024, 42, 911002, 9, 13, 17, 15, 17, 28, 30, 113, 143, 168), +(33, 7, 911023, 38, 911024, 44, 911002, 12, 13, 17, 15, 17, 28, 30, 116, 146, 171), +(34, 7, 911023, 39, 911024, 46, 911002, 15, 13, 17, 15, 17, 28, 30, 119, 149, 174), +(35, 7, 911023, 40, 911024, 48, 911002, 18, 13, 17, 15, 17, 28, 30, 122, 152, 177), +(36, 7, 911023, 41, 911024, 50, 911002, 21, 15, 19, 17, 19, 32, 34, 125, 155, 180), +(37, 7, 911023, 42, 911024, 52, 911002, 24, 15, 19, 17, 19, 32, 34, 128, 158, 183), +(38, 7, 911023, 43, 911024, 54, 911002, 27, 15, 19, 17, 19, 32, 34, 131, 161, 186), +(39, 7, 911023, 44, 911024, 56, 911002, 30, 15, 19, 17, 19, 32, 34, 134, 164, 189), +(40, 7, 911023, 44, 911024, 58, 911002, 33, 15, 19, 17, 19, 32, 34, 137, 167, 192), +(41, 7, 911023, 45, 911024, 60, 911002, 36, 17, 21, 19, 21, 36, 38, 140, 170, 195), +(42, 7, 911023, 46, 911024, 62, 911002, 39, 17, 21, 19, 21, 36, 38, 143, 173, 198), +(43, 7, 911023, 47, 911024, 64, 911002, 42, 17, 21, 19, 21, 36, 38, 146, 176, 201), +(44, 7, 911023, 48, 911024, 66, 911002, 45, 17, 21, 19, 21, 36, 38, 149, 179, 204), +(45, 7, 911023, 49, 911024, 68, 911002, 48, 17, 21, 19, 21, 36, 38, 152, 182, 207), +(46, 7, 911023, 50, 911024, 70, 911002, 51, 19, 23, 21, 23, 40, 42, 155, 185, 210), +(47, 7, 911023, 51, 911024, 72, 911002, 54, 19, 23, 21, 23, 40, 42, 158, 188, 213), +(48, 7, 911023, 52, 911024, 74, 911002, 57, 19, 23, 21, 23, 40, 42, 161, 191, 216), +(49, 7, 911023, 53, 911024, 76, 911002, 60, 19, 23, 21, 23, 40, 42, 164, 194, 219), +(50, 7, 911023, 53, 911024, 78, 911002, 63, 19, 23, 21, 23, 40, 42, 167, 197, 222), +(1, 8, 911015, 4, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 20, 50, 75), +(2, 8, 911015, 6, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 23, 53, 78), +(3, 8, 911015, 8, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 26, 56, 81), +(4, 8, 911015, 9, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 29, 59, 84), +(5, 8, 911015, 11, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 32, 62, 87), +(6, 8, 911015, 13, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 35, 65, 90), +(7, 8, 911015, 15, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 38, 68, 93), +(8, 8, 911015, 16, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 41, 71, 96), +(9, 8, 911015, 18, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 44, 74, 99), +(10, 8, 911015, 20, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 47, 77, 102), +(11, 8, 911015, 18, 911016, 0, 0, 0, 5, 9, 7, 9, 12, 14, 50, 80, 105), +(12, 8, 911015, 19, 911016, 2, 0, 0, 5, 9, 7, 9, 12, 14, 53, 83, 108), +(13, 8, 911015, 20, 911016, 4, 0, 0, 5, 9, 7, 9, 12, 14, 56, 86, 111), +(14, 8, 911015, 22, 911016, 6, 0, 0, 5, 9, 7, 9, 12, 14, 59, 89, 114), +(15, 8, 911015, 23, 911016, 8, 0, 0, 5, 9, 7, 9, 12, 14, 62, 92, 117), +(16, 8, 911015, 24, 911016, 10, 0, 0, 7, 11, 9, 11, 16, 18, 65, 95, 120), +(17, 8, 911015, 25, 911016, 12, 0, 0, 7, 11, 9, 11, 16, 18, 68, 98, 123), +(18, 8, 911015, 27, 911016, 14, 0, 0, 7, 11, 9, 11, 16, 18, 71, 101, 126), +(19, 8, 911015, 28, 911016, 16, 0, 0, 7, 11, 9, 11, 16, 18, 74, 104, 129), +(20, 8, 911015, 29, 911016, 18, 0, 0, 7, 11, 9, 11, 16, 18, 77, 107, 132), +(21, 8, 911015, 30, 911016, 20, 0, 0, 9, 13, 11, 13, 20, 22, 80, 110, 135), +(22, 8, 911015, 32, 911016, 22, 0, 0, 9, 13, 11, 13, 20, 22, 83, 113, 138), +(23, 8, 911015, 33, 911016, 24, 0, 0, 9, 13, 11, 13, 20, 22, 86, 116, 141), +(24, 8, 911015, 34, 911016, 26, 0, 0, 9, 13, 11, 13, 20, 22, 89, 119, 144), +(25, 8, 911015, 35, 911016, 28, 0, 0, 9, 13, 11, 13, 20, 22, 92, 122, 147), +(26, 8, 911015, 37, 911016, 30, 0, 0, 11, 15, 13, 15, 24, 26, 95, 125, 150), +(27, 8, 911015, 38, 911016, 32, 0, 0, 11, 15, 13, 15, 24, 26, 98, 128, 153), +(28, 8, 911015, 39, 911016, 34, 0, 0, 11, 15, 13, 15, 24, 26, 101, 131, 156), +(29, 8, 911015, 40, 911016, 36, 0, 0, 11, 15, 13, 15, 24, 26, 104, 134, 159), +(30, 8, 911015, 35, 911016, 38, 911002, 3, 11, 15, 13, 15, 24, 26, 107, 137, 162), +(31, 8, 911015, 36, 911016, 40, 911002, 6, 13, 17, 15, 17, 28, 30, 110, 140, 165), +(32, 8, 911015, 37, 911016, 42, 911002, 9, 13, 17, 15, 17, 28, 30, 113, 143, 168), +(33, 8, 911015, 38, 911016, 44, 911002, 12, 13, 17, 15, 17, 28, 30, 116, 146, 171), +(34, 8, 911015, 39, 911016, 46, 911002, 15, 13, 17, 15, 17, 28, 30, 119, 149, 174), +(35, 8, 911015, 40, 911016, 48, 911002, 18, 13, 17, 15, 17, 28, 30, 122, 152, 177), +(36, 8, 911015, 41, 911016, 50, 911002, 21, 15, 19, 17, 19, 32, 34, 125, 155, 180), +(37, 8, 911015, 42, 911016, 52, 911002, 24, 15, 19, 17, 19, 32, 34, 128, 158, 183), +(38, 8, 911015, 43, 911016, 54, 911002, 27, 15, 19, 17, 19, 32, 34, 131, 161, 186), +(39, 8, 911015, 44, 911016, 56, 911002, 30, 15, 19, 17, 19, 32, 34, 134, 164, 189), +(40, 8, 911015, 44, 911016, 58, 911002, 33, 15, 19, 17, 19, 32, 34, 137, 167, 192), +(41, 8, 911015, 45, 911016, 60, 911002, 36, 17, 21, 19, 21, 36, 38, 140, 170, 195), +(42, 8, 911015, 46, 911016, 62, 911002, 39, 17, 21, 19, 21, 36, 38, 143, 173, 198), +(43, 8, 911015, 47, 911016, 64, 911002, 42, 17, 21, 19, 21, 36, 38, 146, 176, 201), +(44, 8, 911015, 48, 911016, 66, 911002, 45, 17, 21, 19, 21, 36, 38, 149, 179, 204), +(45, 8, 911015, 49, 911016, 68, 911002, 48, 17, 21, 19, 21, 36, 38, 152, 182, 207), +(46, 8, 911015, 50, 911016, 70, 911002, 51, 19, 23, 21, 23, 40, 42, 155, 185, 210), +(47, 8, 911015, 51, 911016, 72, 911002, 54, 19, 23, 21, 23, 40, 42, 158, 188, 213), +(48, 8, 911015, 52, 911016, 74, 911002, 57, 19, 23, 21, 23, 40, 42, 161, 191, 216), +(49, 8, 911015, 53, 911016, 76, 911002, 60, 19, 23, 21, 23, 40, 42, 164, 194, 219), +(50, 8, 911015, 53, 911016, 78, 911002, 63, 19, 23, 21, 23, 40, 42, 167, 197, 222), +(1, 9, 911021, 4, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 20, 50, 75), +(2, 9, 911021, 6, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 23, 53, 78), +(3, 9, 911021, 8, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 26, 56, 81), +(4, 9, 911021, 9, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 29, 59, 84), +(5, 9, 911021, 11, 0, 0, 0, 0, 1, 5, 3, 5, 4, 6, 32, 62, 87), +(6, 9, 911021, 13, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 35, 65, 90), +(7, 9, 911021, 15, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 38, 68, 93), +(8, 9, 911021, 16, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 41, 71, 96), +(9, 9, 911021, 18, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 44, 74, 99), +(10, 9, 911021, 20, 0, 0, 0, 0, 3, 7, 5, 7, 8, 10, 47, 77, 102), +(11, 9, 911021, 18, 911022, 0, 0, 0, 5, 9, 7, 9, 12, 14, 50, 80, 105), +(12, 9, 911021, 19, 911022, 2, 0, 0, 5, 9, 7, 9, 12, 14, 53, 83, 108), +(13, 9, 911021, 20, 911022, 4, 0, 0, 5, 9, 7, 9, 12, 14, 56, 86, 111), +(14, 9, 911021, 22, 911022, 6, 0, 0, 5, 9, 7, 9, 12, 14, 59, 89, 114), +(15, 9, 911021, 23, 911022, 8, 0, 0, 5, 9, 7, 9, 12, 14, 62, 92, 117), +(16, 9, 911021, 24, 911022, 10, 0, 0, 7, 11, 9, 11, 16, 18, 65, 95, 120), +(17, 9, 911021, 25, 911022, 12, 0, 0, 7, 11, 9, 11, 16, 18, 68, 98, 123), +(18, 9, 911021, 27, 911022, 14, 0, 0, 7, 11, 9, 11, 16, 18, 71, 101, 126), +(19, 9, 911021, 28, 911022, 16, 0, 0, 7, 11, 9, 11, 16, 18, 74, 104, 129), +(20, 9, 911021, 29, 911022, 18, 0, 0, 7, 11, 9, 11, 16, 18, 77, 107, 132), +(21, 9, 911021, 30, 911022, 20, 0, 0, 9, 13, 11, 13, 20, 22, 80, 110, 135), +(22, 9, 911021, 32, 911022, 22, 0, 0, 9, 13, 11, 13, 20, 22, 83, 113, 138), +(23, 9, 911021, 33, 911022, 24, 0, 0, 9, 13, 11, 13, 20, 22, 86, 116, 141), +(24, 9, 911021, 34, 911022, 26, 0, 0, 9, 13, 11, 13, 20, 22, 89, 119, 144), +(25, 9, 911021, 35, 911022, 28, 0, 0, 9, 13, 11, 13, 20, 22, 92, 122, 147), +(26, 9, 911021, 37, 911022, 30, 0, 0, 11, 15, 13, 15, 24, 26, 95, 125, 150), +(27, 9, 911021, 38, 911022, 32, 0, 0, 11, 15, 13, 15, 24, 26, 98, 128, 153), +(28, 9, 911021, 39, 911022, 34, 0, 0, 11, 15, 13, 15, 24, 26, 101, 131, 156), +(29, 9, 911021, 40, 911022, 36, 0, 0, 11, 15, 13, 15, 24, 26, 104, 134, 159), +(30, 9, 911021, 35, 911022, 38, 911002, 3, 11, 15, 13, 15, 24, 26, 107, 137, 162), +(31, 9, 911021, 36, 911022, 40, 911002, 6, 13, 17, 15, 17, 28, 30, 110, 140, 165), +(32, 9, 911021, 37, 911022, 42, 911002, 9, 13, 17, 15, 17, 28, 30, 113, 143, 168), +(33, 9, 911021, 38, 911022, 44, 911002, 12, 13, 17, 15, 17, 28, 30, 116, 146, 171), +(34, 9, 911021, 39, 911022, 46, 911002, 15, 13, 17, 15, 17, 28, 30, 119, 149, 174), +(35, 9, 911021, 40, 911022, 48, 911002, 18, 13, 17, 15, 17, 28, 30, 122, 152, 177), +(36, 9, 911021, 41, 911022, 50, 911002, 21, 15, 19, 17, 19, 32, 34, 125, 155, 180), +(37, 9, 911021, 42, 911022, 52, 911002, 24, 15, 19, 17, 19, 32, 34, 128, 158, 183), +(38, 9, 911021, 43, 911022, 54, 911002, 27, 15, 19, 17, 19, 32, 34, 131, 161, 186), +(39, 9, 911021, 44, 911022, 56, 911002, 30, 15, 19, 17, 19, 32, 34, 134, 164, 189), +(40, 9, 911021, 44, 911022, 58, 911002, 33, 15, 19, 17, 19, 32, 34, 137, 167, 192), +(41, 9, 911021, 45, 911022, 60, 911002, 36, 17, 21, 19, 21, 36, 38, 140, 170, 195), +(42, 9, 911021, 46, 911022, 62, 911002, 39, 17, 21, 19, 21, 36, 38, 143, 173, 198), +(43, 9, 911021, 47, 911022, 64, 911002, 42, 17, 21, 19, 21, 36, 38, 146, 176, 201), +(44, 9, 911021, 48, 911022, 66, 911002, 45, 17, 21, 19, 21, 36, 38, 149, 179, 204), +(45, 9, 911021, 49, 911022, 68, 911002, 48, 17, 21, 19, 21, 36, 38, 152, 182, 207), +(46, 9, 911021, 50, 911022, 70, 911002, 51, 19, 23, 21, 23, 40, 42, 155, 185, 210), +(47, 9, 911021, 51, 911022, 72, 911002, 54, 19, 23, 21, 23, 40, 42, 158, 188, 213), +(48, 9, 911021, 52, 911022, 74, 911002, 57, 19, 23, 21, 23, 40, 42, 161, 191, 216), +(49, 9, 911021, 53, 911022, 76, 911002, 60, 19, 23, 21, 23, 40, 42, 164, 194, 219), +(50, 9, 911021, 53, 911022, 78, 911002, 63, 19, 23, 21, 23, 40, 42, 167, 197, 222), +; diff --git a/scripts/upgrade_ranks/main.go b/scripts/upgrade_ranks/main.go index 497b4bc..5fee056 100644 --- a/scripts/upgrade_ranks/main.go +++ b/scripts/upgrade_ranks/main.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "math" "os" ) @@ -15,13 +16,80 @@ const ( ) const ( - RESIST_FROST = iota + RESIST_ARCANE = iota RESIST_FIRE RESIST_NATURE + RESIST_FROST RESIST_SHADOW - RESIST_ARCANE ) +// Return the itemEntry for a state item and based on quality (3 - rare, 4 - epic) +func getStatItemEntry(statID int, quality int) int { + switch statID { + case STAT_INTELLECT: + if quality == 3 { + return 911005 + } + return 911006 + case STAT_SPIRIT: + if quality == 3 { + return 911009 + } + return 911010 + case STAT_STRENGTH: + if quality == 3 { + return 911003 + } + return 911004 + case STAT_AGILITY: + if quality == 3 { + return 911007 + } + return 911008 + case STAT_STAMINA: + if quality == 3 { + return 911011 + } + return 911012 + + default: + return 0 + } +} + +func getResistItemEntry(resistID int, quality int) int { + switch resistID { + case RESIST_FROST: + if quality == 3 { + return 911015 + } + return 911016 + case RESIST_FIRE: + if quality == 3 { + return 911017 + } + return 911018 + case RESIST_NATURE: + if quality == 3 { + return 911023 + } + return 911024 + case RESIST_SHADOW: + if quality == 3 { + return 911021 + } + return 911022 + case RESIST_ARCANE: + if quality == 3 { + return 911019 + } + return 911020 + + default: + return 0 + } +} + func main() { // Output file for the SQL script outputFile, err := os.Create("generate_stat_upgrades.sql") @@ -40,9 +108,17 @@ func main() { STAT_STAMINA: "Stamina", } + resistTypes := map[int]string{ + RESIST_ARCANE: "Arcane", + RESIST_FIRE: "Fire", + RESIST_NATURE: "Nature", + RESIST_FROST: "Frost", + RESIST_SHADOW: "Shadow", + } + // Start writing the SQL script fmt.Fprintln(outputFile, "-- SQL Script to Insert 50 Ranks for Each Stat") - fmt.Fprintln(outputFile, "INSERT INTO mp_upgrade_ranks (upgradeRank, advancementId, materialId1, materialCost1, materialId2, materialCost2, materialId3, materialCost3, minIncrease1, maxIncrease1, minIncrease2, maxIncrease2, minIncrease3, maxIncrease3, chanceCost1, chanceCost2, chanceCost3) VALUES") + fmt.Fprintln(outputFile, "INSERT INTO mp_upgrade_ranks (upgradeRank, advancementId, itemEntry1, itemCost1, itemEntry2, itemCost2, itemEntry3, itemCost3, minIncrease1, maxIncrease1, minIncrease2, maxIncrease2, minIncrease3, maxIncrease3, chanceCost1, chanceCost2, chanceCost3) VALUES") // Iterate over stats for statID := range stats { @@ -59,6 +135,9 @@ func main() { materialCost = 1000 + (rank-30)*18 } + // Make adjustment for new fusion core types + itemCost1 := int(math.Ceil(float64(materialCost) / 20)) + // Stat growth minIncrease1 := 1 + (rank-1)/10*2 maxIncrease1 := 10 + (rank-1)/10*2 @@ -74,47 +153,49 @@ func main() { chanceCost3 := 75 + (rank-1)*3 // use material ids from the mp_material_types table material1 should be common stuff. - materialId1 := statID*2 + 1 + itemEntry1 := getStatItemEntry(statID, 3) // material2 should be rare stuff only required after rank 10 at growth rate of 5 per rank - materialId2, materialCost2 := 0, 0 + itemEntry2, itemCost2 := 0, 0 if rank > 10 { - materialId2 = statID*2 + 2 - materialCost2 = (rank - 11) * 10 + itemEntry2 = getStatItemEntry(statID, 4) + itemCost2 = (rank - 11) * 10 } - materialId3, materialCost3 := 0, 0 + // Adjust from old formula to new mythic fusion core types + itemCost2 = int(math.Ceil(float64(itemCost2) / 5)) + + itemEntry3, itemCost3 := 0, 0 if rank >= 30 { - materialId3 = 20 // Group lot of raid only items - materialCost3 = (rank - 29) * 3 + itemEntry3 = 911002 // veilstones + itemCost3 = (rank - 29) * 3 + if itemCost3 > 15 { + itemCost3 = 15 + } } // Write SQL insert statement for this rank sql := fmt.Sprintf( "(%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d)", - rank, statID, materialId1, materialCost, materialId2, materialCost2, materialId3, materialCost3, + rank, statID, itemEntry1, itemCost1, itemEntry2, itemCost2, itemEntry3, itemCost3, minIncrease1, maxIncrease1, minIncrease2, maxIncrease1, minIncrease3, maxIncrease3, chanceCost1, chanceCost2, chanceCost3, ) // Add a comma for all but the last line - sql += "," - fmt.Fprintln(outputFile, sql) + isLastStat := statID == STAT_STAMINA && rank == 50 + isLastResist := false + isLast := isLastStat && len(resistTypes) == 0 || isLastResist + if !isLast { + sql += "," + } + fmt.Fprintln(outputFile, sql) } } - resists := map[int]string{ - RESIST_FROST: "Frost", - RESIST_FIRE: "Fire", - RESIST_NATURE: "Nature", - RESIST_SHADOW: "Shadow", - RESIST_ARCANE: "Arcane", - } - - // Iterate over stats - for resistId := range resists { - + // Iterate over resists + for resistId := range resistTypes { resistIdbump := resistId + 5 for rank := 1; rank <= 50; rank++ { // Material cost increases by 50 per rank @@ -129,6 +210,9 @@ func main() { materialCost = 700 + (rank-30)*18 } + // Make adjustment for new fusion core types + itemCost1 := int(math.Ceil(float64(materialCost) / 20)) + // Stat growth minIncrease1 := 1 + (rank-1)/5*2 maxIncrease1 := 5 + (rank-1)/5*2 @@ -145,31 +229,36 @@ func main() { chanceCost3 := 75 + (rank-1)*3 // use material ids from the mp_material_types table material1 should be common stuff. - materialId1 := resistIdbump*2 + 1 + itemEntry1 := getResistItemEntry(resistId, 3) // material2 should be rare stuff only required after rank 10 at growth rate of 5 per rank - materialId2, materialCost2 := 0, 0 + itemEntry2, itemCost2 := 0, 0 if rank > 10 { - materialId2 = resistIdbump*2 + 2 - materialCost2 = (rank - 11) * 10 + itemEntry2 = getResistItemEntry(resistId, 4) + itemCost2 = (rank - 11) * 10 } - materialId3, materialCost3 := 0, 0 + // Adjust from old formula to new mythic fusion core types + itemCost2 = int(math.Ceil(float64(itemCost2) / 5)) + + itemEntry3, itemCost3 := 0, 0 if rank >= 30 { - materialId3 = 20 // Group lot of raid only items - materialCost3 = (rank - 29) * 3 + itemEntry3 = 911002 // veilstones + itemCost3 = (rank - 29) * 3 } // Write SQL insert statement for this rank sql := fmt.Sprintf( "(%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d)", - rank, resistIdbump, materialId1, materialCost, materialId2, materialCost2, materialId3, materialCost3, + rank, resistIdbump, itemEntry1, itemCost1, itemEntry2, itemCost2, itemEntry3, itemCost3, minIncrease1, maxIncrease1, minIncrease2, maxIncrease1, minIncrease3, maxIncrease3, chanceCost1, chanceCost2, chanceCost3, ) // Add a comma for all but the last line - if !(resistId == RESIST_ARCANE && rank == 50) { + isLast := resistId == RESIST_ARCANE && rank == 50 + + if !isLast { sql += "," } fmt.Fprintln(outputFile, sql) diff --git a/src/AdvancementMgr.cpp b/src/AdvancementMgr.cpp index 81474d4..1ab1435 100644 --- a/src/AdvancementMgr.cpp +++ b/src/AdvancementMgr.cpp @@ -34,12 +34,12 @@ std::string MpAdvancementsToString(MpAdvancements advancement) * * upgradeRank INT UNSIGNED NOT NULL, * advancementId INT UNSIGNED NOT NULL, - * materialId1 INT UNSIGNED NOT NULL, - * materialId2 INT UNSIGNED NOT NULL, - * materialId3 INT UNSIGNED NOT NULL, - * materialCost INT UNSIGNED NOT NULL, - * materialCost2 INT UNSIGNED NOT NULL, - * materialCost3 INT UNSIGNED NOT NULL, + * itemEntry1 INT UNSIGNED NOT NULL, + * itemEntry2 INT UNSIGNED NOT NULL, + * itemEntry3 INT UNSIGNED NOT NULL, + * itemCost1 INT UNSIGNED NOT NULL, + * itemCost2 INT UNSIGNED NOT NULL, + * itemCost3 INT UNSIGNED NOT NULL, * minIncrease1 INT UNSIGNED NOT NULL, * maxIncrease1 INT UNSIGNED NOT NULL, * minIncrease2 INT UNSIGNED NOT NULL, @@ -64,12 +64,12 @@ int32 AdvancementMgr::LoadAdvancementRanks() { SELECT upgradeRank, advancementId, - materialId1, - materialId2, - materialId3, - materialCost1, - materialCost2, - materialCost3, + itemEntry1, + itemEntry2, + itemEntry3, + itemCost1, + itemCost2, + itemCost3, minIncrease1, maxIncrease1, minIncrease2, @@ -84,7 +84,7 @@ int32 AdvancementMgr::LoadAdvancementRanks() { QueryResult result = WorldDatabase.Query(query); if (!result) { - MpLogger::error("Failed to load mythic scale factors from database"); + MpLogger::error("Failed to load advancement ranks from database"); return 0; } @@ -96,12 +96,12 @@ int32 AdvancementMgr::LoadAdvancementRanks() { Field* fields = result->Fetch(); uint32 upgradeRank = fields[0].Get(); uint32 advancementId = fields[1].Get(); - uint32 materialId1 = fields[2].Get(); - uint32 materialId2 = fields[3].Get(); - uint32 materialId3 = fields[4].Get(); - uint32 materialCost1 = fields[5].Get(); - uint32 materialCost2 = fields[6].Get(); - uint32 materialCost3 = fields[7].Get(); + uint32 itemEntry1 = fields[2].Get(); + uint32 itemEntry2 = fields[3].Get(); + uint32 itemEntry3 = fields[4].Get(); + uint32 itemCost1 = fields[5].Get(); + uint32 itemCost2 = fields[6].Get(); + uint32 itemCost3 = fields[7].Get(); uint32 minIncrease1 = fields[8].Get(); uint32 maxIncrease1 = fields[9].Get(); uint32 minIncrease2 = fields[10].Get(); @@ -124,9 +124,9 @@ int32 AdvancementMgr::LoadAdvancementRanks() { .lowRange = std::make_pair(minIncrease1, maxIncrease1), .midRange = std::make_pair(minIncrease2, maxIncrease2), .highRange = std::make_pair(minIncrease3, maxIncrease3), - .material1 = std::make_pair(materialId1, materialCost1), - .material2 = std::make_pair(materialId2, materialCost2), - .material3 = std::make_pair(materialId3, materialCost3) + .material1 = std::make_pair(itemEntry1, itemCost1), + .material2 = std::make_pair(itemEntry2, itemCost2), + .material3 = std::make_pair(itemEntry3, itemCost3) }; _advancementRanks.try_emplace(std::make_pair(upgradeRank, advancement), rank); @@ -172,24 +172,34 @@ void AdvancementMgr::LoadPlayerAdvancements(Player* player) { return; } - Field* fields = result->Fetch(); - uint32 guid = fields[0].Get(); - uint32 advancementId = fields[1].Get(); - float bonus = fields[2].Get(); - uint32 upgradeRank = fields[3].Get(); - uint32 diceSpent = fields[4].Get(); + uint32 count = 0; + uint32 guid = player->GetGUID().GetCounter(); - MpAdvancements advancement = static_cast(advancementId); - MpPlayerRank playerRank = MpPlayerRank(); - playerRank.rank = upgradeRank; - playerRank.advancementId = advancement; - playerRank.diceSpent = diceSpent; - playerRank.bonus = bonus; + // Loop through all results to load all advancements for this player + do { + Field* fields = result->Fetch(); + uint32 advancementId = fields[1].Get(); + float bonus = fields[2].Get(); + uint32 upgradeRank = fields[3].Get(); + uint32 diceSpent = fields[4].Get(); - // List of all ranks keyed by rank, advancementId - _playerAdvancements[guid][advancement] = playerRank; + MpAdvancements advancement = static_cast(advancementId); + MpPlayerRank playerRank = MpPlayerRank(); + playerRank.rank = upgradeRank; + playerRank.advancementId = advancement; + playerRank.diceSpent = diceSpent; + playerRank.bonus = bonus; - MpLogger::info("Loaded player {} advancement {} rank {}", player->GetName(), playerRank.advancementId, upgradeRank); + // List of all ranks keyed by rank, advancementId + _playerAdvancements[guid][advancement] = playerRank; + + MpLogger::debug("Loaded player {} advancement {} rank {} with bonus {}", + player->GetName(), static_cast(advancement), upgradeRank, bonus); + + count++; + } while (result->NextRow()); + + MpLogger::info("Loaded {} advancements for player {}", count, player->GetName()); } /** @@ -204,21 +214,25 @@ int32 AdvancementMgr::LoadMaterialTypes() { FROM mp_material_types )"; - QueryResult result = WorldDatabase.Query(query); + if(QueryResult result = WorldDatabase.Query(query)) { - do { - Field* fields = result->Fetch(); - uint32 materialId = fields[0].Get(); - uint32 entry = fields[1].Get(); + do { + Field* fields = result->Fetch(); + uint32 materialId = fields[0].Get(); + uint32 entry = fields[1].Get(); - if(!_materialTypes.contains(materialId)) { - _materialTypes.emplace(materialId,std::vector()); - } - _materialTypes.at(materialId).push_back(entry); + if(!_materialTypes.contains(materialId)) { + _materialTypes.emplace(materialId,std::vector()); + } + _materialTypes.at(materialId).push_back(entry); - } while (result->NextRow()); + } while (result->NextRow()); - return result->GetRowCount(); + return result->GetRowCount(); + } else { + MpLogger::error("Query failed to load material types from database"); + return 0; + } } MpAdvancementRank* AdvancementMgr::GetAdvancementRank(uint32 rank, MpAdvancements advancement) @@ -250,7 +264,7 @@ MpPlayerRank* AdvancementMgr::GetPlayerAdvancementRank(Player* player, MpAdvance return nullptr; } -uint32 AdvancementMgr::UpgradeAdvancement(Player* player, MpAdvancements advancement, uint32 diceCostLevel, uint32 itemEntry1, uint32 itemEntry2, uint32 itemEntry3) +uint32 AdvancementMgr::UpgradeAdvancement(Player* player, MpAdvancements advancement, uint32 diceCostLevel) { std::lock_guard lock(_playerAdvancementMutex); @@ -262,9 +276,6 @@ uint32 AdvancementMgr::UpgradeAdvancement(Player* player, MpAdvancements advance if(diceCostLevel < 1 || diceCostLevel > 3) { throw new std::runtime_error(Acore::StringFormat("Invalid dice cost level valid vales (1,2,3) received {} for player {}", diceCostLevel, player->GetName())); } - if(itemEntry1 == 0) { - throw new std::runtime_error(Acore::StringFormat("Material1 can not be 0 can not perform advancement upgrade for player {} Advancement {}", player->GetName(), advancement)); - } MpPlayerRank* playerRank = GetPlayerAdvancementRank(player, advancement); @@ -285,10 +296,16 @@ uint32 AdvancementMgr::UpgradeAdvancement(Player* player, MpAdvancements advance uint32 newRank = playerRank->rank + 1; MpAdvancementRank* advancementRank = GetAdvancementRank(newRank, advancement); - if(!advancementRank->IsValid()) { - throw std::runtime_error("Advancement rank could not be found. Rank: " + std::to_string(newRank) + " Advancement: " + std::to_string(advancement)); + if(advancementRank == nullptr || !advancementRank->IsValid()) { + MpLogger::error("Advancement rank could not be found. Rank: {} Advancement: {}", newRank, static_cast(advancement)); + return 0; } + // Get the items needed to upgrade this advancement + uint32 itemEntry1 = advancementRank->material1.first; + uint32 itemEntry2 = advancementRank->material2.first; + uint32 itemEntry3 = advancementRank->material3.first; + // If the player has the items needed to upgrade this advancement, then remove the items from the player inventory and apply the upgrade if(!_PlayerHasItems(player, advancementRank, diceCostLevel, itemEntry1, itemEntry2, itemEntry3)) { MpLogger::debug("Player {} does not have the required items to upgrade advancement {}", player->GetName(), advancement); @@ -315,6 +332,17 @@ uint32 AdvancementMgr::UpgradeAdvancement(Player* player, MpAdvancements advance // Save the advancement to the database _SaveAdvancement(player, advancementRank, playerRank, advancementRank->rollCost[diceCostLevel-1], roll, itemEntry1, itemEntry2, itemEntry3); + // Remove and reapply the aura to refresh the spell with the latest bonuses + uint32 spellId = MpConstants::GetAdvancementAura(advancement); + if (spellId > 0) + { + MpLogger::info("Refreshing advancement aura {} for player {}", spellId, player->GetName()); + + // First remove the aura completely + player->RemoveAura(spellId); + player->AddAura(spellId, player); + } + return roll; } @@ -352,7 +380,7 @@ float AdvancementMgr::_RollAdvancement(MpAdvancementRank* advancementRank, uint3 max = advancementRank->highRange.second; break; default: - MpLogger::error("Invalid dice cost level valid vales (1,2,3) received {} for rank roll", diceCostLevel, advancementRank->rank); + MpLogger::error("Invalid dice cost level valid vales (1,2,3) received {} for rank roll {}", diceCostLevel, advancementRank->rank); break; } @@ -367,79 +395,92 @@ float AdvancementMgr::_RollAdvancement(MpAdvancementRank* advancementRank, uint3 */ bool AdvancementMgr::_PlayerHasItems(Player* player, MpAdvancementRank* advancementRank, uint32 diceCostLevel, uint32 itemEntry1, uint32 itemEntry2, uint32 itemEntry3) { - MpLogger::debug("Debugging player dice {} item1 {} item2 {} item3 {}", diceCostLevel, itemEntry1, itemEntry2, itemEntry3); - MpLogger::debug("Advancement Rank dice info {} {} {} {}", advancementRank->materialCost[1], advancementRank->materialCost[2], advancementRank->materialCost[3]); + MpLogger::debug("Checking items for player {} dice level {} item1 {} item2 {} item3 {}", + player->GetName(), diceCostLevel, itemEntry1, itemEntry2, itemEntry3); - // Check if player has the required dice to upgrade the advancement if not do nothing. + // Check if player has the required dice to upgrade the advancement uint32 diceCost = advancementRank->rollCost[diceCostLevel-1]; if(!player->HasItemCount(MpConstants::ANCIENT_DICE, diceCost)) { - MpLogger::info("Player {} does not have enough dice to upgrade advancement {}", player->GetName(), advancementRank->advancementId); + MpLogger::info("Player {} does not have enough dice to upgrade advancement {}", + player->GetName(), advancementRank->advancementId); return false; } - // Create arrays of material data for easier iteration - std::pair materials[] = { - advancementRank->material1, - advancementRank->material2, - advancementRank->material3 - }; - - uint32 itemEntries[] = {itemEntry1, itemEntry2, itemEntry3}; - - // Validate each material - for (size_t i = 0; i < 3; ++i) { - uint32 materialId = materials[i].first; - uint32 requiredCount = materials[i].second; - uint32 itemEntry = itemEntries[i]; - - // if the materialID is not set and is not the first material then return true as no material is required - if (materialId == 0 && i != 0) { - return true; + // Check material 1 (required) + if (advancementRank->material1.first > 0) { + if (itemEntry1 == 0) { + throw std::runtime_error("Primary material entry is required but was not provided"); } - if (itemEntry == 0 && materialId != 0) { - throw std::runtime_error("The entry for materialId: " + std::to_string(materialId) + " was not passed in."); - } - - std::vector entries = _materialTypes.at(materialId); - if (entries.empty()) { - throw std::runtime_error("MaterialId: " + std::to_string(materialId) + " could not be found in the materials list"); - } - - if (std::find(entries.begin(), entries.end(), itemEntry) == entries.end()) { - throw std::runtime_error("Incorrect material entry" + std::to_string(itemEntry) + " passed in passed in for Advancement id:" + std::to_string(advancementRank->advancementId)); - } - - if (!player->HasItemCount(itemEntry, requiredCount)) { - MpLogger::info("Player {} does not have enough material {} to upgrade advancement {} requires: {}", - player->GetName(), itemEntry, advancementRank->advancementId, requiredCount); + uint32 requiredCount = advancementRank->material1.second; + if (!player->HasItemCount(itemEntry1, requiredCount)) { + MpLogger::info("Player {} does not have enough of item {} for advancement {}, requires: {}", + player->GetName(), itemEntry1, advancementRank->advancementId, requiredCount); return false; } } + // Check material 2 (optional) + if (advancementRank->material2.first > 0) { + if (itemEntry2 == 0) { + MpLogger::debug("Secondary material is required but not provided"); + return false; + } + + uint32 requiredCount = advancementRank->material2.second; + if (!player->HasItemCount(itemEntry2, requiredCount)) { + MpLogger::info("Player {} does not have enough of item {} for advancement {}, requires: {}", + player->GetName(), itemEntry2, advancementRank->advancementId, requiredCount); + return false; + } + } + + // Check material 3 (optional) + if (advancementRank->material3.first > 0) { + if (itemEntry3 == 0) { + MpLogger::debug("Tertiary material is required but not provided"); + return false; + } + + uint32 requiredCount = advancementRank->material3.second; + if (!player->HasItemCount(itemEntry3, requiredCount)) { + MpLogger::info("Player {} does not have enough of item {} for advancement {}, requires: {}", + player->GetName(), itemEntry3, advancementRank->advancementId, requiredCount); + return false; + } + } + + MpLogger::debug("Player {} has all required materials to upgrade advancement {}", + player->GetName(), advancementRank->advancementId); return true; } // Remove all items required for the upgrade. void AdvancementMgr::_ChargeItemCost(Player *player, MpAdvancementRank* advancementRank, uint32 diceCostLevel, uint32 itemEntry1, uint32 itemEntry2, uint32 itemEntry3) { - MpLogger::debug("Charging player dice {} item1 {} item2 {} item3 {}", diceCostLevel, itemEntry1, itemEntry2, itemEntry3); + MpLogger::debug("Charging player {} dice level {} item1 {} item2 {} item3 {}", + player->GetName(), diceCostLevel, itemEntry1, itemEntry2, itemEntry3); + + // Remove the dice cost uint32 diceCost = advancementRank->rollCost[diceCostLevel-1]; player->DestroyItemCount(MpConstants::ANCIENT_DICE, diceCost, true); - std::vector> items = { - {itemEntry1, advancementRank->material1.second}, - {itemEntry2, advancementRank->material2.second}, - {itemEntry3, advancementRank->material3.second} - }; - - for (const auto& item : items) { - if (item.first > 0) { - player->DestroyItemCount(item.first, item.second, true); - } + // Remove material 1 if it exists + if (itemEntry1 > 0 && advancementRank->material1.first > 0) { + player->DestroyItemCount(itemEntry1, advancementRank->material1.second, true); } - return; + // Remove material 2 if it exists + if (itemEntry2 > 0 && advancementRank->material2.first > 0) { + player->DestroyItemCount(itemEntry2, advancementRank->material2.second, true); + } + + // Remove material 3 if it exists + if (itemEntry3 > 0 && advancementRank->material3.first > 0) { + player->DestroyItemCount(itemEntry3, advancementRank->material3.second, true); + } + + MpLogger::debug("Successfully charged player {} for advancement upgrade", player->GetName()); } void AdvancementMgr::_SaveAdvancement(Player* player, MpAdvancementRank* advancementRank, MpPlayerRank* playerRank, uint32 diceCost, float roll, uint32 itemEntry1, uint32 itemEntry2, uint32 itemEntry3) diff --git a/src/AdvancementMgr.h b/src/AdvancementMgr.h index 23d340c..26ed0a1 100644 --- a/src/AdvancementMgr.h +++ b/src/AdvancementMgr.h @@ -121,7 +121,7 @@ public: * mixed materials is more complicated and the UI to support it is much more complex, while this is not as nice it is much simpler to implement. * That means all materials have to be selected and passed in at the time of making this call. */ - uint32 UpgradeAdvancement(Player* player, MpAdvancements advancement, uint32 diceCostLevel, uint32 itemEntry1, uint32 itemEntry2, uint32 itemEntry3); + uint32 UpgradeAdvancement(Player* player, MpAdvancements advancement, uint32 diceCostLevel); // Used to reset all advancements for a specific player bool ResetPlayerAdvancements(Player* player); diff --git a/src/Event/MpEvent.h b/src/Event/MpEvent.h index eaf42ad..2408d82 100644 --- a/src/Event/MpEvent.h +++ b/src/Event/MpEvent.h @@ -35,7 +35,7 @@ inline std::unordered_map MpEventMap = {{ {"ResetAdvancement", MpEvent::ResetAdvancement}, {"ResetAllAdvancements", MpEvent::ResetAllAdvancements}, {"GetPlayerRank", MpEvent::GetPlayerRank}, - {"GetAdvancementRank", MpEvent::ResetAllAdvancements} + {"GetAdvancementRank", MpEvent::GetAdvancementRank} }}; inline std::unordered_map MpClientEventNames = {{ diff --git a/src/Event/MpEventHandlers.cpp b/src/Event/MpEventHandlers.cpp index 3063e3f..68dcb02 100644 --- a/src/Event/MpEventHandlers.cpp +++ b/src/Event/MpEventHandlers.cpp @@ -63,7 +63,7 @@ bool SendEventError(Player* player, const std::string& method, MP_EVENT_CODE cod * Message Format: * p|playerGuid|UpgradeAdvancement|advancementId|diceLevel|itemEntry1|itemEntry2|itemEntry3 */ -class UpdateAdvancements : public MpEventInterface +class UpgradeAdvancements : public MpEventInterface { public: const std::string EventName() const override @@ -82,40 +82,36 @@ class UpdateAdvancements : public MpEventInterface MpLogger::info("{} Arg: {}", EventName(), arg); } - // Validate the message is int he right format - if(args.size() != 5) { - return SendEventError(player, EventName(),MP_EVENT_CODE::INVALID_ARGUMENT_SIZE, "Invalid number of arguments expected 5, found " + std::to_string(args.size())); + // Validate the message is in the right format + if(args.size() != 2) { + return SendEventError(player, EventName(), MP_EVENT_CODE::INVALID_ARGUMENT_SIZE, "Invalid number of arguments expected 2, found " + std::to_string(args.size())); } uint32 advancementId = std::stoi(args[0]); if(advancementId >= MpAdvancements::MP_ADV_MAX) { - return SendEventError(player, EventName(),MP_EVENT_CODE::INVALID_ARGUMENT, "Invalid advancement id " + args[0] + " max is " + std::to_string(MpAdvancements::MP_ADV_MAX)); + return SendEventError(player, EventName(), MP_EVENT_CODE::INVALID_ARGUMENT, "Invalid advancement id " + args[0] + " max is " + std::to_string(MpAdvancements::MP_ADV_MAX)); } uint32 diceLevel = std::stoi(args[1]); if(diceLevel < 1 || diceLevel > 3) { - return SendEventError(player, EventName(),MP_EVENT_CODE::INVALID_ARGUMENT, "Invalid dice level " + args[1] + " valid values are 1,2,3"); + return SendEventError(player, EventName(), MP_EVENT_CODE::INVALID_ARGUMENT, "Invalid dice level " + args[1] + " valid values are 1,2,3"); } - uint32 itemEntry1 = std::stoi(args[2]); - if(itemEntry1 == 0) { - return SendEventError(player, EventName(),MP_EVENT_CODE::INVALID_ARGUMENT, "Invalid item entry1 can not be empty " + args[2]); - } - - uint32 itemEntry2 = std::stoi(args[3]); - uint32 itemEntry3 = std::stoi(args[4]); - uint32 increase; try { - increase = sAdvancementMgr->UpgradeAdvancement(player, static_cast(advancementId), diceLevel, itemEntry1, itemEntry2, itemEntry3); - if( increase == 0) { - return SendEventError(player, EventName(),MP_EVENT_CODE::INVALID_ARGUMENT, "Failed to upgrade advancement invalid request see error logs for player " + player->GetName()); + increase = sAdvancementMgr->UpgradeAdvancement(player, static_cast(advancementId), diceLevel); + if(increase == 0) { + return SendEventError(player, EventName(), MP_EVENT_CODE::INVALID_ARGUMENT, "Failed to upgrade advancement invalid request see error logs for player " + player->GetName()); } } catch(const std::exception& e) { - return SendEventError(player, EventName(),MP_EVENT_CODE::FAILED_UPGRADE_ADV, "Failed to upgrade: " + std::string(e.what()) + " for player " + player->GetName()); + return SendEventError(player, EventName(), MP_EVENT_CODE::FAILED_UPGRADE_ADV, "Failed to upgrade: " + std::string(e.what()) + " for player " + player->GetName()); } + // Only proceed to here if no errors occurred MpPlayerRank* playerRank = sAdvancementMgr->GetPlayerAdvancementRank(player, static_cast(advancementId)); + if (!playerRank) { + return SendEventError(player, EventName(), MP_EVENT_CODE::INVALID_ARGUMENT, "Failed to get advancement rank for player " + player->GetName()); + } // Format the success event data for client increase|newrank|bonus eventData = { @@ -206,8 +202,8 @@ class GetAdvancementRank : public MpEventInterface { bool Execute(Player* player, std::vector& args) override { - if(args.size() != 3) { - return SendEventError(player, EventName(),MP_EVENT_CODE::INVALID_ARGUMENT_SIZE, "Invalid number of arguments expected 3, found " + std::to_string(args.size())); + if(args.size() != 2) { + return SendEventError(player, EventName(),MP_EVENT_CODE::INVALID_ARGUMENT_SIZE, "Invalid number of arguments expected 2, found " + std::to_string(args.size())); } uint32 advancementId = std::stoi(args[0]); @@ -251,7 +247,7 @@ class GetAdvancementRank : public MpEventInterface { void MP_Register_EventHandlers() { - sMpEventProcessor->RegisterHandler(MpEvent::UpgradeAdvancement, std::make_shared()); + sMpEventProcessor->RegisterHandler(MpEvent::UpgradeAdvancement, std::make_shared()); sMpEventProcessor->RegisterHandler(MpEvent::GetPlayerRank, std::make_shared()); sMpEventProcessor->RegisterHandler(MpEvent::GetAdvancementRank, std::make_shared()); } diff --git a/src/Event/MpEventProcessor.cpp b/src/Event/MpEventProcessor.cpp index 440df99..6df6653 100644 --- a/src/Event/MpEventProcessor.cpp +++ b/src/Event/MpEventProcessor.cpp @@ -68,7 +68,7 @@ bool MpEventProcessor::Dispatch(MpEvent event, Player* player, std::vector clientError = { std::to_string(static_cast(event)), "No handler registered for event: " + std::to_string(static_cast(event)) }; + std::vector clientError = { "Error", "No handler registered for event: " + std::to_string(static_cast(event)) }; sMpClientDispatcher->Dispatch(MpClientEvent::Error, player, clientError); MpLogger::warn("No handler registered for event: {}", event); return false; diff --git a/src/MpConstants.h b/src/MpConstants.h index 944618f..64bb768 100644 --- a/src/MpConstants.h +++ b/src/MpConstants.h @@ -1,11 +1,112 @@ - #ifndef MP_CONSTANTS_H #define MP_CONSTANTS_H +#include "AdvancementMgr.h" + namespace MpConstants { + // Spell IDs for passive stat and resist bonuses + constexpr int TITANS_STRENGTH_AURA = 80000001; // strength + constexpr int STEEL_FORGED_AURA = 80000002; // stamina + constexpr int CELESTIAL_GRACE_AURA = 80000003; // spirit + constexpr int FORBIDDEN_KNOWLEDGE_AURA = 80000004; // intellect + constexpr int SPECTRAL_REFLEXES_AURA = 80000005; // agility + constexpr int ELDRITCH_BARRIER_AURA = 80000006; // arcane resistance + constexpr int HELLFIRE_SHIELDING_AURA = 80000007; // fire resistance + constexpr int PRIMAL_ENDURACE_AURA = 80000008; // nature resistance + constexpr int LICHS_BANE_AURA = 80000009; // shadow resistance + constexpr int GLACIAL_FORTRESS_AURA = 80000010; // frost resistance + + /** + * @brief Adds a static method for looking up the corect advancement aura based on the advancement type. + * + * @param advancement + * @return int + */ + static int GetAdvancementAura(MpAdvancements advancement) + { + switch (advancement) + { + case MpAdvancements::MP_ADV_INTELLECT: + return MpConstants::FORBIDDEN_KNOWLEDGE_AURA; + case MpAdvancements::MP_ADV_SPIRIT: + return MpConstants::CELESTIAL_GRACE_AURA; + case MpAdvancements::MP_ADV_STRENGTH: + return MpConstants::TITANS_STRENGTH_AURA; + case MpAdvancements::MP_ADV_AGILITY: + return MpConstants::SPECTRAL_REFLEXES_AURA; + case MpAdvancements::MP_ADV_STAMINA: + return MpConstants::STEEL_FORGED_AURA; + case MpAdvancements::MP_ADV_RESIST_ARCANE: + return MpConstants::ELDRITCH_BARRIER_AURA; + case MpAdvancements::MP_ADV_RESIST_FIRE: + return MpConstants::HELLFIRE_SHIELDING_AURA; + case MpAdvancements::MP_ADV_RESIST_NATURE: + return MpConstants::PRIMAL_ENDURACE_AURA; + case MpAdvancements::MP_ADV_RESIST_FROST: + return MpConstants::GLACIAL_FORTRESS_AURA; + case MpAdvancements::MP_ADV_RESIST_SHADOW: + return MpConstants::LICHS_BANE_AURA; + default: + return 0; + } + } + + // Spells used for learning how to make items used for advancement. + constexpr int SPELL_ORE_FUSION = 150000; + constexpr int SPELL_CLOTH_FUSION = 150001; + constexpr int SPELL_LEATHER_FUSION = 150002; + constexpr int SPELL_ALCHEMY_FUSION = 150003; + constexpr int SPELL_GEM_FUSION = 150004; + constexpr int SPELL_ESSENCE_FUSION = 150005; + constexpr int SPELL_COLD_FUSION = 150006; + constexpr int SPELL_FLAME_FUSION = 150007; + constexpr int SPELL_ARCANE_FUSION = 150008; + constexpr int SPELL_DARK_FUSION = 150009; + constexpr int SPELL_EARTH_FUSION = 150010; + constexpr int SPELL_ORE_FUSION_RANK_2 = 150011; + constexpr int SPELL_CLOTH_FUSION_RANK_2 = 150012; + constexpr int SPELL_LEATHER_FUSION_RANK_2 = 150013; + constexpr int SPELL_ALCHEMY_FUSION_RANK_2 = 150014; + constexpr int SPELL_GEM_FUSION_RANK_2 = 150015; + constexpr int SPELL_ESSENCE_FUSION_RANK_2 = 150016; + constexpr int SPELL_COLD_FUSION_RANK_2 = 150017; + constexpr int SPELL_FLAME_FUSION_RANK_2 = 150018; + constexpr int SPELL_ARCANE_FUSION_RANK_2 = 150019; + constexpr int SPELL_DARK_FUSION_RANK_2 = 150020; + constexpr int SPELL_EARTH_FUSION_RANK_2 = 150021; + + // New dropping unique items for mythic plus constexpr int ANCIENT_DICE = 911000; - constexpr int DARK_SPIKE = 911001; + constexpr int DARK_SPIKE = 911001; + constexpr int VEILSTONE = 911002; + + // Item IDs for fused materials used in advancement crafting + constexpr int FUSED_RARE_ORE = 911003; + constexpr int FUSED_MYTHIC_ORE = 911004; + constexpr int FUSED_RARE_CLOTH = 911005; + constexpr int FUSED_MYTHIC_CLOTH = 911006; + constexpr int FUSED_RARE_LEATHER = 911007; + constexpr int FUSED_MYTHIC_LEATHER = 911008; + constexpr int FUSED_RARE_ALCHEMY = 911009; + constexpr int FUSED_MYTHIC_ALCHEMY = 911010; + constexpr int FUSED_RARE_GEM = 911011; + constexpr int FUSED_MYTHIC_GEM = 911012; + constexpr int FUSED_RARE_ESSENCE = 911013; + constexpr int FUSED_MYTHIC_ESSENCE = 911014; + constexpr int FUSED_RARE_ICE_STONE = 911015; + constexpr int FUSED_MYTHIC_ICE_STONE = 911016; + constexpr int FUSED_RARE_INFERNAL_STONE = 911017; + constexpr int FUSED_MYTHIC_INFERNAL_STONE = 911018; + constexpr int FUSED_RARE_ARCANE_CRYSTAL = 911019; + constexpr int FUSED_MYTHIC_ARCANE_CRYSTAL = 911020; + constexpr int FUSED_RARE_DARK_CRYSTAL = 911021; + constexpr int FUSED_MYTHIC_DARK_CRYSTAL = 911022; + constexpr int FUSED_RARE_EARTH_STONE = 911023; + constexpr int FUSED_MYTHIC_EARTH_STONE = 911024; + + // Shadowy Remains + constexpr int SHADOWY_REMAINS = 911100; } #endif diff --git a/src/MpDataStore.cpp b/src/MpDataStore.cpp index c03ed08..80185ea 100644 --- a/src/MpDataStore.cpp +++ b/src/MpDataStore.cpp @@ -135,7 +135,7 @@ void MpDataStore::RemoveGroupData(Group *group) { MpLogger::debug("RemoveGroupData for group {}", group->GetGUID().GetCounter()); _groupData->erase(group->GetGUID()); - CharacterDatabase.Execute("DELETE FROM group_difficulty WHERE guid = {}) ", group->GetGUID().GetCounter()); + CharacterDatabase.Execute("DELETE FROM group_difficulty WHERE guid = {}", group->GetGUID().GetCounter()); } // Adds PlayerData related to MythicRun Status to map @@ -220,45 +220,61 @@ MpScaleFactor MpDataStore::GetScaleFactor(int32 mapId, int32 difficulty) const { return _scaleFactors->at(key); } + // Just send back untouched bonus database will override. return MpScaleFactor{ - .dmgBonus = 3, - .healthBonus = 2, - .maxDamageBonus = 30 + .meleeBonus = 1.0f, + .healthBonus = 1.0f, + .spellBonus = 1.0f, + .healBonus = 1.0f }; } -int32 MpDataStore::GetHealthScaleFactor(int32 mapId, int32 difficulty) const { +float MpDataStore::GetHealthScaleFactor(int32 mapId, int32 difficulty) const { return GetScaleFactor(mapId, difficulty).healthBonus; } -int32 MpDataStore::GetDamageScaleFactor(int32 mapId, int32 difficulty) const { - return GetScaleFactor(mapId, difficulty).dmgBonus; +float MpDataStore::GetMeleeScaleFactor(int32 mapId, int32 difficulty) const { + return GetScaleFactor(mapId, difficulty).meleeBonus; } -int32 MpDataStore::GetSpellScaleFactor(int32 mapId, int32 difficulty) const { +float MpDataStore::GetSpellScaleFactor(int32 mapId, int32 difficulty) const { return GetScaleFactor(mapId, difficulty).spellBonus; } -int32 MpDataStore::GetMaxDamageScaleFactor(int32 mapId, int32 difficulty) const { - return GetScaleFactor(mapId, difficulty).maxDamageBonus; +float MpDataStore::GetHealScaleFactor(int32 mapId, int32 difficulty) const { + return GetScaleFactor(mapId, difficulty).healBonus; } -void MpDataStore::SetHealthScaleFactor(int32 mapId, int32 difficulty, int32 newValue) { +uint32 MpDataStore::GetPlayerHealthAvg(uint32 level) const { + if (_playerHealthAvg.contains(level)) { + return _playerHealthAvg.at(level); + } + return 0; +} + +void MpDataStore::SetHealScaleFactor(int32 mapId, int32 difficulty, float newValue) { + auto key = GetScaleFactorKey(mapId, difficulty); + if (_scaleFactors && _scaleFactors->contains(key)) { + _scaleFactors->at(key).healBonus = newValue; + } +} + +void MpDataStore::SetHealthScaleFactor(int32 mapId, int32 difficulty, float newValue) { auto key = GetScaleFactorKey(mapId, difficulty); if (_scaleFactors && _scaleFactors->contains(key)) { _scaleFactors->at(key).healthBonus = newValue; } } -void MpDataStore::SetDamageScaleFactor(int32 mapId, int32 difficulty, int32 newValue) { +void MpDataStore::SetMeleeScaleFactor(int32 mapId, int32 difficulty, float newValue) { auto key = GetScaleFactorKey(mapId, difficulty); if (_scaleFactors && _scaleFactors->contains(key)) { - _scaleFactors->at(key).dmgBonus = newValue; + _scaleFactors->at(key).meleeBonus = newValue; } } -void MpDataStore::SetSpellScaleFactor(int32 mapId, int32 difficulty, int32 newValue) { +void MpDataStore::SetSpellScaleFactor(int32 mapId, int32 difficulty, float newValue) { auto key = GetScaleFactorKey(mapId, difficulty); if (_scaleFactors && _scaleFactors->contains(key)) { _scaleFactors->at(key).spellBonus = newValue; @@ -269,7 +285,7 @@ int32 MpDataStore::LoadScaleFactors() { _scaleFactors->clear(); // 0 1 2 3 4 5 - QueryResult result = WorldDatabase.Query("SELECT mapId, dmg_bonus, spell_bonus, hp_bonus, difficulty, max FROM mp_scale_factors"); + QueryResult result = WorldDatabase.Query("SELECT mapId, melee_bonus, spell_bonus, heal_bonus, hp_bonus, difficulty FROM mp_scale_factors"); if (!result) { MpLogger::error("Failed to load mythic scale factors from database"); return 0; @@ -278,17 +294,17 @@ int32 MpDataStore::LoadScaleFactors() { do { Field* fields = result->Fetch(); uint32 mapId = fields[0].Get(); - int32 damageBonus = fields[1].Get(); - int32 spellBonus = fields[2].Get(); - int32 healthBonus = fields[3].Get(); - int32 difficulty = fields[4].Get(); - int32 maxDamageBonus = fields[5].Get(); + float meleeBonus = fields[1].Get(); + float spellBonus = fields[2].Get(); + float healBonus = fields[3].Get(); + float healthBonus = fields[4].Get(); + int32 difficulty = fields[5].Get(); MpScaleFactor scaleFactor = { - .dmgBonus = damageBonus, + .meleeBonus = meleeBonus, .healthBonus = healthBonus, .spellBonus = spellBonus, - .maxDamageBonus = maxDamageBonus + .healBonus = healBonus }; _scaleFactors->emplace(GetScaleFactorKey(mapId, difficulty), scaleFactor); @@ -298,6 +314,45 @@ int32 MpDataStore::LoadScaleFactors() { return int32(_scaleFactors->size()); } +void MpDataStore::LoadPlayerHealthAvg() { + _playerHealthAvg.clear(); + + std::string_view query = R"( + SELECT + Level, + ROUND(CASE + WHEN Level BETWEEN 1 AND 30 THEN ((AVG(Stamina) - 20) * 10 + AVG(BaseHP) + 20) * 1.0 + WHEN Level BETWEEN 31 AND 50 THEN ((AVG(Stamina) - 20) * 10 + AVG(BaseHP) + 20) * 1.3 + WHEN Level BETWEEN 51 AND 59 THEN ((AVG(Stamina) - 20) * 10 + AVG(BaseHP) + 20) * 1.6 + WHEN Level BETWEEN 60 AND 69 THEN ((AVG(Stamina) - 20) * 10 + AVG(BaseHP) + 20) * 2.0 + WHEN Level BETWEEN 70 AND 79 THEN ((AVG(Stamina) - 20) * 10 + AVG(BaseHP) + 20) * 2.5 + WHEN Level BETWEEN 80 AND 84 THEN ((AVG(Stamina) - 20) * 10 + AVG(BaseHP) + 20) * 3.0 + WHEN Level >= 85 THEN ((AVG(Stamina) - 20) * 10 + AVG(BaseHP) + 20) * 4.0 + ELSE ((AVG(Stamina) - 20) * 10 + AVG(BaseHP) + 20) + END) AS BaseHealth + FROM + player_class_stats + GROUP BY + Level + ORDER BY + Level; + )"; + + if (QueryResult result = WorldDatabase.Query(query.data())) { + do { + Field* fields = result->Fetch(); + uint32 level = fields[0].Get(); + uint32 baseHealth = fields[1].Get(); + + _playerHealthAvg[level] = baseHealth; + + } while (result->NextRow()); + + } else { + MpLogger::error("Failed to load player health averages from database"); + } +} + /** * Database Calls below for storing player data. * @todo refactor to use prepared statements diff --git a/src/MpDataStore.h b/src/MpDataStore.h index ed24b3e..01874ef 100644 --- a/src/MpDataStore.h +++ b/src/MpDataStore.h @@ -143,17 +143,22 @@ struct MpGroupData }; +/** + * @brief Struct used for internal scaling of mythic+ difficulty. Fine-tuned in + * database. + */ struct MpScaleFactor { - int32 dmgBonus; - int32 healthBonus; - int32 spellBonus; - int32 maxDamageBonus; + float meleeBonus; + float spellBonus; + float healBonus; + float healthBonus; std::string ToString() const { - return "MpScaleFactor: { dmgBonus: " + std::to_string(dmgBonus) + + return "MpScaleFactor: { meleeBonus: " + std::to_string(meleeBonus) + ", healthBonus: " + std::to_string(healthBonus) + - ", spellBonus: " + std::to_string(spellBonus) + "}"; + ", spellBonus: " + std::to_string(spellBonus) + + ", healBonus: " + std::to_string(healBonus) + "}"; } }; @@ -323,6 +328,10 @@ private: // use to mimic pattern normals scale to heroic (loaded at server start) std::unique_ptr,MpScaleFactor>> _scaleFactors; // {mapId,difficulty} + // Player mapping of level to average amount of health for that level, this is used for scaling against + // percentages to more consistently scale damage from spells and healing from creatures. + std::unordered_map _playerHealthAvg; // level -> avg health + // Single creature multipliers used to scale creatures individually that may need tuned up or down. // std::unique_ptr> _creatureOverrides; @@ -377,15 +386,19 @@ public: std::vector GetUnscaledCreatures(uint32 mapId, uint32 instanceId); // Scale factors are used to determine a base bonus for enemies base on the instance difficulty - int32 GetHealthScaleFactor(int32 mapId, int32 difficulty) const; - int32 GetDamageScaleFactor(int32 mapId, int32 difficulty) const; - int32 GetMaxDamageScaleFactor(int32 mapId, int32 difficulty) const; - int32 GetSpellScaleFactor(int32 mapId, int32 difficulty) const; + float GetHealthScaleFactor(int32 mapId, int32 difficulty) const; + float GetMeleeScaleFactor(int32 mapId, int32 difficulty) const; + float GetSpellScaleFactor(int32 mapId, int32 difficulty) const; + float GetHealScaleFactor(int32 mapId, int32 difficulty) const; MpScaleFactor GetScaleFactor(int32 mapId, int32 difficulty) const; - void SetDamageScaleFactor(int32 mapId, int32 difficulty, int32 value); - void SetHealthScaleFactor(int32 mapId, int32 difficulty, int32 value); - void SetSpellScaleFactor(int32 mapId, int32 difficulty, int32 value); + void SetMeleeScaleFactor(int32 mapId, int32 difficulty, float value); + void SetHealthScaleFactor(int32 mapId, int32 difficulty, float value); + void SetSpellScaleFactor(int32 mapId, int32 difficulty, float value); + void SetHealScaleFactor(int32 mapId, int32 difficulty, float value); + + // Retrieves the average players hp pool for a player level + uint32 GetPlayerHealthAvg(uint32 level) const; // Individual Creature Scaling Multipliers // void AddCreatureOverride(uint32 entry, CreatureOverride* override); @@ -401,6 +414,9 @@ public: // Used at initial server load int32 LoadScaleFactors(); + // Load the player health average from the database + void LoadPlayerHealthAvg(); + // Database API calls void DBUpdatePlayerInstanceData(ObjectGuid playerGuid, MpDifficulty difficulty, uint32 mapId = 0, uint32 instanceId = 0, uint32 deaths = 0); diff --git a/src/MythicPlus.cpp b/src/MythicPlus.cpp index fe96356..e2152a4 100644 --- a/src/MythicPlus.cpp +++ b/src/MythicPlus.cpp @@ -146,6 +146,12 @@ bool MythicPlus::IsCreatureEligible(Creature* creature) MpLogger::debug("Creature {} is an NPC Bot, do not scale", creature->GetName()); return false; } + + if(creature->GetBotOwner()) { + MpLogger::debug("Creature is owned by a NPC Bot {} skip scaling creature: {}", creature->GetBotOwner()->GetName(), creature->GetName()); + return false; + } + #endif // Check for NPC-related flags (vendor, gossip, quest giver, trainer, etc.) @@ -264,6 +270,7 @@ void MythicPlus::ScaleCreature(uint8 level, Creature* creature, MpMultipliers* m cInfo->unit_class ); + // Scale the creatures base health uint32 basehp = stats->BaseHealth[EXPANSION_WRATH_OF_THE_LICH_KING]; uint32 health = CalculateNewHealth(creature, cInfo, mapId, difficulty, basehp, multipliers->health); @@ -276,6 +283,7 @@ void MythicPlus::ScaleCreature(uint8 level, Creature* creature, MpMultipliers* m /** * @TODO: Figure out mana later for unit_types 2 and 8 */ + // Scale the creatures mana pool uint32 mana = uint32(std::ceil(stats->BaseMana * cInfo->ModMana)); creature->SetCreateMana(mana); creature->SetMaxPower(POWER_MANA, mana); @@ -289,30 +297,43 @@ void MythicPlus::ScaleCreature(uint8 level, Creature* creature, MpMultipliers* m creature->SetModifierValue(UNIT_MOD_MANA, BASE_VALUE, (float)mana * 3.0f); } + // Scale the creatures damage + MpInstanceData *instanceData = sMpDataStore->GetInstanceData(creature->GetMapId(), creature->GetInstanceId()); - int32 meleeDamage = sMpDataStore->GetDamageScaleFactor(creature->GetMapId(), instanceData->difficulty); - if(creature->IsDungeonBoss() || creature->GetEntry() == 23682) { - // Give the boss an increase in casting speed. - creature->SetFloatValue(UNIT_MOD_CAST_SPEED, 1.20f); - } + // int32 meleeDamage = sMpDataStore->GetMeleeScaleFactor(creature->GetMapId(), instanceData->difficulty); // Calculate the level difference - float levelDifference = creature->GetLevel() - origLevel; + // float levelDifference = creature->GetLevel() - origLevel; // New formula with adjusted divisor for smoother scaling float scalingFactor; - uint32 ap = uint32(sMythicPlus->meleeAttackPowerStart - sMythicPlus->meleeAttackPowerDampener); - uint32 rangeAp = irand(215, 357); + // uint32 ap = uint32(sMythicPlus->meleeAttackPowerStart - sMythicPlus->meleeAttackPowerDampener); - scalingFactor = CalculateScaling(levelDifference, meleeDamage); - ap = uint32(stats->AttackPower * scalingFactor); - rangeAp = uint32(rangeAp * scalingFactor); + // cInfo->DifficultyEntry + + // Calculate base scaling first, then apply creature type modifier + // float baseScaling = CalculateScaling(levelDifference, meleeDamage); + + // if (creature->IsDungeonBoss() || creature->isElite() || cInfo->rank >= CREATURE_ELITE_ELITE) { + // // Full scaling for bosses and elites + // scalingFactor = baseScaling; + // } else { + // // Reduced scaling for normal creatures to achieve ~60% of elite damage + // scalingFactor = baseScaling * 0.6f; + // } + + // Handle new melee/range scaling with simple formula (for simplicity range will just be 80% of melee bonus) + float meleeMultiplier = sMpDataStore->GetMeleeScaleFactor(creature->GetMapId(), instanceData->difficulty); + + // Scale up the attack power based on the instance set in the database difficulty table. + uint32 ap = std::ceil(stats->AttackPower * meleeMultiplier); + uint32 rangeAp = std::ceil(stats->RangedAttackPower * meleeMultiplier * 0.5f); MpCreatureData* creatureData = sMpDataStore->GetCreatureData(creature->GetGUID()); if(creatureData) { creatureData->NewAttackPower = ap; - creatureData->AttackPowerScaleMultiplier = scalingFactor; + creatureData->AttackPowerScaleMultiplier = meleeMultiplier; } // Set scaled attack power @@ -321,7 +342,10 @@ void MythicPlus::ScaleCreature(uint8 level, Creature* creature, MpMultipliers* m // set the base weapon damage creature->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, stats->BaseDamage[EXPANSION_WRATH_OF_THE_LICH_KING], 0); - creature->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, stats->BaseDamage[EXPANSION_WRATH_OF_THE_LICH_KING], 0); + creature->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, stats->BaseDamage[EXPANSION_WRATH_OF_THE_LICH_KING] * 1.5f, 0); + + creature->SetBaseWeaponDamage(RANGED_ATTACK, MINDAMAGE, stats->BaseDamage[EXPANSION_WRATH_OF_THE_LICH_KING] * 0.6f, 0); + creature->SetBaseWeaponDamage(RANGED_ATTACK, MAXDAMAGE, stats->BaseDamage[EXPANSION_WRATH_OF_THE_LICH_KING] * 1.0f, 0); // Update all stats to apply the new damage values creature->UpdateAllStats(); @@ -334,7 +358,6 @@ void MythicPlus::ScaleCreature(uint8 level, Creature* creature, MpMultipliers* m int32 MythicPlus::ScaleDamageSpell(SpellInfo const * spellInfo, uint32 damage, MpCreatureData* creatureData, Creature* creature, Unit* target, float damageMultiplier) { - if (!spellInfo) { MpLogger::error("Invalid spell info ScaleDamageSpell()"); return damage; @@ -343,12 +366,30 @@ int32 MythicPlus::ScaleDamageSpell(SpellInfo const * spellInfo, uint32 damage, M if(!creatureData) { // this is probably a summoned object or totem so going to cheat here and just use the flat modifer - // Handle totems that do some nasty things to us Slave Pens anyone - if(creature->IsTotem()) { + // Handle totems and summons - scale based on owner's elite status + if(creature->IsTotem() || creature->IsSummon()) { Unit* owner = creature->GetOwner(); - if(owner) { - float lvlDmgBonus = float(85 - owner->GetLevel() / 10.0f); - return int32(damage * lvlDmgBonus * damageMultiplier); + if(owner && owner->IsCreature()) { + Creature* ownerCreature = owner->ToCreature(); + MpInstanceData *instanceData = sMpDataStore->GetInstanceData(creature->GetMapId(), creature->GetInstanceId()); + int32 spellBonus = sMpDataStore->GetSpellScaleFactor(creature->GetMapId(), instanceData->difficulty); + + // Calculate level difference (use owner's scaling) + float levelDifference = ownerCreature->GetLevel() - 80; // Assume original level 80 for simplicity + + // Apply same scaling rules as owner + float baseTotemScaling = CalculateScaling(levelDifference, spellBonus); + + float scalingFactor; + if (ownerCreature->IsDungeonBoss() || ownerCreature->isElite() || ownerCreature->GetCreatureTemplate()->rank >= CREATURE_ELITE_ELITE) { + // Elite owner - use elite spell scaling + scalingFactor = baseTotemScaling * 0.85f; + } else { + // Normal owner - use normal creature spell scaling + scalingFactor = baseTotemScaling * 0.5f; + } + + return int32(damage * scalingFactor * damageMultiplier); } else { return damage * damageMultiplier; } @@ -367,20 +408,21 @@ int32 MythicPlus::ScaleDamageSpell(SpellInfo const * spellInfo, uint32 damage, M MpInstanceData *instanceData = sMpDataStore->GetInstanceData(creature->GetMapId(), creature->GetInstanceId()); int32 spellBonus = sMpDataStore->GetSpellScaleFactor(creature->GetMapId(), instanceData->difficulty); - // if((creature->IsDungeonBoss() && creature->isElite()) || creature->GetEntry() == 23682) { - // spellBonus *= 1.15; - // } // Calculate the level difference float levelDifference = creature->GetLevel() - originalLevel; - // New formula with adjusted divisor for smoother scaling - // float scalingFactor = 1 + (std::log2(levelDifference + 1) * (float(spellBonus))); + // Calculate base spell scaling first, then apply creature type modifier + float baseSpellScaling = CalculateScaling(levelDifference, spellBonus); - float scalingFactor = CalculateScaling(levelDifference, spellBonus); - - // float scalingFactor = pow(float((creature->GetLevel() - originalLevel) / 10.0f ), float(spellBonus) / 5.0f); - // MpLogger::debug("Creature {} original level: {} New Level{} and Scaling level {}", creature->GetName(), originalLevel, creature->GetLevel(), scalingFactor); + float scalingFactor; + if (creature->IsDungeonBoss() || creature->isElite() || creature->GetCreatureTemplate()->rank >= CREATURE_ELITE_ELITE) { + // Reduced scaling for elite/boss spells to prevent them from hitting too hard + scalingFactor = baseSpellScaling * 0.85f; + } else { + // Much more reduced scaling for normal creature spells to achieve ~60% of elite damage + scalingFactor = baseSpellScaling * 0.5f; + } int32 totalDamage = 0; auto effects = spellInfo->GetEffects(); @@ -440,7 +482,6 @@ int32 MythicPlus::ScaleDamageSpell(SpellInfo const * spellInfo, uint32 damage, M int32 MythicPlus::ScaleHealSpell(SpellInfo const * spellInfo, uint32 heal, MpCreatureData* creatureData, Creature* creature, Creature* /* target */, float healMultiplier) { - if (!spellInfo) { MpLogger::error("Invalid spell info ScaleHealSpell()"); return 0; @@ -467,7 +508,8 @@ int32 MythicPlus::ScaleHealSpell(SpellInfo const * spellInfo, uint32 heal, MpCre float levelDifference = creature->GetLevel() - originalLevel; float spellBonus = sMpDataStore->GetSpellScaleFactor(creature->GetMapId(), creature->GetInstanceId()); - float scalingFactor = CalculateScaling(levelDifference, spellBonus, 2.5f); + // Reduced scaling for heals to prevent them from being too powerful + float scalingFactor = CalculateScaling(levelDifference, spellBonus * 0.4f, 1.8f); // Reduced scaling factor and constant MpLogger::debug(" >>> Spell {} healed scaled from for spell New Heal: {} using: scaling Factor: {} and damage Multi: {}",spellInfo->SpellName[0], heal, scalingFactor, healMultiplier); return int32(heal * scalingFactor * healMultiplier); @@ -477,7 +519,6 @@ void MythicPlus::GroupReset(Group* /*group*/, Map* /* map */) { // Stubbed out for later implementation } - bool MythicPlus::IsFinalBoss(Creature* creature) { std::array finalBosses = { // --- WoW Classic Dungeons --- @@ -638,46 +679,74 @@ float GetTypeHealthModifier(int32 Rank) // This takes the orignal health and scales flat based on the factor then applies the configuration modifier from the conf file uint32 CalculateNewHealth(Creature* creature, CreatureTemplate const* cInfo, uint32 mapId, MpDifficulty difficulty, uint32 origHealth, float confHPMod) { + // int32 rank = 0; if(cInfo && cInfo->rank > 0) { rank = cInfo->rank; } + // These Factors that increase or decrease health based on different settings applied to the creature + + // Health Variation is used to create some random element to HP so not all creatures of the same level + // have the same HP for more variety. float healthVariation; - // if(creature->IsPet() || creature->IsSummon() || creature->IsTotem()) { - // return origHealth; - // } - + // This is the fine grained hpScaleFactor set for the instance (and/or) creature overrides in the database. int32 hpScaleFactor = sMpDataStore->GetHealthScaleFactor(mapId, difficulty); // Add some variance to the healthpool so enemies are not all the same - if(creature->IsDungeonBoss() || creature->GetEntry() == HEADLESS_HORSEMAN || creature->isWorldBoss()) { // Is a boss of some kind - healthVariation = frand(1.1f, 1.2f); - } else if(creature->isElite() || cInfo->rank == CREATURE_ELITE_RARE) { // Is Elite Mob - healthVariation = frand(1.0f, 1.10f); - hpScaleFactor *= 0.90; - } else if(creature->IsSummon() || creature->IsPet() || creature->IsTotem()) { // Is a pet or summon + if(creature->IsDungeonBoss() || creature->isWorldBoss() || creature->isElite() || cInfo->rank == CREATURE_ELITE_RARE) { + healthVariation = frand(1.0f, 1.15f); + } else { // This addresses Normals and other trash from getting to big a HP bonus healthVariation = frand(1.0f, 1.05f); - hpScaleFactor *= 0.65; - } else { + hpScaleFactor *= 0.40; + } + + // Add in special overrides here as necessary: + if(creature->GetEntry() == HEADLESS_HORSEMAN) { healthVariation = frand(1.0f, 1.1f); - hpScaleFactor *= 0.55; } float unitTypeMod = GetTypeHealthModifier(rank); - uint32 basehp = uint32(std::ceil(origHealth * unitTypeMod * healthVariation)); + uint32 basehp = uint32(std::ceil(origHealth * healthVariation)); + /** + * @brief Calculating the final creature health encompasses all the potential modifiers + * CreatureTemplate.HealthModifier (ModHealth) - Creatures that are capable of being in a Heroic instance get a boost here + * even though they are the same. In this case we allow + * + * hpScaleFactor: allows to tweak the bonus modifier more directly at a creature or instance level, since + * you can not override it in cInfo directly as it is loaded statically from database + * + * confHPMod: is from the mythic settings directly. + */ if(cInfo->ModHealth > 0.0f) { return uint32(basehp * (cInfo->ModHealth + hpScaleFactor) * confHPMod); + } else { - return uint32(basehp * (hpScaleFactor) * confHPMod); + return uint32(basehp * hpScaleFactor * confHPMod); } } -// Calculates a logarithmic growth curve using scaling factor of percentages increase 50 = 1.5, 100 = 2.0,... this allows for fine grain tuning per instance. +// Calculates a balanced growth curve that provides good scaling across all level ranges float CalculateScaling(int levelDifference, float scaleFactor, float constant, float growthFactor) { - float scaling = constant * std::pow(2.0f, levelDifference / growthFactor) * (1 + (scaleFactor / 100.0f)); + float levelMultiplier; + + if (levelDifference <= 0) { + // High-level creatures need a minimum boost + levelMultiplier = 1.5f; // Minimum 50% boost for near-level or higher creatures + } else if (levelDifference <= 10) { + // Moderate scaling for small level differences + levelMultiplier = 1.5f + (levelDifference * 0.2f); // 1.5x to 3.5x + } else if (levelDifference <= 30) { + // Higher scaling for medium level differences + levelMultiplier = 3.5f + ((levelDifference - 10) * 0.15f); // 3.5x to 6.5x + } else { + // Cap extreme scaling for very low level creatures + levelMultiplier = 6.5f + std::min((levelDifference - 30) * 0.05f, 3.5f); // Cap at 10x + } + + float scaling = constant * levelMultiplier * (1 + (scaleFactor / 100.0f)); return scaling; } @@ -699,4 +768,3 @@ float GetTypeDamageModifier(int32 Rank) return sWorld->getRate(RATE_CREATURE_ELITE_ELITE_DAMAGE); } } - diff --git a/src/MythicPlus_loader.cpp b/src/MythicPlus_loader.cpp index 5525028..415acf3 100755 --- a/src/MythicPlus_loader.cpp +++ b/src/MythicPlus_loader.cpp @@ -1,5 +1,6 @@ #include "MpScheduler.h" #include "MpLogger.h" +#include "Spells/AdvancmentSpells.cpp" // Creature Overrides enum { @@ -8,7 +9,6 @@ enum { // This adds schedulers for use across scripts scoped to MythicPlus void Add_MP_Schedulers() { - MpLogger::debug("Add_MP_Schedulers()"); new MpScheduler_WorldScript(); } @@ -23,20 +23,25 @@ void Add_MP_UnitScripts(); void Add_MP_WorldScripts(); void Add_MP_PlayerMessageEvents(); +// Spell Scripts +void AddSC_AdvancementSpells(); + void Addmod_mythic_plusScripts() { Add_MP_AllCreatureScripts(); Add_MP_AllMapScripts(); Add_MP_CommandScripts(); Add_MP_GlobalScripts(); - // Add_MP_GroupScripts(); Add_MP_PlayerScripts(); Add_MP_UnitScripts(); Add_MP_WorldScripts(); Add_MP_Schedulers(); Add_MP_PlayerMessageEvents(); - // new Ragefire_Bazzalan_Mythic(); + // Spell Scripts + AddSC_AdvancementSpells(); + // new Ragefire_Bazzalan_Mythic(); + // Add_MP_GroupScripts(); // list of boss / creature event handlers // new Ragefire_Bazzalan_Mythic(RAGEFIRE_BAZZALAN); diff --git a/src/Scripts/CommandScript.cpp b/src/Scripts/CommandScript.cpp index 64f376c..61e8ef5 100644 --- a/src/Scripts/CommandScript.cpp +++ b/src/Scripts/CommandScript.cpp @@ -157,7 +157,7 @@ public: group->SetDungeonDifficulty(DUNGEON_DIFFICULTY_NORMAL); } else { - handler->PSendSysMessage("|cFFFF0000 Invalid difficulty level. Expected values are 'mythic', 'legendary', or 'ascendant'."); + handler->PSendSysMessage("|cFFFF0000 Invalid difficulty level. Expected values are 'normal', 'heroic', 'mythic', 'legendary', or 'ascendant'."); return true; } @@ -311,8 +311,8 @@ public: auto groupData = sMpDataStore->GetGroupData(player->GetGroup()->GetGUID()); if(groupData) { - uint32 value = std::stoi(args[0]); - sMpDataStore->SetDamageScaleFactor(player->GetMapId(), groupData->difficulty, value); + float value = std::stof(args[0]); + sMpDataStore->SetMeleeScaleFactor(player->GetMapId(), groupData->difficulty, value); handler->PSendSysMessage(Acore::StringFormat("Melee scale factor set to: {}", value)); return true; } @@ -339,7 +339,7 @@ public: auto groupData = sMpDataStore->GetGroupData(player->GetGroup()->GetGUID()); if(groupData) { - uint32 value = std::stoi(args[0]); + float value = std::stof(args[0]); sMpDataStore->SetSpellScaleFactor(player->GetMapId(), groupData->difficulty, value); handler->PSendSysMessage(Acore::StringFormat("Spell scale factor set to: {}", value)); return true; @@ -367,7 +367,7 @@ public: auto groupData = sMpDataStore->GetGroupData(player->GetGroup()->GetGUID()); if(groupData) { - uint32 value = std::stoi(args[0]); + float value = std::stof(args[0]); sMpDataStore->SetHealthScaleFactor(player->GetMapId(), groupData->difficulty, value); handler->PSendSysMessage(Acore::StringFormat("Health scale factor set to: {}", value)); return true; diff --git a/src/Scripts/GlobalScript.cpp b/src/Scripts/GlobalScript.cpp index 86712a8..8d99ae1 100644 --- a/src/Scripts/GlobalScript.cpp +++ b/src/Scripts/GlobalScript.cpp @@ -1,5 +1,6 @@ #include "MpLogger.h" #include "MythicPlus.h" +#include "MpConstants.h" #include "ScriptMgr.h" #include "Player.h" #include "Map.h" @@ -11,7 +12,7 @@ public: MythicPlus_GlobalScript() : GlobalScript("MythicPlus_GlobalScript") { } // This adds the mythic+ item scaling to the loot table for enemies - void OnBeforeDropAddItem(Player const* player, Loot& /*loot*/, bool /*canRate*/, uint16 /*lootMode*/, LootStoreItem* LootStoreItem, LootStore const& store) override { + void OnBeforeDropAddItem(Player const* player, Loot& loot, bool /*canRate*/, uint16 /*lootMode*/, LootStoreItem* LootStoreItem, LootStore const& store) override { if(LootStoreItem->itemid == 0) { return; @@ -44,8 +45,30 @@ public: // get the item to scale up ItemTemplate const* origItem = sObjectMgr->GetItemTemplate(LootStoreItem->itemid); if (!origItem) { - MpLogger::warn("Item not found for itemid {} in OnBeforeDropAddItem()", LootStoreItem->itemid); - return; + + // If there is not a scaled up item and the item is a below quality green then set an invalid item_id so it is not added to loot + ItemTemplate const* nonMythicItem = sObjectMgr->GetItemTemplate(LootStoreItem->itemid); + if (nonMythicItem->Quality < 2) { + LootStoreItem->itemid = 0; + return; + } + + // otherwise roll a chance to see a shadowy remains item is provided instead only if there is not already a shadowy remains item on the corpse + bool hasShadowyRemains = false; + for (auto& item : loot.items) { + if(item.itemid == MpConstants::SHADOWY_REMAINS) { + hasShadowyRemains = true; + break; + } + } + + if (!hasShadowyRemains) { + LootStoreItem->itemid = MpConstants::SHADOWY_REMAINS; + return; + } else { + LootStoreItem->itemid = 0; + return; + } } uint32 newItemId = origItem->ItemId + mythicSettings->itemOffset; diff --git a/src/Scripts/PlayerScript.cpp b/src/Scripts/PlayerScript.cpp index 306b7b8..a9b5f83 100644 --- a/src/Scripts/PlayerScript.cpp +++ b/src/Scripts/PlayerScript.cpp @@ -120,6 +120,13 @@ public: // Load the player advancement data for the player when they login sAdvancementMgr->LoadPlayerAdvancements(player); + + // Cast all unique advancement spells + for(uint32 i = 1; i <= 10; ++i) { + uint32 spellId = 80000000 + i; + MpLogger::info("Casting spell {} to player {}", spellId, player->GetName()); + player->AddAura(spellId, player); + } } // When a player is bound to an instance need to make sure they are saved in the data soure to retrieve later. diff --git a/src/Scripts/UnitScript.cpp b/src/Scripts/UnitScript.cpp index 564482c..3e669ed 100644 --- a/src/Scripts/UnitScript.cpp +++ b/src/Scripts/UnitScript.cpp @@ -148,7 +148,7 @@ public: */ switch (eventType) { case MythicPlus::UNIT_EVENT_MELEE: - if(creature->IsDungeonBoss() || creature->GetEntry() == 23682) { + if(creature->IsDungeonBoss() || creature->isWorldBoss() || creature->GetEntry() == 23682) { alteredDmgHeal = damageOrHeal * instanceData->boss.melee; } else { alteredDmgHeal = damageOrHeal * instanceData->creature.melee; @@ -157,25 +157,24 @@ public: break; case MythicPlus::UNIT_EVENT_DOT: case MythicPlus::UNIT_EVENT_SPELL: - if(creature->IsDungeonBoss() || creature->GetEntry() == 23682) { + if(creature->IsDungeonBoss() || creature->isWorldBoss() || creature->GetEntry() == 23682) { if(spellInfo) { + MpLogger::debug("Scaling spell {} using ScaleDamageSpell() Original Damage: {} New Damage: {}", spellInfo->SpellName[0], damageOrHeal, alteredDmgHeal); alteredDmgHeal = sMythicPlus->ScaleDamageSpell(spellInfo, damageOrHeal, sMpDataStore->GetCreatureData(attacker->GetGUID()), creature, target, instanceData->boss.spell); } else { alteredDmgHeal = damageOrHeal * instanceData->boss.spell; + MpLogger::debug("Scaling spell {} using flat modifier Original Damage: {} New Damage: {}", spellInfo->SpellName[0], damageOrHeal, alteredDmgHeal); } } else { if(spellInfo) { + MpLogger::debug("Scaling spell {} using ScaleDamageSpell() Original Damage: {} New Damage: {}", spellInfo->SpellName[0], damageOrHeal, alteredDmgHeal); alteredDmgHeal = sMythicPlus->ScaleDamageSpell(spellInfo, damageOrHeal, sMpDataStore->GetCreatureData(attacker->GetGUID()), creature, target, instanceData->creature.spell); } else { + MpLogger::debug("Scaling spell {} using flat modifier Original Damage: {} New Damage: {}", spellInfo->SpellName[0], damageOrHeal, alteredDmgHeal); alteredDmgHeal = damageOrHeal * instanceData->creature.spell; } } - if(spellInfo) { - MpLogger::debug("Incoming spell New Damage: {}({}) {} hits {} spell: {} ID: {}", alteredDmgHeal, damageOrHeal, attacker->GetName(), target->GetName(), spellInfo->SpellName[0], spellInfo->Id); - } else { - MpLogger::debug("Incoming spell New Damage: {}({}) {} hits {}", alteredDmgHeal, damageOrHeal, attacker->GetName(), target->GetName()); - } break; case MythicPlus::UNIT_EVENT_HEAL: case MythicPlus::UNIT_EVENT_HOT: diff --git a/src/Scripts/WorldScript.cpp b/src/Scripts/WorldScript.cpp index 473b94c..98b9d2f 100644 --- a/src/Scripts/WorldScript.cpp +++ b/src/Scripts/WorldScript.cpp @@ -104,6 +104,9 @@ public: size = sAdvancementMgr->LoadMaterialTypes(); MpLogger::info("Loaded {} material types...", size); + sMpDataStore->LoadPlayerHealthAvg(); + MpLogger::info("Loaded player health averages used for scaling calculations..."); + // Registering event handlers for the Mythic+ events from client MP_Register_EventHandlers(); MpLogger::info("Registered Mythic+ Event Handlers..."); diff --git a/src/Spells/Toughness.cpp b/src/Spells/Toughness.cpp deleted file mode 100644 index 2fb9260..0000000 --- a/src/Spells/Toughness.cpp +++ /dev/null @@ -1,70 +0,0 @@ -// #include "CreatureScript.h" -// #include "PetDefines.h" -// #include "Player.h" -// #include "MpLogger.h" -// #include "SpellAuraEffects.h" -// #include "SpellInfo.h" -// #include "SpellMgr.h" -// #include "SpellScript.h" -// #include "SpellScriptLoader.h" -// #include "UnitAI.h" -// #include "World.h" - - -// class spell_mp_toughness_aura : public AuraScript -// { -// PrepareAuraScript(spell_mp_toughness_aura); - -// void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) -// { -// Player* player = GetTarget()->ToPlayer(); -// if (!player) -// return; - -// MpLogger::info("Applying Advancement Toughness to Player {}", player->GetName()); - -// if (Unit* caster = GetCaster()) -// { -// if (caster->IsPlayer()) -// { -// Player* player = caster->ToPlayer(); - -// // Add 500 Strength -// player->HandleStatModifier(UNIT_MOD_STAT_STRENGTH, TOTAL_VALUE, 500, true); - -// // Apply red glow visual effect -// caster->SendPlaySpellVisual(11674); // Visual ID 11674 for red glow -// } -// } -// } - -// void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) -// { -// LOG_INFO("server.worldserver", "spell_custom_red_glow_strength_aura::HandleEffectRemove"); - -// if (Unit* caster = GetCaster()) -// { -// if (caster->IsPlayer()) -// { -// Player* player = caster->ToPlayer(); - -// // Remove 500 Strength -// player->HandleStatModifier(UNIT_MOD_STAT_STRENGTH, TOTAL_VALUE, 500, false); -// } -// } -// } - -// void Register() override -// { -// LOG_INFO("server.worldserver", "spell_custom_red_glow_strength_aura::Register"); - -// OnEffectApply += AuraEffectApplyFn(spell_custom_red_glow_strength_aura::HandleEffectApply, EFFECT_0, SPELL_AURA_MOD_STAT, AURA_EFFECT_HANDLE_REAL); -// OnEffectRemove += AuraEffectRemoveFn(spell_custom_red_glow_strength_aura::HandleEffectRemove, EFFECT_0, SPELL_AURA_MOD_STAT, AURA_EFFECT_HANDLE_REAL); -// } -// }; - -// void AddSC_spell_custom_red_glow_strength_aura() -// { -// // LOG_INFO("server.loading", "Registering spell custom_red_glow_strength_aura"); -// RegisterSpellScript(spell_custom_red_glow_strength_aura); -// }