diff --git a/Source/Framework/Constants/SharedConst.cs b/Source/Framework/Constants/SharedConst.cs index 5f5954223..aa05057c0 100644 --- a/Source/Framework/Constants/SharedConst.cs +++ b/Source/Framework/Constants/SharedConst.cs @@ -1884,6 +1884,7 @@ namespace Framework.Constants StartAllSpells, StartDeathKnightPlayerLevel, StartDemonHunterPlayerLevel, + StartEvokerPlayerLevel, StartGmLevel, StartPlayerLevel, StartPlayerMoney, diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index e09b254a7..025749320 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -1905,6 +1905,8 @@ namespace Game.Entities } else if (playerClass == Class.DemonHunter) startLevel = Math.Max(WorldConfig.GetUIntValue(WorldCfg.StartDemonHunterPlayerLevel), startLevel); + else if (playerClass == CLASS_EVOKER) + startLevel = Math.Max(WorldConfig.GetUIntValue(WorldCfg.StartEvokerPlayerLevel), startLevel); if (characterTemplateId.HasValue) { diff --git a/Source/Game/Globals/ObjectManager.cs b/Source/Game/Globals/ObjectManager.cs index 040737fb1..095a7cd41 100644 --- a/Source/Game/Globals/ObjectManager.cs +++ b/Source/Game/Globals/ObjectManager.cs @@ -6503,6 +6503,9 @@ namespace Game if (WorldConfig.GetIntValue(WorldCfg.Expansion) < (int)Expansion.Legion && _class == Class.DemonHunter) continue; + if (WorldConfig.GetIntValue(WorldCfg.Expansion) < (int)Expansion.Dragonflight && _class == Class.Evoker) + continue; + // fatal error if no level 1 data if (playerInfo.levelInfo == null || playerInfo.levelInfo[0].stats[0] == 0) { diff --git a/Source/Game/Networking/Packets/CharacterPackets.cs b/Source/Game/Networking/Packets/CharacterPackets.cs index 2de02379b..9cce2a4c1 100644 --- a/Source/Game/Networking/Packets/CharacterPackets.cs +++ b/Source/Game/Networking/Packets/CharacterPackets.cs @@ -238,7 +238,7 @@ namespace Game.Networking.Packets public byte RaceId; public Class ClassId; public byte SexId; - public Array Customizations = new(50); + public Array Customizations = new(72); public byte ExperienceLevel; public uint ZoneId; public uint MapId; @@ -580,7 +580,7 @@ namespace Game.Networking.Packets public string Name; public byte SexID; public byte RaceID; - public Array Customizations = new(50); + public Array Customizations = new(72); } } @@ -892,7 +892,7 @@ namespace Game.Networking.Packets } public byte NewSex; - public Array Customizations = new(50); + public Array Customizations = new(72); public int CustomizedRace; } @@ -1042,7 +1042,7 @@ namespace Game.Networking.Packets ObjectGuid CharGUID; string CharName = ""; byte SexID; - Array Customizations = new(50); + Array Customizations = new(72); } class CharCustomizeFailure : ServerPacket @@ -1104,7 +1104,7 @@ namespace Game.Networking.Packets public Race RaceId = Race.None; public Class ClassId = Class.None; public Gender Sex = Gender.None; - public Array Customizations = new(50); + public Array Customizations = new(72); public uint? TemplateSet; public bool IsTrialBoost; public bool UseNPE; @@ -1125,7 +1125,7 @@ namespace Game.Networking.Packets public ObjectGuid CharGUID; public Gender SexID = Gender.None; public string CharName; - public Array Customizations = new(50); + public Array Customizations = new(72); } public class CharRaceOrFactionChangeInfo @@ -1136,7 +1136,7 @@ namespace Game.Networking.Packets public ObjectGuid Guid; public bool FactionChange; public string Name; - public Array Customizations = new(50); + public Array Customizations = new(72); } public class CharacterUndeleteInfo diff --git a/Source/Game/Server/WorldConfig.cs b/Source/Game/Server/WorldConfig.cs index 19cf8b51c..13bacdf58 100644 --- a/Source/Game/Server/WorldConfig.cs +++ b/Source/Game/Server/WorldConfig.cs @@ -462,6 +462,18 @@ namespace Game Values[WorldCfg.StartDemonHunterPlayerLevel] = Values[WorldCfg.MaxPlayerLevel]; } + Values[WorldCfg.StartEvokerPlayerLevel] = GetDefaultValue("StartEvokerPlayerLevel", 58); + if ((int)Values[WorldCfg.StartEvokerPlayerLevel] < 1) + { + Log.outError(LogFilter.ServerLoading, $"StartEvokerPlayerLevel ({Values[WorldCfg.StartEvokerPlayerLevel]}) must be in range 1..MaxPlayerLevel({Values[WorldCfg.MaxPlayerLevel]}). Set to 1."); + Values[WorldCfg.StartEvokerPlayerLevel] = 1; + } + else if ((int)Values[WorldCfg.StartEvokerPlayerLevel] > (int)Values[WorldCfg.MaxPlayerLevel]) + { + Log.outError(LogFilter.ServerLoading, $"StartEvokerPlayerLevel ({Values[WorldCfg.StartEvokerPlayerLevel]}) must be in range 1..MaxPlayerLevel({Values[WorldCfg.MaxPlayerLevel]}). Set to {Values[WorldCfg.MaxPlayerLevel]}."); + Values[WorldCfg.StartEvokerPlayerLevel] = Values[WorldCfg.MaxPlayerLevel]; + } + Values[WorldCfg.StartAlliedRaceLevel] = GetDefaultValue("StartAlliedRacePlayerLevel", 10); if ((int)Values[WorldCfg.StartAlliedRaceLevel] < 1) { diff --git a/Source/Scripts/DragonIsles/ZoneTheForbiddenReach.cs b/Source/Scripts/DragonIsles/ZoneTheForbiddenReach.cs new file mode 100644 index 000000000..619ff126a --- /dev/null +++ b/Source/Scripts/DragonIsles/ZoneTheForbiddenReach.cs @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2012-2020 CypherCore + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using Framework.Constants; +using Game; +using Game.Entities; +using Game.Scripting; +using Game.Spells; +using System; + +namespace Scripts.DragonIsles +{ + struct SpellIds + { + // Spells + public const uint DracthyrLogin = 369728; // teleports to random room, plays scene for the room, binds the home position + public const uint Stasis1 = 369735; // triggers 366620 + public const uint Stasis2 = 366620; // triggers 366636 + public const uint Stasis3 = 366636; // removes 365560, sends first quest (64864) + public const uint Stasis4 = 365560; // freeze the target + public const uint DracthyrMovieRoom01 = 394245; // scene for room 1 + public const uint DracthyrMovieRoom02 = 394279; // scene for room 2 + public const uint DracthyrMovieRoom03 = 394281; // scene for room 3 + public const uint DracthyrMovieRoom04 = 394282; // scene for room 4 + //public const uint DracthyrMovieRoom05 = 394283, // scene for room 5 (only plays sound, unused?) + } + + struct MiscConst + { + public static Tuple[] LoginRoomData = + { + Tuple.Create(SpellIds.DracthyrMovieRoom01, new Position(5725.32f, -3024.26f, 251.047f, 0.01745329238474369f)), + Tuple.Create(SpellIds.DracthyrMovieRoom02, new Position( 5743.03f, -3067.28f, 251.047f, 0.798488140106201171f)), + Tuple.Create(SpellIds.DracthyrMovieRoom03, new Position(5787.1597f, -3083.3906f, 251.04698f, 1.570796370506286621f)), + Tuple.Create(SpellIds.DracthyrMovieRoom04, new Position(5829.32f, -3064.49f, 251.047f, 2.364955902099609375f)) + }; + } + + [Script] // 369728 - Dracthyr Login + class spell_dracthyr_login : SpellScript + { + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.DracthyrMovieRoom01, SpellIds.DracthyrMovieRoom02, SpellIds.DracthyrMovieRoom03, SpellIds.DracthyrMovieRoom04); + } + + void HandleTeleport(uint effIndex) + { + var room = MiscConst.LoginRoomData[RandomHelper.URand(0, 3)]; + + WorldLocation dest = GetHitUnit().GetWorldLocation(); + SetExplTargetDest(dest); + + GetHitDest().Relocate(room.Item2); + + GetCaster().CastSpell(GetHitUnit(), room.Item1, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new EffectHandler(HandleTeleport, 0, SpellEffectName.TeleportUnits)); + } + } + + [Script] // 3730 - Dracthyr Evoker Intro (Post Movie) + class scene_dracthyr_evoker_intro : SceneScript + { + public scene_dracthyr_evoker_intro() : base("scene_dracthyr_evoker_intro") { } + + public override void OnSceneComplete(Player player, uint sceneInstanceID, SceneTemplate sceneTemplate) + { + player.CastSpell(player, SpellIds.Stasis1, true); + } + + public override void OnSceneCancel(Player player, uint sceneInstanceID, SceneTemplate sceneTemplate) + { + player.CastSpell(player, SpellIds.Stasis1, true); + } + } +} diff --git a/Source/WorldServer/WorldServer.conf.dist b/Source/WorldServer/WorldServer.conf.dist index c959badea..b6ec6c187 100644 --- a/Source/WorldServer/WorldServer.conf.dist +++ b/Source/WorldServer/WorldServer.conf.dist @@ -895,6 +895,14 @@ StartDeathKnightPlayerLevel = 8 StartDemonHunterPlayerLevel = 8 +# +# StartEvokerPlayerLevel +# Description: Staring level for evokers after creation. +# Range: 1-MaxPlayerLevel +# Default: 58 + +StartEvokerPlayerLevel = 58 + # # StartAlliedRacePlayerLevel # Description: Staring level for allied races after creation.