diff options
20 files changed, 1017 insertions, 1055 deletions
diff --git a/sql/updates/world/2014_12_01_00_world.sql b/sql/updates/world/2014_12_01_00_world.sql index fed2dbf6ade..6e96a1bfe9a 100644 --- a/sql/updates/world/2014_12_01_00_world.sql +++ b/sql/updates/world/2014_12_01_00_world.sql @@ -1,423 +1,423 @@ DELETE FROM `playercreateinfo_action`; INSERT INTO `playercreateinfo_action` (`race`, `class`, `button`, `action`, `type`) VALUES -('10', '10', '0', '100780', '0'), -('10', '10', '9', '129597', '0'), -('10', '10', '72', '100780', '0'), -('10', '10', '81', '129597', '0'), -('10', '8', '0', '44614', '0'), -('10', '8', '9', '28730', '0'), -('10', '9', '0', '686', '0'), -('10', '9', '9', '28730', '0'), -('10', '9', '10', '10', '48'), -('10', '2', '0', '35395', '0'), -('10', '2', '9', '155145', '0'), -('10', '3', '0', '3044', '0'), -('10', '3', '9', '80483', '0'), -('10', '3', '10', '9', '48'), -('10', '3', '11', '982', '0'), -('10', '1', '0', '88163', '0'), -('10', '1', '1', '78', '0'), -('10', '1', '9', '69179', '0'), -('10', '1', '72', '88163', '0'), -('10', '1', '73', '78', '0'), -('10', '1', '81', '69179', '0'), -('10', '4', '0', '1752', '0'), -('10', '4', '9', '25046', '0'), -('10', '5', '0', '585', '0'), -('10', '5', '9', '28730', '0'), -('4', '6', '0', '6603', '0'), -('4', '6', '1', '49576', '0'), -('4', '6', '2', '45477', '0'), -('4', '6', '3', '45462', '0'), -('4', '6', '4', '50842', '0'), -('4', '6', '5', '47541', '0'), -('4', '6', '10', '58984', '0'), -('4', '6', '83', '58984', '0'), -('7', '6', '0', '6603', '0'), -('7', '6', '1', '49576', '0'), -('7', '6', '2', '45477', '0'), -('7', '6', '3', '45462', '0'), -('7', '6', '4', '50842', '0'), -('7', '6', '5', '47541', '0'), -('7', '6', '10', '20589', '0'), -('7', '6', '72', '6603', '0'), -('7', '6', '83', '117', '128'), -('7', '6', '84', '6603', '0'), -('7', '6', '96', '6603', '0'), -('7', '6', '108', '6603', '0'), -('3', '6', '0', '6603', '0'), -('3', '6', '1', '49576', '0'), -('3', '6', '2', '45477', '0'), -('3', '6', '3', '45462', '0'), -('3', '6', '4', '50842', '0'), -('3', '6', '5', '47541', '0'), -('1', '6', '0', '6603', '0'), -('1', '6', '1', '49576', '0'), -('1', '6', '2', '45477', '0'), -('1', '6', '3', '45462', '0'), -('1', '6', '4', '50842', '0'), -('1', '6', '5', '47541', '0'), -('1', '6', '11', '59752', '0'), -('6', '6', '0', '6603', '0'), -('6', '6', '1', '49576', '0'), -('6', '6', '2', '45477', '0'), -('6', '6', '3', '45462', '0'), -('6', '6', '4', '50842', '0'), -('6', '6', '5', '47541', '0'), -('6', '6', '10', '20549', '0'), -('6', '6', '75', '20549', '0'), -('2', '6', '0', '6603', '0'), -('2', '6', '1', '49576', '0'), -('2', '6', '2', '45477', '0'), -('2', '6', '3', '45462', '0'), -('2', '6', '4', '50842', '0'), -('2', '6', '5', '47541', '0'), -('2', '6', '10', '20572', '0'), -('22', '6', '0', '6603', '0'), -('22', '6', '1', '49576', '0'), -('22', '6', '2', '45477', '0'), -('22', '6', '3', '45462', '0'), -('22', '6', '4', '50842', '0'), -('22', '6', '5', '47541', '0'), -('22', '6', '9', '68992', '0'), -('22', '6', '10', '68996', '0'), -('22', '6', '11', '87840', '0'), -('5', '6', '0', '6603', '0'), -('5', '6', '1', '49576', '0'), -('5', '6', '2', '45477', '0'), -('5', '6', '3', '45462', '0'), -('5', '6', '4', '50842', '0'), -('5', '6', '5', '47541', '0'), -('5', '6', '10', '20577', '0'), -('10', '6', '0', '6603', '0'), -('10', '6', '1', '49576', '0'), -('10', '6', '2', '45477', '0'), -('10', '6', '3', '45462', '0'), -('10', '6', '4', '50842', '0'), -('10', '6', '5', '47541', '0'), -('10', '6', '6', '50613', '0'), -('8', '6', '0', '6603', '0'), -('8', '6', '1', '49576', '0'), -('8', '6', '2', '45477', '0'), -('8', '6', '3', '45462', '0'), -('8', '6', '4', '50842', '0'), -('8', '6', '5', '47541', '0'), -('8', '6', '10', '26297', '0'), -('9', '6', '0', '6603', '0'), -('9', '6', '1', '49576', '0'), -('9', '6', '2', '45477', '0'), -('9', '6', '3', '45462', '0'), -('9', '6', '4', '50842', '0'), -('9', '6', '5', '47541', '0'), -('9', '6', '9', '69070', '0'), -('9', '6', '10', '69041', '0'), -('9', '6', '11', '69046', '0'), -('11', '6', '0', '6603', '0'), -('11', '6', '1', '49576', '0'), -('11', '6', '2', '45477', '0'), -('11', '6', '3', '45462', '0'), -('11', '6', '4', '50842', '0'), -('11', '6', '5', '47541', '0'), -('11', '6', '10', '59545', '0'), -('11', '3', '0', '3044', '0'), -('11', '3', '9', '59543', '0'), -('11', '3', '10', '9', '48'), -('11', '3', '11', '982', '0'), -('11', '3', '72', '6603', '0'), -('11', '3', '74', '75', '0'), -('11', '3', '82', '159', '128'), -('11', '3', '83', '4540', '128'), -('11', '2', '0', '35395', '0'), -('11', '2', '9', '59542', '0'), -('11', '2', '83', '4540', '128'), -('11', '1', '0', '88163', '0'), -('11', '1', '1', '78', '0'), -('11', '1', '9', '28880', '0'), -('11', '1', '72', '88163', '0'), -('11', '1', '73', '78', '0'), -('11', '1', '81', '28880', '0'), -('11', '5', '0', '585', '0'), -('11', '5', '9', '59544', '0'), -('11', '5', '83', '4540', '128'), -('11', '7', '0', '403', '0'), -('11', '7', '9', '59547', '0'), -('11', '10', '0', '100780', '0'), -('11', '10', '72', '100780', '0'), -('11', '10', '81', '121093', '0'), -('11', '8', '0', '44614', '0'), -('11', '8', '9', '59548', '0'), -('11', '8', '83', '4540', '128'), -('3', '3', '0', '3044', '0'), -('3', '3', '9', '20594', '0'), -('3', '3', '10', '9', '48'), -('3', '3', '11', '982', '0'), -('3', '3', '75', '20594', '0'), -('3', '2', '0', '35395', '0'), -('3', '2', '9', '20594', '0'), -('3', '1', '0', '88163', '0'), -('3', '1', '1', '78', '0'), -('3', '1', '9', '20594', '0'), -('3', '1', '72', '88163', '0'), -('3', '1', '73', '78', '0'), -('3', '1', '81', '20594', '0'), -('3', '7', '0', '403', '0'), -('3', '7', '9', '20594', '0'), -('3', '7', '72', '403', '0'), -('3', '5', '0', '585', '0'), -('3', '5', '9', '20594', '0'), -('3', '4', '0', '1752', '0'), -('3', '4', '9', '20594', '0'), -('3', '10', '0', '100780', '0'), -('3', '10', '72', '100780', '0'), -('3', '10', '81', '20594', '0'), -('3', '9', '0', '686', '0'), -('3', '9', '9', '20594', '0'), -('3', '9', '10', '10', '48'), -('3', '8', '0', '44614', '0'), -('3', '8', '9', '20594', '0'), -('7', '5', '0', '585', '0'), -('7', '4', '0', '1752', '0'), -('7', '1', '0', '88163', '0'), -('7', '1', '1', '78', '0'), -('7', '1', '72', '88163', '0'), -('7', '1', '73', '78', '0'), -('7', '1', '81', '20589', '0'), -('7', '10', '0', '100780', '0'), -('7', '10', '72', '100780', '0'), -('7', '10', '81', '20589', '0'), -('7', '9', '0', '686', '0'), -('7', '9', '10', '10', '48'), -('7', '8', '0', '44614', '0'), -('9', '9', '0', '686', '0'), -('9', '9', '9', '69070', '0'), -('9', '9', '10', '69041', '0'), -('9', '9', '11', '10', '48'), -('9', '8', '0', '44614', '0'), -('9', '8', '9', '69070', '0'), -('9', '8', '10', '69041', '0'), -('9', '1', '0', '88163', '0'), -('9', '1', '1', '78', '0'), -('9', '1', '9', '69070', '0'), -('9', '1', '10', '69041', '0'), -('9', '1', '72', '88163', '0'), -('9', '1', '73', '78', '0'), -('9', '1', '81', '69070', '0'), -('9', '1', '82', '69041', '0'), -('9', '3', '0', '3044', '0'), -('9', '3', '8', '982', '0'), -('9', '3', '9', '69070', '0'), -('9', '3', '10', '69041', '0'), -('9', '3', '11', '9', '48'), -('9', '5', '0', '585', '0'), -('9', '5', '9', '69070', '0'), -('9', '5', '10', '69041', '0'), -('9', '4', '0', '1752', '0'), -('9', '4', '9', '69070', '0'), -('9', '4', '10', '69041', '0'), -('9', '7', '0', '403', '0'), -('9', '7', '9', '69070', '0'), -('9', '7', '10', '69041', '0'), -('9', '7', '72', '403', '0'), -('1', '1', '0', '88163', '0'), -('1', '1', '1', '78', '0'), -('1', '1', '9', '59752', '0'), -('1', '1', '72', '88163', '0'), -('1', '1', '73', '78', '0'), -('1', '1', '81', '59752', '0'), -('1', '3', '0', '3044', '0'), -('1', '3', '9', '59752', '0'), -('1', '3', '10', '9', '48'), -('1', '3', '11', '982', '0'), -('1', '2', '0', '35395', '0'), -('1', '2', '9', '59752', '0'), -('1', '5', '0', '585', '0'), -('1', '5', '9', '59752', '0'), -('1', '4', '0', '1752', '0'), -('1', '4', '9', '59752', '0'), -('1', '9', '0', '686', '0'), -('1', '9', '9', '59752', '0'), -('1', '9', '10', '10', '48'), -('1', '8', '0', '44614', '0'), -('1', '8', '9', '59752', '0'), -('1', '10', '0', '100780', '0'), -('1', '10', '72', '100780', '0'), -('1', '10', '81', '59752', '0'), -('4', '4', '0', '1752', '0'), -('4', '4', '4', '58984', '0'), -('4', '4', '81', '58984', '0'), -('4', '5', '0', '585', '0'), -('4', '5', '9', '58984', '0'), -('4', '5', '81', '58984', '0'), -('4', '1', '0', '88163', '0'), -('4', '1', '1', '78', '0'), -('4', '1', '9', '58984', '0'), -('4', '1', '72', '88163', '0'), -('4', '1', '73', '78', '0'), -('4', '1', '81', '58984', '0'), -('4', '3', '0', '3044', '0'), -('4', '3', '9', '58984', '0'), -('4', '3', '10', '9', '48'), -('4', '3', '11', '982', '0'), -('4', '3', '81', '58984', '0'), -('4', '8', '0', '44614', '0'), -('4', '8', '9', '58984', '0'), -('4', '10', '0', '100780', '0'), -('4', '10', '72', '100780', '0'), -('4', '10', '81', '58984', '0'), -('4', '11', '0', '5176', '0'), -('4', '11', '9', '58984', '0'), -('4', '11', '72', '6603', '0'), -('4', '11', '74', '58984', '0'), -('4', '11', '84', '6603', '0'), -('4', '11', '96', '6603', '0'), -('4', '11', '108', '6603', '0'), -('2', '3', '0', '3044', '0'), -('2', '3', '9', '20572', '0'), -('2', '3', '10', '9', '48'), -('2', '3', '11', '982', '0'), -('2', '1', '0', '88163', '0'), -('2', '1', '1', '78', '0'), -('2', '1', '9', '20572', '0'), -('2', '1', '72', '88163', '0'), -('2', '1', '73', '78', '0'), -('2', '1', '81', '20572', '0'), -('2', '7', '0', '403', '0'), -('2', '7', '9', '33697', '0'), -('2', '7', '72', '403', '0'), -('2', '4', '0', '1752', '0'), -('2', '4', '9', '20572', '0'), -('2', '10', '0', '100780', '0'), -('2', '10', '72', '100780', '0'), -('2', '10', '81', '33697', '0'), -('2', '8', '0', '44614', '0'), -('2', '8', '9', '33702', '0'), -('2', '9', '0', '686', '0'), -('2', '9', '9', '33702', '0'), -('2', '9', '10', '10', '48'), -('24', '8', '0', '44614', '0'), -('24', '8', '9', '107079', '0'), -('24', '8', '11', '77264', '128'), -('24', '10', '0', '100780', '0'), -('24', '10', '72', '100780', '0'), -('24', '10', '81', '107079', '0'), -('24', '10', '83', '77272', '128'), -('24', '1', '0', '88163', '0'), -('24', '1', '1', '78', '0'), -('24', '1', '9', '107079', '0'), -('24', '1', '11', '77273', '128'), -('24', '1', '72', '88163', '0'), -('24', '1', '73', '78', '0'), -('24', '1', '81', '107079', '0'), -('24', '1', '83', '77273', '128'), -('24', '3', '0', '3044', '0'), -('24', '3', '7', '77272', '128'), -('24', '3', '9', '107079', '0'), -('24', '3', '10', '9', '48'), -('24', '3', '11', '982', '0'), -('24', '4', '0', '1752', '0'), -('24', '4', '9', '107079', '0'), -('24', '4', '11', '77272', '128'), -('24', '5', '0', '585', '0'), -('24', '5', '9', '107079', '0'), -('24', '5', '11', '77264', '128'), -('24', '7', '0', '403', '0'), -('24', '7', '9', '107079', '0'), -('24', '7', '11', '77272', '128'), -('24', '7', '72', '403', '0'), -('6', '7', '0', '403', '0'), -('6', '7', '9', '20549', '0'), -('6', '7', '75', '20549', '0'), -('6', '5', '0', '585', '0'), -('6', '5', '9', '20549', '0'), -('6', '2', '0', '35395', '0'), -('6', '2', '9', '20549', '0'), -('6', '3', '0', '3044', '0'), -('6', '3', '9', '20549', '0'), -('6', '3', '10', '9', '48'), -('6', '3', '11', '982', '0'), -('6', '3', '75', '20549', '0'), -('6', '1', '0', '88163', '0'), -('6', '1', '1', '78', '0'), -('6', '1', '9', '20549', '0'), -('6', '1', '72', '88163', '0'), -('6', '1', '73', '78', '0'), -('6', '1', '81', '20549', '0'), -('6', '10', '0', '100780', '0'), -('6', '10', '72', '100780', '0'), -('6', '10', '81', '20549', '0'), -('6', '11', '0', '5176', '0'), -('6', '11', '9', '20549', '0'), -('6', '11', '72', '6603', '0'), -('6', '11', '75', '20549', '0'), -('6', '11', '84', '6603', '0'), -('6', '11', '96', '6603', '0'), -('6', '11', '108', '6603', '0'), -('8', '8', '0', '44614', '0'), -('8', '8', '9', '26297', '0'), -('8', '9', '0', '686', '0'), -('8', '9', '9', '26297', '0'), -('8', '9', '10', '10', '48'), -('8', '10', '0', '100780', '0'), -('8', '10', '72', '100780', '0'), -('8', '10', '81', '26297', '0'), -('8', '11', '0', '5176', '0'), -('8', '11', '9', '26297', '0'), -('8', '11', '72', '6603', '0'), -('8', '11', '84', '6603', '0'), -('8', '11', '96', '6603', '0'), -('8', '1', '0', '88163', '0'), -('8', '1', '1', '78', '0'), -('8', '1', '9', '26297', '0'), -('8', '1', '72', '88163', '0'), -('8', '1', '73', '78', '0'), -('8', '1', '81', '26297', '0'), -('8', '3', '0', '3044', '0'), -('8', '3', '9', '26297', '0'), -('8', '3', '10', '9', '48'), -('8', '3', '11', '982', '0'), -('8', '4', '0', '1752', '0'), -('8', '4', '9', '26297', '0'), -('8', '4', '76', '26297', '0'), -('8', '5', '0', '585', '0'), -('8', '5', '9', '26297', '0'), -('8', '7', '0', '403', '0'), -('8', '7', '9', '26297', '0'), -('8', '7', '72', '403', '0'), -('5', '5', '0', '585', '0'), -('5', '5', '9', '20577', '0'), -('5', '4', '0', '1752', '0'), -('5', '4', '9', '20577', '0'), -('5', '1', '0', '88163', '0'), -('5', '1', '1', '78', '0'), -('5', '1', '9', '20577', '0'), -('5', '1', '72', '88163', '0'), -('5', '1', '73', '78', '0'), -('5', '1', '81', '20577', '0'), -('5', '3', '0', '3044', '0'), -('5', '3', '9', '20577', '0'), -('5', '3', '10', '9', '48'), -('5', '3', '11', '982', '0'), -('5', '9', '0', '686', '0'), -('5', '9', '9', '20577', '0'), -('5', '9', '10', '10', '48'), -('5', '8', '0', '44614', '0'), -('5', '8', '9', '20577', '0'), -('5', '10', '0', '100780', '0'), -('5', '10', '72', '100780', '0'), -('5', '10', '81', '20577', '0'), -('22', '4', '0', '1752', '0'), -('22', '5', '0', '585', '0'), -('22', '3', '0', '3044', '0'), -('22', '3', '10', '9', '48'), -('22', '3', '11', '982', '0'), -('22', '1', '0', '88163', '0'), -('22', '1', '1', '78', '0'), -('22', '1', '72', '88163', '0'), -('22', '1', '73', '78', '0'), -('22', '11', '0', '5176', '0'), -('22', '11', '72', '6603', '0'), -('22', '11', '84', '6603', '0'), -('22', '11', '96', '6603', '0'), -('22', '8', '0', '44614', '0'), -('22', '9', '0', '686', '0'), -('22', '9', '10', '10', '48'); +(10, 10, 0, 100780, 0), +(10, 10, 9, 129597, 0), +(10, 10, 72, 100780, 0), +(10, 10, 81, 129597, 0), +(10, 8, 0, 44614, 0), +(10, 8, 9, 28730, 0), +(10, 9, 0, 686, 0), +(10, 9, 9, 28730, 0), +(10, 9, 10, 10, 48), +(10, 2, 0, 35395, 0), +(10, 2, 9, 155145, 0), +(10, 3, 0, 3044, 0), +(10, 3, 9, 80483, 0), +(10, 3, 10, 9, 48), +(10, 3, 11, 982, 0), +(10, 1, 0, 88163, 0), +(10, 1, 1, 78, 0), +(10, 1, 9, 69179, 0), +(10, 1, 72, 88163, 0), +(10, 1, 73, 78, 0), +(10, 1, 81, 69179, 0), +(10, 4, 0, 1752, 0), +(10, 4, 9, 25046, 0), +(10, 5, 0, 585, 0), +(10, 5, 9, 28730, 0), +(4, 6, 0, 6603, 0), +(4, 6, 1, 49576, 0), +(4, 6, 2, 45477, 0), +(4, 6, 3, 45462, 0), +(4, 6, 4, 50842, 0), +(4, 6, 5, 47541, 0), +(4, 6, 10, 58984, 0), +(4, 6, 83, 58984, 0), +(7, 6, 0, 6603, 0), +(7, 6, 1, 49576, 0), +(7, 6, 2, 45477, 0), +(7, 6, 3, 45462, 0), +(7, 6, 4, 50842, 0), +(7, 6, 5, 47541, 0), +(7, 6, 10, 20589, 0), +(7, 6, 72, 6603, 0), +(7, 6, 83, 117, 128), +(7, 6, 84, 6603, 0), +(7, 6, 96, 6603, 0), +(7, 6, 108, 6603, 0), +(3, 6, 0, 6603, 0), +(3, 6, 1, 49576, 0), +(3, 6, 2, 45477, 0), +(3, 6, 3, 45462, 0), +(3, 6, 4, 50842, 0), +(3, 6, 5, 47541, 0), +(1, 6, 0, 6603, 0), +(1, 6, 1, 49576, 0), +(1, 6, 2, 45477, 0), +(1, 6, 3, 45462, 0), +(1, 6, 4, 50842, 0), +(1, 6, 5, 47541, 0), +(1, 6, 11, 59752, 0), +(6, 6, 0, 6603, 0), +(6, 6, 1, 49576, 0), +(6, 6, 2, 45477, 0), +(6, 6, 3, 45462, 0), +(6, 6, 4, 50842, 0), +(6, 6, 5, 47541, 0), +(6, 6, 10, 20549, 0), +(6, 6, 75, 20549, 0), +(2, 6, 0, 6603, 0), +(2, 6, 1, 49576, 0), +(2, 6, 2, 45477, 0), +(2, 6, 3, 45462, 0), +(2, 6, 4, 50842, 0), +(2, 6, 5, 47541, 0), +(2, 6, 10, 20572, 0), +(22, 6, 0, 6603, 0), +(22, 6, 1, 49576, 0), +(22, 6, 2, 45477, 0), +(22, 6, 3, 45462, 0), +(22, 6, 4, 50842, 0), +(22, 6, 5, 47541, 0), +(22, 6, 9, 68992, 0), +(22, 6, 10, 68996, 0), +(22, 6, 11, 87840, 0), +(5, 6, 0, 6603, 0), +(5, 6, 1, 49576, 0), +(5, 6, 2, 45477, 0), +(5, 6, 3, 45462, 0), +(5, 6, 4, 50842, 0), +(5, 6, 5, 47541, 0), +(5, 6, 10, 20577, 0), +(10, 6, 0, 6603, 0), +(10, 6, 1, 49576, 0), +(10, 6, 2, 45477, 0), +(10, 6, 3, 45462, 0), +(10, 6, 4, 50842, 0), +(10, 6, 5, 47541, 0), +(10, 6, 6, 50613, 0), +(8, 6, 0, 6603, 0), +(8, 6, 1, 49576, 0), +(8, 6, 2, 45477, 0), +(8, 6, 3, 45462, 0), +(8, 6, 4, 50842, 0), +(8, 6, 5, 47541, 0), +(8, 6, 10, 26297, 0), +(9, 6, 0, 6603, 0), +(9, 6, 1, 49576, 0), +(9, 6, 2, 45477, 0), +(9, 6, 3, 45462, 0), +(9, 6, 4, 50842, 0), +(9, 6, 5, 47541, 0), +(9, 6, 9, 69070, 0), +(9, 6, 10, 69041, 0), +(9, 6, 11, 69046, 0), +(11, 6, 0, 6603, 0), +(11, 6, 1, 49576, 0), +(11, 6, 2, 45477, 0), +(11, 6, 3, 45462, 0), +(11, 6, 4, 50842, 0), +(11, 6, 5, 47541, 0), +(11, 6, 10, 59545, 0), +(11, 3, 0, 3044, 0), +(11, 3, 9, 59543, 0), +(11, 3, 10, 9, 48), +(11, 3, 11, 982, 0), +(11, 3, 72, 6603, 0), +(11, 3, 74, 75, 0), +(11, 3, 82, 159, 128), +(11, 3, 83, 4540, 128), +(11, 2, 0, 35395, 0), +(11, 2, 9, 59542, 0), +(11, 2, 83, 4540, 128), +(11, 1, 0, 88163, 0), +(11, 1, 1, 78, 0), +(11, 1, 9, 28880, 0), +(11, 1, 72, 88163, 0), +(11, 1, 73, 78, 0), +(11, 1, 81, 28880, 0), +(11, 5, 0, 585, 0), +(11, 5, 9, 59544, 0), +(11, 5, 83, 4540, 128), +(11, 7, 0, 403, 0), +(11, 7, 9, 59547, 0), +(11, 10, 0, 100780, 0), +(11, 10, 72, 100780, 0), +(11, 10, 81, 121093, 0), +(11, 8, 0, 44614, 0), +(11, 8, 9, 59548, 0), +(11, 8, 83, 4540, 128), +(3, 3, 0, 3044, 0), +(3, 3, 9, 20594, 0), +(3, 3, 10, 9, 48), +(3, 3, 11, 982, 0), +(3, 3, 75, 20594, 0), +(3, 2, 0, 35395, 0), +(3, 2, 9, 20594, 0), +(3, 1, 0, 88163, 0), +(3, 1, 1, 78, 0), +(3, 1, 9, 20594, 0), +(3, 1, 72, 88163, 0), +(3, 1, 73, 78, 0), +(3, 1, 81, 20594, 0), +(3, 7, 0, 403, 0), +(3, 7, 9, 20594, 0), +(3, 7, 72, 403, 0), +(3, 5, 0, 585, 0), +(3, 5, 9, 20594, 0), +(3, 4, 0, 1752, 0), +(3, 4, 9, 20594, 0), +(3, 10, 0, 100780, 0), +(3, 10, 72, 100780, 0), +(3, 10, 81, 20594, 0), +(3, 9, 0, 686, 0), +(3, 9, 9, 20594, 0), +(3, 9, 10, 10, 48), +(3, 8, 0, 44614, 0), +(3, 8, 9, 20594, 0), +(7, 5, 0, 585, 0), +(7, 4, 0, 1752, 0), +(7, 1, 0, 88163, 0), +(7, 1, 1, 78, 0), +(7, 1, 72, 88163, 0), +(7, 1, 73, 78, 0), +(7, 1, 81, 20589, 0), +(7, 10, 0, 100780, 0), +(7, 10, 72, 100780, 0), +(7, 10, 81, 20589, 0), +(7, 9, 0, 686, 0), +(7, 9, 10, 10, 48), +(7, 8, 0, 44614, 0), +(9, 9, 0, 686, 0), +(9, 9, 9, 69070, 0), +(9, 9, 10, 69041, 0), +(9, 9, 11, 10, 48), +(9, 8, 0, 44614, 0), +(9, 8, 9, 69070, 0), +(9, 8, 10, 69041, 0), +(9, 1, 0, 88163, 0), +(9, 1, 1, 78, 0), +(9, 1, 9, 69070, 0), +(9, 1, 10, 69041, 0), +(9, 1, 72, 88163, 0), +(9, 1, 73, 78, 0), +(9, 1, 81, 69070, 0), +(9, 1, 82, 69041, 0), +(9, 3, 0, 3044, 0), +(9, 3, 8, 982, 0), +(9, 3, 9, 69070, 0), +(9, 3, 10, 69041, 0), +(9, 3, 11, 9, 48), +(9, 5, 0, 585, 0), +(9, 5, 9, 69070, 0), +(9, 5, 10, 69041, 0), +(9, 4, 0, 1752, 0), +(9, 4, 9, 69070, 0), +(9, 4, 10, 69041, 0), +(9, 7, 0, 403, 0), +(9, 7, 9, 69070, 0), +(9, 7, 10, 69041, 0), +(9, 7, 72, 403, 0), +(1, 1, 0, 88163, 0), +(1, 1, 1, 78, 0), +(1, 1, 9, 59752, 0), +(1, 1, 72, 88163, 0), +(1, 1, 73, 78, 0), +(1, 1, 81, 59752, 0), +(1, 3, 0, 3044, 0), +(1, 3, 9, 59752, 0), +(1, 3, 10, 9, 48), +(1, 3, 11, 982, 0), +(1, 2, 0, 35395, 0), +(1, 2, 9, 59752, 0), +(1, 5, 0, 585, 0), +(1, 5, 9, 59752, 0), +(1, 4, 0, 1752, 0), +(1, 4, 9, 59752, 0), +(1, 9, 0, 686, 0), +(1, 9, 9, 59752, 0), +(1, 9, 10, 10, 48), +(1, 8, 0, 44614, 0), +(1, 8, 9, 59752, 0), +(1, 10, 0, 100780, 0), +(1, 10, 72, 100780, 0), +(1, 10, 81, 59752, 0), +(4, 4, 0, 1752, 0), +(4, 4, 4, 58984, 0), +(4, 4, 81, 58984, 0), +(4, 5, 0, 585, 0), +(4, 5, 9, 58984, 0), +(4, 5, 81, 58984, 0), +(4, 1, 0, 88163, 0), +(4, 1, 1, 78, 0), +(4, 1, 9, 58984, 0), +(4, 1, 72, 88163, 0), +(4, 1, 73, 78, 0), +(4, 1, 81, 58984, 0), +(4, 3, 0, 3044, 0), +(4, 3, 9, 58984, 0), +(4, 3, 10, 9, 48), +(4, 3, 11, 982, 0), +(4, 3, 81, 58984, 0), +(4, 8, 0, 44614, 0), +(4, 8, 9, 58984, 0), +(4, 10, 0, 100780, 0), +(4, 10, 72, 100780, 0), +(4, 10, 81, 58984, 0), +(4, 11, 0, 5176, 0), +(4, 11, 9, 58984, 0), +(4, 11, 72, 6603, 0), +(4, 11, 74, 58984, 0), +(4, 11, 84, 6603, 0), +(4, 11, 96, 6603, 0), +(4, 11, 108, 6603, 0), +(2, 3, 0, 3044, 0), +(2, 3, 9, 20572, 0), +(2, 3, 10, 9, 48), +(2, 3, 11, 982, 0), +(2, 1, 0, 88163, 0), +(2, 1, 1, 78, 0), +(2, 1, 9, 20572, 0), +(2, 1, 72, 88163, 0), +(2, 1, 73, 78, 0), +(2, 1, 81, 20572, 0), +(2, 7, 0, 403, 0), +(2, 7, 9, 33697, 0), +(2, 7, 72, 403, 0), +(2, 4, 0, 1752, 0), +(2, 4, 9, 20572, 0), +(2, 10, 0, 100780, 0), +(2, 10, 72, 100780, 0), +(2, 10, 81, 33697, 0), +(2, 8, 0, 44614, 0), +(2, 8, 9, 33702, 0), +(2, 9, 0, 686, 0), +(2, 9, 9, 33702, 0), +(2, 9, 10, 10, 48), +(24, 8, 0, 44614, 0), +(24, 8, 9, 107079, 0), +(24, 8, 11, 77264, 128), +(24, 10, 0, 100780, 0), +(24, 10, 72, 100780, 0), +(24, 10, 81, 107079, 0), +(24, 10, 83, 77272, 128), +(24, 1, 0, 88163, 0), +(24, 1, 1, 78, 0), +(24, 1, 9, 107079, 0), +(24, 1, 11, 77273, 128), +(24, 1, 72, 88163, 0), +(24, 1, 73, 78, 0), +(24, 1, 81, 107079, 0), +(24, 1, 83, 77273, 128), +(24, 3, 0, 3044, 0), +(24, 3, 7, 77272, 128), +(24, 3, 9, 107079, 0), +(24, 3, 10, 9, 48), +(24, 3, 11, 982, 0), +(24, 4, 0, 1752, 0), +(24, 4, 9, 107079, 0), +(24, 4, 11, 77272, 128), +(24, 5, 0, 585, 0), +(24, 5, 9, 107079, 0), +(24, 5, 11, 77264, 128), +(24, 7, 0, 403, 0), +(24, 7, 9, 107079, 0), +(24, 7, 11, 77272, 128), +(24, 7, 72, 403, 0), +(6, 7, 0, 403, 0), +(6, 7, 9, 20549, 0), +(6, 7, 75, 20549, 0), +(6, 5, 0, 585, 0), +(6, 5, 9, 20549, 0), +(6, 2, 0, 35395, 0), +(6, 2, 9, 20549, 0), +(6, 3, 0, 3044, 0), +(6, 3, 9, 20549, 0), +(6, 3, 10, 9, 48), +(6, 3, 11, 982, 0), +(6, 3, 75, 20549, 0), +(6, 1, 0, 88163, 0), +(6, 1, 1, 78, 0), +(6, 1, 9, 20549, 0), +(6, 1, 72, 88163, 0), +(6, 1, 73, 78, 0), +(6, 1, 81, 20549, 0), +(6, 10, 0, 100780, 0), +(6, 10, 72, 100780, 0), +(6, 10, 81, 20549, 0), +(6, 11, 0, 5176, 0), +(6, 11, 9, 20549, 0), +(6, 11, 72, 6603, 0), +(6, 11, 75, 20549, 0), +(6, 11, 84, 6603, 0), +(6, 11, 96, 6603, 0), +(6, 11, 108, 6603, 0), +(8, 8, 0, 44614, 0), +(8, 8, 9, 26297, 0), +(8, 9, 0, 686, 0), +(8, 9, 9, 26297, 0), +(8, 9, 10, 10, 48), +(8, 10, 0, 100780, 0), +(8, 10, 72, 100780, 0), +(8, 10, 81, 26297, 0), +(8, 11, 0, 5176, 0), +(8, 11, 9, 26297, 0), +(8, 11, 72, 6603, 0), +(8, 11, 84, 6603, 0), +(8, 11, 96, 6603, 0), +(8, 1, 0, 88163, 0), +(8, 1, 1, 78, 0), +(8, 1, 9, 26297, 0), +(8, 1, 72, 88163, 0), +(8, 1, 73, 78, 0), +(8, 1, 81, 26297, 0), +(8, 3, 0, 3044, 0), +(8, 3, 9, 26297, 0), +(8, 3, 10, 9, 48), +(8, 3, 11, 982, 0), +(8, 4, 0, 1752, 0), +(8, 4, 9, 26297, 0), +(8, 4, 76, 26297, 0), +(8, 5, 0, 585, 0), +(8, 5, 9, 26297, 0), +(8, 7, 0, 403, 0), +(8, 7, 9, 26297, 0), +(8, 7, 72, 403, 0), +(5, 5, 0, 585, 0), +(5, 5, 9, 20577, 0), +(5, 4, 0, 1752, 0), +(5, 4, 9, 20577, 0), +(5, 1, 0, 88163, 0), +(5, 1, 1, 78, 0), +(5, 1, 9, 20577, 0), +(5, 1, 72, 88163, 0), +(5, 1, 73, 78, 0), +(5, 1, 81, 20577, 0), +(5, 3, 0, 3044, 0), +(5, 3, 9, 20577, 0), +(5, 3, 10, 9, 48), +(5, 3, 11, 982, 0), +(5, 9, 0, 686, 0), +(5, 9, 9, 20577, 0), +(5, 9, 10, 10, 48), +(5, 8, 0, 44614, 0), +(5, 8, 9, 20577, 0), +(5, 10, 0, 100780, 0), +(5, 10, 72, 100780, 0), +(5, 10, 81, 20577, 0), +(22, 4, 0, 1752, 0), +(22, 5, 0, 585, 0), +(22, 3, 0, 3044, 0), +(22, 3, 10, 9, 48), +(22, 3, 11, 982, 0), +(22, 1, 0, 88163, 0), +(22, 1, 1, 78, 0), +(22, 1, 72, 88163, 0), +(22, 1, 73, 78, 0), +(22, 11, 0, 5176, 0), +(22, 11, 72, 6603, 0), +(22, 11, 84, 6603, 0), +(22, 11, 96, 6603, 0), +(22, 8, 0, 44614, 0), +(22, 9, 0, 686, 0), +(22, 9, 10, 10, 48); diff --git a/sql/updates/world/2014_12_01_01_world.sql b/sql/updates/world/2014_12_01_01_world.sql deleted file mode 100644 index d9532d5881b..00000000000 --- a/sql/updates/world/2014_12_01_01_world.sql +++ /dev/null @@ -1,277 +0,0 @@ -DROP TABLE IF EXISTS `playercreateinfo_skills`; -DROP TABLE IF EXISTS `playercreateinfo_spell`; - -CREATE TABLE `playercreateinfo_spell` ( - `racemask` int(10) unsigned NOT NULL DEFAULT '0', - `classmask` int(10) unsigned NOT NULL DEFAULT '0', - `Spell` mediumint(8) unsigned NOT NULL DEFAULT '0', - `Note` varchar(255) DEFAULT NULL, - PRIMARY KEY (`racemask`,`classmask`,`Spell`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -INSERT INTO `playercreateinfo_spell` (`racemask`, `classmask`, `Spell`, `Note`) VALUES -('10487807', '943', '201', 'One-Handed Swords'), -('10487807', '623', '196', 'One-Handed Axes'), -('10487807', '1659', '198', 'One-Handed Maces'), -('10487807', '2047', '522', 'SPELLDEFENSE (DND)'), -('10487807', '2047', '204', 'Defense'), -('10487807', '2047', '81', 'Dodge'), -('946', '2047', '669', 'Language Orcish'), -('10487807', '2005', '227', 'Staves'), -('512', '959', '813', 'Language Thalassian'), -('10487807', '2047', '203', 'Unarmed'), -('10487807', '2047', '6478', 'Opening'), -('10487807', '2047', '6603', 'Auto Attack'), -('10487807', '2047', '45927', 'Summon Friend'), -('10487807', '2047', '22027', 'Remove Insignia'), -('10487807', '2047', '114585', 'Mastery'), -('10487807', '2047', '2382', 'Generic'), -('10487807', '2047', '21652', 'Closing'), -('10487807', '2047', '8386', 'Attacking'), -('10487807', '2047', '7266', 'Duel'), -('10487807', '2047', '7267', 'Grovel'), -('10487807', '2047', '7355', 'Stuck'), -('10487807', '2047', '6233', 'Closing'), -('10487807', '2047', '6247', 'Opening'), -('10487807', '2047', '6477', 'Opening'), -('10487807', '2047', '115043', 'Player Damage Reduction'), -('10487807', '2047', '3050', 'Detect'), -('10487807', '2047', '9125', 'Generic'), -('10487807', '2047', '61437', 'Opening'), -('10487807', '2047', '68398', 'Opening'), -('10487807', '2047', '96220', 'Opening'), -('8390399', '512', '106902', 'Weapon Skills'), -('8390399', '512', '106904', 'Armor Skills'), -('10487807', '2047', '3365', 'Opening'), -('10487807', '2047', '21651', 'Opening'), -('10487807', '2047', '6246', 'Closing'), -('10487807', '2047', '132334', ''), -('10487807', '2047', '22810', 'Opening - No Text'), -('10487807', '2047', '134732', 'Battle Fatigue'), -('10487807', '2047', '161691', 'Garrison Ability'), -('10487807', '1575', '200', 'Polearms'), -('10487807', '1647', '9077', 'Leather'), -('10487807', '2047', '9078', 'Cloth'), -('10487807', '1613', '15590', 'Fist Weapons'), -('512', '959', '822', 'Arcane Resistance'), -('512', '959', '28877', 'Arcane Affinity'), -('512', '959', '79748', 'Languages'), -('512', '512', '129597', 'Arcane Torrent'), -('512', '959', '154742', 'Arcane Acuity'), -('8390399', '512', '125670', 'Targeted Expulsion'), -('8390399', '512', '116812', 'Parry'), -('8390399', '512', '128678', 'Jab'), -('8390399', '512', '107500', '<DND> Monk Energy Driver'), -('8390399', '512', '108562', 'Monk Weapon Override Driver'), -('8390399', '512', '108977', 'Way of the Monk'), -('8390399', '512', '120275', 'Way of the Monk'), -('8390399', '512', '115074', 'Fighting Style'), -('8390399', '512', '100780', 'Jab'), -('8390399', '512', '115612', 'Expel Harm Driver'), -('8390399', '512', '119650', 'Energy Usage'), -('8390399', '512', '120277', 'Way of the Monk'), -('8390399', '512', '137022', 'Hotfix Passive'), -('8390399', '512', '103985', 'Stance of the Fierce Tiger'), -('10487807', '1501', '1180', 'Daggers'), -('10487775', '128', '76276', 'Armor Skills'), -('10487775', '128', '76298', 'Weapon Skills'), -('10487807', '400', '5009', 'Wands'), -('10487807', '400', '5019', 'Shoot'), -('512', '400', '28730', 'Arcane Torrent'), -('10487775', '128', '121039', 'Mana Attunement'), -('10487775', '128', '44614', 'Frostfire Bolt'), -('10487775', '128', '137018', 'Hotfix Passive'), -('10487775', '384', '162699', 'Stat Negation Aura - Intellect DPS'), -('2098135', '256', '76299', 'Weapon Skills'), -('2098135', '256', '76277', 'Armor Skills'), -('2098135', '256', '121688', ''), -('2098135', '256', '688', 'Summon Imp'), -('2098135', '256', '686', 'Shadow Bolt'), -('2098135', '256', '114190', ''), -('2098135', '256', '137042', 'Hotfix Passive'), -('2098135', '256', '157903', 'Warlock'), -('10487807', '39', '202', 'Two-Handed Swords'), -('10487807', '67', '107', 'Block'), -('10487807', '1123', '199', 'Two-Handed Maces'), -('10487807', '103', '197', 'Two-Handed Axes'), -('1573', '2', '76271', 'Armor Skills'), -('1573', '2', '76294', 'Weapon Skills'), -('10487807', '35', '119811', 'Mail'), -('10487807', '67', '9116', 'Shield'), -('512', '2', '155145', 'Arcane Torrent'), -('1573', '2', '82242', 'Parry'), -('1573', '2', '123830', 'Block'), -('1573', '2', '35395', 'Crusader Strike'), -('1573', '2', '137026', 'Hotfix Passive'), -('10487807', '13', '264', 'Bows'), -('10487807', '13', '266', 'Guns'), -('10487807', '12', '674', 'Dual Wield'), -('10487743', '4', '34082', 'Hunter Passive Auras (DND)'), -('10487743', '4', '76249', 'Weapon Skills'), -('10487743', '4', '76250', 'Armor Skills'), -('10487743', '4', '75', 'Auto Shot'), -('10487807', '13', '5011', 'Crossbows'), -('512', '4', '80483', 'Arcane Torrent'), -('10487743', '4', '77442', 'Focus'), -('10487743', '4', '883', 'Call Pet 1'), -('10487743', '4', '982', 'Revive Pet'), -('10487743', '4', '137014', 'Hotfix Passive'), -('10487743', '4', '157443', 'Critical Strikes'), -('10487807', '12', '162697', 'Stat Negation Aura - Agility DPS'), -('10487743', '4', '3044', 'Arcane Shot'), -('10487807', '1', '5301', 'Revenge Trigger'), -('10487807', '1', '32215', 'Victorious State'), -('10487807', '1', '76268', 'Armor Skills'), -('10487807', '1', '76290', 'Weapon Skills'), -('512', '1', '69179', 'Arcane Torrent'), -('10487807', '1', '3127', 'Parry'), -('10487807', '1', '88163', 'Attack'), -('10487807', '1', '2457', 'Battle Stance'), -('10487807', '1', '123829', 'Block'), -('10487807', '1', '128217', 'Pummel (shield visual override) (DND)'), -('10487807', '1', '137047', 'Hotfix Passive'), -('10487807', '1', '78', 'Heroic Strike'), -('10486751', '8', '76297', 'Weapon Skills'), -('10486751', '8', '76273', 'Armor Skills'), -('512', '8', '25046', 'Arcane Torrent'), -('10486751', '8', '1752', 'Sinister Strike'), -('10486751', '8', '121733', 'Throw'), -('10486751', '8', '82245', 'Parry'), -('10486751', '8', '137034', 'Hotfix Passive'), -('10486751', '8', '157442', 'Critical Strikes'), -('10487805', '16', '76279', 'Armor Skills'), -('10487805', '16', '76301', 'Weapon Skills'), -('10487805', '16', '585', 'Smite'), -('10487805', '16', '137030', 'Hotfix Passive'), -('2098253', '2047', '668', 'Language Common'), -('8', '1725', '671', 'Language Darnassian'), -('8', '1725', '76252', 'Languages'), -('8', '1725', '20582', 'Quickness'), -('8', '1725', '20585', 'Wisp Spirit'), -('8', '1725', '21009', 'Elusiveness'), -('8', '1725', '58984', 'Shadowmeld'), -('8', '1725', '20583', 'Nature Resistance'), -('8', '1725', '154748', 'Touch of Elune'), -('2099199', '32', '10846', 'First Aid'), -('2099199', '32', '7928', 'Silk Bandage'), -('2099199', '32', '7929', 'Heavy Silk Bandage'), -('2099199', '32', '7934', 'Anti-Venom'), -('2099199', '32', '3275', 'Linen Bandage'), -('2099199', '32', '3276', 'Heavy Linen Bandage'), -('2099199', '32', '3278', 'Heavy Wool Bandage'), -('2099199', '32', '18629', 'Runecloth Bandage'), -('2099199', '32', '10840', 'Mageweave Bandage'), -('2099199', '32', '10841', 'Heavy Mageweave Bandage'), -('2099199', '32', '18630', 'Heavy Runecloth Bandage'), -('2099199', '32', '3277', 'Wool Bandage'), -('2099199', '32', '76292', 'Weapon Skills'), -('2099199', '32', '76282', 'Armor Skills'), -('2099199', '32', '750', 'Plate Mail'), -('2099199', '32', '33391', 'Journeyman Riding'), -('2099199', '32', '86524', 'Plate Specialization'), -('2099199', '32', '82246', 'Parry'), -('2099199', '32', '47541', 'Death Coil'), -('2099199', '32', '49576', 'Death Grip'), -('2099199', '32', '48266', 'Frost Presence'), -('2099199', '32', '45477', 'Icy Touch'), -('2099199', '32', '50842', 'Blood Boil'), -('2099199', '32', '45462', 'Plague Strike'), -('2099199', '32', '137005', 'Hotfix Passive'), -('2099199', '32', '89964', 'Vanishing Powder'), -('2099199', '32', '58715', 'Shifting Presences'), -('2099199', '32', '63644', 'Activating Secondary Spec'), -('2099199', '32', '63645', 'Activating Primary Spec'), -('2099199', '32', '127650', 'Remove Talent'), -('64', '953', '7340', 'Language Gnomish'), -('64', '953', '20589', 'Escape Artist'), -('64', '953', '20593', 'Engineering Specialization'), -('64', '953', '20592', 'Arcane Resistance'), -('64', '953', '92680', 'Nimble Fingers'), -('64', '953', '79740', 'Languages'), -('64', '32', '154747', 'Expansive Mind'), -('4', '1023', '20596', 'Frost Resistance'), -('4', '1023', '20594', 'Stoneform'), -('4', '1023', '59224', 'Might of the Mountain'), -('4', '1023', '92682', 'Explorer'), -('4', '1023', '79739', 'Languages'), -('4', '1023', '672', 'Language Dwarven'), -('1', '959', '20599', 'Diplomacy'), -('1', '959', '20598', 'The Human Spirit'), -('1', '959', '59752', 'Every Man for Himself'), -('1', '959', '79738', 'Languages'), -('32', '1655', '670', 'Language Taurahe'), -('32', '1655', '20549', 'War Stomp'), -('32', '1655', '20550', 'Endurance'), -('32', '1655', '20551', 'Nature Resistance'), -('32', '1655', '20552', 'Cultivation'), -('32', '1655', '79746', 'Languages'), -('32', '1655', '154743', 'Brawn'), -('2', '1005', '21563', 'Command'), -('2', '45', '20572', 'Blood Fury'), -('2', '1005', '20573', 'Hardiness'), -('2', '1005', '79743', 'Languages'), -('2097152', '32', '94293', 'Altered Form'), -('2097152', '32', '87840', 'Running Wild'), -('2097152', '1469', '79742', 'Languages'), -('2097152', '32', '68975', 'Viciousness'), -('2097152', '32', '68978', 'Flayer'), -('2097152', '32', '68992', 'Darkflight'), -('2097152', '32', '68976', 'Aberration'), -('2097152', '32', '68996', 'Two Forms'), -('16', '957', '5227', 'Touch of the Grave'), -('16', '957', '7744', 'Will of the Forsaken'), -('16', '957', '20577', 'Cannibalize'), -('16', '957', '20579', 'Shadow Resistance'), -('16', '957', '79747', 'Languages'), -('16', '957', '17737', 'Language Gutterspeak'), -('512', '32', '50613', 'Arcane Torrent'), -('128', '2045', '7341', 'Language Troll'), -('128', '2045', '26297', 'Berserking'), -('128', '2045', '58943', 'Da Voodoo Shuffle'), -('128', '2045', '20555', 'Regeneration'), -('128', '2045', '20557', 'Beast Slaying'), -('128', '2045', '79744', 'Languages'), -('256', '32', '69046', 'Pack Hobgoblin'), -('256', '509', '79749', 'Languages'), -('256', '509', '69070', 'Rocket Jump'), -('256', '509', '69044', 'Best Deals Anywhere'), -('256', '509', '69045', 'Better Living Through Chemistry'), -('256', '509', '69041', 'Rocket Barrage'), -('256', '509', '69042', 'Time is Money'), -('256', '509', '69269', 'Language Goblin'), -('1024', '759', '29932', 'Language Draenei'), -('1024', '759', '6562', 'Heroic Presence'), -('1024', '759', '28875', 'Gemcutting'), -('1024', '759', '59221', 'Shadow Resistance'), -('1024', '32', '59545', 'Gift of the Naaru'), -('1024', '759', '79741', 'Languages'), -('1024', '4', '59543', 'Gift of the Naaru'), -('1024', '2', '59542', 'Gift of the Naaru'), -('1024', '1', '28880', 'Gift of the Naaru'), -('1024', '16', '59544', 'Gift of the Naaru'), -('8390054', '64', '76296', 'Weapon Skills'), -('8390054', '64', '76272', 'Armor Skills'), -('1024', '64', '59547', 'Gift of the Naaru'), -('8390054', '64', '403', 'Lightning Bolt'), -('8390054', '64', '123831', 'Block'), -('8390054', '64', '137038', 'Hotfix Passive'), -('1024', '512', '121093', 'Gift of the Naaru'), -('1024', '128', '59548', 'Gift of the Naaru'), -('64', '912', '20591', 'Expansive Mind'), -('64', '520', '154744', 'Expansive Mind'), -('64', '1', '154746', 'Expansive Mind'), -('2097320', '1024', '76275', 'Armor Skills'), -('2097320', '1024', '76300', 'Weapon Skills'), -('2097320', '1024', '5176', 'Wrath'), -('2097320', '1024', '137009', 'Hotfix Passive'), -('2097320', '1024', '159822', 'Shapemender'), -('2', '576', '33697', 'Blood Fury'), -('2', '384', '33702', 'Blood Fury'), -('8388608', '733', '131701', 'Languages'), -('8388608', '733', '107076', 'Bouncy'), -('8388608', '733', '107074', 'Inner Peace'), -('8388608', '733', '107073', 'Gourmand'), -('8388608', '733', '107072', 'Epicurean'), -('8388608', '733', '107079', 'Quaking Palm'), -('8388608', '733', '108127', 'Language Pandaren Neutral'), -('2097152', '1437', '69001', ''); diff --git a/sql/updates/world/2014_12_04_00_world.sql b/sql/updates/world/2014_12_04_00_world.sql new file mode 100644 index 00000000000..5308b0f51d7 --- /dev/null +++ b/sql/updates/world/2014_12_04_00_world.sql @@ -0,0 +1,64 @@ +DROP TABLE IF EXISTS `playercreateinfo_spell`; +DROP TABLE IF EXISTS `playercreateinfo_skills`; +CREATE TABLE `playercreateinfo_skills` ( + `raceMask` int(10) unsigned NOT NULL, + `classMask` int(10) unsigned NOT NULL, + `skill` smallint(5) unsigned NOT NULL, + `rank` smallint(5) unsigned NOT NULL DEFAULT '0', + `comment` varchar(255) DEFAULT NULL, + PRIMARY KEY (`raceMask`,`classMask`,`skill`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO `playercreateinfo_skills` (`raceMask`, `classMask`, `skill`, `rank`, `comment`) VALUES +(0, 0, 95, 0, 'Defense'), +(0, 0, 162, 0, 'Unarmed'), +(0, 0, 183, 0, 'GENERIC (DND)'), +(0, 0, 415, 0, 'Cloth'), +(0, 0, 777, 0, 'Mounts'), +(0, 0, 778, 0, 'Companion Pets'), +(0, 0, 934, 0, 'All - Specializations'), +(0, 3, 160, 0, 'Two-Handed Maces'), +(0, 4, 45, 0, 'Bows'), +(0, 4, 46, 0, 'Guns'), +(0, 4, 226, 0, 'Crossbows'), +(0, 8, 176, 0, 'Thrown'), +(0, 32, 129, 4, 'Death Knight - First Aid'), +(0, 32, 229, 0, 'Polearms'), +(0, 32, 293, 0, 'Plate'), +(0, 32, 762, 0, 'Death Knight - Riding'), +(0, 35, 55, 0, 'Two-Handed Swords'), +(0, 35, 413, 0, 'Mail'), +(0, 37, 44, 0, 'Axes'), +(0, 37, 172, 0, 'Two-Handed Axes'), +(0, 39, 43, 0, 'Swords'), +(0, 40, 118, 0, 'Dual Wield'), +(0, 67, 433, 0, 'Shield'), +(0, 400, 228, 0, 'Wands'), +(0, 1107, 54, 0, 'Maces'), +(0, 1135, 414, 0, 'Leather'), +(0, 1293, 173, 0, 'Daggers'), +(0, 1488, 136, 0, 'Staves'), +(1, 0, 754, 0, 'Human - Racial'), +(2, 0, 125, 0, 'Orc - Racial'), +(4, 0, 101, 0, 'Dwarf - Racial'), +(4, 0, 111, 0, 'Language: Dwarven'), +(8, 0, 113, 0, 'Language: Darnassian'), +(8, 0, 126, 0, 'Night Elf - Racial'), +(16, 0, 220, 0, 'Undead - Racial'), +(16, 0, 673, 0, 'Language: Forsaken'), +(32, 0, 115, 0, 'Language: Taurahe'), +(32, 0, 124, 0, 'Tauren - Racial'), +(64, 0, 313, 0, 'Language: Gnomish'), +(64, 0, 753, 0, 'Gnome - Racial'), +(128, 0, 315, 0, 'Language: Troll'), +(128, 0, 733, 0, 'Troll - Racial'), +(256, 0, 790, 0, 'Racial - Goblin'), +(256, 0, 792, 0, 'Language: Goblin'), +(512, 0, 137, 0, 'Language: Thalassian'), +(512, 0, 756, 0, 'Blood Elf - Racial'), +(946, 0, 109, 0, 'Language: Orcish'), +(1024, 0, 759, 0, 'Language: Draenei'), +(1024, 0, 760, 0, 'Draenei - Racial'), +(2097152, 0, 789, 0, 'Racial - Worgen'), +(2097152, 0, 791, 0, 'Language: Worgen'), +(2098253, 0, 98, 0, 'Language: Common'); diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index cc85b56615b..f23dd49102b 100644 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -518,7 +518,10 @@ void LoadDBCStores(const std::string& dataPath) SpecializationSpellsEntry const* specSpells = sSpecializationSpellsStore.LookupEntry(i); if (!specSpells) continue; - sSpecializationSpellsBySpecStore[specSpells->SpecID].insert(specSpells); + sSpecializationSpellsBySpecStore[specSpells->SpecID].push_back(specSpells); + + if (specSpells->OverridesSpellID) + sSpecializationOverrideSpellMap[specSpells->SpecID][specSpells->OverridesSpellID] = specSpells->SpellID; } LoadDBC(availableDbcLocales, bad_dbc_files, sSpellStore, dbcPath, "Spell.dbc"/*, &CustomSpellEntryfmt, &CustomSpellEntryIndex*/); LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCategoriesStore, dbcPath, "SpellCategories.dbc");//15595 @@ -1256,16 +1259,16 @@ std::list<uint32> GetSpellsForLevels(uint32 classId, uint32 raceMask, uint32 spe if (!specializationId) return spellList; - SpecializationSpellsMap::const_iterator specIter = sSpecializationSpellsMap.find(specializationId); - if (specIter != sSpecializationSpellsMap.end()) + SpecializationSpellsBySpecStore::const_iterator specIter = sSpecializationSpellsBySpecStore.find(specializationId); + if (specIter != sSpecializationSpellsBySpecStore.end()) { - const std::vector<uint32>& learnSpellList = specIter->second; + SpecializationSpellsBySpecEntry learnSpellList = specIter->second; for (int i = 0; i < learnSpellList.size(); i++) { - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(learnSpellList[i]); + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(learnSpellList[i]->SpellID); if (!spellInfo) { - TC_LOG_ERROR("spells", "GetSpellsForLevels: spell %u not found in spellstore", learnSpellList[i]); + TC_LOG_ERROR("spells", "GetSpellsForLevels: spell %u not found in spellstore", learnSpellList[i]->SpellID); continue; } if (spellInfo->SpellLevel <= minLevel || spellInfo->SpellLevel > maxLevel) diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h index a6ecadfaf45..633376d85aa 100644 --- a/src/server/game/DataStores/DBCStores.h +++ b/src/server/game/DataStores/DBCStores.h @@ -93,7 +93,7 @@ typedef std::unordered_multimap<uint32, SkillRaceClassInfoEntry const*> SkillRac typedef std::pair<SkillRaceClassInfoMap::iterator, SkillRaceClassInfoMap::iterator> SkillRaceClassInfoBounds; SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, uint8 class_); -typedef std::set<SpecializationSpellsEntry const*> SpecializationSpellsBySpecEntry; +typedef std::vector<SpecializationSpellsEntry const*> SpecializationSpellsBySpecEntry; typedef std::unordered_map<uint32, SpecializationSpellsBySpecEntry> SpecializationSpellsBySpecStore; typedef ChrSpecializationEntry const* ChrSpecializationByIndexArray[MAX_CLASSES][MAX_SPECIALIZATIONS]; typedef std::unordered_map<uint32, TalentEntry const*> TalentBySpellIDMap; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index d18f8542f16..740c96753ab 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -1122,7 +1122,7 @@ bool Player::Create(ObjectGuid::LowType guidlow, WorldPackets::Character::Charac } // original spells - LearnDefaultSpells(); + LearnDefaultSkills(); LearnCustomSpells(); // original action bar @@ -2985,11 +2985,39 @@ void Player::GiveLevel(uint8 level) SetByteFlag(PLAYER_FIELD_BYTES, 1, 0x01); } + std::list<uint32> learnList = GetSpellsForLevels(getClass(), getRaceMask(), GetTalentSpec(GetActiveTalentGroup()), oldLevel, level); + for (std::list<uint32>::const_iterator iter = learnList.begin(); iter != learnList.end(); iter++) + { + if (!HasSpell(*iter)) + LearnSpell(*iter, true); + } + sScriptMgr->OnPlayerLevelChanged(this, oldLevel); } void Player::InitTalentForLevel() { + uint8 level = getLevel(); + // talents base at level diff (talents = level - 9 but some can be used already) + if (level < 15) + { + // Remove all talent points + if (GetUsedTalentCount() > 0) // Free any used talents + { + ResetTalents(true); + } + } + else + { + if (level < sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL) || GetTalentGroupsCount() == 0) + { + SetTalentGroupsCount(1); + SetActiveTalentGroup(0); + } + } + + SetUInt32Value(PLAYER_FIELD_MAX_TALENT_TIERS, CalculateTalentsPoints()); + if (!GetSession()->PlayerLoading()) SendTalentsInfoData(); // update at client } @@ -3267,7 +3295,7 @@ void DeleteSpellFromAllPlayers(uint32 spellId) } } -bool Player::AddTalent(uint32 talentId, uint8 spec) +bool Player::AddTalent(uint32 talentId, uint8 spec, bool learning) { TalentEntry const* talentEntry = sTalentStore.LookupEntry(talentId); @@ -3309,15 +3337,28 @@ bool Player::AddTalent(uint32 talentId, uint8 spec) return false; } - TalentGroupInfo* talentGroupInfo = GetTalentGroupInfo(spec); + PlayerTalentMap::iterator itr = GetTalentMap(spec)->find(talentId); + if (itr == GetTalentMap(spec)->end()) + { + //if (GetTalentBySpellID(talentEntry->SpellID)) + { + PlayerSpellState state = learning ? PLAYERSPELL_NEW : PLAYERSPELL_UNCHANGED; + PlayerTalent* newtalent = new PlayerTalent(); - // Check if player already has this talent - if (talentGroupInfo->HasTalent(talentId)) - return false; + newtalent->state = state; + newtalent->spec = spec; - talentGroupInfo->Talents[talentEntry->TierID] = talentId; + (*GetTalentMap(spec))[talentId] = newtalent; - return true; + return true; + } + //else + // TC_LOG_ERROR("spells", "Player::addTalent: Talent %u not found in talent store.", talentId); + } + else + itr->second->state = PLAYERSPELL_UNCHANGED; + + return false; } bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent, bool disabled, bool loading /*= false*/, bool fromSkill /*= false*/) @@ -3421,9 +3462,9 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent SendSupercededSpell(spellId, next_active_spell_id); else { - WorldPacket data(SMSG_REMOVED_SPELL, 4); - data << uint32(spellId); - GetSession()->SendPacket(&data); + WorldPackets::Spells::SendRemovedSpell removedSpells; + removedSpells.Spells.push_back(spellId); + GetSession()->SendPacket(removedSpells.Write()); } } @@ -3594,11 +3635,15 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent if (HasSkill(pSkill->ID)) continue; + SkillRaceClassInfoEntry const* rcEntry = GetSkillRaceClassInfo(pSkill->ID, getRace(), getClass()); + if (!rcEntry) + continue; + if (_spell_idx->second->AquireMethod == SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN || // lockpicking/runeforging special case, not have SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN ((pSkill->ID == SKILL_LOCKPICKING || pSkill->ID == SKILL_RUNEFORGING) && (_spell_idx->second->TrivialSkillLineRankHigh == 0 || _spell_idx->second->TrivialSkillLineRankHigh == 1))) { - switch (GetSkillRangeType(pSkill, _spell_idx->second->RaceMask!= 0)) + switch (GetSkillRangeType(rcEntry)) { case SKILL_RANGE_LANGUAGE: SetSkill(pSkill->ID, GetSkillStep(pSkill->ID), 300, 300); @@ -3690,6 +3735,7 @@ bool Player::IsNeedCastPassiveSpellAtLearn(SpellInfo const* spellInfo) const bool Player::IsCurrentSpecMasterySpell(SpellInfo const* spellInfo) const { + if (ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(GetActiveTalentSpec())) return spellInfo->Id == chrSpec->MasterySpellID[0] || spellInfo->Id == chrSpec->MasterySpellID[1]; @@ -3893,9 +3939,9 @@ void Player::RemoveSpell(uint32 spell_id, bool disabled, bool learn_low_rank) // remove from spell book if not replaced by lesser rank if (!prev_activate) { - WorldPacket data(SMSG_REMOVED_SPELL, 4); - data << uint32(spell_id); - GetSession()->SendPacket(&data); + WorldPackets::Spells::SendRemovedSpell removedSpells; + removedSpells.Spells.push_back(spell_id); + GetSession()->SendPacket(removedSpells.Write()); } } @@ -4080,17 +4126,20 @@ uint32 Player::GetNextResetTalentsCost() const } } -bool Player::ResetTalents(bool no_cost) +bool Player::ResetTalents(bool noCost, bool resetTalents, bool resetSpecialization) { - sScriptMgr->OnPlayerTalentsReset(this, no_cost); + if (!resetTalents && !resetSpecialization) + return false; + sScriptMgr->OnPlayerTalentsReset(this, noCost); + // not need after this call if (HasAtLoginFlag(AT_LOGIN_RESET_TALENTS)) RemoveAtLoginFlag(AT_LOGIN_RESET_TALENTS, true); uint32 cost = 0; - if (!no_cost && !sWorld->getBoolConfig(CONFIG_NO_RESET_TALENT_COST)) + if (!noCost && !sWorld->getBoolConfig(CONFIG_NO_RESET_TALENT_COST)) { cost = GetNextResetTalentsCost(); @@ -4103,66 +4152,54 @@ bool Player::ResetTalents(bool no_cost) RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true); - uint8 group = GetActiveTalentGroup(); - uint32 specID = GetActiveTalentSpec(); - - for (uint32 talentId = 0; talentId < sTalentStore.GetNumRows(); ++talentId) + if (resetTalents) { - TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId); + for (uint32 talentId = 0; talentId < sTalentStore.GetNumRows(); ++talentId) + { + TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId); - if (!talentInfo) - continue; + if (!talentInfo) + continue; - // unlearn only talents for character class - // some spell learned by one class as normal spells or know at creation but another class learn it as talent, - // to prevent unexpected lost normal learned spell skip another class talents - if (getClass() != talentInfo->ClassID) - continue; + // unlearn only talents for character class + // some spell learned by one class as normal spells or know at creation but another class learn it as talent, + // to prevent unexpected lost normal learned spell skip another class talents + if (talentInfo->ClassID != getClass()) + continue; - const SpellInfo* _spellEntry = sSpellMgr->GetSpellInfo(talentInfo->SpellID); + SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(talentInfo->SpellID); + if (!spellEntry) + continue; - if (!_spellEntry) - continue; + RemoveSpell(spellEntry->Id, false); - RemoveSpell(talentInfo->SpellID, true); + // search for spells that the talent teaches and unlearn them, 6.x remove? + for (SpellEffectInfo const* effect : spellEntry->GetEffectsForDifficulty(DIFFICULTY_NONE)) + if (effect && effect->TriggerSpell > 0 && effect->Effect == SPELL_EFFECT_LEARN_SPELL) + RemoveSpell(effect->TriggerSpell, true); - // search for spells that the talent teaches and unlearn them - for (SpellEffectInfo const* effect : _spellEntry->GetEffectsForDifficulty(DIFFICULTY_NONE)) - if (effect && effect->TriggerSpell > 0 && effect->Effect == SPELL_EFFECT_LEARN_SPELL) - RemoveSpell(effect->TriggerSpell, true); + GetTalentMap(GetActiveTalentGroup())->erase(talentId); + } } - // Remove all specialization specific spells and give default ones which were overriden - auto specSpells = sSpecializationSpellsBySpecStore.find(specID); - if (specSpells != sSpecializationSpellsBySpecStore.end()) + if (resetSpecialization) { - for (auto it = specSpells->second.begin(); it != specSpells->second.end(); ++it) + std::list<uint32> learnList = GetSpellsForLevels(0, getRaceMask(), GetTalentSpec(GetActiveTalentGroup()), 0, getLevel()); + for (std::list<uint32>::const_iterator iter = learnList.begin(); iter != learnList.end(); iter++) { - SpecializationSpellsEntry const* specSpell = *it; - if (HasSpell(specSpell->SpellID)) { - RemoveSpell(specSpell->SpellID, true); - if (specSpell->OverridesSpellID) - LearnSpell(specSpell->OverridesSpellID, false); - } + if (HasSpell(*iter)) + RemoveSpell(*iter, true); } + SetTalentSpec(GetActiveTalentGroup(), 0); + SetUInt32Value(PLAYER_FIELD_CURRENT_SPEC_ID, 0); } - // Unlearn masteries - if (ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(specID)) - for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i) - if (uint32 mastery = chrSpec->MasterySpellID[i]) - RemoveAurasDueToSpell(mastery); - - // Reset talents store - GetTalentGroupInfo(group)->Reset(); - SetTalentSpec(group, 0); - SQLTransaction trans = CharacterDatabase.BeginTransaction(); _SaveTalents(trans); _SaveSpells(trans); CharacterDatabase.CommitTransaction(trans); - if (!no_cost) + if (!noCost) { ModifyMoney(-(int64)cost); UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS, cost); @@ -4183,6 +4220,35 @@ bool Player::ResetTalents(bool no_cost) return true; } +bool Player::RemoveTalent(uint32 talentId) +{ + TalentEntry const* talent = sTalentStore.LookupEntry(talentId); + if (!talent) + return false; + + uint32 spellId = talent->SpellID; + + SpellInfo const* unlearnSpellProto = sSpellMgr->GetSpellInfo(spellId); + + RemoveSpell(spellId, false); + + // 6.x remove? + for (SpellEffectInfo const* effect : unlearnSpellProto->GetEffectsForDifficulty(DIFFICULTY_NONE)) + if (effect && effect->TriggerSpell > 0 && effect->Effect == SPELL_EFFECT_LEARN_SPELL) + RemoveSpell(effect->TriggerSpell, false); + + GetTalentMap(GetActiveTalentSpec())->erase(talentId); + + // Needs to be executed orthewise the talents will be screwedsx + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + _SaveTalents(trans); + _SaveSpells(trans); + CharacterDatabase.CommitTransaction(trans); + + SendTalentsInfoData(); + return true; +} + Mail* Player::GetMail(uint32 id) { for (PlayerMails::iterator itr = m_mail.begin(); itr != m_mail.end(); ++itr) @@ -4249,7 +4315,8 @@ bool Player::HasSpell(uint32 spell) const bool Player::HasTalent(uint32 talentId, uint8 group) { - return GetTalentGroupInfo(group)->HasTalent(talentId); + PlayerTalentMap::const_iterator itr = GetTalentMap(group)->find(talentId); + return (itr != GetTalentMap(group)->end()); } bool Player::HasActiveSpell(uint32 spell) const @@ -5892,14 +5959,14 @@ void Player::UpdateSkillsForLevel() continue; uint32 pskill = itr->first; - SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(pskill); - if (!pSkill) + SkillRaceClassInfoEntry const* rcEntry = GetSkillRaceClassInfo(pskill, getRace(), getClass()); + if (!rcEntry) continue; - if (GetSkillRangeType(pSkill, false) != SKILL_RANGE_LEVEL) + if (GetSkillRangeType(rcEntry) != SKILL_RANGE_LEVEL) continue; - if (IsWeaponSkill(pSkill->ID)) + if (IsWeaponSkill(rcEntry->SkillID)) continue; uint16 field = itr->second.pos / 2; @@ -17415,11 +17482,16 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) break; uint32 talentSpec = atoul(talentSpecs[i]); - if (sChrSpecializationStore.LookupEntry(talentSpec)) - SetTalentSpec(i, talentSpec); - else - SetAtLoginFlag(AT_LOGIN_RESET_TALENTS); + if (talentSpec) + { + if (sChrSpecializationStore.LookupEntry(talentSpec)) + SetTalentSpec(i, talentSpec); + else + SetAtLoginFlag(AT_LOGIN_RESET_TALENTS); + } } + + SetUInt32Value(PLAYER_FIELD_CURRENT_SPEC_ID, GetActiveTalentSpec()); _LoadTalents(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_TALENTS)); _LoadSpells(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_SPELLS)); @@ -17442,7 +17514,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) // after spell and quest load InitTalentForLevel(); - LearnDefaultSpells(); + LearnDefaultSkills(); LearnCustomSpells(); // must be before inventory (some items required reputation check) @@ -18486,6 +18558,13 @@ void Player::_LoadSpells(PreparedQueryResult result) AddSpell((*result)[0].GetUInt32(), (*result)[1].GetBool(), false, false, (*result)[2].GetBool(), true); while (result->NextRow()); } + + std::list<uint32> learnList = GetSpellsForLevels(getClass(), getRaceMask(), GetActiveTalentSpec(), 0, getLevel()); + for (std::list<uint32>::const_iterator iter = learnList.begin(); iter != learnList.end(); iter++) + { + if (!HasSpell(*iter)) + LearnSpell(*iter, true); + } } void Player::_LoadGroup(PreparedQueryResult result) @@ -23243,8 +23322,8 @@ void Player::ResetSpells(bool myClassOnly) else for (PlayerSpellMap::const_iterator iter = smap.begin(); iter != smap.end(); ++iter) RemoveSpell(iter->first, false, false); // only iter->first can be accessed, object by iter->second can be deleted already - - LearnDefaultSpells(); + + LearnDefaultSkills(); LearnCustomSpells(); LearnQuestRewardedSpells(); } @@ -23267,21 +23346,72 @@ void Player::LearnCustomSpells() } } -void Player::LearnDefaultSpells() +void Player::LearnDefaultSkills() { - // learn default race/class spells + // learn default race/class skills PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getRace(), getClass()); - for (PlayerCreateInfoSpells::const_iterator itr = info->spells.begin(); itr != info->spells.end(); ++itr) + for (PlayerCreateInfoSkills::const_iterator itr = info->skills.begin(); itr != info->skills.end(); ++itr) { - uint32 tspell = *itr; - TC_LOG_DEBUG("entities.player.loading", "PLAYER (Class: %u Race: %u): Adding initial spell, id = %u", uint32(getClass()), uint32(getRace()), tspell); - if (!IsInWorld()) // will send in INITIAL_SPELLS in list anyway at map add - AddSpell(tspell, true, true, true, false); - else // but send in normal spell in game learn case - LearnSpell(tspell, true); + uint32 skillId = itr->SkillId; + if (HasSkill(skillId)) + continue; + + LearnDefaultSkill(skillId, itr->Rank); + } +} + +void Player::LearnDefaultSkill(uint32 skillId, uint16 rank) +{ + SkillRaceClassInfoEntry const* rcInfo = GetSkillRaceClassInfo(skillId, getRace(), getClass()); + if (!rcInfo) + return; + + switch (GetSkillRangeType(rcInfo)) + { + case SKILL_RANGE_LANGUAGE: + SetSkill(skillId, 0, 300, 300); + break; + case SKILL_RANGE_LEVEL: + { + uint16 skillValue = 1; + uint16 maxValue = GetMaxSkillValueForLevel(); + if (rcInfo->Flags & SKILL_FLAG_ALWAYS_MAX_VALUE) + skillValue = maxValue; + else if (getClass() == CLASS_DEATH_KNIGHT) + skillValue = std::min(std::max<uint16>({ 1, uint16((getLevel() - 1) * 5) }), maxValue); + else if (skillId == SKILL_FIST_WEAPONS) + skillValue = std::max<uint16>(1, GetSkillValue(SKILL_UNARMED)); + else if (skillId == SKILL_LOCKPICKING) + skillValue = std::max<uint16>(1, GetSkillValue(SKILL_LOCKPICKING)); + + SetSkill(skillId, 0, skillValue, maxValue); + break; + } + case SKILL_RANGE_MONO: + SetSkill(skillId, 0, 1, 1); + break; + case SKILL_RANGE_RANK: + { + if (!rank) + break; + + SkillTiersEntry const* tier = sSkillTiersStore.LookupEntry(rcInfo->SkillTierID); + uint16 maxValue = tier->Value[std::max<int32>(rank - 1, 0)]; + uint16 skillValue = 1; + if (rcInfo->Flags & SKILL_FLAG_ALWAYS_MAX_VALUE) + skillValue = maxValue; + else if (getClass() == CLASS_DEATH_KNIGHT) + skillValue = std::min(std::max<uint16>({ uint16(1), uint16((getLevel() - 1) * 5) }), maxValue); + + SetSkill(skillId, rank, skillValue, maxValue); + break; + } + default: + break; } } + void Player::LearnQuestRewardedSpells(Quest const* quest) { int32 spell_id = quest->GetRewSpellCast(); @@ -23396,31 +23526,41 @@ void Player::LearnQuestRewardedSpells() void Player::LearnSkillRewardedSpells(uint32 skillId, uint32 skillValue) { - uint32 raceMask = getRaceMask(); + uint32 raceMask = getRaceMask(); uint32 classMask = getClassMask(); for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j) { - SkillLineAbilityEntry const* pAbility = sSkillLineAbilityStore.LookupEntry(j); - if (!pAbility || pAbility->SkillLine != skillId || pAbility->AquireMethod != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_VALUE) + SkillLineAbilityEntry const* ability = sSkillLineAbilityStore.LookupEntry(j); + if (!ability || ability->SkillLine != skillId) + continue; + + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(ability->SpellID); + if (!spellInfo) + continue; + + if (ability->AquireMethod != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_VALUE && ability->AquireMethod != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN) continue; + // Check race if set - if (pAbility->RaceMask && !(pAbility->RaceMask & raceMask)) + if (ability->RaceMask && !(ability->RaceMask & raceMask)) continue; + // Check class if set - if (pAbility->ClassMask && !(pAbility->ClassMask & classMask)) + if (ability->ClassMask && !(ability->ClassMask & classMask)) continue; - if (sSpellMgr->GetSpellInfo(pAbility->SpellID)) - { - // need unlearn spell - if (skillValue < pAbility->MinSkillLineRank) - RemoveSpell(pAbility->SpellID); - // need learn - else if (!IsInWorld()) - AddSpell(pAbility->SpellID, true, true, true, false); - else - LearnSpell(pAbility->SpellID, true); - } + // check level, skip class spells if not high enough + if (getLevel() < spellInfo->SpellLevel) + continue; + + // need unlearn spell + if (skillValue < ability->MinSkillLineRank && ability->AquireMethod == SKILL_LINE_ABILITY_LEARNED_ON_SKILL_VALUE) + RemoveSpell(ability->SpellID); + // need learn + else if (!IsInWorld()) + AddSpell(ability->SpellID, true, true, true, false, false, true); + else + LearnSpell(ability->SpellID, true, true); } } @@ -25135,8 +25275,8 @@ void Player::_LoadSkills(PreparedQueryResult result) uint16 value = fields[1].GetUInt16(); uint16 max = fields[2].GetUInt16(); - SkillLineEntry const* skillLine = sSkillLineStore.LookupEntry(skill); - if (!skillLine) + SkillRaceClassInfoEntry const* rcEntry = GetSkillRaceClassInfo(skill, getRace(), getClass()); + if (!rcEntry) { TC_LOG_ERROR("entities.player", "Character: %s (%s Race: %u Class: %u) has skill %u not allowed for his race/class combination", GetName().c_str(), GetGUID().ToString().c_str(), uint32(getRace()), uint32(getClass()), skill); @@ -25146,7 +25286,7 @@ void Player::_LoadSkills(PreparedQueryResult result) } // set fixed skill ranges - switch (GetSkillRangeType(skillLine, false)) + switch (GetSkillRangeType(rcEntry)) { case SKILL_RANGE_LANGUAGE: // 300..300 value = max = 300; @@ -25180,15 +25320,19 @@ void Player::_LoadSkills(PreparedQueryResult result) SetUInt16Value(PLAYER_SKILL_LINEID + SKILL_ID_OFFSET + field, offset, skill); uint16 step = 0; - if (skillLine->CategoryID == SKILL_CATEGORY_SECONDARY) - step = max / 75; - - if (skillLine->CategoryID == SKILL_CATEGORY_PROFESSION) + SkillLineEntry const* skillLine = sSkillLineStore.LookupEntry(rcEntry->SkillID); + if (skillLine) { - step = max / 75; + if (skillLine->CategoryID == SKILL_CATEGORY_SECONDARY) + step = max / 75; + + if (skillLine->CategoryID == SKILL_CATEGORY_PROFESSION) + { + step = max / 75; - if (professionCount < 2) - SetUInt32Value(PLAYER_PROFESSION_SKILL_LINE_1 + professionCount++, skill); + if (professionCount < 2) + SetUInt32Value(PLAYER_PROFESSION_SKILL_LINE_1 + professionCount++, skill); + } } SetUInt16Value(PLAYER_SKILL_LINEID + SKILL_STEP_OFFSET + field, offset, step); @@ -25407,37 +25551,36 @@ void Player::CompletedAchievement(AchievementEntry const* entry) bool Player::LearnTalent(uint32 talentId) { - uint8 group = GetActiveTalentGroup(); - - // check if talent specialization is learnt - if (!GetTalentSpec(group)) - return false; - TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId); if (!talentInfo) return false; + + uint32 maxTalentTier = GetUInt32Value(PLAYER_FIELD_MAX_TALENT_TIERS); // prevent learn talent for different class (cheating) - if (getClass() != talentInfo->ClassID) + if (talentInfo->ClassID != getClass()) return false; - // Check player level - // TODO: fix level requirements for deathknights - uint8 levelReq = std::min(15*talentInfo->TierID + 15, sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)); - if (getLevel() < levelReq) + // check if we have enough talent points + if (talentInfo->TierID > maxTalentTier) return false; - // Check if such tier talent hasn't been picked already - TalentGroupInfo* talentGroupInfo = GetTalentGroupInfo(group); - if (talentGroupInfo->Talents[talentInfo->TierID]) - return false; + // Check if player doesnt have any spell in selected collumn + for (uint32 i = 0; i < sTalentStore.GetNumRows(); i++) + { + if (TalentEntry const* talent = sTalentStore.LookupEntry(i)) + { + if (talentInfo->TierID == talent->TierID && HasSpell(talent->SpellID)) + return false; + } + } // spell not set in talent.dbc uint32 spellid = talentInfo->SpellID; if (spellid == 0) { - TC_LOG_ERROR("entities.player", "Talent.dbc have for talent: %u spell id = 0", talentId); + TC_LOG_ERROR("entities.player", "Talent.dbc has no spellInfo for talent: %u (spell id = 0)", talentId); return false; } @@ -25445,54 +25588,39 @@ bool Player::LearnTalent(uint32 talentId) if (HasSpell(spellid)) return false; - // Check talent spec - if (talentInfo->SpecID != GetTalentSpec(group)) + if (!AddTalent(talentId, GetActiveTalentGroup(), true)) return false; - // learn! (other talent ranks will unlearned at learning) LearnSpell(spellid, false); - AddTalent(talentId, group); - TC_LOG_INFO("misc", "TalentID: %u Spell: %u Group: %u\n", talentId, spellid, group); + TC_LOG_INFO("misc", "TalentID: %u Spell: %u Group: %u\n", talentId, spellid, GetActiveTalentGroup()); return true; } void Player::LearnTalentSpecialization(uint32 talentSpec) { - SetTalentSpec(GetActiveTalentGroup(), talentSpec); - - // Replace default spells by specialization spells - auto specSpells = sSpecializationSpellsBySpecStore.find(talentSpec); - if (specSpells != sSpecializationSpellsBySpecStore.end()) - { - for (auto it = specSpells->second.begin(); it != specSpells->second.end(); ++it) - { - SpecializationSpellsEntry const* specSpell = *it; + if (GetActiveTalentSpec()) + return; - // Unlearn spell if it is replaced by new specialization - if (specSpell->OverridesSpellID) - RemoveSpell(specSpell->OverridesSpellID, true); + SetTalentSpec(GetActiveTalentGroup(), talentSpec); - // Learn new spell - if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(specSpell->SpellID)) - if (spellInfo->BaseLevel <= getLevel()) - LearnSpell(specSpell->SpellID, false); - } - } + SetUInt32Value(PLAYER_FIELD_CURRENT_SPEC_ID, talentSpec); + SendTalentsInfoData(); - if (CanUseMastery()) + std::list<uint32> learnList = GetSpellsForLevels(0, getRaceMask(), GetActiveTalentSpec(), 0, getLevel()); + for (std::list<uint32>::const_iterator iter = learnList.begin(); iter != learnList.end(); iter++) { - ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(talentSpec); - for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i) - if (SpellInfo const* masterySpell = sSpellMgr->GetSpellInfo(chrSpec->MasterySpellID[i])) - if (masterySpell->IsPassive() && IsNeedCastPassiveSpellAtLearn(masterySpell)) - CastSpell(this, masterySpell->Id, true); + if (!HasSpell(*iter)) + LearnSpell(*iter, true); } + SaveToDB(); + SendTalentsInfoData(); } + void Player::AddKnownCurrency(uint32 itemId) { if (CurrencyTypesEntry const* ctEntry = sCurrencyTypesStore.LookupEntry(itemId)) @@ -25577,23 +25705,39 @@ void Player::SendTalentsInfoData() for (uint8 i = 0; i < groupsCount; ++i) { - TalentGroupInfo* groupInfo = GetTalentGroupInfo(i); WorldPackets::Talent::TalentGroupInfo groupInfoPkt; - groupInfoPkt.SpecID = groupInfo->SpecID; + groupInfoPkt.SpecID = GetTalentSpec(i); + + groupInfoPkt.TalentIDs.reserve(GetTalentMap(i)->size()); - groupInfoPkt.TalentIDs.reserve(MAX_TALENT_TIERS); - for (uint32 x = 0; x < MAX_TALENT_TIERS; ++x) + for (PlayerTalentMap::const_iterator itr = GetTalentMap(i)->begin(); itr != GetTalentMap(i)->end(); ++itr) { - // Do not send empty talents - if (!groupInfo->Talents[x]) - break; + TalentEntry const* talentInfo = sTalentStore.LookupEntry(itr->first); + if (!talentInfo) + { + TC_LOG_ERROR("entities.player", "Player %s has unknown talent id: %u", GetName().c_str(), itr->first); + continue; + } - groupInfoPkt.TalentIDs.push_back(groupInfo->Talents[x]); + if (talentInfo->ClassID != getClass()) + continue; + + SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(talentInfo->SpellID); + if (!spellEntry) + { + TC_LOG_ERROR("entities.player", "Player %s has unknown talent spell: %u", GetName().c_str(), talentInfo->SpellID); + continue; + } + + if (!HasTalent(itr->first, i)) + continue; + + groupInfoPkt.TalentIDs.push_back(uint16(itr->first)); } for (uint32 x = 0; x < MAX_GLYPH_SLOT_INDEX; ++x) - groupInfoPkt.GlyphIDs[x] = groupInfo->Glyphs[x]; + groupInfoPkt.GlyphIDs[x] = uint16(GetGlyph(i, x)); packet.Info.TalentGroups.push_back(groupInfoPkt); } @@ -25905,7 +26049,7 @@ void Player::_LoadTalents(PreparedQueryResult result) if (result) { do - AddTalent((*result)[0].GetUInt32(), (*result)[1].GetUInt8()); + AddTalent((*result)[0].GetUInt32(), (*result)[1].GetUInt8(), false); while (result->NextRow()); } } @@ -25918,17 +26062,12 @@ void Player::_SaveTalents(SQLTransaction& trans) for (uint8 group = 0; group < MAX_TALENT_GROUPS; ++group) { - TalentGroupInfo* talentGroupInfo = GetTalentGroupInfo(group); - - for (uint32 tier = 0; tier < MAX_TALENT_TIERS; ++tier) + for (PlayerTalentMap::iterator itr = GetTalentMap(group)->begin(); itr != GetTalentMap(group)->end(); ++itr) { - if (!talentGroupInfo->Talents[tier]) - continue; - stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_TALENT); stmt->setUInt64(0, GetGUID().GetCounter()); - stmt->setUInt32(1, talentGroupInfo->Talents[tier]); - stmt->setUInt8(2, group); + stmt->setUInt32(1, itr->first); + stmt->setUInt8(2, itr->second->spec); trans->Append(stmt); } } @@ -26027,30 +26166,27 @@ void Player::ActivateTalentGroup(uint8 group) if (getClass() != talentInfo->ClassID) continue; + SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(talentInfo->SpellID); + if (!spellEntry) + continue; + RemoveSpell(talentInfo->SpellID, true); + + // search for spells that the talent teaches and unlearn them + for (SpellEffectInfo const* effect : spellEntry->GetEffectsForDifficulty(DIFFICULTY_NONE)) + if (effect && effect->TriggerSpell > 0 && effect->Effect == SPELL_EFFECT_LEARN_SPELL) + RemoveSpell(effect->TriggerSpell, true); } // Unlearn specialization specific spells - auto specSpells = sSpecializationSpellsBySpecStore.find(GetActiveTalentSpec()); - if (specSpells != sSpecializationSpellsBySpecStore.end()) + std::list<uint32> learnList = GetSpellsForLevels(0, getRaceMask(), GetActiveTalentSpec(), 0, getLevel()); + for (std::list<uint32>::const_iterator iter = learnList.begin(); iter != learnList.end(); iter++) { - for (auto it = specSpells->second.begin(); it != specSpells->second.end(); ++it) - { - SpecializationSpellsEntry const* specSpell = *it; - if (HasSpell(specSpell->SpellID)) { - RemoveSpell(specSpell->SpellID, true); - LearnSpell(specSpell->OverridesSpellID, false); - } - } + if (HasSpell(*iter)) + RemoveSpell(*iter, true); } - // Unlearn mastery spells - ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(GetActiveTalentSpec()); - for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i) - if (chrSpec->MasterySpellID[i]) - RemoveSpell(chrSpec->MasterySpellID[i], true); - - // set glyphs + // remove glyphs for (uint8 slot = 0; slot < MAX_GLYPH_SLOT_INDEX; ++slot) // remove secondary glyph if (uint32 oldglyph = GetGlyph(GetActiveTalentGroup(), slot)) @@ -26060,6 +26196,15 @@ void Player::ActivateTalentGroup(uint8 group) // Activate new group SetActiveTalentGroup(group); + uint32 spentTalents = 0; + + learnList = GetSpellsForLevels(getClass(), getRaceMask(), GetActiveTalentSpec(), 0, getLevel()); + for (std::list<uint32>::const_iterator iter = learnList.begin(); iter != learnList.end(); iter++) + { + if (!HasSpell(*iter)) + LearnSpell(*iter, true); + } + for (uint32 talentId = 0; talentId < sTalentStore.GetNumRows(); ++talentId) { TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId); @@ -26071,31 +26216,12 @@ void Player::ActivateTalentGroup(uint8 group) if (getClass() != talentInfo->ClassID) continue; - LearnSpell(talentInfo->SpellID, false); - } + ++spentTalents; - // Replace default spells with specialization specific spells - auto newSpecSpells = sSpecializationSpellsBySpecStore.find(GetActiveTalentSpec()); - if (newSpecSpells != sSpecializationSpellsBySpecStore.end()) - { - for (auto it = newSpecSpells->second.begin(); it != newSpecSpells->second.end(); ++it) - { - SpecializationSpellsEntry const* specSpell = *it; - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(specSpell->SpellID); - if (getLevel() >= spellInfo->BaseLevel) { - if (specSpell->OverridesSpellID) - RemoveSpell(specSpell->OverridesSpellID, true); - LearnSpell(specSpell->SpellID, false); - } - } + if (HasTalent(talentInfo->SpellID, group)) + LearnSpell(talentInfo->SpellID, false); } - if (CanUseMastery()) - if (ChrSpecializationEntry const* newChrSpec = sChrSpecializationStore.LookupEntry(GetActiveTalentSpec())) - for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i) - if (newChrSpec->MasterySpellID[i]) - LearnSpell(newChrSpec->MasterySpellID[i], false); - // set glyphs for (uint8 slot = 0; slot < MAX_GLYPH_SLOT_INDEX; ++slot) { @@ -26109,6 +26235,7 @@ void Player::ActivateTalentGroup(uint8 group) SetGlyph(slot, glyph); } + SetUsedTalentCount(spentTalents); InitTalentForLevel(); { @@ -26128,7 +26255,9 @@ void Player::ActivateTalentGroup(uint8 group) SetPower(pw, 0); if (!sChrSpecializationStore.LookupEntry(GetActiveTalentSpec())) + { ResetTalents(true); + } } void Player::ResetTimeSync() @@ -27168,3 +27297,9 @@ void Player::SendSupercededSpell(uint32 oldSpell, uint32 newSpell) data << uint32(newSpell) << uint32(oldSpell); GetSession()->SendPacket(&data); } + +uint32 Player::CalculateTalentsPoints() const +{ + // 1 talent point for every 15 levels + return getLevel() >= 100 ? 7 : uint32(floor(getLevel() / 15.f)); +}
\ No newline at end of file diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 2d919159819..6b9e925e28d 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -116,6 +116,12 @@ struct PlayerSpell bool disabled : 1; // first rank has been learned in result talent learn but currently talent unlearned, save max learned ranks }; +struct PlayerTalent +{ + PlayerSpellState state : 8; + uint8 spec : 8; +}; + extern uint32 const MasterySpells[MAX_CLASSES]; enum TalentSpecialization // talent tabs @@ -184,6 +190,7 @@ struct PlayerCurrency uint32 weekCount; }; +typedef std::unordered_map<uint32, PlayerTalent*> PlayerTalentMap; typedef std::unordered_map<uint32, PlayerSpell*> PlayerSpellMap; typedef std::list<SpellModifier*> SpellModList; typedef std::unordered_map<uint32, PlayerCurrency> PlayerCurrenciesMap; @@ -412,9 +419,9 @@ struct PlayerInfo uint16 displayId_f; PlayerCreateInfoItems item; PlayerCreateInfoSpells customSpells; - PlayerCreateInfoSpells spells; PlayerCreateInfoSpells castSpells; PlayerCreateInfoActions action; + PlayerCreateInfoSkills skills; PlayerLevelInfo* levelInfo; //[level-1] 0..MaxPlayerLevel-1 }; @@ -1223,56 +1230,41 @@ private: bool _isPvP; }; -struct TalentGroupInfo +struct PlayerTalentInfo { - uint32 Talents[MAX_TALENT_TIERS]; - uint32 Glyphs[MAX_GLYPH_SLOT_INDEX]; - uint32 SpecID; - - bool HasTalent(uint32 talentId) - { - for (uint32 i = 0; i < MAX_TALENT_TIERS; ++i) - if (Talents[i] == talentId) - return true; - return false; - } - - uint32 TalentCount() + PlayerTalentInfo() : UsedTalentCount(0), ResetTalentsCost(0), ResetTalentsTime(0), ActiveGroup(0), GroupsCount(1) { - for (uint32 i = 0; i < MAX_TALENT_TIERS; ++i) - if (!Talents[i]) - return i; - return MAX_TALENT_TIERS; + for (uint8 i = 0; i < MAX_TALENT_GROUPS; ++i) + { + GroupInfo[i].Talents = new PlayerTalentMap(); + memset(GroupInfo[i].Glyphs, 0, MAX_GLYPH_SLOT_INDEX * sizeof(uint32)); + GroupInfo[i].TalentTree = 0; + } } - void Reset() - { - for (uint32 i = 0; i < MAX_TALENT_TIERS; ++i) - Talents[i] = 0; - } -}; - -struct PlayerTalentInfo -{ - PlayerTalentInfo() : ResetTalentsCost(0), ResetTalentsTime(0), ActiveGroup(0), GroupsCount(1) + ~PlayerTalentInfo() { for (uint8 i = 0; i < MAX_TALENT_GROUPS; ++i) { - memset(GroupInfo[i].Talents, 0, sizeof(uint32)*MAX_TALENT_TIERS); - memset(GroupInfo[i].Glyphs, 0, MAX_GLYPH_SLOT_INDEX * sizeof(uint32)); - GroupInfo[i].SpecID = 0; + for (PlayerTalentMap::const_iterator itr = GroupInfo[i].Talents->begin(); itr != GroupInfo[i].Talents->end(); ++itr) + delete itr->second; + delete GroupInfo[i].Talents; } } - TalentGroupInfo GroupInfo[MAX_TALENT_GROUPS]; + struct TalentGroupInfo + { + PlayerTalentMap* Talents; + uint32 Glyphs[MAX_GLYPH_SLOT_INDEX]; + uint32 TalentTree; + } GroupInfo[MAX_TALENT_GROUPS]; + + uint32 UsedTalentCount; uint32 ResetTalentsCost; time_t ResetTalentsTime; uint8 ActiveGroup; uint8 GroupsCount; - - uint32 UsedTalentCount; - private: PlayerTalentInfo(PlayerTalentInfo const&); }; @@ -1824,7 +1816,8 @@ class Player : public Unit, public GridObject<Player> void RemoveSpell(uint32 spell_id, bool disabled = false, bool learn_low_rank = true); void ResetSpells(bool myClassOnly = false); void LearnCustomSpells(); - void LearnDefaultSpells(); + void LearnDefaultSkills(); + void LearnDefaultSkill(uint32 skillId, uint16 rank); void LearnQuestRewardedSpells(); void LearnQuestRewardedSpells(Quest const* quest); void LearnSpellHighestRank(uint32 spellid); @@ -1837,26 +1830,33 @@ class Player : public Unit, public GridObject<Player> // Talents uint32 GetUsedTalentCount() const { return _talentMgr->UsedTalentCount; } void SetUsedTalentCount(uint32 talents) { _talentMgr->UsedTalentCount = talents; } - uint32 GetTalentResetCost() const { return _talentMgr->ResetTalentsCost; } void SetTalentResetCost(uint32 cost) { _talentMgr->ResetTalentsCost = cost; } uint32 GetTalentResetTime() const { return _talentMgr->ResetTalentsTime; } void SetTalentResetTime(time_t time_) { _talentMgr->ResetTalentsTime = time_; } - uint8 GetActiveTalentGroup() const { return _talentMgr->ActiveGroup; } - void SetActiveTalentGroup(uint8 group){ _talentMgr->ActiveGroup = group; } + uint8 GetTalentGroupsCount() const { return _talentMgr->GroupsCount; } void SetTalentGroupsCount(uint8 count) { _talentMgr->GroupsCount = count; } - uint32 GetTalentSpec(uint8 group) const { return _talentMgr->GroupInfo[group].SpecID; } - void SetTalentSpec(uint8 group, uint32 talentSpec) const { _talentMgr->GroupInfo[group].SpecID = talentSpec; } - uint32 GetActiveTalentSpec() const { return _talentMgr->GroupInfo[_talentMgr->ActiveGroup].SpecID; } + uint8 GetActiveTalentGroup() const { return _talentMgr->ActiveGroup; } + void SetActiveTalentGroup(uint8 group){ _talentMgr->ActiveGroup = group; } + + uint32 GetTalentSpec(uint8 group) const { return _talentMgr->GroupInfo[group].TalentTree; } + void SetTalentSpec(uint8 group, uint32 talentSpec) const { _talentMgr->GroupInfo[group].TalentTree = talentSpec; } + uint32 GetActiveTalentSpec() const { return _talentMgr->GroupInfo[_talentMgr->ActiveGroup].TalentTree; } + + + bool ResetTalents(bool noCost = false, bool resetTalents = true, bool resetSpecialization = true); + bool RemoveTalent(uint32 talentId); - bool ResetTalents(bool no_cost = false); uint32 GetNextResetTalentsCost() const; void InitTalentForLevel(); void SendTalentsInfoData(); bool LearnTalent(uint32 talentId); - bool AddTalent(uint32 talentId, uint8 spec); + bool AddTalent(uint32 talentId, uint8 spec, bool learning); bool HasTalent(uint32 talentId, uint8 spec); + uint32 CalculateTalentsPoints() const; + + void LearnTalentSpecialization(uint32 talentSpec); // Dual Spec @@ -1870,7 +1870,8 @@ class Player : public Unit, public GridObject<Player> void SetGlyph(uint8 slot, uint32 glyph); uint32 GetGlyph(uint8 group, uint8 slot) const { return _talentMgr->GroupInfo[group].Glyphs[slot]; } - TalentGroupInfo* GetTalentGroupInfo(uint8 group) { return &_talentMgr->GroupInfo[group]; } + PlayerTalentMap const* GetTalentMap(uint8 spec) const { return _talentMgr->GroupInfo[spec].Talents; } + PlayerTalentMap* GetTalentMap(uint8 spec) { return _talentMgr->GroupInfo[spec].Talents; } ActionButtonList const& GetActionButtons() const { return m_actionButtons; } uint32 GetFreePrimaryProfessionPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS); } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 5fbc6e7632c..e4f12614b33 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -3033,7 +3033,7 @@ Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint3 bp = *(baseAmount + effect->EffectIndex); else bp = effect->BasePoints; - TC_LOG_ERROR("spells", "_TryStackingOrRefreshingExistingAura spell %u effMask %u currIdx %u", newAura->Id, effMask, effect->EffectIndex); + int32* oldBP = const_cast<int32*>(&(foundAura->GetEffect(effect->EffectIndex)->m_baseAmount)); // todo 6.x review GetBaseAmount and GetCastItemGUID in this case *oldBP = bp; } diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 4858800b3d2..ae39c405e26 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -3279,16 +3279,16 @@ void ObjectMgr::LoadPlayerInfo() } } - // Load playercreate spells - TC_LOG_INFO("server.loading", "Loading Player Create Spell Data..."); + // Load playercreate skills + TC_LOG_INFO("server.loading", "Loading Player Create Skill Data..."); { uint32 oldMSTime = getMSTime(); - QueryResult result = WorldDatabase.PQuery("SELECT racemask, classmask, Spell FROM playercreateinfo_spell"); + QueryResult result = WorldDatabase.PQuery("SELECT raceMask, classMask, skill, rank FROM playercreateinfo_skills"); if (!result) { - TC_LOG_ERROR("server.loading", ">> Loaded 0 player create spells. DB table `playercreateinfo_spell` is empty."); + TC_LOG_ERROR("server.loading", ">> Loaded 0 player create skills. DB table `playercreateinfo_skills` is empty."); } else { @@ -3299,17 +3299,31 @@ void ObjectMgr::LoadPlayerInfo() Field* fields = result->Fetch(); uint32 raceMask = fields[0].GetUInt32(); uint32 classMask = fields[1].GetUInt32(); - uint32 spellId = fields[2].GetUInt32(); + PlayerCreateInfoSkill skill; + skill.SkillId = fields[2].GetUInt16(); + skill.Rank = fields[3].GetUInt16(); + + if (skill.Rank >= MAX_SKILL_STEP) + { + TC_LOG_ERROR("sql.sql", "Skill rank value %hu set for skill %hu raceMask %u classMask %u is too high, max allowed value is %d", skill.Rank, skill.SkillId, raceMask, classMask, MAX_SKILL_STEP); + continue; + } if (raceMask != 0 && !(raceMask & RACEMASK_ALL_PLAYABLE)) { - TC_LOG_ERROR("sql.sql", "Wrong race mask %u in `playercreateinfo_spell` table, ignoring.", raceMask); + TC_LOG_ERROR("sql.sql", "Wrong race mask %u in `playercreateinfo_skills` table, ignoring.", raceMask); continue; } if (classMask != 0 && !(classMask & CLASSMASK_ALL_PLAYABLE)) { - TC_LOG_ERROR("sql.sql", "Wrong class mask %u in `playercreateinfo_spell` table, ignoring.", classMask); + TC_LOG_ERROR("sql.sql", "Wrong class mask %u in `playercreateinfo_skills` table, ignoring.", classMask); + continue; + } + + if (!sSkillLineStore.LookupEntry(skill.SkillId)) + { + TC_LOG_ERROR("sql.sql", "Wrong skill id %u in `playercreateinfo_skills` table, ignoring.", skill.SkillId); continue; } @@ -3321,23 +3335,21 @@ void ObjectMgr::LoadPlayerInfo() { if (classMask == 0 || ((1 << (classIndex - 1)) & classMask)) { + if (!GetSkillRaceClassInfo(skill.SkillId, raceIndex, classIndex)) + continue; + if (PlayerInfo* info = _playerInfo[raceIndex][classIndex]) { - info->spells.push_back(spellId); + info->skills.push_back(skill); ++count; } - // We need something better here, the check is not accounting for spells used by multiple races/classes but not all of them. - // Either split the masks per class, or per race, which kind of kills the point yet. - // else if (raceMask != 0 && classMask != 0) - // TC_LOG_ERROR("sql.sql", "Racemask/classmask (%u/%u) combination was found containing an invalid race/class combination (%u/%u) in `%s` (Spell %u), ignoring.", raceMask, classMask, raceIndex, classIndex, tableName.c_str(), spellId); } } } } - } - while (result->NextRow()); + } while (result->NextRow()); - TC_LOG_INFO("server.loading", ">> Loaded %u player create spells in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); + TC_LOG_INFO("server.loading", ">> Loaded %u player create skills in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } } @@ -7846,34 +7858,27 @@ int32 ObjectMgr::GetBaseReputationOf(FactionEntry const* factionEntry, uint8 rac return 0; } -SkillRangeType GetSkillRangeType(SkillLineEntry const* pSkill, bool racial) +SkillRangeType GetSkillRangeType(SkillRaceClassInfoEntry const* rcEntry) { - switch (pSkill->CategoryID) + SkillLineEntry const* skill = sSkillLineStore.LookupEntry(rcEntry->SkillID); + if (!skill) + return SKILL_RANGE_NONE; + + if (sSkillTiersStore.LookupEntry(rcEntry->SkillTierID)) + return SKILL_RANGE_RANK; + + if (rcEntry->SkillID == SKILL_RUNEFORGING) + return SKILL_RANGE_MONO; + + switch (skill->CategoryID) { + case SKILL_CATEGORY_ARMOR: + return SKILL_RANGE_MONO; case SKILL_CATEGORY_LANGUAGES: return SKILL_RANGE_LANGUAGE; - case SKILL_CATEGORY_WEAPON: - return SKILL_RANGE_LEVEL; - case SKILL_CATEGORY_ARMOR: - case SKILL_CATEGORY_CLASS: - if (pSkill->ID != SKILL_LOCKPICKING) - return SKILL_RANGE_MONO; - else - return SKILL_RANGE_LEVEL; - case SKILL_CATEGORY_SECONDARY: - case SKILL_CATEGORY_PROFESSION: - // not set skills for professions and racial abilities - if (IsProfessionSkill(pSkill->ID)) - return SKILL_RANGE_RANK; - else if (racial) - return SKILL_RANGE_NONE; - else - return SKILL_RANGE_MONO; - default: - case SKILL_CATEGORY_ATTRIBUTES: //not found in dbc - case SKILL_CATEGORY_GENERIC: //only GENERIC(DND) - return SKILL_RANGE_NONE; } + + return SKILL_RANGE_LEVEL; } void ObjectMgr::LoadGameTele() diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index bf0d889057b..e7191735ca1 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -668,7 +668,7 @@ enum SkillRangeType SKILL_RANGE_NONE // 0..0 always }; -SkillRangeType GetSkillRangeType(SkillLineEntry const* pSkill, bool racial); +SkillRangeType GetSkillRangeType(SkillRaceClassInfoEntry const* rcEntry); #define MAX_PLAYER_NAME 12 // max allowed by client name length #define MAX_INTERNAL_PLAYER_NAME 15 // max server internal player name length (> MAX_PLAYER_NAME for support declined names) diff --git a/src/server/game/Handlers/SkillHandler.cpp b/src/server/game/Handlers/SkillHandler.cpp index f0c1b28117b..278169c2d63 100644 --- a/src/server/game/Handlers/SkillHandler.cpp +++ b/src/server/game/Handlers/SkillHandler.cpp @@ -28,59 +28,22 @@ #include "WorldSession.h" #include "TalentPackets.h" -void WorldSession::HandleLearnTalentOpcode(WorldPacket& recvData) +void WorldSession::HandleLearnTalentOpcode(WorldPackets::Talent::LearnTalent& packet) { - /* TODO: 6.x update packet struct (note: LearnTalent no longer has rank argument) - uint32 talentId, requestedRank; - recvData >> talentId >> requestedRank; - - if (_player->LearnTalent(talentId, requestedRank)) - _player->SendTalentsInfoData(false);*/ + bool anythingLearned = false; + for (uint32 talentId : packet.Talents) + { + if (_player->LearnTalent(talentId)) + anythingLearned = true; + } + + if (anythingLearned) + _player->SendTalentsInfoData(); } void WorldSession::HandleLearnPreviewTalents(WorldPacket& recvPacket) { - /* TODO: 6.x update packet struct TC_LOG_DEBUG("network", "CMSG_LEARN_PREVIEW_TALENTS"); - - int32 tabPage; - uint32 talentsCount; - recvPacket >> tabPage; // talent tree - - // prevent cheating (selecting new tree with points already in another) - if (tabPage >= 0) // -1 if player already has specialization - { - if (TalentTabEntry const* talentTabEntry = sTalentTabStore.LookupEntry(_player->GetPrimaryTalentTree(_player->GetActiveSpec()))) - { - if (talentTabEntry->tabpage != uint32(tabPage)) - { - recvPacket.rfinish(); - return; - } - } - } - - recvPacket >> talentsCount; - - uint32 talentId, talentRank; - - // Client has max 21 talents for tree for 3 trees, rounded up : 70 - uint32 const MaxTalentsCount = 70; - - for (uint32 i = 0; i < talentsCount && i < MaxTalentsCount; ++i) - { - recvPacket >> talentId >> talentRank; - - if (!_player->LearnTalent(talentId, talentRank)) - { - recvPacket.rfinish(); - break; - } - } - - _player->SendTalentsInfoData(false); - - recvPacket.rfinish();*/ } void WorldSession::HandleTalentWipeConfirmOpcode(WorldPacket& recvData) diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index 3ca660dccd1..a6bd43f72c6 100644 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -371,6 +371,29 @@ void WorldSession::HandleCastSpellOpcode(WorldPackets::Spells::SpellCastRequest& // not have spell in spellbook return; } + + if (Player* plr = caster->ToPlayer()) + { + uint32 specId = plr->GetActiveTalentSpec(); + if (specId) + { + if (sSpecializationOverrideSpellMap.find(specId) != sSpecializationOverrideSpellMap.end()) + { + if (sSpecializationOverrideSpellMap[specId].find(castRequest.SpellID) != sSpecializationOverrideSpellMap[specId].end()) + { + SpellInfo const* newSpellInfo = sSpellMgr->GetSpellInfo(sSpecializationOverrideSpellMap[specId][castRequest.SpellID]); + if (newSpellInfo) + { + if (newSpellInfo->SpellLevel <= caster->getLevel()) + { + spellInfo = newSpellInfo; + castRequest.SpellID = newSpellInfo->Id; + } + } + } + } + } + } Unit::AuraEffectList swaps = mover->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS); Unit::AuraEffectList const& swaps2 = mover->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS_2); diff --git a/src/server/game/Server/Packets/SpellPackets.cpp b/src/server/game/Server/Packets/SpellPackets.cpp index 7c536363335..1e181d37ff9 100644 --- a/src/server/game/Server/Packets/SpellPackets.cpp +++ b/src/server/game/Server/Packets/SpellPackets.cpp @@ -182,8 +182,6 @@ void WorldPackets::Spells::SpellCastRequest::Read() _worldPacket >> SpellID; _worldPacket >> Misc; - TC_LOG_ERROR("spells", "SpellID %u Misc %u", SpellID, Misc); - _worldPacket.ResetBitPos(); TargetFlags = _worldPacket.ReadBits(21); @@ -469,3 +467,12 @@ WorldPacket const* WorldPackets::Spells::SetSpellModifier::Write() return &_worldPacket; } + +WorldPacket const* WorldPackets::Spells::SendRemovedSpell::Write() +{ + _worldPacket << uint32(Spells.size()); + for (uint32 spellId : Spells) + _worldPacket << uint32(spellId); + + return &_worldPacket; +}
\ No newline at end of file diff --git a/src/server/game/Server/Packets/SpellPackets.h b/src/server/game/Server/Packets/SpellPackets.h index e9ae7ada77b..6971b730742 100644 --- a/src/server/game/Server/Packets/SpellPackets.h +++ b/src/server/game/Server/Packets/SpellPackets.h @@ -223,6 +223,16 @@ namespace WorldPackets std::vector<SpellModifier> Modifiers; }; + + class SendRemovedSpell final : public ServerPacket + { + public: + SendRemovedSpell() : ServerPacket(SMSG_REMOVED_SPELL, 4) { } + + WorldPacket const* Write() override; + + std::vector<uint32> Spells; + }; } } diff --git a/src/server/game/Server/Packets/TalentPackets.cpp b/src/server/game/Server/Packets/TalentPackets.cpp index 4855f663662..d340b476cf9 100644 --- a/src/server/game/Server/Packets/TalentPackets.cpp +++ b/src/server/game/Server/Packets/TalentPackets.cpp @@ -41,3 +41,17 @@ void WorldPackets::Talent::SetSpecialization::Read() { _worldPacket >> SpecGroupIndex; } + + +void WorldPackets::Talent::LearnTalent::Read() +{ + uint32 count; + _worldPacket >> count; + + for (uint32 i = 0; i < count; ++i) + { + uint16 talent; + _worldPacket >> talent; + Talents.push_back(talent); + } +}
\ No newline at end of file diff --git a/src/server/game/Server/Packets/TalentPackets.h b/src/server/game/Server/Packets/TalentPackets.h index 21753e22c8d..2bc8b3934a8 100644 --- a/src/server/game/Server/Packets/TalentPackets.h +++ b/src/server/game/Server/Packets/TalentPackets.h @@ -57,6 +57,19 @@ namespace WorldPackets uint32 SpecGroupIndex = 0; }; + + class LearnTalent final : public ClientPacket + { + public: + LearnTalent(WorldPacket&& packet) : ClientPacket(std::move(packet)) + { + ASSERT(packet.GetOpcode() == CMSG_LEARN_TALENT); + } + + void Read() override; + std::vector<uint16> Talents; + + }; } } diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 79671b85892..671f0deb919 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -369,7 +369,7 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_KEEP_ALIVE, STATUS_NEVER, PROCESS_THREADUNSAFE, &WorldSession::Handle_EarlyProccess ); DEFINE_OPCODE_HANDLER_OLD(CMSG_LEARN_PREVIEW_TALENTS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLearnPreviewTalents ); DEFINE_OPCODE_HANDLER_OLD(CMSG_LEARN_PREVIEW_TALENTS_PET, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLearnPreviewTalentsPet ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_LEARN_TALENT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLearnTalentOpcode ); + DEFINE_HANDLER(CMSG_LEARN_TALENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Talent::LearnTalent, &WorldSession::HandleLearnTalentOpcode); DEFINE_HANDLER(CMSG_LEAVE_CHANNEL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Channel::LeaveChannel, &WorldSession::HandleLeaveChannel); DEFINE_OPCODE_HANDLER_OLD(CMSG_LFG_GET_STATUS, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleLfgGetStatus ); DEFINE_OPCODE_HANDLER_OLD(CMSG_LFG_JOIN, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgJoinOpcode ); @@ -1247,7 +1247,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_REFER_A_FRIEND_FAILURE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_REFORGE_RESULT, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_REFRESH_SPELL_HISTORY, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_REMOVED_SPELL, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_REMOVED_SPELL, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_REPORT_PVP_AFK_RESULT, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_REQUEST_CEMETERY_LIST_RESPONSE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_REQUEST_PVP_REWARDS_RESPONSE, STATUS_UNHANDLED); diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h index f6bdf0892d7..ee95bd840ab 100644 --- a/src/server/game/Server/Protocol/Opcodes.h +++ b/src/server/game/Server/Protocol/Opcodes.h @@ -314,7 +314,7 @@ enum OpcodeClient : uint32 CMSG_KEEP_ALIVE = 0xBADD, CMSG_LEARN_PREVIEW_TALENTS = 0xBADD, CMSG_LEARN_PREVIEW_TALENTS_PET = 0xBADD, - CMSG_LEARN_TALENT = 0xBADD, + CMSG_LEARN_TALENT = 0x0BB6, CMSG_LEAVE_CHANNEL = 0x19F2, CMSG_LFG_GET_STATUS = 0xBADD, CMSG_LFG_JOIN = 0xBADD, @@ -1269,7 +1269,7 @@ enum OpcodeServer : uint32 SMSG_REFER_A_FRIEND_FAILURE = 0xBADD, SMSG_REFORGE_RESULT = 0xBADD, SMSG_REFRESH_SPELL_HISTORY = 0x0A2A, - SMSG_REMOVED_SPELL = 0xBADD, + SMSG_REMOVED_SPELL = 0x0B3B, SMSG_REPORT_PVP_AFK_RESULT = 0xBADD, SMSG_REQUEST_CEMETERY_LIST_RESPONSE = 0x059E, SMSG_REQUEST_PVP_REWARDS_RESPONSE = 0xBADD, diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 26db96b232d..910a8ad4aa6 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -147,6 +147,7 @@ namespace WorldPackets namespace Talent { class SetSpecialization; + class LearnTalent; } namespace Trade @@ -876,7 +877,7 @@ class WorldSession void HandleCancelGrowthAuraOpcode(WorldPacket& recvPacket); void HandleCancelAutoRepeatSpellOpcode(WorldPacket& recvPacket); - void HandleLearnTalentOpcode(WorldPacket& recvPacket); + void HandleLearnTalentOpcode(WorldPackets::Talent::LearnTalent& packet); void HandleLearnPreviewTalents(WorldPacket& recvPacket); void HandleTalentWipeConfirmOpcode(WorldPacket& recvPacket); void HandleUnlearnSkillOpcode(WorldPacket& recvPacket); diff --git a/src/server/scripts/Commands/cs_learn.cpp b/src/server/scripts/Commands/cs_learn.cpp index 9d2d4426efe..e571f30b74e 100644 --- a/src/server/scripts/Commands/cs_learn.cpp +++ b/src/server/scripts/Commands/cs_learn.cpp @@ -204,7 +204,7 @@ public: // learn highest rank of talent and learn all non-talent spell ranks (recursive by tree) player->LearnSpellHighestRank(talentInfo->SpellID); - player->AddTalent(talentInfo->SpellID, player->GetActiveTalentGroup()); + player->AddTalent(talentInfo->SpellID, player->GetActiveTalentGroup(), true); } handler->SendSysMessage(LANG_COMMAND_LEARN_CLASS_TALENTS); @@ -306,7 +306,7 @@ public: if (!handler->extractPlayerTarget((char*)args, &target)) return false; - target->LearnDefaultSpells(); + target->LearnDefaultSkills(); target->LearnCustomSpells(); target->LearnQuestRewardedSpells(); |