diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/AccountCommands.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/AccountCommands.cs index 2125233..0737e3c 100644 --- a/src/DiIiS-NA/D3-GameServer/CommandManager/AccountCommands.cs +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/AccountCommands.cs @@ -12,198 +12,6 @@ using System.Threading.Tasks; namespace DiIiS_NA.GameServer.CommandManager { - [CommandGroup("account", "Provides account management commands.")] - public class AccountCommands : CommandGroup - { - [Command("show", "Shows information about given account\nUsage: account show ", Account.UserLevels.GM)] - public string Show(string[] @params, BattleClient invokerClient) - { - if (!@params.Any()) - return "Invalid arguments. Type 'help account show' to get help."; - - var email = @params[0]; - var account = AccountManager.GetAccountByEmail(email); - - if (account == null) - return $"No account with email '{email}' exists."; - - return $"Email: {account.Email} User Level: {account.UserLevel}"; - } - - [Command("add", "Allows you to add a new user account.\nUsage: account add [userlevel]", Account.UserLevels.GM)] - public string Add(string[] @params, BattleClient invokerClient) - { - if (@params.Length < 3) - return "Invalid arguments. Type 'help account add' to get help."; - - var email = @params[0]; - var password = @params[1]; - var battleTagName = @params[2]; - var userLevel = Account.UserLevels.User; - - if (@params.Length == 4) - { - var level = @params[3].ToLower(); - switch (level) - { - case "owner": - userLevel = Account.UserLevels.Owner; - break; - case "admin": - userLevel = Account.UserLevels.Admin; - break; - case "gm": - userLevel = Account.UserLevels.GM; - break; - case "tester": - userLevel = Account.UserLevels.Tester; - break; - case "user": - userLevel = Account.UserLevels.User; - break; - default: - return level + " is not a valid user level."; - } - } - - if (!email.Contains('@')) - return $"'{email}' is not a valid email address."; - - if (battleTagName.Contains('#')) - return "BattleTag must not contain '#' or HashCode."; - - if (password.Length < 8 || password.Length > 16) - return "Password should be a minimum of 8 and a maximum of 16 characters."; - - if (AccountManager.GetAccountByEmail(email) != null) - return $"An account already exists for email address {email}."; - - var account = AccountManager.CreateAccount(email, password, battleTagName, userLevel); - var gameAccount = GameAccountManager.CreateGameAccount(account); - //account.DBAccount.DBGameAccounts.Add(gameAccount.DBGameAccount); - return - $"Created new account {account.Email} [user-level: {account.UserLevel}] Full BattleTag: {account.BattleTag}."; - } - - [Command("setpassword", "Allows you to set a new password for account\nUsage: account setpassword ", Account.UserLevels.GM)] - public string SetPassword(string[] @params, BattleClient invokerClient) - { - if (@params.Length < 2) - return "Invalid arguments. Type 'help account setpassword' to get help."; - - var email = @params[0]; - var password = @params[1]; - - var account = AccountManager.GetAccountByEmail(email); - - if (account == null) - return $"No account with email '{email}' exists."; - - if (password.Length < 8 || password.Length > 16) - return "Password should be a minimum of 8 and a maximum of 16 characters."; - - account.UpdatePassword(password); - return $"Updated password for account {email}."; - } - - [Command("setbtag", "Allows you to change battle tag for account\nUsage: account setbtag ", Account.UserLevels.GM)] - public string SetBTag(string[] @params, BattleClient invokerClient) - { - if (@params.Length < 2) - return "Invalid arguments. Type 'help account setbtag' to get help."; - - var email = @params[0]; - var newname = @params[1]; - - var account = AccountManager.GetAccountByEmail(email); - - if (account == null) - return $"No account with email '{email}' exists."; - - account.UpdateBattleTag(newname); - return $"Updated battle tag for account {email}."; - } - - [Command("setuserlevel", "Allows you to set a new user level for account\nUsage: account setuserlevel .\nAvailable user levels: owner, admin, gm, user.", Account.UserLevels.GM)] - public string SetLevel(string[] @params, BattleClient invokerClient) - { - if (@params.Length < 2) - return "Invalid arguments. Type 'help account setuserlevel' to get help."; - - var email = @params[0]; - var level = @params[1].ToLower(); - Account.UserLevels userLevel; - - var account = AccountManager.GetAccountByEmail(email); - - if (account == null) - return $"No account with email '{email}' exists."; - - switch (level) - { - case "owner": - userLevel = Account.UserLevels.Owner; - break; - case "admin": - userLevel = Account.UserLevels.Admin; - break; - case "gm": - userLevel = Account.UserLevels.GM; - break; - case "tester": - userLevel = Account.UserLevels.Tester; - break; - case "user": - userLevel = Account.UserLevels.User; - break; - default: - return level + " is not a valid user level."; - } - account.UpdateUserLevel(userLevel); - return $"Updated user level for account {email} [user-level: {userLevel}]."; - } - } - - [CommandGroup("mute", "Disables chat messages for the account for some defined time span.")] - class MuteCommand : CommandGroup - { - [DefaultCommand(Account.UserLevels.GM)] - public string Mute(string[] @params, BattleClient invokerClient) - { - if (@params.Length < 2) - return "Invalid arguments. Type 'help mute' to get help."; - - var bTagName = @params[0]; - int muteTime = 0; - Int32.TryParse(@params[1], out muteTime); - - var account = AccountManager.GetAccountByName(bTagName); - - if (account == null) - return $"No account with bTagName '{bTagName}' exists."; - - account.MuteTime = DateTime.Now.ToUnixTime() + (muteTime * 60); - - return string.Format("Done!"); - } - } - - [CommandGroup("tag", "Switch private Tag for connect")] - class TagCommand : CommandGroup - { - [DefaultCommand(Account.UserLevels.User)] - public string Tag(string[] @params, BattleClient invokerClient) - { - if(@params == null) - return "Wrong game tag. Example: !tag mytag"; - if (@params.Length != 1) - return "Invalid arguments. Enter one string tag."; - - string Tag = @params[0]; - invokerClient.GameTeamTag = Tag; - - return string.Format("New Game Tag - " + Tag ); - } - } + } diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/AccountCommands.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/AccountCommands.cs new file mode 100644 index 0000000..44e6301 --- /dev/null +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/AccountCommands.cs @@ -0,0 +1,165 @@ +using System.Linq; +using DiIiS_NA.LoginServer.AccountsSystem; +using DiIiS_NA.LoginServer.Battle; + +namespace DiIiS_NA.GameServer.CommandManager; + +[CommandGroup("account", "Provides account management commands.")] +public class AccountCommands : CommandGroup +{ + [Command("show", "Shows information about given account\nUsage: account show ", Account.UserLevels.GM)] + public string Show(string[] @params, BattleClient invokerClient) + { + if (!@params.Any()) + return "Invalid arguments. Type 'help account show' to get help."; + + var email = @params[0]; + var account = AccountManager.GetAccountByEmail(email); + + if (account == null) + return $"No account with email '{email}' exists."; + + return $"Email: {account.Email} User Level: {account.UserLevel}"; + } + + [Command("add", + "Allows you to add a new user account.\nUsage: account add [userlevel]", + Account.UserLevels.GM)] + public string Add(string[] @params, BattleClient invokerClient) + { + if (@params.Length < 3) + return "Invalid arguments. Type 'help account add' to get help."; + + var email = @params[0]; + var password = @params[1]; + var battleTagName = @params[2]; + var userLevel = Account.UserLevels.User; + + if (@params.Length == 4) + { + var level = @params[3].ToLower(); + switch (level) + { + case "owner": + userLevel = Account.UserLevels.Owner; + break; + case "admin": + userLevel = Account.UserLevels.Admin; + break; + case "gm": + userLevel = Account.UserLevels.GM; + break; + case "tester": + userLevel = Account.UserLevels.Tester; + break; + case "user": + userLevel = Account.UserLevels.User; + break; + default: + return level + " is not a valid user level."; + } + } + + if (!email.Contains('@')) + return $"'{email}' is not a valid email address."; + + if (battleTagName.Contains('#')) + return "BattleTag must not contain '#' or HashCode."; + + if (password.Length < 8 || password.Length > 16) + return "Password should be a minimum of 8 and a maximum of 16 characters."; + + if (AccountManager.GetAccountByEmail(email) != null) + return $"An account already exists for email address {email}."; + + var account = AccountManager.CreateAccount(email, password, battleTagName, userLevel); + var gameAccount = GameAccountManager.CreateGameAccount(account); + //account.DBAccount.DBGameAccounts.Add(gameAccount.DBGameAccount); + return + $"Created new account {account.Email} [user-level: {account.UserLevel}] Full BattleTag: {account.BattleTag}."; + } + + [Command("setpassword", + "Allows you to set a new password for account\nUsage: account setpassword ", + Account.UserLevels.GM)] + public string SetPassword(string[] @params, BattleClient invokerClient) + { + if (@params.Length < 2) + return "Invalid arguments. Type 'help account setpassword' to get help."; + + var email = @params[0]; + var password = @params[1]; + + var account = AccountManager.GetAccountByEmail(email); + + if (account == null) + return $"No account with email '{email}' exists."; + + if (password.Length < 8 || password.Length > 16) + return "Password should be a minimum of 8 and a maximum of 16 characters."; + + account.UpdatePassword(password); + return $"Updated password for account {email}."; + } + + [Command("setbtag", "Allows you to change battle tag for account\nUsage: account setbtag ", + Account.UserLevels.GM)] + public string SetBTag(string[] @params, BattleClient invokerClient) + { + if (@params.Length < 2) + return "Invalid arguments. Type 'help account setbtag' to get help."; + + var email = @params[0]; + var newname = @params[1]; + + var account = AccountManager.GetAccountByEmail(email); + + if (account == null) + return $"No account with email '{email}' exists."; + + account.UpdateBattleTag(newname); + return $"Updated battle tag for account {email}."; + } + + [Command("setuserlevel", + "Allows you to set a new user level for account\nUsage: account setuserlevel .\nAvailable user levels: owner, admin, gm, user.", + Account.UserLevels.GM)] + public string SetLevel(string[] @params, BattleClient invokerClient) + { + if (@params.Length < 2) + return "Invalid arguments. Type 'help account setuserlevel' to get help."; + + var email = @params[0]; + var level = @params[1].ToLower(); + Account.UserLevels userLevel; + + var account = AccountManager.GetAccountByEmail(email); + + if (account == null) + return $"No account with email '{email}' exists."; + + switch (level) + { + case "owner": + userLevel = Account.UserLevels.Owner; + break; + case "admin": + userLevel = Account.UserLevels.Admin; + break; + case "gm": + userLevel = Account.UserLevels.GM; + break; + case "tester": + userLevel = Account.UserLevels.Tester; + break; + case "user": + userLevel = Account.UserLevels.User; + break; + default: + return level + " is not a valid user level."; + } + + account.UpdateUserLevel(userLevel); + return $"Updated user level for account {email} [user-level: {userLevel}]."; + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/ConversationCommand.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/ConversationCommand.cs new file mode 100644 index 0000000..4e3d2e9 --- /dev/null +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/ConversationCommand.cs @@ -0,0 +1,34 @@ +using System; +using DiIiS_NA.Core.MPQ; +using DiIiS_NA.GameServer.Core.Types.SNO; +using DiIiS_NA.LoginServer.Battle; + +namespace DiIiS_NA.GameServer.CommandManager; + +[CommandGroup("conversation", "Starts a conversation. \n Usage: conversation snoConversation")] +public class ConversationCommand : CommandGroup +{ + [DefaultCommand] + public string Conversation(string[] @params, BattleClient invokerClient) + { + if (invokerClient == null) + return "You cannot invoke this command from console."; + + if (invokerClient.InGameClient == null) + return "You can only invoke this command while in-game."; + + if (@params.Length != 1) + return "Invalid arguments. Type 'help conversation' to get help."; + + try + { + var conversation = MPQStorage.Data.Assets[SNOGroup.Conversation][int.Parse(@params[0])]; + invokerClient.InGameClient.Player.Conversations.StartConversation(int.Parse(@params[0])); + return $"Started conversation {conversation.FileName}"; + } + catch (Exception e) + { + return e.Message; + } + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/DifficultyCommand.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/DifficultyCommand.cs new file mode 100644 index 0000000..57b28c0 --- /dev/null +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/DifficultyCommand.cs @@ -0,0 +1,49 @@ +using DiIiS_NA.LoginServer.AccountsSystem; +using DiIiS_NA.LoginServer.Battle; + +namespace DiIiS_NA.GameServer.CommandManager; + +[CommandGroup("difficulty", "Changes difficulty of the game", Account.UserLevels.GM)] +public class DifficultyCommand : CommandGroup +{ + [Command("up", "Increases difficulty of the game", Account.UserLevels.GM)] + public string Up(string[] @params, BattleClient invokerClient) + { + if (invokerClient?.InGameClient is null) + return "You must execute this command in-game."; + if (invokerClient.InGameClient.Player.World.Game.Difficulty == 19) + return "You can't increase difficulty any more."; + invokerClient.InGameClient.Player.World.Game.RaiseDifficulty(invokerClient.InGameClient, null); + return $"Difficulty increased - set to {invokerClient.InGameClient.Player.World.Game.Difficulty}"; + } + + [Command("down", "Decreases difficulty of the game", Account.UserLevels.GM)] + public string Down(string[] @params, BattleClient invokerClient) + { + if (invokerClient?.InGameClient is null) + return "You must execute this command in-game."; + if (invokerClient.InGameClient.Player.World.Game.Difficulty == 0) + return "Difficulty is already at minimum"; + invokerClient.InGameClient.Player.World.Game.LowDifficulty(invokerClient.InGameClient, null); + return $"Difficulty decreased - set to {invokerClient.InGameClient.Player.World.Game.Difficulty}"; + } + + [Command("set", "Sets difficulty of the game", Account.UserLevels.GM)] + public string Set(string[] @params, BattleClient invokerClient) + { + if (invokerClient?.InGameClient is null) + return "You must execute this command in-game."; + if (!int.TryParse(@params[0], out var difficulty) || difficulty is < 0 or > 19) + return "Invalid difficulty. Must be between 0 and 19."; + invokerClient.InGameClient.Player.World.Game.SetDifficulty(difficulty); + return $"Difficulty set to {invokerClient.InGameClient.Player.World.Game.Difficulty}"; + } + + [DefaultCommand] + public string Get(string[] @params, BattleClient invokerClient) + { + if (invokerClient?.InGameClient is null) + return "You must execute this command in-game."; + return $"Current difficulty is {invokerClient.InGameClient.Player.World.Game.Difficulty}"; + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/DropCommand.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/DropCommand.cs new file mode 100644 index 0000000..274f9ef --- /dev/null +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/DropCommand.cs @@ -0,0 +1,44 @@ +using System.Linq; +using DiIiS_NA.LoginServer.AccountsSystem; +using DiIiS_NA.LoginServer.Battle; + +namespace DiIiS_NA.GameServer.CommandManager; + +[CommandGroup("drop", "Drops an epic item for your class.\nOptionally specify the number of items: !drop [1-20]", + Account.UserLevels.Owner)] +public class DropCommand : CommandGroup +{ + [DefaultCommand] + public string Drop(string[] @params, BattleClient invokerClient) + { + if (invokerClient?.InGameClient?.Player is not { } player) + return "You can only invoke from the client."; + + var amount = 1; + if (@params != null && @params.Any()) + if (!int.TryParse(@params[0], out amount)) + amount = 1; + + amount = amount switch + { + < 1 => 1, + > 20 => 20, + _ => amount + }; + + try + { + for (var i = 0; i < amount; i++) + player.World.SpawnRandomEquip(player, player, 11, player.Level, toonClass: player.Toon.Class, + canBeUnidentified: false); + } + catch + { + for (var i = 0; i < amount; i++) + player.World.SpawnRandomEquip(player, player, 8, player.Level, toonClass: player.Toon.Class, + canBeUnidentified: false); + } + + return $"Dropped {amount} random equipment."; + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/FollowersCommand.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/FollowersCommand.cs new file mode 100644 index 0000000..3f60eee --- /dev/null +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/FollowersCommand.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using System.Linq; +using DiIiS_NA.LoginServer.AccountsSystem; +using DiIiS_NA.LoginServer.Battle; + +namespace DiIiS_NA.GameServer.CommandManager; + +[CommandGroup("followers", "Manage your followers.", Account.UserLevels.Tester)] +public class FollowersCommand : CommandGroup +{ + [Command("list", "List all followers.")] + public string List(string[] @params, BattleClient invokerClient) + { + if (invokerClient?.InGameClient?.Player is not { } player) + return "You must be in game to use this command."; + + List followers = new(); + foreach (var follower in player.Followers.OrderBy(s => s.Value)) + followers.Add($"[{follower.Key}] {follower.Value.ToString()}"); + + return string.Join('\n', followers); + } + + [Command("dismiss", "Dismisses all followers.")] + public string DismissAllCommand(string[] @params, BattleClient invokerClient) + { + if (invokerClient?.InGameClient?.Player is not { } player) + return "You are not in game."; + + var followers = player.Followers.ToArray(); + // destroy followers + foreach (var follower in followers) player.DestroyFollower(follower.Value); + + return $"Dismissed {followers.Length} followers."; + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/GoldCommand.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/GoldCommand.cs new file mode 100644 index 0000000..9267464 --- /dev/null +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/GoldCommand.cs @@ -0,0 +1,30 @@ +using DiIiS_NA.LoginServer.AccountsSystem; +using DiIiS_NA.LoginServer.Battle; + +namespace DiIiS_NA.GameServer.CommandManager; + +[CommandGroup("gold", "Gold for your character.\nOptionally specify the number of gold: !gold [count]", + Account.UserLevels.GM)] +public class GoldCommand : CommandGroup +{ + [DefaultCommand] + public string Gold(string[] @params, BattleClient invokerClient) + { + if (invokerClient == null) + return "You cannot invoke this command from console."; + + if (invokerClient.InGameClient == null) + return "You can only invoke this command while in-game."; + + var player = invokerClient.InGameClient.Player; + var amount = 1; + + if (@params != null) + if (!int.TryParse(@params[0], out amount)) + amount = 1; + + player.Inventory.AddGoldAmount(amount); + + return $"Added Gold {amount}"; + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/HealCommand.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/HealCommand.cs new file mode 100644 index 0000000..8c4e199 --- /dev/null +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/HealCommand.cs @@ -0,0 +1,18 @@ +using DiIiS_NA.LoginServer.AccountsSystem; +using DiIiS_NA.LoginServer.Battle; + +namespace DiIiS_NA.GameServer.CommandManager; + +[CommandGroup("heal", "Heals yourself", Account.UserLevels.Tester)] +public class HealCommand : CommandGroup +{ + [DefaultCommand] + public string Heal(string[] @params, BattleClient invokerClient) + { + if (invokerClient?.InGameClient?.Player is not { } player) + return "You are not in game"; + + player.Heal(); + return "You have been healed"; + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/IdentifyCommand.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/IdentifyCommand.cs new file mode 100644 index 0000000..6c1ac6f --- /dev/null +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/IdentifyCommand.cs @@ -0,0 +1,26 @@ +using System; +using System.Linq; +using DiIiS_NA.LoginServer.AccountsSystem; +using DiIiS_NA.LoginServer.Battle; + +namespace DiIiS_NA.GameServer.CommandManager; + +[CommandGroup("identify", "Identifies all items in your inventory.", Account.UserLevels.Tester)] +public class IdentifyCommand +{ + [DefaultCommand()] + public string Identify(string[] @params, BattleClient invokerClient) + { + if (invokerClient?.InGameClient?.Player is not { } player) + return "You must be in game to use this command."; + + var unidentified = player.Inventory.GetBackPackItems().Where(i => i.Unidentified).ToArray(); + var count = unidentified.Length; + player.StartCasting(60 * 2, new Action(() => + { + foreach (var item in unidentified) + item.Identify(); + })); + return $"Identified {count} items."; + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/InfoCommand.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/InfoCommand.cs new file mode 100644 index 0000000..689db32 --- /dev/null +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/InfoCommand.cs @@ -0,0 +1,60 @@ +using System.Collections.Generic; +using System.Linq; +using DiIiS_NA.GameServer.GSSystem.GameSystem; +using DiIiS_NA.GameServer.GSSystem.PlayerSystem; +using DiIiS_NA.GameServer.MessageSystem; +using DiIiS_NA.LoginServer.AccountsSystem; +using DiIiS_NA.LoginServer.Battle; + +namespace DiIiS_NA.GameServer.CommandManager; + +[CommandGroup("info", "Get current game information.")] +public class InfoCommand : CommandGroup +{ + [DefaultCommand] + public string Info(string[] @params, BattleClient invokerClient) + { + if (invokerClient?.InGameClient?.Game is not { } game || invokerClient.InGameClient.Player is not { } player || + invokerClient.Account is not { } account) + return "You are not in game."; + return GetInfo(account, player, game); + } + + private string GetInfo(Account account, Player player, Game game) + { + List info = new() + { + $"Game: {game.GameId}", + $"Difficulty: {game.Difficulty}", + $"Worlds: {game.Worlds.Count}", + $"Players: {game.Players.Count}", + $"Monsters: {game.Worlds.Sum(w => w.Monsters.Count)}" + }; + + if (account.UserLevel >= Account.UserLevels.GM) + foreach (var world in game.Worlds) + { + info.Add($"World: {world.SNO.ToString()} - {(int)world.SNO}"); + info.Add($"Players: {world.Players.Count}"); + info.Add($"Monsters: {world.Monsters.Count}"); + info.Add($"{world.Monsters.Count} players in world: "); + foreach (var playerInWorld in world.Players) + { + info.Add($"> Player[{playerInWorld.Value.PlayerIndex}]"); + info.Add($"> Id: {playerInWorld.Value.GlobalID}"); + // info.Add($"Index: {playerInWorld.Value.PlayerIndex}"); + info.Add($"> Name: {playerInWorld.Value.Name}"); + info.Add($"> Class: {playerInWorld.Value.Toon.Class.ToString()}"); + info.Add($"> Level: {playerInWorld.Value.Toon.Level}"); + info.Add( + $"> Health: {playerInWorld.Value.Attributes[GameAttribute.Hitpoints_Cur]} / {playerInWorld.Value.Attributes[GameAttribute.Hitpoints_Max]}"); + info.Add($"> Damage: {playerInWorld.Value.Attributes[GameAttribute.Damage_Min, 0]}"); + info.Add(""); + } + + info.Add(""); + } + + return string.Join('\n', info); + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/InvulnerableCommand.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/InvulnerableCommand.cs new file mode 100644 index 0000000..b2a1df0 --- /dev/null +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/InvulnerableCommand.cs @@ -0,0 +1,30 @@ +using DiIiS_NA.GameServer.GSSystem.ObjectsSystem; +using DiIiS_NA.GameServer.MessageSystem; +using DiIiS_NA.LoginServer.AccountsSystem; +using DiIiS_NA.LoginServer.Battle; + +namespace DiIiS_NA.GameServer.CommandManager; + +[CommandGroup("invulnerable", "Makes you invulnerable", Account.UserLevels.GM)] +public class InvulnerableCommand : CommandGroup +{ + [DefaultCommand] + public string Invulnerable(string[] @params, BattleClient invokerClient) + { + if (invokerClient?.InGameClient?.Player is not { } player) + return "You cannot invoke this command from console."; + + if (player.Attributes.FixedMap.Contains(FixedAttribute.Invulnerable)) + { + player.Attributes.FixedMap.Remove(FixedAttribute.Invulnerable); + player.Attributes[GameAttribute.Invulnerable] = false; + player.Attributes.BroadcastChangedIfRevealed(); + return "You are no longer invulnerable."; + } + + player.Attributes.FixedMap.Add(FixedAttribute.Invulnerable, + attributes => { attributes[GameAttribute.Invulnerable] = true; }); + player.Attributes.BroadcastChangedIfRevealed(); + return "You are now invulnerable."; + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/ItemCommand.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/ItemCommand.cs new file mode 100644 index 0000000..cb69759 --- /dev/null +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/ItemCommand.cs @@ -0,0 +1,120 @@ +using System.Collections.Generic; +using DiIiS_NA.Core.Helpers.Math; +using DiIiS_NA.GameServer.Core.Types.Math; +using DiIiS_NA.GameServer.GSSystem.ItemsSystem; +using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Inventory; +using DiIiS_NA.LoginServer.AccountsSystem; +using DiIiS_NA.LoginServer.Battle; + +namespace DiIiS_NA.GameServer.CommandManager; + +[CommandGroup("item", "Spawns an item (with a name or type).\nUsage: item [type |] [amount]", + Account.UserLevels.GM)] +public class ItemCommand : CommandGroup +{ + [DefaultCommand] + public string Spawn(string[] @params, BattleClient invokerClient) + { + if (invokerClient == null) + return "You cannot invoke this command from console."; + + if (invokerClient.InGameClient == null) + return "You can only invoke this command while in-game."; + + var player = invokerClient.InGameClient.Player; + var name = "Dye_02"; + var amount = 1; + + + if (@params == null) + return Fallback(); + + name = @params[0]; + + if (!ItemGenerator.IsValidItem(name)) + return "You need to specify a valid item name!"; + + + if (@params.Length == 1 || !int.TryParse(@params[1], out amount)) + amount = 1; + + if (amount > 100) amount = 100; + + for (var i = 0; i < amount; i++) + { + var position = new Vector3D(player.Position.X + (float)RandomHelper.NextDouble() * 20f, + player.Position.Y + (float)RandomHelper.NextDouble() * 20f, + player.Position.Z); + + var item = ItemGenerator.Cook(player, name); + item.EnterWorld(position); + } + + return $"Spawned {amount} items with name: {name}"; + } + + [Command("type", "Spawns random items of a given type.\nUsage: item type [amount]")] + public string Type(string[] @params, BattleClient invokerClient) + { + if (invokerClient == null) + return "You cannot invoke this command from console."; + + if (invokerClient.InGameClient == null) + return "You can only invoke this command while in-game."; + + var player = invokerClient.InGameClient.Player; + var name = "Dye"; + var amount = 1; + + + if (@params == null) + return "You need to specify a item type!"; + + name = @params[0]; + + var type = ItemGroup.FromString(name); + + if (type == null) + return "The type given is not a valid item type."; + + if (@params.Length == 1 || !int.TryParse(@params[1], out amount)) + amount = 1; + + if (amount > 100) amount = 100; + + for (var i = 0; i < amount; i++) + { + var position = new Vector3D(player.Position.X + (float)RandomHelper.NextDouble() * 20f, + player.Position.Y + (float)RandomHelper.NextDouble() * 20f, + player.Position.Z); + + var item = ItemGenerator.GenerateRandom(player, type); + item.EnterWorld(position); + } + + return $"Spawned {amount} items with type: {name}"; + } + + [Command("dropall", "Drops all items in Backpack.\nUsage: item dropall")] + public string DropAll(string[] @params, BattleClient invokerClient) + { + if (invokerClient == null) + return "You cannot invoke this command from console."; + + if (invokerClient.InGameClient == null) + return "You can only invoke this command while in-game."; + + var player = invokerClient.InGameClient.Player; + + var bpItems = new List(player.Inventory.GetBackPackItems()); + + + foreach (var item in bpItems) + { + var msg = new InventoryDropItemMessage { ItemID = item.DynamicID(player) }; + player.Inventory.Consume(invokerClient.InGameClient, msg); + } + + return $"Dropped {bpItems.Count} Items for you"; + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/LevelUpCommand.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/LevelUpCommand.cs new file mode 100644 index 0000000..6ebc2a0 --- /dev/null +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/LevelUpCommand.cs @@ -0,0 +1,45 @@ +using DiIiS_NA.GameServer.MessageSystem; +using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Effect; +using DiIiS_NA.LoginServer.AccountsSystem; +using DiIiS_NA.LoginServer.Battle; + +namespace DiIiS_NA.GameServer.CommandManager; + +[CommandGroup("levelup", "Levels your character.\nOptionally specify the number of levels: !levelup [count]", + Account.UserLevels.GM)] +public class LevelUpCommand : CommandGroup +{ + [DefaultCommand] + public string LevelUp(string[] @params, BattleClient invokerClient) + { + if (invokerClient == null) + return "You cannot invoke this command from console."; + + if (invokerClient.InGameClient == null) + return "You can only invoke this command while in-game."; + + var player = invokerClient.InGameClient.Player; + var amount = 1; + + if (@params != null) + if (!int.TryParse(@params[0], out amount)) + amount = 1; + + for (var i = 0; i < amount; i++) + if (player.Level >= 70) + { + player.UpdateExp((int)player.Attributes[GameAttribute.Alt_Experience_Next_Lo]); + player.PlayEffect(Effect.ParagonLevelUp, null, false); + player.World.PowerManager.RunPower(player, 252038); + } + else + { + player.UpdateExp((int)player.Attributes[GameAttribute.Experience_Next_Lo]); + player.PlayEffect(Effect.LevelUp, null, false); + player.World.PowerManager.RunPower(player, 85954); + } + + player.Toon.GameAccount.NotifyUpdate(); + return player.Level >= 70 ? $"New paragon level: {player.ParagonLevel}" : $"New level: {player.Toon.Level}"; + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/ModifySpeedCommand.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/ModifySpeedCommand.cs new file mode 100644 index 0000000..5a0f01b --- /dev/null +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/ModifySpeedCommand.cs @@ -0,0 +1,430 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using DiIiS_NA.Core.MPQ; +using DiIiS_NA.Core.MPQ.FileFormats; +using DiIiS_NA.GameServer.Core.Types.SNO; +using DiIiS_NA.GameServer.Core.Types.TagMap; +using DiIiS_NA.GameServer.GSSystem.ActorSystem; +using DiIiS_NA.GameServer.GSSystem.ObjectsSystem; +using DiIiS_NA.GameServer.MessageSystem; +using DiIiS_NA.LoginServer.Battle; +using Actor = DiIiS_NA.Core.MPQ.FileFormats.Actor; + +namespace DiIiS_NA.GameServer.CommandManager; + +[CommandGroup("speed", "Modify speed walk of you character.\nUsage: !speed \nReset: !speed")] +public class ModifySpeedCommand : CommandGroup +{ + [DefaultCommand] + public string ModifySpeed(string[] @params, BattleClient invokerClient) + { + if (invokerClient?.InGameClient == null) + return "This command can only be used in-game."; + + if (@params == null) + return + "Change the movement speed. Min 0 (Base), Max 2.\n You can use decimal values like 1.3 for example."; + float speedValue; + + const float maxSpeed = 2; + const float baseSpeed = 0.36f; + + if (@params.Any()) + { + if (!float.TryParse(@params[0], out speedValue) || speedValue is < 0 or > maxSpeed) + return "Invalid speed value. Must be a number between 0 and 2."; + } + else + { + speedValue = 0; + } + + var playerSpeed = invokerClient.InGameClient.Player.Attributes; + + if (playerSpeed.FixedMap.Contains(FixedAttribute.Speed)) + playerSpeed.FixedMap.Remove(FixedAttribute.Speed); + + if (speedValue <= baseSpeed) // Base Run Speed [Necrosummon] + { + playerSpeed[GameAttribute.Running_Rate] = baseSpeed; + return $"Speed reset to Base Speed ({baseSpeed:0.000})."; + } + playerSpeed.FixedMap.Add(FixedAttribute.Speed, attr => attr[GameAttribute.Running_Rate] = speedValue); + playerSpeed.BroadcastChangedIfRevealed(); + return $"Speed changed to {speedValue}"; + } + + [CommandGroup("quest", + "Retrieves information about quest states and manipulates quest progress.\n Usage: quest [triggers | trigger eventType eventValue | advance snoQuest]")] + public class QuestCommand : CommandGroup + { + [DefaultCommand] + public string Quest(string[] @params, BattleClient invokerClient) + { + if (invokerClient == null) + return "You cannot invoke this command from console."; + + if (invokerClient.InGameClient == null) + return "You can only invoke this command while in-game."; + + return Info(@params, invokerClient); + } + + [Command("advance", "Advances a quest by a single step\n Usage: advance")] + public string Advance(string[] @params, BattleClient invokerClient) + { + try + { + invokerClient.InGameClient.Game.QuestManager.Advance(); + return "Advancing main quest line"; + } + catch (Exception e) + { + return e.Message; + } + } + + [Command("sideadvance", "Advances a side-quest by a single step\n Usage: sideadvance")] + public string SideAdvance(string[] @params, BattleClient invokerClient) + { + try + { + invokerClient.InGameClient.Game.QuestManager.SideAdvance(); + return "Advancing side quest line"; + } + catch (Exception e) + { + return e.Message; + } + } + + [Command("event", "Launches chosen side-quest by snoID\n Usage: event snoId")] + public string Event(string[] @params, BattleClient invokerClient) + { + if (@params == null) + return Fallback(); + + if (@params.Length != 1) + return "Invalid arguments. Type 'help text public' to get help."; + + var questId = int.Parse(@params[0]); + + try + { + invokerClient.InGameClient.Game.QuestManager.LaunchSideQuest(questId, true); + return "Advancing side quest line"; + } + catch (Exception e) + { + return e.Message; + } + } + + [Command("timer", "Send broadcasted text message.\n Usage: public 'message'")] + public string Timer(string[] @params, BattleClient invokerClient) + { + if (@params == null) + return Fallback(); + + if (@params.Length != 2) + return "Invalid arguments. Type 'help text public' to get help."; + + var eventId = int.Parse(@params[0]); + var duration = int.Parse(@params[1]); + + invokerClient.InGameClient.Game.QuestManager.LaunchQuestTimer(eventId, (float)duration, + new Action((q) => { })); + + return "Message sent."; + } + + [Command("info", "Retrieves information about quest states.\n Usage: info")] + public string Info(string[] @params, BattleClient invokerClient) + { + if (invokerClient?.InGameClient?.Game?.QuestManager is not {} questManager) + return "You can only invoke this command while in-game."; + + var act = questManager.CurrentAct; + var quest = questManager.Game.CurrentQuest; + var questStep = questManager.Game.CurrentStep; + var currentSideQuest = questManager.Game.CurrentSideQuest; + var currentSideQuestStep = questManager.Game.CurrentSideStep; + return $"Act: {act}\n" + + $"Quest: {quest}\n" + + $"Quest Step: {questStep}\n" + + $"Side Quest: {currentSideQuest}\n" + + $"Side Quest Step: {currentSideQuestStep}"; + } + } + + [CommandGroup("lookup", + "Searches in sno databases.\nUsage: lookup [actor|conv|power|scene|la|sp|weather] ")] + public class LookupCommand : CommandGroup + { + [DefaultCommand] + public string Search(string[] @params, BattleClient invokerClient) + { + if (@params == null) + return Fallback(); + + var matches = new List(); + + if (!@params.Any()) + return "Invalid arguments. Type 'help lookup actor' to get help."; + + var pattern = @params[0].ToLower(); + + foreach (var groupPair in MPQStorage.Data.Assets) matches.AddRange(from pair in groupPair.Value where pair.Value.Name.ToLower().Contains(pattern) select pair.Value); + + return matches.Aggregate(matches.Count >= 1 ? "Matches:\n" : "No matches found.", + (current, match) => + $"{current} [{match.SNOId:D6}] [{match.Group}] {match.Name}\n"); + } + + [Command("actor", "Allows you to search for an actor.\nUsage: lookup actor ")] + public string Actor(string[] @params, BattleClient invokerClient) + { + if (!@params.Any()) + return "Invalid arguments. Type 'help lookup actor' to get help."; + + var pattern = @params[0].ToLower(); + + var matches = (from pair in MPQStorage.Data.Assets[SNOGroup.Actor] where pair.Value.Name.ToLower().Contains(pattern) select pair.Value).ToList(); + + return matches.Aggregate(matches.Count >= 1 ? "Actor Matches:\n" : "No match found.", + (current, match) => current + + $"[{match.SNOId:D6}] {match.Name} ({((Actor)match.Data).Type} {(((Actor)match.Data).Type == ActorType.Gizmo ? ((int)((Actor)match.Data).TagMap[ActorKeys.GizmoGroup]).ToString() : "")})\n"); + } + + [Command("rope", "Allows you to search for an rope.\nUsage: lookup rope ")] + public string Rope(string[] @params, BattleClient invokerClient) + { + if (!@params.Any()) + return "Invalid arguments. Type 'help lookup actor' to get help."; + + var pattern = @params[0].ToLower(); + + var matches = (from pair in MPQStorage.Data.Assets[SNOGroup.Rope] where pair.Value.Name.ToLower().Contains(pattern) select pair.Value).ToList(); + + return matches.Aggregate(matches.Count >= 1 ? "Rope Matches:\n" : "No match found.", + (current, match) => current + $"[{match.SNOId:D6}] {match.Name}\n"); + } + + [Command("conv", "Allows you to search for an conversation.\nUsage: lookup conv ")] + public string Conversation(string[] @params, BattleClient invokerClient) + { + if (!@params.Any()) + return "Invalid arguments. Type 'help lookup actor' to get help."; + + var pattern = @params[0].ToLower(); + + var matches = (from pair in MPQStorage.Data.Assets[SNOGroup.Conversation] where pair.Value.Name.ToLower().Contains(pattern) select pair.Value).ToList(); + + return matches.Aggregate(matches.Count >= 1 ? "Conversation Matches:\n" : "No match found.", + (current, match) => current + $"[{match.SNOId:D6}] {match.Name}\n"); + } + + [Command("power", "Allows you to search for a power.\nUsage: lookup power ")] + public string Power(string[] @params, BattleClient invokerClient) + { + var matches = new List(); + + if (!@params.Any()) + return "Invalid arguments. Type 'help lookup power' to get help."; + + if (@params[0].ToLower() == "id") + { + var num = int.Parse(@params[1]); + matches.AddRange(from pair in MPQStorage.Data.Assets[SNOGroup.Power] where pair.Value.SNOId == num select pair.Value); + } + else + { + var pattern = @params[0].ToLower(); + matches.AddRange(from pair in MPQStorage.Data.Assets[SNOGroup.Power] where pair.Value.Name.ToLower().Contains(pattern) select pair.Value); + } + + return matches.Aggregate(matches.Count >= 1 ? "World Matches:\n" : "No match found.", + (current, match) => current + + $"[{match.SNOId:D6}] {match.Name} - {((World)match.Data).DynamicWorld}\n"); + } + + [Command("world", + "Allows you to search for a world.\nUsage: lookup world OR lookup world id ")] + public string World(string[] @params, BattleClient invokerClient) + { + var matches = new List(); + + if (!@params.Any()) + return "Invalid arguments. Type 'help lookup world' to get help."; + + if (@params[0].ToLower() == "id") + { + var num = int.Parse(@params[1]); + foreach (var pair in MPQStorage.Data.Assets[SNOGroup.Worlds]) + if (pair.Value.SNOId == num) + matches.Add(pair.Value); + } + else + { + var pattern = @params[0].ToLower(); + foreach (var pair in MPQStorage.Data.Assets[SNOGroup.Worlds]) + if (pair.Value.Name.ToLower().Contains(pattern)) + matches.Add(pair.Value); + } + + return matches.Aggregate(matches.Count >= 1 ? "World Matches:\n" : "No match found.", + (current, match) => current + + $"[{match.SNOId:D6}] {match.Name} - {(match.Data as World).DynamicWorld}\n"); + } + + [Command("qr", "Show QuestRange of an actor.\nUsage: lookup qr ")] + public string QuestRange(string[] @params, BattleClient invokerClient) + { + var matches = new List(); + + if (!@params.Any()) + return "Invalid arguments. Type 'help lookup world' to get help."; + + var num = int.Parse(@params[0]); + var qr_id = "-1"; + var qr_name = "None"; + foreach (var pair in MPQStorage.Data.Assets[SNOGroup.QuestRange]) + if (pair.Value.SNOId == num) + { + qr_id = pair.Value.SNOId.ToString("D6"); + qr_name = pair.Value.Name; + } + + return $"[{qr_id}] {qr_name}"; + } + + public static int GetExitBits(Asset scene) + { + if (scene.Name.Contains("_N_")) return 1; + if (scene.Name.Contains("_S_")) return 2; + if (scene.Name.Contains("_NS_")) return 3; + if (scene.Name.Contains("_E_")) return 4; + if (scene.Name.Contains("_NE_")) return 5; + if (scene.Name.Contains("_SE_")) return 6; + if (scene.Name.Contains("_NSE_")) return 7; + if (scene.Name.Contains("_W_")) return 8; + if (scene.Name.Contains("_NW_")) return 9; + if (scene.Name.Contains("_SW_")) return 10; + if (scene.Name.Contains("_NSW_")) return 11; + if (scene.Name.Contains("_EW_")) return 12; + if (scene.Name.Contains("_NEW_")) return 13; + if (scene.Name.Contains("_SEW_")) return 14; + if (scene.Name.Contains("_NSEW_")) return 15; + return 0; + } + + [Command("la", "Allows you to search for a LevelArea.\nUsage: lookup la ")] + public string LevelArea(string[] @params, BattleClient invokerClient) + { + var matches = new List(); + + if (!@params.Any()) + return "Invalid arguments. Type 'help lookup la' to get help."; + + var pattern = @params[0].ToLower(); + + foreach (var pair in MPQStorage.Data.Assets[SNOGroup.LevelArea]) + if (pair.Value.Name.ToLower().Contains(pattern)) + matches.Add(pair.Value); + + return matches.Aggregate(matches.Count >= 1 ? "LevelArea Matches:\n" : "No match found.", + (current, match) => current + $"[{match.SNOId:D6}] {match.Name}\n"); + } + + [Command("sp", "List all Starting Points in world.\nUsage: lookup sp")] + public string StartingPoint(string[] @params, BattleClient invokerClient) + { + var matches = invokerClient.InGameClient.Player.World.StartingPoints; + + return matches.Aggregate(matches.Count >= 1 ? "Starting Points:\n" : "No match found.", + (current, match) => current + + $"[{match.GlobalID.ToString("D6")}] {match.Name} - {match.TargetId}\n"); + } + + [Command("weather", "Allows you to search for a Weather.\nUsage: lookup weather ")] + public string Weather(string[] @params, BattleClient invokerClient) + { + var matches = new List(); + + if (!@params.Any()) + return "Invalid arguments. Type 'help lookup weather' to get help."; + + var pattern = @params[0].ToLower(); + + foreach (var pair in MPQStorage.Data.Assets[SNOGroup.Weather]) + if (pair.Value.Name.ToLower().Contains(pattern)) + matches.Add(pair.Value); + + return matches.Aggregate(matches.Count >= 1 ? "Weather Matches:\n" : "No match found.", + (current, match) => current + $"[{match.SNOId:D6}] {match.Name}\n"); + } + + [Command("scene", "Allows you to search for a scene.\nUsage: lookup scene ")] + public string Scene(string[] @params, BattleClient invokerClient) + { + var matches = new List(); + + if (!@params.Any()) + return "Invalid arguments. Type 'help lookup scene' to get help."; + + var pattern = @params[0].ToLower(); + + foreach (var pair in MPQStorage.Data.Assets[SNOGroup.Scene]) + if (pair.Value.Name.ToLower().Contains(pattern)) + matches.Add(pair.Value); + + return matches.Aggregate(matches.Count >= 1 ? "Scene Matches:\n" : "No match found.", + (current, match) => current + + $"[{match.SNOId:D6}] {match.Name} - {GetExitBits(match)}\n"); + } + + [Command("eg", "Allows you to search for an EffectGroup.\nUsage: lookup eg ")] + public string EffectGroup(string[] @params, BattleClient invokerClient) + { + var matches = new List(); + + if (!@params.Any()) + return "Invalid arguments. Type 'help lookup eg' to get help."; + + var pattern = @params[0].ToLower(); + + foreach (var pair in MPQStorage.Data.Assets[SNOGroup.EffectGroup]) + if (pair.Value.Name.ToLower().Contains(pattern)) + matches.Add(pair.Value); + + return matches.Aggregate(matches.Count >= 1 ? "EffectGroup Matches:\n" : "No match found.", + (current, match) => current + + $"[{match.SNOId:D6}] {match.Name} - {GetExitBits(match)}\n"); + } + + [Command("item", "Allows you to search for an item.\nUsage: lookup item ")] + public string Item(string[] @params, BattleClient invokerClient) + { + var matches = new List(); + + if (!@params.Any()) + return "Invalid arguments. Type 'help lookup item' to get help."; + + var pattern = @params[0].ToLower(); + + foreach (var asset in MPQStorage.Data.Assets[SNOGroup.GameBalance].Values) + { + var data = asset.Data as GameBalance; + if (data == null || data.Type != GameBalance.BalanceType.Items) continue; + + foreach (var itemDefinition in data.Item) + if (itemDefinition.Name.ToLower().Contains(pattern)) + matches.Add(itemDefinition); + } + + return matches.Aggregate(matches.Count >= 1 ? "Item Matches:\n" : "No match found.", + (current, match) => current + $"[{match.SNOActor:D6}] {match.Name}\n"); + } + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/MuteCommand.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/MuteCommand.cs new file mode 100644 index 0000000..fb6ccb5 --- /dev/null +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/MuteCommand.cs @@ -0,0 +1,30 @@ +using System; +using DiIiS_NA.Core.Extensions; +using DiIiS_NA.LoginServer.AccountsSystem; +using DiIiS_NA.LoginServer.Battle; + +namespace DiIiS_NA.GameServer.CommandManager; + +[CommandGroup("mute", "Disables chat messages for the account for some defined time span.")] +class MuteCommand : CommandGroup +{ + [DefaultCommand(Account.UserLevels.GM)] + public string Mute(string[] @params, BattleClient invokerClient) + { + if (@params.Length < 2) + return "Invalid arguments. Type 'help mute' to get help."; + + var bTagName = @params[0]; + int muteTime = 0; + Int32.TryParse(@params[1], out muteTime); + + var account = AccountManager.GetAccountByName(bTagName); + + if (account == null) + return $"No account with bTagName '{bTagName}' exists."; + + account.MuteTime = DateTime.Now.ToUnixTime() + (muteTime * 60); + + return string.Format("Done!"); + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/OpenDoorCommand.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/OpenDoorCommand.cs new file mode 100644 index 0000000..c6a75cf --- /dev/null +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/OpenDoorCommand.cs @@ -0,0 +1,75 @@ +using DiIiS_NA.LoginServer.Battle; +using System.Linq; +using DiIiS_NA.GameServer.GSSystem.ActorSystem.Implementations; +using DiIiS_NA.LoginServer.AccountsSystem; + +namespace DiIiS_NA.GameServer.CommandManager; + +[CommandGroup("doors", "Information about all doors in the vicinity. This is useful for testing purposes.. Useful for testing.", Account.UserLevels.Tester)] +public class OpenDoorCommand : CommandGroup +{ + [Command("all", "Activate all doors. This is useful for testing purposes.\nUsage: !open all", Account.UserLevels.Tester)] + public string OpenAllDoors(string[] @params, BattleClient invokerClient) + { + if (invokerClient?.InGameClient?.Player is not { } player) + return "You are not in game."; + var world = player.World; + var openedDoors = world.OpenAllDoors(); + if (openedDoors.Length == 0) + return "No doors found."; + return $"Opened {openedDoors.Length} doors: {string.Join(", ", openedDoors.Select(d => (int)d.SNO + " - " + d.SNO))}"; + } + + [Command("near", "Activate all nearby doors in the vicinity. This is useful for testing purposes.\nUsage: !open near [distance:50]", Account.UserLevels.Tester)] + public string OpenAllDoorsNear(string[] @params, BattleClient invokerClient) + { + if (invokerClient?.InGameClient?.Player is not { } player) + return "You are not in game."; + var world = player.World; + + var distance = 50f; + + if (@params.Length > 0) + { + if (!float.TryParse(@params[0], out distance) || distance < 1) + return "Invalid distance. Distance must be greater than 1."; + } + + var openedDoors = player.OpenNearDoors(distance); + if (openedDoors.Length == 0) + return "No doors found."; + return $"Opened {openedDoors.Count()} in a distance of {distance:0.0000} doors: {string.Join(", ", openedDoors)}"; + } + + [Command("info", "Retrieve all world doors in proximity, sorted in descending order.\nUsage: !open info [distance:50]", Account.UserLevels.Tester)] + public string InfoDoorsNear(string[] @params, BattleClient invokerClient) + { + if (invokerClient?.InGameClient?.Player is not { } player) + return "You are not in game."; + var world = player.World; + var distance = 50f; + + if (@params.Length > 0) + { + if (!float.TryParse(@params[0], out distance) || distance < 1) + return "Invalid distance. Distance must be greater than 1."; + } + + var doors = player.GetNearDoors(distance); + if (doors.Length == 0) + return "No doors found."; + return $"{doors.Length} doors in a distance of {distance:0.0000} doors: \n{string.Join("\n", doors.Select(s=> + { + var position = player.Position; + return s.Position.DistanceSquared(ref position) + " distance - [" + (int)s.SNO + "] " + s.SNO;; + }))}"; + } + + [DefaultCommand()] + public string DefaultCommand(string[] @params, BattleClient invokerClient) + { + return "!doors all - Activate all doors. This is useful for testing purposes.\n" + + "!doors near [distance:50] - Activate all nearby doors in the vicinity. This is useful for testing purposes.\n" + + "!doors info [distance:50] - Retrieve all world doors in proximity, sorted in descending order."; + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/PlatinumAchiCommand.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/PlatinumAchiCommand.cs new file mode 100644 index 0000000..c6632d4 --- /dev/null +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/PlatinumAchiCommand.cs @@ -0,0 +1,39 @@ +using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Platinum; +using DiIiS_NA.LoginServer.AccountsSystem; +using DiIiS_NA.LoginServer.Battle; + +namespace DiIiS_NA.GameServer.CommandManager; + +[CommandGroup("achiplatinum", + "Platinum for your character.\nOptionally specify the number of levels: !platinum [count]", Account.UserLevels.GM)] +public class PlatinumAchiCommand : CommandGroup +{ + [DefaultCommand] + public string Platinum(string[] @params, BattleClient invokerClient) + { + if (invokerClient == null) + return "You cannot invoke this command from console."; + + if (invokerClient.InGameClient == null) + return "You can only invoke this command while in-game."; + + var player = invokerClient.InGameClient.Player; + var amount = 1; + var achiid = 74987243307074; + + if (@params != null) + if (!int.TryParse(@params[0], out amount)) + amount = 1; + //if (!Int32.TryParse(@params[1], out amount)) + // achiid = 74987243307074; + player.InGameClient.SendMessage(new PlatinumAchievementAwardedMessage + { + CurrentPlatinum = 0, + idAchievement = (ulong)achiid, + PlatinumIncrement = amount + }); + + + return "Achievement test"; + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/PlatinumCommand.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/PlatinumCommand.cs new file mode 100644 index 0000000..07ec0ae --- /dev/null +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/PlatinumCommand.cs @@ -0,0 +1,39 @@ +using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Platinum; +using DiIiS_NA.LoginServer.AccountsSystem; +using DiIiS_NA.LoginServer.Battle; + +namespace DiIiS_NA.GameServer.CommandManager; + +[CommandGroup("platinum", + "Platinum for your character.\nOptionally specify the number of levels: !platinum [count]", + Account.UserLevels.Tester)] +public class PlatinumCommand : CommandGroup +{ + [DefaultCommand] + public string Platinum(string[] @params, BattleClient invokerClient) + { + if (invokerClient == null) + return "You cannot invoke this command from console."; + + if (invokerClient.InGameClient == null) + return "You can only invoke this command while in-game."; + + var player = invokerClient.InGameClient.Player; + var amount = 1; + + if (@params != null) + if (!int.TryParse(@params[0], out amount)) + amount = 1; + + + player.InGameClient.SendMessage(new PlatinumAwardedMessage + { + CurrentPlatinum = player.InGameClient.BnetClient.Account.GameAccount.Platinum, + PlatinumIncrement = amount + }); + + player.InGameClient.BnetClient.Account.GameAccount.Platinum += amount; + player.Inventory.UpdateCurrencies(); + return "Platinum given."; + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/PlayEffectGroup.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/PlayEffectGroup.cs new file mode 100644 index 0000000..c3ee86c --- /dev/null +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/PlayEffectGroup.cs @@ -0,0 +1,30 @@ +using DiIiS_NA.LoginServer.AccountsSystem; +using DiIiS_NA.LoginServer.Battle; + +namespace DiIiS_NA.GameServer.CommandManager; + +[CommandGroup("eff", "Platinum for your character.\nOptionally specify the number of levels: !eff [count]", + Account.UserLevels.GM)] +public class PlayEffectGroup : CommandGroup +{ + [DefaultCommand] + public string PlayEffectCommand(string[] @params, BattleClient invokerClient) + { + if (invokerClient == null) + return "You cannot invoke this command from console."; + + if (invokerClient.InGameClient == null) + return "You can only invoke this command while in-game."; + + var player = invokerClient.InGameClient.Player; + var id = 1; + + if (@params != null) + if (!int.TryParse(@params[0], out id)) + id = 1; + + player.PlayEffectGroup(id); + + return $"PlayEffectGroup {id}"; + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/PowerfulCommand.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/PowerfulCommand.cs new file mode 100644 index 0000000..681c45b --- /dev/null +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/PowerfulCommand.cs @@ -0,0 +1,36 @@ +using DiIiS_NA.GameServer.GSSystem.ObjectsSystem; +using DiIiS_NA.GameServer.MessageSystem; +using DiIiS_NA.LoginServer.AccountsSystem; +using DiIiS_NA.LoginServer.Battle; + +namespace DiIiS_NA.GameServer.CommandManager; + +[CommandGroup("powerful", "Makes your character with absurd amount of damage. Useful for testing.", + Account.UserLevels.Tester)] +public class PowerfulCommand : CommandGroup +{ + [DefaultCommand] + public string Powerful(string[] @params, BattleClient invokerClient) + { + if (invokerClient?.InGameClient?.Player is not { } player) + return "You must be in game to use this command."; + + if (player.Attributes.FixedMap.Contains(FixedAttribute.Powerful)) + { + player.Attributes.FixedMap.Remove(FixedAttribute.Powerful); + player.Attributes.BroadcastChangedIfRevealed(); + return "You are no longer powerful."; + } + + player.Attributes.FixedMap.Add(FixedAttribute.Powerful, (attributes) => + { + attributes[GameAttribute.Damage_Delta, 0] = float.MaxValue; + attributes[GameAttribute.Damage_Min, 0] = float.MaxValue; + attributes[GameAttribute.Damage_Weapon_Delta, 0] = float.MaxValue; + attributes[GameAttribute.Damage_Weapon_Min, 0] = float.MaxValue; + }); + + player.Attributes.BroadcastChangedIfRevealed(); + return "You are now powerful."; + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/ResourcefulCommand.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/ResourcefulCommand.cs new file mode 100644 index 0000000..70d324d --- /dev/null +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/ResourcefulCommand.cs @@ -0,0 +1,33 @@ +using DiIiS_NA.GameServer.GSSystem.ObjectsSystem; +using DiIiS_NA.GameServer.MessageSystem; +using DiIiS_NA.LoginServer.AccountsSystem; +using DiIiS_NA.LoginServer.Battle; + +namespace DiIiS_NA.GameServer.CommandManager; + +[CommandGroup("resourceful", "Makes your character with full resource. Useful for testing.", + Account.UserLevels.Tester)] +public class ResourcefulCommand : CommandGroup +{ + [DefaultCommand] + public string Resourceful(string[] @params, BattleClient invokerClient) + { + if (invokerClient?.InGameClient?.Player is not { } player) + return "You must be in game to use this command."; + + if (player.Attributes.FixedMap.Contains(FixedAttribute.Resourceful)) + { + player.Attributes.FixedMap.Remove(FixedAttribute.Resourceful); + player.Attributes.BroadcastChangedIfRevealed(); + return "You are no longer Resourceful."; + } + + player.Attributes.FixedMap.Add(FixedAttribute.Resourceful, (attributes) => + { + attributes[GameAttribute.Resource_Cur, 1] = 100; + }); + + player.Attributes.BroadcastChangedIfRevealed(); + return "You are now resourceful."; + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/SpawnCommand.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/SpawnCommand.cs new file mode 100644 index 0000000..a2b3ba6 --- /dev/null +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/SpawnCommand.cs @@ -0,0 +1,61 @@ +using DiIiS_NA.Core.Helpers.Math; +using DiIiS_NA.D3_GameServer.Core.Types.SNO; +using DiIiS_NA.GameServer.Core.Types.Math; +using DiIiS_NA.LoginServer.AccountsSystem; +using DiIiS_NA.LoginServer.Battle; + +namespace DiIiS_NA.GameServer.CommandManager; + +[CommandGroup("spawn", "Spawns a mob.\nUsage: spawn [actorSNO] [amount]", Account.UserLevels.GM)] +public class SpawnCommand : CommandGroup +{ + [DefaultCommand] + public string Spawn(string[] @params, BattleClient invokerClient) + { + if (invokerClient == null) + return "You cannot invoke this command from console."; + + if (invokerClient.InGameClient == null) + return "You can only invoke this command while in-game."; + + var player = invokerClient.InGameClient.Player; + var actorSNO = 6652; /* zombie */ + var amount = 1; + + /* + if (@params != null) + { + if (!Int32.TryParse(@params[0], out amount)) + amount = 1; + + if (amount > 100) amount = 100; + + if (@params.Count() > 1) + if (!Int32.TryParse(@params[1], out actorSNO)) + actorSNO = 6652; + } + */ + if (@params != null) + { + if (!int.TryParse(@params[0], out actorSNO)) + actorSNO = 6652; + + + if (@params.Length > 1) + if (!int.TryParse(@params[1], out amount)) + amount = 1; + if (amount > 100) amount = 100; + } + + for (var i = 0; i < amount; i++) + { + var position = new Vector3D(player.Position.X + (float)RandomHelper.NextDouble() * 20f, + player.Position.Y + (float)RandomHelper.NextDouble() * 20f, + player.Position.Z); + + var monster = player.World.SpawnMonster((ActorSno)actorSNO, position); + } + + return $"Spawned {amount} mobs with ActorSNO: {actorSNO}"; + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/StashUpCommand.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/StashUpCommand.cs new file mode 100644 index 0000000..ed723fd --- /dev/null +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/StashUpCommand.cs @@ -0,0 +1,24 @@ +using DiIiS_NA.LoginServer.AccountsSystem; +using DiIiS_NA.LoginServer.Battle; + +namespace DiIiS_NA.GameServer.CommandManager; + +[CommandGroup("stashup", "Upgrade Stash.", Account.UserLevels.Tester)] +public class StashUpCommand : CommandGroup +{ + [DefaultCommand] + public string Stashup(string[] @params, BattleClient invokerClient) + { + if (invokerClient == null) + return "You cannot invoke this command from console."; + + if (invokerClient.InGameClient == null) + return "You can only invoke this command while in-game."; + + var player = invokerClient.InGameClient.Player; + + player.Inventory.OnBuySharedStashSlots(null); + + return "Stash Upgraded"; + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/TagCommand.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/TagCommand.cs new file mode 100644 index 0000000..5d3b060 --- /dev/null +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/TagCommand.cs @@ -0,0 +1,22 @@ +using DiIiS_NA.LoginServer.AccountsSystem; +using DiIiS_NA.LoginServer.Battle; + +namespace DiIiS_NA.GameServer.CommandManager; + +[CommandGroup("tag", "Switch private Tag for connect")] +class TagCommand : CommandGroup +{ + [DefaultCommand(Account.UserLevels.User)] + public string Tag(string[] @params, BattleClient invokerClient) + { + if(@params == null) + return "Wrong game tag. Example: !tag mytag"; + if (@params.Length != 1) + return "Invalid arguments. Enter one string tag."; + + string Tag = @params[0]; + invokerClient.GameTeamTag = Tag; + + return string.Format("New Game Tag - " + Tag ); + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/TeleportCommand.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/TeleportCommand.cs new file mode 100644 index 0000000..6bf2f4e --- /dev/null +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/TeleportCommand.cs @@ -0,0 +1,76 @@ +using System.Linq; +using DiIiS_NA.Core.MPQ; +using DiIiS_NA.Core.MPQ.FileFormats; +using DiIiS_NA.D3_GameServer.Core.Types.SNO; +using DiIiS_NA.GameServer.Core.Types.SNO; +using DiIiS_NA.LoginServer.Battle; + +namespace DiIiS_NA.GameServer.CommandManager; + +[CommandGroup("tp", "Transfers your character to another world.")] +public class TeleportCommand : CommandGroup +{ + [DefaultCommand] + public string Portal(string[] @params, BattleClient invokerClient) + { + if (invokerClient == null) + return "You cannot invoke this command from console."; + + if (invokerClient.InGameClient == null) + return "You can only invoke this command while in-game."; + + if (@params != null && @params.Any()) + { + int.TryParse(@params[0], out var worldId); + + if (worldId == 0) + return "Invalid arguments. Type 'help tp' to get help."; + + if (!MPQStorage.Data.Assets[SNOGroup.Worlds].ContainsKey(worldId)) + return "There exist no world with SNOId: " + worldId; + + var world = invokerClient.InGameClient.Game.GetWorld((WorldSno)worldId); + + if (world == null) + return "Can't teleport you to world with snoId " + worldId; + + invokerClient.InGameClient.Player.ChangeWorld(world, world.StartingPoints.First().Position); + + var proximity = new System.Drawing.RectangleF(invokerClient.InGameClient.Player.Position.X - 1f, + invokerClient.InGameClient.Player.Position.Y - 1f, 2f, 2f); + var scenes = + invokerClient.InGameClient.Player.World.QuadTree.Query(proximity); + if (scenes.Count == 0) return ""; // cork (is it real?) + + var scene = scenes[0]; // Parent scene /fasbat + + if (scenes.Count == 2) // What if it's a subscene? + if (scenes[1].ParentChunkID != 0xFFFFFFFF) + scene = scenes[1]; + + var levelArea = scene.Specification.SNOLevelAreas[0]; + + //handling quest triggers + if (invokerClient.InGameClient.Player.World.Game.SideQuestProgress.GlobalQuestTriggers + .ContainsKey(levelArea)) //EnterLevelArea + { + var trigger = + invokerClient.InGameClient.Player.World.Game.SideQuestProgress.GlobalQuestTriggers[levelArea]; + if (trigger.triggerType == QuestStepObjectiveType.EnterLevelArea) + try + { + trigger.questEvent.Execute(invokerClient.InGameClient.Player.World); // launch a questEvent + } + catch + { + } + } + + foreach (var bounty in invokerClient.InGameClient.Player.World.Game.QuestManager.Bounties) + bounty.CheckLevelArea(levelArea); + return $"Teleported to: {MPQStorage.Data.Assets[SNOGroup.Worlds][worldId].Name} [id: {worldId}]"; + } + + return "Invalid arguments. Type 'help tp' to get help."; + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/UnlockArtCommand.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/UnlockArtCommand.cs new file mode 100644 index 0000000..e55797e --- /dev/null +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/UnlockArtCommand.cs @@ -0,0 +1,42 @@ +using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Hireling; +using DiIiS_NA.LoginServer.AccountsSystem; +using DiIiS_NA.LoginServer.Battle; + +namespace DiIiS_NA.GameServer.CommandManager; + +[CommandGroup("unlockart", "Unlock all artisans: !unlockart", Account.UserLevels.Tester)] +public class UnlockArtCommand : CommandGroup +{ + [DefaultCommand] + public string UnlockArt(string[] @params, BattleClient invokerClient) + { + if (invokerClient == null) + return "You cannot invoke this command from console."; + + if (invokerClient.InGameClient == null) + return "You can only invoke this command while in-game."; + + var player = invokerClient.InGameClient.Player; + + player.BlacksmithUnlocked = true; + player.JewelerUnlocked = true; + player.MysticUnlocked = true; + player.GrantAchievement(74987243307766); // Blacksmith + player.GrantAchievement(74987243307780); // Jeweler + player.GrantAchievement(74987247205955); // Mystic + + player.HirelingTemplarUnlocked = true; + player.InGameClient.SendMessage(new HirelingNewUnlocked() { NewClass = 1 }); + player.GrantAchievement(74987243307073); + player.HirelingScoundrelUnlocked = true; + player.InGameClient.SendMessage(new HirelingNewUnlocked() { NewClass = 2 }); + player.GrantAchievement(74987243307147); + player.HirelingEnchantressUnlocked = true; + player.InGameClient.SendMessage(new HirelingNewUnlocked() { NewClass = 3 }); + player.GrantAchievement(74987243307145); + + player.LoadCrafterData(); + player.Toon.GameAccount.NotifyUpdate(); + return "All artisans Unlocked"; + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/GameCommands.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/GameCommands.cs deleted file mode 100644 index 620f29e..0000000 --- a/src/DiIiS-NA/D3-GameServer/CommandManager/GameCommands.cs +++ /dev/null @@ -1,1268 +0,0 @@ -using DiIiS_NA.Core.Helpers.Math; -using DiIiS_NA.Core.MPQ; -using DiIiS_NA.Core.MPQ.FileFormats; -using DiIiS_NA.D3_GameServer.Core.Types.SNO; -using DiIiS_NA.GameServer.Core.Types.Math; -using DiIiS_NA.GameServer.Core.Types.SNO; -using DiIiS_NA.GameServer.Core.Types.TagMap; -using DiIiS_NA.GameServer.GSSystem.ActorSystem; -using DiIiS_NA.GameServer.GSSystem.ItemsSystem; -using DiIiS_NA.GameServer.MessageSystem; -using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Effect; -using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Hireling; -using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Inventory; -using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Platinum; -using DiIiS_NA.LoginServer.Battle; -using System; -using System.Collections.Generic; -using System.Linq; -using DiIiS_NA.GameServer.GSSystem.ActorSystem.Implementations; -using DiIiS_NA.GameServer.GSSystem.GameSystem; -using DiIiS_NA.GameServer.GSSystem.ObjectsSystem; -using DiIiS_NA.GameServer.GSSystem.PlayerSystem; -using DiIiS_NA.LoginServer.AccountsSystem; -using static DiIiS_NA.Core.MPQ.FileFormats.GameBalance; -using Actor = DiIiS_NA.Core.MPQ.FileFormats.Actor; - -namespace DiIiS_NA.GameServer.CommandManager; - -[CommandGroup("doors", "Information about all doors in the vicinity. This is useful for testing purposes.. Useful for testing.", Account.UserLevels.Tester)] -public class OpenDoorCommand : CommandGroup -{ - [Command("all", "Activate all doors. This is useful for testing purposes.\nUsage: !open all", Account.UserLevels.Tester)] - public string OpenAllDoors(string[] @params, BattleClient invokerClient) - { - if (invokerClient?.InGameClient?.Player is not { } player) - return "You are not in game."; - var world = player.World; - var openedDoors = world.OpenAllDoors(); - if (openedDoors.Length == 0) - return "No doors found."; - return $"Opened {openedDoors.Length} doors: {string.Join(", ", openedDoors.Select(d => (int)d.SNO + " - " + d.SNO))}"; - } - - [Command("near", "Activate all nearby doors in the vicinity. This is useful for testing purposes.\nUsage: !open near [distance:50]", Account.UserLevels.Tester)] - public string OpenAllDoorsNear(string[] @params, BattleClient invokerClient) - { - if (invokerClient?.InGameClient?.Player is not { } player) - return "You are not in game."; - var world = player.World; - - var distance = 50f; - - if (@params.Length > 0) - { - if (!float.TryParse(@params[0], out distance) || distance < 1) - return "Invalid distance. Distance must be greater than 1."; - } - - var openedDoors = player.OpenNearDoors(distance); - if (openedDoors.Length == 0) - return "No doors found."; - return $"Opened {openedDoors.Count()} in a distance of {distance:0.0000} doors: {string.Join(", ", openedDoors)}"; - } - - [Command("info", "Retrieve all world doors in proximity, sorted in descending order.\nUsage: !open info [distance:50]", Account.UserLevels.Tester)] - public string InfoDoorsNear(string[] @params, BattleClient invokerClient) - { - if (invokerClient?.InGameClient?.Player is not { } player) - return "You are not in game."; - var world = player.World; - var distance = 50f; - - if (@params.Length > 0) - { - if (!float.TryParse(@params[0], out distance) || distance < 1) - return "Invalid distance. Distance must be greater than 1."; - } - - var doors = player.GetNearDoors(distance); - if (doors.Length == 0) - return "No doors found."; - return $"{doors.Length} doors in a distance of {distance:0.0000} doors: \n{string.Join("\n", doors.Select(s=> - { - var position = player.Position; - return s.Position.DistanceSquared(ref position) + " distance - [" + (int)s.SNO + "] " + s.SNO;; - }))}"; - } - - [DefaultCommand()] - public string DefaultCommand(string[] @params, BattleClient invokerClient) - { - return "!doors all - Activate all doors. This is useful for testing purposes.\n" + - "!doors near [distance:50] - Activate all nearby doors in the vicinity. This is useful for testing purposes.\n" + - "!doors info [distance:50] - Retrieve all world doors in proximity, sorted in descending order."; - } -} -[CommandGroup("powerful", "Makes your character with absurd amount of damage. Useful for testing.", - Account.UserLevels.Tester)] -public class PowerfulCommand : CommandGroup -{ - [DefaultCommand] - public string Powerful(string[] @params, BattleClient invokerClient) - { - if (invokerClient?.InGameClient?.Player is not { } player) - return "You must be in game to use this command."; - - if (player.Attributes.FixedMap.Contains(FixedAttribute.Powerful)) - { - player.Attributes.FixedMap.Remove(FixedAttribute.Powerful); - player.Attributes.BroadcastChangedIfRevealed(); - return "You are no longer powerful."; - } - - player.Attributes.FixedMap.Add(FixedAttribute.Powerful, (attributes) => - { - attributes[GameAttribute.Damage_Delta, 0] = float.MaxValue; - attributes[GameAttribute.Damage_Min, 0] = float.MaxValue; - attributes[GameAttribute.Damage_Weapon_Delta, 0] = float.MaxValue; - attributes[GameAttribute.Damage_Weapon_Min, 0] = float.MaxValue; - }); - - player.Attributes.BroadcastChangedIfRevealed(); - return "You are now powerful."; - } -} - -[CommandGroup("resourceful", "Makes your character with full resource. Useful for testing.", - Account.UserLevels.Tester)] -public class ResourcefulCommand : CommandGroup -{ - [DefaultCommand] - public string Resourceful(string[] @params, BattleClient invokerClient) - { - if (invokerClient?.InGameClient?.Player is not { } player) - return "You must be in game to use this command."; - - if (player.Attributes.FixedMap.Contains(FixedAttribute.Resourceful)) - { - player.Attributes.FixedMap.Remove(FixedAttribute.Resourceful); - player.Attributes.BroadcastChangedIfRevealed(); - return "You are no longer Resourceful."; - } - - player.Attributes.FixedMap.Add(FixedAttribute.Resourceful, (attributes) => - { - attributes[GameAttribute.Resource_Cur, 1] = 100; - }); - - player.Attributes.BroadcastChangedIfRevealed(); - return "You are now resourceful."; - } -} - -[CommandGroup("info", "Get current game information.")] -public class InfoCommand : CommandGroup -{ - [DefaultCommand] - public string Info(string[] @params, BattleClient invokerClient) - { - if (invokerClient?.InGameClient?.Game is not { } game || invokerClient.InGameClient.Player is not { } player || - invokerClient.Account is not { } account) - return "You are not in game."; - return GetInfo(account, player, game); - } - - private string GetInfo(Account account, Player player, Game game) - { - List info = new() - { - $"Game: {game.GameId}", - $"Difficulty: {game.Difficulty}", - $"Worlds: {game.Worlds.Count}", - $"Players: {game.Players.Count}", - $"Monsters: {game.Worlds.Sum(w => w.Monsters.Count)}" - }; - - if (account.UserLevel >= Account.UserLevels.GM) - foreach (var world in game.Worlds) - { - info.Add($"World: {world.SNO.ToString()} - {(int)world.SNO}"); - info.Add($"Players: {world.Players.Count}"); - info.Add($"Monsters: {world.Monsters.Count}"); - info.Add($"{world.Monsters.Count} players in world: "); - foreach (var playerInWorld in world.Players) - { - info.Add($"> Player[{playerInWorld.Value.PlayerIndex}]"); - info.Add($"> Id: {playerInWorld.Value.GlobalID}"); - // info.Add($"Index: {playerInWorld.Value.PlayerIndex}"); - info.Add($"> Name: {playerInWorld.Value.Name}"); - info.Add($"> Class: {playerInWorld.Value.Toon.Class.ToString()}"); - info.Add($"> Level: {playerInWorld.Value.Toon.Level}"); - info.Add( - $"> Health: {playerInWorld.Value.Attributes[GameAttribute.Hitpoints_Cur]} / {playerInWorld.Value.Attributes[GameAttribute.Hitpoints_Max]}"); - info.Add($"> Damage: {playerInWorld.Value.Attributes[GameAttribute.Damage_Min, 0]}"); - info.Add(""); - } - - info.Add(""); - } - - return string.Join('\n', info); - } -} - -[CommandGroup("identify", "Identifies all items in your inventory.", Account.UserLevels.Tester)] -public class IdentifyCommand -{ - [DefaultCommand()] - public string Identify(string[] @params, BattleClient invokerClient) - { - if (invokerClient?.InGameClient?.Player is not { } player) - return "You must be in game to use this command."; - - var unidentified = player.Inventory.GetBackPackItems().Where(i => i.Unidentified).ToArray(); - var count = unidentified.Length; - player.StartCasting(60 * 2, new Action(() => - { - foreach (var item in unidentified) - item.Identify(); - })); - return $"Identified {count} items."; - } -} - -[CommandGroup("followers", "Manage your followers.", Account.UserLevels.Tester)] -public class FollowersCommand : CommandGroup -{ - [Command("list", "List all followers.")] - public string List(string[] @params, BattleClient invokerClient) - { - if (invokerClient?.InGameClient?.Player is not { } player) - return "You must be in game to use this command."; - - List followers = new(); - foreach (var follower in player.Followers.OrderBy(s => s.Value)) - followers.Add($"[{follower.Key}] {follower.Value.ToString()}"); - - return string.Join('\n', followers); - } - - [Command("dismiss", "Dismisses all followers.")] - public string DismissAllCommand(string[] @params, BattleClient invokerClient) - { - if (invokerClient?.InGameClient?.Player is not { } player) - return "You are not in game."; - - var followers = player.Followers.ToArray(); - // destroy followers - foreach (var follower in followers) player.DestroyFollower(follower.Value); - - return $"Dismissed {followers.Length} followers."; - } -} - -[CommandGroup("difficulty", "Changes difficulty of the game", Account.UserLevels.GM)] -public class DifficultyCommand : CommandGroup -{ - [Command("up", "Increases difficulty of the game", Account.UserLevels.GM)] - public string Up(string[] @params, BattleClient invokerClient) - { - if (invokerClient?.InGameClient is null) - return "You must execute this command in-game."; - if (invokerClient.InGameClient.Player.World.Game.Difficulty == 19) - return "You can't increase difficulty any more."; - invokerClient.InGameClient.Player.World.Game.RaiseDifficulty(invokerClient.InGameClient, null); - return $"Difficulty increased - set to {invokerClient.InGameClient.Player.World.Game.Difficulty}"; - } - - [Command("down", "Decreases difficulty of the game", Account.UserLevels.GM)] - public string Down(string[] @params, BattleClient invokerClient) - { - if (invokerClient?.InGameClient is null) - return "You must execute this command in-game."; - if (invokerClient.InGameClient.Player.World.Game.Difficulty == 0) - return "Difficulty is already at minimum"; - invokerClient.InGameClient.Player.World.Game.LowDifficulty(invokerClient.InGameClient, null); - return $"Difficulty decreased - set to {invokerClient.InGameClient.Player.World.Game.Difficulty}"; - } - - [Command("set", "Sets difficulty of the game", Account.UserLevels.GM)] - public string Set(string[] @params, BattleClient invokerClient) - { - if (invokerClient?.InGameClient is null) - return "You must execute this command in-game."; - if (!int.TryParse(@params[0], out var difficulty) || difficulty is < 0 or > 19) - return "Invalid difficulty. Must be between 0 and 19."; - invokerClient.InGameClient.Player.World.Game.SetDifficulty(difficulty); - return $"Difficulty set to {invokerClient.InGameClient.Player.World.Game.Difficulty}"; - } - - [DefaultCommand] - public string Get(string[] @params, BattleClient invokerClient) - { - if (invokerClient?.InGameClient is null) - return "You must execute this command in-game."; - return $"Current difficulty is {invokerClient.InGameClient.Player.World.Game.Difficulty}"; - } -} - -[CommandGroup("heal", "Heals yourself", Account.UserLevels.Tester)] -public class HealCommand : CommandGroup -{ - [DefaultCommand] - public string Heal(string[] @params, BattleClient invokerClient) - { - if (invokerClient?.InGameClient?.Player is not { } player) - return "You are not in game"; - - player.Heal(); - return "You have been healed"; - } -} - -[CommandGroup("invulnerable", "Makes you invulnerable", Account.UserLevels.GM)] -public class InvulnerableCommand : CommandGroup -{ - [DefaultCommand] - public string Invulnerable(string[] @params, BattleClient invokerClient) - { - if (invokerClient?.InGameClient?.Player is not { } player) - return "You cannot invoke this command from console."; - - if (player.Attributes.FixedMap.Contains(FixedAttribute.Invulnerable)) - { - player.Attributes.FixedMap.Remove(FixedAttribute.Invulnerable); - player.Attributes[GameAttribute.Invulnerable] = false; - player.Attributes.BroadcastChangedIfRevealed(); - return "You are no longer invulnerable."; - } - - player.Attributes.FixedMap.Add(FixedAttribute.Invulnerable, - attributes => { attributes[GameAttribute.Invulnerable] = true; }); - player.Attributes.BroadcastChangedIfRevealed(); - return "You are now invulnerable."; - } -} - -[CommandGroup("spawn", "Spawns a mob.\nUsage: spawn [actorSNO] [amount]", Account.UserLevels.GM)] -public class SpawnCommand : CommandGroup -{ - [DefaultCommand] - public string Spawn(string[] @params, BattleClient invokerClient) - { - if (invokerClient == null) - return "You cannot invoke this command from console."; - - if (invokerClient.InGameClient == null) - return "You can only invoke this command while in-game."; - - var player = invokerClient.InGameClient.Player; - var actorSNO = 6652; /* zombie */ - var amount = 1; - - /* - if (@params != null) - { - if (!Int32.TryParse(@params[0], out amount)) - amount = 1; - - if (amount > 100) amount = 100; - - if (@params.Count() > 1) - if (!Int32.TryParse(@params[1], out actorSNO)) - actorSNO = 6652; - } - */ - if (@params != null) - { - if (!int.TryParse(@params[0], out actorSNO)) - actorSNO = 6652; - - - if (@params.Length > 1) - if (!int.TryParse(@params[1], out amount)) - amount = 1; - if (amount > 100) amount = 100; - } - - for (var i = 0; i < amount; i++) - { - var position = new Vector3D(player.Position.X + (float)RandomHelper.NextDouble() * 20f, - player.Position.Y + (float)RandomHelper.NextDouble() * 20f, - player.Position.Z); - - var monster = player.World.SpawnMonster((ActorSno)actorSNO, position); - } - - return $"Spawned {amount} mobs with ActorSNO: {actorSNO}"; - } -} - -[CommandGroup("levelup", "Levels your character.\nOptionally specify the number of levels: !levelup [count]", - Account.UserLevels.GM)] -public class LevelUpCommand : CommandGroup -{ - [DefaultCommand] - public string LevelUp(string[] @params, BattleClient invokerClient) - { - if (invokerClient == null) - return "You cannot invoke this command from console."; - - if (invokerClient.InGameClient == null) - return "You can only invoke this command while in-game."; - - var player = invokerClient.InGameClient.Player; - var amount = 1; - - if (@params != null) - if (!int.TryParse(@params[0], out amount)) - amount = 1; - - for (var i = 0; i < amount; i++) - if (player.Level >= 70) - { - player.UpdateExp((int)player.Attributes[GameAttribute.Alt_Experience_Next_Lo]); - player.PlayEffect(Effect.ParagonLevelUp, null, false); - player.World.PowerManager.RunPower(player, 252038); - } - else - { - player.UpdateExp((int)player.Attributes[GameAttribute.Experience_Next_Lo]); - player.PlayEffect(Effect.LevelUp, null, false); - player.World.PowerManager.RunPower(player, 85954); - } - - player.Toon.GameAccount.NotifyUpdate(); - return player.Level >= 70 ? $"New paragon level: {player.ParagonLevel}" : $"New level: {player.Toon.Level}"; - } -} - -[CommandGroup("unlockart", "Unlock all artisans: !unlockart", Account.UserLevels.Tester)] -public class UnlockArtCommand : CommandGroup -{ - [DefaultCommand] - public string UnlockArt(string[] @params, BattleClient invokerClient) - { - if (invokerClient == null) - return "You cannot invoke this command from console."; - - if (invokerClient.InGameClient == null) - return "You can only invoke this command while in-game."; - - var player = invokerClient.InGameClient.Player; - - player.BlacksmithUnlocked = true; - player.JewelerUnlocked = true; - player.MysticUnlocked = true; - player.GrantAchievement(74987243307766); // Blacksmith - player.GrantAchievement(74987243307780); // Jeweler - player.GrantAchievement(74987247205955); // Mystic - - player.HirelingTemplarUnlocked = true; - player.InGameClient.SendMessage(new HirelingNewUnlocked() { NewClass = 1 }); - player.GrantAchievement(74987243307073); - player.HirelingScoundrelUnlocked = true; - player.InGameClient.SendMessage(new HirelingNewUnlocked() { NewClass = 2 }); - player.GrantAchievement(74987243307147); - player.HirelingEnchantressUnlocked = true; - player.InGameClient.SendMessage(new HirelingNewUnlocked() { NewClass = 3 }); - player.GrantAchievement(74987243307145); - - player.LoadCrafterData(); - player.Toon.GameAccount.NotifyUpdate(); - return "All artisans Unlocked"; - } -} - -[CommandGroup("platinum", - "Platinum for your character.\nOptionally specify the number of levels: !platinum [count]", - Account.UserLevels.Tester)] -public class PlatinumCommand : CommandGroup -{ - [DefaultCommand] - public string Platinum(string[] @params, BattleClient invokerClient) - { - if (invokerClient == null) - return "You cannot invoke this command from console."; - - if (invokerClient.InGameClient == null) - return "You can only invoke this command while in-game."; - - var player = invokerClient.InGameClient.Player; - var amount = 1; - - if (@params != null) - if (!int.TryParse(@params[0], out amount)) - amount = 1; - - - player.InGameClient.SendMessage(new PlatinumAwardedMessage - { - CurrentPlatinum = player.InGameClient.BnetClient.Account.GameAccount.Platinum, - PlatinumIncrement = amount - }); - - player.InGameClient.BnetClient.Account.GameAccount.Platinum += amount; - player.Inventory.UpdateCurrencies(); - return "Platinum given."; - } -} - -[CommandGroup("stashup", "Upgrade Stash.", Account.UserLevels.Tester)] -public class StashUpCommand : CommandGroup -{ - [DefaultCommand] - public string Stashup(string[] @params, BattleClient invokerClient) - { - if (invokerClient == null) - return "You cannot invoke this command from console."; - - if (invokerClient.InGameClient == null) - return "You can only invoke this command while in-game."; - - var player = invokerClient.InGameClient.Player; - - player.Inventory.OnBuySharedStashSlots(null); - - return "Stash Upgraded"; - } -} - -[CommandGroup("gold", "Gold for your character.\nOptionally specify the number of gold: !gold [count]", - Account.UserLevels.GM)] -public class GoldCommand : CommandGroup -{ - [DefaultCommand] - public string Gold(string[] @params, BattleClient invokerClient) - { - if (invokerClient == null) - return "You cannot invoke this command from console."; - - if (invokerClient.InGameClient == null) - return "You can only invoke this command while in-game."; - - var player = invokerClient.InGameClient.Player; - var amount = 1; - - if (@params != null) - if (!int.TryParse(@params[0], out amount)) - amount = 1; - - player.Inventory.AddGoldAmount(amount); - - return $"Added Gold {amount}"; - } -} - -[CommandGroup("achiplatinum", - "Platinum for your character.\nOptionally specify the number of levels: !platinum [count]", Account.UserLevels.GM)] -public class PlatinumAchiCommand : CommandGroup -{ - [DefaultCommand] - public string Platinum(string[] @params, BattleClient invokerClient) - { - if (invokerClient == null) - return "You cannot invoke this command from console."; - - if (invokerClient.InGameClient == null) - return "You can only invoke this command while in-game."; - - var player = invokerClient.InGameClient.Player; - var amount = 1; - var achiid = 74987243307074; - - if (@params != null) - if (!int.TryParse(@params[0], out amount)) - amount = 1; - //if (!Int32.TryParse(@params[1], out amount)) - // achiid = 74987243307074; - player.InGameClient.SendMessage(new PlatinumAchievementAwardedMessage - { - CurrentPlatinum = 0, - idAchievement = (ulong)achiid, - PlatinumIncrement = amount - }); - - - return "Achievement test"; - } -} - -[CommandGroup("eff", "Platinum for your character.\nOptionally specify the number of levels: !eff [count]", - Account.UserLevels.GM)] -public class PlayEffectGroup : CommandGroup -{ - [DefaultCommand] - public string PlayEffectCommand(string[] @params, BattleClient invokerClient) - { - if (invokerClient == null) - return "You cannot invoke this command from console."; - - if (invokerClient.InGameClient == null) - return "You can only invoke this command while in-game."; - - var player = invokerClient.InGameClient.Player; - var id = 1; - - if (@params != null) - if (!int.TryParse(@params[0], out id)) - id = 1; - - player.PlayEffectGroup(id); - - return $"PlayEffectGroup {id}"; - } -} - -[CommandGroup("item", "Spawns an item (with a name or type).\nUsage: item [type |] [amount]", - Account.UserLevels.GM)] -public class ItemCommand : CommandGroup -{ - [DefaultCommand] - public string Spawn(string[] @params, BattleClient invokerClient) - { - if (invokerClient == null) - return "You cannot invoke this command from console."; - - if (invokerClient.InGameClient == null) - return "You can only invoke this command while in-game."; - - var player = invokerClient.InGameClient.Player; - var name = "Dye_02"; - var amount = 1; - - - if (@params == null) - return Fallback(); - - name = @params[0]; - - if (!ItemGenerator.IsValidItem(name)) - return "You need to specify a valid item name!"; - - - if (@params.Length == 1 || !int.TryParse(@params[1], out amount)) - amount = 1; - - if (amount > 100) amount = 100; - - for (var i = 0; i < amount; i++) - { - var position = new Vector3D(player.Position.X + (float)RandomHelper.NextDouble() * 20f, - player.Position.Y + (float)RandomHelper.NextDouble() * 20f, - player.Position.Z); - - var item = ItemGenerator.Cook(player, name); - item.EnterWorld(position); - } - - return $"Spawned {amount} items with name: {name}"; - } - - [Command("type", "Spawns random items of a given type.\nUsage: item type [amount]")] - public string Type(string[] @params, BattleClient invokerClient) - { - if (invokerClient == null) - return "You cannot invoke this command from console."; - - if (invokerClient.InGameClient == null) - return "You can only invoke this command while in-game."; - - var player = invokerClient.InGameClient.Player; - var name = "Dye"; - var amount = 1; - - - if (@params == null) - return "You need to specify a item type!"; - - name = @params[0]; - - var type = ItemGroup.FromString(name); - - if (type == null) - return "The type given is not a valid item type."; - - if (@params.Length == 1 || !int.TryParse(@params[1], out amount)) - amount = 1; - - if (amount > 100) amount = 100; - - for (var i = 0; i < amount; i++) - { - var position = new Vector3D(player.Position.X + (float)RandomHelper.NextDouble() * 20f, - player.Position.Y + (float)RandomHelper.NextDouble() * 20f, - player.Position.Z); - - var item = ItemGenerator.GenerateRandom(player, type); - item.EnterWorld(position); - } - - return $"Spawned {amount} items with type: {name}"; - } - - [Command("dropall", "Drops all items in Backpack.\nUsage: item dropall")] - public string DropAll(string[] @params, BattleClient invokerClient) - { - if (invokerClient == null) - return "You cannot invoke this command from console."; - - if (invokerClient.InGameClient == null) - return "You can only invoke this command while in-game."; - - var player = invokerClient.InGameClient.Player; - - var bpItems = new List(player.Inventory.GetBackPackItems()); - - - foreach (var item in bpItems) - { - var msg = new InventoryDropItemMessage { ItemID = item.DynamicID(player) }; - player.Inventory.Consume(invokerClient.InGameClient, msg); - } - - return $"Dropped {bpItems.Count} Items for you"; - } -} - -[CommandGroup("drop", "Drops an epic item for your class.\nOptionally specify the number of items: !drop [1-20]", - Account.UserLevels.Owner)] -public class DropCommand : CommandGroup -{ - [DefaultCommand] - public string Drop(string[] @params, BattleClient invokerClient) - { - if (invokerClient?.InGameClient?.Player is not { } player) - return "You can only invoke from the client."; - - var amount = 1; - if (@params != null && @params.Any()) - if (!int.TryParse(@params[0], out amount)) - amount = 1; - - amount = amount switch - { - < 1 => 1, - > 20 => 20, - _ => amount - }; - - try - { - for (var i = 0; i < amount; i++) - player.World.SpawnRandomEquip(player, player, 11, player.Level, toonClass: player.Toon.Class, - canBeUnidentified: false); - } - catch - { - for (var i = 0; i < amount; i++) - player.World.SpawnRandomEquip(player, player, 8, player.Level, toonClass: player.Toon.Class, - canBeUnidentified: false); - } - - return $"Dropped {amount} random equipment."; - } -} - -[CommandGroup("tp", "Transfers your character to another world.")] -public class TeleportCommand : CommandGroup -{ - [DefaultCommand] - public string Portal(string[] @params, BattleClient invokerClient) - { - if (invokerClient == null) - return "You cannot invoke this command from console."; - - if (invokerClient.InGameClient == null) - return "You can only invoke this command while in-game."; - - if (@params != null && @params.Any()) - { - int.TryParse(@params[0], out var worldId); - - if (worldId == 0) - return "Invalid arguments. Type 'help tp' to get help."; - - if (!MPQStorage.Data.Assets[SNOGroup.Worlds].ContainsKey(worldId)) - return "There exist no world with SNOId: " + worldId; - - var world = invokerClient.InGameClient.Game.GetWorld((WorldSno)worldId); - - if (world == null) - return "Can't teleport you to world with snoId " + worldId; - - invokerClient.InGameClient.Player.ChangeWorld(world, world.StartingPoints.First().Position); - - var proximity = new System.Drawing.RectangleF(invokerClient.InGameClient.Player.Position.X - 1f, - invokerClient.InGameClient.Player.Position.Y - 1f, 2f, 2f); - var scenes = - invokerClient.InGameClient.Player.World.QuadTree.Query(proximity); - if (scenes.Count == 0) return ""; // cork (is it real?) - - var scene = scenes[0]; // Parent scene /fasbat - - if (scenes.Count == 2) // What if it's a subscene? - if (scenes[1].ParentChunkID != 0xFFFFFFFF) - scene = scenes[1]; - - var levelArea = scene.Specification.SNOLevelAreas[0]; - - //handling quest triggers - if (invokerClient.InGameClient.Player.World.Game.SideQuestProgress.GlobalQuestTriggers - .ContainsKey(levelArea)) //EnterLevelArea - { - var trigger = - invokerClient.InGameClient.Player.World.Game.SideQuestProgress.GlobalQuestTriggers[levelArea]; - if (trigger.triggerType == QuestStepObjectiveType.EnterLevelArea) - try - { - trigger.questEvent.Execute(invokerClient.InGameClient.Player.World); // launch a questEvent - } - catch - { - } - } - - foreach (var bounty in invokerClient.InGameClient.Player.World.Game.QuestManager.Bounties) - bounty.CheckLevelArea(levelArea); - return $"Teleported to: {MPQStorage.Data.Assets[SNOGroup.Worlds][worldId].Name} [id: {worldId}]"; - } - - return "Invalid arguments. Type 'help tp' to get help."; - } -} - -[CommandGroup("conversation", "Starts a conversation. \n Usage: conversation snoConversation")] -public class ConversationCommand : CommandGroup -{ - [DefaultCommand] - public string Conversation(string[] @params, BattleClient invokerClient) - { - if (invokerClient == null) - return "You cannot invoke this command from console."; - - if (invokerClient.InGameClient == null) - return "You can only invoke this command while in-game."; - - if (@params.Length != 1) - return "Invalid arguments. Type 'help conversation' to get help."; - - try - { - var conversation = MPQStorage.Data.Assets[SNOGroup.Conversation][int.Parse(@params[0])]; - invokerClient.InGameClient.Player.Conversations.StartConversation(int.Parse(@params[0])); - return $"Started conversation {conversation.FileName}"; - } - catch (Exception e) - { - return e.Message; - } - } -} - -[CommandGroup("speed", "Modify speed walk of you character.\nUsage: !speed \nReset: !speed")] -public class ModifySpeedCommand : CommandGroup -{ - [DefaultCommand] - public string ModifySpeed(string[] @params, BattleClient invokerClient) - { - if (invokerClient?.InGameClient == null) - return "This command can only be used in-game."; - - if (@params == null) - return - "Change the movement speed. Min 0 (Base), Max 2.\n You can use decimal values like 1.3 for example."; - float speedValue; - - const float maxSpeed = 2; - const float baseSpeed = 0.36f; - - if (@params.Any()) - { - if (!float.TryParse(@params[0], out speedValue) || speedValue is < 0 or > maxSpeed) - return "Invalid speed value. Must be a number between 0 and 2."; - } - else - { - speedValue = 0; - } - - var playerSpeed = invokerClient.InGameClient.Player.Attributes; - - if (playerSpeed.FixedMap.Contains(FixedAttribute.Speed)) - playerSpeed.FixedMap.Remove(FixedAttribute.Speed); - - if (speedValue <= baseSpeed) // Base Run Speed [Necrosummon] - { - playerSpeed[GameAttribute.Running_Rate] = baseSpeed; - return $"Speed reset to Base Speed ({baseSpeed:0.000})."; - } - playerSpeed.FixedMap.Add(FixedAttribute.Speed, attr => attr[GameAttribute.Running_Rate] = speedValue); - playerSpeed.BroadcastChangedIfRevealed(); - return $"Speed changed to {speedValue}"; - } - - [CommandGroup("quest", - "Retrieves information about quest states and manipulates quest progress.\n Usage: quest [triggers | trigger eventType eventValue | advance snoQuest]")] - public class QuestCommand : CommandGroup - { - [DefaultCommand] - public string Quest(string[] @params, BattleClient invokerClient) - { - if (invokerClient == null) - return "You cannot invoke this command from console."; - - if (invokerClient.InGameClient == null) - return "You can only invoke this command while in-game."; - - return Info(@params, invokerClient); - } - - [Command("advance", "Advances a quest by a single step\n Usage: advance")] - public string Advance(string[] @params, BattleClient invokerClient) - { - try - { - invokerClient.InGameClient.Game.QuestManager.Advance(); - return "Advancing main quest line"; - } - catch (Exception e) - { - return e.Message; - } - } - - [Command("sideadvance", "Advances a side-quest by a single step\n Usage: sideadvance")] - public string SideAdvance(string[] @params, BattleClient invokerClient) - { - try - { - invokerClient.InGameClient.Game.QuestManager.SideAdvance(); - return "Advancing side quest line"; - } - catch (Exception e) - { - return e.Message; - } - } - - [Command("event", "Launches chosen side-quest by snoID\n Usage: event snoId")] - public string Event(string[] @params, BattleClient invokerClient) - { - if (@params == null) - return Fallback(); - - if (@params.Length != 1) - return "Invalid arguments. Type 'help text public' to get help."; - - var questId = int.Parse(@params[0]); - - try - { - invokerClient.InGameClient.Game.QuestManager.LaunchSideQuest(questId, true); - return "Advancing side quest line"; - } - catch (Exception e) - { - return e.Message; - } - } - - [Command("timer", "Send broadcasted text message.\n Usage: public 'message'")] - public string Timer(string[] @params, BattleClient invokerClient) - { - if (@params == null) - return Fallback(); - - if (@params.Length != 2) - return "Invalid arguments. Type 'help text public' to get help."; - - var eventId = int.Parse(@params[0]); - var duration = int.Parse(@params[1]); - - invokerClient.InGameClient.Game.QuestManager.LaunchQuestTimer(eventId, (float)duration, - new Action((q) => { })); - - return "Message sent."; - } - - [Command("info", "Retrieves information about quest states.\n Usage: info")] - public string Info(string[] @params, BattleClient invokerClient) - { - if (invokerClient?.InGameClient?.Game?.QuestManager is not {} questManager) - return "You can only invoke this command while in-game."; - - var act = questManager.CurrentAct; - var quest = questManager.Game.CurrentQuest; - var questStep = questManager.Game.CurrentStep; - var currentSideQuest = questManager.Game.CurrentSideQuest; - var currentSideQuestStep = questManager.Game.CurrentSideStep; - return $"Act: {act}\n" + - $"Quest: {quest}\n" + - $"Quest Step: {questStep}\n" + - $"Side Quest: {currentSideQuest}\n" + - $"Side Quest Step: {currentSideQuestStep}"; - } - } - - [CommandGroup("lookup", - "Searches in sno databases.\nUsage: lookup [actor|conv|power|scene|la|sp|weather] ")] - public class LookupCommand : CommandGroup - { - [DefaultCommand] - public string Search(string[] @params, BattleClient invokerClient) - { - if (@params == null) - return Fallback(); - - var matches = new List(); - - if (!@params.Any()) - return "Invalid arguments. Type 'help lookup actor' to get help."; - - var pattern = @params[0].ToLower(); - - foreach (var groupPair in MPQStorage.Data.Assets) matches.AddRange(from pair in groupPair.Value where pair.Value.Name.ToLower().Contains(pattern) select pair.Value); - - return matches.Aggregate(matches.Count >= 1 ? "Matches:\n" : "No matches found.", - (current, match) => - $"{current} [{match.SNOId:D6}] [{match.Group}] {match.Name}\n"); - } - - [Command("actor", "Allows you to search for an actor.\nUsage: lookup actor ")] - public string Actor(string[] @params, BattleClient invokerClient) - { - if (!@params.Any()) - return "Invalid arguments. Type 'help lookup actor' to get help."; - - var pattern = @params[0].ToLower(); - - var matches = (from pair in MPQStorage.Data.Assets[SNOGroup.Actor] where pair.Value.Name.ToLower().Contains(pattern) select pair.Value).ToList(); - - return matches.Aggregate(matches.Count >= 1 ? "Actor Matches:\n" : "No match found.", - (current, match) => current + - $"[{match.SNOId:D6}] {match.Name} ({((Actor)match.Data).Type} {(((Actor)match.Data).Type == ActorType.Gizmo ? ((int)((Actor)match.Data).TagMap[ActorKeys.GizmoGroup]).ToString() : "")})\n"); - } - - [Command("rope", "Allows you to search for an rope.\nUsage: lookup rope ")] - public string Rope(string[] @params, BattleClient invokerClient) - { - if (!@params.Any()) - return "Invalid arguments. Type 'help lookup actor' to get help."; - - var pattern = @params[0].ToLower(); - - var matches = (from pair in MPQStorage.Data.Assets[SNOGroup.Rope] where pair.Value.Name.ToLower().Contains(pattern) select pair.Value).ToList(); - - return matches.Aggregate(matches.Count >= 1 ? "Rope Matches:\n" : "No match found.", - (current, match) => current + $"[{match.SNOId:D6}] {match.Name}\n"); - } - - [Command("conv", "Allows you to search for an conversation.\nUsage: lookup conv ")] - public string Conversation(string[] @params, BattleClient invokerClient) - { - if (!@params.Any()) - return "Invalid arguments. Type 'help lookup actor' to get help."; - - var pattern = @params[0].ToLower(); - - var matches = (from pair in MPQStorage.Data.Assets[SNOGroup.Conversation] where pair.Value.Name.ToLower().Contains(pattern) select pair.Value).ToList(); - - return matches.Aggregate(matches.Count >= 1 ? "Conversation Matches:\n" : "No match found.", - (current, match) => current + $"[{match.SNOId:D6}] {match.Name}\n"); - } - - [Command("power", "Allows you to search for a power.\nUsage: lookup power ")] - public string Power(string[] @params, BattleClient invokerClient) - { - var matches = new List(); - - if (!@params.Any()) - return "Invalid arguments. Type 'help lookup power' to get help."; - - if (@params[0].ToLower() == "id") - { - var num = int.Parse(@params[1]); - matches.AddRange(from pair in MPQStorage.Data.Assets[SNOGroup.Power] where pair.Value.SNOId == num select pair.Value); - } - else - { - var pattern = @params[0].ToLower(); - matches.AddRange(from pair in MPQStorage.Data.Assets[SNOGroup.Power] where pair.Value.Name.ToLower().Contains(pattern) select pair.Value); - } - - return matches.Aggregate(matches.Count >= 1 ? "World Matches:\n" : "No match found.", - (current, match) => current + - $"[{match.SNOId:D6}] {match.Name} - {((World)match.Data).DynamicWorld}\n"); - } - - [Command("world", - "Allows you to search for a world.\nUsage: lookup world OR lookup world id ")] - public string World(string[] @params, BattleClient invokerClient) - { - var matches = new List(); - - if (!@params.Any()) - return "Invalid arguments. Type 'help lookup world' to get help."; - - if (@params[0].ToLower() == "id") - { - var num = int.Parse(@params[1]); - foreach (var pair in MPQStorage.Data.Assets[SNOGroup.Worlds]) - if (pair.Value.SNOId == num) - matches.Add(pair.Value); - } - else - { - var pattern = @params[0].ToLower(); - foreach (var pair in MPQStorage.Data.Assets[SNOGroup.Worlds]) - if (pair.Value.Name.ToLower().Contains(pattern)) - matches.Add(pair.Value); - } - - return matches.Aggregate(matches.Count >= 1 ? "World Matches:\n" : "No match found.", - (current, match) => current + - $"[{match.SNOId:D6}] {match.Name} - {(match.Data as World).DynamicWorld}\n"); - } - - [Command("qr", "Show QuestRange of an actor.\nUsage: lookup qr ")] - public string QuestRange(string[] @params, BattleClient invokerClient) - { - var matches = new List(); - - if (!@params.Any()) - return "Invalid arguments. Type 'help lookup world' to get help."; - - var num = int.Parse(@params[0]); - var qr_id = "-1"; - var qr_name = "None"; - foreach (var pair in MPQStorage.Data.Assets[SNOGroup.QuestRange]) - if (pair.Value.SNOId == num) - { - qr_id = pair.Value.SNOId.ToString("D6"); - qr_name = pair.Value.Name; - } - - return $"[{qr_id}] {qr_name}"; - } - - public static int GetExitBits(Asset scene) - { - if (scene.Name.Contains("_N_")) return 1; - if (scene.Name.Contains("_S_")) return 2; - if (scene.Name.Contains("_NS_")) return 3; - if (scene.Name.Contains("_E_")) return 4; - if (scene.Name.Contains("_NE_")) return 5; - if (scene.Name.Contains("_SE_")) return 6; - if (scene.Name.Contains("_NSE_")) return 7; - if (scene.Name.Contains("_W_")) return 8; - if (scene.Name.Contains("_NW_")) return 9; - if (scene.Name.Contains("_SW_")) return 10; - if (scene.Name.Contains("_NSW_")) return 11; - if (scene.Name.Contains("_EW_")) return 12; - if (scene.Name.Contains("_NEW_")) return 13; - if (scene.Name.Contains("_SEW_")) return 14; - if (scene.Name.Contains("_NSEW_")) return 15; - return 0; - } - - [Command("la", "Allows you to search for a LevelArea.\nUsage: lookup la ")] - public string LevelArea(string[] @params, BattleClient invokerClient) - { - var matches = new List(); - - if (!@params.Any()) - return "Invalid arguments. Type 'help lookup la' to get help."; - - var pattern = @params[0].ToLower(); - - foreach (var pair in MPQStorage.Data.Assets[SNOGroup.LevelArea]) - if (pair.Value.Name.ToLower().Contains(pattern)) - matches.Add(pair.Value); - - return matches.Aggregate(matches.Count >= 1 ? "LevelArea Matches:\n" : "No match found.", - (current, match) => current + $"[{match.SNOId:D6}] {match.Name}\n"); - } - - [Command("sp", "List all Starting Points in world.\nUsage: lookup sp")] - public string StartingPoint(string[] @params, BattleClient invokerClient) - { - var matches = invokerClient.InGameClient.Player.World.StartingPoints; - - return matches.Aggregate(matches.Count >= 1 ? "Starting Points:\n" : "No match found.", - (current, match) => current + - $"[{match.GlobalID.ToString("D6")}] {match.Name} - {match.TargetId}\n"); - } - - [Command("weather", "Allows you to search for a Weather.\nUsage: lookup weather ")] - public string Weather(string[] @params, BattleClient invokerClient) - { - var matches = new List(); - - if (!@params.Any()) - return "Invalid arguments. Type 'help lookup weather' to get help."; - - var pattern = @params[0].ToLower(); - - foreach (var pair in MPQStorage.Data.Assets[SNOGroup.Weather]) - if (pair.Value.Name.ToLower().Contains(pattern)) - matches.Add(pair.Value); - - return matches.Aggregate(matches.Count >= 1 ? "Weather Matches:\n" : "No match found.", - (current, match) => current + $"[{match.SNOId:D6}] {match.Name}\n"); - } - - [Command("scene", "Allows you to search for a scene.\nUsage: lookup scene ")] - public string Scene(string[] @params, BattleClient invokerClient) - { - var matches = new List(); - - if (!@params.Any()) - return "Invalid arguments. Type 'help lookup scene' to get help."; - - var pattern = @params[0].ToLower(); - - foreach (var pair in MPQStorage.Data.Assets[SNOGroup.Scene]) - if (pair.Value.Name.ToLower().Contains(pattern)) - matches.Add(pair.Value); - - return matches.Aggregate(matches.Count >= 1 ? "Scene Matches:\n" : "No match found.", - (current, match) => current + - $"[{match.SNOId:D6}] {match.Name} - {GetExitBits(match)}\n"); - } - - [Command("eg", "Allows you to search for an EffectGroup.\nUsage: lookup eg ")] - public string EffectGroup(string[] @params, BattleClient invokerClient) - { - var matches = new List(); - - if (!@params.Any()) - return "Invalid arguments. Type 'help lookup eg' to get help."; - - var pattern = @params[0].ToLower(); - - foreach (var pair in MPQStorage.Data.Assets[SNOGroup.EffectGroup]) - if (pair.Value.Name.ToLower().Contains(pattern)) - matches.Add(pair.Value); - - return matches.Aggregate(matches.Count >= 1 ? "EffectGroup Matches:\n" : "No match found.", - (current, match) => current + - $"[{match.SNOId:D6}] {match.Name} - {GetExitBits(match)}\n"); - } - - [Command("item", "Allows you to search for an item.\nUsage: lookup item ")] - public string Item(string[] @params, BattleClient invokerClient) - { - var matches = new List(); - - if (!@params.Any()) - return "Invalid arguments. Type 'help lookup item' to get help."; - - var pattern = @params[0].ToLower(); - - foreach (var asset in MPQStorage.Data.Assets[SNOGroup.GameBalance].Values) - { - var data = asset.Data as GameBalance; - if (data == null || data.Type != BalanceType.Items) continue; - - foreach (var itemDefinition in data.Item) - if (itemDefinition.Name.ToLower().Contains(pattern)) - matches.Add(itemDefinition); - } - - return matches.Aggregate(matches.Count >= 1 ? "Item Matches:\n" : "No match found.", - (current, match) => current + $"[{match.SNOActor:D6}] {match.Name}\n"); - } - } -} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Implementations/Minions/NecromancerSkeleton_A.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Implementations/Minions/NecromancerSkeleton_A.cs index e6f27c6..ba9bda1 100644 --- a/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Implementations/Minions/NecromancerSkeleton_A.cs +++ b/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Implementations/Minions/NecromancerSkeleton_A.cs @@ -20,10 +20,12 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem.Implementations.Minions { Scale = 1.35f; - PowerContext context = new PowerContext(); - context.User = master as Player; - context.World = master.World; - context.PowerSNO = 453801; + PowerContext context = new() + { + User = master as Player, + World = master.World, + PowerSNO = 453801 + }; WalkSpeed *= 3; DamageCoefficient = context.ScriptFormula(14) * 2f; @@ -35,7 +37,7 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem.Implementations.Minions Attributes[GameAttribute.Hitpoints_Regen_Per_Second] = 0; Attributes[GameAttribute.Core_Attributes_From_Item_Bonus_Multiplier] = 1; - Attributes[GameAttribute.Hitpoints_Max] = 20f * (Master as Player).Toon.Level; + Attributes[GameAttribute.Hitpoints_Max] = 20f * ((Player) Master).Toon.Level; Attributes[GameAttribute.Hitpoints_Max_Percent_Bonus_Multiplicative] = 1; Attributes[GameAttribute.Hitpoints_Cur] = Attributes[GameAttribute.Hitpoints_Max_Total]; @@ -43,8 +45,8 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem.Implementations.Minions Attributes[GameAttribute.Summoned_By_SNO] = 453801; Attributes[GameAttribute.Attacks_Per_Second] = 1.0f; - Attributes[GameAttribute.Damage_Weapon_Min, 0] = 0.5f * context.User.Attributes[GameAttribute.Damage_Weapon_Min_Total, 0]; - Attributes[GameAttribute.Damage_Weapon_Delta, 0] = 0.5f * context.User.Attributes[GameAttribute.Damage_Weapon_Delta_Total, 0]; + Attributes[GameAttribute.Damage_Weapon_Min, 0] = 0.5f * context!.User!.Attributes[GameAttribute.Damage_Weapon_Min_Total, 0]; + Attributes[GameAttribute.Damage_Weapon_Delta, 0] = 0.5f * context!.User!.Attributes[GameAttribute.Damage_Weapon_Delta_Total, 0]; Attributes[GameAttribute.Pet_Type] = 0x8; //Pet_Owner and Pet_Creator seems to be 0 diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Implementations/Minions/SentryMinion.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Implementations/Minions/SentryMinion.cs index 55fac6a..6c078a0 100644 --- a/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Implementations/Minions/SentryMinion.cs +++ b/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Implementations/Minions/SentryMinion.cs @@ -33,7 +33,7 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem.Implementations.Minions WalkSpeed = 0f; DamageCoefficient = context.ScriptFormula(2); SetBrain(new MinionBrain(this)); - (Brain as MinionBrain).AddPresetPower(129661); //DemonHunter_Sentry_TurretAttack.pow + ((MinionBrain) Brain).AddPresetPower(129661); //DemonHunter_Sentry_TurretAttack.pow //TODO: These values should most likely scale, but we don't know how yet, so just temporary values. //Attributes[GameAttribute.Hitpoints_Max] = 20f; //Attributes[GameAttribute.Hitpoints_Cur] = 20f; diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/PowerSystem/Implementations/HeroSkills/Necromancer.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/PowerSystem/Implementations/HeroSkills/Necromancer.cs index 6a27a12..0d8c231 100644 --- a/src/DiIiS-NA/D3-GameServer/GSSystem/PowerSystem/Implementations/HeroSkills/Necromancer.cs +++ b/src/DiIiS-NA/D3-GameServer/GSSystem/PowerSystem/Implementations/HeroSkills/Necromancer.cs @@ -74,36 +74,36 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations EffectActor Explosion = SpawnEffect(defaultEff, TargetPosition, 0, WaitSeconds(0.4f)); Explosion.PlayEffect(Effect.PlayEffectGroup, RuneSelect(462185, 470458, 471513, 472538, 472598, 472762)); - var Targets = GetEnemiesInRadius(TargetPosition, 5f); + var targets = GetEnemiesInRadius(TargetPosition, 5f); - if (Targets.Actors.Count > 0) + if (targets.Actors.Count > 0) GeneratePrimaryResource(24f); if (Rune_A > 0) - foreach (var Target in Targets.Actors) - if (RandomHelper.Next(0, 100) > 60) - AddBuff(Target, new DebuffStunned(WaitSeconds(1f))); + foreach (var target in targets.Actors) + if (FastRandom.Instance.Chance(50)) + AddBuff(target, new DebuffStunned(WaitSeconds(1f))); if (Rune_D == 1) { - WeaponDamage(Targets, 1.50f, DamageType.Cold); + WeaponDamage(targets, 1.50f, DamageType.Cold); EffectActor Explosion1 = SpawnEffect(defaultEff, TargetPosition, 0, WaitSeconds(2f)); Explosion1.PlayEffect(Effect.PlayEffectGroup, 471410); - foreach (var Target in Targets.Actors) - AddBuff(Target, new DebuffChilled(0.4f, WaitSeconds(0.5f))); + foreach (var target in targets.Actors) + AddBuff(target, new DebuffChilled(0.4f, WaitSeconds(0.5f))); } else if (Rune_C == 1) { - var Target = GetEnemiesInRadius(TargetPosition, 5f); - if (Target.Actors.Count > 0) - WeaponDamage(Target.Actors[0], 1.50f, DamageType.Physical); - if (Target.Actors.Count > 1) + var target = GetEnemiesInRadius(TargetPosition, 5f); + if (target.Actors.Count > 0) + WeaponDamage(target.Actors[0], 1.50f, DamageType.Physical); + if (target.Actors.Count > 1) { for (int i = 0; i < 2; i++) - if (Target.Actors.Count >= i) + if (target.Actors.Count >= i) { - EffectActor ExplosionAdd = SpawnEffect(defaultEff, Target.Actors[i].Position, 0, WaitSeconds(0.4f)); + EffectActor ExplosionAdd = SpawnEffect(defaultEff, target.Actors[i].Position, 0, WaitSeconds(0.4f)); ExplosionAdd.PlayEffect(Effect.PlayEffectGroup, RuneSelect(462185, 470458, 471513, 472538, 472598, 472762)); - WeaponDamage(Target.Actors[i], 1.50f, DamageType.Physical); + WeaponDamage(target.Actors[i], 1.50f, DamageType.Physical); } } else @@ -116,33 +116,31 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations } else if (Rune_E == 1) { - WeaponDamage(Targets, 1.00f, DamageType.Physical); - foreach (var Target in Targets.Actors) - (User as PlayerSystem.Player).AddPercentageHP(0.5f); + WeaponDamage(targets, 1.00f, DamageType.Physical); + foreach (var target in targets.Actors) + ((Player)User).AddPercentageHP(0.5f); } else - WeaponDamage(Targets, 1.50f, DamageType.Physical); + WeaponDamage(targets, 1.50f, DamageType.Physical); } } else { - Vector3D Range = new Vector3D(); - - Range = TargetPosition - User.Position; + Vector3D range = TargetPosition - User.Position; - bool Regen = false; + bool regen = false; foreach (var divider in rangeDividers) { - var explosion = SpawnEffect(ActorSno._p6_necro_bonespikes, new Vector3D(User.Position.X + Range.X / divider, User.Position.Y + Range.Y / divider, TargetPosition.Z), 0, WaitSeconds(0.4f)); + var explosion = SpawnEffect(ActorSno._p6_necro_bonespikes, new Vector3D(User.Position.X + range.X / divider, User.Position.Y + range.Y / divider, TargetPosition.Z), 0, WaitSeconds(0.4f)); explosion.PlayEffect(Effect.PlayEffectGroup, 471513); var targets = GetEnemiesInRadius(explosion.Position, 5f); if (targets.Actors.Count > 0) - Regen = true; + regen = true; WeaponDamage(targets, 1.00f, DamageType.Physical); } - if (Regen) + if (regen) GeneratePrimaryResource(30f); } //yield return WaitSeconds(1f); @@ -247,38 +245,40 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations { public override IEnumerable Main() { - var PowerData = (DiIiS_NA.Core.MPQ.FileFormats.Power)MPQStorage.Data.Assets[SNOGroup.Power][PowerSNO].Data; + var powerData = (DiIiS_NA.Core.MPQ.FileFormats.Power)MPQStorage.Data.Assets[SNOGroup.Power][PowerSNO].Data; TargetPosition = PowerMath.TranslateDirection2D(User.Position, TargetPosition, User.Position, 7f); - DamageType DType = DamageType.Physical; - if (Rune_E > 0) DType = DamageType.Poison; - else if (Rune_C > 0) DType = DamageType.Cold; + DamageType damageType = DamageType.Physical; + if (Rune_E > 0) damageType = DamageType.Poison; + else if (Rune_C > 0) damageType = DamageType.Cold; - AttackPayload attack = new AttackPayload(this); - attack.Targets = GetEnemiesInRadius(TargetPosition, 7f); - attack.AddWeaponDamage(1.50f, DType); + AttackPayload attack = new(this) + { + Targets = GetEnemiesInRadius(TargetPosition, 7f) + }; + attack.AddWeaponDamage(1.50f, damageType); attack.OnHit = hit => { GeneratePrimaryResource(12f); - if (Rune_B > 0)//Казнь + if (Rune_B > 0)//Execution { if (hit.Target.Attributes[GameAttribute.Hitpoints_Cur] < (hit.Target.Attributes[GameAttribute.Hitpoints_Max_Total] / 5)) - if (RandomHelper.Next(1, 100) >= 95) + if (FastRandom.Instance.Chance(95)) WeaponDamage(hit.Target, 99999f, DamageType.Physical); } - else if (Rune_D > 0)//Парные + else if (Rune_D > 0)//Pare { WeaponDamage(hit.Target, 1.50f, DamageType.Physical); } - else if (Rune_E > 0)//Проклятая коса + else if (Rune_E > 0)//Cursed Scythe { if (RandomHelper.Next(1, 100) >= 85) { - //Рандомный дебаф. + //Random debuff AddBuff(Target, new DebuffChilled(0.75f, WaitSeconds(30f))); } } - else if (Rune_C > 0) //Морозная жатва + else if (Rune_C > 0) //Frost Harvest { AddBuff(User, new FBuff()); @@ -287,9 +287,9 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations //AddBuff(User, new TBuff()); //*/ } - else if (Rune_A > 0) //Мрачная жатва + else if (Rune_A > 0) //Dark Harvest { - (User as PlayerSystem.Player).AddPercentageHP(1); + ((Player) User).AddPercentageHP(1); } }; attack.Apply(); @@ -487,12 +487,14 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations } } + private bool _channelClosed; public override void OnChannelClose() { - if (_beamEnd != null) - _beamEnd.Destroy(); - if (Effect != null) - Effect.Destroy(); + if (_channelClosed) + return; + _beamEnd?.Destroy(); + Effect?.Destroy(); + _channelClosed = true; } public override void OnChannelUpdated() @@ -505,10 +507,8 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations var PowerData = (DiIiS_NA.Core.MPQ.FileFormats.Power)MPQStorage.Data.Assets[SNOGroup.Power][PowerSNO].Data; AttackPayload attack = new AttackPayload(this); { - if (attack.Targets == null) - attack.Targets = new TargetList(); - if (attack.Targets.Actors == null) - attack.Targets.Actors = new List(); + attack.Targets ??= new TargetList(); + attack.Targets.Actors ??= new List(); if (Target != null) attack.Targets.Actors.Add(Target); DamageType DType = DamageType.Physical; @@ -521,37 +521,37 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations Effect.AddComplexEffect(RuneSelect(467461, 467557, 467500, 467643, 469460, 469275), _beamEnd); //Effect.AddComplexEffect(baseEffectSkill, _beamEnd); AddBuff(hit.Target, new DebuffChilled(0.3f, WaitSeconds(0.5f))); - (User as PlayerSystem.Player).AddPercentageHP(2); + ((Player) User).AddPercentageHP(2); if (Rune_C < 1) GeneratePrimaryResource(15f); }; - if (Rune_E > 0)//Кровопийца + if (Rune_E > 0)//Bloodsucker { - //Присасываем сферы в радиусе 40 - (User as PlayerSystem.Player).VacuumPickupHealthOrb(40f); + //we are looking for all actors in a radius of 40 + ((Player) User).VacuumPickupHealthOrb(40f); } - else if (Rune_A > 0)//Подавление + else if (Rune_A > 0)//energy shift { - //Подморозка на 75% передвижения + //75% slow on movement AddBuff(Target, new DebuffChilled(0.75f, WaitSeconds(1f))); } - else if (Rune_D > 0)//Энергетический сдвиг + else if (Rune_D > 0)//energy shift { - //10 стаков по 10% к усилению дамага. + //10 stacks of 10% damage amplification AddBuff(User, new BustBuff()); } - else if (Rune_B > 0)//Чистая эссенция + else if (Rune_B > 0)//Pure Essence { - //Если HP 100% - восстанавливаем больше эссенции. + //If HP is 100% - we restore more essence. if (User.Attributes[GameAttribute.Hitpoints_Cur] == User.Attributes[GameAttribute.Hitpoints_Max_Total]) GeneratePrimaryResource(5f); } - else if (Rune_C > 0)//Похищение жизни + else if (Rune_C > 0)//Theft of life { - (User as PlayerSystem.Player).AddPercentageHP(4); - //10 стаков по 10% к усилению дамага. + ((Player) User).AddPercentageHP(4); + //10 stacks of 10% damage amplification. } } attack.Apply(); @@ -694,29 +694,29 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations } else { - var Actor = ActorSno._p6_necro_bonespear01_ghostly; + var actor = ActorSno._p6_necro_bonespear01_ghostly; if (Rune_C > 0) - Actor = ActorSno._p6_necro_bonespear01_decay; - if (Rune_A > 0) //Кристализация - Actor = ActorSno._p6_necro_bonespear01;//452802 - if (Rune_D > 0) //Кровавое копье + actor = ActorSno._p6_necro_bonespear01_decay; + if (Rune_A > 0) //Crystallization + actor = ActorSno._p6_necro_bonespear01;//452802 + if (Rune_D > 0) //Blood Spear { - Actor = ActorSno._p6_necro_bonespear01_blood; - (User as PlayerSystem.Player).AddPercentageHP(-10); + actor = ActorSno._p6_necro_bonespear01_blood; + ((Player) User).AddPercentageHP(-10); } - var projectile = new Projectile(this, Actor, User.Position); + var projectile = new Projectile(this, actor, User.Position); projectile.Position.Z += 5f; // fix height - float percentofmoredamage = 0; - DamageType NowDamage = DamageType.Physical; + float percentExtraDamage = 0; + DamageType damageType = DamageType.Physical; projectile.OnCollision = (hit) => { if (Rune_B > 0) { //var Targs = GetEnemiesInRadius(hit.Position, 15f); - foreach (var Targ in GetEnemiesInRadius(hit.Position, 15f).Actors) + foreach (var target in GetEnemiesInRadius(hit.Position, 15f).Actors) { - WeaponDamage(Targ, 5.0f, DamageType.Physical); + WeaponDamage(target, 5.0f, DamageType.Physical); } hit.PlayEffect(Effect.PlayEffectGroup, 465209); @@ -726,18 +726,18 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations { if (Rune_C > 0) { - percentofmoredamage += 0.15f; - NowDamage = DamageType.Poison; + percentExtraDamage += 0.15f; + damageType = DamageType.Poison; } if (Rune_A > 0) { - NowDamage = DamageType.Cold; + damageType = DamageType.Cold; AddBuff(hit, new SBuff()); AddBuff(User, new FBuff()); } hit.PlayEffect(Effect.PlayEffectGroup, 456994); - WeaponDamage(hit, Rune_D > 0 ? 6.5f : 5f + percentofmoredamage, NowDamage); + WeaponDamage(hit, Rune_D > 0 ? 6.5f : 5f + percentExtraDamage, damageType); } }; @@ -769,14 +769,6 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations Timeout = WaitSeconds(3f); } - public override bool Apply() - { - if (!base.Apply()) - return false; - - return true; - } - public override void OnPayload(Payload payload) { if (payload.Target == Target && payload is HitPayload) @@ -784,20 +776,6 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations } } - - public override bool Update() - { - if (base.Update()) - return true; - - return false; - } - - public override void Remove() - { - base.Remove(); - - } } [ImplementsPowerBuff(1, true)] @@ -932,7 +910,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations if (Rune_B > 0) { - Count = User.Attributes[GameAttribute.Resource_Cur, (int)(User as PlayerSystem.Player).Toon.HeroTable.PrimaryResource]; + Count = User.Attributes[GameAttribute.Resource_Cur, (int)((Player) User).Toon.HeroTable.PrimaryResource]; UsePrimaryResource(Count); } else if (Rune_C > 0) @@ -943,9 +921,9 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations else UsePrimaryResource(EvalTag(PowerKeys.ResourceCost)); - var dataOfSkill = MPQStorage.Data.Assets[SNOGroup.Power][PowerSNO].Data; + var dataOfSkill = MPQStorage.Data.Assets[SNOGroup.Power][PowerSNO].Data; - var Mage = new SkeletalMage( + var mage = new SkeletalMage( World, this, 0, @@ -958,26 +936,26 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations ActorSno._p6_necro_skeletonmage_f_archer ) ); - Mage.Brain.DeActivate(); + mage.Brain.DeActivate(); - Mage.Scale = 1.2f; - Mage.Position = RandomDirection(TargetPosition, 3f, 8f); - Mage.Attributes[GameAttribute.Untargetable] = true; - Mage.EnterWorld(Mage.Position); + mage.Scale = 1.2f; + mage.Position = RandomDirection(TargetPosition, 3f, 8f); + mage.Attributes[GameAttribute.Untargetable] = true; + mage.EnterWorld(mage.Position); yield return WaitSeconds(0.05f); - Mage.Brain.Activate(); - Mage.PlayEffectGroup(RuneSelect(472276, 472596, 472614, 472718, 472781, 472803)); - ((MinionBrain)Mage.Brain).PresetPowers.Clear(); - if (Rune_D > 0)//Заражение - AddBuff(Mage, new BustBuff7()); - else if (Rune_E > 0)//Лучник морозный - ((MinionBrain)Mage.Brain).AddPresetPower(30499); + mage.Brain.Activate(); + mage.PlayEffectGroup(RuneSelect(472276, 472596, 472614, 472718, 472781, 472803)); + ((MinionBrain)mage.Brain).PresetPowers.Clear(); + if (Rune_D > 0)//Infection + AddBuff(mage, new BustBuff7()); + else if (Rune_E > 0)//archer frosty + ((MinionBrain)mage.Brain).AddPresetPower(30499); else - ((MinionBrain)Mage.Brain).AddPresetPower(466879); + ((MinionBrain)mage.Brain).AddPresetPower(466879); - Mage.Attributes[GameAttribute.Untargetable] = false; - Mage.Attributes.BroadcastChangedIfRevealed(); + mage.Attributes[GameAttribute.Untargetable] = false; + mage.Attributes.BroadcastChangedIfRevealed(); yield break; } [ImplementsPowerBuff(1)] @@ -1223,48 +1201,48 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations float Dmg = 3.5f; DamageType DType = DamageType.Poison; User.PlayEffectGroup(RuneSelect(474458, 474459, 474460, 474461, 474462, 474463)); - int BoomEffect = 474290; + int boomEffect = 474290; if (Rune_E > 0) - switch ((User as PlayerSystem.Player).SpecialComboIndex) + switch (((Player) User).SpecialComboIndex) { case 0: - (User as PlayerSystem.Player).SpecialComboIndex++; - BoomEffect = 474410; + ((Player) User).SpecialComboIndex++; + boomEffect = 474410; break; case 1: Radius = 30f; - (User as PlayerSystem.Player).SpecialComboIndex++; - BoomEffect = 474432; + ((Player) User).SpecialComboIndex++; + boomEffect = 474432; break; case 2: Radius = 35f; - (User as PlayerSystem.Player).SpecialComboIndex = 0; - BoomEffect = 474421; + ((Player) User).SpecialComboIndex = 0; + boomEffect = 474421; break; } - else (User as PlayerSystem.Player).SpecialComboIndex = 0; + else ((Player) User).SpecialComboIndex = 0; if (Rune_A > 0) { Dmg = 2.25f; - BoomEffect = 466321; + boomEffect = 466321; DType = DamageType.Physical; } else if (Rune_B > 0) { Dmg = 4.75f; - BoomEffect = 466324; + boomEffect = 466324; DType = DamageType.Physical; } else if (Rune_C > 0) { - (User as PlayerSystem.Player).AddPercentageHP(-10); + ((Player) User).AddPercentageHP(-10); Dmg = 4.5f; - BoomEffect = 462662; + boomEffect = 462662; DType = DamageType.Physical; } else if (Rune_D > 0) { - BoomEffect = 472863; + boomEffect = 472863; DType = DamageType.Poison; var Proxy = SpawnProxy(User.Position, new TickTimer(User.World.Game, 300)); Proxy.PlayEffectGroup(471115); @@ -1273,14 +1251,16 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations AddBuff(act, new DebuffChilled(0.60f, WaitSeconds(1f))); } } - User.PlayEffectGroup(BoomEffect); - AttackPayload attack = new AttackPayload(this); - attack.Targets = GetEnemiesInRadius(User.Position, Radius); + User.PlayEffectGroup(boomEffect); + AttackPayload attack = new AttackPayload(this) + { + Targets = GetEnemiesInRadius(User.Position, Radius) + }; attack.AddWeaponDamage(Dmg, DType); attack.OnHit = hit => { if (Rune_A > 0) - (User as PlayerSystem.Player).AddPercentageHP(1); + ((Player) User).AddPercentageHP(1); }; attack.Apply(); @@ -1292,7 +1272,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations #region CorpseExlosion [ImplementsPowerSNO(SkillsSystem.Skills.Necromancer.ExtraSkills.CorpseExlosion)] - public class CorpseExlosion : Skill + public class CorpseExplosion : Skill { public override IEnumerable Main() { @@ -1300,7 +1280,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations //PowerDefinition_Fields //Мертвячинка) - if (player.SkillSet.HasPassive(208594)) 454066 if (Rune_B > 0) - (User as PlayerSystem.Player).AddPercentageHP(-2); + ((Player) User).AddPercentageHP(-2); float Radius = 20f; float Damage = 10.5f; DamageType DType = DamageType.Physical; @@ -1308,25 +1288,25 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations var Point = SpawnEffect(ActorSno._p6_necro_bonespikes, TargetPosition, 0, WaitSeconds(0.2f)); Point.PlayEffect(Effect.PlayEffectGroup, RuneSelect(459954, 473926, 459954, 473907, 459954//D , 473864)); - var Actors = User.Attributes[GameAttribute.Necromancer_Corpse_Free_Casting] + var actors = User.Attributes[GameAttribute.Necromancer_Corpse_Free_Casting] ? new List { User.World.SpawnMonster(ActorSno._p6_necro_corpse_flesh, TargetPosition).GlobalID } : User.GetActorsInRange(TargetPosition, 11).Where(x => x.SNO == ActorSno._p6_necro_corpse_flesh).Select(x => x.GlobalID).Take(5).ToList(); if (Rune_D > 0) Radius = 25f; - else if (Rune_C > 0)//Ближнее действие + else if (Rune_C > 0)//licking action { Damage = 15.75f; DType = DamageType.Poison; } else if (Rune_A > 0) DType = DamageType.Poison; - foreach (var actor in Actors) + foreach (var actor in actors) { if (Rune_B > 0) { - var Bomb = World.GetActorByGlobalId(actor); - var NearEnemy = Bomb.GetActorsInRange(20f).First(); - if (NearEnemy != null) - Bomb.Teleport(NearEnemy.Position); + var bomb = World.GetActorByGlobalId(actor); + var nearestEnemy = bomb.GetActorsInRange(20f).First(); + if (nearestEnemy != null) + bomb.Teleport(nearestEnemy.Position); } @@ -1341,8 +1321,10 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations Explosion.UpdateDelay = 0.1f; Explosion.OnUpdate = () => { - AttackPayload attack = new AttackPayload(this); - attack.Targets = GetEnemiesInRadius(User.Position, Radius); + AttackPayload attack = new AttackPayload(this) + { + Targets = GetEnemiesInRadius(User.Position, Radius) + }; if (Rune_E > 0) DType = DamageType.Cold; @@ -1443,29 +1425,28 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations if (Rune_C > 0) { - var NewProxy = SpawnProxy(User.Position, new TickTimer(User.World.Game, 300)); - - + var newProxy = SpawnProxy(User.Position, new TickTimer(User.World.Game, 300)); + foreach (var plr in User.World.Players.Values) { plr.InGameClient.SendMessage(new EffectGroupACDToACDMessage() { //A, D, E? EffectSNOId = RuneSelect(468032, 468032, 468240, 467966, 468032, 474474),//468032, - ActorID = NewProxy.DynamicID(plr), + ActorID = newProxy.DynamicID(plr), TargetID = Target.DynamicID(plr) }); plr.InGameClient.SendMessage(new EffectGroupACDToACDMessage() { EffectSNOId = 474690, ActorID = Target.DynamicID(plr), - TargetID = NewProxy.DynamicID(plr) + TargetID = newProxy.DynamicID(plr) }); } - TickTimer Timeout1 = new SecondsTickTimer(Target.World.Game, 0.4f); - var Boom1 = Task.Factory.StartNew(() => WaitTo(Timeout1)); - Boom1.ContinueWith(delegate + TickTimer timeout = new SecondsTickTimer(Target.World.Game, 0.4f); + var boom = Task.Factory.StartNew(() => WaitTo(timeout)); + boom.ContinueWith(delegate { Target.PlayEffect(Effect.PlayEffectGroup, 456994); WeaponDamage(Target, 5.25f, DType); @@ -1675,23 +1656,23 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations } act.PlayEffectGroup(RuneSelect(467200, 462756, 467230, 470482, 470549, 470574)); act.Destroy(); - User.Attributes[GameAttribute.Resource_Cur, (int)(User as PlayerSystem.Player).Toon.HeroTable.PrimaryResource] += 10f; + User.Attributes[GameAttribute.Resource_Cur, (int)((Player) User).Toon.HeroTable.PrimaryResource] += 10f; if (Rune_A > 0) - (User as PlayerSystem.Player).AddPercentageHP(3); + ((Player) User).AddPercentageHP(3); else if (Rune_E > 0) - AddBuff(User, new SBuff()); //Сытность + AddBuff(User, new SBuff()); //satiety else if (Rune_C > 0) - AddBuff(User, new TBuff()); //Ненасытность - else if (Rune_B > 0) //Бесчеловечность + AddBuff(User, new TBuff()); //Gluttony + else if (Rune_B > 0) //Inhumanity foreach (var minion in User.GetActorsInRange(60f)) { - if ((User as PlayerSystem.Player).FindFollowerIndex(minion.SNO) == 0) + if (((Player) User).FindFollowerIndex(minion.SNO) == 0) break; else { minion.Destroy(); - User.Attributes[GameAttribute.Resource_Cur, (int)(User as PlayerSystem.Player).Toon.HeroTable.PrimaryResource] += 10f; + User.Attributes[GameAttribute.Resource_Cur, (int)((Player) User).Toon.HeroTable.PrimaryResource] += 10f; } } User.Attributes.BroadcastChangedIfRevealed(); @@ -1740,7 +1721,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations { } } - [ImplementsPowerBuff(1, true)] //Сытность + [ImplementsPowerBuff(1, true)] //satiety public class SBuff : PowerBuff { public override void Init() @@ -1792,7 +1773,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations { if (!base.Apply()) return false; - (User as PlayerSystem.Player).DecreaseUseResourcePercent += 0.02f; + ((Player) User).DecreaseUseResourcePercent += 0.02f; return true; } @@ -1804,14 +1785,14 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations { base.Stack(buff); User.Attributes.BroadcastChangedIfRevealed(); - (User as PlayerSystem.Player).DecreaseUseResourcePercent += 0.02f; + ((Player) User).DecreaseUseResourcePercent += 0.02f; } return true; } public override void Remove() { User.Attributes.BroadcastChangedIfRevealed(); - (User as PlayerSystem.Player).DecreaseUseResourcePercent -= StackCount * 0.02f; + ((Player) User).DecreaseUseResourcePercent -= StackCount * 0.02f; base.Remove(); } private void _AddAmp() @@ -1830,19 +1811,19 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations #endregion public override IEnumerable Main() { - var DataOfSkill = MPQStorage.Data.Assets[SNOGroup.Power][PowerSNO].Data; + var skillData = MPQStorage.Data.Assets[SNOGroup.Power][PowerSNO].Data; //454066 var Proxy = SpawnProxy(TargetPosition, new TickTimer(User.World.Game, 300)); var Flesh = Proxy.GetActorsInRange(20f); bool Resurrected = false; if (Rune_B > 0) - (User as PlayerSystem.Player).AddPercentageHP(-3); + ((Player) User).AddPercentageHP(-3); Proxy.PlayEffectGroup(RuneSelect(465009, 465021, 465016, 465027, 465011, 465026)); foreach (var act in Flesh) { - if ((User as PlayerSystem.Player).Revived.Count < 10) + if (((Player) User).Revived.Count < 10) { var Temp = User.World.SpawnMonster((ActorSno)act.Attributes[GameAttribute.Necromancer_Corpse_Source_Monster_SNO], act.Position); var RevivedTemp = new Minion(User.World, Temp.SNO, User, Temp.Tags, false, true); @@ -1865,7 +1846,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations RevivedTemp.SetBrain(new AISystem.Brains.MinionBrain(RevivedTemp)); RevivedTemp.Brain.Activate(); RevivedTemp.PlayEffectGroup(RuneSelect(464739, 464900, 464872, 464954, 464859, 464746)); - (User as PlayerSystem.Player).Revived.Add(RevivedTemp); + ((Player) User).Revived.Add(RevivedTemp); Resurrected = true; RevivedTemp.Attributes[GameAttribute.Team_Override] = 1; RevivedTemp.Attributes.BroadcastChangedIfRevealed(); @@ -1876,9 +1857,9 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations if (Resurrected) if (Rune_E > 0) { - var Enemys = Proxy.GetActorsInRange(20f); - foreach (var Enemy in Enemys) - AddBuff(Enemy, new DebuffFeared(WaitSeconds(3f))); + var enemies = Proxy.GetActorsInRange(20f); + foreach (var enemy in enemies) + AddBuff(enemy, new DebuffFeared(WaitSeconds(3f))); } yield break; @@ -2125,7 +2106,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations //AddBuff(User, new TBuff()); //AddBuff(User, new FrBuff()); //*/ - var Golem = (User as PlayerSystem.Player).ActiveGolem; + var Golem = ((Player) User).ActiveGolem; int countofFlesh = 5; float cooldown = 5f; if (Rune_D > 0) @@ -2134,8 +2115,8 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations float targetDistance = PowerMath.Distance2D(TargetPosition, Golem.Position); if (Rune_E > 0) { - ((this.User as PlayerSystem.Player).ActiveGolem as Minion).Brain.DeActivate(); - (this.User as PlayerSystem.Player).ActiveGolem.PlayActionAnimation(AnimationSno.p6_icegolem_generic_cast); + (((Player)this.User).ActiveGolem as Minion).Brain.DeActivate(); + ((Player) User).ActiveGolem.PlayActionAnimation(AnimationSno.p6_icegolem_generic_cast); var proxy = SpawnProxy(TargetPosition, WaitSeconds(3f)); proxy.PlayEffectGroup(474839); @@ -2148,7 +2129,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations }; attack.Apply(); yield return WaitSeconds(1f); - ((User as PlayerSystem.Player).ActiveGolem as Minion).Brain.Activate(); + (((Player) User).ActiveGolem as Minion).Brain.Activate(); } else if (Rune_A > 0) { @@ -2164,7 +2145,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations yield return WaitSeconds(targetDistance * 0.024f); //Индикация зоны - (this.User as PlayerSystem.Player).ActiveGolem.PlayActionAnimation(AnimationSno.p6_bonegolem_active_01); + ((Player) User).ActiveGolem.PlayActionAnimation(AnimationSno.p6_bonegolem_active_01); var proxy = SpawnProxy(TargetPosition, WaitSeconds(2f)); //Рывок proxy.PlayEffectGroup(466735); //[466735] p6_necro_golem_bone_areaIndicator @@ -2200,7 +2181,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations else if (Rune_B > 0) { cooldown = 0f; - (User as PlayerSystem.Player).AddPercentageHP(25f); + ((Player) User).AddPercentageHP(25f); if (User.World.CheckLocationForFlag(TargetPosition, DiIiS_NA.Core.MPQ.FileFormats.Scene.NavCellFlags.AllowWalk)) { @@ -2275,7 +2256,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations (Golem as Minion).Kill(this); Golem.Destroy(); - (User as PlayerSystem.Player).ActiveGolem = null; + ((Player) User).ActiveGolem = null; }); @@ -2605,13 +2586,13 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations public override IEnumerable Main() { StartCooldown(EvalTag(PowerKeys.CooldownTime)); - var DataOfSkill = MPQStorage.Data.Assets[SNOGroup.Power][460358].Data; + var skillData = MPQStorage.Data.Assets[SNOGroup.Power][460358].Data; - var EffectSNO = ActorSno._necro_aotd_a_emitter; - float Range = 15f; - float Damage = 120.0f; - var DType = DamageType.Physical; - float Time = 1.0f; + var effectSno = ActorSno._necro_aotd_a_emitter; + float range = 15f; + float damage = 120.0f; + var damageType = DamageType.Physical; + float time = 1.0f; //Морозная шняга /* [466460] [Actor] necro_AotD_B_north_emitter @@ -2625,8 +2606,8 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations */ if (Rune_B > 0) { - DType = DamageType.Cold; - Damage = 5.2f; + damageType = DamageType.Cold; + damage = 5.2f; var Angle = ActorSystem.Movement.MovementHelpers.GetFacingAngle(User, TargetPosition); var E = SpawnEffect(ActorSno._necro_aotd_b_north_emitter, TargetPosition, Angle); @@ -2634,9 +2615,9 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations E.OnUpdate = () => { AttackPayload attack = new AttackPayload(this); - attack.Targets = GetEnemiesInRadius(E.Position, Range); + attack.Targets = GetEnemiesInRadius(E.Position, range); - attack.AddWeaponDamage(Damage, DType); + attack.AddWeaponDamage(damage, damageType); attack.OnHit = hitPayload => { @@ -2650,29 +2631,29 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations if (Rune_C > 0) { - EffectSNO = ActorSno._necro_aotd_c_emitter; - Range = 20f; - Damage = 500.0f; + effectSno = ActorSno._necro_aotd_c_emitter; + range = 20f; + damage = 500.0f; } else if (Rune_E > 0) { - (User as PlayerSystem.Player).AddPercentageHP(-20f); - EffectSNO = ActorSno._necro_aotd_f_emitter; - Time = 5.0f; - Damage = 6.2f; + ((Player) User).AddPercentageHP(-20f); + effectSno = ActorSno._necro_aotd_f_emitter; + time = 5.0f; + damage = 6.2f; } - var Point = SpawnEffect(EffectSNO, TargetPosition, 0, WaitSeconds(Time)); + var Point = SpawnEffect(effectSno, TargetPosition, 0, WaitSeconds(time)); yield return WaitSeconds(0.7f); - if (Rune_A > 0) { Damage = 140.0f; DType = DamageType.Poison; } - foreach (var Tar in Point.GetMonstersInRange(Range)) + if (Rune_A > 0) { damage = 140.0f; damageType = DamageType.Poison; } + foreach (var Tar in Point.GetMonstersInRange(range)) { if (Rune_C > 0) { int[] Effects = new int[] { 47400, 474402, 474435, 474437, 474453, 474455, 474464, 474466 }; Tar.PlayEffectGroup(Effects[RandomHelper.Next(0, 7)]); yield return WaitSeconds(0.5f); - WeaponDamage(Tar, Damage, DType); + WeaponDamage(Tar, damage, damageType); } else if (Rune_E > 0) @@ -2681,9 +2662,9 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations Point.OnUpdate = () => { AttackPayload attack = new AttackPayload(this); - attack.Targets = GetEnemiesInRadius(Point.Position, Range); + attack.Targets = GetEnemiesInRadius(Point.Position, range); - attack.AddWeaponDamage(Damage, DType); + attack.AddWeaponDamage(damage, damageType); attack.OnHit = hitPayload => { }; @@ -2694,7 +2675,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations { if (Rune_D > 0) Knockback(Tar, 5f); - WeaponDamage(Tar, Damage, DType); + WeaponDamage(Tar, damage, damageType); } } } @@ -3261,13 +3242,13 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations if (Rune_D > 0) //Проклятая земля { foreach (var alr in World.GetActorsBySNO(ActorSno._p6_necro_leech_e_proxyactor)) - if (alr.Attributes[GameAttribute.Summoner_ID] == (User as PlayerSystem.Player).PlayerIndex) + if (alr.Attributes[GameAttribute.Summoner_ID] == ((Player) User).PlayerIndex) alr.Destroy(); var proxy = SpawnEffect(ActorSno._p6_necro_leech_e_proxyactor, TargetPosition, ActorSystem.Movement.MovementHelpers.GetFacingAngle(User, TargetPosition), WaitSeconds(30f)); - proxy.Attributes[GameAttribute.Summoner_ID] = (User as PlayerSystem.Player).PlayerIndex; + proxy.Attributes[GameAttribute.Summoner_ID] = ((Player) User).PlayerIndex; AddBuff(User, new Rune_DBuff(proxy)); } else @@ -3521,7 +3502,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations if (Ticker.TimedOut) { - (User as PlayerSystem.Player).AddPercentageHP(Obj.GetMonstersInRange(20f).Count); + ((Player) User).AddPercentageHP(Obj.GetMonstersInRange(20f).Count); Ticker = new SecondsTickTimer(User.World.Game, 1.0f); } @@ -4146,7 +4127,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations else StartCooldown(EvalTag(PowerKeys.CooldownTime)); if (Rune_D > 0) - (User as PlayerSystem.Player).AddPercentageHP(-20f); + ((Player) User).AddPercentageHP(-20f); int Count = 0; @@ -4593,7 +4574,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations if (base.Update()) return true; - if ((User as PlayerSystem.Player).SkillSet.HasSkillWithRune(464896, 2)) + if (((Player) User).SkillSet.HasSkillWithRune(464896, 2)) Max = 4; else { @@ -4674,9 +4655,9 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Implementations Field2 = unchecked((int)0xD8A4C675) }); - (User as PlayerSystem.Player).InGameClient.SendMessage(new ACDTranslateSnappedMessage() + ((Player) User).InGameClient.SendMessage(new ACDTranslateSnappedMessage() { - ActorId = (int)User.DynamicID(User as PlayerSystem.Player), + ActorId = (int)User.DynamicID((Player) User), Position = PointTP.Position, Angle = ActorSystem.Movement.MovementHelpers.GetFacingAngle(User, PointTP), Field3 = true,