diff --git a/src/DiIiS-NA/Core/Logging/AnsiTarget.cs b/src/DiIiS-NA/Core/Logging/AnsiTarget.cs
index 6a31edf..5c4b609 100644
--- a/src/DiIiS-NA/Core/Logging/AnsiTarget.cs
+++ b/src/DiIiS-NA/Core/Logging/AnsiTarget.cs
@@ -57,8 +57,14 @@ public class AnsiTarget : LogTarget
CancellationTokenSource.Cancel();
}
-
- public static string Filter(string text)
+ ///
+ /// Logging keywords to beautify the output.
+ /// It's ugly, I know.
+ /// Changes are welcome - @iamdroppy
+ ///
+ /// Text to "beautify"
+ /// Replaced with color changes
+ public static string Beautify(string text)
{
return text
.Replace("Blizzless", "[dodgerblue1]Blizz[/][deepskyblue2]less[/]", StringComparison.CurrentCultureIgnoreCase)
@@ -81,7 +87,7 @@ public class AnsiTarget : LogTarget
///
///
///
- string Cleanup(string x) => Filter(x.Replace("[", "[[").Replace("]", "]]").Replace("$[[/]]$", "[/]").Replace("$[[", "[").Replace("]]$", "]"));
+ string Cleanup(string x) => Beautify(x.Replace("[", "[[").Replace("]", "]]").Replace("$[[/]]$", "[/]").Replace("$[[", "[").Replace("]]$", "]"));
public override void LogMessage(Logger.Level level, string logger, string message)
{
diff --git a/src/DiIiS-NA/Core/Logging/ConsoleTarget.cs b/src/DiIiS-NA/Core/Logging/ConsoleTarget.cs
index c5ed39e..4a771f2 100644
--- a/src/DiIiS-NA/Core/Logging/ConsoleTarget.cs
+++ b/src/DiIiS-NA/Core/Logging/ConsoleTarget.cs
@@ -52,7 +52,7 @@ namespace DiIiS_NA.Core.Logging
///
///
///
- string Cleanup(string x) => AnsiTarget.Filter(x.Replace("[", "[[").Replace("]", "]]").Replace("$[[/]]$", "[/]").Replace("$[[", "[").Replace("]]$", "]"));
+ string Cleanup(string x) => AnsiTarget.Beautify(x.Replace("[", "[[").Replace("]", "]]").Replace("$[[/]]$", "[/]").Replace("$[[", "[").Replace("]]$", "]"));
///
private static string SetColor(Logger.Level level, bool withBackground = false)
diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/CommandGroup.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/CommandGroup.cs
index 9b14ee4..cb1efe4 100644
--- a/src/DiIiS-NA/D3-GameServer/CommandManager/CommandGroup.cs
+++ b/src/DiIiS-NA/D3-GameServer/CommandManager/CommandGroup.cs
@@ -11,7 +11,7 @@ namespace DiIiS_NA.GameServer.CommandManager
{
public class CommandGroup
{
- private static readonly Logger Logger = LogManager.CreateLogger("CM");
+ private static readonly Logger Logger = LogManager.CreateLogger("Commands");
public CommandGroupAttribute Attributes { get; private set; }
@@ -37,7 +37,7 @@ namespace DiIiS_NA.GameServer.CommandManager
if (!_commands.ContainsKey(attribute))
_commands.Add(attribute, method);
else
- Logger.Error("Command '{0}' already exists.", attribute.Name);
+ Logger.Fatal("Command '$[underline white]${0}$[/]$' already exists.", attribute.Name);
}
}
@@ -62,8 +62,11 @@ namespace DiIiS_NA.GameServer.CommandManager
// check if the user has enough privileges to access command group.
// check if the user has enough privileges to invoke the command.
if (invokerClient != null && Attributes.MinUserLevel > invokerClient.Account.UserLevel)
+#if DEBUG
+ return $"You don't have enough privileges to invoke that command (Min. level: {Attributes.MinUserLevel}).";
+#else
return "You don't have enough privileges to invoke that command.";
-
+#endif
string[] @params = null;
CommandAttribute target = null;
@@ -99,13 +102,10 @@ namespace DiIiS_NA.GameServer.CommandManager
[DefaultCommand]
public virtual string Fallback(string[] @params = null, BattleClient invokerClient = null)
{
- var output = "Available subcommands: ";
- foreach (var pair in _commands)
- {
- if (pair.Key.Name.Trim() == string.Empty) continue; // skip fallback command.
- if (invokerClient != null && pair.Key.MinUserLevel > invokerClient.Account.UserLevel) continue;
- output += pair.Key.Name + ", ";
- }
+ var output = _commands
+ .Where(pair => pair.Key.Name.Trim() != string.Empty)
+ .Where(pair => invokerClient == null || pair.Key.MinUserLevel <= invokerClient.Account.UserLevel)
+ .Aggregate("Available subcommands: ", (current, pair) => current + (pair.Key.Name + ", "));
return output.Substring(0, output.Length - 2) + ".";
}
diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/CommandManager.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/CommandManager.cs
index c32d092..2d07573 100644
--- a/src/DiIiS-NA/D3-GameServer/CommandManager/CommandManager.cs
+++ b/src/DiIiS-NA/D3-GameServer/CommandManager/CommandManager.cs
@@ -150,21 +150,12 @@ namespace DiIiS_NA.GameServer.CommandManager
public override string Fallback(string[] parameters = null, BattleClient invokerClient = null)
{
var output = "Available commands: ";
- if (invokerClient != null)
- {
- foreach (var pair in CommandGroups.Where(pair =>
- pair.Key.MinUserLevel > invokerClient?.Account.UserLevel))
- {
- output += "!" + pair.Key.Name + ": " + pair.Key.Help + "\n\n";
- }
- }
- else
- {
- foreach (var pair in CommandGroups)
- {
- output += "!" + pair.Key.Name + ": " + pair.Key.Help + "\n\n";
- }
- }
+ output =
+ invokerClient != null
+ ? CommandGroups.Where(pair => pair.Key.MinUserLevel > invokerClient?.Account.UserLevel)
+ .Aggregate(output, (current, pair) => current + ($"{Config.Instance.CommandPrefix}{pair.Key.Name}: {pair.Key.Help}\n\n"))
+ : CommandGroups
+ .Aggregate(output, (current, pair) => current + (($"$[underline green]${Config.Instance.CommandPrefix}{pair.Key.Name}$[/]$: {pair.Key.Help}\n\n")));
return output + "Type 'help ' to get help about a specific command.";
}
@@ -173,10 +164,7 @@ namespace DiIiS_NA.GameServer.CommandManager
[CommandGroup("help", "usage: help \nType 'commands' to get a list of available commands.")]
public class HelpCommandGroup : CommandGroup
{
- public override string Fallback(string[] parameters = null, BattleClient invokerClient = null)
- {
- return "usage: help \nType 'commands' to get a list of available commands.";
- }
+ public override string Fallback(string[] parameters = null, BattleClient invokerClient = null) => "usage: help \nType 'commands' to get a list of available commands.";
public override string Handle(string parameters, BattleClient invokerClient = null)
{
@@ -189,11 +177,8 @@ namespace DiIiS_NA.GameServer.CommandManager
var group = @params[0];
var command = @params.Count() > 1 ? @params[1] : string.Empty;
- foreach (var pair in CommandGroups)
+ foreach (var pair in CommandGroups.Where(pair => group == pair.Key.Name))
{
- if (group != pair.Key.Name)
- continue;
-
if (command == string.Empty)
return pair.Key.Help;
@@ -202,7 +187,7 @@ namespace DiIiS_NA.GameServer.CommandManager
}
if (!found)
- output = string.Format("Unknown command: {0} {1}", group, command);
+ output = $"Unknown command: {group} {command}";
return output;
}
diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/GameCommands.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/GameCommands.cs
index a9bf146..9eddce5 100644
--- a/src/DiIiS-NA/D3-GameServer/CommandManager/GameCommands.cs
+++ b/src/DiIiS-NA/D3-GameServer/CommandManager/GameCommands.cs
@@ -19,1224 +19,1153 @@ using System.Linq;
using DiIiS_NA.GameServer.GSSystem.GameSystem;
using DiIiS_NA.GameServer.GSSystem.ObjectsSystem;
using DiIiS_NA.GameServer.GSSystem.PlayerSystem;
-using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Animation;
-using DiIiS_NA.GameServer.MessageSystem.Message.Fields;
using DiIiS_NA.LoginServer.AccountsSystem;
-using FluentNHibernate.Utils;
using static DiIiS_NA.Core.MPQ.FileFormats.GameBalance;
+using Actor = DiIiS_NA.Core.MPQ.FileFormats.Actor;
-namespace DiIiS_NA.GameServer.CommandManager
+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
{
- [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)
{
- [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))
{
- 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.FixedMap.Remove(FixedAttribute.Powerful);
player.Attributes.BroadcastChangedIfRevealed();
- return "You are now powerful.";
+ 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("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);
}
- [CommandGroup("info", "Get current game information.")]
- public class InfoCommand : CommandGroup
+ private string GetInfo(Account account, Player player, Game game)
{
- [DefaultCommand]
- public string Info(string[] @params, BattleClient invokerClient)
+ List info = new()
{
- 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);
- }
+ $"Game: {game.GameId}",
+ $"Difficulty: {game.Difficulty}",
+ $"Worlds: {game.Worlds.Count}",
+ $"Players: {game.Players.Count}",
+ $"Monsters: {game.Worlds.Sum(w => w.Monsters.Count)}"
+ };
- private string GetInfo(Account account, Player player, Game game)
- {
- List info = new()
+ if (account.UserLevel >= Account.UserLevels.GM)
+ foreach (var world in game.Worlds)
{
- $"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($"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($"> 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);
- }
+ 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);
}
- [CommandGroup("identify", "Identifies all items in your inventory.", Account.UserLevels.Tester)]
- public class IdentifyCommand
+ [Command("dismiss", "Dismisses all followers.")]
+ public string DismissAllCommand(string[] @params, BattleClient invokerClient)
{
- [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.";
+ if (invokerClient?.InGameClient?.Player is not { } player)
+ return "You are not in game.";
- var unidentified = player.Inventory.GetBackPackItems().Where(i => i.Unidentified).ToArray();
- int count = unidentified.Length;
- player.StartCasting(60*2, new Action(() =>
- {
- foreach (var item in unidentified)
- item.Identify();
- }));
- return $"Identified {count} items.";
- }
+ var followers = player.Followers.ToArray();
+ // destroy followers
+ foreach (var follower in followers) player.DestroyFollower(follower.Value);
+
+ return $"Dismissed {followers.Length} followers.";
}
- [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
+[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)
{
- [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}";
- }
+ 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}";
}
- [CommandGroup("heal", "Heals yourself", Account.UserLevels.Tester)]
- public class HealCommand : CommandGroup
+ [Command("down", "Decreases difficulty of the game", Account.UserLevels.GM)]
+ public string Down(string[] @params, BattleClient invokerClient)
{
- [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";
- }
+ 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}";
}
- [CommandGroup("invulnerable", "Makes you invulnerable", Account.UserLevels.GM)]
- public class InvulnerableCommand : CommandGroup
+ [Command("set", "Sets difficulty of the game", Account.UserLevels.GM)]
+ public string Set(string[] @params, BattleClient invokerClient)
{
- [DefaultCommand]
- public string Invulnerable(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))
{
- if (invokerClient?.InGameClient?.Player is not { } player)
- return "You can not 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.FixedMap.Remove(FixedAttribute.Invulnerable);
+ player.Attributes[GameAttribute.Invulnerable] = false;
player.Attributes.BroadcastChangedIfRevealed();
- return "You are now invulnerable.";
+ 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
+[CommandGroup("spawn", "Spawns a mob.\nUsage: spawn [actorSNO] [amount]", Account.UserLevels.GM)]
+public class SpawnCommand : CommandGroup
+{
+ [DefaultCommand]
+ public string Spawn(string[] @params, BattleClient invokerClient)
{
- [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 (invokerClient == null)
- return "You can not invoke this command from console.";
+ if (!Int32.TryParse(@params[0], out amount))
+ amount = 1;
- if (invokerClient.InGameClient == null)
- return "You can only invoke this command while ingame.";
+ if (amount > 100) amount = 100;
- 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 (!Int32.TryParse(@params[0], out actorSNO))
+ 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.Count() > 1)
- if (!Int32.TryParse(@params[1], out amount))
- amount = 1;
- if (amount > 100) amount = 100;
-
- }
-
- for (int 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}";
+ if (@params.Count() > 1)
+ if (!int.TryParse(@params[1], out amount))
+ amount = 1;
+ if (amount > 100) amount = 100;
}
- }
-
- [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)
+ for (var i = 0; i < amount; i++)
{
- if (invokerClient == null)
- return "You can not invoke this command from console.";
+ var position = new Vector3D(player.Position.X + (float)RandomHelper.NextDouble() * 20f,
+ player.Position.Y + (float)RandomHelper.NextDouble() * 20f,
+ player.Position.Z);
- if (invokerClient.InGameClient == null)
- return "You can only invoke this command while ingame.";
+ var monster = player.World.SpawnMonster((ActorSno)actorSNO, position);
+ }
- var player = invokerClient.InGameClient.Player;
- var amount = 1;
+ return $"Spawned {amount} mobs with ActorSNO: {actorSNO}";
+ }
+}
- if (@params != null)
- {
- if (!Int32.TryParse(@params[0], out amount))
- amount = 1;
- }
+[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.";
- for (int 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);
- }
- }
+ if (invokerClient.InGameClient == null)
+ return "You can only invoke this command while in-game.";
- player.Toon.GameAccount.NotifyUpdate();
+ 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)
- return $"New paragon level: {player.ParagonLevel}";
+ {
+ player.UpdateExp((int)player.Attributes[GameAttribute.Alt_Experience_Next_Lo]);
+ player.PlayEffect(Effect.ParagonLevelUp, null, false);
+ player.World.PowerManager.RunPower(player, 252038);
+ }
else
- return $"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 can not invoke this command from console.";
-
- if (invokerClient.InGameClient == null)
- return "You can only invoke this command while ingame.";
-
- 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 string.Format("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 can not invoke this command from console.";
-
- if (invokerClient.InGameClient == null)
- return "You can only invoke this command while ingame.";
-
- var player = invokerClient.InGameClient.Player;
- var amount = 1;
-
- if (@params != null)
{
- if (!Int32.TryParse(@params[0], out amount))
- amount = 1;
+ player.UpdateExp((int)player.Attributes[GameAttribute.Experience_Next_Lo]);
+ player.PlayEffect(Effect.LevelUp, null, false);
+ player.World.PowerManager.RunPower(player, 85954);
}
-
- player.InGameClient.SendMessage(new PlatinumAwardedMessage
- {
- CurrentPlatinum = player.InGameClient.BnetClient.Account.GameAccount.Platinum,
- PlatinumIncrement = amount
- });
-
- player.InGameClient.BnetClient.Account.GameAccount.Platinum += amount;
-
- return string.Format("Platinum test");
- }
+ player.Toon.GameAccount.NotifyUpdate();
+ return player.Level >= 70 ? $"New paragon level: {player.ParagonLevel}" : $"New level: {player.Toon.Level}";
}
+}
- [CommandGroup("stashup", "Upgrade Stash.", Account.UserLevels.Tester)]
- public class StashUpCommand : CommandGroup
+[CommandGroup("unlockart", "Unlock all artisans: !unlockart", Account.UserLevels.Tester)]
+public class UnlockArtCommand : CommandGroup
+{
+ [DefaultCommand]
+ public string UnlockArt(string[] @params, BattleClient invokerClient)
{
- [DefaultCommand]
- public string Stashup(string[] @params, BattleClient invokerClient)
- {
- if (invokerClient == null)
- return "You can not invoke this command from console.";
+ if (invokerClient == null)
+ return "You cannot invoke this command from console.";
- if (invokerClient.InGameClient == null)
- return "You can only invoke this command while ingame.";
+ if (invokerClient.InGameClient == null)
+ return "You can only invoke this command while in-game.";
- var player = invokerClient.InGameClient.Player;
+ var player = invokerClient.InGameClient.Player;
- player.Inventory.OnBuySharedStashSlots(null);
+ player.BlacksmithUnlocked = true;
+ player.JewelerUnlocked = true;
+ player.MysticUnlocked = true;
+ player.GrantAchievement(74987243307766); // Blacksmith
+ player.GrantAchievement(74987243307780); // Jeweler
+ player.GrantAchievement(74987247205955); // Mystic
- return string.Format("Stash Upgraded");
- }
+ 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("gold", "Gold for your character.\nOptionally specify the number of gold: !gold [count]", Account.UserLevels.GM)]
- public class GoldCommand : CommandGroup
+[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)
{
- [DefaultCommand]
- public string Gold(string[] @params, BattleClient invokerClient)
- {
- if (invokerClient == null)
- return "You can not invoke this command from console.";
+ if (invokerClient == null)
+ return "You cannot invoke this command from console.";
- if (invokerClient.InGameClient == null)
- return "You can only invoke this command while ingame.";
+ if (invokerClient.InGameClient == null)
+ return "You can only invoke this command while in-game.";
- var player = invokerClient.InGameClient.Player;
- var amount = 1;
+ var player = invokerClient.InGameClient.Player;
+ var amount = 1;
- if (@params != null)
- {
- if (!Int32.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 can not invoke this command from console.";
-
- if (invokerClient.InGameClient == null)
- return "You can only invoke this command while ingame.";
-
- var player = invokerClient.InGameClient.Player;
- var amount = 1;
- var achiid = 74987243307074;
-
- if (@params != null)
- {
- if (!Int32.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 string.Format("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 can not invoke this command from console.";
-
- if (invokerClient.InGameClient == null)
- return "You can only invoke this command while ingame.";
-
- var player = invokerClient.InGameClient.Player;
- var id = 1;
-
- if (@params != null)
- {
- if (!Int32.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 can not invoke this command from console.";
-
- if (invokerClient.InGameClient == null)
- return "You can only invoke this command while ingame.";
-
- 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.Count() == 1 || !Int32.TryParse(@params[1], out amount))
+ if (@params != null)
+ if (!int.TryParse(@params[0], out amount))
amount = 1;
- if (amount > 100) amount = 100;
- for (int 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)
+ player.InGameClient.SendMessage(new PlatinumAwardedMessage
{
- if (invokerClient == null)
- return "You can not invoke this command from console.";
+ CurrentPlatinum = player.InGameClient.BnetClient.Account.GameAccount.Platinum,
+ PlatinumIncrement = amount
+ });
- if (invokerClient.InGameClient == null)
- return "You can only invoke this command while ingame.";
+ player.InGameClient.BnetClient.Account.GameAccount.Platinum += amount;
- var player = invokerClient.InGameClient.Player;
- var name = "Dye";
- var amount = 1;
+ return "Platinum test";
+ }
+}
+[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 (@params == null)
- return "You need to specify a item type!";
+ if (invokerClient.InGameClient == null)
+ return "You can only invoke this command while in-game.";
- name = @params[0];
+ var player = invokerClient.InGameClient.Player;
- var type = ItemGroup.FromString(name);
+ player.Inventory.OnBuySharedStashSlots(null);
- if (type == null)
- return "The type given is not a valid item type.";
+ return "Stash Upgraded";
+ }
+}
- if (@params.Count() == 1 || !Int32.TryParse(@params[1], out amount))
+[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;
- if (amount > 100) amount = 100;
+ player.Inventory.AddGoldAmount(amount);
- for (int 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);
+ return $"Added Gold {amount}";
+ }
+}
- var item = ItemGenerator.GenerateRandom(player, type);
- item.EnterWorld(position);
- }
+[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.";
- return $"Spawned {amount} items with type: {name}";
- }
+ if (invokerClient.InGameClient == null)
+ return "You can only invoke this command while in-game.";
- [Command("dropall", "Drops all items in Backpack.\nUsage: item dropall")]
- public string DropAll(string[] @params, BattleClient invokerClient)
+ 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
{
- if (invokerClient == null)
- return "You can not invoke this command from console.";
-
- if (invokerClient.InGameClient == null)
- return "You can only invoke this command while ingame.";
-
- var player = invokerClient.InGameClient.Player;
-
- var bpItems = new List- (player.Inventory.GetBackPackItems());
+ CurrentPlatinum = 0,
+ idAchievement = (ulong)achiid,
+ PlatinumIncrement = amount
+ });
- 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";
+ 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.Count() == 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}";
}
- [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
+ [Command("type", "Spawns random items of a given type.\nUsage: item type [amount]")]
+ public string Type(string[] @params, BattleClient invokerClient)
{
- [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 (!Int32.TryParse(@params[0], out amount)) amount = 1;
+ if (invokerClient == null)
+ return "You cannot invoke this command from console.";
- amount = amount switch
- {
- < 1 => 1,
- > 20 => 20,
- _ => amount
- };
-
- try
- {
- for (int i = 0; i < amount; i++)
- player.World.SpawnRandomEquip(player, player, 11, player.Level, toonClass: player.Toon.Class, canBeUnidentified: false);
- }
- catch
- {
- for (int i = 0; i < amount; i++)
- player.World.SpawnRandomEquip(player, player, 8, player.Level, toonClass: player.Toon.Class, canBeUnidentified: false);
- }
- return $"Dropped {amount} random equipment.";
+ 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.Count() == 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}";
}
-
- [CommandGroup("tp", "Transfers your character to another world.")]
- public class TeleportCommand : CommandGroup
+ [Command("dropall", "Drops all items in Backpack.\nUsage: item dropall")]
+ public string DropAll(string[] @params, BattleClient invokerClient)
{
- [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.";
+
+ var player = invokerClient.InGameClient.Player;
+
+ var bpItems = new List
- (player.Inventory.GetBackPackItems());
+
+
+ foreach (var item in bpItems)
{
- if (invokerClient == null)
- return "You can not invoke this command from console.";
+ var msg = new InventoryDropItemMessage { ItemID = item.DynamicID(player) };
+ player.Inventory.Consume(invokerClient.InGameClient, msg);
+ }
- if (invokerClient.InGameClient == null)
- return "You can only invoke this command while ingame.";
+ return $"Dropped {bpItems.Count} Items for you";
+ }
+}
- if (@params != null && @params.Count() > 0)
+[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 worldId = 0;
- Int32.TryParse(@params[0], out 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)
+ 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
{
- 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.";
+ 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.Count() != 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("conversation", "Starts a conversation. \n Usage: conversation snoConversation")]
- public class ConversationCommand : CommandGroup
+[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 Conversation(string[] @params, BattleClient invokerClient)
+ public string Quest(string[] @params, BattleClient invokerClient)
{
if (invokerClient == null)
- return "You can not invoke this command from console.";
+ return "You cannot invoke this command from console.";
if (invokerClient.InGameClient == null)
- return "You can only invoke this command while ingame.";
+ return "You can only invoke this command while in-game.";
- if (@params.Count() != 1)
- return "Invalid arguments. Type 'help conversation' to get help.";
+ return "";
+ }
+ [Command("advance", "Advances a quest by a single step\n Usage: advance")]
+ public string Advance(string[] @params, BattleClient invokerClient)
+ {
try
{
- var conversation = MPQStorage.Data.Assets[SNOGroup.Conversation][Int32.Parse(@params[0])];
- invokerClient.InGameClient.Player.Conversations.StartConversation(Int32.Parse(@params[0]));
- return $"Started conversation {conversation.FileName}";
+ 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.Count() != 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.Count() != 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)
+ {
+ var questManager = invokerClient.InGameClient.Game.QuestManager;
+ 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("speed", "Modify speed walk of you character.\nUsage: !speed \nReset: !speed")]
- public class ModifySpeedCommand : CommandGroup
+ [CommandGroup("lookup",
+ "Searches in sno databases.\nUsage: lookup [actor|conv|power|scene|la|sp|weather] ")]
+ public class LookupCommand : CommandGroup
{
[DefaultCommand]
- public string ModifySpeed(string[] @params, BattleClient invokerClient)
+ public string Search(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;
+ return Fallback();
- const float maxSpeed = 2;
- const float baseSpeed = 0.36f;
+ var matches = new List();
- if (@params.Any())
+ 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")
{
- if (!float.TryParse(@params[0], out speedValue) || speedValue < 0 || speedValue > maxSpeed)
- return ("Invalid speed value. Must be a number between 0 and 2.");
+ 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
{
- 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 can not invoke this command from console.";
-
- if (invokerClient.InGameClient == null)
- return "You can only invoke this command while ingame.";
-
- return "";
- }
-
- [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 String.Format("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 String.Format("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.Count() != 1)
- return "Invalid arguments. Type 'help text public' to get help.";
-
- int questId = Int32.Parse(@params[0]);
-
- try
- {
- invokerClient.InGameClient.Game.QuestManager.LaunchSideQuest(questId, true);
- return String.Format("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.Count() != 2)
- return "Invalid arguments. Type 'help text public' to get help.";
-
- int eventId = Int32.Parse(@params[0]);
- int duration = Int32.Parse(@params[1]);
-
- invokerClient.InGameClient.Game.QuestManager.LaunchQuestTimer(eventId, (float)duration,
- new Action((q) => { }));
-
- return String.Format("Message sent.");
- }
-
- [Command("info", "Retrieves information about quest states.\n Usage: info")]
- public string Info(string[] @params, BattleClient invokerClient)
- {
- var questManager = invokerClient.InGameClient.Game.QuestManager;
- 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.Count() < 1)
- return "Invalid arguments. Type 'help lookup actor' to get help.";
-
var pattern = @params[0].ToLower();
-
- foreach (var groupPair in MPQStorage.Data.Assets)
- {
- foreach (var pair in groupPair.Value)
- {
- if (pair.Value.Name.ToLower().Contains(pattern))
- matches.Add(pair.Value);
- }
- }
-
- return matches.Aggregate(matches.Count >= 1 ? "Matches:\n" : "No matches found.",
- (current, match) => current +
- $"[{match.SNOId.ToString("D6")}] [{match.Group}] {match.Name}\n");
+ matches.AddRange(from pair in MPQStorage.Data.Assets[SNOGroup.Power] where pair.Value.Name.ToLower().Contains(pattern) select pair.Value);
}
- [Command("actor", "Allows you to search for an actor.\nUsage: lookup actor ")]
- public string Actor(string[] @params, BattleClient invokerClient)
- {
- var matches = new List();
-
- if (@params.Count() < 1)
- return "Invalid arguments. Type 'help lookup actor' to get help.";
-
- var pattern = @params[0].ToLower();
-
- foreach (var pair in MPQStorage.Data.Assets[SNOGroup.Actor])
- {
- if (pair.Value.Name.ToLower().Contains(pattern))
- matches.Add(pair.Value);
- }
-
- return matches.Aggregate(matches.Count >= 1 ? "Actor Matches:\n" : "No match found.",
- (current, match) => current +
- $"[{match.SNOId.ToString("D6")}] {match.Name} ({(match.Data as DiIiS_NA.Core.MPQ.FileFormats.Actor).Type} {(((match.Data as DiIiS_NA.Core.MPQ.FileFormats.Actor).Type == ActorType.Gizmo) ? ((int)(match.Data as DiIiS_NA.Core.MPQ.FileFormats.Actor).TagMap[ActorKeys.GizmoGroup]).ToString() : "")})\n");
- }
-
- [Command("rope", "Allows you to search for an rope.\nUsage: lookup rope ")]
- public string Rope(string[] @params, BattleClient invokerClient)
- {
- var matches = new List();
-
- if (@params.Count() < 1)
- return "Invalid arguments. Type 'help lookup actor' to get help.";
-
- var pattern = @params[0].ToLower();
-
- foreach (var pair in MPQStorage.Data.Assets[SNOGroup.Rope])
- {
- if (pair.Value.Name.ToLower().Contains(pattern))
- matches.Add(pair.Value);
- }
-
- return matches.Aggregate(matches.Count >= 1 ? "Rope Matches:\n" : "No match found.",
- (current, match) => current + $"[{match.SNOId.ToString("D6")}] {match.Name}\n");
- }
-
- [Command("conv", "Allows you to search for an conversation.\nUsage: lookup conv ")]
- public string Conversation(string[] @params, BattleClient invokerClient)
- {
- var matches = new List();
-
- if (@params.Count() < 1)
- return "Invalid arguments. Type 'help lookup actor' to get help.";
-
- var pattern = @params[0].ToLower();
-
- foreach (var pair in MPQStorage.Data.Assets[SNOGroup.Conversation])
- {
- if (pair.Value.Name.ToLower().Contains(pattern))
- matches.Add(pair.Value);
- }
-
- return matches.Aggregate(matches.Count >= 1 ? "Conversation Matches:\n" : "No match found.",
- (current, match) => current + $"[{match.SNOId.ToString("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.Count() < 1)
- return "Invalid arguments. Type 'help lookup power' to get help.";
-
- if (@params[0].ToLower() == "id")
- {
- var num = Int32.Parse(@params[1]);
- foreach (var pair in MPQStorage.Data.Assets[SNOGroup.Power])
- {
- if (pair.Value.SNOId == num)
- matches.Add(pair.Value);
- }
- }
- else
- {
- var pattern = @params[0].ToLower();
- foreach (var pair in MPQStorage.Data.Assets[SNOGroup.Power])
- {
- 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.ToString("D6")}] {match.Name} - {(match.Data as World).DynamicWorld}\n");
+ (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)
+ [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 matches = new List();
-
- if (@params.Count() < 1)
- return "Invalid arguments. Type 'help lookup world' to get help.";
-
- if (@params[0].ToLower() == "id")
- {
- var num = Int32.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.ToString("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.Count() < 1)
- return "Invalid arguments. Type 'help lookup world' to get help.";
-
- var num = Int32.Parse(@params[0]);
- string qr_id = "-1";
- string qr_name = "None";
- foreach (var pair in MPQStorage.Data.Assets[SNOGroup.QuestRange])
- {
+ var num = int.Parse(@params[1]);
+ foreach (var pair in MPQStorage.Data.Assets[SNOGroup.Worlds])
if (pair.Value.SNOId == num)
- {
- qr_id = pair.Value.SNOId.ToString("D6");
- qr_name = pair.Value.Name;
- }
- }
-
- return $"[{qr_id}] {qr_name}";
+ matches.Add(pair.Value);
}
-
- public static int GetExitBits(Asset scene)
+ else
{
- if (scene.Name.Contains("_N_")) return 1;
- else if (scene.Name.Contains("_S_")) return 2;
- else if (scene.Name.Contains("_NS_")) return 3;
- else if (scene.Name.Contains("_E_")) return 4;
- else if (scene.Name.Contains("_NE_")) return 5;
- else if (scene.Name.Contains("_SE_")) return 6;
- else if (scene.Name.Contains("_NSE_")) return 7;
- else if (scene.Name.Contains("_W_")) return 8;
- else if (scene.Name.Contains("_NW_")) return 9;
- else if (scene.Name.Contains("_SW_")) return 10;
- else if (scene.Name.Contains("_NSW_")) return 11;
- else if (scene.Name.Contains("_EW_")) return 12;
- else if (scene.Name.Contains("_NEW_")) return 13;
- else if (scene.Name.Contains("_SEW_")) return 14;
- else if (scene.Name.Contains("_NSEW_")) return 15;
- else 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.Count() < 1)
- return "Invalid arguments. Type 'help lookup la' to get help.";
-
var pattern = @params[0].ToLower();
-
- foreach (var pair in MPQStorage.Data.Assets[SNOGroup.LevelArea])
- {
+ 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 ? "LevelArea Matches:\n" : "No match found.",
- (current, match) => current + $"[{match.SNOId.ToString("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 ? "World Matches:\n" : "No match found.",
+ (current, match) => current +
+ $"[{match.SNOId:D6}] {match.Name} - {(match.Data as World).DynamicWorld}\n");
+ }
- 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("qr", "Show QuestRange of an actor.\nUsage: lookup qr ")]
+ public string QuestRange(string[] @params, BattleClient invokerClient)
+ {
+ var matches = new List();
- [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 world' to get help.";
- if (@params.Count() < 1)
- return "Invalid arguments. Type 'help lookup weather' to get help.";
-
- var pattern = @params[0].ToLower();
-
- foreach (var pair in MPQStorage.Data.Assets[SNOGroup.Weather])
+ 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)
{
- if (pair.Value.Name.ToLower().Contains(pattern))
- matches.Add(pair.Value);
+ qr_id = pair.Value.SNOId.ToString("D6");
+ qr_name = pair.Value.Name;
}
- return matches.Aggregate(matches.Count >= 1 ? "Weather Matches:\n" : "No match found.",
- (current, match) => current + $"[{match.SNOId.ToString("D6")}] {match.Name}\n");
- }
+ return $"[{qr_id}] {qr_name}";
+ }
- [Command("scene", "Allows you to search for a scene.\nUsage: lookup scene ")]
- public string Scene(string[] @params, BattleClient invokerClient)
+ 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 matches = new List();
-
- if (@params.Count() < 1)
- return "Invalid arguments. Type 'help lookup scene' to get help.";
+ var data = asset.Data as GameBalance;
+ if (data == null || data.Type != BalanceType.Items) continue;
- 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.ToString("D6")}] {match.Name} - {GetExitBits(match)}\n");
+ foreach (var itemDefinition in data.Item)
+ if (itemDefinition.Name.ToLower().Contains(pattern))
+ matches.Add(itemDefinition);
}
- [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.Count() < 1)
- 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.ToString("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.Count() < 1)
- 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.ToString("D6")}] {match.Name}\n");
- }
+ 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/Actor.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Actor.cs
index 75f7941..496f7a2 100644
--- a/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Actor.cs
+++ b/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Actor.cs
@@ -117,7 +117,7 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem
///
/// Attribute map.
///
- public GameAttributeMap Attributes { get; set; } //TODO: this needs to be "private set", but without errors on speed modifications
+ public GameAttributeMap Attributes { get; }
///
/// Affix list.
diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Implementations/ScriptObjects/actIIIBridgeLever.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Implementations/ScriptObjects/actIIIBridgeLever.cs
index fa8e34f..07cefc7 100644
--- a/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Implementations/ScriptObjects/actIIIBridgeLever.cs
+++ b/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Implementations/ScriptObjects/actIIIBridgeLever.cs
@@ -41,7 +41,7 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem.Implementations.ScriptObjects
{
try
{
- (World.FindAt(ActorSno._a3dun_keep_bridge, Position, 60.0f) as Door).Open();
+ (World.FindActorAt(ActorSno._a3dun_keep_bridge, Position, 60.0f) as Door).Open();
}
catch { }
}
diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Implementations/ScriptObjects/actIITombLever.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Implementations/ScriptObjects/actIITombLever.cs
index 7053199..b48c106 100644
--- a/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Implementations/ScriptObjects/actIITombLever.cs
+++ b/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Implementations/ScriptObjects/actIITombLever.cs
@@ -43,12 +43,12 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem.Implementations.ScriptObjects
if (Attributes[GameAttribute.Disabled] == true) return;
try
{
- Door waterfall = World.FindAt(ActorSno._caout_oasis_door_aqueduct_a_top, Position, 80.0f) as Door;
+ Door waterfall = World.FindActorAt(ActorSno._caout_oasis_door_aqueduct_a_top, Position, 80.0f) as Door;
if (waterfall == null)
{
- Door gate = World.FindAt(ActorSno._caout_oasis_door_aqueduct_a, Position, 80.0f) as Door;
+ Door gate = World.FindActorAt(ActorSno._caout_oasis_door_aqueduct_a, Position, 80.0f) as Door;
if (gate == null)
- (World.FindAt(ActorSno._caout_oasis_cenote_door, Position, 80.0f) as Door).Open();
+ (World.FindActorAt(ActorSno._caout_oasis_cenote_door, Position, 80.0f) as Door).Open();
else
gate.Open();
}
diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/MapSystem/World.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/MapSystem/World.cs
index a4a4c43..7e2d651 100644
--- a/src/DiIiS-NA/D3-GameServer/GSSystem/MapSystem/World.cs
+++ b/src/DiIiS-NA/D3-GameServer/GSSystem/MapSystem/World.cs
@@ -1,5 +1,13 @@
-using DiIiS_NA.Core.Helpers.Math;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using DiIiS_NA.Core.Helpers.Hash;
+using DiIiS_NA.Core.Helpers.Math;
using DiIiS_NA.Core.Logging;
+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.QuadTrees;
@@ -7,27 +15,22 @@ 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.ActorSystem.Implementations;
+using DiIiS_NA.GameServer.GSSystem.ActorSystem.Movement;
using DiIiS_NA.GameServer.GSSystem.GameSystem;
using DiIiS_NA.GameServer.GSSystem.ItemsSystem;
using DiIiS_NA.GameServer.GSSystem.ObjectsSystem;
using DiIiS_NA.GameServer.GSSystem.PlayerSystem;
using DiIiS_NA.GameServer.GSSystem.PowerSystem;
using DiIiS_NA.GameServer.MessageSystem;
+using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.ACD;
using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Animation;
using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Misc;
using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.World;
using DiIiS_NA.GameServer.MessageSystem.Message.Fields;
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using DiIiS_NA.Core.MPQ.FileFormats;
using DiIiS_NA.LoginServer.Toons;
using Actor = DiIiS_NA.GameServer.GSSystem.ActorSystem.Actor;
using Circle = DiIiS_NA.GameServer.Core.Types.Misc.Circle;
+using Environment = DiIiS_NA.Core.MPQ.FileFormats.Environment;
using Monster = DiIiS_NA.GameServer.GSSystem.ActorSystem.Monster;
using ResolvedPortalDestination = DiIiS_NA.GameServer.MessageSystem.Message.Fields.ResolvedPortalDestination;
@@ -36,8 +39,8 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
public sealed class World : DynamicObject, IRevealable, IUpdateable
{
static readonly Logger Logger = LogManager.CreateLogger();
- public readonly Dictionary> DbItems = new Dictionary>(); //we need this list to delete item_instances from items which have no owner anymore.
- public readonly Dictionary CachedItems = new Dictionary();
+ public readonly Dictionary> DbItems = new(); //we need this list to delete item_instances from items which have no owner anymore.
+ public readonly Dictionary CachedItems = new();
public int LastCEId = 3000;
@@ -52,30 +55,24 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
/// SNOHandle for the world.
///
public SNOHandle WorldSNO { get; private set; }
- public WorldSno SNO
- {
- get { return (WorldSno)WorldSNO.Id; }
- }
+ public WorldSno SNO => (WorldSno)WorldSNO.Id;
- ///
+ ///
/// QuadTree that contains scenes & actors.
///
private QuadTree _quadTree;
- public static QuadTree _PvPQuadTree = new QuadTree(new Size(60, 60), 0);
+ public static QuadTree _PvPQuadTree = new(new Size(60, 60), 0);
public QuadTree QuadTree
{
- get
- {
- return (IsPvP ? _PvPQuadTree : _quadTree);
- }
+ get => (IsPvP ? _PvPQuadTree : _quadTree);
set { }
}
///
/// WorldData loaded from MPQs/DB
///
- public DiIiS_NA.Core.MPQ.FileFormats.World worldData = new DiIiS_NA.Core.MPQ.FileFormats.World();
+ public DiIiS_NA.Core.MPQ.FileFormats.World worldData = new();
///
/// Destination for portals(on Exit and DungeonStone)
@@ -92,14 +89,11 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
///
private readonly ConcurrentDictionary _scenes;
- private static readonly ConcurrentDictionary _PvPscenes = new ConcurrentDictionary();
+ private static readonly ConcurrentDictionary _PvPscenes = new();
public ConcurrentDictionary Scenes
{
- get
- {
- return (IsPvP ? _PvPscenes : _scenes);
- }
+ get => (IsPvP ? _PvPscenes : _scenes);
set { }
}
@@ -108,46 +102,36 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
///
private readonly ConcurrentDictionary _actors;
- public static readonly ConcurrentDictionary _PvPActors = new ConcurrentDictionary();
+ public static readonly ConcurrentDictionary _PvPActors = new();
public ConcurrentDictionary Actors
{
- get
- {
- return (IsPvP ? _PvPActors : _actors);
- }
+ get => (IsPvP ? _PvPActors : _actors);
set { }
}
- public Dictionary PortalOverrides = new Dictionary();
+ public Dictionary PortalOverrides = new();
///
/// List of players contained in the world.
///
private readonly ConcurrentDictionary _players;
- public static readonly ConcurrentDictionary _PvPPlayers = new ConcurrentDictionary();
+ public static readonly ConcurrentDictionary _PvPPlayers = new();
- public ConcurrentDictionary Players
- {
- get
- {
- return (IsPvP ? _PvPPlayers : _players);
- }
- set { }
- }
+ public ConcurrentDictionary Players => (IsPvP ? _PvPPlayers : _players);
///
/// Returns true if the world has players in.
///
- public bool HasPlayersIn { get { return Players.Count > 0; } }
+ public bool HasPlayersIn => Players.Count > 0;
///
/// Returns a new dynamicId for scenes.
///
- public uint NewSceneID { get { return IsPvP ? NewPvPSceneID : Game.NewSceneID; } }
+ public uint NewSceneID => IsPvP ? NewPvPSceneID : Game.NewSceneID;
- public bool IsPvP { get { return SNO == WorldSno.pvp_duel_small_multi; } } //PvP_Duel_Small
+ public bool IsPvP => SNO == WorldSno.pvp_duel_small_multi; //PvP_Duel_Small
public static bool PvPMapLoaded = false;
@@ -164,21 +148,15 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
}
// Environment
- public DiIiS_NA.Core.MPQ.FileFormats.Environment Environment
- {
- get
- {
- return ((DiIiS_NA.Core.MPQ.FileFormats.World)DiIiS_NA.Core.MPQ.MPQStorage.Data.Assets[SNOGroup.Worlds][WorldSNO.Id].Data).Environment;
- }
- }
+ public Environment Environment => ((DiIiS_NA.Core.MPQ.FileFormats.World)MPQStorage.Data.Assets[SNOGroup.Worlds][WorldSNO.Id].Data).Environment;
private static uint _lastPvPObjectID = 10001;
- private static object obj = new object();
+ private static readonly object _obj = new();
public static uint NewActorPvPID
{
get
{
- lock (obj)
+ lock (_obj)
{
_lastPvPObjectID++;
return _lastPvPObjectID;
@@ -191,7 +169,7 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
{
get
{
- lock (obj)
+ lock (_obj)
{
_lastPvPSceneID++;
return _lastPvPSceneID;
@@ -218,14 +196,14 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
}
private PowerManager _powerManager;
- public static PowerManager _PvPPowerManager = new PowerManager();
+ public static PowerManager _PvPPowerManager = new();
- public PowerManager PowerManager { get { return IsPvP ? _PvPPowerManager : _powerManager; } }
+ public PowerManager PowerManager => IsPvP ? _PvPPowerManager : _powerManager;
private BuffManager _buffManager;
- public static BuffManager _PvPBuffManager = new BuffManager();
+ public static BuffManager _PvPBuffManager = new();
- public BuffManager BuffManager { get { return IsPvP ? _PvPBuffManager : _buffManager; } }
+ public BuffManager BuffManager => IsPvP ? _PvPBuffManager : _buffManager;
///
/// Creates a new world for the given game with given snoId.
@@ -257,8 +235,8 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
if (SNO == WorldSno.x1_bog_01) //Blood Marsh
{
- var worlds = new List() { WorldSno.x1_catacombs_level01, WorldSno.x1_catacombs_fakeentrance_02, WorldSno.x1_catacombs_fakeentrance_03, WorldSno.x1_catacombs_fakeentrance_04 };
- var scenes = new List() { 265624, 265655, 265678, 265693 };
+ var worlds = new List { WorldSno.x1_catacombs_level01, WorldSno.x1_catacombs_fakeentrance_02, WorldSno.x1_catacombs_fakeentrance_03, WorldSno.x1_catacombs_fakeentrance_04 };
+ var scenes = new List { 265624, 265655, 265678, 265693 };
foreach (var scene in scenes)
{
var wld = worlds[FastRandom.Instance.Next(worlds.Count)];
@@ -283,17 +261,17 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
{
foreach (var actor in player.GetActorsInRange().OfType()) // get IUpdateable actors in range.
{
- if (actorsToUpdate.Contains(actor as IUpdateable)) // don't let a single actor in range of more than players to get updated more thance per tick /raist.
+ if (actorsToUpdate.Contains(actor)) // don't let a single actor in range of more than players to get updated more thance per tick /raist.
continue;
- actorsToUpdate.Add(actor as IUpdateable);
+ actorsToUpdate.Add(actor);
}
}
foreach (var minion in Actors.Values.OfType())
{
- if (actorsToUpdate.Contains(minion as IUpdateable))
+ if (actorsToUpdate.Contains(minion))
continue;
- actorsToUpdate.Add(minion as IUpdateable);
+ actorsToUpdate.Add(minion);
}
foreach (var actor in actorsToUpdate) // trigger the updates.
{
@@ -313,6 +291,49 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
#region message broadcasting
+ ///
+ /// Broadcasts a message to all players in the world.
+ ///
+ /// The action that will be invoked to all players
+ /// If there was an error to broadcast to player.
+ public void BroadcastOperation(Action action)
+ {
+ foreach (var player in Players.Values)
+ {
+ if (player == null) continue;
+ try
+ {
+ action(player);
+ }
+ catch (Exception ex)
+ {
+ throw new Exception("Error while broadcasting to player " + player.Name, ex);
+ }
+ }
+ }
+
+ ///
+ /// Broadcasts a message to all players in the world where the is true.
+ ///
+ /// Players matching criteria
+ /// The action that will be invoked to all players
+ /// If there was an error to broadcast to player
+ public void BroadcastOperation(Func predicate, Action action)
+ {
+ foreach (var player in Players.Values.Where(predicate))
+ {
+ if (player == null) continue;
+ try
+ {
+ action(player);
+ }
+ catch (Exception ex)
+ {
+ throw new Exception("Error while broadcasting to player " + player.Name, ex);
+ }
+ }
+ }
+
// NOTE: Scenes are actually laid out in cells with Subscenes filling in certain areas under a Scene.
// We can use this design feature to track Actors' current scene and send updates to it and neighboring
// scenes instead of distance checking for broadcasting messages. / komiga
@@ -325,11 +346,7 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
/// The actor.
public void BroadcastIfRevealed(Func message, Actor actor)
{
- foreach (var player in Players.Values)
- {
- if (player.RevealedObjects.ContainsKey(actor.GlobalID))
- player.InGameClient.SendMessage(message(player));
- }
+ BroadcastOperation(player => player.RevealedObjects.ContainsKey(actor.GlobalID), player => player.InGameClient.SendMessage(message(player)));
}
///
@@ -338,10 +355,7 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
///
public void BroadcastGlobal(Func message)
{
- foreach (var player in Players.Values)
- {
- player.InGameClient.SendMessage(message(player));
- }
+ BroadcastOperation(player => player.InGameClient.SendMessage(message(player)));
}
///
@@ -349,9 +363,9 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
///
/// The message to broadcast.
/// The actor.
- public void BroadcastInclusive(Func message, Actor actor)
+ public void BroadcastInclusive(Func message, Actor actor, float? radius = null)
{
- var players = actor.GetPlayersInRange();
+ var players = actor.GetPlayersInRange(radius);
foreach (var player in players)
{
player.InGameClient.SendMessage(message(player));
@@ -404,12 +418,12 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
WorldSizeInFeetY = 5040,
snoDungeonFinderSourceWorld = -1
});
- player.InGameClient.SendMessage(new WorldStatusMessage() { WorldID = GlobalID, Field1 = false });
+ player.InGameClient.SendMessage(new WorldStatusMessage { WorldID = GlobalID, Field1 = false });
//*
- player.InGameClient.SendMessage(new WorldSyncedDataMessage()
+ player.InGameClient.SendMessage(new WorldSyncedDataMessage
{
WorldID = GlobalID,
- SyncedData = new WorldSyncedData()
+ SyncedData = new WorldSyncedData
{
SnoWeatherOverride = -1,
WeatherIntensityOverride = 0,
@@ -436,7 +450,7 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
foreach (var scene in Scenes.Values) scene.Unreveal(player);
player.RevealedObjects.Remove(GlobalID);
- player.InGameClient.SendMessage(new WorldStatusMessage() { WorldID = GlobalID, Field1 = true });
+ player.InGameClient.SendMessage(new WorldStatusMessage { WorldID = GlobalID, Field1 = true });
player.InGameClient.SendMessage(new PrefetchDataMessage(Opcodes.PrefetchWorldMessage) { SNO = WorldSNO.Id });
//player.InGameClient.SendMessage(new WorldDeletedMessage() { WorldID = this.GlobalID });
@@ -560,7 +574,7 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
UnitAniimStartTime = 0,
tAnim = new PlayAnimationMessageSpec[]
{
- new PlayAnimationMessageSpec()
+ new()
{
Duration = 150,
AnimationSNO = monster.AnimationSet.TagMapAnimDefault[animationTag],
@@ -576,7 +590,7 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
return monster;
}
- private Queue> _flippyTimers = new Queue>();
+ private Queue> _flippyTimers = new();
private const int FlippyDurationInTicks = 10;
private const int FlippyMaxDistanceManhattan = 10; // length of one side of the square around the player where the item will appear
@@ -592,14 +606,14 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
public void PlayPieAnimation(Actor actor, Actor User, int PowerSNO, Vector3D TargetPosition)
{
- BroadcastIfRevealed(plr => new MessageSystem.Message.Definitions.ACD.ACDTranslateDetPathPieWedgeMessage
+ BroadcastIfRevealed(plr => new ACDTranslateDetPathPieWedgeMessage
{
ann = (int)actor.DynamicID(plr),
StartPos = User.Position,
FirstTagetPos = User.Position,
MoveFlags = 9,
AnimTag = 1,
- PieData = new DPathPieData()
+ PieData = new DPathPieData
{
Field0 = TargetPosition,
Field1 = 1,
@@ -613,7 +627,7 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
public void PlayCircleAnimation(Actor actor, Actor User, int PowerSNO, Vector3D TargetPosition)
{
- BroadcastIfRevealed(plr => new MessageSystem.Message.Definitions.ACD.ACDTranslateDetPathSinMessage
+ BroadcastIfRevealed(plr => new ACDTranslateDetPathSinMessage
{
ActorID = actor.DynamicID(plr),
DPath = 6,
@@ -625,14 +639,14 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
Seed = 1,
Carry = 1,
TargetPostition = TargetPosition,
- Angle = ActorSystem.Movement.MovementHelpers.GetFacingAngle(User.Position, TargetPosition),
+ Angle = MovementHelpers.GetFacingAngle(User.Position, TargetPosition),
StartPosition = User.Position,
MoveFlags = 1,
AnimTag = 1,
PowerSNO = PowerSNO,
Var0Int = 1,
Var0Fl = 1f,
- SinData = new DPathSinData()
+ SinData = new DPathSinData
{
annOwner = (int)actor.DynamicID(plr),
SinIncAccel = 0f,
@@ -649,28 +663,28 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
public void PlayZigAnimation(Actor actor, Actor User, int PowerSNO, Vector3D TargetPosition)
{
- BroadcastIfRevealed(plr => new MessageSystem.Message.Definitions.ACD.ACDTranslateFacingMessage
+ BroadcastIfRevealed(plr => new ACDTranslateFacingMessage
{
ActorId = actor.DynamicID(plr),
- Angle = ActorSystem.Movement.MovementHelpers.GetFacingAngle(User.Position, TargetPosition),
+ Angle = MovementHelpers.GetFacingAngle(User.Position, TargetPosition),
TurnImmediately = true
}, actor);
- BroadcastIfRevealed(plr => new MessageSystem.Message.Definitions.ACD.ACDTranslateDetPathSinMessage
+ BroadcastIfRevealed(plr => new ACDTranslateDetPathSinMessage
{
ActorID = actor.DynamicID(plr),
DPath = 5,
Seed = 1,
Carry = 1,
TargetPostition = TargetPosition,
- Angle = ActorSystem.Movement.MovementHelpers.GetFacingAngle(User.Position, TargetPosition),
+ Angle = MovementHelpers.GetFacingAngle(User.Position, TargetPosition),
StartPosition = User.Position,
MoveFlags = 1,
AnimTag = 1,
PowerSNO = PowerSNO,
Var0Int = 1,
Var0Fl = 1f,
- SinData = new DPathSinData()
+ SinData = new DPathSinData
{
annOwner = (int)actor.DynamicID(plr),
SinIncAccel = 0f,
@@ -687,14 +701,14 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
public void PlayReverSpiralAnimation(Actor actor, Actor User, int PowerSNO, Vector3D TargetPosition)
{
- BroadcastIfRevealed(plr => new MessageSystem.Message.Definitions.ACD.ACDTranslateFacingMessage
+ BroadcastIfRevealed(plr => new ACDTranslateFacingMessage
{
ActorId = actor.DynamicID(plr),
- Angle = ActorSystem.Movement.MovementHelpers.GetFacingAngle(User.Position, TargetPosition),
+ Angle = MovementHelpers.GetFacingAngle(User.Position, TargetPosition),
TurnImmediately = true
}, actor);
- BroadcastIfRevealed(plr => new MessageSystem.Message.Definitions.ACD.ACDTranslateDetPathSinMessage
+ BroadcastIfRevealed(plr => new ACDTranslateDetPathSinMessage
{
ActorID = actor.DynamicID(plr),
DPath = 4,
@@ -706,14 +720,14 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
Seed = 1,
Carry = 1,
TargetPostition = TargetPosition,
- Angle = ActorSystem.Movement.MovementHelpers.GetFacingAngle(User.Position, TargetPosition),
+ Angle = MovementHelpers.GetFacingAngle(User.Position, TargetPosition),
StartPosition = User.Position,
MoveFlags = 1,
AnimTag = 1,
PowerSNO = PowerSNO,
Var0Int = 1,
Var0Fl = 1f,
- SinData = new DPathSinData()
+ SinData = new DPathSinData
{
annOwner = (int)actor.DynamicID(plr),
SinIncAccel = 0.2f,
@@ -730,14 +744,14 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
public void PlaySpiralAnimation(Actor actor, Actor User, int PowerSNO, Vector3D TargetPosition)
{
- BroadcastIfRevealed(plr => new MessageSystem.Message.Definitions.ACD.ACDTranslateFacingMessage
+ BroadcastIfRevealed(plr => new ACDTranslateFacingMessage
{
ActorId = actor.DynamicID(plr),
- Angle = ActorSystem.Movement.MovementHelpers.GetFacingAngle(User.Position, TargetPosition),
+ Angle = MovementHelpers.GetFacingAngle(User.Position, TargetPosition),
TurnImmediately = true
}, actor);
- BroadcastIfRevealed(plr => new MessageSystem.Message.Definitions.ACD.ACDTranslateDetPathSinMessage
+ BroadcastIfRevealed(plr => new ACDTranslateDetPathSinMessage
{
ActorID = actor.DynamicID(plr),
DPath = 3,
@@ -749,14 +763,14 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
Seed = 1,
Carry = 1,
TargetPostition = TargetPosition,
- Angle = ActorSystem.Movement.MovementHelpers.GetFacingAngle(User.Position, TargetPosition),
+ Angle = MovementHelpers.GetFacingAngle(User.Position, TargetPosition),
StartPosition = User.Position,
MoveFlags = 1,
AnimTag = 1,
PowerSNO = PowerSNO,
Var0Int = 1,
Var0Fl = 1f,
- SinData = new DPathSinData()
+ SinData = new DPathSinData
{
annOwner = (int)actor.DynamicID(plr),
SinIncAccel = 0.2f,
@@ -773,7 +787,7 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
public Item SpawnRandomEquip(Actor source, Player player, int forceQuality = -1, int forceLevel = -1,
GameBalance.ItemTypeTable type = null, bool canBeUnidentified = true, ToonClass toonClass = ToonClass.Unknown)
{
- Logger.Debug("SpawnRandomEquip(): quality {0}", forceQuality);
+ Logger.MethodTrace("SpawnRandomEquip(): quality {0}", forceQuality);
if (player != null)
{
int level = (forceLevel > 0 ? forceLevel : source.Attributes[GameAttribute.Level]);
@@ -857,7 +871,7 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
}
public void SpawnRandomPotion(Actor source, Player player)
{
- if (player != null && !player.Inventory.HaveEnough(DiIiS_NA.Core.Helpers.Hash.StringHashHelper.HashItemName("HealthPotionBottomless"), 1))
+ if (player != null && !player.Inventory.HaveEnough(StringHashHelper.HashItemName("HealthPotionBottomless"), 1))
{
var item = ItemGenerator.GenerateRandomPotion(player);
if (item == null) return;
@@ -946,7 +960,7 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
///
public bool HasActorsInGroup(string group)
{
- var groupHash = DiIiS_NA.Core.Helpers.Hash.StringHashHelper.HashItemName(group);
+ var groupHash = StringHashHelper.HashItemName(group);
foreach (var actor in Actors.Values)
{
if (actor.Tags != null)
@@ -963,7 +977,7 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
public List GetActorsInGroup(string group)
{
List matchingActors = new List();
- var groupHash = DiIiS_NA.Core.Helpers.Hash.StringHashHelper.HashItemName(group);
+ var groupHash = StringHashHelper.HashItemName(group);
foreach (var actor in Actors.Values)
{
if (actor.Tags != null)
@@ -1087,7 +1101,7 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
public void AddScene(Scene scene)
{
if (scene.GlobalID == 0 || HasScene(scene.GlobalID))
- throw new Exception(String.Format("Scene has an invalid ID or was already present (ID = {0})", scene.GlobalID));
+ throw new Exception($"Scene has an invalid ID or was already present (ID = {scene.GlobalID})");
Scenes.TryAdd(scene.GlobalID, scene); // add to scenes collection.
QuadTree.Insert(scene); // add it to quad-tree too.
@@ -1100,10 +1114,9 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
public void RemoveScene(Scene scene)
{
if (scene.GlobalID == 0 || !HasScene(scene.GlobalID))
- throw new Exception(String.Format("Scene has an invalid ID or was not present (ID = {0})", scene.GlobalID));
+ throw new Exception($"Scene has an invalid ID or was not present (ID = {scene.GlobalID})");
- Scene remotedScene;
- Scenes.TryRemove(scene.GlobalID, out remotedScene); // remove it from scenes collection.
+ Scenes.TryRemove(scene.GlobalID, out _); // remove it from scenes collection.
QuadTree.Remove(scene); // remove from quad-tree too.
}
@@ -1114,8 +1127,7 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
///
public Scene GetScene(uint dynamicID)
{
- Scene scene;
- Scenes.TryGetValue(dynamicID, out scene);
+ Scenes.TryGetValue(dynamicID, out var scene);
return scene;
}
@@ -1161,10 +1173,9 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
private void RemoveActor(Actor actor)
{
if (actor.GlobalID == 0 || !Actors.ContainsKey(actor.GlobalID))
- throw new Exception(String.Format("Actor has an invalid ID or was not present (ID = {0})", actor.GlobalID));
+ throw new Exception($"Actor has an invalid ID or was not present (ID = {actor.GlobalID})");
- Actor removedActor;
- Actors.TryRemove(actor.GlobalID, out removedActor); // remove it from actors collection.
+ Actors.TryRemove(actor.GlobalID, out _); // remove it from actors collection.
QuadTree.Remove(actor); // remove from quad-tree too.
if (actor.ActorType == ActorType.Player) // if actors is a player, remove it from players collection too.
@@ -1173,8 +1184,7 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
public Actor GetActorByGlobalId(uint globalID)
{
- Actor actor;
- Actors.TryGetValue(globalID, out actor);
+ Actors.TryGetValue(globalID, out var actor);
return actor;
}
@@ -1204,9 +1214,8 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
{
if (actor.ActorType == matchType)
return actor;
- else
- Logger.Warn("Attempted to get actor ID {0} as a {1}, whereas the actor is type {2}",
- dynamicID, Enum.GetName(typeof(ActorType), matchType), Enum.GetName(typeof(ActorType), actor.ActorType));
+ Logger.Warn("Attempted to get actor ID {0} as a {1}, whereas the actor is type {2}",
+ dynamicID, Enum.GetName(typeof(ActorType), matchType), Enum.GetName(typeof(ActorType), actor.ActorType));
}
return null;
}
@@ -1247,37 +1256,42 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
/// Adds given player to world.
///
/// The player to add.
- private void AddPlayer(Player player)
+ private bool AddPlayer(Player player)
{
+ if (player == null)
+ throw new Exception($"Player in world {SNO} is null and cannot be removed.");
+
if (player.GlobalID == 0 || HasPlayer(player.GlobalID))
- throw new Exception(String.Format("Player has an invalid ID or was already present (ID = {0})", player.GlobalID));
+ throw new Exception($"Player has an invalid ID or was already present (ID = {player.GlobalID})");
- Players.TryAdd(player.GlobalID, player); // add it to players collection.
+ return Players.TryAdd(player.GlobalID, player); // add it to players collection.
}
///
/// Removes given player from world.
///
///
- private void RemovePlayer(Player player)
+ private bool RemovePlayer(Player player)
{
+ if (player == null)
+ throw new Exception($"Player in world {SNO} is null and cannot be removed.");
+
if (player.GlobalID == 0 || !Players.ContainsKey(player.GlobalID))
- throw new Exception(String.Format("Player has an invalid ID or was not present (ID = {0})", player.GlobalID));
+ throw new Exception($"Player has an invalid ID or was not present (ID = {player.GlobalID})");
- Player removedPlayer;
- Players.TryRemove(player.GlobalID, out removedPlayer); // remove it from players collection.
+ return Players.TryRemove(player.GlobalID, out _); // remove it from players collection.
}
///
- /// Returns player with given dynamicId.
+ /// Returns player with a given predicate
///
- /// The dynamicId of the player.
- ///
- public Player GetPlayer(uint dynamicID)
+ /// Predicate to find player
+ /// Player result
+ /// Whether the player was found.
+ public bool TryGetPlayer(Func predicate, out Player player)
{
- Player player;
- Players.TryGetValue(dynamicID, out player);
- return player;
+ player = Players.Values.FirstOrDefault(predicate);
+ return player != null;
}
///
@@ -1285,40 +1299,28 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
///
/// The dynamicId of the player.
///
- public bool HasPlayer(uint dynamicID)
- {
- return Players.ContainsKey(dynamicID);
- }
+ public bool HasPlayer(uint dynamicID) => Players.ContainsKey(dynamicID);
///
/// Returns item with given dynamicId.
///
/// The dynamicId of the item.
///
- public Item GetItem(uint dynamicID)
- {
- return (Item)GetActorByGlobalId(dynamicID, ActorType.Item);
- }
+ public Item GetItem(uint dynamicID) => (Item)GetActorByGlobalId(dynamicID, ActorType.Item);
///
/// Returns true if world contains a monster with given dynamicId.
///
/// The dynamicId of the monster.
///
- public bool HasMonster(uint dynamicID)
- {
- return HasActor(dynamicID, ActorType.Monster);
- }
+ public bool HasMonster(uint dynamicID) => HasActor(dynamicID, ActorType.Monster);
///
/// Returns true if world contains an item with given dynamicId.
///
/// The dynamicId of the item.
///
- public bool HasItem(uint dynamicID)
- {
- return HasActor(dynamicID, ActorType.Item);
- }
+ public bool HasItem(uint dynamicID) => HasActor(dynamicID, ActorType.Item);
#endregion
@@ -1330,17 +1332,14 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
/// The id of the StartingPoint.
///
- public StartingPoint GetStartingPointById(int id)
- {
- return Actors.Values.OfType().Where(sp => sp.TargetId == id).ToList().FirstOrDefault();
- }
+ public StartingPoint GetStartingPointById(int id) => Actors.Values.OfType().Where(sp => sp.TargetId == id).ToList().FirstOrDefault();
- public Actor FindAt(ActorSno actorSno, Vector3D position, float radius = 3.0f)
+ public Actor FindActorAt(ActorSno actorSno, Vector3D position, float radius = 3.0f)
{
var proximityCircle = new Circle(position.X, position.Y, radius);
var actors = QuadTree.Query(proximityCircle);
- foreach (var actr in actors)
- if (actr.Attributes[GameAttribute.Disabled] == false && actr.Attributes[GameAttribute.Gizmo_Has_Been_Operated] == false && actr.SNO == actorSno) return actr;
+ foreach (var actor in actors)
+ if (actor.Attributes[GameAttribute.Disabled] == false && actor.Attributes[GameAttribute.Gizmo_Has_Been_Operated] == false && actor.SNO == actorSno) return actor;
return null;
}
@@ -1349,10 +1348,13 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
///
/// The id of the WayPoint
///
- public Waypoint GetWayPointById(int id)
- {
- return Actors.Values.OfType().FirstOrDefault(waypoint => waypoint.WaypointId == id);
- }
+ public Waypoint GetWayPointById(int id) => Actors.Values.OfType().FirstOrDefault(waypoint => waypoint.WaypointId == id);
+
+ public Waypoint[] GetAllWaypoints() => Actors.Values.OfType().ToArray();
+
+ public Waypoint[] GetAllWaypointsInWorld(WorldSno worldSno) => Actors.Values.OfType().Where(waypoint => waypoint.World.SNO == worldSno).ToArray();
+
+ public Waypoint[] GetAllWaypointsInWorld(World world) => Actors.Values.OfType().Where(waypoint => waypoint.World == world).ToArray();
#endregion
@@ -1360,8 +1362,27 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
public override void Destroy()
{
- // TODO: Destroy all objects /raist
-
+ Logger.Trace($"$[red]$Destroying$[/]$ World #{GlobalID} $[underline red]${SNO}$[/]$");
+ // TODO: Destroy all objects @iamdroppy - solution below added for testing on 21/01/2023
+ // foreach (var actor in Actors.Values)
+ // try
+ // {
+ // actor.Destroy();
+ // }
+ // catch {}
+ //
+ // foreach (var player in Players.Values)
+ // try
+ // {
+ // player.Destroy();
+ // }
+ // catch{}
+ // foreach (var portal in Portals)
+ // try
+ // {
+ // portal.Destroy();
+ // }
+ // catch{}
// TODO: Destroy pre-generated tile set
worldData = null;
@@ -1384,18 +1405,15 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
if (s.Parent != null) { scene = s.Parent; }
if (s.Subscenes.Count > 0)
{
- foreach (var subscene in s.Subscenes)
+ foreach (var subScene in s.Subscenes.Where(subScene => subScene.Bounds.Contains(location.X, location.Y)))
{
- if (subscene.Bounds.Contains(location.X, location.Y))
- {
- scene = subscene;
- }
+ scene = subScene;
}
}
int x = (int)((location.X - scene.Bounds.Left) / 2.5f);
int y = (int)((location.Y - scene.Bounds.Top) / 2.5f);
- int total = (int)((y * scene.NavMesh.SquaresCountX) + x);
+ int total = (y * scene.NavMesh.SquaresCountX) + x;
if (total < 0 || total > scene.NavMesh.NavMeshSquareCount)
{
Logger.Error("Navmesh overflow!");
@@ -1413,57 +1431,59 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
public float GetZForLocation(Vector3D location, float defaultZ)
{
- foreach (Scene s in Scenes.Values)
+ foreach (Scene s in Scenes.Values.Where(s => s.Bounds.Contains(location.X, location.Y)))
{
- if (s.Bounds.Contains(location.X, location.Y))
+ Scene scene = s;
+ if (s.Parent != null)
{
- Scene scene = s;
- if (s.Parent != null) { scene = s.Parent; }
- if (s.Subscenes.Count > 0)
+ scene = s.Parent;
+ }
+
+ if (s.Subscenes.Count > 0)
+ {
+ foreach (var subScene in s.Subscenes)
{
- foreach (var subscene in s.Subscenes)
+ if (subScene.Bounds.Contains(location.X, location.Y))
{
- if (subscene.Bounds.Contains(location.X, location.Y))
- {
- scene = subscene;
- }
+ scene = subScene;
}
}
+ }
- int x = (int)((location.X - scene.Bounds.Left) / 2.5f);
- int y = (int)((location.Y - scene.Bounds.Top) / 2.5f);
- int total = (int)((y * scene.NavMesh.SquaresCountX) + x);
- if (total < 0 || total > scene.NavMesh.NavMeshSquareCount)
- {
- Logger.Error("Navmesh overflow!");
- return defaultZ;
- }
- try
- {
- return scene.NavMesh.Squares[total].Z;
- }
- catch
- {
- return defaultZ;
- }
+ int x = (int)((location.X - scene.Bounds.Left) / 2.5f);
+ int y = (int)((location.Y - scene.Bounds.Top) / 2.5f);
+ int total = (y * scene.NavMesh.SquaresCountX) + x;
+ if (total < 0 || total > scene.NavMesh.NavMeshSquareCount)
+ {
+ Logger.Error("Navmesh overflow!");
+ return defaultZ;
+ }
+
+ try
+ {
+ return scene.NavMesh.Squares[total].Z;
+ }
+ catch
+ {
+ return defaultZ;
}
}
+
return defaultZ;
}
+ [Obsolete("Isn't used anymore")] // made obsolete by @iamdroppy on 28/01/2023
public bool CheckRayPath(Vector3D start, Vector3D destination)
{
-
var proximity = new RectangleF(start.X - 1f, start.Y - 1f, 2f, 2f);
var scenes = QuadTree.Query(proximity);
if (scenes.Count == 0) return false;
- var scene = scenes[0]; // Parent scene /fasbat
-
if (scenes.Count == 2) // What if it's a subscene? /fasbat
{
if (scenes[1].ParentChunkID != 0xFFFFFFFF)
- scene = scenes[1];
+ {
+ }
}
return true;
@@ -1471,7 +1491,7 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
public override string ToString()
{
- return string.Format("[World] SNOId: {0} GlobalId: {1} Name: {2}", WorldSNO.Id, GlobalID, WorldSNO.Name);
+ return $"[World] SNOId: {WorldSNO.Id} GlobalId: {GlobalID} Name: {WorldSNO.Name}";
}
}
}
diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/PlayerSystem/Player.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/PlayerSystem/Player.cs
index 5324589..a661fe6 100644
--- a/src/DiIiS-NA/D3-GameServer/GSSystem/PlayerSystem/Player.cs
+++ b/src/DiIiS-NA/D3-GameServer/GSSystem/PlayerSystem/Player.cs
@@ -1,4 +1,5 @@
//Blizzless Project 2022
+
using System;
//Blizzless Project 2022
using System.Collections.Generic;
@@ -122,2670 +123,2937 @@ using DiIiS_NA.D3_GameServer.GSSystem.ActorSystem.Implementations.Artisans;
using DiIiS_NA.D3_GameServer.GSSystem.PlayerSystem;
using NHibernate.Util;
-namespace DiIiS_NA.GameServer.GSSystem.PlayerSystem
+namespace DiIiS_NA.GameServer.GSSystem.PlayerSystem;
+
+public class Player : Actor, IMessageConsumer, IUpdateable
{
- public class Player : Actor, IMessageConsumer, IUpdateable
- {
- private static readonly Logger Logger = LogManager.CreateLogger();
-
- ///
- /// The ingame-client for player.
- ///
- public GameClient InGameClient { get; set; }
-
- ///
- /// The player index.
- ///
- public int PlayerIndex { get; private set; }
-
- ///
- /// The player index.
- ///
- public int PlayerGroupIndex { get; private set; }
-
- ///
- /// Current crafting NPC type(for learning recipes)
- ///
- public ArtisanType? CurrentArtisan { get; set; }
-
- ///
- /// The player's toon.
- /// We need a better name /raist.
- ///
- public Toon Toon { get; private set; }
-
- public float DecreaseUseResourcePercent = 0;
- public int Level { get; private set; }
- public int ParagonLevel { get; private set; }
- public long ExperienceNext { get; private set; }
- public List Revived = new List() { };
-
- public bool LevelingBoosted { get; set; }
-
- public int PreSceneId = -1;
-
- public List NecroSkeletons = new List { };
- public bool ActiveSkeletons = false;
- public Actor ActiveGolem = null;
- public bool EnableGolem = false;
- public bool IsInPvPWorld
- {
- get => (World != null && World.IsPvP);
- set { }
- }
-
- ///
- /// Skillset for the player (or actually for player's toons class).
- ///
- public SkillSet SkillSet { get; private set; }
-
- ///
- /// The inventory of player's toon.
- ///
- public Inventory Inventory { get; private set; }
-
- public int GearScore
- {
- get
- {
- if (Inventory == null)
- return 0;
- else
- return Inventory.GetGearScore();
- }
- private set { }
- }
-
- public Actor PlayerDirectBanner = null;
-
- public uint NewDynamicID(uint globalId, int pIndex = -1)
- {
- lock (RevealedObjects)
- {
- if (pIndex > -1)
- return (uint)pIndex;
- for (uint i = 9; i < 4123; i++)
- {
- if (!RevealedObjects.ContainsValue(i))
- {
- //Logger.Trace("adding GlobalId {0} -> DynID {1} to player {2}", globalId, i, this.Toon.Name);
- return i;
- }
- }
- return 0;
- }
- }
-
- ///
- /// ActorType = Player.
- ///
- public override ActorType ActorType => ActorType.Player;
-
- ///
- /// Revealed objects to player.
- ///
- public Dictionary RevealedObjects = new Dictionary();
-
- public ConversationManager Conversations { get; private set; }
- public int SpecialComboIndex = 0;
- // Collection of items that only the player can see. This is only used when items drop from killing an actor
- // TODO: Might want to just have a field on the item itself to indicate whether it is visible to only one player
- ///
- /// Dropped items for the player
- ///
- public Dictionary GroundItems { get; private set; }
-
- ///
- /// Everything connected to ExpBonuses.
- ///
- public ExpBonusData ExpBonusData { get; private set; }
-
- public bool EventWeatherEnabled { get; set; }
-
- public bool BlacksmithUnlocked { get; set; }
- public bool JewelerUnlocked { get; set; }
- public bool MysticUnlocked { get; set; }
- public bool KanaiUnlocked { get; set; }
-
- public bool HirelingTemplarUnlocked { get; set; }
- public bool HirelingScoundrelUnlocked { get; set; }
- public bool HirelingEnchantressUnlocked { get; set; }
-
- public int LastMovementTick = 0;
-
- public int _spiritGenHit = 0;
- public int _SpiritGeneratorHit
- {
- get => _spiritGenHit;
-
- set
- {
- _spiritGenHit = value;
- if (SkillSet.HasPassive(315271) && _spiritGenHit >= 3) //Mythic Rhythm
- {
- World.BuffManager.AddBuff(this, this, new MythicRhythmBuff());
- _spiritGenHit = 0;
- }
- }
- }
-
- ///
- /// NPC currently interaced with
- ///
- public InteractiveNPC SelectedNPC { get; set; }
- public Dictionary Followers { get; private set; }
- private Hireling _activeHireling = null;
- private Hireling _questHireling = null;
- public Hireling ActiveHireling
- {
- get => _activeHireling;
- set
- {
- if (value == null)
- {
- HirelingId = null;
- lock (Toon.DBToon)
- {
- var dbToon = Toon.DBToon;
- dbToon.ActiveHireling = null;
- DBSessions.SessionUpdate(dbToon);
- }
- }
- else if (value != _activeHireling)
- {
- HirelingId = value.Attributes[GameAttribute.Hireling_Class];
- lock (Toon.DBToon)
- {
- var dbToon = Toon.DBToon;
- dbToon.ActiveHireling = value.Attributes[GameAttribute.Hireling_Class];
- DBSessions.SessionUpdate(dbToon);
- }
- }
-
- if (value == _activeHireling && value != null)
- return;
-
- if (_activeHireling != null)
- {
- _activeHireling.Dismiss();
- }
-
- _activeHireling = value;
- }
- }
- public Hireling QuestHireling
- {
- get => _questHireling;
- set
- {
- if (_questHireling != null)
- {
- _questHireling.Dismiss();
- }
- _questHireling = value;
- }
- }
- public int CurrentWingsPowerId = -1;
- private int _lastResourceUpdateTick;
- private float _CurrentHPValue = -1f;
- private float _CurrentResourceValue = -1f;
- public int GoldCollectedTempCount = 0;
- public int BloodShardsCollectedTempCount = 0;
- public int KilledMonstersTempCount = 0;
- public int KilledSeasonalTempCount = 0;
- public int KilledElitesTempCount = 0;
- public int BuffStreakKill = 0;
- private ushort[] ParagonBonuses;
- public int? HirelingId = null;
- public bool IsCasting = false;
- private Action CastResult = null;
- private Action ConfirmationResult = null;
- private const float SkillChangeCooldownLength = 10f;
- ///
- /// Creates a new player.
- ///
- /// The initial world player joins in.
- /// The gameclient for the player.
- /// Toon of the player.
- public Player(World world, GameClient client, Toon bnetToon)
- : base(world, bnetToon.Gender == 0 ? (ActorSno)bnetToon.HeroTable.SNOMaleActor : (ActorSno)bnetToon.HeroTable.SNOFemaleActor)
- {
- InGameClient = client;
- PlayerIndex = Interlocked.Increment(ref InGameClient.Game.PlayerIndexCounter);
- PlayerGroupIndex = InGameClient.Game.PlayerGroupIndexCounter;
- Toon = bnetToon;
- LevelingBoosted = Toon.LevelingBoosted;
- var dbToon = Toon.DBToon;
- HirelingId = dbToon.ActiveHireling;
- GBHandle.Type = (int)ActorType.Player;
- GBHandle.GBID = Toon.ClassID;
- Level = dbToon.Level;
- ParagonLevel = Toon.ParagonLevel;
- ExperienceNext = Toon.ExperienceNext;
- ParagonBonuses = dbToon.ParagonBonuses;
- CurrentWingsPowerId = dbToon.WingsActive;
-
- Field2 = 0x00000009;
- Scale = ModelScale;
- RotationW = 0.05940768f;
- RotationAxis = new Vector3D(0f, 0f, 0.9982339f);
- Field7 = -1;
- NameSNO = ActorSno.__NONE;
- Field10 = 0x0;
- Dead = false;
- EventWeatherEnabled = false;
-
- var achievements = InGameClient.Game.GameDBSession.SessionQueryWhere(dba => dba.DBGameAccount.Id == Toon.GameAccount.PersistentID);
-
- BlacksmithUnlocked = achievements.Any(dba => dba.AchievementId == 74987243307766);
- JewelerUnlocked = achievements.Any(dba => dba.AchievementId == 74987243307780);
- MysticUnlocked = achievements.Any(dba => dba.AchievementId == 74987247205955);
-
- KanaiUnlocked = achievements.Where(dba => dba.AchievementId == 74987254626662)
- .SelectMany(x => AchievementSystem.AchievementManager.UnserializeBytes(x.Criteria))
- .Any(x => x == unchecked((uint)74987252674266));
-
- if (Level >= 70)
- GrantCriteria(74987254853541);
-
- HirelingTemplarUnlocked = achievements.Any(dba => dba.AchievementId == 74987243307073);
- HirelingScoundrelUnlocked = achievements.Any(dba => dba.AchievementId == 74987243307147);
- HirelingEnchantressUnlocked = achievements.Any(dba => dba.AchievementId == 74987243307145);
- SkillSet = new SkillSet(this, Toon.Class, Toon);
- GroundItems = new Dictionary();
- Followers = new Dictionary();
- Conversations = new ConversationManager(this);
- ExpBonusData = new ExpBonusData(this);
- SelectedNPC = null;
-
- _lastResourceUpdateTick = 0;
- SavePointData = new SavePointData() { snoWorld = -1, SavepointId = -1 };
-
- // Attributes
- if (World.Game.PvP)
- Attributes[GameAttribute.TeamID] = PlayerIndex + 2;
- else
- Attributes[GameAttribute.TeamID] = 2;
-
- //make sure if greater is not active enable banner.
- if (!World.Game.NephalemGreater)
- {
- Attributes[GameAttribute.Banner_Usable] = true;
- }
- SetAllStatsInCorrectOrder();
- // Enabled stone of recall
- if (!World.Game.PvP & Toon.StoneOfPortal)
- EnableStoneOfRecall();
- else if (InGameClient.Game.CurrentAct == 3000)
- EnableStoneOfRecall();
-
- List lores = UnserializeBytes(Toon.DBToon.Lore);
- int num = 0;
- foreach (int lore in lores)
- {
- LearnedLore.m_snoLoreLearned[num] = lore;
- num++;
- }
- LearnedLore.Count = lores.Count();
-
- Attributes[GameAttribute.Hitpoints_Cur] = Attributes[GameAttribute.Hitpoints_Max_Total];
- Attributes.BroadcastChangedIfRevealed();
- }
-
- #region Attribute Setters
- public void SetAllStatsInCorrectOrder()
- {
- SetAttributesSkills();
- SetAttributesBuffs();
- SetAttributesDamage();
- SetAttributesRessources();
- SetAttributesClassSpecific();
- SetAttributesMovement();
- SetAttributesMisc();
- SetAttributesOther();
- if (Inventory == null)
- Inventory = new Inventory(this);
- SetAttributesByItems();//needs the Inventory
- SetAttributesByItemProcs();
- SetAttributesByGems();
- SetAttributesByItemSets();
- if (SkillSet == null)
- SkillSet = new SkillSet(this, Toon.Class, Toon);
- SetAttributesByPassives();//needs the SkillSet
- SetAttributesByParagon();
- SetNewAttributes();
- UpdatePercentageHP(PercHPbeforeChange);
- }
-
- public void SetAttributesSkills()
- {
- //Skills
- Attributes[GameAttribute.SkillKit] = Toon.HeroTable.SNOSKillKit0;
-
- Attributes[GameAttribute.Buff_Icon_Start_Tick0, 0x00033C40] = 153;
- Attributes[GameAttribute.Buff_Icon_End_Tick0, 0x00033C40] = 3753;
- Attributes[GameAttribute.Buff_Icon_Count0, 0x0006B48E] = 1;
- Attributes[GameAttribute.Buff_Icon_Count0, 0x0004601B] = 1;
- Attributes[GameAttribute.Buff_Icon_Count0, 0x00033C40] = 1;
-
- Attributes[GameAttribute.Currencies_Discovered] = 0x0011FFF8;
-
- Attributes[GameAttribute.Skill, 30592] = 1;
- Attributes[GameAttribute.Resource_Degeneration_Prevented] = false;
- Attributes[GameAttribute.Resource_Degeneration_Stop_Point] = 0;
- //scripted //this.Attributes[GameAttribute.Skill_Total, 0x7545] = 1; //Axe Operate Gizmo
- //scripted //this.Attributes[GameAttribute.Skill_Total, 0x76B7] = 1; //Punch!
- //scripted //this.Attributes[GameAttribute.Skill_Total, 0x6DF] = 1; //Use Item
- //scripted //this.Attributes[GameAttribute.Skill_Total, 0x7780] = 1; //Basic Attack
- //scripted //this.Attributes[GameAttribute.Skill_Total, 0xFFFFF] = 1;
- //this.Attributes[GameAttribute.Skill, 0xFFFFF] = 1;
- }
-
- public void SetAttributesBuffs()
- {
- //Buffs
- Attributes[GameAttribute.Buff_Exclusive_Type_Active, 0x33C40] = true;
- Attributes[GameAttribute.Buff_Icon_End_Tick0, 0x00033C40] = 0x000003FB;
- Attributes[GameAttribute.Buff_Icon_Start_Tick0, 0x00033C40] = 0x00000077;
- Attributes[GameAttribute.Buff_Icon_Count0, 0x00033C40] = 1;
- Attributes[GameAttribute.Buff_Exclusive_Type_Active, 0xCE11] = true;
- Attributes[GameAttribute.Buff_Icon_Count0, 0x0000CE11] = 1;
- Attributes[GameAttribute.Buff_Visual_Effect, 0xFFFFF] = true;
- //Wings
- if (CurrentWingsPowerId != -1)
- {
- Attributes[GameAttribute.Buff_Exclusive_Type_Active, CurrentWingsPowerId] = true;
- Attributes[GameAttribute.Power_Buff_0_Visual_Effect_None, CurrentWingsPowerId] = true;
- Attributes[GameAttribute.Buff_Icon_Start_Tick0, CurrentWingsPowerId] = 0;
- Attributes[GameAttribute.Buff_Icon_End_Tick0, CurrentWingsPowerId] = 100;
- Attributes[GameAttribute.Buff_Icon_Count0, CurrentWingsPowerId] = 1;
- }
- }
-
- public void SetAttributesDamage()
- {
- Attributes[GameAttribute.Primary_Damage_Attribute] = (int)Toon.HeroTable.CoreAttribute + 1;
- Attributes[GameAttribute.Attacks_Per_Second_Percent_Cap] = 4f;
- }
-
- public void SetAttributesRessources()
- {
- Attributes[GameAttribute.Resource_Type_Primary] = (int)Toon.HeroTable.PrimaryResource + 1;
- Attributes[GameAttribute.Resource_Max, Attributes[GameAttribute.Resource_Type_Primary] - 1] = Toon.HeroTable.PrimaryResourceBase;
- Attributes[GameAttribute.Resource_Max_Bonus, Attributes[GameAttribute.Resource_Type_Primary] - 1] = 0;
- Attributes[GameAttribute.Resource_Factor_Level, Attributes[GameAttribute.Resource_Type_Primary] - 1] = Toon.HeroTable.PrimaryResourceFactorLevel;
- Attributes[GameAttribute.Resource_Percent, Attributes[GameAttribute.Resource_Type_Primary] - 1] = 0;
- Attributes[GameAttribute.Resource_Cur, (int)Attributes[GameAttribute.Resource_Type_Primary]] = GetMaxResource((int)Attributes[GameAttribute.Resource_Type_Primary] - 1);
-
-
- var max = Attributes[GameAttribute.Resource_Max, (int)Attributes[GameAttribute.Resource_Type_Primary] - 1];
- var cur = Attributes[GameAttribute.Resource_Cur, (int)Attributes[GameAttribute.Resource_Type_Primary] - 1];
-
-
- Attributes[GameAttribute.Resource_Regen_Per_Second, (int)Attributes[GameAttribute.Resource_Type_Primary] - 1] = Toon.HeroTable.PrimaryResourceRegen;
- Attributes[GameAttribute.Resource_Regen_Stop_Regen] = false;
- if (Toon.Class == ToonClass.Barbarian)
- Attributes[GameAttribute.Resource_Cur, (int)Toon.HeroTable.PrimaryResource + 1] = 0;
- else
- Attributes[GameAttribute.Resource_Cur, (int)Toon.HeroTable.PrimaryResource + 1] = (int)GetMaxResource((int)Toon.HeroTable.PrimaryResource + 1) * 100;
-
- if (Toon.HeroTable.SecondaryResource != GameBalance.HeroTable.Resource.None)
- {
- Attributes[GameAttribute.Resource_Type_Secondary] = (int)Toon.HeroTable.SecondaryResource + 1;
- Attributes[GameAttribute.Resource_Max, (int)Attributes[GameAttribute.Resource_Type_Secondary] - 1] = Toon.HeroTable.SecondaryResourceBase;
- Attributes[GameAttribute.Resource_Max_Bonus, Attributes[GameAttribute.Resource_Type_Secondary] - 1] = 0;
- Attributes[GameAttribute.Resource_Percent, Attributes[GameAttribute.Resource_Type_Secondary] - 1] = 0;
- Attributes[GameAttribute.Resource_Factor_Level, (int)Attributes[GameAttribute.Resource_Type_Secondary] - 1] = Toon.HeroTable.SecondaryResourceFactorLevel;
- Attributes[GameAttribute.Resource_Cur, (int)Attributes[GameAttribute.Resource_Type_Secondary] - 1] = GetMaxResource((int)Toon.HeroTable.SecondaryResource + 1);
- Attributes[GameAttribute.Resource_Regen_Per_Second, (int)Attributes[GameAttribute.Resource_Type_Secondary] - 1] = Toon.HeroTable.SecondaryResourceRegen;
- }
-
- Attributes[GameAttribute.Get_Hit_Recovery_Per_Level] = (int)Toon.HeroTable.GetHitRecoveryPerLevel;
- Attributes[GameAttribute.Get_Hit_Recovery_Base] = (int)Toon.HeroTable.GetHitRecoveryBase;
-
- Attributes[GameAttribute.Get_Hit_Max_Per_Level] = (int)Toon.HeroTable.GetHitMaxPerLevel;
- Attributes[GameAttribute.Get_Hit_Max_Base] = (int)Toon.HeroTable.GetHitMaxBase;
- }
-
- public void SetAttributesClassSpecific()
- {
- // Class specific
- switch (Toon.Class)
- {
- case ToonClass.Barbarian:
- //scripted //this.Attributes[GameAttribute.Skill_Total, 30078] = 1; //Fury Trait
- Attributes[GameAttribute.Skill, 30078] = 1;
- Attributes[GameAttribute.Trait, 30078] = 1;
- Attributes[GameAttribute.Buff_Exclusive_Type_Active, 30078] = true;
- Attributes[GameAttribute.Buff_Icon_Count0, 30078] = 1;
- break;
- case ToonClass.DemonHunter:
- break;
- case ToonClass.Crusader:
- Attributes[GameAttribute.Skill, 0x000418F2] = 1;
- Attributes[GameAttribute.Skill, 0x00045CCF] = 1;
- Attributes[GameAttribute.Skill, 0x000564D4] = 1;
-
- break;
- case ToonClass.Monk:
- //scripted //this.Attributes[GameAttribute.Skill_Total, 0x0000CE11] = 1; //Spirit Trait
- Attributes[GameAttribute.Skill, 0x0000CE11] = 1;
- Attributes[GameAttribute.Trait, 0x0000CE11] = 1;
- Attributes[GameAttribute.Buff_Exclusive_Type_Active, 0xCE11] = true;
- Attributes[GameAttribute.Buff_Icon_Count0, 0x0000CE11] = 1;
- break;
- case ToonClass.WitchDoctor:
- break;
- case ToonClass.Wizard:
- break;
- }
- }
-
- public void SetAttributesMovement()
- {
- Attributes[GameAttribute.Movement_Scalar_Cap] = 3f;
- Attributes[GameAttribute.Movement_Scalar] = 1f;
- Attributes[GameAttribute.Walking_Rate] = Toon.HeroTable.WalkingRate;
- Attributes[GameAttribute.Running_Rate] = Toon.HeroTable.RunningRate;
- Attributes[GameAttribute.Experience_Bonus] = 0f;
- Attributes[GameAttribute.Sprinting_Rate] = Toon.HeroTable.SprintRate * 2;
- Attributes[GameAttribute.Strafing_Rate] = Toon.HeroTable.SprintRate * 2;
- }
-
- public void SetAttributesMisc()
- {
- //Miscellaneous
- /*
- this.Attributes[GameAttribute.Disabled] = false; // we should be making use of these ones too /raist.
- this.Attributes[GameAttribute.Loading] = true;
- this.Attributes[GameAttribute.Loading_Player_ACD] = this.PlayerIndex;
- this.Attributes[GameAttribute.Invulnerable] = true;
- this.Attributes[GameAttribute.Hidden] = false;
- this.Attributes[GameAttribute.Immobolize] = true;
- this.Attributes[GameAttribute.Untargetable] = true;
- this.Attributes[GameAttribute.CantStartDisplayedPowers] = true;
- this.Attributes[GameAttribute.IsContentRestrictedActor] = true;
- this.Attributes[GameAttribute.Cannot_Dodge] = false;
- this.Attributes[GameAttribute.Trait, 0x0000CE11] = 1;
- this.Attributes[GameAttribute.Backpack_Slots] = 60;
- this.Attributes[GameAttribute.General_Cooldown] = 0;
- //*/
- Attributes[GameAttribute.Disabled] = true; // we should be making use of these ones too /raist.
- Attributes[GameAttribute.Loading] = true;
- Attributes[GameAttribute.Loading_Player_ACD] = PlayerIndex;
- Attributes[GameAttribute.Invulnerable] = true;
- Attributes[GameAttribute.Hidden] = false;
- Attributes[GameAttribute.Immobolize] = true;
- Attributes[GameAttribute.Untargetable] = true;
- Attributes[GameAttribute.CantStartDisplayedPowers] = true;
- Attributes[GameAttribute.IsContentRestrictedActor] = true;
- Attributes[GameAttribute.Cannot_Dodge] = false;
- Attributes[GameAttribute.Trait, 0x0000CE11] = 1;
- Attributes[GameAttribute.TeamID] = 2;
- Attributes[GameAttribute.Stash_Tabs_Purchased_With_Gold] = 5; // what do these do?
- Attributes[GameAttribute.Stash_Tabs_Rewarded_By_Achievements] = 5;
- Attributes[GameAttribute.Backpack_Slots] = 60;
- Attributes[GameAttribute.General_Cooldown] = 0;
- }
-
- public void SetAttributesByParagon()
- {
- // Until the Paragon 800 should be distributed on the 4 tabs,
- // after that only in the first Core tab.
- var baseParagonPoints = Math.Min(Toon.ParagonLevel, 800);
- var extraParagonPoints = Math.Max(0, Toon.ParagonLevel - 800);
- for (int i = 0; i < 4; i++)
- {
- Attributes[GameAttribute.Paragon_Bonus_Points_Available, i] = baseParagonPoints / 4;
- // Process remainder only for base points.
- if (i < baseParagonPoints % 4)
- {
- Attributes[GameAttribute.Paragon_Bonus_Points_Available, i]++;
- }
- }
- // First tab of Paragon (Core) - pos 0.
- Attributes[GameAttribute.Paragon_Bonus_Points_Available, 0] += extraParagonPoints;
-
- var assigned_bonuses = ParagonBonuses;
-
- var bonus_ids = ItemGenerator.GetParagonBonusTable(Toon.Class);
-
- foreach (var bonus in bonus_ids)
- {
- int slot_index = (bonus.Category * 4) + bonus.Index - 1;
-
- Attributes[GameAttribute.Paragon_Bonus_Points_Available, bonus.Category] -= assigned_bonuses[slot_index];
-
- Attributes[GameAttribute.Paragon_Bonus, bonus.Hash] = assigned_bonuses[slot_index];
-
- float result;
- if (FormulaScript.Evaluate(bonus.AttributeSpecifiers[0].Formula.ToArray(), new ItemRandomHelper(0), out result))
- {
- if (bonus.AttributeSpecifiers[0].AttributeId == 104) //Resistance_All
- {
- foreach (var damageType in DamageType.AllTypes)
- {
- Attributes[GameAttribute.Resistance, damageType.AttributeKey] += (result * assigned_bonuses[slot_index]);
- }
- }
- else
- {
- if (bonus.AttributeSpecifiers[0].AttributeId == 133) result = 33f; //Hitpoints_Regen_Per_Second
-
- if (bonus.AttributeSpecifiers[0].AttributeId == 342) result = 16.5f; //Hitpoints_On_Hit
-
- if (GameAttribute.Attributes[bonus.AttributeSpecifiers[0].AttributeId] is GameAttributeF)
- {
- var attr = GameAttribute.Attributes[bonus.AttributeSpecifiers[0].AttributeId] as GameAttributeF;
- if (bonus.AttributeSpecifiers[0].SNOParam != -1)
- Attributes[attr, bonus.AttributeSpecifiers[0].SNOParam] += (result * assigned_bonuses[slot_index]);
- else
- Attributes[attr] += (result * assigned_bonuses[slot_index]);
- }
- else if (GameAttribute.Attributes[bonus.AttributeSpecifiers[0].AttributeId] is GameAttributeI)
- {
-
- var attr = GameAttribute.Attributes[bonus.AttributeSpecifiers[0].AttributeId] as GameAttributeI;
- if (bonus.AttributeSpecifiers[0].SNOParam != -1)
- Attributes[attr, bonus.AttributeSpecifiers[0].SNOParam] += (int)(result * assigned_bonuses[slot_index]);
- else
- Attributes[attr] += (int)(result * assigned_bonuses[slot_index]);
- }
- }
- }
- //Logger.Debug("Paragon attribute {0} - value {1}", bonus.Attribute[0].AttributeId, (result * assigned_bonuses[slot_index]));
- }
- }
- public float PercHPbeforeChange = 0;
- public void SetAttributesByItems()
- {
- const float nonPhysDefault = 0f; //was 3.051758E-05f
- var MaxHPOld = Attributes[GameAttribute.Hitpoints_Max_Total];
- var PercentOfOld = Attributes[GameAttribute.Hitpoints_Max_Total] / 100;
- PercHPbeforeChange = Attributes[GameAttribute.Hitpoints_Cur] / (Attributes[GameAttribute.Hitpoints_Max_Total] / 100);
- ;
-
- var damageAttributeMinValues = new Dictionary
- {
- {DamageType.Physical, new[] {2f, 2f}},
- {DamageType.Arcane, new[] {nonPhysDefault, nonPhysDefault}},
- {DamageType.Cold, new[] {nonPhysDefault, nonPhysDefault}},
- {DamageType.Fire, new[] {nonPhysDefault, nonPhysDefault}},
- {DamageType.Holy, new[] {nonPhysDefault, nonPhysDefault}},
- {DamageType.Lightning, new[] {nonPhysDefault, nonPhysDefault}},
- {DamageType.Poison, new[] {nonPhysDefault, nonPhysDefault}}
- };
-
-
- foreach (var damageType in DamageType.AllTypes)
- {
- //var weaponDamageMin = damageType.AttributeKey == 0 ? this.Inventory.GetItemBonus(GameAttribute.Damage_Weapon_Min, 0) : (this.Inventory.GetItemBonus(GameAttribute.Damage_Weapon_Min, 0) + Math.Max(this.Inventory.GetItemBonus(GameAttribute.Damage_Weapon_Min, damageType.AttributeKey), damageAttributeMinValues[damageType][0]));
- //var weaponDamageDelta = damageType.AttributeKey == 0 ? this.Inventory.GetItemBonus(GameAttribute.Damage_Weapon_Min, 0) : (this.Inventory.GetItemBonus(GameAttribute.Damage_Weapon_Delta, 0) + Math.Max(this.Inventory.GetItemBonus(GameAttribute.Damage_Weapon_Delta, damageType.AttributeKey), damageAttributeMinValues[damageType][1]));
-
- Attributes[GameAttribute.Damage_Weapon_Min, damageType.AttributeKey] = Math.Max(Inventory.GetItemBonus(GameAttribute.Damage_Weapon_Min_Total, damageType.AttributeKey), damageAttributeMinValues[damageType][0]) + Inventory.GetItemBonus(GameAttribute.Damage_Min, damageType.AttributeKey);
- Attributes[GameAttribute.Damage_Weapon_Min, damageType.AttributeKey] -= Inventory.AdjustDualWieldMin(damageType); //Damage on weapons should not add when dual-wielding
- Attributes[GameAttribute.Damage_Weapon_Delta, damageType.AttributeKey] = Math.Max(Inventory.GetItemBonus(GameAttribute.Damage_Weapon_Delta_Total, damageType.AttributeKey), damageAttributeMinValues[damageType][1]) + Inventory.GetItemBonus(GameAttribute.Damage_Delta, damageType.AttributeKey);
- Attributes[GameAttribute.Damage_Weapon_Delta, damageType.AttributeKey] -= Inventory.AdjustDualWieldDelta(damageType); //Damage on weapons should not add when dual-wielding
-
- Attributes[GameAttribute.Damage_Weapon_Bonus_Min, damageType.AttributeKey] = 0f;
- Attributes[GameAttribute.Damage_Weapon_Bonus_Min_X1, damageType.AttributeKey] = 0f;
- Attributes[GameAttribute.Damage_Weapon_Bonus_Delta, damageType.AttributeKey] = 0f;
- Attributes[GameAttribute.Damage_Weapon_Bonus_Delta_X1, damageType.AttributeKey] = 0f;
- Attributes[GameAttribute.Damage_Weapon_Bonus_Flat, damageType.AttributeKey] = 0f;
-
- Attributes[GameAttribute.Damage_Type_Percent_Bonus, damageType.AttributeKey] = Inventory.GetItemBonus(GameAttribute.Damage_Type_Percent_Bonus, damageType.AttributeKey);
- Attributes[GameAttribute.Damage_Dealt_Percent_Bonus, damageType.AttributeKey] = Inventory.GetItemBonus(GameAttribute.Damage_Dealt_Percent_Bonus, damageType.AttributeKey);
-
- Attributes[GameAttribute.Resistance, damageType.AttributeKey] = Inventory.GetItemBonus(GameAttribute.Resistance, damageType.AttributeKey);
- Attributes[GameAttribute.Damage_Percent_Reduction_From_Type, damageType.AttributeKey] = Inventory.GetItemBonus(GameAttribute.Damage_Percent_Reduction_From_Type, damageType.AttributeKey);
- Attributes[GameAttribute.Amplify_Damage_Type_Percent, damageType.AttributeKey] = Inventory.GetItemBonus(GameAttribute.Amplify_Damage_Type_Percent, damageType.AttributeKey);
- }
-
- for (int i = 0; i < 4; i++)
- Attributes[GameAttribute.Damage_Percent_Bonus_Vs_Monster_Type, i] = Inventory.GetItemBonus(GameAttribute.Damage_Percent_Bonus_Vs_Monster_Type, i);
-
-
- Attributes[GameAttribute.Resistance_All] = Inventory.GetItemBonus(GameAttribute.Resistance_All);
- Attributes[GameAttribute.Resistance_Percent_All] = Inventory.GetItemBonus(GameAttribute.Resistance_Percent_All);
- Attributes[GameAttribute.Damage_Percent_Reduction_From_Melee] = Inventory.GetItemBonus(GameAttribute.Damage_Percent_Reduction_From_Melee);
- Attributes[GameAttribute.Damage_Percent_Reduction_From_Ranged] = Inventory.GetItemBonus(GameAttribute.Damage_Percent_Reduction_From_Ranged);
-
- Attributes[GameAttribute.Thorns_Fixed, 0] = Inventory.GetItemBonus(GameAttribute.Thorns_Fixed, 0);
-
- //this.Attributes[GameAttribute.Armor_Item_Percent] = this.Inventory.GetItemBonus(GameAttribute.Armor_Item_Percent);
- float allStatsBonus = Inventory.GetItemBonus(GameAttribute.Stats_All_Bonus);// / 1065353216;
- /*
- this.Attributes[GameAttribute.Armor_Item] = this.Inventory.GetItemBonus(GameAttribute.Armor_Item_Total);
- this.Attributes[GameAttribute.Strength_Item] = this.Inventory.GetItemBonus(GameAttribute.Dexterity_Item);// / 1065353216;
- this.Attributes[GameAttribute.Strength_Item] += allStatsBonus;
- this.Attributes[GameAttribute.Dexterity_Item] = this.Inventory.GetItemBonus(GameAttribute.Intelligence_Item);// / 1065353216;
- this.Attributes[GameAttribute.Dexterity_Item] += allStatsBonus;
- this.Attributes[GameAttribute.Intelligence_Item] = this.Inventory.GetItemBonus(GameAttribute.Vitality_Item);// / 1065353216; //I know that's wild, but client can't display it properly...
- this.Attributes[GameAttribute.Intelligence_Item] += allStatsBonus;
- this.Attributes[GameAttribute.Vitality_Item] = this.Inventory.GetItemBonus(GameAttribute.Item_Level_Requirement_Reduction);// / 1065353216;
- this.Attributes[GameAttribute.Vitality_Item] += allStatsBonus;
- //*/
- //*
- Attributes[GameAttribute.Strength_Item] = Inventory.GetItemBonus(GameAttribute.Strength_Item);// / 1065353216;
- Attributes[GameAttribute.Strength_Item] += allStatsBonus;
- Attributes[GameAttribute.Vitality_Item] = Inventory.GetItemBonus(GameAttribute.Vitality_Item);// / 1065353216;
- Attributes[GameAttribute.Vitality_Item] += allStatsBonus;
- Attributes[GameAttribute.Dexterity_Item] = Inventory.GetItemBonus(GameAttribute.Dexterity_Item);// / 1065353216;
- Attributes[GameAttribute.Dexterity_Item] += allStatsBonus;
- Attributes[GameAttribute.Intelligence_Item] = Inventory.GetItemBonus(GameAttribute.Intelligence_Item);// / 1065353216; //I know that's wild, but client can't display it properly...
- Attributes[GameAttribute.Intelligence_Item] += allStatsBonus;
- //*/
-
- //this.Attributes[GameAttribute.Cube_Enchanted_Strength_Item] = 0;
- Attributes[GameAttribute.Core_Attributes_From_Item_Bonus_Multiplier] = 1;
-
-
- Attributes[GameAttribute.Hitpoints_Max_Percent_Bonus] = Inventory.GetItemBonus(GameAttribute.Hitpoints_Max_Percent_Bonus);
- Attributes[GameAttribute.Hitpoints_Max_Percent_Bonus_Item] = Inventory.GetItemBonus(GameAttribute.Hitpoints_Max_Percent_Bonus_Item);
- Attributes[GameAttribute.Hitpoints_Max_Bonus] = Inventory.GetItemBonus(GameAttribute.Hitpoints_Max_Bonus);
-
-
-
- Attributes[GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.PrimaryResource] = Inventory.GetItemBonus(GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.PrimaryResource);
-
- Attributes[GameAttribute.Attacks_Per_Second] = Inventory.GetAPS();
-
- Attributes[GameAttribute.Attacks_Per_Second_Percent] = Inventory.GetItemBonus(GameAttribute.Attacks_Per_Second_Item_Percent) + Inventory.GetItemBonus(GameAttribute.Attacks_Per_Second_Percent);
- Attributes[GameAttribute.Attacks_Per_Second_Bonus] = Inventory.GetItemBonus(GameAttribute.Attacks_Per_Second_Item_Bonus);
- Attributes[GameAttribute.Attacks_Per_Second_Item] = Inventory.GetItemBonus(GameAttribute.Attacks_Per_Second_Item);
- var a = Attributes[GameAttribute.Attacks_Per_Second];
- var b = Attributes[GameAttribute.Attacks_Per_Second_Percent];
- var c = Attributes[GameAttribute.Attacks_Per_Second_Bonus];
- var d = Attributes[GameAttribute.Attacks_Per_Second_Item];
- var e = Attributes[GameAttribute.Attacks_Per_Second_Item_CurrentHand];
- var f = Attributes[GameAttribute.Attacks_Per_Second_Item_Bonus];
- var g = Attributes[GameAttribute.Attacks_Per_Second_Percent_Subtotal];
- var h = Attributes[GameAttribute.Attacks_Per_Second_Percent_Cap];
- var j = Attributes[GameAttribute.Attacks_Per_Second_Percent_Uncapped];
- var k = Attributes[GameAttribute.Attacks_Per_Second_Percent_Reduction];
- var o = Attributes[GameAttribute.Attacks_Per_Second_Total];
-
- if (Attributes[GameAttribute.Attacks_Per_Second_Total] < 1)
- Attributes[GameAttribute.Attacks_Per_Second] = 1.0f;
- Attributes[GameAttribute.Crit_Percent_Bonus_Capped] = Inventory.GetItemBonus(GameAttribute.Crit_Percent_Bonus_Capped);
- Attributes[GameAttribute.Weapon_Crit_Chance] = 0.05f + Inventory.GetItemBonus(GameAttribute.Weapon_Crit_Chance);
- Attributes[GameAttribute.Crit_Damage_Percent] = 0.5f + Inventory.GetItemBonus(GameAttribute.Crit_Damage_Percent);
-
- Attributes[GameAttribute.Splash_Damage_Effect_Percent] = Inventory.GetItemBonus(GameAttribute.Splash_Damage_Effect_Percent);
-
- Attributes[GameAttribute.On_Hit_Fear_Proc_Chance] = Inventory.GetItemBonus(GameAttribute.On_Hit_Fear_Proc_Chance) + Inventory.GetItemBonus(GameAttribute.Weapon_On_Hit_Fear_Proc_Chance);
- Attributes[GameAttribute.On_Hit_Stun_Proc_Chance] = Inventory.GetItemBonus(GameAttribute.On_Hit_Stun_Proc_Chance) + Inventory.GetItemBonus(GameAttribute.Weapon_On_Hit_Stun_Proc_Chance);
- Attributes[GameAttribute.On_Hit_Blind_Proc_Chance] = Inventory.GetItemBonus(GameAttribute.On_Hit_Blind_Proc_Chance) + Inventory.GetItemBonus(GameAttribute.Weapon_On_Hit_Blind_Proc_Chance);
- Attributes[GameAttribute.On_Hit_Freeze_Proc_Chance] = Inventory.GetItemBonus(GameAttribute.On_Hit_Freeze_Proc_Chance) + Inventory.GetItemBonus(GameAttribute.Weapon_On_Hit_Freeze_Proc_Chance);
- Attributes[GameAttribute.On_Hit_Chill_Proc_Chance] = Inventory.GetItemBonus(GameAttribute.On_Hit_Chill_Proc_Chance) + Inventory.GetItemBonus(GameAttribute.Weapon_On_Hit_Chill_Proc_Chance);
- Attributes[GameAttribute.On_Hit_Slow_Proc_Chance] = Inventory.GetItemBonus(GameAttribute.On_Hit_Slow_Proc_Chance) + Inventory.GetItemBonus(GameAttribute.Weapon_On_Hit_Slow_Proc_Chance);
- Attributes[GameAttribute.On_Hit_Immobilize_Proc_Chance] = Inventory.GetItemBonus(GameAttribute.On_Hit_Immobilize_Proc_Chance) + Inventory.GetItemBonus(GameAttribute.Weapon_On_Hit_Immobilize_Proc_Chance);
- Attributes[GameAttribute.On_Hit_Knockback_Proc_Chance] = Inventory.GetItemBonus(GameAttribute.On_Hit_Knockback_Proc_Chance) + Inventory.GetItemBonus(GameAttribute.Weapon_On_Hit_Knockback_Proc_Chance);
- Attributes[GameAttribute.On_Hit_Bleed_Proc_Chance] = Inventory.GetItemBonus(GameAttribute.On_Hit_Bleed_Proc_Chance) + Inventory.GetItemBonus(GameAttribute.Weapon_On_Hit_Bleed_Proc_Chance);
-
- Attributes[GameAttribute.Running_Rate] = Toon.HeroTable.RunningRate + Inventory.GetItemBonus(GameAttribute.Running_Rate);
- Attributes[GameAttribute.Movement_Scalar_Uncapped_Bonus] = Inventory.GetItemBonus(GameAttribute.Movement_Scalar_Uncapped_Bonus);
- Attributes[GameAttribute.Movement_Scalar] = Inventory.GetItemBonus(GameAttribute.Movement_Scalar) + 1.0f;
-
- //this.Attributes[GameAttribute.Magic_Find] = this.Inventory.GetItemBonus(GameAttribute.Magic_Find);
- Attributes[GameAttribute.Magic_Find] = Inventory.GetMagicFind();
- //this.Attributes[GameAttribute.Gold_Find] = this.Inventory.GetItemBonus(GameAttribute.Gold_Find);
- Attributes[GameAttribute.Gold_Find] = Inventory.GetGoldFind();
-
- Attributes[GameAttribute.Gold_PickUp_Radius] = (5f + Inventory.GetItemBonus(GameAttribute.Gold_PickUp_Radius));
-
- Attributes[GameAttribute.Experience_Bonus] = Inventory.GetItemBonus(GameAttribute.Experience_Bonus);
- Attributes[GameAttribute.Experience_Bonus_Percent] = Inventory.GetItemBonus(GameAttribute.Experience_Bonus_Percent);
-
- Attributes[GameAttribute.Resistance_Freeze] = Inventory.GetItemBonus(GameAttribute.Resistance_Freeze);
- Attributes[GameAttribute.Resistance_Penetration] = Inventory.GetItemBonus(GameAttribute.Resistance_Penetration);
- Attributes[GameAttribute.Resistance_Percent] = Inventory.GetItemBonus(GameAttribute.Resistance_Percent);
- Attributes[GameAttribute.Resistance_Root] = Inventory.GetItemBonus(GameAttribute.Resistance_Root);
- Attributes[GameAttribute.Resistance_Stun] = Inventory.GetItemBonus(GameAttribute.Resistance_Stun);
- Attributes[GameAttribute.Resistance_StunRootFreeze] = Inventory.GetItemBonus(GameAttribute.Resistance_StunRootFreeze);
-
- Attributes[GameAttribute.Dodge_Chance_Bonus] = Inventory.GetItemBonus(GameAttribute.Dodge_Chance_Bonus);
-
- Attributes[GameAttribute.Block_Amount_Item_Min] = Inventory.GetItemBonus(GameAttribute.Block_Amount_Item_Min);
- Attributes[GameAttribute.Block_Amount_Item_Delta] = Inventory.GetItemBonus(GameAttribute.Block_Amount_Item_Delta);
- Attributes[GameAttribute.Block_Amount_Bonus_Percent] = Inventory.GetItemBonus(GameAttribute.Block_Amount_Bonus_Percent);
- Attributes[GameAttribute.Block_Chance] = Inventory.GetItemBonus(GameAttribute.Block_Chance_Item_Total);
-
- Attributes[GameAttribute.Power_Cooldown_Reduction_Percent] = 0;
- Attributes[GameAttribute.Health_Globe_Bonus_Health] = Inventory.GetItemBonus(GameAttribute.Health_Globe_Bonus_Health);
-
- Attributes[GameAttribute.Hitpoints_Regen_Per_Second] = Inventory.GetItemBonus(GameAttribute.Hitpoints_Regen_Per_Second) + Toon.HeroTable.GetHitRecoveryBase + (Toon.HeroTable.GetHitRecoveryPerLevel * Level);
-
- Attributes[GameAttribute.Resource_Cost_Reduction_Percent_All] = Inventory.GetItemBonus(GameAttribute.Resource_Cost_Reduction_Percent_All);
- Attributes[GameAttribute.Resource_Cost_Reduction_Percent, (int)Toon.HeroTable.PrimaryResource] = Inventory.GetItemBonus(GameAttribute.Resource_Cost_Reduction_Percent, (int)Toon.HeroTable.PrimaryResource);
- Attributes[GameAttribute.Resource_Regen_Per_Second, (int)Toon.HeroTable.PrimaryResource] = Toon.HeroTable.PrimaryResourceRegen + Inventory.GetItemBonus(GameAttribute.Resource_Regen_Per_Second, (int)Toon.HeroTable.PrimaryResource);
- Attributes[GameAttribute.Resource_Regen_Bonus_Percent, (int)Toon.HeroTable.PrimaryResource] = Inventory.GetItemBonus(GameAttribute.Resource_Regen_Bonus_Percent, (int)Toon.HeroTable.PrimaryResource);
-
- Attributes[GameAttribute.Resource_Cost_Reduction_Percent, (int)Toon.HeroTable.SecondaryResource] = Inventory.GetItemBonus(GameAttribute.Resource_Cost_Reduction_Percent, (int)Toon.HeroTable.SecondaryResource);
- Attributes[GameAttribute.Resource_Regen_Per_Second, (int)Toon.HeroTable.SecondaryResource] = Toon.HeroTable.SecondaryResourceRegen + Inventory.GetItemBonus(GameAttribute.Resource_Regen_Per_Second, (int)Toon.HeroTable.SecondaryResource);
- Attributes[GameAttribute.Resource_Regen_Bonus_Percent, (int)Toon.HeroTable.SecondaryResource] = Inventory.GetItemBonus(GameAttribute.Resource_Regen_Bonus_Percent, (int)Toon.HeroTable.SecondaryResource);
-
- Attributes[GameAttribute.Resource_On_Hit] = 0;
- Attributes[GameAttribute.Resource_On_Hit, 0] = Inventory.GetItemBonus(GameAttribute.Resource_On_Hit, 0);
- Attributes[GameAttribute.Resource_On_Crit, 1] = Inventory.GetItemBonus(GameAttribute.Resource_On_Crit, 1);
-
- Attributes[GameAttribute.Steal_Health_Percent] = Inventory.GetItemBonus(GameAttribute.Steal_Health_Percent) * 0.1f;
- Attributes[GameAttribute.Hitpoints_On_Hit] = Inventory.GetItemBonus(GameAttribute.Hitpoints_On_Hit);
- Attributes[GameAttribute.Hitpoints_On_Kill] = Inventory.GetItemBonus(GameAttribute.Hitpoints_On_Kill);
- Attributes[GameAttribute.Damage_Weapon_Percent_Bonus] = Inventory.GetItemBonus(GameAttribute.Damage_Weapon_Percent_Bonus);
- Attributes[GameAttribute.Damage_Percent_Bonus_Vs_Elites] = Inventory.GetItemBonus(GameAttribute.Damage_Percent_Bonus_Vs_Elites);
- //this.Attributes[GameAttribute.Power_Cooldown_Reduction_Percent_All_Capped] = 0.5f;
- //this.Attributes[GameAttribute.Power_Cooldown_Reduction_Percent_Cap] = 0.5f;
- Attributes[GameAttribute.Power_Cooldown_Reduction_Percent] = 0.5f;
- Attributes[GameAttribute.Power_Cooldown_Reduction_Percent_All] = Inventory.GetItemBonus(GameAttribute.Power_Cooldown_Reduction_Percent_All);
- Attributes[GameAttribute.Crit_Percent_Bonus_Uncapped] = Inventory.GetItemBonus(GameAttribute.Crit_Percent_Bonus_Uncapped);
-
- //this.Attributes[GameAttribute.Projectile_Speed] = 0.3f;
-
- switch (Toon.Class)
- {
- case ToonClass.Barbarian:
- Attributes[GameAttribute.Power_Resource_Reduction, 80028] = Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 80028);
- Attributes[GameAttribute.Power_Resource_Reduction, 70472] = Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 70472);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 79242] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 79242);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 80263] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 80263);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 78548] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 78548);
- Attributes[GameAttribute.Power_Resource_Reduction, 93885] = Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 93885);
- Attributes[GameAttribute.Power_Crit_Percent_Bonus, 86989] = Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 86989);
- Attributes[GameAttribute.Power_Crit_Percent_Bonus, 96296] = Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 96296);
- Attributes[GameAttribute.Power_Crit_Percent_Bonus, 109342] = Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 109342);
- Attributes[GameAttribute.Power_Crit_Percent_Bonus, 159169] = Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 159169);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 93885] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 93885);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 69979] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 69979);
- break;
- case ToonClass.DemonHunter:
- Attributes[GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.SecondaryResource] = Inventory.GetItemBonus(GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.SecondaryResource);
- Attributes[GameAttribute.Bow] = Inventory.GetItemBonus(GameAttribute.Bow);
- Attributes[GameAttribute.Crossbow] = Inventory.GetItemBonus(GameAttribute.Crossbow);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 129215] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 129215);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 134209] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 134209);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 77552] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 77552);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 75873] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 75873);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 86610] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 86610);
- Attributes[GameAttribute.Power_Crit_Percent_Bonus, 131192] = Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 131192);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 131325] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 131325);
- Attributes[GameAttribute.Power_Crit_Percent_Bonus, 77649] = Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 77649);
- Attributes[GameAttribute.Power_Crit_Percent_Bonus, 134030] = Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 134030);
- Attributes[GameAttribute.Power_Resource_Reduction, 129214] = Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 129214);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 75301] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 75301);
- Attributes[GameAttribute.Power_Resource_Reduction, 131366] = Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 131366);
- Attributes[GameAttribute.Power_Resource_Reduction, 129213] = Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 129213);
- break;
- case ToonClass.Monk:
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 95940] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 95940);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 96019] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 96019);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 96311] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 96311);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 97328] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 97328);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 96090] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 96090);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 97110] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 97110);
- Attributes[GameAttribute.Power_Crit_Percent_Bonus, 121442] = Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 121442);
- Attributes[GameAttribute.Power_Resource_Reduction, 111676] = Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 111676);
- Attributes[GameAttribute.Power_Resource_Reduction, 223473] = Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 223473);
- Attributes[GameAttribute.Power_Crit_Percent_Bonus, 96033] = Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 96033);
- break;
- case ToonClass.WitchDoctor:
- Attributes[GameAttribute.Power_Resource_Reduction, 105963] = Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 105963);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 103181] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 103181);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 106465] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 106465);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 83602] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 83602);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 108506] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 108506);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 69866] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 69866);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 69867] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 69867);
- Attributes[GameAttribute.Power_Resource_Reduction, 74003] = Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 74003);
- Attributes[GameAttribute.Power_Crit_Percent_Bonus, 70455] = Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 103181);
- Attributes[GameAttribute.Power_Resource_Reduction, 67567] = Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 67567);
- Attributes[GameAttribute.Power_Cooldown_Reduction, 134837] = Inventory.GetItemBonus(GameAttribute.Power_Cooldown_Reduction, 134837);
- Attributes[GameAttribute.Power_Cooldown_Reduction, 67600] = Inventory.GetItemBonus(GameAttribute.Power_Cooldown_Reduction, 67600);
- Attributes[GameAttribute.Power_Cooldown_Reduction, 102573] = Inventory.GetItemBonus(GameAttribute.Power_Cooldown_Reduction, 102573);
- Attributes[GameAttribute.Power_Cooldown_Reduction, 30624] = Inventory.GetItemBonus(GameAttribute.Power_Cooldown_Reduction, 30624);
- break;
- case ToonClass.Wizard:
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 30744] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 30744);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 30783] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 30783);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 71548] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 71548);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 1765] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 1765);
- Attributes[GameAttribute.Power_Crit_Percent_Bonus, 30668] = Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 30668);
- Attributes[GameAttribute.Power_Crit_Percent_Bonus, 77113] = Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 77113);
- Attributes[GameAttribute.Power_Resource_Reduction, 91549] = Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 91549);
- Attributes[GameAttribute.Power_Crit_Percent_Bonus, 87525] = Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 87525);
- Attributes[GameAttribute.Power_Crit_Percent_Bonus, 93395] = Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 93395);
- Attributes[GameAttribute.Power_Resource_Reduction, 134456] = Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 134456);
- Attributes[GameAttribute.Power_Resource_Reduction, 30725] = Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 30725);
- Attributes[GameAttribute.Power_Duration_Increase, 30680] = Inventory.GetItemBonus(GameAttribute.Power_Duration_Increase, 30680);
- Attributes[GameAttribute.Power_Resource_Reduction, 69190] = Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 69190);
- Attributes[GameAttribute.Power_Cooldown_Reduction, 168344] = Inventory.GetItemBonus(GameAttribute.Power_Cooldown_Reduction, 168344);
- Attributes[GameAttribute.Power_Damage_Percent_Bonus, 71548] = Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 71548);
- break;
- }
-
- }
-
- public void UpdatePercentageHP(float percent)
- {
- var m = Attributes[GameAttribute.Hitpoints_Max_Total];
- Attributes[GameAttribute.Hitpoints_Cur] = percent * Attributes[GameAttribute.Hitpoints_Max_Total] / 100;
- Attributes.BroadcastChangedIfRevealed();
- }
- public void UpdatePercentageHP()
- {
- }
-
- public void SetAttributesByGems()
- {
- Inventory.SetGemBonuses();
- }
-
- public void SetAttributesByItemProcs()
- {
- Attributes[GameAttribute.Item_Power_Passive, 248776] = Inventory.GetItemBonus(GameAttribute.Item_Power_Passive, 248776); //cluck
- Attributes[GameAttribute.Item_Power_Passive, 248629] = Inventory.GetItemBonus(GameAttribute.Item_Power_Passive, 248629); //death laugh
- Attributes[GameAttribute.Item_Power_Passive, 247640] = Inventory.GetItemBonus(GameAttribute.Item_Power_Passive, 247640); //gore1
- Attributes[GameAttribute.Item_Power_Passive, 249963] = Inventory.GetItemBonus(GameAttribute.Item_Power_Passive, 249963); //gore2
- Attributes[GameAttribute.Item_Power_Passive, 249954] = Inventory.GetItemBonus(GameAttribute.Item_Power_Passive, 249954); //gore3
- Attributes[GameAttribute.Item_Power_Passive, 246116] = Inventory.GetItemBonus(GameAttribute.Item_Power_Passive, 246116); //butcher
- Attributes[GameAttribute.Item_Power_Passive, 247724] = Inventory.GetItemBonus(GameAttribute.Item_Power_Passive, 247724); //plum!
- Attributes[GameAttribute.Item_Power_Passive, 245741] = Inventory.GetItemBonus(GameAttribute.Item_Power_Passive, 245741); //weee!
- }
-
- public void SetAttributesByItemSets()
- {
- Attributes[GameAttribute.Strength] = Strength;
- Attributes[GameAttribute.Dexterity] = Dexterity;
- Attributes[GameAttribute.Vitality] = Vitality;
- Attributes[GameAttribute.Intelligence] = Intelligence;
- Attributes.BroadcastChangedIfRevealed();
-
- Inventory.SetItemSetBonuses();
- }
-
- public void SetAttributesByPassives() //also reapplies synergy buffs
- {
- // Class specific
- Attributes[GameAttribute.Damage_Percent_All_From_Skills] = 0;
- Attributes[GameAttribute.Allow_2H_And_Shield] = false;
- Attributes[GameAttribute.Cannot_Dodge] = false;
-
- foreach (int passiveId in SkillSet.PassiveSkills)
- switch (Toon.Class)
- {
- case ToonClass.Barbarian:
- switch (passiveId)
- {
- case 217819: //NervesOfSteel
- Attributes[GameAttribute.Armor_Item] += Attributes[GameAttribute.Vitality_Total] * 0.50f;
- break;
- case 205228: //Animosity
- Attributes[GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.PrimaryResource] += 20;
- Attributes[GameAttribute.Resource_Regen_Per_Second, (int)Toon.HeroTable.PrimaryResource] = Attributes[GameAttribute.Resource_Regen_Per_Second, (int)Toon.HeroTable.PrimaryResource] * 1.1f;
- Attributes[GameAttribute.Resource_Cur, (int)Toon.HeroTable.PrimaryResource] = Toon.HeroTable.PrimaryResourceBase + Attributes[GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.PrimaryResource];
- break;
- case 205848: //ToughAsNails
- Attributes[GameAttribute.Armor_Item] *= 1.25f;
- break;
- case 205707: //Juggernaut
- Attributes[GameAttribute.CrowdControl_Reduction] += 0.3f;
- break;
- case 206147: //WeaponsMaster
- var weapon = Inventory.GetEquippedWeapon();
- if (weapon != null)
- {
- string name = weapon.ItemDefinition.Name.ToLower();
- if (name.Contains("sword") || name.Contains("dagger"))
- Attributes[GameAttribute.Damage_Weapon_Percent_Bonus] += 0.08f;
- else
- if (name.Contains("axe") || name.Contains("mace"))
- Attributes[GameAttribute.Weapon_Crit_Chance] += 0.05f;
- else
- if (name.Contains("spear") || name.Contains("polearm"))
- Attributes[GameAttribute.Attacks_Per_Second] *= 1.08f;
- else
- if (name.Contains("mighty"))
- Attributes[GameAttribute.Resource_On_Hit] += 1f;
- }
- break;
- }
- break;
- case ToonClass.DemonHunter:
- switch (passiveId)
- {
- case 155714: //Blood Vengeance
- Attributes[GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.PrimaryResource] += 25;
- Attributes[GameAttribute.Resource_Cur, (int)Toon.HeroTable.PrimaryResource] = Toon.HeroTable.PrimaryResourceBase + Attributes[GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.PrimaryResource];
- break;
- case 210801: //Brooding
- Attributes[GameAttribute.Hitpoints_Regen_Per_Second] += (Attributes[GameAttribute.Hitpoints_Max_Total]) / 100;
- break;
- case 155715: //Sharpshooter
- World.BuffManager.RemoveBuffs(this, 155715);
- World.BuffManager.AddBuff(this, this, new SharpshooterBuff());
- break;
- case 324770: //Awareness
- World.BuffManager.RemoveBuffs(this, 324770);
- World.BuffManager.AddBuff(this, this, new AwarenessBuff());
- break;
- case 209734: //Archery
- var weapon = Inventory.GetEquippedWeapon();
- if (weapon != null)
- {
- string name = weapon.ItemDefinition.Name.ToLower();
- if (name.Contains("xbow"))
- Attributes[GameAttribute.Crit_Damage_Percent] += 0.5f;
- if (name.Contains("handxbow"))
- Attributes[GameAttribute.Crit_Percent_Bonus_Uncapped] += 0.05f;
- else
- if (name.Contains("xbow"))
- Attributes[GameAttribute.Resource_Regen_Per_Second, (int)Toon.HeroTable.PrimaryResource] += 1f;
- else
- if (name.Contains("bow"))
- {
- Attributes[GameAttribute.Damage_Weapon_Percent_Bonus] += 0.08f;
- Attributes[GameAttribute.Damage_Percent_All_From_Skills] = 0.08f;
- }
- }
- break;
- case 155722: //Perfectionist
- Attributes[GameAttribute.Armor_Item] *= 1.1f;
- Attributes[GameAttribute.Hitpoints_Max_Percent_Bonus] += 0.1f;
- Attributes[GameAttribute.Resistance_Percent_All] += 0.1f;
- break;
- }
- break;
- case ToonClass.Monk:
- switch (passiveId)
- {
- case 209029: //FleetFooted
- Attributes[GameAttribute.Movement_Scalar_Uncapped_Bonus] += 0.1f;
- break;
- case 209027: //ExaltedSoul
- Attributes[GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.PrimaryResource] += 100;
- //this.Attributes[GameAttribute.Resource_Cur, (int)Toon.HeroTable.PrimaryResource] = Toon.HeroTable.PrimaryResourceMax + this.Attributes[GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.PrimaryResource];
- Attributes[GameAttribute.Resource_Regen_Per_Second, 3] += 2f;
- break;
- case 209628: //SeizeTheInitiative
- Attributes[GameAttribute.Armor_Item] += (Attributes[GameAttribute.Dexterity_Total] * 0.3f);
- break;
- case 209622: //SixthSense
- Attributes[GameAttribute.Dodge_Chance_Bonus] += Math.Min(((Attributes[GameAttribute.Weapon_Crit_Chance] + Attributes[GameAttribute.Crit_Percent_Bonus_Capped] + Attributes[GameAttribute.Crit_Percent_Bonus_Uncapped]) * 0.425f), 0.15f);
- break;
- case 209104: //BeaconOfYtar
- Attributes[GameAttribute.Power_Cooldown_Reduction_Percent_All] += 0.20f;
- break;
- case 209656: //OneWithEverything
- var maxResist = Math.Max(
- Math.Max(Math.Max(Attributes[GameAttribute.Resistance, DamageType.Physical.AttributeKey], Attributes[GameAttribute.Resistance, DamageType.Cold.AttributeKey]), Attributes[GameAttribute.Resistance, DamageType.Fire.AttributeKey]),
- Math.Max(Math.Max(Attributes[GameAttribute.Resistance, DamageType.Arcane.AttributeKey], Attributes[GameAttribute.Resistance, DamageType.Holy.AttributeKey]), Math.Max(Attributes[GameAttribute.Resistance, DamageType.Lightning.AttributeKey], Attributes[GameAttribute.Resistance, DamageType.Poison.AttributeKey]))
- );
- foreach (var damageType in DamageType.AllTypes)
- Attributes[GameAttribute.Resistance, damageType.AttributeKey] = maxResist;
- break;
- case 209812: //TheGuardiansPath
- try
- {
- var weapon = Inventory.GetEquippedWeapon();
- if (weapon != null && Inventory.GetEquippedOffHand() != null)
- Attributes[GameAttribute.Dodge_Chance_Bonus] += 0.15f;
- else
- if (weapon.ItemDefinition.Name.ToLower().Contains("2h"))
- {
- World.BuffManager.RemoveBuffs(this, 209812);
- World.BuffManager.AddBuff(this, this, new GuardiansPathBuff());
- }
- }
- catch { }
- break;
- case 341559: //Momentum
- World.BuffManager.RemoveBuffs(this, 341559);
- World.BuffManager.AddBuff(this, this, new MomentumCheckBuff());
- break;
- case 209813: //Provocation
- Attributes[GameAttribute.CrowdControl_Reduction] += 0.25f;
- break;
- }
- break;
- case ToonClass.WitchDoctor:
- switch (passiveId)
- {
- case 208569: //SpiritualAttunement
- Attributes[GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.PrimaryResource] += Attributes[GameAttribute.Resource_Max, (int)Toon.HeroTable.PrimaryResource] * 0.2f;
- Attributes[GameAttribute.Resource_Regen_Per_Second, (int)Toon.HeroTable.PrimaryResource] = Toon.HeroTable.PrimaryResourceRegen + ((Toon.HeroTable.PrimaryResourceBase + Attributes[GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.PrimaryResource]) / 100);
- Attributes[GameAttribute.Resource_Cur, (int)Toon.HeroTable.PrimaryResource] = Toon.HeroTable.PrimaryResourceBase + Attributes[GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.PrimaryResource];
- break;
- case 340910: //PhysicalAttunement
- World.BuffManager.RemoveBuffs(this, 340910);
- World.BuffManager.AddBuff(this, this, new PhysicalAttunementBuff());
- break;
- case 208568: //BloodRitual
- Attributes[GameAttribute.Hitpoints_Regen_Per_Second] += (Attributes[GameAttribute.Hitpoints_Max_Total]) / 100;
- break;
- case 208639: //FierceLoyalty
- foreach (var minionId in Followers.Keys)
- {
- var minion = World.GetActorByGlobalId(minionId);
- if (minion != null)
- minion.Attributes[GameAttribute.Hitpoints_Regen_Per_Second] = Inventory.GetItemBonus(GameAttribute.Hitpoints_Regen_Per_Second);
- }
- break;
- }
- break;
- case ToonClass.Wizard:
- switch (passiveId)
- {
- case 208541: //Galvanizing Ward
- World.BuffManager.RemoveBuffs(this, 208541);
- World.BuffManager.AddBuff(this, this, new GalvanizingBuff());
- break;
- case 208473: //Evocation
- Attributes[GameAttribute.Power_Cooldown_Reduction_Percent_All] += 0.20f;
- break;
- case 208472: //AstralPresence
- Attributes[GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.PrimaryResource] += 20;
- Attributes[GameAttribute.Resource_Regen_Per_Second, (int)Toon.HeroTable.PrimaryResource] = Toon.HeroTable.PrimaryResourceRegen + 2;
- Attributes[GameAttribute.Resource_Cur, (int)Toon.HeroTable.PrimaryResource] = Toon.HeroTable.PrimaryResourceBase + Attributes[GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.PrimaryResource];
- break;
- case 208468: //Blur (Wizard)
- Attributes[GameAttribute.Damage_Percent_Reduction_From_Melee] += 0.17f;
- break;
- }
- break;
- case ToonClass.Crusader:
- switch (passiveId)
- {
- case 286177: //HeavenlyStrength
- Attributes[GameAttribute.Movement_Scalar_Uncapped_Bonus] -= 0.15f;
- Attributes[GameAttribute.Allow_2H_And_Shield] = true;
- break;
- case 310626: //Vigilant
- Attributes[GameAttribute.Hitpoints_Regen_Per_Second] += (10 + 0.008f * (float)Math.Pow(Attributes[GameAttribute.Level], 3));
- break;
- case 356147: //Righteousness
- Attributes[GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.PrimaryResource] += 30;
- break;
- case 310804: //HolyCause
- Attributes[GameAttribute.Damage_Weapon_Min, 6] *= 1.1f;
- break;
- case 356176: //DivineFortress
- World.BuffManager.RemoveBuffs(this, 356176);
- World.BuffManager.AddBuff(this, this, new DivineFortressBuff());
- break;
- case 302500: //HoldYourGround
- Attributes[GameAttribute.Cannot_Dodge] = true;
- Attributes[GameAttribute.Block_Chance] += 0.15f;
- break;
- case 310783: //IronMaiden
- Attributes[GameAttribute.Thorns_Fixed, 0] += (87.17f * Attributes[GameAttribute.Level]);
- break;
- case 311629: //Finery
- World.BuffManager.RemoveBuffs(this, 311629);
- World.BuffManager.AddBuff(this, this, new FineryBuff());
- break;
- case 310640: //Insurmountable
- World.BuffManager.RemoveBuffs(this, 310640);
- World.BuffManager.AddBuff(this, this, new InsurmountableBuff());
- break;
- case 309830: //Indesctructible
- World.BuffManager.RemoveBuffs(this, 309830);
- World.BuffManager.AddBuff(this, this, new IndestructibleBuff());
- break;
- case 356173: //Renewal
- World.BuffManager.RemoveBuffs(this, 356173);
- World.BuffManager.AddBuff(this, this, new RenewalBuff());
- break;
- case 356052: //Towering Shield
- World.BuffManager.RemoveBuffs(this, 356052);
- World.BuffManager.AddBuff(this, this, new ToweringShieldBuff());
- break;
- }
- break;
- case ToonClass.Necromancer:
- switch (passiveId)
- {
- case 470764: //HugeEssense
- Attributes[GameAttribute.Resource_Max_Bonus, Attributes[GameAttribute.Resource_Type_Primary] - 1] += 40;
- break;
- case 470725:
- World.BuffManager.RemoveBuffs(this, 470725);
- World.BuffManager.AddBuff(this, this, new OnlyOne());
- break;
- }
-
- break;
- }
-
- SetAttributesSkillSets(); //reapply synergy passives (laws, mantras, summons)
- }
-
- public void SetAttributesSkillSets()
- {
- // unlocking assigned skills
- for (int i = 0; i < SkillSet.ActiveSkills.Length; i++)
- {
- if (SkillSet.ActiveSkills[i].snoSkill != -1)
- {
- Attributes[GameAttribute.Skill, SkillSet.ActiveSkills[i].snoSkill] = 1;
- //scripted //this.Attributes[GameAttribute.Skill_Total, this.SkillSet.ActiveSkills[i].snoSkill] = 1;
- // update rune attributes for new skill
- Attributes[GameAttribute.Rune_A, SkillSet.ActiveSkills[i].snoSkill] = SkillSet.ActiveSkills[i].snoRune == 0 ? 1 : 0;
- Attributes[GameAttribute.Rune_B, SkillSet.ActiveSkills[i].snoSkill] = SkillSet.ActiveSkills[i].snoRune == 1 ? 1 : 0;
- Attributes[GameAttribute.Rune_C, SkillSet.ActiveSkills[i].snoSkill] = SkillSet.ActiveSkills[i].snoRune == 2 ? 1 : 0;
- Attributes[GameAttribute.Rune_D, SkillSet.ActiveSkills[i].snoSkill] = SkillSet.ActiveSkills[i].snoRune == 3 ? 1 : 0;
- Attributes[GameAttribute.Rune_E, SkillSet.ActiveSkills[i].snoSkill] = SkillSet.ActiveSkills[i].snoRune == 4 ? 1 : 0;
-
- PowerScript power = PowerLoader.CreateImplementationForPowerSNO(SkillSet.ActiveSkills[i].snoSkill);
- if (power != null && power.EvalTag(PowerKeys.SynergyPower) != -1)
- {
- World.PowerManager.RunPower(this, power.EvalTag(PowerKeys.SynergyPower)); //SynergyPower buff
- }
- }
- }
- for (int i = 0; i < SkillSet.PassiveSkills.Length; ++i)
- {
- if (SkillSet.PassiveSkills[i] != -1)
- {
- // switch on passive skill
- Attributes[GameAttribute.Trait, SkillSet.PassiveSkills[i]] = 1;
- Attributes[GameAttribute.Skill, SkillSet.PassiveSkills[i]] = 1;
- //scripted //this.Attributes[GameAttribute.Skill_Total, this.SkillSet.PassiveSkills[i]] = 1;
- }
- }
- if (Toon.Class == ToonClass.Monk) //Setting power range override
- {
- Attributes[GameAttribute.PowerBonusAttackRadius, 0x000176C4] = 20f; //Fists of Thunder
- if (Attributes[GameAttribute.Rune_A, 0x00017B56] > 0) //Way of the Hundred Fists -> Fists of Fury
- Attributes[GameAttribute.PowerBonusAttackRadius, 0x00017B56] = 15f;
- }
- }
-
- public void SetAttributesOther()
- {
- //Bonus stats
- Attributes[GameAttribute.Hit_Chance] = 1f;
-
- Attributes[GameAttribute.Attacks_Per_Second] = 1.2f;
- //this.Attributes[GameAttribute.Attacks_Per_Second_Item] = 1.199219f;
- Attributes[GameAttribute.Crit_Percent_Cap] = Toon.HeroTable.CritPercentCap;
- //scripted //this.Attributes[GameAttribute.Casting_Speed_Total] = 1f;
- Attributes[GameAttribute.Casting_Speed] = 1f;
-
- //Basic stats
- Attributes[GameAttribute.Level_Cap] = Program.MaxLevel;
- Attributes[GameAttribute.Level] = Level;
- Attributes[GameAttribute.Alt_Level] = ParagonLevel;
- if (Level == Program.MaxLevel)
- {
- Attributes[GameAttribute.Alt_Experience_Next_Lo] = (int)(ExperienceNext % UInt32.MaxValue);
- Attributes[GameAttribute.Alt_Experience_Next_Hi] = (int)(ExperienceNext / UInt32.MaxValue);
- }
- else
- {
- Attributes[GameAttribute.Experience_Next_Lo] = (int)(ExperienceNext % UInt32.MaxValue);
- Attributes[GameAttribute.Experience_Next_Hi] = (int)(ExperienceNext / UInt32.MaxValue);
- //this.Attributes[GameAttribute.Alt_Experience_Next] = 0;
- }
-
- Attributes[GameAttribute.Experience_Granted_Low] = 1000;
- Attributes[GameAttribute.Armor] = Toon.HeroTable.Armor;
- Attributes[GameAttribute.Damage_Min, 0] = Toon.HeroTable.Dmg;
- //scripted //this.Attributes[GameAttribute.Armor_Total]
-
-
- Attributes[GameAttribute.Strength] = (int)Strength;
- Attributes[GameAttribute.Dexterity] = (int)Dexterity;
- Attributes[GameAttribute.Vitality] = (int)Vitality;
- Attributes[GameAttribute.Intelligence] = (int)Intelligence;
- Attributes[GameAttribute.Core_Attributes_From_Item_Bonus_Multiplier] = 1;
-
- //Hitpoints have to be calculated after Vitality
- Attributes[GameAttribute.Hitpoints_Factor_Level] = Toon.HeroTable.HitpointsFactorLevel;
- Attributes[GameAttribute.Hitpoints_Factor_Vitality] = 10f + Math.Max(Level - 35, 0);
- //this.Attributes[GameAttribute.Hitpoints_Max] = 276f;
-
- Attributes[GameAttribute.Hitpoints_Max_Percent_Bonus_Multiplicative] = (int)1;
- Attributes[GameAttribute.Hitpoints_Factor_Level] = (int)Toon.HeroTable.HitpointsFactorLevel;
- Attributes[GameAttribute.Hitpoints_Factor_Vitality] = 10f;// + Math.Max(this.Level - 35, 0);
- Attributes[GameAttribute.Hitpoints_Max] = (int)Toon.HeroTable.HitpointsMax;
-
- Attributes[GameAttribute.Hitpoints_Cur] = Attributes[GameAttribute.Hitpoints_Max_Total];
-
- Attributes[GameAttribute.Corpse_Resurrection_Charges] = 3;
- //TestOutPutItemAttributes(); //Activate this only for finding item stats.
- Attributes.BroadcastChangedIfRevealed();
-
- }
-
- #endregion
-
- #region game-message handling & consumers
-
- ///
- /// Consumes the given game-message.
- ///
- /// The client.
- /// The GameMessage.
- public void Consume(GameClient client, GameMessage message)
- {
- if (message is AssignSkillMessage) OnAssignActiveSkill(client, (AssignSkillMessage)message);
- else if (message is AssignTraitsMessage) OnAssignPassiveSkills(client, (AssignTraitsMessage)message);
- else if (message is UnassignSkillMessage) OnUnassignActiveSkill(client, (UnassignSkillMessage)message);
- else if (message is TargetMessage) OnObjectTargeted(client, (TargetMessage)message);
- else if (message is ACDClientTranslateMessage) OnPlayerMovement(client, (ACDClientTranslateMessage)message);
- else if (message is TryWaypointMessage) OnTryWaypoint(client, (TryWaypointMessage)message);
- else if (message is RequestBuyItemMessage) OnRequestBuyItem(client, (RequestBuyItemMessage)message);
- else if (message is RequestSellItemMessage) OnRequestSellItem(client, (RequestSellItemMessage)message);
- else if (message is HirelingRequestLearnSkillMessage) OnHirelingRequestLearnSkill(client, (HirelingRequestLearnSkillMessage)message);
- else if (message is HirelingRetrainMessage) OnHirelingRetrainMessage();
- else if (message is HirelingSwapAgreeMessage) OnHirelingSwapAgreeMessage();
- else if (message is PetAwayMessage) OnHirelingDismiss(client, message as PetAwayMessage);
- else if (message is ChangeUsableItemMessage) OnEquipPotion(client, (ChangeUsableItemMessage)message);
- else if (message is ArtisanWindowClosedMessage) OnArtisanWindowClosed();
- else if (message is RequestTrainArtisanMessage) TrainArtisan(client, (RequestTrainArtisanMessage)message);
- else if (message is RessurectionPlayerMessage) OnResurrectOption(client, (RessurectionPlayerMessage)message);
- else if (message is PlayerTranslateFacingMessage) OnTranslateFacing(client, (PlayerTranslateFacingMessage)message);
- else if (message is LoopingAnimationPowerMessage) OnLoopingAnimationPowerMessage(client, (LoopingAnimationPowerMessage)message);
- else if (message is SecondaryAnimationPowerMessage) OnSecondaryPowerMessage(client, (SecondaryAnimationPowerMessage)message);
- else if (message is MiscPowerMessage) OnMiscPowerMessage(client, (MiscPowerMessage)message);
- else if (message is RequestBuffCancelMessage) OnRequestBuffCancel(client, (RequestBuffCancelMessage)message);
- else if (message is CancelChanneledSkillMessage) OnCancelChanneledSkill(client, (CancelChanneledSkillMessage)message);
- else if (message is TutorialShownMessage) OnTutorialShown(client, (TutorialShownMessage)message);
- else if (message is AcceptConfirmMessage) OnConfirm(client, (AcceptConfirmMessage)message);
- else if (message is SpendParagonPointsMessage) OnSpendParagonPointsMessage(client, (SpendParagonPointsMessage)message);
- else if (message is ResetParagonPointsMessage) OnResetParagonPointsMessage(client, (ResetParagonPointsMessage)message);
- else if (message is MailRetrieveMessage) OnMailRetrieve(client, (MailRetrieveMessage)message);
- else if (message is MailReadMessage) OnMailRead(client, (MailReadMessage)message);
- else if (message is StashIconStateAssignMessage) OnStashIconsAssign(client, (StashIconStateAssignMessage)message);
- else if (message is TransmuteItemsMessage) TransumteItemsPlayer(client, (TransmuteItemsMessage)message);
- else if (message is RiftStartAcceptedMessage) OpenNephalem(client, (RiftStartAcceptedMessage)message);
- else if (message is BossEncounterAcceptMessage) AcceptBossEncounter();
- else if (message is DeActivateCameraCutsceneMode) DeactivateCamera(client, (DeActivateCameraCutsceneMode)message);
- else if (message is JewelUpgradeMessage) JewelUpgrade(client, (JewelUpgradeMessage)message);
- else if (message is SwitchCosmeticMessage) SwitchCosmetic(client, (SwitchCosmeticMessage)message);
-
- else return;
- }
- public void SwitchCosmetic(GameClient client, SwitchCosmeticMessage message)
- {
- var Definition = ItemGenerator.GetItemDefinition(message.Field0);
-
- ;
- if (Definition.Name.ToLower().Contains("portrait"))
- {
- client.BnetClient.Account.GameAccount.CurrentToon.Cosmetic4 = message.Field0;
- }
-
- var RangeCosmetic = new[]
- {
- D3.Hero.VisualCosmeticItem.CreateBuilder().SetGbid(client.BnetClient.Account.GameAccount.CurrentToon.Cosmetic1).Build(), // Wings
- D3.Hero.VisualCosmeticItem.CreateBuilder().SetGbid(client.BnetClient.Account.GameAccount.CurrentToon.Cosmetic2).Build(), // Flag
- D3.Hero.VisualCosmeticItem.CreateBuilder().SetGbid(client.BnetClient.Account.GameAccount.CurrentToon.Cosmetic3).Build(), // Pet
- D3.Hero.VisualCosmeticItem.CreateBuilder().SetGbid(client.BnetClient.Account.GameAccount.CurrentToon.Cosmetic4).Build(), // Frame
- };
-
- //RangeCosmetic[request.CosmeticItemType - 1] = D3.Hero.VisualCosmeticItem.CreateBuilder().SetGbid(unchecked((int)request.Gbid)).Build();
-
- client.BnetClient.Account.GameAccount.CurrentToon.StateChanged();
-
- var NewVisual = D3.Hero.VisualEquipment.CreateBuilder()
- .AddRangeVisualItem(client.BnetClient.Account.GameAccount.CurrentToon.HeroVisualEquipmentField.Value.VisualItemList).AddRangeCosmeticItem(RangeCosmetic).Build();
-
- client.BnetClient.Account.GameAccount.CurrentToon.HeroVisualEquipmentField.Value = NewVisual;
- client.BnetClient.Account.GameAccount.ChangedFields.SetPresenceFieldValue(client.BnetClient.Account.GameAccount.CurrentToon.HeroVisualEquipmentField);
- client.BnetClient.Account.GameAccount.NotifyUpdate();
- }
- public void ResetParagonPoints(GameClient client, ResetParagonPointsMessage message)
- {
-
- }
- public void SpendParagonPoints(GameClient client, SpendParagonPointsMessage message)
- {
-
- }
- public void JewelUpgrade(GameClient client, JewelUpgradeMessage message)
- {
- var Jewel = Inventory.GetItemByDynId(this, message.ActorID);
- Jewel.Attributes[GameAttribute.Jewel_Rank]++;
- Jewel.Attributes.BroadcastChangedIfRevealed();
- Attributes[GameAttribute.Jewel_Upgrades_Used]++;
- Attributes.BroadcastChangedIfRevealed();
- if (Attributes[GameAttribute.Jewel_Upgrades_Used] == Attributes[GameAttribute.Jewel_Upgrades_Max] + Attributes[GameAttribute.Jewel_Upgrades_Bonus])
- {
- Attributes[GameAttribute.Jewel_Upgrades_Max] = 0;
- Attributes[GameAttribute.Jewel_Upgrades_Bonus] = 0;
- Attributes[GameAttribute.Jewel_Upgrades_Used] = 0;
- }
- InGameClient.SendMessage(new JewelUpgradeResultsMessage()
- {
- ActorID = message.ActorID,
- Field1 = 1
- });
- }
- public void OnHirelingSwapAgreeMessage()
- {
- Hireling hireling = null;
- DiIiS_NA.Core.MPQ.FileFormats.Actor Data = null;
- if (World.Game.Players.Count > 1) return;
-
-
- switch (InGameClient.Game.CurrentQuest)
- {
- case 72061:
- //Templar
- Data = (DiIiS_NA.Core.MPQ.FileFormats.Actor)MPQStorage.Data.Assets[SNOGroup.Actor][52693].Data;
- hireling = new Templar(World, ActorSno._hireling_templar, Data.TagMap);
- hireling.GBHandle.GBID = StringHashHelper.HashItemName("Templar");
-
- break;
- case 72738:
- //Scoundrel
- Data = (DiIiS_NA.Core.MPQ.FileFormats.Actor)MPQStorage.Data.Assets[SNOGroup.Actor][52694].Data;
- hireling = new Templar(World, ActorSno._hireling_scoundrel, Data.TagMap);
- hireling.GBHandle.GBID = StringHashHelper.HashItemName("Scoundrel");
- break;
- case 0:
- //Enchantress
- Data = (DiIiS_NA.Core.MPQ.FileFormats.Actor)MPQStorage.Data.Assets[SNOGroup.Actor][4482].Data;
- hireling = new Templar(World, ActorSno._hireling_enchantress, Data.TagMap);
- hireling.GBHandle.GBID = StringHashHelper.HashItemName("Enchantress");
- break;
-
- }
-
- hireling.SetUpAttributes(this);
- hireling.GBHandle.Type = 4;
- hireling.Attributes[GameAttribute.Pet_Creator] = PlayerIndex + 1;
- hireling.Attributes[GameAttribute.Pet_Type] = 1;
- hireling.Attributes[GameAttribute.Pet_Owner] = PlayerIndex + 1;
- hireling.Attributes[GameAttribute.Untargetable] = false;
- hireling.Attributes[GameAttribute.NPC_Is_Escorting] = true;
-
- hireling.EnterWorld(RandomDirection(Position, 3, 10)); //Random
- hireling.Brain = new HirelingBrain(hireling, this);
- ActiveHireling = hireling;
- SelectedNPC = null;
- }
-
- public static Vector3D RandomDirection(Vector3D position, float minRadius, float maxRadius)
- {
- float angle = (float)(FastRandom.Instance.NextDouble() * Math.PI * 2);
- float radius = minRadius + (float)FastRandom.Instance.NextDouble() * (maxRadius - minRadius);
- return new Vector3D(position.X + (float)Math.Cos(angle) * radius,
- position.Y + (float)Math.Sin(angle) * radius,
- position.Z);
- }
-
- public void AwayPet(GameClient client, PetAwayMessage message)
- {
-
- }
- public void DeactivateCamera(GameClient client, DeActivateCameraCutsceneMode message)
- {
- InGameClient.SendMessage(new BoolDataMessage(Opcodes.CameraTriggerFadeToBlackMessage) { Field0 = true });
- InGameClient.SendMessage(new SimpleMessage(Opcodes.CameraSriptedSequenceStopMessage) { });
- //this.InGameClient.SendMessage(new ActivateCameraCutsceneMode() { Activate = true });
- }
- public void AcceptBossEncounter()
- {
- InGameClient.Game.AcceptBossEncounter();
- }
- public void DeclineBossEncounter()
- {
- InGameClient.Game.CurrentEncounter.activated = false;
- }
- public void TransumteItemsPlayer(GameClient client, TransmuteItemsMessage message)
- {
- var recipeDefinition = ItemGenerator.GetRecipeDefinition(608170752);
- for (int i = 0; i < message.CurrenciesCount; i++)
- {
- var data = ItemGenerator.GetItemDefinition(message.GBIDCurrencies[i]).Name;
- switch(data)
- {
- case "p2_ActBountyReagent_01": break;
- case "p2_ActBountyReagent_02": break;
- case "p2_ActBountyReagent_03": break;
- case "p2_ActBountyReagent_04": break;
- case "p2_ActBountyReagent_05": break;
- case "Crafting_Looted_Reagent_01": break;
- }
- }
- foreach (var it in message.annItems)
- {
- var a = Inventory.GetItemByDynId(this, (uint)it);
- }
-
- Item ItemPortalToCows = null;
- List
- Items = new List
- { };
- for (int i = 0; i < message.ItemsCount; i++)
- {
- Items.Add(Inventory.GetItemByDynId(this, (uint)message.annItems[i]));
- if (Items[i].SNO == ActorSno._x1_polearm_norm_unique_05)
- ItemPortalToCows = Items[i];
- }
-
- //Type - 0 - Новое свойство
- //Type - 1 - Преобразование
- //Type - 2 -
-
- if (ItemPortalToCows != null)
- {
- InGameClient.SendMessage(new TransmuteResultsMessage()
- {
- annItem = -1,
- Type = -1,
- GBIDFakeItem = -1,
- GBIDPower = -1,
- FakeItemStackCount = -1
- });
-
- Inventory.DestroyInventoryItem(ItemPortalToCows);
- World.SpawnMonster(ActorSno._p2_totallynotacowlevel_portal, new Vector3D(Position.X + 5, Position.Y + 5, Position.Z));
- }
- else
- {
- InGameClient.SendMessage(new TransmuteResultsMessage()
- {
- annItem = (int)Items[0].DynamicID(this),
- Type = 0,
- GBIDFakeItem = -1,
- GBIDPower = (int)Items[0].ItemDefinition.Hash,
- FakeItemStackCount = -1
- });
- GrantCriteria(74987245494264);
- GrantCriteria(74987258962046);
- }
- }
- private bool WaitToSpawn(TickTimer timer)
- {
- while (timer.TimedOut != true)
- {
-
- }
- return true;
- }
- public void OpenNephalem(GameClient client, RiftStartAcceptedMessage message)
- {
- //396751 - X1_OpenWorld_Tiered_Rifts_Portal - Великий портал
- //345935 - X1_OpenWorld_LootRunPortal - Обычные порталы
- //408511 - X1_OpenWorld_Tiered_Rifts_Challenge_Portal
-
- //1073741824 - Первый уровень Великого бафнутого
- //0 - Первый уровень Великого
- //
- bool Activated = false;
- TagMap NewTagMap = new TagMap();
- World NephalemPWorld = null;
- Actor NStone = null;
- Portal portal = null;
- var map = WorldSno.__NONE;
- WorldSno[] Maps = new WorldSno[]
- {
-
- WorldSno.x1_lr_tileset_westmarch, //x1_lr_tileset_Westmarch
- WorldSno.x1_lr_tileset_fortress_large, //_x1_lr_tileset_fortress_large
- WorldSno.x1_lr_tileset_zoltruins, //x1_lr_tileset_zoltruins
- WorldSno.x1_lr_tileset_hexmaze, //x1_lr_tileset_hexmaze
- WorldSno.x1_lr_tileset_icecave, //x1_lr_tileset_icecave
-
- WorldSno.x1_lr_tileset_crypt, //x1_lr_tileset_crypt
- WorldSno.x1_lr_tileset_corruptspire, //x1_lr_tileset_corruptspire
-
- //288843, //x1_lr_tileset_sewers
- };
-
- switch (message.Field0)
- {
- #region Нефалемский портал
- case -1:
- Logger.Debug("Calling Nephalem Portal (Normal)");
- Activated = false;
-
- foreach (var oldp in World.GetActorsBySNO(ActorSno._x1_openworld_lootrunportal, ActorSno._x1_openworld_tiered_rifts_portal)) { oldp.Destroy(); }
-
- map = Maps[RandomHelper.Next(0, Maps.Length)];
- //map = 288823;
- NewTagMap.Add(new TagKeySNO(526850), new TagMapEntry(526850, (int)map, 0)); //World
- NewTagMap.Add(new TagKeySNO(526853), new TagMapEntry(526853, 288482, 0)); //Zone
- NewTagMap.Add(new TagKeySNO(526851), new TagMapEntry(526851, 172, 0)); //Entry-Pointа
- InGameClient.Game.WorldOfPortalNephalem = map;
-
- while (true)
- {
- map = Maps[RandomHelper.Next(0, Maps.Length)];
- if (map != InGameClient.Game.WorldOfPortalNephalem) break;
- }
- InGameClient.Game.WorldOfPortalNephalemSec = map;
-
- NephalemPWorld = InGameClient.Game.GetWorld(InGameClient.Game.WorldOfPortalNephalem);
-
- int ExitSceneSNO = -1;
- foreach (var scene in NephalemPWorld.Scenes.Values)
- if (scene.SceneSNO.Name.ToLower().Contains("exit"))
- ExitSceneSNO = scene.SceneSNO.Id;
- bool ExitSetted = false;
- foreach (var actor in NephalemPWorld.Actors.Values)
- if (actor is Portal)
- {
- var p = actor as Portal;
- if (!actor.CurrentScene.SceneSNO.Name.ToLower().Contains("entrance"))
- {
- if (!actor.CurrentScene.SceneSNO.Name.ToLower().Contains("exit"))
- actor.Destroy();
- else if (!ExitSetted)
- {
- p.Destination.DestLevelAreaSNO = 288684;
- p.Destination.WorldSNO = (int)InGameClient.Game.WorldOfPortalNephalemSec;
- ExitSetted = true;
-
- var NephalemPWorldS2 = InGameClient.Game.GetWorld(InGameClient.Game.WorldOfPortalNephalemSec);
- foreach (var atr in NephalemPWorldS2.Actors.Values)
- if (atr is Portal)
- {
- if (!atr.CurrentScene.SceneSNO.Name.ToLower().Contains("entrance"))
- atr.Destroy();
- else
- {
- (atr as Portal).Destination.DestLevelAreaSNO = 332339;
- (atr as Portal).Destination.WorldSNO = (int)WorldSno.x1_tristram_adventure_mode_hub;
- (atr as Portal).Destination.StartingPointActorTag = 172;
- }
- }
- else if (atr is Waypoint)
- atr.Destroy();
- }
- else
- actor.Destroy();
- }
- else
- {
- p.Destination.DestLevelAreaSNO = 332339;
- p.Destination.WorldSNO = (int)WorldSno.x1_tristram_adventure_mode_hub;
- p.Destination.StartingPointActorTag = 24;
- }
- }
- else if (actor is Waypoint)
- actor.Destroy();
-
- #region Активация
- NStone = World.GetActorBySNO(ActorSno._x1_openworld_lootrunobelisk_b);
- NStone.PlayAnimation(5, (AnimationSno)NStone.AnimationSet.TagMapAnimDefault[AnimationSetKeys.Opening]);
- NStone.Attributes[GameAttribute.Team_Override] = (Activated ? -1 : 2);
- NStone.Attributes[GameAttribute.Untargetable] = !Activated;
- NStone.Attributes[GameAttribute.NPC_Is_Operatable] = Activated;
- NStone.Attributes[GameAttribute.Operatable] = Activated;
- NStone.Attributes[GameAttribute.Operatable_Story_Gizmo] = Activated;
- NStone.Attributes[GameAttribute.Disabled] = !Activated;
- NStone.Attributes[GameAttribute.Immunity] = !Activated;
- NStone.Attributes.BroadcastChangedIfRevealed();
-
- NStone.CollFlags = 0;
- World.BroadcastIfRevealed(plr => new ACDCollFlagsMessage
- {
- ActorID = NStone.DynamicID(plr),
- CollFlags = 0
- }, NStone);
- portal = new Portal(World, ActorSno._x1_openworld_lootrunportal, NewTagMap);
-
- TickTimer Timeout = new SecondsTickTimer(World.Game, 3.5f);
- var Boom = System.Threading.Tasks.Task.Factory.StartNew(() => WaitToSpawn(Timeout));
- Boom.ContinueWith(delegate
- {
- portal.EnterWorld(NStone.Position);
- //Quest - 382695 - Великий Нефалемский
- //Quest - 337492 - Просто Нефалемский
- foreach (var plr in InGameClient.Game.Players.Values)
- {
- plr.InGameClient.SendMessage(new QuestUpdateMessage()
- {
- snoQuest = 0x00052654,
- snoLevelArea = 0x000466E2,
- StepID = -1,
- DisplayButton = true,
- Failed = false
- });
-
- plr.InGameClient.SendMessage(new QuestCounterMessage()
- {
- snoQuest = 0x00052654,
- snoLevelArea = 0x000466E2,
- StepID = -1,
- Checked = 1,
- Counter = 1
- });
-
- plr.InGameClient.SendMessage(new QuestUpdateMessage()
- {
- snoQuest = 0x00052654,
- snoLevelArea = 0x000466E2,
- StepID = 1,
- DisplayButton = true,
- Failed = false
- });
-
- plr.InGameClient.Game.ActiveNephalemPortal = true;
- plr.InGameClient.SendMessage(new SimpleMessage(Opcodes.RiftStartedMessage));
-
- plr.InGameClient.SendMessage(new GameSyncedDataMessage
- {
- SyncedData = new GameSyncedData
- {
- GameSyncedFlags = 6,
- Act = 3000, //act id
- InitialMonsterLevel = InGameClient.Game.InitialMonsterLevel, //InitialMonsterLevel
- MonsterLevel = 0x64E4425E, //MonsterLevel
- RandomWeatherSeed = InGameClient.Game.WeatherSeed, //RandomWeatherSeed
- OpenWorldMode = -1, //OpenWorldMode
- OpenWorldModeAct = -1, //OpenWorldModeAct
- OpenWorldModeParam = -1, //OpenWorldModeParam
- OpenWorldTransitionTime = 0x00000064, //OpenWorldTransitionTime
- OpenWorldDefaultAct = 100, //OpenWorldDefaultAct
- OpenWorldBonusAct = -1, //OpenWorldBonusAct
- SNODungeonFinderLevelArea = 0x00000001, //SNODungeonFinderLevelArea
- LootRunOpen = -1, //LootRunOpen //0 - Великий Портал
- OpenLootRunLevel = 0, //OpenLootRunLevel
- LootRunBossDead = 0, //LootRunBossDead
- HunterPlayerIdx = 0, //HunterPlayerIdx
- LootRunBossActive = -1, //LootRunBossActive
- TieredLootRunFailed = 0, //TieredLootRunFailed
- LootRunChallengeCompleted = 0, //LootRunChallengeCompleted
- SetDungeonActive = 0, //SetDungeonActive
- Pregame = 0, //Pregame
- PregameEnd = 0, //PregameEnd
- RoundStart = 0, //RoundStart
- RoundEnd = 0, //RoundEnd
- PVPGameOver = 0x0, //PVPGameOver
- field_v273 = 0x0,
- TeamWins = new[] { 0x0, 0x0 }, //TeamWins
- TeamScore = new[] { 0x0, 0x0 }, //TeamScore
- PVPGameResult = new[] { 0x0, 0x0 }, //PVPGameResult
- PartyGuideHeroId = 0x0, //PartyGuideHeroId //new EntityId() { High = 0, Low = (long)this.Players.Values.First().Toon.PersistentID }
- TiredRiftPaticipatingHeroID = new long[] { 0x0, 0x0, 0x0, 0x0 }, //TiredRiftPaticipatingHeroID
- }
- });
- }
- });
-
- #endregion
-
-
- break;
- #endregion
- #region Великий портал
- default:
- InGameClient.Game.NephalemGreaterLevel = message.Field0;
-
- Logger.Debug("Calling Nephalem Portal (Level: {0})", message.Field0);
- Activated = false;
- foreach (var oldp in World.GetActorsBySNO(ActorSno._x1_openworld_lootrunportal, ActorSno._x1_openworld_tiered_rifts_portal)) { oldp.Destroy(); }
-
- InGameClient.Game.ActiveNephalemPortal = true;
- InGameClient.Game.NephalemGreater = true;
- //disable banner while greater is active enable once boss is killed or portal is closed /advocaite
- Attributes[GameAttribute.Banner_Usable] = false;
- map = Maps[RandomHelper.Next(0, Maps.Length)];
- NewTagMap.Add(new TagKeySNO(526850), new TagMapEntry(526850, (int)map, 0)); //World
- NewTagMap.Add(new TagKeySNO(526853), new TagMapEntry(526853, 288482, 0)); //Zone
- NewTagMap.Add(new TagKeySNO(526851), new TagMapEntry(526851, 172, 0)); //Entry-Pointа
- InGameClient.Game.WorldOfPortalNephalem = map;
-
- NephalemPWorld = InGameClient.Game.GetWorld(map);
- foreach (var actor in NephalemPWorld.Actors.Values)
- if (actor is Portal)
- {
- if (!actor.CurrentScene.SceneSNO.Name.ToLower().Contains("entrance"))
- actor.Destroy();
- else
- {
- (actor as Portal).Destination.DestLevelAreaSNO = 332339;
- (actor as Portal).Destination.WorldSNO = (int)WorldSno.x1_tristram_adventure_mode_hub;
- (actor as Portal).Destination.StartingPointActorTag = 24;
- }
- }
- else if (actor is Waypoint)
- actor.Destroy();
- #region Активация
- NStone = World.GetActorBySNO(ActorSno._x1_openworld_lootrunobelisk_b);
- NStone.PlayAnimation(5, (AnimationSno)NStone.AnimationSet.TagMapAnimDefault[AnimationSetKeys.Opening]);
- NStone.Attributes[GameAttribute.Team_Override] = (Activated ? -1 : 2);
- NStone.Attributes[GameAttribute.Untargetable] = !Activated;
- NStone.Attributes[GameAttribute.NPC_Is_Operatable] = Activated;
- NStone.Attributes[GameAttribute.Operatable] = Activated;
- NStone.Attributes[GameAttribute.Operatable_Story_Gizmo] = Activated;
- NStone.Attributes[GameAttribute.Disabled] = !Activated;
- NStone.Attributes[GameAttribute.Immunity] = !Activated;
- NStone.Attributes.BroadcastChangedIfRevealed();
-
- NStone.CollFlags = 0;
- World.BroadcastIfRevealed(plr => new ACDCollFlagsMessage
- {
- ActorID = NStone.DynamicID(plr),
- CollFlags = 0
- }, NStone);
- portal = new Portal(World, ActorSno._x1_openworld_tiered_rifts_portal, NewTagMap);
-
- TickTimer AltTimeout = new SecondsTickTimer(World.Game, 3.5f);
- var AltBoom = System.Threading.Tasks.Task.Factory.StartNew(() => WaitToSpawn(AltTimeout));
- AltBoom.ContinueWith(delegate
- {
- portal.EnterWorld(NStone.Position);
- //Quest - 382695 - Великий Нефалемский
- //Quest - 337492 - Просто Нефалемский
-
- //this.ChangeWorld(NephalemPWorld, NephalemPWorld.GetStartingPointById(172).Position);
-
- foreach (var plr in InGameClient.Game.Players.Values)
- {
- plr.InGameClient.SendMessage(new SimpleMessage(Opcodes.RiftStartedMessage));
- plr.InGameClient.SendMessage(new QuestUpdateMessage()
- {
- snoQuest = 337492,
- snoLevelArea = 0x000466E2,
- StepID = -1,
- DisplayButton = true,
- Failed = false
- });
- plr.InGameClient.SendMessage(new QuestCounterMessage()
- {
- snoQuest = 337492,
- snoLevelArea = 0x000466E2,
- StepID = -1,
- Checked = 1,
- Counter = 1
- });
- plr.InGameClient.SendMessage(new QuestUpdateMessage()
- {
- snoQuest = 337492,
- snoLevelArea = 0x000466E2,
- StepID = 13,
- DisplayButton = true,
- Failed = false
- });
- plr.InGameClient.SendMessage(new GameSyncedDataMessage
- {
- SyncedData = new GameSyncedData
- {
- GameSyncedFlags = 6,
- Act = 3000, //act id
- InitialMonsterLevel = InGameClient.Game.InitialMonsterLevel, //InitialMonsterLevel
- MonsterLevel = 0x64E4425E, //MonsterLevel
- RandomWeatherSeed = InGameClient.Game.WeatherSeed, //RandomWeatherSeed
- OpenWorldMode = -1, //OpenWorldMode
- OpenWorldModeAct = -1, //OpenWorldModeAct
- OpenWorldModeParam = -1, //OpenWorldModeParam
- OpenWorldTransitionTime = 0x00000064, //OpenWorldTransitionTime
- OpenWorldDefaultAct = 100, //OpenWorldDefaultAct
- OpenWorldBonusAct = -1, //OpenWorldBonusAct
- SNODungeonFinderLevelArea = 0x00000001, //SNODungeonFinderLevelArea
- LootRunOpen = 44, //LootRunOpen //0 - Великий Портал
- OpenLootRunLevel = 0, //OpenLootRunLevel
- LootRunBossDead = 0, //LootRunBossDead
- HunterPlayerIdx = 0, //HunterPlayerIdx
- LootRunBossActive = -1, //LootRunBossActive
- TieredLootRunFailed = 0, //TieredLootRunFailed
- LootRunChallengeCompleted = 0, //LootRunChallengeCompleted
- SetDungeonActive = 0, //SetDungeonActive
- Pregame = 0, //Pregame
- PregameEnd = 0, //PregameEnd
- RoundStart = 0, //RoundStart
- RoundEnd = 0, //RoundEnd
- PVPGameOver = 0x0, //PVPGameOver
- field_v273 = 0x0,
- TeamWins = new[] { 0x0, 0x0 }, //TeamWins
- TeamScore = new[] { 0x0, 0x0 }, //TeamScore
- PVPGameResult = new[] { 0x0, 0x0 }, //PVPGameResult
- PartyGuideHeroId = 0x0, //PartyGuideHeroId //new EntityId() { High = 0, Low = (long)this.Players.Values.First().Toon.PersistentID }
- TiredRiftPaticipatingHeroID = new long[] { 0x0, 0x0, 0x0, 0x0 }, //TiredRiftPaticipatingHeroID
- }
- });
- plr.InGameClient.SendMessage(new IntDataMessage(Opcodes.DungeonFinderSeedMessage)
- {
- Field0 = 0x3E0FC64C
- });
- plr.InGameClient.SendMessage(new IntDataMessage(Opcodes.DungeonFinderParticipatingPlayerCount)
- {
- Field0 = 1
- });
- plr.InGameClient.SendMessage(new FloatDataMessage(Opcodes.DungeonFinderProgressMessage)
- {
- Field0 = 0
- });
- plr.InGameClient.SendMessage(new SNODataMessage(Opcodes.DungeonFinderSetTimedEvent)
- {
- Field0 = -1
- });
- plr.Attributes[GameAttribute.Tiered_Loot_Run_Death_Count] = 0;
- }
- });
-
-
-
-
- #endregion
-
-
- break;
- #endregion
- }
- }
-
- private void OnTutorialShown(GameClient client, TutorialShownMessage message)
- {
-
- // Server has to save what tutorials are shown, so the player
- // does not have to see them over and over...
- int index = ItemGenerator.Tutorials.IndexOf(message.SNOTutorial);
- if (index == -1) return;
- var seenTutorials = Toon.GameAccount.DBGameAccount.SeenTutorials;
- if(seenTutorials.Length <= 34)
- seenTutorials = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- seenTutorials[index / 8] |= (byte)(1 << (index % 8));
-
- lock (Toon.GameAccount.DBGameAccount)
- {
- var dbGAcc = Toon.GameAccount.DBGameAccount;
- dbGAcc.SeenTutorials = seenTutorials;
- DBSessions.SessionUpdate(dbGAcc);
- }
- //*/
- }
-
- private void OnConfirm(GameClient client, AcceptConfirmMessage message)
- {
- if (ConfirmationResult != null)
- {
- ConfirmationResult.Invoke();
- ConfirmationResult = null;
- }
- }
-
- private void OnSpendParagonPointsMessage(GameClient client, SpendParagonPointsMessage message)
- {
- var bonus = ItemGenerator.GetParagonBonusTable(Toon.Class).Where(b => b.Hash == message.BonusGBID).FirstOrDefault();
-
- if (bonus == null) return;
- if (message.Amount > Attributes[GameAttribute.Paragon_Bonus_Points_Available, bonus.Category]) return;
- //if (this.ParagonBonuses[(bonus.Category * 4) + bonus.Index - 1] + (byte)message.Amount > bonus.Limit) return;
-
- // message.Amount have the value send to add on attr of Paragon tabs.
- ParagonBonuses[(bonus.Category * 4) + bonus.Index - 1] += (ushort)message.Amount;
-
- var dbToon = Toon.DBToon;
- dbToon.ParagonBonuses = ParagonBonuses;
- World.Game.GameDBSession.SessionUpdate(dbToon);
-
- SetAttributesByItems();
- SetAttributesByItemProcs();
- SetAttributesByGems();
- SetAttributesByItemSets();
- SetAttributesByPassives();
- SetAttributesByParagon();
- Attributes.BroadcastChangedIfRevealed();
- UpdatePercentageHP(PercHPbeforeChange);
-
- }
- private void OnResetParagonPointsMessage(GameClient client, ResetParagonPointsMessage message)
- {
- ParagonBonuses = new ushort[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- var dbToon = Toon.DBToon;
- dbToon.ParagonBonuses = ParagonBonuses;
- World.Game.GameDBSession.SessionUpdate(dbToon);
-
- SetAttributesByItems();
- SetAttributesByItemProcs();
- SetAttributesByGems();
- SetAttributesByItemSets();
- SetAttributesByPassives();
- SetAttributesByParagon();
- Attributes.BroadcastChangedIfRevealed();
- UpdatePercentageHP(PercHPbeforeChange);
-
- }
-
- private void OnMailRead(GameClient client, MailReadMessage message)
- {
- //does it make sense?
- }
-
- private void OnMailRetrieve(GameClient client, MailRetrieveMessage message)
- {
- var dbMail = World.Game.GameDBSession.SessionGet((ulong)message.MailId);
- if (dbMail == null || dbMail.DBToon.Id != Toon.PersistentID) return;
- dbMail.Claimed = true;
- World.Game.GameDBSession.SessionUpdate(dbMail);
-
- if (dbMail.ItemGBID != -1)
- Inventory.PickUp(ItemGenerator.CookFromDefinition(World, ItemGenerator.GetItemDefinition(dbMail.ItemGBID), -1, true));
-
- LoadMailData();
- }
-
- private void OnStashIconsAssign(GameClient client, StashIconStateAssignMessage message)
- {
- if (message.StashIcons.Length != 4) return;
- lock (Toon.GameAccount.DBGameAccount)
- {
- var dbGAcc = Toon.GameAccount.DBGameAccount;
- dbGAcc.StashIcons = message.StashIcons;
- DBSessions.SessionUpdate(dbGAcc);
- }
- //LoadStashIconsData();
- }
-
- public void PlayCutscene(int cutsceneId)
- {
- InGameClient.SendMessage(new PlayCutsceneMessage()
- {
- Index = cutsceneId
- });
- }
-
- private void OnTranslateFacing(GameClient client, PlayerTranslateFacingMessage message)
- {
- SetFacingRotation(message.Angle);
-
- World.BroadcastExclusive(plr => new ACDTranslateFacingMessage
- {
- ActorId = DynamicID(plr),
- Angle = message.Angle,
- TurnImmediately = message.TurnImmediately
- }, this);
- }
- private void OnAssignActiveSkill(GameClient client, AssignSkillMessage message)
- {
- var old_skills = SkillSet.ActiveSkills.Select(s => s.snoSkill).ToList();
- foreach (var skill in old_skills)
- {
- PowerScript power = PowerLoader.CreateImplementationForPowerSNO(skill);
- if (power != null && power.EvalTag(PowerKeys.SynergyPower) != -1)
- {
- World.BuffManager.RemoveBuffs(this, power.EvalTag(PowerKeys.SynergyPower));
- }
- }
-
- var oldSNOSkill = SkillSet.ActiveSkills[message.SkillIndex].snoSkill; // find replaced skills SNO.
- if (oldSNOSkill != -1)
- {
- Attributes[GameAttribute.Skill, oldSNOSkill] = 0;
- World.BuffManager.RemoveBuffs(this, oldSNOSkill);
-
- var rem = new List();
- foreach (var fol in Followers.Where(f => World.GetActorByGlobalId(f.Key) == null || World.GetActorByGlobalId(f.Key).Attributes[GameAttribute.Summoned_By_SNO] == oldSNOSkill))
- rem.Add(fol.Key);
- foreach (var rm in rem)
- DestroyFollowerById(rm);
- }
-
- Attributes[GameAttribute.Skill, message.SNOSkill] = 1;
- //scripted //this.Attributes[GameAttribute.Skill_Total, message.SNOSkill] = 1;
- SkillSet.ActiveSkills[message.SkillIndex].snoSkill = message.SNOSkill;
- SkillSet.ActiveSkills[message.SkillIndex].snoRune = message.RuneIndex;
- SkillSet.SwitchUpdateSkills(message.SkillIndex, message.SNOSkill, message.RuneIndex, Toon);
- SetAttributesSkillSets();
-
- Attributes.BroadcastChangedIfRevealed();
- UpdateHeroState();
-
- var cooldownskill = SkillSet.ActiveSkills.GetValue(message.SkillIndex);
-
- if (SkillSet.HasSkill(460757))
- foreach (var skill in SkillSet.ActiveSkills)
- if (skill.snoSkill == 460757)
- if (skill.snoRune == 3)
- World.BuffManager.AddBuff(this, this, new P6_Necro_Devour_Aura());
- else
- World.BuffManager.RemoveBuffs(this, 474325);
-
- if (SkillSet.HasSkill(460870))
- foreach (var skill in SkillSet.ActiveSkills)
- if (skill.snoSkill == 460870)
- if (skill.snoRune == 4)
- World.BuffManager.AddBuff(this, this, new P6_Necro_Frailty_Aura());
- else
- World.BuffManager.RemoveBuffs(this, 473992);
-
-
- //_StartSkillCooldown((cooldownskill as ActiveSkillSavedData).snoSkill, SkillChangeCooldownLength);
- }
- private void OnAssignPassiveSkills(GameClient client, AssignTraitsMessage message)
- {
- for (int i = 0; i < message.SNOPowers.Length; ++i)
- {
- int oldSNOSkill = SkillSet.PassiveSkills[i]; // find replaced skills SNO.
- if (message.SNOPowers[i] != oldSNOSkill)
- {
- if (oldSNOSkill != -1)
- {
- World.BuffManager.RemoveAllBuffs(this);
- // switch off old passive skill
- Attributes[GameAttribute.Trait, oldSNOSkill] = 0;
- Attributes[GameAttribute.Skill, oldSNOSkill] = 0;
- //scripted //this.Attributes[GameAttribute.Skill_Total, oldSNOSkill] = 0;
- }
-
- if (message.SNOPowers[i] != -1)
- {
- // switch on new passive skill
- Attributes[GameAttribute.Trait, message.SNOPowers[i]] = 1;
- Attributes[GameAttribute.Skill, message.SNOPowers[i]] = 1;
- //scripted //this.Attributes[GameAttribute.Skill_Total, message.SNOPowers[i]] = 1;
- }
-
- SkillSet.PassiveSkills[i] = message.SNOPowers[i];
- }
- }
-
- SkillSet.UpdatePassiveSkills(Toon);
-
- var skills = SkillSet.ActiveSkills.Select(s => s.snoSkill).ToList();
- foreach (var skill in skills)
- _StartSkillCooldown(skill, SkillChangeCooldownLength);
-
- SetAttributesByItems();
- SetAttributesByGems();
- SetAttributesByItemSets();
- SetAttributesByPassives();
- SetAttributesByParagon();
- SetAttributesSkillSets();
- Inventory.CheckWeapons(); //Handles removal of Heavenly Strength
- Attributes.BroadcastChangedIfRevealed();
- UpdateHeroState();
- UpdatePercentageHP(PercHPbeforeChange);
-
- }
- private void OnUnassignActiveSkill(GameClient client, UnassignSkillMessage message)
- {
- var oldSNOSkill = SkillSet.ActiveSkills[message.SkillIndex].snoSkill; // find replaced skills SNO.
- if (oldSNOSkill != -1)
- {
- Attributes[GameAttribute.Skill, oldSNOSkill] = 0;
- World.BuffManager.RemoveBuffs(this, oldSNOSkill);
-
- var rem = new List();
- foreach (var fol in Followers.Where(f => World.GetActorByGlobalId(f.Key).Attributes[GameAttribute.Summoned_By_SNO] == oldSNOSkill))
- rem.Add(fol.Key);
- foreach (var rm in rem)
- DestroyFollowerById(rm);
- }
-
- SkillSet.ActiveSkills[message.SkillIndex].snoSkill = -1;
- SkillSet.ActiveSkills[message.SkillIndex].snoRune = -1;
- SkillSet.SwitchUpdateSkills(message.SkillIndex, -1, -1, Toon);
- SetAttributesSkillSets();
-
- Attributes.BroadcastChangedIfRevealed();
- UpdateHeroState();
- }
- public void SetNewAttributes()
- {
- //this.Attributes[GameAttribute.Attacks_Per_Second] = 1.0f;
- //this.Attributes[GameAttribute.Attacks_Per_Second_Bonus] = 1.0f;
- //this.Attributes[GameAttribute.Gold] = 1;
- //[GameAttribute.Damage_Weapon_Min_Total, 0]
- Attributes[GameAttribute.Attacks_Per_Second_Percent] = 0;
- Attributes[GameAttribute.Attacks_Per_Second_Percent_Uncapped] = 0;
- Attributes[GameAttribute.Attacks_Per_Second_Percent_Reduction] = 0;
- Attributes[GameAttribute.Attacks_Per_Second_Percent_Cap] = 0;
- //this.Attributes[GameAttribute.Gold_PickUp_Radius] = 5f;
- /*
- this.Attributes[GameAttribute.Experience_Bonus_Percent_Anniversary_Buff] = 100;
- this.Attributes[GameAttribute.Experience_Bonus_Percent_Community_Buff] = 100;
- this.Attributes[GameAttribute.Experience_Bonus_Percent_Handicap] = 100;
- this.Attributes[GameAttribute.Experience_Bonus_Percent_IGR_Buff] = 100;
- this.Attributes[GameAttribute.Experience_Bonus_Percent_Potion_Buff] = 1;
- //*/
- /*
- this.InGameClient.SendMessage(new PlayerSkillsMessage()
- {
- PlayerIndex = this.PlayerIndex,
- ActiveSkills = this.SkillSet.ActiveSkills,
- Traits = new int[4] { 0x00032E5E, -1, -1, -1 },
- LegendaryPowers = new int[4] { -1, -1, -1, -1 }
- });
- //*/
-
- }
- private void _StartSkillCooldown(int snoPower, float seconds)
- {
- World.BuffManager.AddBuff(this, this,
- new CooldownBuff(snoPower, seconds));
- }
-
- //private void OnPlayerChangeHotbarButtonMessage(GameClient client, PlayerChangeHotbarButtonMessage message)
- //{
- // this.SkillSet.HotBarSkills[message.BarIndex] = message.ButtonData;
- //}
-
- private void OnObjectTargeted(GameClient client, TargetMessage message)
- {
- if (message.TargetID != 0xffffffff)
- message.TargetID = World.GetGlobalId(this, message.TargetID);
-
- if (Toon.Class == ToonClass.Crusader)
- if (World.BuffManager.HasBuff(this)) //Crusader -> cancel Steed Charge
- World.BuffManager.RemoveBuffs(this, 243853);
-
- bool powerHandled = World.PowerManager.RunPower(this, message.PowerSNO, message.TargetID, message.Place.Position, message);
-
- if (!powerHandled)
- {
- Actor actor = World.GetActorByGlobalId(message.TargetID);
- if (actor == null) return;
-
-
-
-#if DEBUG
- Logger.Warn("OnTargetedActor ID: {0}, Name: {1}, NumInWorld: {2}", actor.SNO, actor.Name, actor.NumberInWorld);
-#else
-
-#endif
- if ((actor.GBHandle.Type == 1) && (actor.Attributes[GameAttribute.TeamID] == 10))
- {
- ExpBonusData.MonsterAttacked(InGameClient.Game.TickCounter);
- }
- actor.OnTargeted(this, message);
-
-
- }
-
- ExpBonusData.Check(2);
- }
-
- private int _hackCounter = 0;
-
- public bool SpeedCheckDisabled = false;
-
- public static byte[] StringToByteArray(string hex)
- {
- return Enumerable.Range(0, hex.Length)
- .Where(x => x % 2 == 0)
- .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
- .ToArray();
- }
- public int i = 0;
-
- private void OnPlayerMovement(GameClient client, ACDClientTranslateMessage message)
- {
- Attributes.BroadcastChangedIfRevealed();
- var a = GetActorsInRange(15f);
-
- #region
- //UpdateExp(5000000);
- /*
- this.Attributes[GameAttribute.Jewel_Upgrades_Max] = 3;
- this.Attributes[GameAttribute.Jewel_Upgrades_Bonus] = 2;
- this.Attributes[GameAttribute.Jewel_Upgrades_Used] = 0;
- Attributes[GameAttribute.Currencies_Discovered] = 20;
- this.Attributes.BroadcastChangedIfRevealed();
- var Quest = DiIiS_NA.Core.MPQ.MPQStorage.Data.Assets[Core.Types.SNO.SNOGroup.Quest][337492].Data;
- //*/
- //this.Toon.BigPortalKey++;
- //this.Toon.CraftItem4++;
- /*
- //Приглашение на великий портал
- InGameClient.SendMessage(new MessageSystem.Message.Definitions.Encounter.RiftJoinMessage()
- {
- PlayerIndex = 0,
- RiftStartServerTime = this.InGameClient.Game.TickCounter,
- RiftTier = 0
- });
- /*
- //Результаты прохождения подземелья
- InGameClient.SendMessage(new MessageSystem.Message.Definitions.Dungeon.SetDungeonResultsMessage()
- {
- SNOQuestKill = -1,
- QuestKillMonsterCounter = 0,
- SNOQuestBonus1 = -1,
- QuestBonus1Success = false,
- SNOQuestBonus2 = -1,
- QuestBonus2Success = false,
- SNOQuestMastery = -1,
- QuestMasterySuccess = false,
- QuestKillSuccess = false,
- ShowTotalTime = true,
- TimeTaken = 120,
- TargetTime = 200
- });
- /*
- //Приглашение в комплектное подземелье
- InGameClient.SendMessage(new MessageSystem.Message.Definitions.Dungeon.SetDungeonDialogMessage()
- {
- PlayerIndex = 0,
- LabelDescription = 1,
- LabelTitle = 1
- }) ;
- /*
- InGameClient.SendMessage(new BroadcastTextMessage()
- {
- Field0 = "Тест"
- });
- /*
- this.InGameClient.SendMessage(new DisplayGameTextMessage(Opcodes.DisplayGameTextMessage)
- {
- Message = "Пампам"
- });
- //*/
-
- #endregion
- if (World == null) return;
-
- if (Dead)
- {
- World.BroadcastIfRevealed(ACDWorldPositionMessage, this);
- return;
- }
-
- if (World.Game.Paused || BetweenWorlds) return;
-
- if (message.MovementSpeed > (Attributes[GameAttribute.Running_Rate_Total] * 1.5f) && !SpeedCheckDisabled)
- {
- _hackCounter++;
- if (_hackCounter > 5)
- {
- _hackCounter = 0;
- }
- World.BroadcastIfRevealed(ACDWorldPositionMessage, this);
- return;
- }
-
- if (message.Position != null)
- {
- if (PowerMath.Distance2D(message.Position, Position) > 300f)
- {
- World.BroadcastIfRevealed(ACDWorldPositionMessage, this);
- InGameClient.SendMessage(new ACDTranslateSyncMessage()
- {
- ActorId = DynamicID(this),
- Position = Position
- });
- return;
- }
- Position = message.Position;
- }
-
- SetFacingRotation(message.Angle);
-
- if (IsCasting) StopCasting();
- World.BuffManager.RemoveBuffs(this, 298038);
-
- RevealScenesToPlayer();
- RevealPlayersToPlayer();
- RevealActorsToPlayer();
-
- World.BroadcastExclusive(plr => new ACDTranslateNormalMessage
- {
- ActorId = DynamicID(plr),
- Position = Position,
- Angle = message.Angle,
- SnapFacing = false,
- MovementSpeed = message.MovementSpeed,
- AnimationTag = message.AnimationTag
- }, this, true);
-
- foreach (var actor in GetActorsInRange())
- actor.OnPlayerApproaching(this);
-
- VacuumPickup();
- if (World.Game.OnLoadWorldActions.ContainsKey(World.SNO))
- {
- Logger.Debug("OnLoadWorldActions: {0}", World.SNO);
- lock (World.Game.OnLoadWorldActions[World.SNO])
- {
- try
- {
- foreach (var action in World.Game.OnLoadWorldActions[World.SNO])
- {
- action.Invoke();
- }
- }
- catch { }
- World.Game.OnLoadWorldActions[World.SNO].Clear();
- }
- }
- if (World.Game.OnLoadSceneActions.ContainsKey(CurrentScene.SceneSNO.Id))
- {
- Logger.Debug("OnLoadSceneActions: {0}", CurrentScene.SceneSNO.Id);
- lock (World.Game.OnLoadSceneActions[CurrentScene.SceneSNO.Id])
- {
- try
- {
- foreach (var action in World.Game.OnLoadSceneActions[CurrentScene.SceneSNO.Id])
- {
- action.Invoke();
- }
- }
- catch { }
- World.Game.OnLoadSceneActions[CurrentScene.SceneSNO.Id].Clear();
- }
- }
-
- if (CurrentScene.SceneSNO.Id != PreSceneId)
- {
- PreSceneId = CurrentScene.SceneSNO.Id;
- var levelArea = CurrentScene.Specification.SNOLevelAreas[0];
- if (World.Game.QuestProgress.QuestTriggers.ContainsKey(levelArea)) //EnterLevelArea
- {
- var trigger = World.Game.QuestProgress.QuestTriggers[levelArea];
- if (trigger.triggerType == DiIiS_NA.Core.MPQ.FileFormats.QuestStepObjectiveType.EnterLevelArea)
- {
- try
- {
- trigger.questEvent.Execute(World); // launch a questEvent
- }
- catch (Exception e)
- {
- Logger.WarnException(e, "questEvent()");
- }
- }
- }
-
- Attributes[GameAttribute.Corpse_Resurrection_Charges] = 3; // Reset resurrection charges on zone change (TODO: do not reset charges on reentering the same zone)
-
-#if DEBUG
- Logger.Warn("Player Location {0}, Scene: {1} SNO: {2} LevelArea: {3}", Toon.Name, CurrentScene.SceneSNO.Name, CurrentScene.SceneSNO.Id, CurrentScene.Specification.SNOLevelAreas[0]);
-#else
-
-#endif
- }
- LastMovementTick = World.Game.TickCounter;
- }
-
- private void OnCancelChanneledSkill(GameClient client, CancelChanneledSkillMessage message)
- {
- World.PowerManager.CancelChanneledSkill(this, message.PowerSNO);
- }
-
- private void OnRequestBuffCancel(GameClient client, RequestBuffCancelMessage message)
- {
- World.BuffManager.RemoveBuffs(this, message.PowerSNOId);
- }
-
- private void OnSecondaryPowerMessage(GameClient client, SecondaryAnimationPowerMessage message)
- {
- World.PowerManager.RunPower(this, message.PowerSNO, (uint)message.annTarget);
- }
-
- private void OnMiscPowerMessage(GameClient client, MiscPowerMessage message)
- {
- World.PowerManager.RunPower(this, message.PowerSNO);
- }
-
- private void OnLoopingAnimationPowerMessage(GameClient client, LoopingAnimationPowerMessage message)
- {
- StartCasting(150, new Action(() => {
- try
- {
- World.PowerManager.RunPower(this, message.snoPower);
- }
- catch { }
- }),message.snoPower);
- }
-
- private void OnTryWaypoint(GameClient client, TryWaypointMessage tryWaypointMessage)
- {
- var wpWorld = World.Game.GetWayPointWorldById(tryWaypointMessage.nWaypoint);
- var wayPoint = wpWorld.GetWayPointById(tryWaypointMessage.nWaypoint);
- if (wayPoint == null) return;
- Logger.Debug("---Waypoint Debug---");
- var proximity = new RectangleF(wayPoint.Position.X - 1f, wayPoint.Position.Y - 1f, 2f, 2f);
- var scenes = wpWorld.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];
- Logger.Debug($"OnTryWaypoint: Id: {tryWaypointMessage.nWaypoint}, WorldId: {wpWorld.SNO}, levelArea: {levelArea}");
- Logger.Debug($"WpWorld: {wpWorld}, wayPoint: {wayPoint}");
- InGameClient.SendMessage(new SimpleMessage(Opcodes.LoadingWarping));
- if (wpWorld == World)
- Teleport(wayPoint.Position);
- else
- ChangeWorld(wpWorld, wayPoint.Position);
-
- //handling quest triggers
- if (World.Game.QuestProgress.QuestTriggers.ContainsKey(levelArea)) //EnterLevelArea
- {
- var trigger = World.Game.QuestProgress.QuestTriggers[levelArea];
- if (trigger.triggerType == DiIiS_NA.Core.MPQ.FileFormats.QuestStepObjectiveType.EnterLevelArea)
- {
- try
- {
- trigger.questEvent.Execute(World); // launch a questEvent
- }
- catch (Exception e)
- {
- Logger.WarnException(e, "questEvent()");
- }
- }
- }
- foreach (var bounty in World.Game.QuestManager.Bounties)
- bounty.CheckLevelArea(levelArea);
-
- InGameClient.SendMessage(new PortedToWaypointMessage
- {
- PlayerIndex = PlayerIndex,
- LevelAreaSNO = levelArea
- });
- Logger.Debug("---Waypoint Debug End---");
- }
- public void RefreshReveal()
- {
- float range = 200f;
- if (InGameClient.Game.CurrentEncounter.activated)
- range = 360f;
-
- foreach (var actor in GetActorsInRange(range).Where(actor => actor is not Player))
- actor.Unreveal(this);
- RevealActorsToPlayer();
- }
- private void OnRequestBuyItem(GameClient client, RequestBuyItemMessage requestBuyItemMessage)
- {
- var vendor = SelectedNPC as Vendor;
- if (vendor == null)
- return;
- vendor.OnRequestBuyItem(this, requestBuyItemMessage.ItemId);
- }
-
- private void OnRequestSellItem(GameClient client, RequestSellItemMessage requestSellItemMessage)
- {
- var vendor = SelectedNPC as Vendor;
- if (vendor == null)
- return;
- vendor.OnRequestSellItem(this, (int)requestSellItemMessage.ItemId);
- }
-
- private void OnHirelingRetrainMessage()
- {
- if (ActiveHireling == null) return;
-
- switch (ActiveHireling.Attributes[GameAttribute.Hireling_Class])
- {
- case 1:
- if (ActiveHireling is Templar)
- (ActiveHireling as Templar).Retrain(this);
- break;
- case 2:
- if (ActiveHireling is Scoundrel)
- (ActiveHireling as Scoundrel).Retrain(this);
- break;
- case 3:
- if (ActiveHireling is Enchantress)
- (ActiveHireling as Enchantress).Retrain(this);
- break;
- default:
- return;
- }
- }
- //*
- private void OnHirelingDismiss(GameClient client, PetAwayMessage message)
- {
- Logger.Trace("OnPetDismiss(): {0}", message.ActorID);
- var petId = World.GetGlobalId(this, message.ActorID);
- var pet = World.GetActorByGlobalId(petId);
- if (pet is Hireling)
- ActiveHireling = null;
- else
- DestroyFollowersBySnoId(pet.SNO);
- }
- private void OnHirelingRequestLearnSkill(GameClient client, HirelingRequestLearnSkillMessage message)
- {
- Logger.Debug("OnHirelingRequestLearnSkill(): {0} - {1}", message.HirelingID, message.PowerSNOId);
- var hireling = World.GetActorByGlobalId(World.GetGlobalId(this, message.HirelingID));
- if (hireling == null) return;
- switch (hireling.Attributes[GameAttribute.Hireling_Class])
- {
- case 1:
- if (!(hireling is Templar)) return;
- (hireling as Templar).SetSkill(this, message.PowerSNOId);
- break;
- case 2:
- if (!(hireling is Scoundrel)) return;
- (hireling as Scoundrel).SetSkill(this, message.PowerSNOId);
- break;
- case 3:
- if (!(hireling is Enchantress)) return;
- (hireling as Enchantress).SetSkill(this, message.PowerSNOId);
- break;
- default:
- break;
- }
- }
- //*/
- private void OnResurrectOption(GameClient client, RessurectionPlayerMessage message)
- {
- Logger.Trace("Resurrect option: {0}", message.Choice);
- switch (message.Choice)
- {
- case 0:
- Revive(Position);
- ChangeWorld(World.Game.StartingWorld, World.Game.StartPosition);
- break;
- case 1:
- Revive(CheckPointPosition);
- break;
- case 2:
- if (Attributes[GameAttribute.Corpse_Resurrection_Charges] > 0)
- {
- Revive(Position);
- Attributes[GameAttribute.Corpse_Resurrection_Charges]--;
- }
- break;
- }
- }
- //*/
- private void OnEquipPotion(GameClient client, ChangeUsableItemMessage message)
- {
- var activeSkills = Toon.DBActiveSkills;
- activeSkills.PotionGBID = message.Field1;
- World.Game.GameDBSession.SessionUpdate(activeSkills);
- }
-
- public void ToonStateChanged()
- {
- try
- {
- ClientSystem.GameServer.GSBackend.ToonStateChanged(Toon.PersistentID);
- }
- catch (Exception e)
- {
- Logger.WarnException(e, "Exception on ToonStateChanged(): ");
- }
- }
-
- private void OnArtisanWindowClosed()
- {
- CurrentArtisan = null;
- }
- //*
- private void TrainArtisan(GameClient client, RequestTrainArtisanMessage message)
- {
- if (CurrentArtisan == null || !artisanTrainHelpers.ContainsKey(CurrentArtisan.Value)) {
- Logger.Warn("Training for artisan {} is not supported", CurrentArtisan);
- return;
- }
-
- var trainHelper = artisanTrainHelpers[CurrentArtisan.Value];
- if (trainHelper.HasMaxLevel)
- return;
-
- var recipeDefinition = ItemGenerator.GetRecipeDefinition(trainHelper.TrainRecipeName);
- if (Inventory.GetGoldAmount() < recipeDefinition.Gold)
- return;
-
- var requiredIngridients = recipeDefinition.Ingredients.Where(x => x.ItemsGBID > 0);
- // FIXME: Inventory.HaveEnough doesn't work for some craft consumables
- var haveEnoughIngredients = requiredIngridients.All(x => Inventory.HaveEnough(x.ItemsGBID, x.Count));
- if (!haveEnoughIngredients)
- return;
-
- Inventory.RemoveGoldAmount(recipeDefinition.Gold);
- foreach (var ingr in requiredIngridients)
- {
- // FIXME: Inventory.GrabSomeItems doesn't work for some craft consumables
- Inventory.GrabSomeItems(ingr.ItemsGBID, ingr.Count);
+ private static readonly Logger Logger = LogManager.CreateLogger();
+
+ ///
+ /// The ingame-client for player.
+ ///
+ public GameClient InGameClient { get; set; }
+
+ ///
+ /// The player index.
+ ///
+ public int PlayerIndex { get; private set; }
+
+ ///
+ /// The player index.
+ ///
+ public int PlayerGroupIndex { get; private set; }
+
+ ///
+ /// Current crafting NPC type(for learning recipes)
+ ///
+ public ArtisanType? CurrentArtisan { get; set; }
+
+ ///
+ /// The player's toon.
+ /// We need a better name /raist.
+ ///
+ public Toon Toon { get; private set; }
+
+ public float DecreaseUseResourcePercent = 0;
+ public int Level { get; private set; }
+ public int ParagonLevel { get; private set; }
+ public long ExperienceNext { get; private set; }
+ public List Revived = new() { };
+
+ public bool LevelingBoosted { get; set; }
+
+ public int PreSceneId = -1;
+
+ public List NecroSkeletons = new() { };
+ public bool ActiveSkeletons = false;
+ public Actor ActiveGolem = null;
+ public bool EnableGolem = false;
+
+ public bool IsInPvPWorld
+ {
+ get => World != null && World.IsPvP;
+ set { }
+ }
+
+ ///
+ /// Skillset for the player (or actually for player's toons class).
+ ///
+ public SkillSet SkillSet { get; private set; }
+
+ ///
+ /// The inventory of player's toon.
+ ///
+ public Inventory Inventory { get; private set; }
+
+ public int GearScore
+ {
+ get
+ {
+ if (Inventory == null)
+ return 0;
+ else
+ return Inventory.GetGearScore();
+ }
+ private set { }
+ }
+
+ public Actor PlayerDirectBanner = null;
+
+ public uint NewDynamicID(uint globalId, int pIndex = -1)
+ {
+ lock (RevealedObjects)
+ {
+ if (pIndex > -1)
+ return (uint)pIndex;
+ for (uint i = 9; i < 4123; i++)
+ if (!RevealedObjects.ContainsValue(i))
+ //Logger.Trace("adding GlobalId {0} -> DynID {1} to player {2}", globalId, i, this.Toon.Name);
+ return i;
+ return 0;
+ }
+ }
+
+ ///
+ /// ActorType = Player.
+ ///
+ public override ActorType ActorType => ActorType.Player;
+
+ ///
+ /// Revealed objects to player.
+ ///
+ public Dictionary RevealedObjects = new();
+
+ public ConversationManager Conversations { get; private set; }
+
+ public int SpecialComboIndex = 0;
+
+ // Collection of items that only the player can see. This is only used when items drop from killing an actor
+ // TODO: Might want to just have a field on the item itself to indicate whether it is visible to only one player
+ ///
+ /// Dropped items for the player
+ ///
+ public Dictionary GroundItems { get; private set; }
+
+ ///
+ /// Everything connected to ExpBonuses.
+ ///
+ public ExpBonusData ExpBonusData { get; private set; }
+
+ public bool EventWeatherEnabled { get; set; }
+
+ public bool BlacksmithUnlocked { get; set; }
+ public bool JewelerUnlocked { get; set; }
+ public bool MysticUnlocked { get; set; }
+ public bool KanaiUnlocked { get; set; }
+
+ public bool HirelingTemplarUnlocked { get; set; }
+ public bool HirelingScoundrelUnlocked { get; set; }
+ public bool HirelingEnchantressUnlocked { get; set; }
+
+ public int LastMovementTick = 0;
+
+ public int _spiritGenHit = 0;
+
+ public int _SpiritGeneratorHit
+ {
+ get => _spiritGenHit;
+
+ set
+ {
+ _spiritGenHit = value;
+ if (SkillSet.HasPassive(315271) && _spiritGenHit >= 3) //Mythic Rhythm
+ {
+ World.BuffManager.AddBuff(this, this, new MythicRhythmBuff());
+ _spiritGenHit = 0;
+ }
+ }
+ }
+
+ ///
+ /// NPC currently interaced with
+ ///
+ public InteractiveNPC SelectedNPC { get; set; }
+
+ public Dictionary Followers { get; private set; }
+ private Hireling _activeHireling = null;
+ private Hireling _questHireling = null;
+
+ public Hireling ActiveHireling
+ {
+ get => _activeHireling;
+ set
+ {
+ if (value == null)
+ {
+ HirelingId = null;
+ lock (Toon.DBToon)
+ {
+ var dbToon = Toon.DBToon;
+ dbToon.ActiveHireling = null;
+ DBSessions.SessionUpdate(dbToon);
+ }
+ }
+ else if (value != _activeHireling)
+ {
+ HirelingId = value.Attributes[GameAttribute.Hireling_Class];
+ lock (Toon.DBToon)
+ {
+ var dbToon = Toon.DBToon;
+ dbToon.ActiveHireling = value.Attributes[GameAttribute.Hireling_Class];
+ DBSessions.SessionUpdate(dbToon);
+ }
}
- trainHelper.DbRef.Level++;
- World.Game.GameDBSession.SessionUpdate(trainHelper.DbRef);
+ if (value == _activeHireling && value != null)
+ return;
- if (trainHelper.Achievement is not null)
- GrantAchievement(trainHelper.Achievement.Value);
- if (trainHelper.Criteria is not null)
- GrantCriteria(trainHelper.Criteria.Value);
+ if (_activeHireling != null) _activeHireling.Dismiss();
- if (artisanTrainHelpers.All(x => x.Value.HasMaxLevel))
- GrantCriteria(74987249993545);
+ _activeHireling = value;
+ }
+ }
- client.SendMessage(new CrafterLevelUpMessage
+ public Hireling QuestHireling
+ {
+ get => _questHireling;
+ set
+ {
+ if (_questHireling != null) _questHireling.Dismiss();
+ _questHireling = value;
+ }
+ }
+
+ public int CurrentWingsPowerId = -1;
+ private int _lastResourceUpdateTick;
+ private float _CurrentHPValue = -1f;
+ private float _CurrentResourceValue = -1f;
+ public int GoldCollectedTempCount = 0;
+ public int BloodShardsCollectedTempCount = 0;
+ public int KilledMonstersTempCount = 0;
+ public int KilledSeasonalTempCount = 0;
+ public int KilledElitesTempCount = 0;
+ public int BuffStreakKill = 0;
+ private ushort[] ParagonBonuses;
+ public int? HirelingId = null;
+ public bool IsCasting = false;
+ private Action CastResult = null;
+ private Action ConfirmationResult = null;
+ private const float SkillChangeCooldownLength = 10f;
+
+ ///
+ /// Creates a new player.
+ ///
+ /// The initial world player joins in.
+ /// The gameclient for the player.
+ /// Toon of the player.
+ public Player(World world, GameClient client, Toon bnetToon)
+ : base(world,
+ bnetToon.Gender == 0
+ ? (ActorSno)bnetToon.HeroTable.SNOMaleActor
+ : (ActorSno)bnetToon.HeroTable.SNOFemaleActor)
+ {
+ InGameClient = client;
+ PlayerIndex = Interlocked.Increment(ref InGameClient.Game.PlayerIndexCounter);
+ PlayerGroupIndex = InGameClient.Game.PlayerGroupIndexCounter;
+ Toon = bnetToon;
+ LevelingBoosted = Toon.LevelingBoosted;
+ var dbToon = Toon.DBToon;
+ HirelingId = dbToon.ActiveHireling;
+ GBHandle.Type = (int)ActorType.Player;
+ GBHandle.GBID = Toon.ClassID;
+ Level = dbToon.Level;
+ ParagonLevel = Toon.ParagonLevel;
+ ExperienceNext = Toon.ExperienceNext;
+ ParagonBonuses = dbToon.ParagonBonuses;
+ CurrentWingsPowerId = dbToon.WingsActive;
+
+ Field2 = 0x00000009;
+ Scale = ModelScale;
+ RotationW = 0.05940768f;
+ RotationAxis = new Vector3D(0f, 0f, 0.9982339f);
+ Field7 = -1;
+ NameSNO = ActorSno.__NONE;
+ Field10 = 0x0;
+ Dead = false;
+ EventWeatherEnabled = false;
+
+ var achievements =
+ InGameClient.Game.GameDBSession.SessionQueryWhere(dba =>
+ dba.DBGameAccount.Id == Toon.GameAccount.PersistentID);
+
+ BlacksmithUnlocked = achievements.Any(dba => dba.AchievementId == 74987243307766);
+ JewelerUnlocked = achievements.Any(dba => dba.AchievementId == 74987243307780);
+ MysticUnlocked = achievements.Any(dba => dba.AchievementId == 74987247205955);
+
+ KanaiUnlocked = achievements.Where(dba => dba.AchievementId == 74987254626662)
+ .SelectMany(x => AchievementSystem.AchievementManager.UnserializeBytes(x.Criteria))
+ .Any(x => x == unchecked((uint)74987252674266));
+
+ if (Level >= 70)
+ GrantCriteria(74987254853541);
+
+ HirelingTemplarUnlocked = achievements.Any(dba => dba.AchievementId == 74987243307073);
+ HirelingScoundrelUnlocked = achievements.Any(dba => dba.AchievementId == 74987243307147);
+ HirelingEnchantressUnlocked = achievements.Any(dba => dba.AchievementId == 74987243307145);
+ SkillSet = new SkillSet(this, Toon.Class, Toon);
+ GroundItems = new Dictionary();
+ Followers = new Dictionary();
+ Conversations = new ConversationManager(this);
+ ExpBonusData = new ExpBonusData(this);
+ SelectedNPC = null;
+
+ _lastResourceUpdateTick = 0;
+ SavePointData = new SavePointData() { snoWorld = -1, SavepointId = -1 };
+
+ // Attributes
+ if (World.Game.PvP)
+ Attributes[GameAttribute.TeamID] = PlayerIndex + 2;
+ else
+ Attributes[GameAttribute.TeamID] = 2;
+
+ //make sure if greater is not active enable banner.
+ if (!World.Game.NephalemGreater) Attributes[GameAttribute.Banner_Usable] = true;
+ SetAllStatsInCorrectOrder();
+ // Enabled stone of recall
+ if (!World.Game.PvP & Toon.StoneOfPortal)
+ EnableStoneOfRecall();
+ else if (InGameClient.Game.CurrentAct == 3000)
+ EnableStoneOfRecall();
+
+ var lores = UnserializeBytes(Toon.DBToon.Lore);
+ var num = 0;
+ foreach (var lore in lores)
+ {
+ LearnedLore.m_snoLoreLearned[num] = lore;
+ num++;
+ }
+
+ LearnedLore.Count = lores.Count();
+
+ Attributes[GameAttribute.Hitpoints_Cur] = Attributes[GameAttribute.Hitpoints_Max_Total];
+ Attributes.BroadcastChangedIfRevealed();
+ }
+
+ #region Attribute Setters
+
+ public void SetAllStatsInCorrectOrder()
+ {
+ SetAttributesSkills();
+ SetAttributesBuffs();
+ SetAttributesDamage();
+ SetAttributesRessources();
+ SetAttributesClassSpecific();
+ SetAttributesMovement();
+ SetAttributesMisc();
+ SetAttributesOther();
+ if (Inventory == null)
+ Inventory = new Inventory(this);
+ SetAttributesByItems(); //needs the Inventory
+ SetAttributesByItemProcs();
+ SetAttributesByGems();
+ SetAttributesByItemSets();
+ if (SkillSet == null)
+ SkillSet = new SkillSet(this, Toon.Class, Toon);
+ SetAttributesByPassives(); //needs the SkillSet
+ SetAttributesByParagon();
+ SetNewAttributes();
+ UpdatePercentageHP(PercHPbeforeChange);
+ }
+
+ public void SetAttributesSkills()
+ {
+ //Skills
+ Attributes[GameAttribute.SkillKit] = Toon.HeroTable.SNOSKillKit0;
+
+ Attributes[GameAttribute.Buff_Icon_Start_Tick0, 0x00033C40] = 153;
+ Attributes[GameAttribute.Buff_Icon_End_Tick0, 0x00033C40] = 3753;
+ Attributes[GameAttribute.Buff_Icon_Count0, 0x0006B48E] = 1;
+ Attributes[GameAttribute.Buff_Icon_Count0, 0x0004601B] = 1;
+ Attributes[GameAttribute.Buff_Icon_Count0, 0x00033C40] = 1;
+
+ Attributes[GameAttribute.Currencies_Discovered] = 0x0011FFF8;
+
+ Attributes[GameAttribute.Skill, 30592] = 1;
+ Attributes[GameAttribute.Resource_Degeneration_Prevented] = false;
+ Attributes[GameAttribute.Resource_Degeneration_Stop_Point] = 0;
+ //scripted //this.Attributes[GameAttribute.Skill_Total, 0x7545] = 1; //Axe Operate Gizmo
+ //scripted //this.Attributes[GameAttribute.Skill_Total, 0x76B7] = 1; //Punch!
+ //scripted //this.Attributes[GameAttribute.Skill_Total, 0x6DF] = 1; //Use Item
+ //scripted //this.Attributes[GameAttribute.Skill_Total, 0x7780] = 1; //Basic Attack
+ //scripted //this.Attributes[GameAttribute.Skill_Total, 0xFFFFF] = 1;
+ //this.Attributes[GameAttribute.Skill, 0xFFFFF] = 1;
+ }
+
+ public void SetAttributesBuffs()
+ {
+ //Buffs
+ Attributes[GameAttribute.Buff_Exclusive_Type_Active, 0x33C40] = true;
+ Attributes[GameAttribute.Buff_Icon_End_Tick0, 0x00033C40] = 0x000003FB;
+ Attributes[GameAttribute.Buff_Icon_Start_Tick0, 0x00033C40] = 0x00000077;
+ Attributes[GameAttribute.Buff_Icon_Count0, 0x00033C40] = 1;
+ Attributes[GameAttribute.Buff_Exclusive_Type_Active, 0xCE11] = true;
+ Attributes[GameAttribute.Buff_Icon_Count0, 0x0000CE11] = 1;
+ Attributes[GameAttribute.Buff_Visual_Effect, 0xFFFFF] = true;
+ //Wings
+ if (CurrentWingsPowerId != -1)
+ {
+ Attributes[GameAttribute.Buff_Exclusive_Type_Active, CurrentWingsPowerId] = true;
+ Attributes[GameAttribute.Power_Buff_0_Visual_Effect_None, CurrentWingsPowerId] = true;
+ Attributes[GameAttribute.Buff_Icon_Start_Tick0, CurrentWingsPowerId] = 0;
+ Attributes[GameAttribute.Buff_Icon_End_Tick0, CurrentWingsPowerId] = 100;
+ Attributes[GameAttribute.Buff_Icon_Count0, CurrentWingsPowerId] = 1;
+ }
+ }
+
+ public void SetAttributesDamage()
+ {
+ Attributes[GameAttribute.Primary_Damage_Attribute] = (int)Toon.HeroTable.CoreAttribute + 1;
+ Attributes[GameAttribute.Attacks_Per_Second_Percent_Cap] = 4f;
+ }
+
+ public void SetAttributesRessources()
+ {
+ Attributes[GameAttribute.Resource_Type_Primary] = (int)Toon.HeroTable.PrimaryResource + 1;
+ Attributes[GameAttribute.Resource_Max, Attributes[GameAttribute.Resource_Type_Primary] - 1] =
+ Toon.HeroTable.PrimaryResourceBase;
+ Attributes[GameAttribute.Resource_Max_Bonus, Attributes[GameAttribute.Resource_Type_Primary] - 1] = 0;
+ Attributes[GameAttribute.Resource_Factor_Level, Attributes[GameAttribute.Resource_Type_Primary] - 1] =
+ Toon.HeroTable.PrimaryResourceFactorLevel;
+ Attributes[GameAttribute.Resource_Percent, Attributes[GameAttribute.Resource_Type_Primary] - 1] = 0;
+ Attributes[GameAttribute.Resource_Cur, (int)Attributes[GameAttribute.Resource_Type_Primary]] =
+ GetMaxResource((int)Attributes[GameAttribute.Resource_Type_Primary] - 1);
+
+
+ var max = Attributes[GameAttribute.Resource_Max, (int)Attributes[GameAttribute.Resource_Type_Primary] - 1];
+ var cur = Attributes[GameAttribute.Resource_Cur, (int)Attributes[GameAttribute.Resource_Type_Primary] - 1];
+
+
+ Attributes[GameAttribute.Resource_Regen_Per_Second, (int)Attributes[GameAttribute.Resource_Type_Primary] - 1] =
+ Toon.HeroTable.PrimaryResourceRegen;
+ Attributes[GameAttribute.Resource_Regen_Stop_Regen] = false;
+ if (Toon.Class == ToonClass.Barbarian)
+ Attributes[GameAttribute.Resource_Cur, (int)Toon.HeroTable.PrimaryResource + 1] = 0;
+ else
+ Attributes[GameAttribute.Resource_Cur, (int)Toon.HeroTable.PrimaryResource + 1] =
+ (int)GetMaxResource((int)Toon.HeroTable.PrimaryResource + 1) * 100;
+
+ if (Toon.HeroTable.SecondaryResource != GameBalance.HeroTable.Resource.None)
+ {
+ Attributes[GameAttribute.Resource_Type_Secondary] = (int)Toon.HeroTable.SecondaryResource + 1;
+ Attributes[GameAttribute.Resource_Max, (int)Attributes[GameAttribute.Resource_Type_Secondary] - 1] =
+ Toon.HeroTable.SecondaryResourceBase;
+ Attributes[GameAttribute.Resource_Max_Bonus, Attributes[GameAttribute.Resource_Type_Secondary] - 1] = 0;
+ Attributes[GameAttribute.Resource_Percent, Attributes[GameAttribute.Resource_Type_Secondary] - 1] = 0;
+ Attributes[GameAttribute.Resource_Factor_Level,
+ (int)Attributes[GameAttribute.Resource_Type_Secondary] - 1] =
+ Toon.HeroTable.SecondaryResourceFactorLevel;
+ Attributes[GameAttribute.Resource_Cur, (int)Attributes[GameAttribute.Resource_Type_Secondary] - 1] =
+ GetMaxResource((int)Toon.HeroTable.SecondaryResource + 1);
+ Attributes[GameAttribute.Resource_Regen_Per_Second,
+ (int)Attributes[GameAttribute.Resource_Type_Secondary] - 1] = Toon.HeroTable.SecondaryResourceRegen;
+ }
+
+ Attributes[GameAttribute.Get_Hit_Recovery_Per_Level] = (int)Toon.HeroTable.GetHitRecoveryPerLevel;
+ Attributes[GameAttribute.Get_Hit_Recovery_Base] = (int)Toon.HeroTable.GetHitRecoveryBase;
+
+ Attributes[GameAttribute.Get_Hit_Max_Per_Level] = (int)Toon.HeroTable.GetHitMaxPerLevel;
+ Attributes[GameAttribute.Get_Hit_Max_Base] = (int)Toon.HeroTable.GetHitMaxBase;
+ }
+
+ public void SetAttributesClassSpecific()
+ {
+ // Class specific
+ switch (Toon.Class)
+ {
+ case ToonClass.Barbarian:
+ //scripted //this.Attributes[GameAttribute.Skill_Total, 30078] = 1; //Fury Trait
+ Attributes[GameAttribute.Skill, 30078] = 1;
+ Attributes[GameAttribute.Trait, 30078] = 1;
+ Attributes[GameAttribute.Buff_Exclusive_Type_Active, 30078] = true;
+ Attributes[GameAttribute.Buff_Icon_Count0, 30078] = 1;
+ break;
+ case ToonClass.DemonHunter:
+ break;
+ case ToonClass.Crusader:
+ Attributes[GameAttribute.Skill, 0x000418F2] = 1;
+ Attributes[GameAttribute.Skill, 0x00045CCF] = 1;
+ Attributes[GameAttribute.Skill, 0x000564D4] = 1;
+
+ break;
+ case ToonClass.Monk:
+ //scripted //this.Attributes[GameAttribute.Skill_Total, 0x0000CE11] = 1; //Spirit Trait
+ Attributes[GameAttribute.Skill, 0x0000CE11] = 1;
+ Attributes[GameAttribute.Trait, 0x0000CE11] = 1;
+ Attributes[GameAttribute.Buff_Exclusive_Type_Active, 0xCE11] = true;
+ Attributes[GameAttribute.Buff_Icon_Count0, 0x0000CE11] = 1;
+ break;
+ case ToonClass.WitchDoctor:
+ break;
+ case ToonClass.Wizard:
+ break;
+ }
+ }
+
+ public void SetAttributesMovement()
+ {
+ Attributes[GameAttribute.Movement_Scalar_Cap] = 3f;
+ Attributes[GameAttribute.Movement_Scalar] = 1f;
+ Attributes[GameAttribute.Walking_Rate] = Toon.HeroTable.WalkingRate;
+ Attributes[GameAttribute.Running_Rate] = Toon.HeroTable.RunningRate;
+ Attributes[GameAttribute.Experience_Bonus] = 0f;
+ Attributes[GameAttribute.Sprinting_Rate] = Toon.HeroTable.SprintRate * 2;
+ Attributes[GameAttribute.Strafing_Rate] = Toon.HeroTable.SprintRate * 2;
+ }
+
+ public void SetAttributesMisc()
+ {
+ //Miscellaneous
+ /*
+ this.Attributes[GameAttribute.Disabled] = false; // we should be making use of these ones too /raist.
+ this.Attributes[GameAttribute.Loading] = true;
+ this.Attributes[GameAttribute.Loading_Player_ACD] = this.PlayerIndex;
+ this.Attributes[GameAttribute.Invulnerable] = true;
+ this.Attributes[GameAttribute.Hidden] = false;
+ this.Attributes[GameAttribute.Immobolize] = true;
+ this.Attributes[GameAttribute.Untargetable] = true;
+ this.Attributes[GameAttribute.CantStartDisplayedPowers] = true;
+ this.Attributes[GameAttribute.IsContentRestrictedActor] = true;
+ this.Attributes[GameAttribute.Cannot_Dodge] = false;
+ this.Attributes[GameAttribute.Trait, 0x0000CE11] = 1;
+ this.Attributes[GameAttribute.Backpack_Slots] = 60;
+ this.Attributes[GameAttribute.General_Cooldown] = 0;
+ //*/
+ Attributes[GameAttribute.Disabled] = true; // we should be making use of these ones too /raist.
+ Attributes[GameAttribute.Loading] = true;
+ Attributes[GameAttribute.Loading_Player_ACD] = PlayerIndex;
+ Attributes[GameAttribute.Invulnerable] = true;
+ Attributes[GameAttribute.Hidden] = false;
+ Attributes[GameAttribute.Immobolize] = true;
+ Attributes[GameAttribute.Untargetable] = true;
+ Attributes[GameAttribute.CantStartDisplayedPowers] = true;
+ Attributes[GameAttribute.IsContentRestrictedActor] = true;
+ Attributes[GameAttribute.Cannot_Dodge] = false;
+ Attributes[GameAttribute.Trait, 0x0000CE11] = 1;
+ Attributes[GameAttribute.TeamID] = 2;
+ Attributes[GameAttribute.Stash_Tabs_Purchased_With_Gold] = 5; // what do these do?
+ Attributes[GameAttribute.Stash_Tabs_Rewarded_By_Achievements] = 5;
+ Attributes[GameAttribute.Backpack_Slots] = 60;
+ Attributes[GameAttribute.General_Cooldown] = 0;
+ }
+
+ public void SetAttributesByParagon()
+ {
+ // Until the Paragon 800 should be distributed on the 4 tabs,
+ // after that only in the first Core tab.
+ var baseParagonPoints = Math.Min(Toon.ParagonLevel, 800);
+ var extraParagonPoints = Math.Max(0, Toon.ParagonLevel - 800);
+ for (var i = 0; i < 4; i++)
+ {
+ Attributes[GameAttribute.Paragon_Bonus_Points_Available, i] = baseParagonPoints / 4;
+ // Process remainder only for base points.
+ if (i < baseParagonPoints % 4) Attributes[GameAttribute.Paragon_Bonus_Points_Available, i]++;
+ }
+
+ // First tab of Paragon (Core) - pos 0.
+ Attributes[GameAttribute.Paragon_Bonus_Points_Available, 0] += extraParagonPoints;
+
+ var assigned_bonuses = ParagonBonuses;
+
+ var bonus_ids = ItemGenerator.GetParagonBonusTable(Toon.Class);
+
+ foreach (var bonus in bonus_ids)
+ {
+ var slot_index = bonus.Category * 4 + bonus.Index - 1;
+
+ Attributes[GameAttribute.Paragon_Bonus_Points_Available, bonus.Category] -= assigned_bonuses[slot_index];
+
+ Attributes[GameAttribute.Paragon_Bonus, bonus.Hash] = assigned_bonuses[slot_index];
+
+ float result;
+ if (FormulaScript.Evaluate(bonus.AttributeSpecifiers[0].Formula.ToArray(), new ItemRandomHelper(0),
+ out result))
{
- Type = trainHelper.Type,
- AnimTag = trainHelper.AnimationTag,
- NewIdle = trainHelper.IdleAnimationTag,
- Level = trainHelper.DbRef.Level
+ if (bonus.AttributeSpecifiers[0].AttributeId == 104) //Resistance_All
+ {
+ foreach (var damageType in DamageType.AllTypes)
+ Attributes[GameAttribute.Resistance, damageType.AttributeKey] +=
+ result * assigned_bonuses[slot_index];
+ }
+ else
+ {
+ if (bonus.AttributeSpecifiers[0].AttributeId == 133) result = 33f; //Hitpoints_Regen_Per_Second
+
+ if (bonus.AttributeSpecifiers[0].AttributeId == 342) result = 16.5f; //Hitpoints_On_Hit
+
+ if (GameAttribute.Attributes[bonus.AttributeSpecifiers[0].AttributeId] is GameAttributeF)
+ {
+ var attr = GameAttribute.Attributes[bonus.AttributeSpecifiers[0].AttributeId] as GameAttributeF;
+ if (bonus.AttributeSpecifiers[0].SNOParam != -1)
+ Attributes[attr, bonus.AttributeSpecifiers[0].SNOParam] +=
+ result * assigned_bonuses[slot_index];
+ else
+ Attributes[attr] += result * assigned_bonuses[slot_index];
+ }
+ else if (GameAttribute.Attributes[bonus.AttributeSpecifiers[0].AttributeId] is GameAttributeI)
+ {
+ var attr = GameAttribute.Attributes[bonus.AttributeSpecifiers[0].AttributeId] as GameAttributeI;
+ if (bonus.AttributeSpecifiers[0].SNOParam != -1)
+ Attributes[attr, bonus.AttributeSpecifiers[0].SNOParam] +=
+ (int)(result * assigned_bonuses[slot_index]);
+ else
+ Attributes[attr] += (int)(result * assigned_bonuses[slot_index]);
+ }
+ }
+ }
+ //Logger.Debug("Paragon attribute {0} - value {1}", bonus.Attribute[0].AttributeId, (result * assigned_bonuses[slot_index]));
+ }
+ }
+
+ public float PercHPbeforeChange = 0;
+
+ public void SetAttributesByItems()
+ {
+ const float nonPhysDefault = 0f; //was 3.051758E-05f
+ var MaxHPOld = Attributes[GameAttribute.Hitpoints_Max_Total];
+ var PercentOfOld = Attributes[GameAttribute.Hitpoints_Max_Total] / 100;
+ PercHPbeforeChange = Attributes[GameAttribute.Hitpoints_Cur] /
+ (Attributes[GameAttribute.Hitpoints_Max_Total] / 100);
+ ;
+
+ var damageAttributeMinValues = new Dictionary
+ {
+ { DamageType.Physical, new[] { 2f, 2f } },
+ { DamageType.Arcane, new[] { nonPhysDefault, nonPhysDefault } },
+ { DamageType.Cold, new[] { nonPhysDefault, nonPhysDefault } },
+ { DamageType.Fire, new[] { nonPhysDefault, nonPhysDefault } },
+ { DamageType.Holy, new[] { nonPhysDefault, nonPhysDefault } },
+ { DamageType.Lightning, new[] { nonPhysDefault, nonPhysDefault } },
+ { DamageType.Poison, new[] { nonPhysDefault, nonPhysDefault } }
+ };
+
+
+ foreach (var damageType in DamageType.AllTypes)
+ {
+ //var weaponDamageMin = damageType.AttributeKey == 0 ? this.Inventory.GetItemBonus(GameAttribute.Damage_Weapon_Min, 0) : (this.Inventory.GetItemBonus(GameAttribute.Damage_Weapon_Min, 0) + Math.Max(this.Inventory.GetItemBonus(GameAttribute.Damage_Weapon_Min, damageType.AttributeKey), damageAttributeMinValues[damageType][0]));
+ //var weaponDamageDelta = damageType.AttributeKey == 0 ? this.Inventory.GetItemBonus(GameAttribute.Damage_Weapon_Min, 0) : (this.Inventory.GetItemBonus(GameAttribute.Damage_Weapon_Delta, 0) + Math.Max(this.Inventory.GetItemBonus(GameAttribute.Damage_Weapon_Delta, damageType.AttributeKey), damageAttributeMinValues[damageType][1]));
+
+ Attributes[GameAttribute.Damage_Weapon_Min, damageType.AttributeKey] =
+ Math.Max(Inventory.GetItemBonus(GameAttribute.Damage_Weapon_Min_Total, damageType.AttributeKey),
+ damageAttributeMinValues[damageType][0]) +
+ Inventory.GetItemBonus(GameAttribute.Damage_Min, damageType.AttributeKey);
+ Attributes[GameAttribute.Damage_Weapon_Min, damageType.AttributeKey] -=
+ Inventory.AdjustDualWieldMin(damageType); //Damage on weapons should not add when dual-wielding
+ Attributes[GameAttribute.Damage_Weapon_Delta, damageType.AttributeKey] =
+ Math.Max(Inventory.GetItemBonus(GameAttribute.Damage_Weapon_Delta_Total, damageType.AttributeKey),
+ damageAttributeMinValues[damageType][1]) +
+ Inventory.GetItemBonus(GameAttribute.Damage_Delta, damageType.AttributeKey);
+ Attributes[GameAttribute.Damage_Weapon_Delta, damageType.AttributeKey] -=
+ Inventory.AdjustDualWieldDelta(damageType); //Damage on weapons should not add when dual-wielding
+
+ Attributes[GameAttribute.Damage_Weapon_Bonus_Min, damageType.AttributeKey] = 0f;
+ Attributes[GameAttribute.Damage_Weapon_Bonus_Min_X1, damageType.AttributeKey] = 0f;
+ Attributes[GameAttribute.Damage_Weapon_Bonus_Delta, damageType.AttributeKey] = 0f;
+ Attributes[GameAttribute.Damage_Weapon_Bonus_Delta_X1, damageType.AttributeKey] = 0f;
+ Attributes[GameAttribute.Damage_Weapon_Bonus_Flat, damageType.AttributeKey] = 0f;
+
+ Attributes[GameAttribute.Damage_Type_Percent_Bonus, damageType.AttributeKey] =
+ Inventory.GetItemBonus(GameAttribute.Damage_Type_Percent_Bonus, damageType.AttributeKey);
+ Attributes[GameAttribute.Damage_Dealt_Percent_Bonus, damageType.AttributeKey] =
+ Inventory.GetItemBonus(GameAttribute.Damage_Dealt_Percent_Bonus, damageType.AttributeKey);
+
+ Attributes[GameAttribute.Resistance, damageType.AttributeKey] =
+ Inventory.GetItemBonus(GameAttribute.Resistance, damageType.AttributeKey);
+ Attributes[GameAttribute.Damage_Percent_Reduction_From_Type, damageType.AttributeKey] =
+ Inventory.GetItemBonus(GameAttribute.Damage_Percent_Reduction_From_Type, damageType.AttributeKey);
+ Attributes[GameAttribute.Amplify_Damage_Type_Percent, damageType.AttributeKey] =
+ Inventory.GetItemBonus(GameAttribute.Amplify_Damage_Type_Percent, damageType.AttributeKey);
+ }
+
+ for (var i = 0; i < 4; i++)
+ Attributes[GameAttribute.Damage_Percent_Bonus_Vs_Monster_Type, i] =
+ Inventory.GetItemBonus(GameAttribute.Damage_Percent_Bonus_Vs_Monster_Type, i);
+
+
+ Attributes[GameAttribute.Resistance_All] = Inventory.GetItemBonus(GameAttribute.Resistance_All);
+ Attributes[GameAttribute.Resistance_Percent_All] = Inventory.GetItemBonus(GameAttribute.Resistance_Percent_All);
+ Attributes[GameAttribute.Damage_Percent_Reduction_From_Melee] =
+ Inventory.GetItemBonus(GameAttribute.Damage_Percent_Reduction_From_Melee);
+ Attributes[GameAttribute.Damage_Percent_Reduction_From_Ranged] =
+ Inventory.GetItemBonus(GameAttribute.Damage_Percent_Reduction_From_Ranged);
+
+ Attributes[GameAttribute.Thorns_Fixed, 0] = Inventory.GetItemBonus(GameAttribute.Thorns_Fixed, 0);
+
+ //this.Attributes[GameAttribute.Armor_Item_Percent] = this.Inventory.GetItemBonus(GameAttribute.Armor_Item_Percent);
+ var allStatsBonus = Inventory.GetItemBonus(GameAttribute.Stats_All_Bonus); // / 1065353216;
+ /*
+ this.Attributes[GameAttribute.Armor_Item] = this.Inventory.GetItemBonus(GameAttribute.Armor_Item_Total);
+ this.Attributes[GameAttribute.Strength_Item] = this.Inventory.GetItemBonus(GameAttribute.Dexterity_Item);// / 1065353216;
+ this.Attributes[GameAttribute.Strength_Item] += allStatsBonus;
+ this.Attributes[GameAttribute.Dexterity_Item] = this.Inventory.GetItemBonus(GameAttribute.Intelligence_Item);// / 1065353216;
+ this.Attributes[GameAttribute.Dexterity_Item] += allStatsBonus;
+ this.Attributes[GameAttribute.Intelligence_Item] = this.Inventory.GetItemBonus(GameAttribute.Vitality_Item);// / 1065353216; //I know that's wild, but client can't display it properly...
+ this.Attributes[GameAttribute.Intelligence_Item] += allStatsBonus;
+ this.Attributes[GameAttribute.Vitality_Item] = this.Inventory.GetItemBonus(GameAttribute.Item_Level_Requirement_Reduction);// / 1065353216;
+ this.Attributes[GameAttribute.Vitality_Item] += allStatsBonus;
+ //*/
+ //*
+ Attributes[GameAttribute.Strength_Item] = Inventory.GetItemBonus(GameAttribute.Strength_Item); // / 1065353216;
+ Attributes[GameAttribute.Strength_Item] += allStatsBonus;
+ Attributes[GameAttribute.Vitality_Item] = Inventory.GetItemBonus(GameAttribute.Vitality_Item); // / 1065353216;
+ Attributes[GameAttribute.Vitality_Item] += allStatsBonus;
+ Attributes[GameAttribute.Dexterity_Item] =
+ Inventory.GetItemBonus(GameAttribute.Dexterity_Item); // / 1065353216;
+ Attributes[GameAttribute.Dexterity_Item] += allStatsBonus;
+ Attributes[GameAttribute.Intelligence_Item] =
+ Inventory.GetItemBonus(GameAttribute
+ .Intelligence_Item); // / 1065353216; //I know that's wild, but client can't display it properly...
+ Attributes[GameAttribute.Intelligence_Item] += allStatsBonus;
+ //*/
+
+ //this.Attributes[GameAttribute.Cube_Enchanted_Strength_Item] = 0;
+ Attributes[GameAttribute.Core_Attributes_From_Item_Bonus_Multiplier] = 1;
+
+
+ Attributes[GameAttribute.Hitpoints_Max_Percent_Bonus] =
+ Inventory.GetItemBonus(GameAttribute.Hitpoints_Max_Percent_Bonus);
+ Attributes[GameAttribute.Hitpoints_Max_Percent_Bonus_Item] =
+ Inventory.GetItemBonus(GameAttribute.Hitpoints_Max_Percent_Bonus_Item);
+ Attributes[GameAttribute.Hitpoints_Max_Bonus] = Inventory.GetItemBonus(GameAttribute.Hitpoints_Max_Bonus);
+
+
+ Attributes[GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.PrimaryResource] =
+ Inventory.GetItemBonus(GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.PrimaryResource);
+
+ Attributes[GameAttribute.Attacks_Per_Second] = Inventory.GetAPS();
+
+ Attributes[GameAttribute.Attacks_Per_Second_Percent] =
+ Inventory.GetItemBonus(GameAttribute.Attacks_Per_Second_Item_Percent) +
+ Inventory.GetItemBonus(GameAttribute.Attacks_Per_Second_Percent);
+ Attributes[GameAttribute.Attacks_Per_Second_Bonus] =
+ Inventory.GetItemBonus(GameAttribute.Attacks_Per_Second_Item_Bonus);
+ Attributes[GameAttribute.Attacks_Per_Second_Item] =
+ Inventory.GetItemBonus(GameAttribute.Attacks_Per_Second_Item);
+ var a = Attributes[GameAttribute.Attacks_Per_Second];
+ var b = Attributes[GameAttribute.Attacks_Per_Second_Percent];
+ var c = Attributes[GameAttribute.Attacks_Per_Second_Bonus];
+ var d = Attributes[GameAttribute.Attacks_Per_Second_Item];
+ var e = Attributes[GameAttribute.Attacks_Per_Second_Item_CurrentHand];
+ var f = Attributes[GameAttribute.Attacks_Per_Second_Item_Bonus];
+ var g = Attributes[GameAttribute.Attacks_Per_Second_Percent_Subtotal];
+ var h = Attributes[GameAttribute.Attacks_Per_Second_Percent_Cap];
+ var j = Attributes[GameAttribute.Attacks_Per_Second_Percent_Uncapped];
+ var k = Attributes[GameAttribute.Attacks_Per_Second_Percent_Reduction];
+ var o = Attributes[GameAttribute.Attacks_Per_Second_Total];
+
+ if (Attributes[GameAttribute.Attacks_Per_Second_Total] < 1)
+ Attributes[GameAttribute.Attacks_Per_Second] = 1.0f;
+ Attributes[GameAttribute.Crit_Percent_Bonus_Capped] =
+ Inventory.GetItemBonus(GameAttribute.Crit_Percent_Bonus_Capped);
+ Attributes[GameAttribute.Weapon_Crit_Chance] = 0.05f + Inventory.GetItemBonus(GameAttribute.Weapon_Crit_Chance);
+ Attributes[GameAttribute.Crit_Damage_Percent] =
+ 0.5f + Inventory.GetItemBonus(GameAttribute.Crit_Damage_Percent);
+
+ Attributes[GameAttribute.Splash_Damage_Effect_Percent] =
+ Inventory.GetItemBonus(GameAttribute.Splash_Damage_Effect_Percent);
+
+ Attributes[GameAttribute.On_Hit_Fear_Proc_Chance] =
+ Inventory.GetItemBonus(GameAttribute.On_Hit_Fear_Proc_Chance) +
+ Inventory.GetItemBonus(GameAttribute.Weapon_On_Hit_Fear_Proc_Chance);
+ Attributes[GameAttribute.On_Hit_Stun_Proc_Chance] =
+ Inventory.GetItemBonus(GameAttribute.On_Hit_Stun_Proc_Chance) +
+ Inventory.GetItemBonus(GameAttribute.Weapon_On_Hit_Stun_Proc_Chance);
+ Attributes[GameAttribute.On_Hit_Blind_Proc_Chance] =
+ Inventory.GetItemBonus(GameAttribute.On_Hit_Blind_Proc_Chance) +
+ Inventory.GetItemBonus(GameAttribute.Weapon_On_Hit_Blind_Proc_Chance);
+ Attributes[GameAttribute.On_Hit_Freeze_Proc_Chance] =
+ Inventory.GetItemBonus(GameAttribute.On_Hit_Freeze_Proc_Chance) +
+ Inventory.GetItemBonus(GameAttribute.Weapon_On_Hit_Freeze_Proc_Chance);
+ Attributes[GameAttribute.On_Hit_Chill_Proc_Chance] =
+ Inventory.GetItemBonus(GameAttribute.On_Hit_Chill_Proc_Chance) +
+ Inventory.GetItemBonus(GameAttribute.Weapon_On_Hit_Chill_Proc_Chance);
+ Attributes[GameAttribute.On_Hit_Slow_Proc_Chance] =
+ Inventory.GetItemBonus(GameAttribute.On_Hit_Slow_Proc_Chance) +
+ Inventory.GetItemBonus(GameAttribute.Weapon_On_Hit_Slow_Proc_Chance);
+ Attributes[GameAttribute.On_Hit_Immobilize_Proc_Chance] =
+ Inventory.GetItemBonus(GameAttribute.On_Hit_Immobilize_Proc_Chance) +
+ Inventory.GetItemBonus(GameAttribute.Weapon_On_Hit_Immobilize_Proc_Chance);
+ Attributes[GameAttribute.On_Hit_Knockback_Proc_Chance] =
+ Inventory.GetItemBonus(GameAttribute.On_Hit_Knockback_Proc_Chance) +
+ Inventory.GetItemBonus(GameAttribute.Weapon_On_Hit_Knockback_Proc_Chance);
+ Attributes[GameAttribute.On_Hit_Bleed_Proc_Chance] =
+ Inventory.GetItemBonus(GameAttribute.On_Hit_Bleed_Proc_Chance) +
+ Inventory.GetItemBonus(GameAttribute.Weapon_On_Hit_Bleed_Proc_Chance);
+
+ Attributes[GameAttribute.Running_Rate] =
+ Toon.HeroTable.RunningRate + Inventory.GetItemBonus(GameAttribute.Running_Rate);
+ Attributes[GameAttribute.Movement_Scalar_Uncapped_Bonus] =
+ Inventory.GetItemBonus(GameAttribute.Movement_Scalar_Uncapped_Bonus);
+ Attributes[GameAttribute.Movement_Scalar] = Inventory.GetItemBonus(GameAttribute.Movement_Scalar) + 1.0f;
+
+ //this.Attributes[GameAttribute.Magic_Find] = this.Inventory.GetItemBonus(GameAttribute.Magic_Find);
+ Attributes[GameAttribute.Magic_Find] = Inventory.GetMagicFind();
+ //this.Attributes[GameAttribute.Gold_Find] = this.Inventory.GetItemBonus(GameAttribute.Gold_Find);
+ Attributes[GameAttribute.Gold_Find] = Inventory.GetGoldFind();
+
+ Attributes[GameAttribute.Gold_PickUp_Radius] = 5f + Inventory.GetItemBonus(GameAttribute.Gold_PickUp_Radius);
+
+ Attributes[GameAttribute.Experience_Bonus] = Inventory.GetItemBonus(GameAttribute.Experience_Bonus);
+ Attributes[GameAttribute.Experience_Bonus_Percent] =
+ Inventory.GetItemBonus(GameAttribute.Experience_Bonus_Percent);
+
+ Attributes[GameAttribute.Resistance_Freeze] = Inventory.GetItemBonus(GameAttribute.Resistance_Freeze);
+ Attributes[GameAttribute.Resistance_Penetration] = Inventory.GetItemBonus(GameAttribute.Resistance_Penetration);
+ Attributes[GameAttribute.Resistance_Percent] = Inventory.GetItemBonus(GameAttribute.Resistance_Percent);
+ Attributes[GameAttribute.Resistance_Root] = Inventory.GetItemBonus(GameAttribute.Resistance_Root);
+ Attributes[GameAttribute.Resistance_Stun] = Inventory.GetItemBonus(GameAttribute.Resistance_Stun);
+ Attributes[GameAttribute.Resistance_StunRootFreeze] =
+ Inventory.GetItemBonus(GameAttribute.Resistance_StunRootFreeze);
+
+ Attributes[GameAttribute.Dodge_Chance_Bonus] = Inventory.GetItemBonus(GameAttribute.Dodge_Chance_Bonus);
+
+ Attributes[GameAttribute.Block_Amount_Item_Min] = Inventory.GetItemBonus(GameAttribute.Block_Amount_Item_Min);
+ Attributes[GameAttribute.Block_Amount_Item_Delta] =
+ Inventory.GetItemBonus(GameAttribute.Block_Amount_Item_Delta);
+ Attributes[GameAttribute.Block_Amount_Bonus_Percent] =
+ Inventory.GetItemBonus(GameAttribute.Block_Amount_Bonus_Percent);
+ Attributes[GameAttribute.Block_Chance] = Inventory.GetItemBonus(GameAttribute.Block_Chance_Item_Total);
+
+ Attributes[GameAttribute.Power_Cooldown_Reduction_Percent] = 0;
+ Attributes[GameAttribute.Health_Globe_Bonus_Health] =
+ Inventory.GetItemBonus(GameAttribute.Health_Globe_Bonus_Health);
+
+ Attributes[GameAttribute.Hitpoints_Regen_Per_Second] =
+ Inventory.GetItemBonus(GameAttribute.Hitpoints_Regen_Per_Second) + Toon.HeroTable.GetHitRecoveryBase +
+ Toon.HeroTable.GetHitRecoveryPerLevel * Level;
+
+ Attributes[GameAttribute.Resource_Cost_Reduction_Percent_All] =
+ Inventory.GetItemBonus(GameAttribute.Resource_Cost_Reduction_Percent_All);
+ Attributes[GameAttribute.Resource_Cost_Reduction_Percent, (int)Toon.HeroTable.PrimaryResource] =
+ Inventory.GetItemBonus(GameAttribute.Resource_Cost_Reduction_Percent, (int)Toon.HeroTable.PrimaryResource);
+ Attributes[GameAttribute.Resource_Regen_Per_Second, (int)Toon.HeroTable.PrimaryResource] =
+ Toon.HeroTable.PrimaryResourceRegen + Inventory.GetItemBonus(GameAttribute.Resource_Regen_Per_Second,
+ (int)Toon.HeroTable.PrimaryResource);
+ Attributes[GameAttribute.Resource_Regen_Bonus_Percent, (int)Toon.HeroTable.PrimaryResource] =
+ Inventory.GetItemBonus(GameAttribute.Resource_Regen_Bonus_Percent, (int)Toon.HeroTable.PrimaryResource);
+
+ Attributes[GameAttribute.Resource_Cost_Reduction_Percent, (int)Toon.HeroTable.SecondaryResource] =
+ Inventory.GetItemBonus(GameAttribute.Resource_Cost_Reduction_Percent,
+ (int)Toon.HeroTable.SecondaryResource);
+ Attributes[GameAttribute.Resource_Regen_Per_Second, (int)Toon.HeroTable.SecondaryResource] =
+ Toon.HeroTable.SecondaryResourceRegen + Inventory.GetItemBonus(GameAttribute.Resource_Regen_Per_Second,
+ (int)Toon.HeroTable.SecondaryResource);
+ Attributes[GameAttribute.Resource_Regen_Bonus_Percent, (int)Toon.HeroTable.SecondaryResource] =
+ Inventory.GetItemBonus(GameAttribute.Resource_Regen_Bonus_Percent, (int)Toon.HeroTable.SecondaryResource);
+
+ Attributes[GameAttribute.Resource_On_Hit] = 0;
+ Attributes[GameAttribute.Resource_On_Hit, 0] = Inventory.GetItemBonus(GameAttribute.Resource_On_Hit, 0);
+ Attributes[GameAttribute.Resource_On_Crit, 1] = Inventory.GetItemBonus(GameAttribute.Resource_On_Crit, 1);
+
+ Attributes[GameAttribute.Steal_Health_Percent] =
+ Inventory.GetItemBonus(GameAttribute.Steal_Health_Percent) * 0.1f;
+ Attributes[GameAttribute.Hitpoints_On_Hit] = Inventory.GetItemBonus(GameAttribute.Hitpoints_On_Hit);
+ Attributes[GameAttribute.Hitpoints_On_Kill] = Inventory.GetItemBonus(GameAttribute.Hitpoints_On_Kill);
+ Attributes[GameAttribute.Damage_Weapon_Percent_Bonus] =
+ Inventory.GetItemBonus(GameAttribute.Damage_Weapon_Percent_Bonus);
+ Attributes[GameAttribute.Damage_Percent_Bonus_Vs_Elites] =
+ Inventory.GetItemBonus(GameAttribute.Damage_Percent_Bonus_Vs_Elites);
+ //this.Attributes[GameAttribute.Power_Cooldown_Reduction_Percent_All_Capped] = 0.5f;
+ //this.Attributes[GameAttribute.Power_Cooldown_Reduction_Percent_Cap] = 0.5f;
+ Attributes[GameAttribute.Power_Cooldown_Reduction_Percent] = 0.5f;
+ Attributes[GameAttribute.Power_Cooldown_Reduction_Percent_All] =
+ Inventory.GetItemBonus(GameAttribute.Power_Cooldown_Reduction_Percent_All);
+ Attributes[GameAttribute.Crit_Percent_Bonus_Uncapped] =
+ Inventory.GetItemBonus(GameAttribute.Crit_Percent_Bonus_Uncapped);
+
+ //this.Attributes[GameAttribute.Projectile_Speed] = 0.3f;
+
+ switch (Toon.Class)
+ {
+ case ToonClass.Barbarian:
+ Attributes[GameAttribute.Power_Resource_Reduction, 80028] =
+ Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 80028);
+ Attributes[GameAttribute.Power_Resource_Reduction, 70472] =
+ Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 70472);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 79242] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 79242);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 80263] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 80263);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 78548] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 78548);
+ Attributes[GameAttribute.Power_Resource_Reduction, 93885] =
+ Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 93885);
+ Attributes[GameAttribute.Power_Crit_Percent_Bonus, 86989] =
+ Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 86989);
+ Attributes[GameAttribute.Power_Crit_Percent_Bonus, 96296] =
+ Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 96296);
+ Attributes[GameAttribute.Power_Crit_Percent_Bonus, 109342] =
+ Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 109342);
+ Attributes[GameAttribute.Power_Crit_Percent_Bonus, 159169] =
+ Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 159169);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 93885] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 93885);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 69979] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 69979);
+ break;
+ case ToonClass.DemonHunter:
+ Attributes[GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.SecondaryResource] =
+ Inventory.GetItemBonus(GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.SecondaryResource);
+ Attributes[GameAttribute.Bow] = Inventory.GetItemBonus(GameAttribute.Bow);
+ Attributes[GameAttribute.Crossbow] = Inventory.GetItemBonus(GameAttribute.Crossbow);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 129215] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 129215);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 134209] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 134209);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 77552] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 77552);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 75873] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 75873);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 86610] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 86610);
+ Attributes[GameAttribute.Power_Crit_Percent_Bonus, 131192] =
+ Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 131192);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 131325] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 131325);
+ Attributes[GameAttribute.Power_Crit_Percent_Bonus, 77649] =
+ Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 77649);
+ Attributes[GameAttribute.Power_Crit_Percent_Bonus, 134030] =
+ Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 134030);
+ Attributes[GameAttribute.Power_Resource_Reduction, 129214] =
+ Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 129214);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 75301] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 75301);
+ Attributes[GameAttribute.Power_Resource_Reduction, 131366] =
+ Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 131366);
+ Attributes[GameAttribute.Power_Resource_Reduction, 129213] =
+ Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 129213);
+ break;
+ case ToonClass.Monk:
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 95940] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 95940);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 96019] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 96019);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 96311] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 96311);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 97328] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 97328);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 96090] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 96090);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 97110] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 97110);
+ Attributes[GameAttribute.Power_Crit_Percent_Bonus, 121442] =
+ Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 121442);
+ Attributes[GameAttribute.Power_Resource_Reduction, 111676] =
+ Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 111676);
+ Attributes[GameAttribute.Power_Resource_Reduction, 223473] =
+ Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 223473);
+ Attributes[GameAttribute.Power_Crit_Percent_Bonus, 96033] =
+ Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 96033);
+ break;
+ case ToonClass.WitchDoctor:
+ Attributes[GameAttribute.Power_Resource_Reduction, 105963] =
+ Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 105963);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 103181] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 103181);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 106465] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 106465);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 83602] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 83602);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 108506] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 108506);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 69866] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 69866);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 69867] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 69867);
+ Attributes[GameAttribute.Power_Resource_Reduction, 74003] =
+ Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 74003);
+ Attributes[GameAttribute.Power_Crit_Percent_Bonus, 70455] =
+ Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 103181);
+ Attributes[GameAttribute.Power_Resource_Reduction, 67567] =
+ Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 67567);
+ Attributes[GameAttribute.Power_Cooldown_Reduction, 134837] =
+ Inventory.GetItemBonus(GameAttribute.Power_Cooldown_Reduction, 134837);
+ Attributes[GameAttribute.Power_Cooldown_Reduction, 67600] =
+ Inventory.GetItemBonus(GameAttribute.Power_Cooldown_Reduction, 67600);
+ Attributes[GameAttribute.Power_Cooldown_Reduction, 102573] =
+ Inventory.GetItemBonus(GameAttribute.Power_Cooldown_Reduction, 102573);
+ Attributes[GameAttribute.Power_Cooldown_Reduction, 30624] =
+ Inventory.GetItemBonus(GameAttribute.Power_Cooldown_Reduction, 30624);
+ break;
+ case ToonClass.Wizard:
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 30744] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 30744);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 30783] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 30783);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 71548] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 71548);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 1765] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 1765);
+ Attributes[GameAttribute.Power_Crit_Percent_Bonus, 30668] =
+ Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 30668);
+ Attributes[GameAttribute.Power_Crit_Percent_Bonus, 77113] =
+ Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 77113);
+ Attributes[GameAttribute.Power_Resource_Reduction, 91549] =
+ Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 91549);
+ Attributes[GameAttribute.Power_Crit_Percent_Bonus, 87525] =
+ Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 87525);
+ Attributes[GameAttribute.Power_Crit_Percent_Bonus, 93395] =
+ Inventory.GetItemBonus(GameAttribute.Power_Crit_Percent_Bonus, 93395);
+ Attributes[GameAttribute.Power_Resource_Reduction, 134456] =
+ Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 134456);
+ Attributes[GameAttribute.Power_Resource_Reduction, 30725] =
+ Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 30725);
+ Attributes[GameAttribute.Power_Duration_Increase, 30680] =
+ Inventory.GetItemBonus(GameAttribute.Power_Duration_Increase, 30680);
+ Attributes[GameAttribute.Power_Resource_Reduction, 69190] =
+ Inventory.GetItemBonus(GameAttribute.Power_Resource_Reduction, 69190);
+ Attributes[GameAttribute.Power_Cooldown_Reduction, 168344] =
+ Inventory.GetItemBonus(GameAttribute.Power_Cooldown_Reduction, 168344);
+ Attributes[GameAttribute.Power_Damage_Percent_Bonus, 71548] =
+ Inventory.GetItemBonus(GameAttribute.Power_Damage_Percent_Bonus, 71548);
+ break;
+ }
+ }
+
+ public void UpdatePercentageHP(float percent)
+ {
+ var m = Attributes[GameAttribute.Hitpoints_Max_Total];
+ Attributes[GameAttribute.Hitpoints_Cur] = percent * Attributes[GameAttribute.Hitpoints_Max_Total] / 100;
+ Attributes.BroadcastChangedIfRevealed();
+ }
+
+ public void UpdatePercentageHP()
+ {
+ }
+
+ public void SetAttributesByGems()
+ {
+ Inventory.SetGemBonuses();
+ }
+
+ public void SetAttributesByItemProcs()
+ {
+ Attributes[GameAttribute.Item_Power_Passive, 248776] =
+ Inventory.GetItemBonus(GameAttribute.Item_Power_Passive, 248776); //cluck
+ Attributes[GameAttribute.Item_Power_Passive, 248629] =
+ Inventory.GetItemBonus(GameAttribute.Item_Power_Passive, 248629); //death laugh
+ Attributes[GameAttribute.Item_Power_Passive, 247640] =
+ Inventory.GetItemBonus(GameAttribute.Item_Power_Passive, 247640); //gore1
+ Attributes[GameAttribute.Item_Power_Passive, 249963] =
+ Inventory.GetItemBonus(GameAttribute.Item_Power_Passive, 249963); //gore2
+ Attributes[GameAttribute.Item_Power_Passive, 249954] =
+ Inventory.GetItemBonus(GameAttribute.Item_Power_Passive, 249954); //gore3
+ Attributes[GameAttribute.Item_Power_Passive, 246116] =
+ Inventory.GetItemBonus(GameAttribute.Item_Power_Passive, 246116); //butcher
+ Attributes[GameAttribute.Item_Power_Passive, 247724] =
+ Inventory.GetItemBonus(GameAttribute.Item_Power_Passive, 247724); //plum!
+ Attributes[GameAttribute.Item_Power_Passive, 245741] =
+ Inventory.GetItemBonus(GameAttribute.Item_Power_Passive, 245741); //weee!
+ }
+
+ public void SetAttributesByItemSets()
+ {
+ Attributes[GameAttribute.Strength] = Strength;
+ Attributes[GameAttribute.Dexterity] = Dexterity;
+ Attributes[GameAttribute.Vitality] = Vitality;
+ Attributes[GameAttribute.Intelligence] = Intelligence;
+ Attributes.BroadcastChangedIfRevealed();
+
+ Inventory.SetItemSetBonuses();
+ }
+
+ public void SetAttributesByPassives() //also reapplies synergy buffs
+ {
+ // Class specific
+ Attributes[GameAttribute.Damage_Percent_All_From_Skills] = 0;
+ Attributes[GameAttribute.Allow_2H_And_Shield] = false;
+ Attributes[GameAttribute.Cannot_Dodge] = false;
+
+ foreach (var passiveId in SkillSet.PassiveSkills)
+ switch (Toon.Class)
+ {
+ case ToonClass.Barbarian:
+ switch (passiveId)
+ {
+ case 217819: //NervesOfSteel
+ Attributes[GameAttribute.Armor_Item] += Attributes[GameAttribute.Vitality_Total] * 0.50f;
+ break;
+ case 205228: //Animosity
+ Attributes[GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.PrimaryResource] += 20;
+ Attributes[GameAttribute.Resource_Regen_Per_Second, (int)Toon.HeroTable.PrimaryResource] =
+ Attributes[GameAttribute.Resource_Regen_Per_Second,
+ (int)Toon.HeroTable.PrimaryResource] * 1.1f;
+ Attributes[GameAttribute.Resource_Cur, (int)Toon.HeroTable.PrimaryResource] =
+ Toon.HeroTable.PrimaryResourceBase + Attributes[GameAttribute.Resource_Max_Bonus,
+ (int)Toon.HeroTable.PrimaryResource];
+ break;
+ case 205848: //ToughAsNails
+ Attributes[GameAttribute.Armor_Item] *= 1.25f;
+ break;
+ case 205707: //Juggernaut
+ Attributes[GameAttribute.CrowdControl_Reduction] += 0.3f;
+ break;
+ case 206147: //WeaponsMaster
+ var weapon = Inventory.GetEquippedWeapon();
+ if (weapon != null)
+ {
+ var name = weapon.ItemDefinition.Name.ToLower();
+ if (name.Contains("sword") || name.Contains("dagger"))
+ Attributes[GameAttribute.Damage_Weapon_Percent_Bonus] += 0.08f;
+ else if (name.Contains("axe") || name.Contains("mace"))
+ Attributes[GameAttribute.Weapon_Crit_Chance] += 0.05f;
+ else if (name.Contains("spear") || name.Contains("polearm"))
+ Attributes[GameAttribute.Attacks_Per_Second] *= 1.08f;
+ else if (name.Contains("mighty"))
+ Attributes[GameAttribute.Resource_On_Hit] += 1f;
+ }
+
+ break;
+ }
+
+ break;
+ case ToonClass.DemonHunter:
+ switch (passiveId)
+ {
+ case 155714: //Blood Vengeance
+ Attributes[GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.PrimaryResource] += 25;
+ Attributes[GameAttribute.Resource_Cur, (int)Toon.HeroTable.PrimaryResource] =
+ Toon.HeroTable.PrimaryResourceBase + Attributes[GameAttribute.Resource_Max_Bonus,
+ (int)Toon.HeroTable.PrimaryResource];
+ break;
+ case 210801: //Brooding
+ Attributes[GameAttribute.Hitpoints_Regen_Per_Second] +=
+ Attributes[GameAttribute.Hitpoints_Max_Total] / 100;
+ break;
+ case 155715: //Sharpshooter
+ World.BuffManager.RemoveBuffs(this, 155715);
+ World.BuffManager.AddBuff(this, this, new SharpshooterBuff());
+ break;
+ case 324770: //Awareness
+ World.BuffManager.RemoveBuffs(this, 324770);
+ World.BuffManager.AddBuff(this, this, new AwarenessBuff());
+ break;
+ case 209734: //Archery
+ var weapon = Inventory.GetEquippedWeapon();
+ if (weapon != null)
+ {
+ var name = weapon.ItemDefinition.Name.ToLower();
+ if (name.Contains("xbow"))
+ Attributes[GameAttribute.Crit_Damage_Percent] += 0.5f;
+ if (name.Contains("handxbow"))
+ {
+ Attributes[GameAttribute.Crit_Percent_Bonus_Uncapped] += 0.05f;
+ }
+ else if (name.Contains("xbow"))
+ {
+ Attributes[GameAttribute.Resource_Regen_Per_Second,
+ (int)Toon.HeroTable.PrimaryResource] += 1f;
+ }
+ else if (name.Contains("bow"))
+ {
+ Attributes[GameAttribute.Damage_Weapon_Percent_Bonus] += 0.08f;
+ Attributes[GameAttribute.Damage_Percent_All_From_Skills] = 0.08f;
+ }
+ }
+
+ break;
+ case 155722: //Perfectionist
+ Attributes[GameAttribute.Armor_Item] *= 1.1f;
+ Attributes[GameAttribute.Hitpoints_Max_Percent_Bonus] += 0.1f;
+ Attributes[GameAttribute.Resistance_Percent_All] += 0.1f;
+ break;
+ }
+
+ break;
+ case ToonClass.Monk:
+ switch (passiveId)
+ {
+ case 209029: //FleetFooted
+ Attributes[GameAttribute.Movement_Scalar_Uncapped_Bonus] += 0.1f;
+ break;
+ case 209027: //ExaltedSoul
+ Attributes[GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.PrimaryResource] += 100;
+ //this.Attributes[GameAttribute.Resource_Cur, (int)Toon.HeroTable.PrimaryResource] = Toon.HeroTable.PrimaryResourceMax + this.Attributes[GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.PrimaryResource];
+ Attributes[GameAttribute.Resource_Regen_Per_Second, 3] += 2f;
+ break;
+ case 209628: //SeizeTheInitiative
+ Attributes[GameAttribute.Armor_Item] += Attributes[GameAttribute.Dexterity_Total] * 0.3f;
+ break;
+ case 209622: //SixthSense
+ Attributes[GameAttribute.Dodge_Chance_Bonus] += Math.Min(
+ (Attributes[GameAttribute.Weapon_Crit_Chance] +
+ Attributes[GameAttribute.Crit_Percent_Bonus_Capped] +
+ Attributes[GameAttribute.Crit_Percent_Bonus_Uncapped]) * 0.425f, 0.15f);
+ break;
+ case 209104: //BeaconOfYtar
+ Attributes[GameAttribute.Power_Cooldown_Reduction_Percent_All] += 0.20f;
+ break;
+ case 209656: //OneWithEverything
+ var maxResist = Math.Max(
+ Math.Max(
+ Math.Max(Attributes[GameAttribute.Resistance, DamageType.Physical.AttributeKey],
+ Attributes[GameAttribute.Resistance, DamageType.Cold.AttributeKey]),
+ Attributes[GameAttribute.Resistance, DamageType.Fire.AttributeKey]),
+ Math.Max(
+ Math.Max(Attributes[GameAttribute.Resistance, DamageType.Arcane.AttributeKey],
+ Attributes[GameAttribute.Resistance, DamageType.Holy.AttributeKey]),
+ Math.Max(Attributes[GameAttribute.Resistance, DamageType.Lightning.AttributeKey],
+ Attributes[GameAttribute.Resistance, DamageType.Poison.AttributeKey]))
+ );
+ foreach (var damageType in DamageType.AllTypes)
+ Attributes[GameAttribute.Resistance, damageType.AttributeKey] = maxResist;
+ break;
+ case 209812: //TheGuardiansPath
+ try
+ {
+ var weapon = Inventory.GetEquippedWeapon();
+ if (weapon != null && Inventory.GetEquippedOffHand() != null)
+ {
+ Attributes[GameAttribute.Dodge_Chance_Bonus] += 0.15f;
+ }
+ else if (weapon.ItemDefinition.Name.ToLower().Contains("2h"))
+ {
+ World.BuffManager.RemoveBuffs(this, 209812);
+ World.BuffManager.AddBuff(this, this, new GuardiansPathBuff());
+ }
+ }
+ catch
+ {
+ }
+
+ break;
+ case 341559: //Momentum
+ World.BuffManager.RemoveBuffs(this, 341559);
+ World.BuffManager.AddBuff(this, this, new MomentumCheckBuff());
+ break;
+ case 209813: //Provocation
+ Attributes[GameAttribute.CrowdControl_Reduction] += 0.25f;
+ break;
+ }
+
+ break;
+ case ToonClass.WitchDoctor:
+ switch (passiveId)
+ {
+ case 208569: //SpiritualAttunement
+ Attributes[GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.PrimaryResource] +=
+ Attributes[GameAttribute.Resource_Max, (int)Toon.HeroTable.PrimaryResource] * 0.2f;
+ Attributes[GameAttribute.Resource_Regen_Per_Second, (int)Toon.HeroTable.PrimaryResource] =
+ Toon.HeroTable.PrimaryResourceRegen + (Toon.HeroTable.PrimaryResourceBase +
+ Attributes[GameAttribute.Resource_Max_Bonus,
+ (int)Toon.HeroTable.PrimaryResource]) / 100;
+ Attributes[GameAttribute.Resource_Cur, (int)Toon.HeroTable.PrimaryResource] =
+ Toon.HeroTable.PrimaryResourceBase + Attributes[GameAttribute.Resource_Max_Bonus,
+ (int)Toon.HeroTable.PrimaryResource];
+ break;
+ case 340910: //PhysicalAttunement
+ World.BuffManager.RemoveBuffs(this, 340910);
+ World.BuffManager.AddBuff(this, this, new PhysicalAttunementBuff());
+ break;
+ case 208568: //BloodRitual
+ Attributes[GameAttribute.Hitpoints_Regen_Per_Second] +=
+ Attributes[GameAttribute.Hitpoints_Max_Total] / 100;
+ break;
+ case 208639: //FierceLoyalty
+ foreach (var minionId in Followers.Keys)
+ {
+ var minion = World.GetActorByGlobalId(minionId);
+ if (minion != null)
+ minion.Attributes[GameAttribute.Hitpoints_Regen_Per_Second] =
+ Inventory.GetItemBonus(GameAttribute.Hitpoints_Regen_Per_Second);
+ }
+
+ break;
+ }
+
+ break;
+ case ToonClass.Wizard:
+ switch (passiveId)
+ {
+ case 208541: //Galvanizing Ward
+ World.BuffManager.RemoveBuffs(this, 208541);
+ World.BuffManager.AddBuff(this, this, new GalvanizingBuff());
+ break;
+ case 208473: //Evocation
+ Attributes[GameAttribute.Power_Cooldown_Reduction_Percent_All] += 0.20f;
+ break;
+ case 208472: //AstralPresence
+ Attributes[GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.PrimaryResource] += 20;
+ Attributes[GameAttribute.Resource_Regen_Per_Second, (int)Toon.HeroTable.PrimaryResource] =
+ Toon.HeroTable.PrimaryResourceRegen + 2;
+ Attributes[GameAttribute.Resource_Cur, (int)Toon.HeroTable.PrimaryResource] =
+ Toon.HeroTable.PrimaryResourceBase + Attributes[GameAttribute.Resource_Max_Bonus,
+ (int)Toon.HeroTable.PrimaryResource];
+ break;
+ case 208468: //Blur (Wizard)
+ Attributes[GameAttribute.Damage_Percent_Reduction_From_Melee] += 0.17f;
+ break;
+ }
+
+ break;
+ case ToonClass.Crusader:
+ switch (passiveId)
+ {
+ case 286177: //HeavenlyStrength
+ Attributes[GameAttribute.Movement_Scalar_Uncapped_Bonus] -= 0.15f;
+ Attributes[GameAttribute.Allow_2H_And_Shield] = true;
+ break;
+ case 310626: //Vigilant
+ Attributes[GameAttribute.Hitpoints_Regen_Per_Second] +=
+ 10 + 0.008f * (float)Math.Pow(Attributes[GameAttribute.Level], 3);
+ break;
+ case 356147: //Righteousness
+ Attributes[GameAttribute.Resource_Max_Bonus, (int)Toon.HeroTable.PrimaryResource] += 30;
+ break;
+ case 310804: //HolyCause
+ Attributes[GameAttribute.Damage_Weapon_Min, 6] *= 1.1f;
+ break;
+ case 356176: //DivineFortress
+ World.BuffManager.RemoveBuffs(this, 356176);
+ World.BuffManager.AddBuff(this, this, new DivineFortressBuff());
+ break;
+ case 302500: //HoldYourGround
+ Attributes[GameAttribute.Cannot_Dodge] = true;
+ Attributes[GameAttribute.Block_Chance] += 0.15f;
+ break;
+ case 310783: //IronMaiden
+ Attributes[GameAttribute.Thorns_Fixed, 0] += 87.17f * Attributes[GameAttribute.Level];
+ break;
+ case 311629: //Finery
+ World.BuffManager.RemoveBuffs(this, 311629);
+ World.BuffManager.AddBuff(this, this, new FineryBuff());
+ break;
+ case 310640: //Insurmountable
+ World.BuffManager.RemoveBuffs(this, 310640);
+ World.BuffManager.AddBuff(this, this, new InsurmountableBuff());
+ break;
+ case 309830: //Indesctructible
+ World.BuffManager.RemoveBuffs(this, 309830);
+ World.BuffManager.AddBuff(this, this, new IndestructibleBuff());
+ break;
+ case 356173: //Renewal
+ World.BuffManager.RemoveBuffs(this, 356173);
+ World.BuffManager.AddBuff(this, this, new RenewalBuff());
+ break;
+ case 356052: //Towering Shield
+ World.BuffManager.RemoveBuffs(this, 356052);
+ World.BuffManager.AddBuff(this, this, new ToweringShieldBuff());
+ break;
+ }
+
+ break;
+ case ToonClass.Necromancer:
+ switch (passiveId)
+ {
+ case 470764: //HugeEssense
+ Attributes[GameAttribute.Resource_Max_Bonus,
+ Attributes[GameAttribute.Resource_Type_Primary] - 1] += 40;
+ break;
+ case 470725:
+ World.BuffManager.RemoveBuffs(this, 470725);
+ World.BuffManager.AddBuff(this, this, new OnlyOne());
+ break;
+ }
+
+ break;
+ }
+
+ SetAttributesSkillSets(); //reapply synergy passives (laws, mantras, summons)
+ }
+
+ public void SetAttributesSkillSets()
+ {
+ // unlocking assigned skills
+ for (var i = 0; i < SkillSet.ActiveSkills.Length; i++)
+ if (SkillSet.ActiveSkills[i].snoSkill != -1)
+ {
+ Attributes[GameAttribute.Skill, SkillSet.ActiveSkills[i].snoSkill] = 1;
+ //scripted //this.Attributes[GameAttribute.Skill_Total, this.SkillSet.ActiveSkills[i].snoSkill] = 1;
+ // update rune attributes for new skill
+ Attributes[GameAttribute.Rune_A, SkillSet.ActiveSkills[i].snoSkill] =
+ SkillSet.ActiveSkills[i].snoRune == 0 ? 1 : 0;
+ Attributes[GameAttribute.Rune_B, SkillSet.ActiveSkills[i].snoSkill] =
+ SkillSet.ActiveSkills[i].snoRune == 1 ? 1 : 0;
+ Attributes[GameAttribute.Rune_C, SkillSet.ActiveSkills[i].snoSkill] =
+ SkillSet.ActiveSkills[i].snoRune == 2 ? 1 : 0;
+ Attributes[GameAttribute.Rune_D, SkillSet.ActiveSkills[i].snoSkill] =
+ SkillSet.ActiveSkills[i].snoRune == 3 ? 1 : 0;
+ Attributes[GameAttribute.Rune_E, SkillSet.ActiveSkills[i].snoSkill] =
+ SkillSet.ActiveSkills[i].snoRune == 4 ? 1 : 0;
+
+ var power = PowerLoader.CreateImplementationForPowerSNO(SkillSet.ActiveSkills[i].snoSkill);
+ if (power != null && power.EvalTag(PowerKeys.SynergyPower) != -1)
+ World.PowerManager.RunPower(this, power.EvalTag(PowerKeys.SynergyPower)); //SynergyPower buff
+ }
+
+ for (var i = 0; i < SkillSet.PassiveSkills.Length; ++i)
+ if (SkillSet.PassiveSkills[i] != -1)
+ {
+ // switch on passive skill
+ Attributes[GameAttribute.Trait, SkillSet.PassiveSkills[i]] = 1;
+ Attributes[GameAttribute.Skill, SkillSet.PassiveSkills[i]] = 1;
+ //scripted //this.Attributes[GameAttribute.Skill_Total, this.SkillSet.PassiveSkills[i]] = 1;
+ }
+
+ if (Toon.Class == ToonClass.Monk) //Setting power range override
+ {
+ Attributes[GameAttribute.PowerBonusAttackRadius, 0x000176C4] = 20f; //Fists of Thunder
+ if (Attributes[GameAttribute.Rune_A, 0x00017B56] > 0) //Way of the Hundred Fists -> Fists of Fury
+ Attributes[GameAttribute.PowerBonusAttackRadius, 0x00017B56] = 15f;
+ }
+ }
+
+ public void SetAttributesOther()
+ {
+ //Bonus stats
+ Attributes[GameAttribute.Hit_Chance] = 1f;
+
+ Attributes[GameAttribute.Attacks_Per_Second] = 1.2f;
+ //this.Attributes[GameAttribute.Attacks_Per_Second_Item] = 1.199219f;
+ Attributes[GameAttribute.Crit_Percent_Cap] = Toon.HeroTable.CritPercentCap;
+ //scripted //this.Attributes[GameAttribute.Casting_Speed_Total] = 1f;
+ Attributes[GameAttribute.Casting_Speed] = 1f;
+
+ //Basic stats
+ Attributes[GameAttribute.Level_Cap] = Program.MaxLevel;
+ Attributes[GameAttribute.Level] = Level;
+ Attributes[GameAttribute.Alt_Level] = ParagonLevel;
+ if (Level == Program.MaxLevel)
+ {
+ Attributes[GameAttribute.Alt_Experience_Next_Lo] = (int)(ExperienceNext % uint.MaxValue);
+ Attributes[GameAttribute.Alt_Experience_Next_Hi] = (int)(ExperienceNext / uint.MaxValue);
+ }
+ else
+ {
+ Attributes[GameAttribute.Experience_Next_Lo] = (int)(ExperienceNext % uint.MaxValue);
+ Attributes[GameAttribute.Experience_Next_Hi] = (int)(ExperienceNext / uint.MaxValue);
+ //this.Attributes[GameAttribute.Alt_Experience_Next] = 0;
+ }
+
+ Attributes[GameAttribute.Experience_Granted_Low] = 1000;
+ Attributes[GameAttribute.Armor] = Toon.HeroTable.Armor;
+ Attributes[GameAttribute.Damage_Min, 0] = Toon.HeroTable.Dmg;
+ //scripted //this.Attributes[GameAttribute.Armor_Total]
+
+
+ Attributes[GameAttribute.Strength] = (int)Strength;
+ Attributes[GameAttribute.Dexterity] = (int)Dexterity;
+ Attributes[GameAttribute.Vitality] = (int)Vitality;
+ Attributes[GameAttribute.Intelligence] = (int)Intelligence;
+ Attributes[GameAttribute.Core_Attributes_From_Item_Bonus_Multiplier] = 1;
+
+ //Hitpoints have to be calculated after Vitality
+ Attributes[GameAttribute.Hitpoints_Factor_Level] = Toon.HeroTable.HitpointsFactorLevel;
+ Attributes[GameAttribute.Hitpoints_Factor_Vitality] = 10f + Math.Max(Level - 35, 0);
+ //this.Attributes[GameAttribute.Hitpoints_Max] = 276f;
+
+ Attributes[GameAttribute.Hitpoints_Max_Percent_Bonus_Multiplicative] = (int)1;
+ Attributes[GameAttribute.Hitpoints_Factor_Level] = (int)Toon.HeroTable.HitpointsFactorLevel;
+ Attributes[GameAttribute.Hitpoints_Factor_Vitality] = 10f; // + Math.Max(this.Level - 35, 0);
+ Attributes[GameAttribute.Hitpoints_Max] = (int)Toon.HeroTable.HitpointsMax;
+
+ Attributes[GameAttribute.Hitpoints_Cur] = Attributes[GameAttribute.Hitpoints_Max_Total];
+
+ Attributes[GameAttribute.Corpse_Resurrection_Charges] = 3;
+ //TestOutPutItemAttributes(); //Activate this only for finding item stats.
+ Attributes.BroadcastChangedIfRevealed();
+ }
+
+ #endregion
+
+ #region game-message handling & consumers
+
+ ///
+ /// Consumes the given game-message.
+ ///
+ /// The client.
+ /// The GameMessage.
+ public void Consume(GameClient client, GameMessage message)
+ {
+ if (message is AssignSkillMessage skillMessage) OnAssignActiveSkill(client, skillMessage);
+ else if (message is AssignTraitsMessage traitsMessage) OnAssignPassiveSkills(client, traitsMessage);
+ else if (message is UnassignSkillMessage unassignSkillMessage) OnUnassignActiveSkill(client, unassignSkillMessage);
+ else if (message is TargetMessage targetMessage) OnObjectTargeted(client, targetMessage);
+ else if (message is ACDClientTranslateMessage translateMessage) OnPlayerMovement(client, translateMessage);
+ else if (message is TryWaypointMessage waypointMessage) OnTryWaypoint(client, waypointMessage);
+ else if (message is RequestBuyItemMessage itemMessage) OnRequestBuyItem(client, itemMessage);
+ else if (message is RequestSellItemMessage sellItemMessage) OnRequestSellItem(client, sellItemMessage);
+ else if (message is HirelingRequestLearnSkillMessage learnSkillMessage)
+ OnHirelingRequestLearnSkill(client, learnSkillMessage);
+ else if (message is HirelingRetrainMessage) OnHirelingRetrainMessage();
+ else if (message is HirelingSwapAgreeMessage) OnHirelingSwapAgreeMessage();
+ else if (message is PetAwayMessage awayMessage) OnHirelingDismiss(client, awayMessage);
+ else if (message is ChangeUsableItemMessage usableItemMessage) OnEquipPotion(client, usableItemMessage);
+ else if (message is ArtisanWindowClosedMessage) OnArtisanWindowClosed();
+ else if (message is RequestTrainArtisanMessage artisanMessage) TrainArtisan(client, artisanMessage);
+ else if (message is RessurectionPlayerMessage playerMessage) OnResurrectOption(client, playerMessage);
+ else if (message is PlayerTranslateFacingMessage facingMessage)
+ OnTranslateFacing(client, facingMessage);
+ else if (message is LoopingAnimationPowerMessage powerMessage)
+ OnLoopingAnimationPowerMessage(client, powerMessage);
+ else if (message is SecondaryAnimationPowerMessage animationPowerMessage)
+ OnSecondaryPowerMessage(client, animationPowerMessage);
+ else if (message is MiscPowerMessage miscPowerMessage) OnMiscPowerMessage(client, miscPowerMessage);
+ else if (message is RequestBuffCancelMessage cancelMessage) OnRequestBuffCancel(client, cancelMessage);
+ else if (message is CancelChanneledSkillMessage channeledSkillMessage)
+ OnCancelChanneledSkill(client, channeledSkillMessage);
+ else if (message is TutorialShownMessage shownMessage) OnTutorialShown(client, shownMessage);
+ else if (message is AcceptConfirmMessage confirmMessage) OnConfirm(client, confirmMessage);
+ else if (message is SpendParagonPointsMessage pointsMessage)
+ OnSpendParagonPointsMessage(client, pointsMessage);
+ else if (message is ResetParagonPointsMessage paragonPointsMessage)
+ OnResetParagonPointsMessage(client, paragonPointsMessage);
+ else if (message is MailRetrieveMessage retrieveMessage) OnMailRetrieve(client, retrieveMessage);
+ else if (message is MailReadMessage readMessage) OnMailRead(client, readMessage);
+ else if (message is StashIconStateAssignMessage assignMessage)
+ OnStashIconsAssign(client, assignMessage);
+ else if (message is TransmuteItemsMessage itemsMessage) TransmuteItemsPlayer(client, itemsMessage);
+ else if (message is RiftStartAcceptedMessage acceptedMessage) OpenNephalem(client, acceptedMessage);
+ else if (message is BossEncounterAcceptMessage) AcceptBossEncounter();
+ else if (message is DeActivateCameraCutsceneMode mode)
+ DeactivateCamera(client, mode);
+ else if (message is JewelUpgradeMessage upgradeMessage) JewelUpgrade(client, upgradeMessage);
+ else if (message is SwitchCosmeticMessage cosmeticMessage) SwitchCosmetic(client, cosmeticMessage);
+
+ else return;
+ }
+
+ public void SwitchCosmetic(GameClient client, SwitchCosmeticMessage message)
+ {
+ var Definition = ItemGenerator.GetItemDefinition(message.Field0);
+
+ ;
+ if (Definition.Name.ToLower().Contains("portrait"))
+ client.BnetClient.Account.GameAccount.CurrentToon.Cosmetic4 = message.Field0;
+
+ var RangeCosmetic = new[]
+ {
+ D3.Hero.VisualCosmeticItem.CreateBuilder()
+ .SetGbid(client.BnetClient.Account.GameAccount.CurrentToon.Cosmetic1).Build(), // Wings
+ D3.Hero.VisualCosmeticItem.CreateBuilder()
+ .SetGbid(client.BnetClient.Account.GameAccount.CurrentToon.Cosmetic2).Build(), // Flag
+ D3.Hero.VisualCosmeticItem.CreateBuilder()
+ .SetGbid(client.BnetClient.Account.GameAccount.CurrentToon.Cosmetic3).Build(), // Pet
+ D3.Hero.VisualCosmeticItem.CreateBuilder()
+ .SetGbid(client.BnetClient.Account.GameAccount.CurrentToon.Cosmetic4).Build() // Frame
+ };
+
+ //RangeCosmetic[request.CosmeticItemType - 1] = D3.Hero.VisualCosmeticItem.CreateBuilder().SetGbid(unchecked((int)request.Gbid)).Build();
+
+ client.BnetClient.Account.GameAccount.CurrentToon.StateChanged();
+
+ var NewVisual = D3.Hero.VisualEquipment.CreateBuilder()
+ .AddRangeVisualItem(client.BnetClient.Account.GameAccount.CurrentToon.HeroVisualEquipmentField.Value
+ .VisualItemList).AddRangeCosmeticItem(RangeCosmetic).Build();
+
+ client.BnetClient.Account.GameAccount.CurrentToon.HeroVisualEquipmentField.Value = NewVisual;
+ client.BnetClient.Account.GameAccount.ChangedFields.SetPresenceFieldValue(client.BnetClient.Account.GameAccount
+ .CurrentToon.HeroVisualEquipmentField);
+ client.BnetClient.Account.GameAccount.NotifyUpdate();
+ }
+
+ public void ResetParagonPoints(GameClient client, ResetParagonPointsMessage message)
+ {
+ }
+
+ public void SpendParagonPoints(GameClient client, SpendParagonPointsMessage message)
+ {
+ }
+
+ public void JewelUpgrade(GameClient client, JewelUpgradeMessage message)
+ {
+ var Jewel = Inventory.GetItemByDynId(this, message.ActorID);
+ Jewel.Attributes[GameAttribute.Jewel_Rank]++;
+ Jewel.Attributes.BroadcastChangedIfRevealed();
+ Attributes[GameAttribute.Jewel_Upgrades_Used]++;
+ Attributes.BroadcastChangedIfRevealed();
+ if (Attributes[GameAttribute.Jewel_Upgrades_Used] == Attributes[GameAttribute.Jewel_Upgrades_Max] +
+ Attributes[GameAttribute.Jewel_Upgrades_Bonus])
+ {
+ Attributes[GameAttribute.Jewel_Upgrades_Max] = 0;
+ Attributes[GameAttribute.Jewel_Upgrades_Bonus] = 0;
+ Attributes[GameAttribute.Jewel_Upgrades_Used] = 0;
+ }
+
+ InGameClient.SendMessage(new JewelUpgradeResultsMessage()
+ {
+ ActorID = message.ActorID,
+ Field1 = 1
+ });
+ }
+
+ public void OnHirelingSwapAgreeMessage()
+ {
+ Hireling hireling = null;
+ DiIiS_NA.Core.MPQ.FileFormats.Actor Data = null;
+ if (World.Game.Players.Count > 1) return;
+
+
+ switch (InGameClient.Game.CurrentQuest)
+ {
+ case 72061:
+ //Templar
+ Data = (DiIiS_NA.Core.MPQ.FileFormats.Actor)MPQStorage.Data.Assets[SNOGroup.Actor][52693].Data;
+ hireling = new Templar(World, ActorSno._hireling_templar, Data.TagMap);
+ hireling.GBHandle.GBID = StringHashHelper.HashItemName("Templar");
+
+ break;
+ case 72738:
+ //Scoundrel
+ Data = (DiIiS_NA.Core.MPQ.FileFormats.Actor)MPQStorage.Data.Assets[SNOGroup.Actor][52694].Data;
+ hireling = new Templar(World, ActorSno._hireling_scoundrel, Data.TagMap);
+ hireling.GBHandle.GBID = StringHashHelper.HashItemName("Scoundrel");
+ break;
+ case 0:
+ //Enchantress
+ Data = (DiIiS_NA.Core.MPQ.FileFormats.Actor)MPQStorage.Data.Assets[SNOGroup.Actor][4482].Data;
+ hireling = new Templar(World, ActorSno._hireling_enchantress, Data.TagMap);
+ hireling.GBHandle.GBID = StringHashHelper.HashItemName("Enchantress");
+ break;
+ }
+
+ hireling.SetUpAttributes(this);
+ hireling.GBHandle.Type = 4;
+ hireling.Attributes[GameAttribute.Pet_Creator] = PlayerIndex + 1;
+ hireling.Attributes[GameAttribute.Pet_Type] = 1;
+ hireling.Attributes[GameAttribute.Pet_Owner] = PlayerIndex + 1;
+ hireling.Attributes[GameAttribute.Untargetable] = false;
+ hireling.Attributes[GameAttribute.NPC_Is_Escorting] = true;
+
+ hireling.EnterWorld(RandomDirection(Position, 3, 10)); //Random
+ hireling.Brain = new HirelingBrain(hireling, this);
+ ActiveHireling = hireling;
+ SelectedNPC = null;
+ }
+
+ public static Vector3D RandomDirection(Vector3D position, float minRadius, float maxRadius)
+ {
+ var angle = (float)(FastRandom.Instance.NextDouble() * Math.PI * 2);
+ var radius = minRadius + (float)FastRandom.Instance.NextDouble() * (maxRadius - minRadius);
+ return new Vector3D(position.X + (float)Math.Cos(angle) * radius,
+ position.Y + (float)Math.Sin(angle) * radius,
+ position.Z);
+ }
+
+ public void AwayPet(GameClient client, PetAwayMessage message)
+ {
+ }
+
+ public void DeactivateCamera(GameClient client, DeActivateCameraCutsceneMode message)
+ {
+ InGameClient.SendMessage(new BoolDataMessage(Opcodes.CameraTriggerFadeToBlackMessage) { Field0 = true });
+ InGameClient.SendMessage(new SimpleMessage(Opcodes.CameraSriptedSequenceStopMessage) { });
+ //this.InGameClient.SendMessage(new ActivateCameraCutsceneMode() { Activate = true });
+ }
+
+ public void AcceptBossEncounter()
+ {
+ InGameClient.Game.AcceptBossEncounter();
+ }
+
+ public void DeclineBossEncounter()
+ {
+ InGameClient.Game.CurrentEncounter.activated = false;
+ }
+
+ public void TransmuteItemsPlayer(GameClient client, TransmuteItemsMessage message)
+ {
+ var recipeDefinition = ItemGenerator.GetRecipeDefinition(608170752);
+ for (var i = 0; i < message.CurrenciesCount; i++)
+ {
+ var data = ItemGenerator.GetItemDefinition(message.GBIDCurrencies[i]).Name;
+ switch (data)
+ {
+ case "p2_ActBountyReagent_01": break;
+ case "p2_ActBountyReagent_02": break;
+ case "p2_ActBountyReagent_03": break;
+ case "p2_ActBountyReagent_04": break;
+ case "p2_ActBountyReagent_05": break;
+ case "Crafting_Looted_Reagent_01": break;
+ }
+ }
+
+ foreach (var it in message.annItems)
+ {
+ var a = Inventory.GetItemByDynId(this, (uint)it);
+ }
+
+ Item ItemPortalToCows = null;
+ var Items = new List
- { };
+ for (var i = 0; i < message.ItemsCount; i++)
+ {
+ Items.Add(Inventory.GetItemByDynId(this, (uint)message.annItems[i]));
+ if (Items[i].SNO == ActorSno._x1_polearm_norm_unique_05)
+ ItemPortalToCows = Items[i];
+ }
+
+ //Type - 0 - New property
+ //Type - 1 - Transmutation
+ //Type - 2 -
+
+ if (ItemPortalToCows != null)
+ {
+ InGameClient.SendMessage(new TransmuteResultsMessage()
+ {
+ annItem = -1,
+ Type = -1,
+ GBIDFakeItem = -1,
+ GBIDPower = -1,
+ FakeItemStackCount = -1
});
- LoadCrafterData();
+ Inventory.DestroyInventoryItem(ItemPortalToCows);
+ World.SpawnMonster(ActorSno._p2_totallynotacowlevel_portal,
+ new Vector3D(Position.X + 5, Position.Y + 5, Position.Z));
+ }
+ else
+ {
+ InGameClient.SendMessage(new TransmuteResultsMessage()
+ {
+ annItem = (int)Items[0].DynamicID(this),
+ Type = 0,
+ GBIDFakeItem = -1,
+ GBIDPower = (int)Items[0].ItemDefinition.Hash,
+ FakeItemStackCount = -1
+ });
+ GrantCriteria(74987245494264);
+ GrantCriteria(74987258962046);
+ }
+ }
+
+ private bool WaitToSpawn(TickTimer timer)
+ {
+ while (!timer.TimedOut) ;
+
+ return true;
+ }
+
+ public void OpenNephalem(GameClient client, RiftStartAcceptedMessage message)
+ {
+ //396751 - X1_OpenWorld_Tiered_Rifts_Portal - Великий портал
+ //345935 - X1_OpenWorld_LootRunPortal - Обычные порталы
+ //408511 - X1_OpenWorld_Tiered_Rifts_Challenge_Portal
+
+ //1073741824 - Первый уровень Великого бафнутого
+ //0 - Первый уровень Великого
+ //
+ var activated = false;
+ var newTagMap = new TagMap();
+ World nephalemPWorld = null;
+ Actor lootRunObelisk = null;
+ Portal portal = null;
+ var map = WorldSno.__NONE;
+ var maps = new WorldSno[]
+ {
+ WorldSno.x1_lr_tileset_westmarch, //x1_lr_tileset_Westmarch
+ WorldSno.x1_lr_tileset_fortress_large, //_x1_lr_tileset_fortress_large
+ WorldSno.x1_lr_tileset_zoltruins, //x1_lr_tileset_zoltruins
+ WorldSno.x1_lr_tileset_hexmaze, //x1_lr_tileset_hexmaze
+ WorldSno.x1_lr_tileset_icecave, //x1_lr_tileset_icecave
+
+ WorldSno.x1_lr_tileset_crypt, //x1_lr_tileset_crypt
+ WorldSno.x1_lr_tileset_corruptspire //x1_lr_tileset_corruptspire
+
+ //288843, //x1_lr_tileset_sewers
+ };
+
+ switch (message.Field0)
+ {
+ #region Нефалемский портал
+
+ case -1:
+ Logger.Debug("Calling Nephalem Portal (Normal)");
+ activated = false;
+
+ foreach (var oldp in World.GetActorsBySNO(ActorSno._x1_openworld_lootrunportal,
+ ActorSno._x1_openworld_tiered_rifts_portal)) oldp.Destroy();
+
+ map = maps[RandomHelper.Next(0, maps.Length)];
+ //map = 288823;
+ newTagMap.Add(new TagKeySNO(526850), new TagMapEntry(526850, (int)map, 0)); //World
+ newTagMap.Add(new TagKeySNO(526853), new TagMapEntry(526853, 288482, 0)); //Zone
+ newTagMap.Add(new TagKeySNO(526851), new TagMapEntry(526851, 172, 0)); //Entry-Pointа
+ InGameClient.Game.WorldOfPortalNephalem = map;
+
+ while (true)
+ {
+ map = maps[RandomHelper.Next(0, maps.Length)];
+ if (map != InGameClient.Game.WorldOfPortalNephalem) break;
+ }
+
+ InGameClient.Game.WorldOfPortalNephalemSec = map;
+
+ nephalemPWorld = InGameClient.Game.GetWorld(InGameClient.Game.WorldOfPortalNephalem);
+
+ var exitSceneSno = -1;
+ foreach (var scene in nephalemPWorld.Scenes.Values)
+ if (scene.SceneSNO.Name.ToLower().Contains("exit"))
+ exitSceneSno = scene.SceneSNO.Id;
+ var exitSetted = false;
+ foreach (var actor in nephalemPWorld.Actors.Values)
+ if (actor is Portal)
+ {
+ var p = actor as Portal;
+ if (!actor.CurrentScene.SceneSNO.Name.ToLower().Contains("entrance"))
+ {
+ if (!actor.CurrentScene.SceneSNO.Name.ToLower().Contains("exit"))
+ {
+ actor.Destroy();
+ }
+ else if (!exitSetted)
+ {
+ p.Destination.DestLevelAreaSNO = 288684;
+ p.Destination.WorldSNO = (int)InGameClient.Game.WorldOfPortalNephalemSec;
+ exitSetted = true;
+
+ var nephalemPWorldS2 =
+ InGameClient.Game.GetWorld(InGameClient.Game.WorldOfPortalNephalemSec);
+ foreach (var atr in nephalemPWorldS2.Actors.Values)
+ if (atr is Portal)
+ {
+ if (!atr.CurrentScene.SceneSNO.Name.ToLower().Contains("entrance"))
+ {
+ atr.Destroy();
+ }
+ else
+ {
+ (atr as Portal).Destination.DestLevelAreaSNO = 332339;
+ (atr as Portal).Destination.WorldSNO =
+ (int)WorldSno.x1_tristram_adventure_mode_hub;
+ (atr as Portal).Destination.StartingPointActorTag = 172;
+ }
+ }
+ else if (atr is Waypoint)
+ {
+ atr.Destroy();
+ }
+ }
+ else
+ {
+ actor.Destroy();
+ }
+ }
+ else
+ {
+ p.Destination.DestLevelAreaSNO = 332339;
+ p.Destination.WorldSNO = (int)WorldSno.x1_tristram_adventure_mode_hub;
+ p.Destination.StartingPointActorTag = 24;
+ }
+ }
+ else if (actor is Waypoint)
+ {
+ actor.Destroy();
+ }
+
+ #region Activation
+
+ lootRunObelisk = World.GetActorBySNO(ActorSno._x1_openworld_lootrunobelisk_b);
+ lootRunObelisk.PlayAnimation(5, (AnimationSno)lootRunObelisk.AnimationSet.TagMapAnimDefault[AnimationSetKeys.Opening]);
+ lootRunObelisk.Attributes[GameAttribute.Team_Override] = activated ? -1 : 2;
+ lootRunObelisk.Attributes[GameAttribute.Untargetable] = !activated;
+ lootRunObelisk.Attributes[GameAttribute.NPC_Is_Operatable] = activated;
+ lootRunObelisk.Attributes[GameAttribute.Operatable] = activated;
+ lootRunObelisk.Attributes[GameAttribute.Operatable_Story_Gizmo] = activated;
+ lootRunObelisk.Attributes[GameAttribute.Disabled] = !activated;
+ lootRunObelisk.Attributes[GameAttribute.Immunity] = !activated;
+ lootRunObelisk.Attributes.BroadcastChangedIfRevealed();
+
+ lootRunObelisk.CollFlags = 0;
+ World.BroadcastIfRevealed(plr => new ACDCollFlagsMessage
+ {
+ ActorID = lootRunObelisk.DynamicID(plr),
+ CollFlags = 0
+ }, lootRunObelisk);
+ portal = new Portal(World, ActorSno._x1_openworld_lootrunportal, newTagMap);
+
+ TickTimer timeout = new SecondsTickTimer(World.Game, 3.5f);
+ var boom = System.Threading.Tasks.Task.Factory.StartNew(() => WaitToSpawn(timeout));
+ boom.ContinueWith(delegate
+ {
+ portal.EnterWorld(lootRunObelisk.Position);
+ //Quest - 382695 - The Great Nephalem
+ //Quest - 337492 - Just Nephalem
+ foreach (var plr in InGameClient.Game.Players.Values)
+ {
+ plr.InGameClient.SendMessage(new QuestUpdateMessage()
+ {
+ snoQuest = 0x00052654,
+ snoLevelArea = 0x000466E2,
+ StepID = -1,
+ DisplayButton = true,
+ Failed = false
+ });
+
+ plr.InGameClient.SendMessage(new QuestCounterMessage()
+ {
+ snoQuest = 0x00052654,
+ snoLevelArea = 0x000466E2,
+ StepID = -1,
+ Checked = 1,
+ Counter = 1
+ });
+
+ plr.InGameClient.SendMessage(new QuestUpdateMessage()
+ {
+ snoQuest = 0x00052654,
+ snoLevelArea = 0x000466E2,
+ StepID = 1,
+ DisplayButton = true,
+ Failed = false
+ });
+
+ plr.InGameClient.Game.ActiveNephalemPortal = true;
+ plr.InGameClient.SendMessage(new SimpleMessage(Opcodes.RiftStartedMessage));
+
+ plr.InGameClient.SendMessage(new GameSyncedDataMessage
+ {
+ SyncedData = new GameSyncedData
+ {
+ GameSyncedFlags = 6,
+ Act = 3000, //act id
+ InitialMonsterLevel = InGameClient.Game.InitialMonsterLevel, //InitialMonsterLevel
+ MonsterLevel = 0x64E4425E, //MonsterLevel
+ RandomWeatherSeed = InGameClient.Game.WeatherSeed, //RandomWeatherSeed
+ OpenWorldMode = -1, //OpenWorldMode
+ OpenWorldModeAct = -1, //OpenWorldModeAct
+ OpenWorldModeParam = -1, //OpenWorldModeParam
+ OpenWorldTransitionTime = 0x00000064, //OpenWorldTransitionTime
+ OpenWorldDefaultAct = 100, //OpenWorldDefaultAct
+ OpenWorldBonusAct = -1, //OpenWorldBonusAct
+ SNODungeonFinderLevelArea = 0x00000001, //SNODungeonFinderLevelArea
+ LootRunOpen = -1, //LootRunOpen //0 - Великий Портал
+ OpenLootRunLevel = 0, //OpenLootRunLevel
+ LootRunBossDead = 0, //LootRunBossDead
+ HunterPlayerIdx = 0, //HunterPlayerIdx
+ LootRunBossActive = -1, //LootRunBossActive
+ TieredLootRunFailed = 0, //TieredLootRunFailed
+ LootRunChallengeCompleted = 0, //LootRunChallengeCompleted
+ SetDungeonActive = 0, //SetDungeonActive
+ Pregame = 0, //Pregame
+ PregameEnd = 0, //PregameEnd
+ RoundStart = 0, //RoundStart
+ RoundEnd = 0, //RoundEnd
+ PVPGameOver = 0x0, //PVPGameOver
+ field_v273 = 0x0,
+ TeamWins = new[] { 0x0, 0x0 }, //TeamWins
+ TeamScore = new[] { 0x0, 0x0 }, //TeamScore
+ PVPGameResult = new[] { 0x0, 0x0 }, //PVPGameResult
+ PartyGuideHeroId =
+ 0x0, //PartyGuideHeroId //new EntityId() { High = 0, Low = (long)this.Players.Values.First().Toon.PersistentID }
+ TiredRiftPaticipatingHeroID =
+ new long[] { 0x0, 0x0, 0x0, 0x0 } //TiredRiftPaticipatingHeroID
+ }
+ });
+ }
+ });
+
+ #endregion
- /**/
- }
- public void UnlockTransmog(int transmogGBID)
- {
- if (learnedTransmogs.Contains(transmogGBID)) return;
- InGameClient.SendMessage(new UnlockTransmogMessage() { TransmogGBID = transmogGBID });
+ break;
- Logger.Trace("Learning transmog #{0}", transmogGBID);
- learnedTransmogs.Add(transmogGBID);
- mystic_data.LearnedRecipes = SerializeBytes(learnedTransmogs);
- World.Game.GameDBSession.SessionUpdate(mystic_data);
+ #endregion
- LoadCrafterData();
- }
- #endregion
+ #region Великий портал
- #region update-logic
+ default:
+ InGameClient.Game.NephalemGreaterLevel = message.Field0;
- int PreviousLevelArea = -1;
+ Logger.Debug("Calling Nephalem Portal (Level: {0})", message.Field0);
+ activated = false;
+ foreach (var oldp in World.GetActorsBySNO(ActorSno._x1_openworld_lootrunportal,
+ ActorSno._x1_openworld_tiered_rifts_portal)) oldp.Destroy();
- private List TimedActions = new List();
+ InGameClient.Game.ActiveNephalemPortal = true;
+ InGameClient.Game.NephalemGreater = true;
+ //disable banner while greater is active enable once boss is killed or portal is closed /advocaite
+ Attributes[GameAttribute.Banner_Usable] = false;
+ map = maps[RandomHelper.Next(0, maps.Length)];
+ newTagMap.Add(new TagKeySNO(526850), new TagMapEntry(526850, (int)map, 0)); //World
+ newTagMap.Add(new TagKeySNO(526853), new TagMapEntry(526853, 288482, 0)); //Zone
+ newTagMap.Add(new TagKeySNO(526851), new TagMapEntry(526851, 172, 0)); //Entry-Pointа
+ InGameClient.Game.WorldOfPortalNephalem = map;
- public int VaultsDone = 0;
- public int SpikeTrapsKilled = 0;
+ nephalemPWorld = InGameClient.Game.GetWorld(map);
+ foreach (var actor in nephalemPWorld.Actors.Values)
+ if (actor is Portal)
+ {
+ if (!actor.CurrentScene.SceneSNO.Name.ToLower().Contains("entrance"))
+ {
+ actor.Destroy();
+ }
+ else
+ {
+ (actor as Portal).Destination.DestLevelAreaSNO = 332339;
+ (actor as Portal).Destination.WorldSNO = (int)WorldSno.x1_tristram_adventure_mode_hub;
+ (actor as Portal).Destination.StartingPointActorTag = 24;
+ }
+ }
+ else if (actor is Waypoint)
+ {
+ actor.Destroy();
+ }
- public void AddTimedAction(float seconds, Action onTimeout)
- {
- TimedActions.Add(TickTimer.WaitSeconds(World.Game, seconds, onTimeout));
- }
+ #region Активация
- public void Update(int tickCounter)
- {
- if (BetweenWorlds) return;
+ lootRunObelisk = World.GetActorBySNO(ActorSno._x1_openworld_lootrunobelisk_b);
+ lootRunObelisk.PlayAnimation(5, (AnimationSno)lootRunObelisk.AnimationSet.TagMapAnimDefault[AnimationSetKeys.Opening]);
+ lootRunObelisk.Attributes[GameAttribute.Team_Override] = activated ? -1 : 2;
+ lootRunObelisk.Attributes[GameAttribute.Untargetable] = !activated;
+ lootRunObelisk.Attributes[GameAttribute.NPC_Is_Operatable] = activated;
+ lootRunObelisk.Attributes[GameAttribute.Operatable] = activated;
+ lootRunObelisk.Attributes[GameAttribute.Operatable_Story_Gizmo] = activated;
+ lootRunObelisk.Attributes[GameAttribute.Disabled] = !activated;
+ lootRunObelisk.Attributes[GameAttribute.Immunity] = !activated;
+ lootRunObelisk.Attributes.BroadcastChangedIfRevealed();
+
+ lootRunObelisk.CollFlags = 0;
+ World.BroadcastIfRevealed(plr => new ACDCollFlagsMessage
+ {
+ ActorID = lootRunObelisk.DynamicID(plr),
+ CollFlags = 0
+ }, lootRunObelisk);
+ portal = new Portal(World, ActorSno._x1_openworld_tiered_rifts_portal, newTagMap);
+
+ TickTimer altTimeout = new SecondsTickTimer(World.Game, 3.5f);
+ var altBoom = System.Threading.Tasks.Task.Factory.StartNew(() => WaitToSpawn(altTimeout));
+ altBoom.ContinueWith(delegate
+ {
+ portal.EnterWorld(lootRunObelisk.Position);
+ //Quest - 382695 - Великий Нефалемский
+ //Quest - 337492 - Просто Нефалемский
+
+ //this.ChangeWorld(NephalemPWorld, NephalemPWorld.GetStartingPointById(172).Position);
+
+ foreach (var plr in InGameClient.Game.Players.Values)
+ {
+ plr.InGameClient.SendMessage(new SimpleMessage(Opcodes.RiftStartedMessage));
+ plr.InGameClient.SendMessage(new QuestUpdateMessage()
+ {
+ snoQuest = 337492,
+ snoLevelArea = 0x000466E2,
+ StepID = -1,
+ DisplayButton = true,
+ Failed = false
+ });
+ plr.InGameClient.SendMessage(new QuestCounterMessage()
+ {
+ snoQuest = 337492,
+ snoLevelArea = 0x000466E2,
+ StepID = -1,
+ Checked = 1,
+ Counter = 1
+ });
+ plr.InGameClient.SendMessage(new QuestUpdateMessage()
+ {
+ snoQuest = 337492,
+ snoLevelArea = 0x000466E2,
+ StepID = 13,
+ DisplayButton = true,
+ Failed = false
+ });
+ plr.InGameClient.SendMessage(new GameSyncedDataMessage
+ {
+ SyncedData = new GameSyncedData
+ {
+ GameSyncedFlags = 6,
+ Act = 3000, //act id
+ InitialMonsterLevel = InGameClient.Game.InitialMonsterLevel, //InitialMonsterLevel
+ MonsterLevel = 0x64E4425E, //MonsterLevel
+ RandomWeatherSeed = InGameClient.Game.WeatherSeed, //RandomWeatherSeed
+ OpenWorldMode = -1, //OpenWorldMode
+ OpenWorldModeAct = -1, //OpenWorldModeAct
+ OpenWorldModeParam = -1, //OpenWorldModeParam
+ OpenWorldTransitionTime = 0x00000064, //OpenWorldTransitionTime
+ OpenWorldDefaultAct = 100, //OpenWorldDefaultAct
+ OpenWorldBonusAct = -1, //OpenWorldBonusAct
+ SNODungeonFinderLevelArea = 0x00000001, //SNODungeonFinderLevelArea
+ LootRunOpen = 44, //LootRunOpen //0 - Великий Портал
+ OpenLootRunLevel = 0, //OpenLootRunLevel
+ LootRunBossDead = 0, //LootRunBossDead
+ HunterPlayerIdx = 0, //HunterPlayerIdx
+ LootRunBossActive = -1, //LootRunBossActive
+ TieredLootRunFailed = 0, //TieredLootRunFailed
+ LootRunChallengeCompleted = 0, //LootRunChallengeCompleted
+ SetDungeonActive = 0, //SetDungeonActive
+ Pregame = 0, //Pregame
+ PregameEnd = 0, //PregameEnd
+ RoundStart = 0, //RoundStart
+ RoundEnd = 0, //RoundEnd
+ PVPGameOver = 0x0, //PVPGameOver
+ field_v273 = 0x0,
+ TeamWins = new[] { 0x0, 0x0 }, //TeamWins
+ TeamScore = new[] { 0x0, 0x0 }, //TeamScore
+ PVPGameResult = new[] { 0x0, 0x0 }, //PVPGameResult
+ PartyGuideHeroId =
+ 0x0, //PartyGuideHeroId //new EntityId() { High = 0, Low = (long)this.Players.Values.First().Toon.PersistentID }
+ TiredRiftPaticipatingHeroID =
+ new long[] { 0x0, 0x0, 0x0, 0x0 } //TiredRiftPaticipatingHeroID
+ }
+ });
+ plr.InGameClient.SendMessage(new IntDataMessage(Opcodes.DungeonFinderSeedMessage)
+ {
+ Field0 = 0x3E0FC64C
+ });
+ plr.InGameClient.SendMessage(new IntDataMessage(Opcodes.DungeonFinderParticipatingPlayerCount)
+ {
+ Field0 = 1
+ });
+ plr.InGameClient.SendMessage(new FloatDataMessage(Opcodes.DungeonFinderProgressMessage)
+ {
+ Field0 = 0
+ });
+ plr.InGameClient.SendMessage(new SNODataMessage(Opcodes.DungeonFinderSetTimedEvent)
+ {
+ Field0 = -1
+ });
+ plr.Attributes[GameAttribute.Tiered_Loot_Run_Death_Count] = 0;
+ }
+ });
+
+ #endregion
+
+
+ break;
+
+ #endregion
+ }
+ }
+
+ private void OnTutorialShown(GameClient client, TutorialShownMessage message)
+ {
+ // Server has to save what tutorials are shown, so the player
+ // does not have to see them over and over...
+ var index = ItemGenerator.Tutorials.IndexOf(message.SNOTutorial);
+ if (index == -1) return;
+ var seenTutorials = Toon.GameAccount.DBGameAccount.SeenTutorials;
+ if (seenTutorials.Length <= 34)
+ seenTutorials = new byte[]
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ seenTutorials[index / 8] |= (byte)(1 << (index % 8));
+
+ lock (Toon.GameAccount.DBGameAccount)
+ {
+ var gameAccount = Toon.GameAccount.DBGameAccount;
+ gameAccount.SeenTutorials = seenTutorials;
+ DBSessions.SessionUpdate(gameAccount);
+ }
+ //*/
+ }
+
+ private void OnConfirm(GameClient client, AcceptConfirmMessage message)
+ {
+ if (ConfirmationResult != null)
+ {
+ ConfirmationResult.Invoke();
+ ConfirmationResult = null;
+ }
+ }
+
+ private void OnSpendParagonPointsMessage(GameClient client, SpendParagonPointsMessage message)
+ {
+ var bonus = ItemGenerator.GetParagonBonusTable(Toon.Class).FirstOrDefault(b => b.Hash == message.BonusGBID);
+
+ if (bonus == null) return;
+ if (message.Amount > Attributes[GameAttribute.Paragon_Bonus_Points_Available, bonus.Category]) return;
+ //if (this.ParagonBonuses[(bonus.Category * 4) + bonus.Index - 1] + (byte)message.Amount > bonus.Limit) return;
+
+ // message.Amount have the value send to add on attr of Paragon tabs.
+ ParagonBonuses[bonus.Category * 4 + bonus.Index - 1] += (ushort)message.Amount;
+
+ var dbToon = Toon.DBToon;
+ dbToon.ParagonBonuses = ParagonBonuses;
+ World.Game.GameDBSession.SessionUpdate(dbToon);
+
+ SetAttributesByItems();
+ SetAttributesByItemProcs();
+ SetAttributesByGems();
+ SetAttributesByItemSets();
+ SetAttributesByPassives();
+ SetAttributesByParagon();
+ Attributes.BroadcastChangedIfRevealed();
+ UpdatePercentageHP(PercHPbeforeChange);
+ }
+
+ private void OnResetParagonPointsMessage(GameClient client, ResetParagonPointsMessage message)
+ {
+ ParagonBonuses = new ushort[]
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ var dbToon = Toon.DBToon;
+ dbToon.ParagonBonuses = ParagonBonuses;
+ World.Game.GameDBSession.SessionUpdate(dbToon);
+
+ SetAttributesByItems();
+ SetAttributesByItemProcs();
+ SetAttributesByGems();
+ SetAttributesByItemSets();
+ SetAttributesByPassives();
+ SetAttributesByParagon();
+ Attributes.BroadcastChangedIfRevealed();
+ UpdatePercentageHP(PercHPbeforeChange);
+ }
+
+ private void OnMailRead(GameClient client, MailReadMessage message)
+ {
+ //does it make sense?
+ }
+
+ private void OnMailRetrieve(GameClient client, MailRetrieveMessage message)
+ {
+ var dbMail = World.Game.GameDBSession.SessionGet((ulong)message.MailId);
+ if (dbMail == null || dbMail.DBToon.Id != Toon.PersistentID) return;
+ dbMail.Claimed = true;
+ World.Game.GameDBSession.SessionUpdate(dbMail);
+
+ if (dbMail.ItemGBID != -1)
+ Inventory.PickUp(ItemGenerator.CookFromDefinition(World, ItemGenerator.GetItemDefinition(dbMail.ItemGBID),
+ -1, true));
+
+ LoadMailData();
+ }
+
+ private void OnStashIconsAssign(GameClient client, StashIconStateAssignMessage message)
+ {
+ if (message.StashIcons.Length != 4) return;
+ lock (Toon.GameAccount.DBGameAccount)
+ {
+ var dbGAcc = Toon.GameAccount.DBGameAccount;
+ dbGAcc.StashIcons = message.StashIcons;
+ DBSessions.SessionUpdate(dbGAcc);
+ }
+ //LoadStashIconsData();
+ }
+
+ public void PlayCutscene(int cutsceneId)
+ {
+ InGameClient.SendMessage(new PlayCutsceneMessage()
+ {
+ Index = cutsceneId
+ });
+ }
+
+ private void OnTranslateFacing(GameClient client, PlayerTranslateFacingMessage message)
+ {
+ SetFacingRotation(message.Angle);
+
+ World.BroadcastExclusive(plr => new ACDTranslateFacingMessage
+ {
+ ActorId = DynamicID(plr),
+ Angle = message.Angle,
+ TurnImmediately = message.TurnImmediately
+ }, this);
+ }
+
+ private void OnAssignActiveSkill(GameClient client, AssignSkillMessage message)
+ {
+ var old_skills = SkillSet.ActiveSkills.Select(s => s.snoSkill).ToList();
+ foreach (var skill in old_skills)
+ {
+ var power = PowerLoader.CreateImplementationForPowerSNO(skill);
+ if (power != null && power.EvalTag(PowerKeys.SynergyPower) != -1)
+ World.BuffManager.RemoveBuffs(this, power.EvalTag(PowerKeys.SynergyPower));
+ }
+
+ var oldSNOSkill = SkillSet.ActiveSkills[message.SkillIndex].snoSkill; // find replaced skills SNO.
+ if (oldSNOSkill != -1)
+ {
+ Attributes[GameAttribute.Skill, oldSNOSkill] = 0;
+ World.BuffManager.RemoveBuffs(this, oldSNOSkill);
+
+ var rem = new List();
+ foreach (var fol in Followers.Where(f =>
+ World.GetActorByGlobalId(f.Key) == null ||
+ World.GetActorByGlobalId(f.Key).Attributes[GameAttribute.Summoned_By_SNO] == oldSNOSkill))
+ rem.Add(fol.Key);
+ foreach (var rm in rem)
+ DestroyFollowerById(rm);
+ }
+
+ Attributes[GameAttribute.Skill, message.SNOSkill] = 1;
+ //scripted //this.Attributes[GameAttribute.Skill_Total, message.SNOSkill] = 1;
+ SkillSet.ActiveSkills[message.SkillIndex].snoSkill = message.SNOSkill;
+ SkillSet.ActiveSkills[message.SkillIndex].snoRune = message.RuneIndex;
+ SkillSet.SwitchUpdateSkills(message.SkillIndex, message.SNOSkill, message.RuneIndex, Toon);
+ SetAttributesSkillSets();
+
+ Attributes.BroadcastChangedIfRevealed();
+ UpdateHeroState();
+
+ var cooldownskill = SkillSet.ActiveSkills.GetValue(message.SkillIndex);
+
+ if (SkillSet.HasSkill(460757))
+ foreach (var skill in SkillSet.ActiveSkills)
+ if (skill.snoSkill == 460757)
+ if (skill.snoRune == 3)
+ World.BuffManager.AddBuff(this, this, new P6_Necro_Devour_Aura());
+ else
+ World.BuffManager.RemoveBuffs(this, 474325);
+
+ if (SkillSet.HasSkill(460870))
+ foreach (var skill in SkillSet.ActiveSkills)
+ if (skill.snoSkill == 460870)
+ if (skill.snoRune == 4)
+ World.BuffManager.AddBuff(this, this, new P6_Necro_Frailty_Aura());
+ else
+ World.BuffManager.RemoveBuffs(this, 473992);
+
+
+ //_StartSkillCooldown((cooldownskill as ActiveSkillSavedData).snoSkill, SkillChangeCooldownLength);
+ }
+
+ private void OnAssignPassiveSkills(GameClient client, AssignTraitsMessage message)
+ {
+ for (var i = 0; i < message.SNOPowers.Length; ++i)
+ {
+ var oldSNOSkill = SkillSet.PassiveSkills[i]; // find replaced skills SNO.
+ if (message.SNOPowers[i] != oldSNOSkill)
+ {
+ if (oldSNOSkill != -1)
+ {
+ World.BuffManager.RemoveAllBuffs(this);
+ // switch off old passive skill
+ Attributes[GameAttribute.Trait, oldSNOSkill] = 0;
+ Attributes[GameAttribute.Skill, oldSNOSkill] = 0;
+ //scripted //this.Attributes[GameAttribute.Skill_Total, oldSNOSkill] = 0;
+ }
+
+ if (message.SNOPowers[i] != -1)
+ {
+ // switch on new passive skill
+ Attributes[GameAttribute.Trait, message.SNOPowers[i]] = 1;
+ Attributes[GameAttribute.Skill, message.SNOPowers[i]] = 1;
+ //scripted //this.Attributes[GameAttribute.Skill_Total, message.SNOPowers[i]] = 1;
+ }
+
+ SkillSet.PassiveSkills[i] = message.SNOPowers[i];
+ }
+ }
+
+ SkillSet.UpdatePassiveSkills(Toon);
+
+ var skills = SkillSet.ActiveSkills.Select(s => s.snoSkill).ToList();
+ foreach (var skill in skills)
+ _StartSkillCooldown(skill, SkillChangeCooldownLength);
+
+ SetAttributesByItems();
+ SetAttributesByGems();
+ SetAttributesByItemSets();
+ SetAttributesByPassives();
+ SetAttributesByParagon();
+ SetAttributesSkillSets();
+ Inventory.CheckWeapons(); //Handles removal of Heavenly Strength
+ Attributes.BroadcastChangedIfRevealed();
+ UpdateHeroState();
+ UpdatePercentageHP(PercHPbeforeChange);
+ }
+
+ private void OnUnassignActiveSkill(GameClient client, UnassignSkillMessage message)
+ {
+ var oldSNOSkill = SkillSet.ActiveSkills[message.SkillIndex].snoSkill; // find replaced skills SNO.
+ if (oldSNOSkill != -1)
+ {
+ Attributes[GameAttribute.Skill, oldSNOSkill] = 0;
+ World.BuffManager.RemoveBuffs(this, oldSNOSkill);
+
+ var rem = new List();
+ foreach (var fol in Followers.Where(f =>
+ Math.Abs(World.GetActorByGlobalId(f.Key).Attributes[GameAttribute.Summoned_By_SNO] -
+ oldSNOSkill) < 0.001))
+ rem.Add(fol.Key);
+ foreach (var rm in rem)
+ DestroyFollowerById(rm);
+ }
+
+ SkillSet.ActiveSkills[message.SkillIndex].snoSkill = -1;
+ SkillSet.ActiveSkills[message.SkillIndex].snoRune = -1;
+ SkillSet.SwitchUpdateSkills(message.SkillIndex, -1, -1, Toon);
+ SetAttributesSkillSets();
+
+ Attributes.BroadcastChangedIfRevealed();
+ UpdateHeroState();
+ }
+
+ public void SetNewAttributes()
+ {
+ //this.Attributes[GameAttribute.Attacks_Per_Second] = 1.0f;
+ //this.Attributes[GameAttribute.Attacks_Per_Second_Bonus] = 1.0f;
+ //this.Attributes[GameAttribute.Gold] = 1;
+ //[GameAttribute.Damage_Weapon_Min_Total, 0]
+ Attributes[GameAttribute.Attacks_Per_Second_Percent] = 0;
+ Attributes[GameAttribute.Attacks_Per_Second_Percent_Uncapped] = 0;
+ Attributes[GameAttribute.Attacks_Per_Second_Percent_Reduction] = 0;
+ Attributes[GameAttribute.Attacks_Per_Second_Percent_Cap] = 0;
+ //this.Attributes[GameAttribute.Gold_PickUp_Radius] = 5f;
+ /*
+ this.Attributes[GameAttribute.Experience_Bonus_Percent_Anniversary_Buff] = 100;
+ this.Attributes[GameAttribute.Experience_Bonus_Percent_Community_Buff] = 100;
+ this.Attributes[GameAttribute.Experience_Bonus_Percent_Handicap] = 100;
+ this.Attributes[GameAttribute.Experience_Bonus_Percent_IGR_Buff] = 100;
+ this.Attributes[GameAttribute.Experience_Bonus_Percent_Potion_Buff] = 1;
+ //*/
+ /*
+ this.InGameClient.SendMessage(new PlayerSkillsMessage()
+ {
+ PlayerIndex = this.PlayerIndex,
+ ActiveSkills = this.SkillSet.ActiveSkills,
+ Traits = new int[4] { 0x00032E5E, -1, -1, -1 },
+ LegendaryPowers = new int[4] { -1, -1, -1, -1 }
+ });
+ //*/
+ }
+
+ private void _StartSkillCooldown(int snoPower, float seconds)
+ {
+ World.BuffManager.AddBuff(this, this,
+ new CooldownBuff(snoPower, seconds));
+ }
+
+ //private void OnPlayerChangeHotbarButtonMessage(GameClient client, PlayerChangeHotbarButtonMessage message)
+ //{
+ // this.SkillSet.HotBarSkills[message.BarIndex] = message.ButtonData;
+ //}
+
+ private void OnObjectTargeted(GameClient client, TargetMessage message)
+ {
+ if (message.TargetID != 0xffffffff)
+ message.TargetID = World.GetGlobalId(this, message.TargetID);
+
+ if (Toon.Class == ToonClass.Crusader)
+ if (World.BuffManager.HasBuff(this)) //Crusader -> cancel Steed Charge
+ World.BuffManager.RemoveBuffs(this, 243853);
+
+ var powerHandled =
+ World.PowerManager.RunPower(this, message.PowerSNO, message.TargetID, message.Place.Position, message);
+
+ if (!powerHandled)
+ {
+ var actor = World.GetActorByGlobalId(message.TargetID);
+ if (actor == null) return;
+
+
+#if DEBUG
+ Logger.Warn("OnTargetedActor ID: {0}, Name: {1}, NumInWorld: {2}", actor.SNO, actor.Name,
+ actor.NumberInWorld);
+#else
+#endif
+ if (actor.GBHandle.Type == 1 && actor.Attributes[GameAttribute.TeamID] == 10)
+ ExpBonusData.MonsterAttacked(InGameClient.Game.TickCounter);
+ actor.OnTargeted(this, message);
+ }
+
+ ExpBonusData.Check(2);
+ }
+
+ private int _hackCounter = 0;
+
+ public bool SpeedCheckDisabled = false;
+
+ public static byte[] StringToByteArray(string hex)
+ {
+ return Enumerable.Range(0, hex.Length)
+ .Where(x => x % 2 == 0)
+ .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
+ .ToArray();
+ }
+
+ public int i = 0;
+
+ private void OnPlayerMovement(GameClient client, ACDClientTranslateMessage message)
+ {
+ Attributes.BroadcastChangedIfRevealed();
+ var a = GetActorsInRange(15f);
+
+ #region
+
+ //UpdateExp(5000000);
+ /*
+ this.Attributes[GameAttribute.Jewel_Upgrades_Max] = 3;
+ this.Attributes[GameAttribute.Jewel_Upgrades_Bonus] = 2;
+ this.Attributes[GameAttribute.Jewel_Upgrades_Used] = 0;
+ Attributes[GameAttribute.Currencies_Discovered] = 20;
+ this.Attributes.BroadcastChangedIfRevealed();
+ var Quest = DiIiS_NA.Core.MPQ.MPQStorage.Data.Assets[Core.Types.SNO.SNOGroup.Quest][337492].Data;
+ //*/
+ //this.Toon.BigPortalKey++;
+ //this.Toon.CraftItem4++;
+ /*
+ //Приглашение на великий портал
+ InGameClient.SendMessage(new MessageSystem.Message.Definitions.Encounter.RiftJoinMessage()
+ {
+ PlayerIndex = 0,
+ RiftStartServerTime = this.InGameClient.Game.TickCounter,
+ RiftTier = 0
+ });
+ /*
+ //Результаты прохождения подземелья
+ InGameClient.SendMessage(new MessageSystem.Message.Definitions.Dungeon.SetDungeonResultsMessage()
+ {
+ SNOQuestKill = -1,
+ QuestKillMonsterCounter = 0,
+ SNOQuestBonus1 = -1,
+ QuestBonus1Success = false,
+ SNOQuestBonus2 = -1,
+ QuestBonus2Success = false,
+ SNOQuestMastery = -1,
+ QuestMasterySuccess = false,
+ QuestKillSuccess = false,
+ ShowTotalTime = true,
+ TimeTaken = 120,
+ TargetTime = 200
+ });
+ /*
+ //Приглашение в комплектное подземелье
+ InGameClient.SendMessage(new MessageSystem.Message.Definitions.Dungeon.SetDungeonDialogMessage()
+ {
+ PlayerIndex = 0,
+ LabelDescription = 1,
+ LabelTitle = 1
+ }) ;
+ /*
+ InGameClient.SendMessage(new BroadcastTextMessage()
+ {
+ Field0 = "Тест"
+ });
+ /*
+ this.InGameClient.SendMessage(new DisplayGameTextMessage(Opcodes.DisplayGameTextMessage)
+ {
+ Message = "Пампам"
+ });
+ //*/
+
+ #endregion
+
+ if (World == null) return;
+
+ if (Dead)
+ {
+ World.BroadcastIfRevealed(ACDWorldPositionMessage, this);
+ return;
+ }
+
+ if (World.Game.Paused || BetweenWorlds) return;
+
+ if (message.MovementSpeed > Attributes[GameAttribute.Running_Rate_Total] * 1.5f && !SpeedCheckDisabled)
+ {
+ _hackCounter++;
+ if (_hackCounter > 5) _hackCounter = 0;
+ World.BroadcastIfRevealed(ACDWorldPositionMessage, this);
+ return;
+ }
+
+ if (message.Position != null)
+ {
+ if (PowerMath.Distance2D(message.Position, Position) > 300f)
+ {
+ World.BroadcastIfRevealed(ACDWorldPositionMessage, this);
+ InGameClient.SendMessage(new ACDTranslateSyncMessage()
+ {
+ ActorId = DynamicID(this),
+ Position = Position
+ });
+ return;
+ }
+
+ Position = message.Position;
+ }
+
+ SetFacingRotation(message.Angle);
+
+ if (IsCasting) StopCasting();
+ World.BuffManager.RemoveBuffs(this, 298038);
+
+ RevealScenesToPlayer();
+ RevealPlayersToPlayer();
+ RevealActorsToPlayer();
+
+ World.BroadcastExclusive(plr => new ACDTranslateNormalMessage
+ {
+ ActorId = DynamicID(plr),
+ Position = Position,
+ Angle = message.Angle,
+ SnapFacing = false,
+ MovementSpeed = message.MovementSpeed,
+ AnimationTag = message.AnimationTag
+ }, this, true);
+
+ foreach (var actor in GetActorsInRange())
+ actor.OnPlayerApproaching(this);
+
+ VacuumPickup();
+ if (World.Game.OnLoadWorldActions.ContainsKey(World.SNO))
+ {
+ Logger.Debug("OnLoadWorldActions: {0}", World.SNO);
+ lock (World.Game.OnLoadWorldActions[World.SNO])
+ {
+ try
+ {
+ foreach (var action in World.Game.OnLoadWorldActions[World.SNO]) action.Invoke();
+ }
+ catch
+ {
+ }
+
+ World.Game.OnLoadWorldActions[World.SNO].Clear();
+ }
+ }
+
+ if (World.Game.OnLoadSceneActions.ContainsKey(CurrentScene.SceneSNO.Id))
+ {
+ Logger.Debug("OnLoadSceneActions: {0}", CurrentScene.SceneSNO.Id);
+ lock (World.Game.OnLoadSceneActions[CurrentScene.SceneSNO.Id])
+ {
+ try
+ {
+ foreach (var action in World.Game.OnLoadSceneActions[CurrentScene.SceneSNO.Id]) action.Invoke();
+ }
+ catch
+ {
+ }
+
+ World.Game.OnLoadSceneActions[CurrentScene.SceneSNO.Id].Clear();
+ }
+ }
+
+ if (CurrentScene.SceneSNO.Id != PreSceneId)
+ {
+ PreSceneId = CurrentScene.SceneSNO.Id;
+ var levelArea = CurrentScene.Specification.SNOLevelAreas[0];
+ if (World.Game.QuestProgress.QuestTriggers.ContainsKey(levelArea)) //EnterLevelArea
+ {
+ var trigger = World.Game.QuestProgress.QuestTriggers[levelArea];
+ if (trigger.triggerType == DiIiS_NA.Core.MPQ.FileFormats.QuestStepObjectiveType.EnterLevelArea)
+ try
+ {
+ trigger.questEvent.Execute(World); // launch a questEvent
+ }
+ catch (Exception e)
+ {
+ Logger.WarnException(e, "questEvent()");
+ }
+ }
+
+ Attributes[GameAttribute.Corpse_Resurrection_Charges] =
+ 3; // Reset resurrection charges on zone change (TODO: do not reset charges on reentering the same zone)
+
+#if DEBUG
+ Logger.Warn("Player Location {0}, Scene: {1} SNO: {2} LevelArea: {3}", Toon.Name,
+ CurrentScene.SceneSNO.Name, CurrentScene.SceneSNO.Id, CurrentScene.Specification.SNOLevelAreas[0]);
+#else
+#endif
+ }
+
+ LastMovementTick = World.Game.TickCounter;
+ }
+
+ private void OnCancelChanneledSkill(GameClient client, CancelChanneledSkillMessage message)
+ {
+ World.PowerManager.CancelChanneledSkill(this, message.PowerSNO);
+ }
+
+ private void OnRequestBuffCancel(GameClient client, RequestBuffCancelMessage message)
+ {
+ World.BuffManager.RemoveBuffs(this, message.PowerSNOId);
+ }
+
+ private void OnSecondaryPowerMessage(GameClient client, SecondaryAnimationPowerMessage message)
+ {
+ World.PowerManager.RunPower(this, message.PowerSNO, (uint)message.annTarget);
+ }
+
+ private void OnMiscPowerMessage(GameClient client, MiscPowerMessage message)
+ {
+ World.PowerManager.RunPower(this, message.PowerSNO);
+ }
+
+ private void OnLoopingAnimationPowerMessage(GameClient client, LoopingAnimationPowerMessage message)
+ {
+ StartCasting(150, new Action(() =>
+ {
+ try
+ {
+ World.PowerManager.RunPower(this, message.snoPower);
+ }
+ catch
+ {
+ }
+ }), message.snoPower);
+ }
+
+ private void OnTryWaypoint(GameClient client, TryWaypointMessage tryWaypointMessage)
+ {
+ var wpWorld = World.Game.GetWayPointWorldById(tryWaypointMessage.nWaypoint);
+ var wayPoint = wpWorld.GetWayPointById(tryWaypointMessage.nWaypoint);
+ if (wayPoint == null) return;
+ Logger.Debug("---Waypoint Debug---");
+ var proximity = new RectangleF(wayPoint.Position.X - 1f, wayPoint.Position.Y - 1f, 2f, 2f);
+ var scenes = wpWorld.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];
+ Logger.Debug(
+ $"OnTryWaypoint: Id: {tryWaypointMessage.nWaypoint}, WorldId: {wpWorld.SNO}, levelArea: {levelArea}");
+ Logger.Debug($"WpWorld: {wpWorld}, wayPoint: {wayPoint}");
+ InGameClient.SendMessage(new SimpleMessage(Opcodes.LoadingWarping));
+ if (wpWorld == World)
+ Teleport(wayPoint.Position);
+ else
+ ChangeWorld(wpWorld, wayPoint.Position);
+
+ //handling quest triggers
+ if (World.Game.QuestProgress.QuestTriggers.ContainsKey(levelArea)) //EnterLevelArea
+ {
+ var trigger = World.Game.QuestProgress.QuestTriggers[levelArea];
+ if (trigger.triggerType == DiIiS_NA.Core.MPQ.FileFormats.QuestStepObjectiveType.EnterLevelArea)
+ try
+ {
+ trigger.questEvent.Execute(World); // launch a questEvent
+ }
+ catch (Exception e)
+ {
+ Logger.WarnException(e, "questEvent()");
+ }
+ }
+
+ foreach (var bounty in World.Game.QuestManager.Bounties)
+ bounty.CheckLevelArea(levelArea);
+
+ InGameClient.SendMessage(new PortedToWaypointMessage
+ {
+ PlayerIndex = PlayerIndex,
+ LevelAreaSNO = levelArea
+ });
+ Logger.Debug("---Waypoint Debug End---");
+ }
+
+ public void RefreshReveal()
+ {
+ var range = 200f;
+ if (InGameClient.Game.CurrentEncounter.activated)
+ range = 360f;
+
+ foreach (var actor in GetActorsInRange(range).Where(actor => actor is not Player))
+ actor.Unreveal(this);
+ RevealActorsToPlayer();
+ }
+
+ private void OnRequestBuyItem(GameClient client, RequestBuyItemMessage requestBuyItemMessage)
+ {
+ var vendor = SelectedNPC as Vendor;
+ if (vendor == null)
+ return;
+ vendor.OnRequestBuyItem(this, requestBuyItemMessage.ItemId);
+ }
+
+ private void OnRequestSellItem(GameClient client, RequestSellItemMessage requestSellItemMessage)
+ {
+ var vendor = SelectedNPC as Vendor;
+ if (vendor == null)
+ return;
+ vendor.OnRequestSellItem(this, (int)requestSellItemMessage.ItemId);
+ }
+
+ private void OnHirelingRetrainMessage()
+ {
+ if (ActiveHireling == null) return;
+
+ switch (ActiveHireling.Attributes[GameAttribute.Hireling_Class])
+ {
+ case 1:
+ if (ActiveHireling is Templar)
+ (ActiveHireling as Templar).Retrain(this);
+ break;
+ case 2:
+ if (ActiveHireling is Scoundrel)
+ (ActiveHireling as Scoundrel).Retrain(this);
+ break;
+ case 3:
+ if (ActiveHireling is Enchantress)
+ (ActiveHireling as Enchantress).Retrain(this);
+ break;
+ default:
+ return;
+ }
+ }
+
+ //*
+ private void OnHirelingDismiss(GameClient client, PetAwayMessage message)
+ {
+ Logger.Trace("OnPetDismiss(): {0}", message.ActorID);
+ var petId = World.GetGlobalId(this, message.ActorID);
+ var pet = World.GetActorByGlobalId(petId);
+ if (pet is Hireling)
+ ActiveHireling = null;
+ else
+ DestroyFollowersBySnoId(pet.SNO);
+ }
+
+ private void OnHirelingRequestLearnSkill(GameClient client, HirelingRequestLearnSkillMessage message)
+ {
+ Logger.Debug("OnHirelingRequestLearnSkill(): {0} - {1}", message.HirelingID, message.PowerSNOId);
+ var hireling = World.GetActorByGlobalId(World.GetGlobalId(this, message.HirelingID));
+ if (hireling == null) return;
+ switch (hireling.Attributes[GameAttribute.Hireling_Class])
+ {
+ case 1:
+ if (!(hireling is Templar)) return;
+ (hireling as Templar).SetSkill(this, message.PowerSNOId);
+ break;
+ case 2:
+ if (!(hireling is Scoundrel)) return;
+ (hireling as Scoundrel).SetSkill(this, message.PowerSNOId);
+ break;
+ case 3:
+ if (!(hireling is Enchantress)) return;
+ (hireling as Enchantress).SetSkill(this, message.PowerSNOId);
+ break;
+ default:
+ break;
+ }
+ }
+
+ //*/
+ private void OnResurrectOption(GameClient client, RessurectionPlayerMessage message)
+ {
+ Logger.Trace("Resurrect option: {0}", message.Choice);
+ switch (message.Choice)
+ {
+ case 0:
+ Revive(Position);
+ ChangeWorld(World.Game.StartingWorld, World.Game.StartPosition);
+ break;
+ case 1:
+ Revive(CheckPointPosition);
+ break;
+ case 2:
+ if (Attributes[GameAttribute.Corpse_Resurrection_Charges] > 0)
+ {
+ Revive(Position);
+ Attributes[GameAttribute.Corpse_Resurrection_Charges]--;
+ }
+
+ break;
+ }
+ }
+
+ //*/
+ private void OnEquipPotion(GameClient client, ChangeUsableItemMessage message)
+ {
+ var activeSkills = Toon.DBActiveSkills;
+ activeSkills.PotionGBID = message.Field1;
+ World.Game.GameDBSession.SessionUpdate(activeSkills);
+ }
+
+ public void ToonStateChanged()
+ {
+ try
+ {
+ ClientSystem.GameServer.GSBackend.ToonStateChanged(Toon.PersistentID);
+ }
+ catch (Exception e)
+ {
+ Logger.WarnException(e, "Exception on ToonStateChanged(): ");
+ }
+ }
+
+ private void OnArtisanWindowClosed()
+ {
+ CurrentArtisan = null;
+ }
+
+ //*
+ private void TrainArtisan(GameClient client, RequestTrainArtisanMessage message)
+ {
+ if (CurrentArtisan == null || !artisanTrainHelpers.ContainsKey(CurrentArtisan.Value))
+ {
+ Logger.Warn("Training for artisan {} is not supported", CurrentArtisan);
+ return;
+ }
+
+ var trainHelper = artisanTrainHelpers[CurrentArtisan.Value];
+ if (trainHelper.HasMaxLevel)
+ return;
+
+ var recipeDefinition = ItemGenerator.GetRecipeDefinition(trainHelper.TrainRecipeName);
+ if (Inventory.GetGoldAmount() < recipeDefinition.Gold)
+ return;
+
+ var requiredIngridients = recipeDefinition.Ingredients.Where(x => x.ItemsGBID > 0);
+ // FIXME: Inventory.HaveEnough doesn't work for some craft consumables
+ var haveEnoughIngredients = requiredIngridients.All(x => Inventory.HaveEnough(x.ItemsGBID, x.Count));
+ if (!haveEnoughIngredients)
+ return;
+
+ Inventory.RemoveGoldAmount(recipeDefinition.Gold);
+ foreach (var ingr in requiredIngridients)
+ // FIXME: Inventory.GrabSomeItems doesn't work for some craft consumables
+ Inventory.GrabSomeItems(ingr.ItemsGBID, ingr.Count);
+
+ trainHelper.DbRef.Level++;
+ World.Game.GameDBSession.SessionUpdate(trainHelper.DbRef);
+
+ if (trainHelper.Achievement is not null)
+ GrantAchievement(trainHelper.Achievement.Value);
+ if (trainHelper.Criteria is not null)
+ GrantCriteria(trainHelper.Criteria.Value);
+
+ if (artisanTrainHelpers.All(x => x.Value.HasMaxLevel))
+ GrantCriteria(74987249993545);
+
+ client.SendMessage(new CrafterLevelUpMessage
+ {
+ Type = trainHelper.Type,
+ AnimTag = trainHelper.AnimationTag,
+ NewIdle = trainHelper.IdleAnimationTag,
+ Level = trainHelper.DbRef.Level
+ });
+
+ LoadCrafterData();
+
+
+ /**/
+ }
+
+ public void UnlockTransmog(int transmogGBID)
+ {
+ if (learnedTransmogs.Contains(transmogGBID)) return;
+ InGameClient.SendMessage(new UnlockTransmogMessage() { TransmogGBID = transmogGBID });
+
+ Logger.Trace("Learning transmog #{0}", transmogGBID);
+ learnedTransmogs.Add(transmogGBID);
+ mystic_data.LearnedRecipes = SerializeBytes(learnedTransmogs);
+ World.Game.GameDBSession.SessionUpdate(mystic_data);
+
+ LoadCrafterData();
+ }
+
+ #endregion
+
+ #region update-logic
+
+ private int PreviousLevelArea = -1;
+
+ private List TimedActions = new();
+
+ public int VaultsDone = 0;
+ public int SpikeTrapsKilled = 0;
+
+ public void AddTimedAction(float seconds, Action onTimeout)
+ {
+ TimedActions.Add(TickTimer.WaitSeconds(World.Game, seconds, onTimeout));
+ }
+
+ public void Update(int tickCounter)
+ {
+ if (BetweenWorlds) return;
#if DEBUG
#else
@@ -2796,2992 +3064,3105 @@ namespace DiIiS_NA.GameServer.GSSystem.PlayerSystem
}
#endif
- // Check the gold
- if (InGameClient.Game.TickCounter % 120 == 0 && World != null && GoldCollectedTempCount > 0)
- {
- Toon.GameAccount.Gold += (ulong)GoldCollectedTempCount;
- Toon.CollectedGold += (ulong)GoldCollectedTempCount;
-
- if (World.Game.IsHardcore)
- Toon.CollectedGoldSeasonal += GoldCollectedTempCount;
-
- UpdateAchievementCounter(10, (uint)GoldCollectedTempCount);
-
- GoldCollectedTempCount = 0;
- }
-
- // Check the blood shards
- if (InGameClient.Game.TickCounter % 120 == 0 && World != null && BloodShardsCollectedTempCount > 0)
- {
- Toon.GameAccount.BloodShards += BloodShardsCollectedTempCount;
- Toon.GameAccount.TotalBloodShards += BloodShardsCollectedTempCount;
- BloodShardsCollectedTempCount = 0;
- }
-
- if (World != null && SkillSet.HasPassive(298038) && (InGameClient.Game.TickCounter - LastMovementTick) > 90)
- World.BuffManager.AddBuff(this, this, new UnwaveringWillBuff());
-
-
- if (World != null && SkillSet.HasSkill(312736) && (InGameClient.Game.TickCounter - LastMovementTick) > 90)
- World.BuffManager.AddBuff(this, this, new MonkDashingStrike.DashingStrikeCountBuff());
- else if (!SkillSet.HasSkill(312736))
- Attributes[GameAttribute.Skill_Charges, 312736] = 0;
-
- if (World != null && SkillSet.HasSkill(129217) && (InGameClient.Game.TickCounter - LastMovementTick) > 90)
- World.BuffManager.AddBuff(this, this, new Sentry.SentryCountBuff());
- else if (!SkillSet.HasSkill(129217))
- Attributes[GameAttribute.Skill_Charges, 129217] = 0;
-
- if (World != null && SkillSet.HasSkill(75301) && (InGameClient.Game.TickCounter - LastMovementTick) > 90)
- World.BuffManager.AddBuff(this, this, new SpikeTrap.SpikeCountBuff());
- else if (!SkillSet.HasSkill(75301))
- Attributes[GameAttribute.Skill_Charges, 75301] = 0;
-
- if (World != null && SkillSet.HasSkill(464896) && (InGameClient.Game.TickCounter - LastMovementTick) > 90)
- World.BuffManager.AddBuff(this, this, new BoneSpirit.SpiritCountBuff());
- else if (!SkillSet.HasSkill(464896))
- Attributes[GameAttribute.Skill_Charges, 464896] = 0;
-
- if (World != null && SkillSet.HasSkill(97435) && (InGameClient.Game.TickCounter - LastMovementTick) > 90)
- World.BuffManager.AddBuff(this, this, new FuriousCharge.FuriousChargeCountBuff());
- else if (!SkillSet.HasSkill(97435))
- Attributes[GameAttribute.Skill_Charges, 97435] = 0;
-
- Attributes.BroadcastChangedIfRevealed();
- lock (TimedActions)
- foreach (var timed_action in TimedActions)
- timed_action.Update(tickCounter);
-
- foreach (var timed_out in TimedActions.Where(t => t.TimedOut).ToList())
- TimedActions.Remove(timed_out);
-
- // Check the Killstreaks
- ExpBonusData.Check(0);
- ExpBonusData.Check(1);
-
- // Check if there is an conversation to close in this tick
- Conversations.Update(World.Game.TickCounter);
-
- foreach (Actor proximityGizmo in GetObjectsInRange(20f, true))
- {
- if (proximityGizmo == null || proximityGizmo.SNO == ActorSno.__NONE) continue;
- if (World.Game.QuestProgress.QuestTriggers.ContainsKey((int)proximityGizmo.SNO) && proximityGizmo.Visible) //EnterTrigger
- {
- var trigger = World.Game.QuestProgress.QuestTriggers[(int)proximityGizmo.SNO];
- if (trigger.triggerType == DiIiS_NA.Core.MPQ.FileFormats.QuestStepObjectiveType.EnterTrigger)
- {
- //this.World.Game.Quests.NotifyQuest(this.World.Game.CurrentQuest, Mooege.Common.MPQ.FileFormats.QuestStepObjectiveType.EnterTrigger, proximityGizmo.ActorSNO.Id);
- try
- {
- trigger.questEvent.Execute(World); // launch a questEvent
- }
- catch (Exception e)
- {
- Logger.WarnException(e, "questEvent()");
- }
- }
- }
- else if (World.Game.SideQuestProgress.QuestTriggers.ContainsKey((int)proximityGizmo.SNO))
- {
- var trigger = World.Game.SideQuestProgress.QuestTriggers[(int)proximityGizmo.SNO];
- if (trigger.triggerType == DiIiS_NA.Core.MPQ.FileFormats.QuestStepObjectiveType.EnterTrigger)
- {
- World.Game.SideQuestProgress.UpdateSideCounter((int)proximityGizmo.SNO);
- if (trigger.count == World.Game.SideQuestProgress.QuestTriggers[(int)proximityGizmo.SNO].counter)
- trigger.questEvent.Execute(World); // launch a questEvent
- }
- }
- if (World.Game.SideQuestProgress.GlobalQuestTriggers.ContainsKey((int)proximityGizmo.SNO) && proximityGizmo.Visible) //EnterTrigger
- {
- var trigger = World.Game.SideQuestProgress.GlobalQuestTriggers[(int)proximityGizmo.SNO];
- if (trigger.triggerType == DiIiS_NA.Core.MPQ.FileFormats.QuestStepObjectiveType.EnterTrigger)
- {
- //this.World.Game.Quests.NotifyQuest(this.World.Game.CurrentQuest, Mooege.Common.MPQ.FileFormats.QuestStepObjectiveType.EnterTrigger, proximityGizmo.ActorSNO.Id);
- try
- {
- trigger.questEvent.Execute(World); // launch a questEvent
- World.Game.SideQuestProgress.GlobalQuestTriggers.Remove((int)proximityGizmo.SNO);
- }
- catch (Exception e)
- {
- Logger.WarnException(e, "questEvent()");
- }
- }
- }
- }
-
- _UpdateResources();
-
- if (IsCasting) UpdateCastState();
-
- if (InGameClient.Game.TickCounter % 60 == 0 && World != null)
- {
- var proximity = new RectangleF(Position.X - 1f, Position.Y - 1f, 2f, 2f);
- var scenes = World.QuadTree.Query(proximity);
- if (scenes.Count == 0) return;
- var scene = scenes[0];
- if (PreviousLevelArea != scene.Specification.SNOLevelAreas[0])
- {
- PreviousLevelArea = scene.Specification.SNOLevelAreas[0];
- World.Game.WorldGenerator.CheckLevelArea(World, PreviousLevelArea);
- if (InGameClient.Game.TickCounter % 600 == 0)
- CheckLevelAreaCriteria(PreviousLevelArea);
- }
- }
-
- if (InGameClient.Game.TickCounter % 600 == 0 && World != null)
- {
- if (KilledMonstersTempCount != 0)
- {
- Toon.TotalKilled += (ulong)KilledMonstersTempCount;
- KilledMonstersTempCount = 0;
-
- if (KilledElitesTempCount != 0)
- {
- Toon.ElitesKilled += (ulong)KilledElitesTempCount;
- KilledElitesTempCount = 0;
- }
-
- if (KilledSeasonalTempCount != 0)
- {
- Toon.SeasonalKills += KilledSeasonalTempCount;
- KilledSeasonalTempCount = 0;
- }
- }
-
- CheckAchievementCounters();
- }
-
- #region Necromancer summons
- bool switchertobool = false;
- bool switchertoboolTwo = false;
- ActiveSkillSavedData NowSkillGolem = null;
- foreach (var skill in SkillSet.ActiveSkills)
- {
- if (skill.snoSkill == 453801)
- switchertobool = true;
- }
- foreach (var skill in SkillSet.ActiveSkills)
- if (skill.snoSkill == 451537)
- {
- switchertoboolTwo = true;
- NowSkillGolem = skill;
- }
- ActiveSkeletons = switchertobool;
- EnableGolem = switchertoboolTwo;
-
-
-
- PowerContext Killer = new PowerContext();
- Killer.User = this;
- Killer.World = World;
- Killer.PowerSNO = -1;
-
- if (ActiveSkeletons)
- {
- while (NecroSkeletons.Count < 7)
- {
- var Skeleton = new NecromancerSkeleton_A(World, ActorSno._p6_necro_commandskeletons_a, this);
- Skeleton.Brain.DeActivate();
- Skeleton.Scale = 1.2f;
-
- Skeleton.EnterWorld(PowerContext.RandomDirection(Position, 3f, 8f));
- NecroSkeletons.Add(Skeleton);
- /*this.InGameClient.SendMessage(new PetMessage()
- {
- Owner = this.PlayerIndex,
- Index = this.CountFollowers(473147),
- PetId = Skeleton.DynamicID(this),
- Type = 70,
- });
- //*/
- Skeleton.Brain.Activate();
- }
- }
- else
- {
- foreach (var skel in NecroSkeletons)
- {
- InGameClient.SendMessage(new PetDetachMessage()
- {
- PetId = skel.GlobalID
- });
- World.Leave(skel);
- }
- NecroSkeletons.Clear();
- }
- if (EnableGolem || ActiveGolem != null)
- {
- var runeActorSno = RuneSelect(451537, ActorSno._p6_necro_revive_golem, ActorSno._p6_bonegolem, ActorSno._p6_bloodgolem, ActorSno._p6_consumefleshgolem, ActorSno._p6_decaygolem, ActorSno._p6_icegolem);
- if (ActiveGolem != null)
- {
- if (ActiveGolem.SNO != runeActorSno || !SkillSet.HasSkill(451537))
- {
- if (ActiveGolem.World != null)
- {
- if (!(ActiveGolem.IsRevealedToPlayer(this)))
- InGameClient.SendMessage(new PetDetachMessage()
- {
- PetId = ActiveGolem.GlobalID
- });
- Killer.Target = ActiveGolem;
- (ActiveGolem as Minion).Kill(Killer);
- }
- ActiveGolem = null;
- }
- }
- else
- {
- if (Attributes[GameAttribute.Power_Cooldown, 451537] > InGameClient.Game.TickCounter)
- {
-
- }
- else
- {
- switch (runeActorSno)
- {
- case ActorSno._p6_necro_revive_golem:
- var NGolem = new BaseGolem(World, this);
- NGolem.Brain.DeActivate();
- NGolem.Position = RandomDirection(Position, 3f, 8f); //Kind of hacky until we get proper collisiondetection
- NGolem.Attributes[GameAttribute.Untargetable] = true;
- NGolem.EnterWorld(NGolem.Position);
-
-
- //(NGolem as BaseGolem).Brain.Activate();
- NGolem.Attributes[GameAttribute.Untargetable] = false;
- NGolem.Attributes.BroadcastChangedIfRevealed();
- ActiveGolem = NGolem;
- break;
- case ActorSno._p6_consumefleshgolem:
- var CFGolem = new ConsumeFleshGolem(World, this);
- CFGolem.Brain.DeActivate();
- CFGolem.Position = RandomDirection(Position, 3f, 8f); //Kind of hacky until we get proper collisiondetection
- CFGolem.Attributes[GameAttribute.Untargetable] = true;
- CFGolem.EnterWorld(CFGolem.Position);
-
-
- //(CFGolem as ConsumeFleshGolem).Brain.Activate();
- CFGolem.Attributes[GameAttribute.Untargetable] = false;
- CFGolem.Attributes.BroadcastChangedIfRevealed();
- ActiveGolem = CFGolem;
-
- break;
- case ActorSno._p6_icegolem:
- var IGolem = new IceGolem(World, this);
- IGolem.Brain.DeActivate();
- IGolem.Position = RandomDirection(Position, 3f, 8f); //Kind of hacky until we get proper collisiondetection
- IGolem.Attributes[GameAttribute.Untargetable] = true;
- IGolem.EnterWorld(IGolem.Position);
-
-
- //(IGolem as IceGolem).Brain.Activate();
- IGolem.Attributes[GameAttribute.Untargetable] = false;
- IGolem.Attributes.BroadcastChangedIfRevealed();
- ActiveGolem = IGolem;
- break;
- case ActorSno._p6_bonegolem:
- var BGolem = new BoneGolem(World, this);
- BGolem.Brain.DeActivate();
- BGolem.Position = RandomDirection(Position, 3f, 8f); //Kind of hacky until we get proper collisiondetection
- BGolem.Attributes[GameAttribute.Untargetable] = true;
- BGolem.EnterWorld(BGolem.Position);
-
-
- //(BGolem as BoneGolem).Brain.Activate();
- BGolem.Attributes[GameAttribute.Untargetable] = false;
- BGolem.Attributes.BroadcastChangedIfRevealed();
- ActiveGolem = BGolem;
- break;
- case ActorSno._p6_decaygolem:
- var DGolem = new DecayGolem(World, this);
- DGolem.Brain.DeActivate();
- DGolem.Position = RandomDirection(Position, 3f, 8f); //Kind of hacky until we get proper collisiondetection
- DGolem.Attributes[GameAttribute.Untargetable] = true;
- DGolem.EnterWorld(DGolem.Position);
-
-
- //(DGolem as DecayGolem).Brain.Activate();
- DGolem.Attributes[GameAttribute.Untargetable] = false;
- DGolem.Attributes.BroadcastChangedIfRevealed();
- ActiveGolem = DGolem;
- break;
- case ActorSno._p6_bloodgolem:
- var BlGolem = new BloodGolem(World, this);
- BlGolem.Brain.DeActivate();
- BlGolem.Position = RandomDirection(Position, 3f, 8f); //Kind of hacky until we get proper collisiondetection
- BlGolem.Attributes[GameAttribute.Untargetable] = true;
- BlGolem.EnterWorld(BlGolem.Position);
-
-
- //(BlGolem as BloodGolem).Brain.Activate();
- BlGolem.Attributes[GameAttribute.Untargetable] = false;
- BlGolem.Attributes.BroadcastChangedIfRevealed();
- ActiveGolem = BlGolem;
- break;
- }
-
- (ActiveGolem as Minion).Brain.Activate();
- ActiveGolem.Attributes[GameAttribute.Untargetable] = false;
- ActiveGolem.Attributes.BroadcastChangedIfRevealed();
- ActiveGolem.PlayActionAnimation(AnimationSno.p6_bloodgolem_spawn_01);
- }
- }
- }
- else
- {
- if (ActiveGolem != null)
- {
- if (ActiveGolem.World != null)
- (ActiveGolem as Minion).Kill();
- ActiveGolem = null;
- }
- }
- #endregion
- }
-
- #endregion
- public T RuneSelect(int PowerSNO, T none, T runeA, T runeB, T runeC, T runeD, T runeE)
- {
- int Rune_A = Attributes[GameAttribute.Rune_A, PowerSNO];
- int Rune_B = Attributes[GameAttribute.Rune_B, PowerSNO];
- int Rune_C = Attributes[GameAttribute.Rune_C, PowerSNO];
- int Rune_D = Attributes[GameAttribute.Rune_D, PowerSNO];
- int Rune_E = Attributes[GameAttribute.Rune_E, PowerSNO];
-
- if (Rune_A > 0) return runeA;
- else if (Rune_B > 0) return runeB;
- else if (Rune_C > 0) return runeC;
- else if (Rune_D > 0) return runeD;
- else if (Rune_E > 0) return runeE;
- else return none;
- }
-#region enter, leave, reveal handling
-
- ///
- /// Revals scenes in player's proximity.
- ///
- public void RevealScenesToPlayer()
- {
- //List scenes_around = this.GetScenesInRegion(DefaultQueryProximityLenght * 2);
- List scenes_around = World.Scenes.Values.ToList();
- if (!World.worldData.DynamicWorld)
- scenes_around = GetScenesInRegion(DefaultQueryProximityLenght * 3);
-
- foreach (var scene in scenes_around) // reveal scenes in player's proximity.
- {
- if (scene.IsRevealedToPlayer(this)) // if the actors is already revealed skip it.
- continue; // if the scene is already revealed, skip it.
-
- if (scene.Parent != null) // if it's a subscene, always make sure it's parent get reveals first and then it reveals his childs.
- scene.Parent.Reveal(this);
- else
- scene.Reveal(this);
- }
-
- foreach (var scene in World.Scenes.Values) // unreveal far scenes
- {
- if (!scene.IsRevealedToPlayer(this) || scenes_around.Contains(scene))
- continue;
-
- if (scene.Parent != null) // if it's a subscene, always make sure it's parent get reveals first and then it reveals his childs.
- scene.Parent.Unreveal(this);
- else
- scene.Unreveal(this);
- }
- }
-
- ///
- /// Reveals actors in player's proximity.
- ///
- public void RevealActorsToPlayer()
- {
- float Range = 200f;
- if (InGameClient.Game.CurrentEncounter.activated)
- Range = 360f;
-
- var specialWorlds = new WorldSno[]
- {
- WorldSno.x1_pand_batteringram,
- WorldSno.gluttony_boss,
- WorldSno.a3dun_hub_adria_tower,
- WorldSno.x1_malthael_boss_arena,
- WorldSno.a1trdun_level05_templar,
- };
-
- var actors_around = specialWorlds.Contains(World.SNO) ? World.Actors.Values.ToList() : GetActorsInRange(Range);
-
- foreach (var actor in actors_around) // reveal actors in player's proximity.
- {
- if (actor is Player) // if the actors is already revealed, skip it.
- continue;
-
- if (World.SNO == WorldSno.x1_tristram_adventure_mode_hub && actor is Portal)
- if ((actor as Portal).Destination.WorldSNO == (int)WorldSno.x1_tristram_adventure_mode_hub)
- continue;
- if (World.SNO == WorldSno.trout_town && actor is Portal)
- if ((actor as Portal).Destination.WorldSNO == (int)WorldSno.trout_town && (actor as Portal).Destination.DestLevelAreaSNO == 19947)
- {
- (actor as Portal).Destination.WorldSNO = (int)WorldSno.x1_tristram_adventure_mode_hub;
- (actor as Portal).Destination.StartingPointActorTag = 483;
- }
-
- if (actor.ActorType != ActorType.ClientEffect && actor.ActorType != ActorType.AxeSymbol && actor.ActorType != ActorType.CustomBrain)
- {
- actor.Reveal(this);
- }
- }
-
- foreach (var actor in World.Actors.Values) // unreveal far actors
- {
- if ((actor is Player && (!World.IsPvP || actor == this)) || actors_around.Contains(actor)) // if the actors is already revealed, skip it.
- continue;
-
- actor.Unreveal(this);
- }
- }
-
- ///
- /// Reveals other players in player's proximity.
- ///
- public void RevealPlayersToPlayer()
- {
- var actors = GetActorsInRange(100f);
-
- foreach (var actor in actors) // reveal actors in player's proximity.
- {
- if (actor.IsRevealedToPlayer(this)) // if the actors is already revealed, skip it.
- continue;
-
- actor.Reveal(this);
-
- if (!IsRevealedToPlayer(actor))
- Reveal(actor);
- }
- }
-
- public void ReRevealPlayersToPlayer()
- {
- var actors = GetActorsInRange(100f);
-
- foreach (var actor in actors) // reveal actors in player's proximity.
- {
- if (actor.IsRevealedToPlayer(this)) // if the actors is already revealed, skip it.
- {
- actor.Unreveal(this);
- }
-
- actor.Reveal(this);
-
- if (!IsRevealedToPlayer(actor))
- Reveal(actor);
- else
- {
- Unreveal(actor);
- Reveal(actor);
- }
- }
- }
-
- public void ClearDoorAnimations()
- {
- var doors = GetActorsInRange(100f);
- foreach (var door in doors)
- {
- if (door.IsRevealedToPlayer(this))
- InGameClient.SendMessage(new SetIdleAnimationMessage
- {
- ActorID = door.DynamicID(this),
- AnimationSNO = AnimationSetKeys.Open.ID
- });
- }
- }
-
- public override void OnEnter(World world)
- {
-
-
- world.Reveal(this);
- Unreveal(this);
-
- if (_CurrentHPValue == -1f)
- DefaultQueryProximityRadius = 60;
-
- InGameClient.SendMessage(new EnterWorldMessage()
- {
- EnterPosition = Position,
- WorldID = world.GlobalID,
- WorldSNO = (int)world.SNO,
- PlayerIndex = PlayerIndex,
- EnterLookUsed = true,
- EnterKnownLookOverrides = new EnterKnownLookOverrides { Field0 = new int[] { -1, -1, -1, -1, -1, -1 } }
- });
-
- switch (world.SNO)
- {
- case WorldSno.x1_westmarch_overlook_d:
- InGameClient.SendMessage(new PlayerSetCameraObserverMessage()
- {
- Field0 = 309026,
- Field1 = new WorldPlace() { Position = new Vector3D(), WorldID = 0 }
- });
- break;
- case WorldSno.x1_westm_intro:
- InGameClient.SendMessage(new PlayerSetCameraObserverMessage()
- {
- Field0 = 1541,
- Field1 = new WorldPlace() { Position = new Vector3D(), WorldID = 0 }
- });
- break;
- }
-
- if (_CurrentHPValue == -1f)
- AddPercentageHP(100);
-
- DefaultQueryProximityRadius = 100;
-
- RevealScenesToPlayer();
- RevealPlayersToPlayer();
-
- // load all inventory items
- if (!Inventory.Loaded)
- {//why reload if already loaded?
- Inventory.LoadFromDB();
- Inventory.LoadStashFromDB();
- }
- else
- Inventory.RefreshInventoryToClient();
-
- // generate visual update message
- //this.Inventory.SendVisualInventory(this);
- SetAllStatsInCorrectOrder();
- SetAttributesSkillSets();
- if (World.IsPvP)
- DisableStoneOfRecall();
- else
- EnableStoneOfRecall();
-
- Reveal(this);
-
- System.Threading.Tasks.Task.Delay(3).Wait();
- RevealActorsToPlayer();
-
- //
- }
-
- public override void OnTeleport()
- {
- Unreveal(this);
- BeforeChangeWorld();
- RevealScenesToPlayer(); // reveal scenes in players proximity.
- RevealPlayersToPlayer();
- RevealActorsToPlayer(); // reveal actors in players proximity.
- //TickTimer.WaitSeconds(this.World.Game, 5.0f, new Action((x) => Logger.Debug("Timer")));
- Reveal(this);
- AfterChangeWorld();
- // load all inventory items
- if (!Inventory.Loaded)
- {
- //why reload if already loaded?
- Inventory.LoadFromDB();
- Inventory.LoadStashFromDB();
- }
- else
- Inventory.RefreshInventoryToClient();
-
-
- }
-
- public override void OnLeave(World world)
- {
- Conversations.StopAll();
-
- // save visual equipment
- Toon.HeroVisualEquipmentField.Value = Inventory.GetVisualEquipment();
- //this.Toon.HeroLevelField.Value = this.Attributes[GameAttribute.Level];
- Toon.GameAccount.ChangedFields.SetPresenceFieldValue(Toon.HeroVisualEquipmentField);
- Toon.GameAccount.ChangedFields.SetPresenceFieldValue(Toon.HeroLevelField);
- Toon.GameAccount.ChangedFields.SetPresenceFieldValue(Toon.HeroParagonLevelField);
- world.Unreveal(this);
- }
-
- public override bool Reveal(Player player)
- {
- if (!base.Reveal(player))
- return false;
-
- if (!World.IsPvP || this == player)
- {
- player.InGameClient.SendMessage(new PlayerEnterKnownMessage()
- {
- PlayerIndex = PlayerIndex,
- ActorId = DynamicID(player),
- });
- }
-
- Inventory.SendVisualInventory(player);
-
- if (this == player) // only send this to player itself. Warning: don't remove this check or you'll make the game start crashing! /raist.
- {
- player.InGameClient.SendMessage(new PlayerActorSetInitialMessage()
- {
- ActorId = DynamicID(player),
- PlayerIndex = PlayerIndex,
- });
- }
-
- if (!base.Reveal(player))
- Inventory.Reveal(player);
-
- if (this == player) // only send this when player's own actor being is revealed. /raist.
- {
- player.InGameClient.SendMessage(new PlayerWarpedMessage()
+ // Check the gold
+ if (InGameClient.Game.TickCounter % 120 == 0 && World != null && GoldCollectedTempCount > 0)
+ {
+ Toon.GameAccount.Gold += (ulong)GoldCollectedTempCount;
+ Toon.CollectedGold += (ulong)GoldCollectedTempCount;
+
+ if (World.Game.IsHardcore)
+ Toon.CollectedGoldSeasonal += GoldCollectedTempCount;
+
+ UpdateAchievementCounter(10, (uint)GoldCollectedTempCount);
+
+ GoldCollectedTempCount = 0;
+ }
+
+ // Check the blood shards
+ if (InGameClient.Game.TickCounter % 120 == 0 && World != null && BloodShardsCollectedTempCount > 0)
+ {
+ Toon.GameAccount.BloodShards += BloodShardsCollectedTempCount;
+ Toon.GameAccount.TotalBloodShards += BloodShardsCollectedTempCount;
+ BloodShardsCollectedTempCount = 0;
+ }
+
+ if (World != null && SkillSet.HasPassive(298038) && InGameClient.Game.TickCounter - LastMovementTick > 90)
+ World.BuffManager.AddBuff(this, this, new UnwaveringWillBuff());
+
+
+ if (World != null && SkillSet.HasSkill(312736) && InGameClient.Game.TickCounter - LastMovementTick > 90)
+ World.BuffManager.AddBuff(this, this, new MonkDashingStrike.DashingStrikeCountBuff());
+ else if (!SkillSet.HasSkill(312736))
+ Attributes[GameAttribute.Skill_Charges, 312736] = 0;
+
+ if (World != null && SkillSet.HasSkill(129217) && InGameClient.Game.TickCounter - LastMovementTick > 90)
+ World.BuffManager.AddBuff(this, this, new Sentry.SentryCountBuff());
+ else if (!SkillSet.HasSkill(129217))
+ Attributes[GameAttribute.Skill_Charges, 129217] = 0;
+
+ if (World != null && SkillSet.HasSkill(75301) && InGameClient.Game.TickCounter - LastMovementTick > 90)
+ World.BuffManager.AddBuff(this, this, new SpikeTrap.SpikeCountBuff());
+ else if (!SkillSet.HasSkill(75301))
+ Attributes[GameAttribute.Skill_Charges, 75301] = 0;
+
+ if (World != null && SkillSet.HasSkill(464896) && InGameClient.Game.TickCounter - LastMovementTick > 90)
+ World.BuffManager.AddBuff(this, this, new BoneSpirit.SpiritCountBuff());
+ else if (!SkillSet.HasSkill(464896))
+ Attributes[GameAttribute.Skill_Charges, 464896] = 0;
+
+ if (World != null && SkillSet.HasSkill(97435) && InGameClient.Game.TickCounter - LastMovementTick > 90)
+ World.BuffManager.AddBuff(this, this, new FuriousCharge.FuriousChargeCountBuff());
+ else if (!SkillSet.HasSkill(97435))
+ Attributes[GameAttribute.Skill_Charges, 97435] = 0;
+
+ Attributes.BroadcastChangedIfRevealed();
+ lock (TimedActions)
+ {
+ foreach (var timed_action in TimedActions)
+ timed_action.Update(tickCounter);
+ }
+
+ foreach (var timed_out in TimedActions.Where(t => t.TimedOut).ToList())
+ TimedActions.Remove(timed_out);
+
+ // Check the Killstreaks
+ ExpBonusData.Check(0);
+ ExpBonusData.Check(1);
+
+ // Check if there is an conversation to close in this tick
+ Conversations.Update(World.Game.TickCounter);
+
+ foreach (var proximityGizmo in GetObjectsInRange(20f, true))
+ {
+ if (proximityGizmo == null || proximityGizmo.SNO == ActorSno.__NONE) continue;
+ if (World.Game.QuestProgress.QuestTriggers.ContainsKey((int)proximityGizmo.SNO) &&
+ proximityGizmo.Visible) //EnterTrigger
+ {
+ var trigger = World.Game.QuestProgress.QuestTriggers[(int)proximityGizmo.SNO];
+ if (trigger.triggerType == DiIiS_NA.Core.MPQ.FileFormats.QuestStepObjectiveType.EnterTrigger)
+ //this.World.Game.Quests.NotifyQuest(this.World.Game.CurrentQuest, Mooege.Common.MPQ.FileFormats.QuestStepObjectiveType.EnterTrigger, proximityGizmo.ActorSNO.Id);
+ try
+ {
+ trigger.questEvent.Execute(World); // launch a questEvent
+ }
+ catch (Exception e)
+ {
+ Logger.WarnException(e, "questEvent()");
+ }
+ }
+ else if (World.Game.SideQuestProgress.QuestTriggers.ContainsKey((int)proximityGizmo.SNO))
+ {
+ var trigger = World.Game.SideQuestProgress.QuestTriggers[(int)proximityGizmo.SNO];
+ if (trigger.triggerType == DiIiS_NA.Core.MPQ.FileFormats.QuestStepObjectiveType.EnterTrigger)
{
- WarpReason = 9,
- WarpFadeInSecods = 0f,
- });
+ World.Game.SideQuestProgress.UpdateSideCounter((int)proximityGizmo.SNO);
+ if (trigger.count == World.Game.SideQuestProgress.QuestTriggers[(int)proximityGizmo.SNO].counter)
+ trigger.questEvent.Execute(World); // launch a questEvent
+ }
}
- if (SkillSet.HasSkill(460757))
- foreach (var skill in SkillSet.ActiveSkills)
- if (skill.snoSkill == 460757)
- if (skill.snoRune == 3)
- World.BuffManager.AddBuff(this, this, new P6_Necro_Devour_Aura());
- else
- World.BuffManager.RemoveBuffs(this, 474325);
+ if (World.Game.SideQuestProgress.GlobalQuestTriggers.ContainsKey((int)proximityGizmo.SNO) &&
+ proximityGizmo.Visible) //EnterTrigger
+ {
+ var trigger = World.Game.SideQuestProgress.GlobalQuestTriggers[(int)proximityGizmo.SNO];
+ if (trigger.triggerType == DiIiS_NA.Core.MPQ.FileFormats.QuestStepObjectiveType.EnterTrigger)
+ //this.World.Game.Quests.NotifyQuest(this.World.Game.CurrentQuest, Mooege.Common.MPQ.FileFormats.QuestStepObjectiveType.EnterTrigger, proximityGizmo.ActorSNO.Id);
+ try
+ {
+ trigger.questEvent.Execute(World); // launch a questEvent
+ World.Game.SideQuestProgress.GlobalQuestTriggers.Remove((int)proximityGizmo.SNO);
+ }
+ catch (Exception e)
+ {
+ Logger.WarnException(e, "questEvent()");
+ }
+ }
+ }
- return true;
- }
+ _UpdateResources();
- public override bool Unreveal(Player player)
- {
- if (!base.Unreveal(player))
- return false;
+ if (IsCasting) UpdateCastState();
- Inventory.Unreveal(player);
+ if (InGameClient.Game.TickCounter % 60 == 0 && World != null)
+ {
+ var proximity = new RectangleF(Position.X - 1f, Position.Y - 1f, 2f, 2f);
+ var scenes = World.QuadTree.Query(proximity);
+ if (scenes.Count == 0) return;
+ var scene = scenes[0];
+ if (PreviousLevelArea != scene.Specification.SNOLevelAreas[0])
+ {
+ PreviousLevelArea = scene.Specification.SNOLevelAreas[0];
+ World.Game.WorldGenerator.CheckLevelArea(World, PreviousLevelArea);
+ if (InGameClient.Game.TickCounter % 600 == 0)
+ CheckLevelAreaCriteria(PreviousLevelArea);
+ }
+ }
- return true;
- }
+ if (InGameClient.Game.TickCounter % 600 == 0 && World != null)
+ {
+ if (KilledMonstersTempCount != 0)
+ {
+ Toon.TotalKilled += (ulong)KilledMonstersTempCount;
+ KilledMonstersTempCount = 0;
- public Dictionary AllBuffs = new Dictionary();
+ if (KilledElitesTempCount != 0)
+ {
+ Toon.ElitesKilled += (ulong)KilledElitesTempCount;
+ KilledElitesTempCount = 0;
+ }
- public bool BetweenWorlds = false;
+ if (KilledSeasonalTempCount != 0)
+ {
+ Toon.SeasonalKills += KilledSeasonalTempCount;
+ KilledSeasonalTempCount = 0;
+ }
+ }
- public override void BeforeChangeWorld()
- {
- ClearDoorAnimations();
- World.Game.QuestManager.UnsetBountyMarker(this);
- BetweenWorlds = true;
- AllBuffs = World.BuffManager.GetAllBuffs(this);
- World.BuffManager.RemoveAllBuffs(this);
- //this.Inventory.Unreveal(this);
- //this.InGameClient.TickingEnabled = false;
- /*this.InGameClient.SendMessage(new FreezeGameMessage
- {
- Field0 = true
- });*/
+ CheckAchievementCounters();
+ }
- InGameClient.SendMessage(new ACDTranslateSyncMessage()
- {
- ActorId = DynamicID(this),
- Position = Position
- });
+ #region Necromancer summons
- _CurrentHPValue = Attributes[GameAttribute.Hitpoints_Cur];
- _CurrentResourceValue = Attributes[GameAttribute.Resource_Cur, (int)Toon.HeroTable.PrimaryResource + 1];
- }
+ var switchertobool = false;
+ var switchertoboolTwo = false;
+ ActiveSkillSavedData NowSkillGolem = null;
+ foreach (var skill in SkillSet.ActiveSkills)
+ if (skill.snoSkill == 453801)
+ switchertobool = true;
+ foreach (var skill in SkillSet.ActiveSkills)
+ if (skill.snoSkill == 451537)
+ {
+ switchertoboolTwo = true;
+ NowSkillGolem = skill;
+ }
- public override void AfterChangeWorld()
- {
- //this.InGameClient.TickingEnabled = true;
- /*
- this.InGameClient.SendMessage(new FreezeGameMessage
- {
- Field0 = false
- });
- */
- Inventory.Reveal(this);
-
- foreach (var buff in AllBuffs)
- World.BuffManager.CopyBuff(this, this, buff.Key, buff.Value);
- AllBuffs.Clear();
- BetweenWorlds = false;
-
- if (_CurrentHPValue != -1)
- {
- Attributes[GameAttribute.Hitpoints_Cur] = _CurrentHPValue;
- Attributes[GameAttribute.Resource_Cur, (int)Toon.HeroTable.PrimaryResource + 1] = _CurrentResourceValue;
- Attributes.BroadcastChangedIfRevealed();
- _CurrentHPValue = -1;
- }
- World.Game.QuestManager.SetBountyMarker(this);
+ ActiveSkeletons = switchertobool;
+ EnableGolem = switchertoboolTwo;
- //System.Threading.Tasks.Task.Delay(1000).ContinueWith(a => {this.BetweenWorlds = false;});
- }
+ var Killer = new PowerContext();
+ Killer.User = this;
+ Killer.World = World;
+ Killer.PowerSNO = -1;
- #endregion
+ if (ActiveSkeletons)
+ {
+ while (NecroSkeletons.Count < 7)
+ {
+ var Skeleton = new NecromancerSkeleton_A(World, ActorSno._p6_necro_commandskeletons_a, this);
+ Skeleton.Brain.DeActivate();
+ Skeleton.Scale = 1.2f;
- #region hero-state
+ Skeleton.EnterWorld(PowerContext.RandomDirection(Position, 3f, 8f));
+ NecroSkeletons.Add(Skeleton);
+ /*this.InGameClient.SendMessage(new PetMessage()
+ {
+ Owner = this.PlayerIndex,
+ Index = this.CountFollowers(473147),
+ PetId = Skeleton.DynamicID(this),
+ Type = 70,
+ });
+ //*/
+ Skeleton.Brain.Activate();
+ }
+ }
+ else
+ {
+ foreach (var skel in NecroSkeletons)
+ {
+ InGameClient.SendMessage(new PetDetachMessage()
+ {
+ PetId = skel.GlobalID
+ });
+ World.Leave(skel);
+ }
- public void WTF()
- {
+ NecroSkeletons.Clear();
+ }
- Attributes[GameAttribute.Power_Buff_0_Visual_Effect_None, 208468] = true;
- Attributes[GameAttribute.Thorns_Fixed_Total, 0] = 0;
- Attributes[GameAttribute.Damage_Delta_Total, 0] = 0;
- Attributes[GameAttribute.UnequippedTime, 4] = 0;
- Attributes[GameAttribute.Experience_Next_Lo] = 717;
- Attributes[GameAttribute.Skill_Total, 93395] = 1;
- Attributes[GameAttribute.Strength] = 0;
- Attributes[GameAttribute.Attacks_Per_Second_Percent_Cap] = 0;
- Attributes[GameAttribute.Invulnerable] = true;
- Attributes[GameAttribute.UnequippedTime, 7] = 0;
- Attributes[GameAttribute.Damage_Min, 0] = 0;
- Attributes[GameAttribute.Damage_Weapon_Min_Total_All] = 0;
- Attributes[GameAttribute.Damage_Delta_Total, 3] = 0;
- Attributes[GameAttribute.General_Cooldown] = 0;
- Attributes[GameAttribute.Attacks_Per_Second_Total] = 0;
- Attributes[GameAttribute.Resource_Cur, 1] = 0;
- Attributes[GameAttribute.UnequippedTime, 6] = 0;
- Attributes[GameAttribute.Backpack_Slots] = 60;
- Attributes[GameAttribute.Corpse_Resurrection_Charges] = 3;
- Attributes[GameAttribute.Skill, 93395] = 1;
- Attributes[GameAttribute.Trait, 451242] = 2;
- Attributes[GameAttribute.UnequippedTime, 9] = 0;
- Attributes[GameAttribute.Attacks_Per_Second] = 0;
- Attributes[GameAttribute.TeamID] = 2;
- Attributes[GameAttribute.Resource_Degeneration_Stop_Point, 1048575] = 0;
- Attributes[GameAttribute.Resource_Max_Bonus, 1] = 0;
- Attributes[GameAttribute.Armor_Total] = 0;
- Attributes[GameAttribute.Skill_Total, 1759] = 1;
- Attributes[GameAttribute.SkillKit] = 35584;
- Attributes[GameAttribute.Armor_Item_Total] = 0;
- Attributes[GameAttribute.Resistance_Total, 5] = 0;
- Attributes[GameAttribute.Skill, 30718] = 1;
- Attributes[GameAttribute.CantStartDisplayedPowers] = true;
- Attributes[GameAttribute.Seasononlyitemsunlocked] = true;
- Attributes[GameAttribute.UnequippedTime, 10] = 0;
- Attributes[GameAttribute.Damage_Weapon_Delta_Total_All] = 0;
- Attributes[GameAttribute.Damage_Min_Total, 3] = 0;
- Attributes[GameAttribute.Resource_Cost_Reduction_Percent_All] = 0;
- Attributes[GameAttribute.Get_Hit_Recovery] = 0;
- Attributes[GameAttribute.Skill, 1759] = 1;
- Attributes[GameAttribute.Buff_Icon_Start_Tick0, 439438] = 155;
- Attributes[GameAttribute.Buff_Icon_End_Tick0, 439438] = 3755;
- Attributes[GameAttribute.Skill, 30744] = 1;
- Attributes[GameAttribute.Get_Hit_Recovery_Per_Level] = 0;
- Attributes[GameAttribute.Requirement, 57] = 0;
- Attributes[GameAttribute.Damage_Weapon_Delta, 3] = 0;
- Attributes[GameAttribute.Attacks_Per_Second_Item_CurrentHand] = 0;
- Attributes[GameAttribute.Get_Hit_Recovery_Base] = 0;
- Attributes[GameAttribute.Resistance_From_Intelligence] = 0;
- Attributes[GameAttribute.Damage_Weapon_Delta, 0] = 0;
- Attributes[GameAttribute.Get_Hit_Max] = 0;
- Attributes[GameAttribute.Crit_Damage_Cap] = 0;
- Attributes[GameAttribute.Class_Damage_Reduction_Percent_PVP] = 0;
- Attributes[GameAttribute.Buff_Icon_Count0, 212032] = 1;
- Attributes[GameAttribute.Hit_Chance] = 0;
- Attributes[GameAttribute.Crit_Percent_Cap] = 0;
- Attributes[GameAttribute.Get_Hit_Max_Per_Level] = 0;
- Attributes[GameAttribute.Resource_Regen_Per_Second, 1] = 0;
- Attributes[GameAttribute.Buff_Icon_Count0, 134334] = 1;
- Attributes[GameAttribute.Buff_Icon_End_Tick0, 134334] = 2101;
- Attributes[GameAttribute.Buff_Icon_Start_Tick0, 134334] = 301;
- Attributes[GameAttribute.Banter_Cooldown, 1048575] = 0;
- Attributes[GameAttribute.Hidden] = false;
- Attributes[GameAttribute.Buff_Icon_Count0, 439438] = 0;
- Attributes[GameAttribute.Buff_Icon_Start_Tick0, 212032] = 0;
- Attributes[GameAttribute.Buff_Icon_End_Tick0, 212032] = 0;
- Attributes[GameAttribute.Immobolize] = false;
- Attributes[GameAttribute.Untargetable] = false;
- Attributes[GameAttribute.Loading] = false;
- Attributes[GameAttribute.Invulnerable] = false;
- Attributes[GameAttribute.Resource_Degeneration_Stop_Point, 1048575] = 0;
- Attributes[GameAttribute.CantStartDisplayedPowers] = false;
- Attributes[GameAttribute.Buff_Icon_Start_Tick0, 439438] = 0;
- Attributes[GameAttribute.Buff_Icon_End_Tick0, 439438] = 0;
- Attributes[GameAttribute.Buff_Icon_Count0, 212032] = 0;
- Attributes.BroadcastChangedIfRevealed();
- }
+ if (EnableGolem || ActiveGolem != null)
+ {
+ var runeActorSno = RuneSelect(451537, ActorSno._p6_necro_revive_golem, ActorSno._p6_bonegolem,
+ ActorSno._p6_bloodgolem, ActorSno._p6_consumefleshgolem, ActorSno._p6_decaygolem,
+ ActorSno._p6_icegolem);
+ if (ActiveGolem != null)
+ {
+ if (ActiveGolem.SNO != runeActorSno || !SkillSet.HasSkill(451537))
+ {
+ if (ActiveGolem.World != null)
+ {
+ if (!ActiveGolem.IsRevealedToPlayer(this))
+ InGameClient.SendMessage(new PetDetachMessage()
+ {
+ PetId = ActiveGolem.GlobalID
+ });
+ Killer.Target = ActiveGolem;
+ (ActiveGolem as Minion).Kill(Killer);
+ }
- ///
- /// Allows hero state message to be sent when hero's some property get's updated.
- ///
- public void UpdateHeroState()
- {
- InGameClient.SendMessage(new HeroStateMessage
- {
- State = GetStateData(),
- PlayerIndex = PlayerIndex
- });
- }
-
- public HeroStateData GetStateData()
- {
- return new HeroStateData()
- {
- LastPlayedAct = 400, //LastPlayedAct
- HighestUnlockedAct = 400, //HighestUnlockedAct
- PlayedFlags = (int)Toon.Flags,
- PlayerSavedData = GetSavedData(),
- //QuestRewardHistoryEntriesCount = QuestRewardHistory.Count,
- tQuestRewardHistory = QuestRewardHistory.ToArray()
- };
- }
-
-#endregion
-
-#region player attribute handling
-
- public void QueueDeath(bool state)
- {
- //this.World.BroadcastIfRevealed(this.ACDWorldPositionMessage, this);
- InGameClient.SendMessage(new ACDTranslateSyncMessage()
- {
- ActorId = DynamicID(this),
- Position = Position
- });
- Attributes[GameAttribute.QueueDeath] = state;
- Attributes[GameAttribute.Disabled] = state;
- Attributes[GameAttribute.Waiting_To_Accept_Resurrection] = false;
- Attributes[GameAttribute.Invulnerable] = state;
- //this.Attributes[GameAttribute.Stunned] = state;
- Attributes[GameAttribute.Immobolize] = state;
- Attributes[GameAttribute.Hidden] = state;
- Attributes[GameAttribute.Untargetable] = state;
- Attributes[GameAttribute.CantStartDisplayedPowers] = state;
- Attributes[GameAttribute.IsContentRestrictedActor] = state;
-
- Attributes[GameAttribute.Rest_Experience_Lo] = 0;
- Attributes[GameAttribute.Rest_Experience_Bonus_Percent] = 0;
-
- Attributes.BroadcastChangedIfRevealed();
- if (World.Game.PvP)
- {
- Attributes[GameAttribute.Resurrect_As_Observer] = state;
- //this.Attributes[GameAttribute.Observer] = !state;
- }
- //this.Attributes[GameAttribute.Corpse_Resurrection_Charges] = 1; // Enable this to allow unlimited resurrection at corpse
- //this.Attributes[GameAttribute.Corpse_Resurrection_Allowed_Game_Time] = this.World.Game.TickCounter + 300; // Timer for auto-revive (seems to be broken?)
- Attributes.BroadcastChangedIfRevealed();
- }
-
- public void Resurrect()
- {
- Attributes[GameAttribute.Waiting_To_Accept_Resurrection] = true;
- Attributes.BroadcastChangedIfRevealed();
- }
-
- public void Revive(Vector3D spawnPosition)
- {
- if (World == null) return;
- /*if (this.World.Game.IsHardcore)
- {
- this.InGameClient.SendMessage(new LogoutTickTimeMessage()
- {
- Field0 = false, // true - logout with party?
- Ticks = 0, // delay 1, make this equal to 0 for instant logout
- Field2 = 0, // delay 2
- });
- } else
- {*/
- QueueDeath(false);
- Dead = false;
- AddPercentageHP(100);
-
- World.BroadcastIfRevealed(plr => new SetIdleAnimationMessage
- {
- ActorID = DynamicID(plr),
- AnimationSNO = AnimationSetKeys.IdleDefault.ID
- }, this);
-
- //removing tomb
- try
- {
- GetObjectsInRange(100.0f).Where(h => h.playerIndex == PlayerIndex).First().Destroy();
- }
- catch { }
- Teleport(spawnPosition);
- World.BuffManager.AddBuff(this, this, new ActorGhostedBuff());
-
- var old_skills = SkillSet.ActiveSkills.Select(s => s.snoSkill).ToList();
- foreach (var skill in old_skills)
- {
- PowerScript power = PowerLoader.CreateImplementationForPowerSNO(skill);
- if (power != null && power.EvalTag(PowerKeys.SynergyPower) != -1)
- {
- World.BuffManager.RemoveBuffs(this, power.EvalTag(PowerKeys.SynergyPower));
- }
- }
-
- SetAttributesByItems();
- SetAttributesByItemProcs();
- SetAttributesByGems();
- SetAttributesByItemSets();
- SetAttributesByPassives();
- SetAttributesByParagon();
- SetAttributesSkillSets();
-
- Attributes[GameAttribute.Resource_Cur, PrimaryResourceID] = 0f;
- if (Toon.Class == ToonClass.DemonHunter)
- Attributes[GameAttribute.Resource_Cur, SecondaryResourceID] = 0f;
- Attributes.BroadcastChangedIfRevealed();
-
- var skills = SkillSet.ActiveSkills.Select(s => s.snoSkill).ToList();
- var cooldowns = World.BuffManager.GetBuffs(this);
- foreach (var skill in skills)
- {
- bool inCooldown = false;
- CooldownBuff skillcd = null;
- foreach (var cooldown in cooldowns)
- if (cooldown.TargetPowerSNO == skill)
- {
- skillcd = cooldown;
- inCooldown = true;
- break;
- }
-
- if (inCooldown && skillcd != null) skillcd.Extend((int)3 * 60);
- else _StartSkillCooldown(skill, 3f);
- }
- Inventory.RefreshInventoryToClient();
- UpdatePercentageHP(PercHPbeforeChange);
- }
+ ActiveGolem = null;
+ }
+ }
+ else
+ {
+ if (Attributes[GameAttribute.Power_Cooldown, 451537] > InGameClient.Game.TickCounter)
+ {
+ }
+ else
+ {
+ switch (runeActorSno)
+ {
+ case ActorSno._p6_necro_revive_golem:
+ var NGolem = new BaseGolem(World, this);
+ NGolem.Brain.DeActivate();
+ NGolem.Position =
+ RandomDirection(Position, 3f,
+ 8f); //Kind of hacky until we get proper collisiondetection
+ NGolem.Attributes[GameAttribute.Untargetable] = true;
+ NGolem.EnterWorld(NGolem.Position);
- public float Strength
- {
- get
- {
- var baseStrength = 0.0f;
+ //(NGolem as BaseGolem).Brain.Activate();
+ NGolem.Attributes[GameAttribute.Untargetable] = false;
+ NGolem.Attributes.BroadcastChangedIfRevealed();
+ ActiveGolem = NGolem;
+ break;
+ case ActorSno._p6_consumefleshgolem:
+ var CFGolem = new ConsumeFleshGolem(World, this);
+ CFGolem.Brain.DeActivate();
+ CFGolem.Position =
+ RandomDirection(Position, 3f,
+ 8f); //Kind of hacky until we get proper collisiondetection
+ CFGolem.Attributes[GameAttribute.Untargetable] = true;
+ CFGolem.EnterWorld(CFGolem.Position);
- if (Toon.HeroTable.CoreAttribute == GameBalance.PrimaryAttribute.Strength)
- baseStrength = Toon.HeroTable.Strength + ((Level - 1) * 3);
- else
- baseStrength = Toon.HeroTable.Strength + (Level - 1);
- return baseStrength;
- }
- }
+ //(CFGolem as ConsumeFleshGolem).Brain.Activate();
+ CFGolem.Attributes[GameAttribute.Untargetable] = false;
+ CFGolem.Attributes.BroadcastChangedIfRevealed();
+ ActiveGolem = CFGolem;
- public float TotalStrength => Attributes[GameAttribute.Strength] + Inventory.GetItemBonus(GameAttribute.Strength_Item);
+ break;
+ case ActorSno._p6_icegolem:
+ var IGolem = new IceGolem(World, this);
+ IGolem.Brain.DeActivate();
+ IGolem.Position =
+ RandomDirection(Position, 3f,
+ 8f); //Kind of hacky until we get proper collisiondetection
+ IGolem.Attributes[GameAttribute.Untargetable] = true;
+ IGolem.EnterWorld(IGolem.Position);
- public float Dexterity
- {
- get
- {
- if (Toon.HeroTable.CoreAttribute == GameBalance.PrimaryAttribute.Dexterity)
- return Toon.HeroTable.Dexterity + ((Level - 1) * 3);
- else
- return Toon.HeroTable.Dexterity + (Level - 1);
- }
- }
- public float TotalDexterity => Attributes[GameAttribute.Dexterity] + Inventory.GetItemBonus(GameAttribute.Dexterity_Item);
+ //(IGolem as IceGolem).Brain.Activate();
+ IGolem.Attributes[GameAttribute.Untargetable] = false;
+ IGolem.Attributes.BroadcastChangedIfRevealed();
+ ActiveGolem = IGolem;
+ break;
+ case ActorSno._p6_bonegolem:
+ var BGolem = new BoneGolem(World, this);
+ BGolem.Brain.DeActivate();
+ BGolem.Position =
+ RandomDirection(Position, 3f,
+ 8f); //Kind of hacky until we get proper collisiondetection
+ BGolem.Attributes[GameAttribute.Untargetable] = true;
+ BGolem.EnterWorld(BGolem.Position);
- public float Vitality => Toon.HeroTable.Vitality + ((Level - 1) * 2);
- public float TotalVitality => Attributes[GameAttribute.Vitality] + Inventory.GetItemBonus(GameAttribute.Vitality_Item);
+ //(BGolem as BoneGolem).Brain.Activate();
+ BGolem.Attributes[GameAttribute.Untargetable] = false;
+ BGolem.Attributes.BroadcastChangedIfRevealed();
+ ActiveGolem = BGolem;
+ break;
+ case ActorSno._p6_decaygolem:
+ var DGolem = new DecayGolem(World, this);
+ DGolem.Brain.DeActivate();
+ DGolem.Position =
+ RandomDirection(Position, 3f,
+ 8f); //Kind of hacky until we get proper collisiondetection
+ DGolem.Attributes[GameAttribute.Untargetable] = true;
+ DGolem.EnterWorld(DGolem.Position);
- public float Intelligence
- {
- get
- {
- if (Toon.HeroTable.CoreAttribute == GameBalance.PrimaryAttribute.Intelligence)
- return Toon.HeroTable.Intelligence + ((Level - 1) * 3);
- else
- return Toon.HeroTable.Intelligence + (Level - 1);
- }
- }
- public float TotalIntelligence => Attributes[GameAttribute.Intelligence] + Inventory.GetItemBonus(GameAttribute.Intelligence_Item);
+ //(DGolem as DecayGolem).Brain.Activate();
+ DGolem.Attributes[GameAttribute.Untargetable] = false;
+ DGolem.Attributes.BroadcastChangedIfRevealed();
+ ActiveGolem = DGolem;
+ break;
+ case ActorSno._p6_bloodgolem:
+ var BlGolem = new BloodGolem(World, this);
+ BlGolem.Brain.DeActivate();
+ BlGolem.Position =
+ RandomDirection(Position, 3f,
+ 8f); //Kind of hacky until we get proper collisiondetection
+ BlGolem.Attributes[GameAttribute.Untargetable] = true;
+ BlGolem.EnterWorld(BlGolem.Position);
- public float PrimaryAttribute
- {
- get
- {
- if (Toon.HeroTable.CoreAttribute == GameBalance.PrimaryAttribute.Strength) return TotalStrength;
- if (Toon.HeroTable.CoreAttribute == GameBalance.PrimaryAttribute.Dexterity) return TotalDexterity;
- if (Toon.HeroTable.CoreAttribute == GameBalance.PrimaryAttribute.Intelligence) return TotalIntelligence;
- return 0f;
- }
- }
- public float DodgeChance
- {
- get
- {
- float dex = TotalDexterity;
- float dodgeChance = dex / (250f * Attributes[GameAttribute.Level] + dex);
+ //(BlGolem as BloodGolem).Brain.Activate();
+ BlGolem.Attributes[GameAttribute.Untargetable] = false;
+ BlGolem.Attributes.BroadcastChangedIfRevealed();
+ ActiveGolem = BlGolem;
+ break;
+ }
- if (dex > 7500f) dodgeChance += 0.04f;
- else if (dex > 6500f) dodgeChance += 0.02f;
- else if (dex > 5500f) dodgeChance += 0.01f;
+ (ActiveGolem as Minion).Brain.Activate();
+ ActiveGolem.Attributes[GameAttribute.Untargetable] = false;
+ ActiveGolem.Attributes.BroadcastChangedIfRevealed();
+ ActiveGolem.PlayActionAnimation(AnimationSno.p6_bloodgolem_spawn_01);
+ }
+ }
+ }
+ else
+ {
+ if (ActiveGolem != null)
+ {
+ if (ActiveGolem.World != null)
+ (ActiveGolem as Minion).Kill();
+ ActiveGolem = null;
+ }
+ }
- dodgeChance = 1f - (1f - dodgeChance) * (1f - Attributes[GameAttribute.Dodge_Chance_Bonus]);
+ #endregion
+ }
- return Math.Min(dodgeChance, 0.75f);
- }
- }
+ #endregion
-#endregion
+ public T RuneSelect(int PowerSNO, T none, T runeA, T runeB, T runeC, T runeD, T runeE)
+ {
+ var Rune_A = Attributes[GameAttribute.Rune_A, PowerSNO];
+ var Rune_B = Attributes[GameAttribute.Rune_B, PowerSNO];
+ var Rune_C = Attributes[GameAttribute.Rune_C, PowerSNO];
+ var Rune_D = Attributes[GameAttribute.Rune_D, PowerSNO];
+ var Rune_E = Attributes[GameAttribute.Rune_E, PowerSNO];
-#region saved-data
+ if (Rune_A > 0) return runeA;
+ else if (Rune_B > 0) return runeB;
+ else if (Rune_C > 0) return runeC;
+ else if (Rune_D > 0) return runeD;
+ else if (Rune_E > 0) return runeE;
+ else return none;
+ }
- private PlayerSavedData GetSavedData()
- {
- var item = StringHashHelper.HashItemName("HealthPotionBottomless");
+ #region enter, leave, reveal handling
- return new PlayerSavedData()
- {
- HotBarButtons = SkillSet.HotBarSkills,
- HotBarButton = new HotbarButtonData { SNOSkill = -1, RuneType = -1, ItemGBId = StringHashHelper.HashItemName("HealthPotionBottomless")//2142362846//this.Toon.DBActiveSkills.PotionGBID
- , ItemAnn = -1 },
- SkillSlotEverAssigned = 0x0F, //0xB4,
- PlaytimeTotal = Toon.TimePlayed,
+ ///
+ /// Revals scenes in player's proximity.
+ ///
+ public void RevealScenesToPlayer()
+ {
+ //List scenes_around = this.GetScenesInRegion(DefaultQueryProximityLenght * 2);
+ var scenes_around = World.Scenes.Values.ToList();
+ if (!World.worldData.DynamicWorld)
+ scenes_around = GetScenesInRegion(DefaultQueryProximityLenght * 3);
+
+ foreach (var scene in scenes_around) // reveal scenes in player's proximity.
+ {
+ if (scene.IsRevealedToPlayer(this)) // if the actors is already revealed skip it.
+ continue; // if the scene is already revealed, skip it.
+
+ if (scene.Parent !=
+ null) // if it's a subscene, always make sure it's parent get reveals first and then it reveals his childs.
+ scene.Parent.Reveal(this);
+ else
+ scene.Reveal(this);
+ }
+
+ foreach (var scene in World.Scenes.Values) // unreveal far scenes
+ {
+ if (!scene.IsRevealedToPlayer(this) || scenes_around.Contains(scene))
+ continue;
+
+ if (scene.Parent !=
+ null) // if it's a subscene, always make sure it's parent get reveals first and then it reveals his childs.
+ scene.Parent.Unreveal(this);
+ else
+ scene.Unreveal(this);
+ }
+ }
+
+ ///
+ /// Reveals actors in player's proximity.
+ ///
+ public void RevealActorsToPlayer()
+ {
+ var Range = 200f;
+ if (InGameClient.Game.CurrentEncounter.activated)
+ Range = 360f;
+
+ var specialWorlds = new WorldSno[]
+ {
+ WorldSno.x1_pand_batteringram,
+ WorldSno.gluttony_boss,
+ WorldSno.a3dun_hub_adria_tower,
+ WorldSno.x1_malthael_boss_arena,
+ WorldSno.a1trdun_level05_templar
+ };
+
+ var actors_around = specialWorlds.Contains(World.SNO) ? World.Actors.Values.ToList() : GetActorsInRange(Range);
+
+ foreach (var actor in actors_around) // reveal actors in player's proximity.
+ {
+ if (actor is Player) // if the actors is already revealed, skip it.
+ continue;
+
+ if (World.SNO == WorldSno.x1_tristram_adventure_mode_hub && actor is Portal)
+ if ((actor as Portal).Destination.WorldSNO == (int)WorldSno.x1_tristram_adventure_mode_hub)
+ continue;
+ if (World.SNO == WorldSno.trout_town && actor is Portal)
+ if ((actor as Portal).Destination.WorldSNO == (int)WorldSno.trout_town &&
+ (actor as Portal).Destination.DestLevelAreaSNO == 19947)
+ {
+ (actor as Portal).Destination.WorldSNO = (int)WorldSno.x1_tristram_adventure_mode_hub;
+ (actor as Portal).Destination.StartingPointActorTag = 483;
+ }
+
+ if (actor.ActorType != ActorType.ClientEffect && actor.ActorType != ActorType.AxeSymbol &&
+ actor.ActorType != ActorType.CustomBrain) actor.Reveal(this);
+ }
+
+ foreach (var actor in World.Actors.Values) // unreveal far actors
+ {
+ if ((actor is Player && (!World.IsPvP || actor == this)) ||
+ actors_around.Contains(actor)) // if the actors is already revealed, skip it.
+ continue;
+
+ actor.Unreveal(this);
+ }
+ }
+
+ ///
+ /// Reveals other players in player's proximity.
+ ///
+ public void RevealPlayersToPlayer()
+ {
+ var actors = GetActorsInRange(100f);
+
+ foreach (var actor in actors) // reveal actors in player's proximity.
+ {
+ if (actor.IsRevealedToPlayer(this)) // if the actors is already revealed, skip it.
+ continue;
+
+ actor.Reveal(this);
+
+ if (!IsRevealedToPlayer(actor))
+ Reveal(actor);
+ }
+ }
+
+ public void ReRevealPlayersToPlayer()
+ {
+ var actors = GetActorsInRange(100f);
+
+ foreach (var actor in actors) // reveal actors in player's proximity.
+ {
+ if (actor.IsRevealedToPlayer(this)) // if the actors is already revealed, skip it.
+ actor.Unreveal(this);
+
+ actor.Reveal(this);
+
+ if (!IsRevealedToPlayer(actor))
+ {
+ Reveal(actor);
+ }
+ else
+ {
+ Unreveal(actor);
+ Reveal(actor);
+ }
+ }
+ }
+
+ public void ClearDoorAnimations()
+ {
+ var doors = GetActorsInRange(100f);
+ foreach (var door in doors)
+ if (door.IsRevealedToPlayer(this))
+ InGameClient.SendMessage(new SetIdleAnimationMessage
+ {
+ ActorID = door.DynamicID(this),
+ AnimationSNO = AnimationSetKeys.Open.ID
+ });
+ }
+
+ public override void OnEnter(World world)
+ {
+ world.Reveal(this);
+ Unreveal(this);
+
+ if (_CurrentHPValue == -1f)
+ DefaultQueryProximityRadius = 60;
+
+ InGameClient.SendMessage(new EnterWorldMessage()
+ {
+ EnterPosition = Position,
+ WorldID = world.GlobalID,
+ WorldSNO = (int)world.SNO,
+ PlayerIndex = PlayerIndex,
+ EnterLookUsed = true,
+ EnterKnownLookOverrides = new EnterKnownLookOverrides { Field0 = new int[] { -1, -1, -1, -1, -1, -1 } }
+ });
+
+ switch (world.SNO)
+ {
+ case WorldSno.x1_westmarch_overlook_d:
+ InGameClient.SendMessage(new PlayerSetCameraObserverMessage()
+ {
+ Field0 = 309026,
+ Field1 = new WorldPlace() { Position = new Vector3D(), WorldID = 0 }
+ });
+ break;
+ case WorldSno.x1_westm_intro:
+ InGameClient.SendMessage(new PlayerSetCameraObserverMessage()
+ {
+ Field0 = 1541,
+ Field1 = new WorldPlace() { Position = new Vector3D(), WorldID = 0 }
+ });
+ break;
+ }
+
+ if (_CurrentHPValue == -1f)
+ AddPercentageHP(100);
+
+ DefaultQueryProximityRadius = 100;
+
+ RevealScenesToPlayer();
+ RevealPlayersToPlayer();
+
+ // load all inventory items
+ if (!Inventory.Loaded)
+ {
+ //why reload if already loaded?
+ Inventory.LoadFromDB();
+ Inventory.LoadStashFromDB();
+ }
+ else
+ {
+ Inventory.RefreshInventoryToClient();
+ }
+
+ // generate visual update message
+ //this.Inventory.SendVisualInventory(this);
+ SetAllStatsInCorrectOrder();
+ SetAttributesSkillSets();
+ if (World.IsPvP)
+ DisableStoneOfRecall();
+ else
+ EnableStoneOfRecall();
+
+ Reveal(this);
+
+ System.Threading.Tasks.Task.Delay(3).Wait();
+ RevealActorsToPlayer();
+
+ //
+ }
+
+ public override void OnTeleport()
+ {
+ Unreveal(this);
+ BeforeChangeWorld();
+ RevealScenesToPlayer(); // reveal scenes in players proximity.
+ RevealPlayersToPlayer();
+ RevealActorsToPlayer(); // reveal actors in players proximity.
+ //TickTimer.WaitSeconds(this.World.Game, 5.0f, new Action((x) => Logger.Debug("Timer")));
+ Reveal(this);
+ AfterChangeWorld();
+ // load all inventory items
+ if (!Inventory.Loaded)
+ {
+ //why reload if already loaded?
+ Inventory.LoadFromDB();
+ Inventory.LoadStashFromDB();
+ }
+ else
+ {
+ Inventory.RefreshInventoryToClient();
+ }
+ }
+
+ public override void OnLeave(World world)
+ {
+ Conversations.StopAll();
+
+ // save visual equipment
+ Toon.HeroVisualEquipmentField.Value = Inventory.GetVisualEquipment();
+ //this.Toon.HeroLevelField.Value = this.Attributes[GameAttribute.Level];
+ Toon.GameAccount.ChangedFields.SetPresenceFieldValue(Toon.HeroVisualEquipmentField);
+ Toon.GameAccount.ChangedFields.SetPresenceFieldValue(Toon.HeroLevelField);
+ Toon.GameAccount.ChangedFields.SetPresenceFieldValue(Toon.HeroParagonLevelField);
+ world.Unreveal(this);
+ }
+
+ public override bool Reveal(Player player)
+ {
+ if (!base.Reveal(player))
+ return false;
+
+ if (!World.IsPvP || this == player)
+ player.InGameClient.SendMessage(new PlayerEnterKnownMessage()
+ {
+ PlayerIndex = PlayerIndex,
+ ActorId = DynamicID(player)
+ });
+
+ Inventory.SendVisualInventory(player);
+
+ if (this == player) // only send this to player itself. Warning: don't remove this check or you'll make the game start crashing! /raist.
+ player.InGameClient.SendMessage(new PlayerActorSetInitialMessage()
+ {
+ ActorId = DynamicID(player),
+ PlayerIndex = PlayerIndex
+ });
+
+ if (!base.Reveal(player))
+ Inventory.Reveal(player);
+
+ if (this == player) // only send this when player's own actor being is revealed. /raist.
+ player.InGameClient.SendMessage(new PlayerWarpedMessage()
+ {
+ WarpReason = 9,
+ WarpFadeInSecods = 0f
+ });
+
+ if (SkillSet.HasSkill(460757))
+ foreach (var skill in SkillSet.ActiveSkills)
+ if (skill.snoSkill == 460757)
+ if (skill.snoRune == 3)
+ World.BuffManager.AddBuff(this, this, new P6_Necro_Devour_Aura());
+ else
+ World.BuffManager.RemoveBuffs(this, 474325);
+
+ return true;
+ }
+
+ public override bool Unreveal(Player player)
+ {
+ if (!base.Unreveal(player))
+ return false;
+
+ Inventory.Unreveal(player);
+
+ return true;
+ }
+
+ public Dictionary AllBuffs = new();
+
+ public bool BetweenWorlds = false;
+
+ public override void BeforeChangeWorld()
+ {
+ ClearDoorAnimations();
+ World.Game.QuestManager.UnsetBountyMarker(this);
+ BetweenWorlds = true;
+ AllBuffs = World.BuffManager.GetAllBuffs(this);
+ World.BuffManager.RemoveAllBuffs(this);
+ //this.Inventory.Unreveal(this);
+ //this.InGameClient.TickingEnabled = false;
+ /*this.InGameClient.SendMessage(new FreezeGameMessage
+ {
+ Field0 = true
+ });*/
+
+ InGameClient.SendMessage(new ACDTranslateSyncMessage()
+ {
+ ActorId = DynamicID(this),
+ Position = Position
+ });
+
+ _CurrentHPValue = Attributes[GameAttribute.Hitpoints_Cur];
+ _CurrentResourceValue = Attributes[GameAttribute.Resource_Cur, (int)Toon.HeroTable.PrimaryResource + 1];
+ }
+
+ public override void AfterChangeWorld()
+ {
+ //this.InGameClient.TickingEnabled = true;
+ /*
+ this.InGameClient.SendMessage(new FreezeGameMessage
+ {
+ Field0 = false
+ });
+ */
+ Inventory.Reveal(this);
+
+ foreach (var buff in AllBuffs)
+ World.BuffManager.CopyBuff(this, this, buff.Key, buff.Value);
+ AllBuffs.Clear();
+ BetweenWorlds = false;
+
+ if (_CurrentHPValue != -1)
+ {
+ Attributes[GameAttribute.Hitpoints_Cur] = _CurrentHPValue;
+ Attributes[GameAttribute.Resource_Cur, (int)Toon.HeroTable.PrimaryResource + 1] = _CurrentResourceValue;
+ Attributes.BroadcastChangedIfRevealed();
+ _CurrentHPValue = -1;
+ }
+
+ World.Game.QuestManager.SetBountyMarker(this);
+
+
+ //System.Threading.Tasks.Task.Delay(1000).ContinueWith(a => {this.BetweenWorlds = false;});
+ }
+
+ #endregion
+
+ #region hero-state
+
+ public void WTF()
+ {
+ Attributes[GameAttribute.Power_Buff_0_Visual_Effect_None, 208468] = true;
+ Attributes[GameAttribute.Thorns_Fixed_Total, 0] = 0;
+ Attributes[GameAttribute.Damage_Delta_Total, 0] = 0;
+ Attributes[GameAttribute.UnequippedTime, 4] = 0;
+ Attributes[GameAttribute.Experience_Next_Lo] = 717;
+ Attributes[GameAttribute.Skill_Total, 93395] = 1;
+ Attributes[GameAttribute.Strength] = 0;
+ Attributes[GameAttribute.Attacks_Per_Second_Percent_Cap] = 0;
+ Attributes[GameAttribute.Invulnerable] = true;
+ Attributes[GameAttribute.UnequippedTime, 7] = 0;
+ Attributes[GameAttribute.Damage_Min, 0] = 0;
+ Attributes[GameAttribute.Damage_Weapon_Min_Total_All] = 0;
+ Attributes[GameAttribute.Damage_Delta_Total, 3] = 0;
+ Attributes[GameAttribute.General_Cooldown] = 0;
+ Attributes[GameAttribute.Attacks_Per_Second_Total] = 0;
+ Attributes[GameAttribute.Resource_Cur, 1] = 0;
+ Attributes[GameAttribute.UnequippedTime, 6] = 0;
+ Attributes[GameAttribute.Backpack_Slots] = 60;
+ Attributes[GameAttribute.Corpse_Resurrection_Charges] = 3;
+ Attributes[GameAttribute.Skill, 93395] = 1;
+ Attributes[GameAttribute.Trait, 451242] = 2;
+ Attributes[GameAttribute.UnequippedTime, 9] = 0;
+ Attributes[GameAttribute.Attacks_Per_Second] = 0;
+ Attributes[GameAttribute.TeamID] = 2;
+ Attributes[GameAttribute.Resource_Degeneration_Stop_Point, 1048575] = 0;
+ Attributes[GameAttribute.Resource_Max_Bonus, 1] = 0;
+ Attributes[GameAttribute.Armor_Total] = 0;
+ Attributes[GameAttribute.Skill_Total, 1759] = 1;
+ Attributes[GameAttribute.SkillKit] = 35584;
+ Attributes[GameAttribute.Armor_Item_Total] = 0;
+ Attributes[GameAttribute.Resistance_Total, 5] = 0;
+ Attributes[GameAttribute.Skill, 30718] = 1;
+ Attributes[GameAttribute.CantStartDisplayedPowers] = true;
+ Attributes[GameAttribute.Seasononlyitemsunlocked] = true;
+ Attributes[GameAttribute.UnequippedTime, 10] = 0;
+ Attributes[GameAttribute.Damage_Weapon_Delta_Total_All] = 0;
+ Attributes[GameAttribute.Damage_Min_Total, 3] = 0;
+ Attributes[GameAttribute.Resource_Cost_Reduction_Percent_All] = 0;
+ Attributes[GameAttribute.Get_Hit_Recovery] = 0;
+ Attributes[GameAttribute.Skill, 1759] = 1;
+ Attributes[GameAttribute.Buff_Icon_Start_Tick0, 439438] = 155;
+ Attributes[GameAttribute.Buff_Icon_End_Tick0, 439438] = 3755;
+ Attributes[GameAttribute.Skill, 30744] = 1;
+ Attributes[GameAttribute.Get_Hit_Recovery_Per_Level] = 0;
+ Attributes[GameAttribute.Requirement, 57] = 0;
+ Attributes[GameAttribute.Damage_Weapon_Delta, 3] = 0;
+ Attributes[GameAttribute.Attacks_Per_Second_Item_CurrentHand] = 0;
+ Attributes[GameAttribute.Get_Hit_Recovery_Base] = 0;
+ Attributes[GameAttribute.Resistance_From_Intelligence] = 0;
+ Attributes[GameAttribute.Damage_Weapon_Delta, 0] = 0;
+ Attributes[GameAttribute.Get_Hit_Max] = 0;
+ Attributes[GameAttribute.Crit_Damage_Cap] = 0;
+ Attributes[GameAttribute.Class_Damage_Reduction_Percent_PVP] = 0;
+ Attributes[GameAttribute.Buff_Icon_Count0, 212032] = 1;
+ Attributes[GameAttribute.Hit_Chance] = 0;
+ Attributes[GameAttribute.Crit_Percent_Cap] = 0;
+ Attributes[GameAttribute.Get_Hit_Max_Per_Level] = 0;
+ Attributes[GameAttribute.Resource_Regen_Per_Second, 1] = 0;
+ Attributes[GameAttribute.Buff_Icon_Count0, 134334] = 1;
+ Attributes[GameAttribute.Buff_Icon_End_Tick0, 134334] = 2101;
+ Attributes[GameAttribute.Buff_Icon_Start_Tick0, 134334] = 301;
+ Attributes[GameAttribute.Banter_Cooldown, 1048575] = 0;
+ Attributes[GameAttribute.Hidden] = false;
+ Attributes[GameAttribute.Buff_Icon_Count0, 439438] = 0;
+ Attributes[GameAttribute.Buff_Icon_Start_Tick0, 212032] = 0;
+ Attributes[GameAttribute.Buff_Icon_End_Tick0, 212032] = 0;
+ Attributes[GameAttribute.Immobolize] = false;
+ Attributes[GameAttribute.Untargetable] = false;
+ Attributes[GameAttribute.Loading] = false;
+ Attributes[GameAttribute.Invulnerable] = false;
+ Attributes[GameAttribute.Resource_Degeneration_Stop_Point, 1048575] = 0;
+ Attributes[GameAttribute.CantStartDisplayedPowers] = false;
+ Attributes[GameAttribute.Buff_Icon_Start_Tick0, 439438] = 0;
+ Attributes[GameAttribute.Buff_Icon_End_Tick0, 439438] = 0;
+ Attributes[GameAttribute.Buff_Icon_Count0, 212032] = 0;
+ Attributes.BroadcastChangedIfRevealed();
+ }
+
+ ///
+ /// Allows hero state message to be sent when hero's some property get's updated.
+ ///
+ public void UpdateHeroState()
+ {
+ InGameClient.SendMessage(new HeroStateMessage
+ {
+ State = GetStateData(),
+ PlayerIndex = PlayerIndex
+ });
+ }
+
+ public HeroStateData GetStateData()
+ {
+ return new HeroStateData()
+ {
+ LastPlayedAct = 400, //LastPlayedAct
+ HighestUnlockedAct = 400, //HighestUnlockedAct
+ PlayedFlags = (int)Toon.Flags,
+ PlayerSavedData = GetSavedData(),
+ //QuestRewardHistoryEntriesCount = QuestRewardHistory.Count,
+ tQuestRewardHistory = QuestRewardHistory.ToArray()
+ };
+ }
+
+ #endregion
+
+ #region player attribute handling
+
+ public void QueueDeath(bool state)
+ {
+ //this.World.BroadcastIfRevealed(this.ACDWorldPositionMessage, this);
+ InGameClient.SendMessage(new ACDTranslateSyncMessage()
+ {
+ ActorId = DynamicID(this),
+ Position = Position
+ });
+ Attributes[GameAttribute.QueueDeath] = state;
+ Attributes[GameAttribute.Disabled] = state;
+ Attributes[GameAttribute.Waiting_To_Accept_Resurrection] = false;
+ Attributes[GameAttribute.Invulnerable] = state;
+ //this.Attributes[GameAttribute.Stunned] = state;
+ Attributes[GameAttribute.Immobolize] = state;
+ Attributes[GameAttribute.Hidden] = state;
+ Attributes[GameAttribute.Untargetable] = state;
+ Attributes[GameAttribute.CantStartDisplayedPowers] = state;
+ Attributes[GameAttribute.IsContentRestrictedActor] = state;
+
+ Attributes[GameAttribute.Rest_Experience_Lo] = 0;
+ Attributes[GameAttribute.Rest_Experience_Bonus_Percent] = 0;
+
+ Attributes.BroadcastChangedIfRevealed();
+ if (World.Game.PvP) Attributes[GameAttribute.Resurrect_As_Observer] = state;
+ //this.Attributes[GameAttribute.Observer] = !state;
+ //this.Attributes[GameAttribute.Corpse_Resurrection_Charges] = 1; // Enable this to allow unlimited resurrection at corpse
+ //this.Attributes[GameAttribute.Corpse_Resurrection_Allowed_Game_Time] = this.World.Game.TickCounter + 300; // Timer for auto-revive (seems to be broken?)
+ Attributes.BroadcastChangedIfRevealed();
+ }
+
+ public void Resurrect()
+ {
+ Attributes[GameAttribute.Waiting_To_Accept_Resurrection] = true;
+ Attributes.BroadcastChangedIfRevealed();
+ }
+
+ public void Revive(Vector3D spawnPosition)
+ {
+ if (World == null) return;
+ /*if (this.World.Game.IsHardcore)
+ {
+ this.InGameClient.SendMessage(new LogoutTickTimeMessage()
+ {
+ Field0 = false, // true - logout with party?
+ Ticks = 0, // delay 1, make this equal to 0 for instant logout
+ Field2 = 0, // delay 2
+ });
+ } else
+ {*/
+ QueueDeath(false);
+ Dead = false;
+ AddPercentageHP(100);
+
+ World.BroadcastIfRevealed(plr => new SetIdleAnimationMessage
+ {
+ ActorID = DynamicID(plr),
+ AnimationSNO = AnimationSetKeys.IdleDefault.ID
+ }, this);
+
+ //removing tomb
+ try
+ {
+ GetObjectsInRange(100.0f).Where(h => h.playerIndex == PlayerIndex).First().Destroy();
+ }
+ catch
+ {
+ }
+
+ Teleport(spawnPosition);
+ World.BuffManager.AddBuff(this, this, new ActorGhostedBuff());
+
+ var old_skills = SkillSet.ActiveSkills.Select(s => s.snoSkill).ToList();
+ foreach (var skill in old_skills)
+ {
+ var power = PowerLoader.CreateImplementationForPowerSNO(skill);
+ if (power != null && power.EvalTag(PowerKeys.SynergyPower) != -1)
+ World.BuffManager.RemoveBuffs(this, power.EvalTag(PowerKeys.SynergyPower));
+ }
+
+ SetAttributesByItems();
+ SetAttributesByItemProcs();
+ SetAttributesByGems();
+ SetAttributesByItemSets();
+ SetAttributesByPassives();
+ SetAttributesByParagon();
+ SetAttributesSkillSets();
+
+ Attributes[GameAttribute.Resource_Cur, PrimaryResourceID] = 0f;
+ if (Toon.Class == ToonClass.DemonHunter)
+ Attributes[GameAttribute.Resource_Cur, SecondaryResourceID] = 0f;
+ Attributes.BroadcastChangedIfRevealed();
+
+ var skills = SkillSet.ActiveSkills.Select(s => s.snoSkill).ToList();
+ var cooldowns = World.BuffManager.GetBuffs(this);
+ foreach (var skill in skills)
+ {
+ var inCooldown = false;
+ CooldownBuff skillcd = null;
+ foreach (var cooldown in cooldowns)
+ if (cooldown.TargetPowerSNO == skill)
+ {
+ skillcd = cooldown;
+ inCooldown = true;
+ break;
+ }
+
+ if (inCooldown && skillcd != null) skillcd.Extend((int)3 * 60);
+ else _StartSkillCooldown(skill, 3f);
+ }
+
+ Inventory.RefreshInventoryToClient();
+ UpdatePercentageHP(PercHPbeforeChange);
+ }
+
+
+ public float Strength
+ {
+ get
+ {
+ var baseStrength = 0.0f;
+
+ if (Toon.HeroTable.CoreAttribute == GameBalance.PrimaryAttribute.Strength)
+ baseStrength = Toon.HeroTable.Strength + (Level - 1) * 3;
+ else
+ baseStrength = Toon.HeroTable.Strength + (Level - 1);
+
+ return baseStrength;
+ }
+ }
+
+ public float TotalStrength =>
+ Attributes[GameAttribute.Strength] + Inventory.GetItemBonus(GameAttribute.Strength_Item);
+
+ public float Dexterity
+ {
+ get
+ {
+ if (Toon.HeroTable.CoreAttribute == GameBalance.PrimaryAttribute.Dexterity)
+ return Toon.HeroTable.Dexterity + (Level - 1) * 3;
+ else
+ return Toon.HeroTable.Dexterity + (Level - 1);
+ }
+ }
+
+ public float TotalDexterity =>
+ Attributes[GameAttribute.Dexterity] + Inventory.GetItemBonus(GameAttribute.Dexterity_Item);
+
+ public float Vitality => Toon.HeroTable.Vitality + (Level - 1) * 2;
+
+ public float TotalVitality =>
+ Attributes[GameAttribute.Vitality] + Inventory.GetItemBonus(GameAttribute.Vitality_Item);
+
+ public float Intelligence
+ {
+ get
+ {
+ if (Toon.HeroTable.CoreAttribute == GameBalance.PrimaryAttribute.Intelligence)
+ return Toon.HeroTable.Intelligence + (Level - 1) * 3;
+ else
+ return Toon.HeroTable.Intelligence + (Level - 1);
+ }
+ }
+
+ public float TotalIntelligence => Attributes[GameAttribute.Intelligence] +
+ Inventory.GetItemBonus(GameAttribute.Intelligence_Item);
+
+ public float PrimaryAttribute
+ {
+ get
+ {
+ if (Toon.HeroTable.CoreAttribute == GameBalance.PrimaryAttribute.Strength) return TotalStrength;
+ if (Toon.HeroTable.CoreAttribute == GameBalance.PrimaryAttribute.Dexterity) return TotalDexterity;
+ if (Toon.HeroTable.CoreAttribute == GameBalance.PrimaryAttribute.Intelligence) return TotalIntelligence;
+ return 0f;
+ }
+ }
+
+ public float DodgeChance
+ {
+ get
+ {
+ var dex = TotalDexterity;
+ var dodgeChance = dex / (250f * Attributes[GameAttribute.Level] + dex);
+
+ if (dex > 7500f) dodgeChance += 0.04f;
+ else if (dex > 6500f) dodgeChance += 0.02f;
+ else if (dex > 5500f) dodgeChance += 0.01f;
+
+ dodgeChance = 1f - (1f - dodgeChance) * (1f - Attributes[GameAttribute.Dodge_Chance_Bonus]);
+
+ return Math.Min(dodgeChance, 0.75f);
+ }
+ }
+
+ #endregion
+
+ #region saved-data
+
+ private PlayerSavedData GetSavedData()
+ {
+ var item = StringHashHelper.HashItemName("HealthPotionBottomless");
+
+ return new PlayerSavedData()
+ {
+ HotBarButtons = SkillSet.HotBarSkills,
+ HotBarButton = new HotbarButtonData
+ {
+ SNOSkill = -1, RuneType = -1, ItemGBId =
+ StringHashHelper.HashItemName(
+ "HealthPotionBottomless") //2142362846//this.Toon.DBActiveSkills.PotionGBID
+ ,
+ ItemAnn = -1
+ },
+ SkillSlotEverAssigned = 0x0F, //0xB4,
+ PlaytimeTotal = Toon.TimePlayed,
#if DEBUG
- WaypointFlags = 0x0000ffff,
+ WaypointFlags = 0x0000ffff,
#else
WaypointFlags = this.World.Game.WaypointFlags,
#endif
- HirelingData = new HirelingSavedData()
- {
- HirelingInfos = HirelingInfo,
- ActiveHireling = 0x00000000,
- AvailableHirelings = 0x00000004,
- },
-
- TimeLastLevel = 0,
- LearnedLore = LearnedLore,
-
- ActiveSkills = SkillSet.ActiveSkills,
- snoTraits = SkillSet.PassiveSkills,
- GBIDLegendaryPowers = new int[4] { -1, -1, -1, -1 },
-
- SavePointData = new SavePointData { snoWorld = -1, SavepointId = -1, },
- EventFlags = 0
- };
- }
-
- public SavePointData SavePointData { get; set; }
-
- public LearnedLore LearnedLore = new LearnedLore()
- {
- Count = 0x00000000,
- m_snoLoreLearned = new int[512]
- {
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000
- },
- };
-
- public void SaveStats() //Save 6 primary stats into DB for showing on hero screen
- {
- //Logger.Debug("SaveStats(): Strength {0}", this.Inventory.GetItemBonus(GameAttribute.Strength_Item).ToString("F0"));
- float damageFromWeapon = (Inventory.GetItemBonus(GameAttribute.Damage_Weapon_Min_Total, 0) + Inventory.GetItemBonus(GameAttribute.Damage_Weapon_Delta_Total, 0)) * (1f + (PrimaryAttribute / 100f));
-
- float totalDamage =
- (damageFromWeapon
- + (damageFromWeapon * Inventory.GetItemBonus(GameAttribute.Weapon_Crit_Chance) * (1.5f + Inventory.GetItemBonus(GameAttribute.Crit_Damage_Percent))))
- * Inventory.GetItemBonus(GameAttribute.Attacks_Per_Second_Total);
-
- string serialized = "";
- serialized += Inventory.GetItemBonus(GameAttribute.Strength_Item).ToString("F0");
- serialized += ";";
- serialized += Inventory.GetItemBonus(GameAttribute.Dexterity_Item).ToString("F0");
- serialized += ";";
- serialized += Inventory.GetItemBonus(GameAttribute.Intelligence_Item).ToString("F0");
- serialized += ";";
- serialized += Inventory.GetItemBonus(GameAttribute.Vitality_Item).ToString("F0");
- serialized += ";";
- serialized += Inventory.GetItemBonus(GameAttribute.Armor_Item).ToString("F0");
- serialized += ";";
- serialized += (totalDamage).ToString("F0");
- var dbStats = Toon.DBToon;
- dbStats.Stats = serialized;
- World.Game.GameDBSession.SessionUpdate(dbStats);
- }
-
- public List QuestRewardHistory
- {
- get
- {
- var result = new List();
- var quests = InGameClient.Game.QuestManager.Quests.Where(q => q.Value.Completed).ToList();
- foreach (var quest in quests)
- {
- InGameClient.SendMessage(new QuestUpdateMessage()
- {
- snoQuest = quest.Key,
- snoLevelArea = -1,
- StepID = quest.Value.Steps.Last().Key,
- DisplayButton = false,
- Failed = false
- });
-
- result.Add(new PlayerQuestRewardHistoryEntry()
- {
- snoQuest = quest.Key,
- Field1 = 0,
- Field2 = (PlayerQuestRewardHistoryEntry.Difficulty)InGameClient.Game.Difficulty
- });
- }
- return result;
- }
- }
-
- private HirelingInfo[] _hirelingInfo = null;
-
- public HirelingInfo[] HirelingInfo
- {
- get
- {
- if (_hirelingInfo == null)
- {
- _hirelingInfo = new HirelingInfo[4];
- for (int i = 0; i < 4; i++)
- _hirelingInfo[i] = GetHirelingInfo(i);
- }
- return _hirelingInfo;
- }
- set => _hirelingInfo = value;
- }
-
-#endregion
-
-#region cooked messages
-
- public void StopMoving()
- {
- World.BroadcastIfRevealed(plr => new ACDTranslateNormalMessage
- {
- ActorId = DynamicID(plr),
- Position = Position,
- SnapFacing = false,
- MovementSpeed = 0,
- AnimationTag = -1
- }, this);
- }
-
- public void CheckBonusSets()
- {
- List sets = World.Game.GameDBSession.SessionQueryWhere(dbi => dbi.DBAccount.Id == Toon.GameAccount.AccountId).ToList();
- foreach (var bonusSet in sets)
- {
- if (World.Game.IsHardcore)
- {
- if (bonusSet.ClaimedHardcore) continue;
- }
- else
- {
- if (bonusSet.Claimed) continue;
- }
-
- //if (!BonusSetsList.CollectionEditions.ContainsKey(bonusSet.SetId)) continue;
-
- if (bonusSet.SetId == 6 && World.Game.IsHardcore) continue;
-
- //if (!(bonusSet.Claimed || bonusSet.ClaimedHardcore))
- // BonusSetsList.CollectionEditions[bonusSet.SetId].ClaimOnce(this);
-
- if (World.Game.IsHardcore)
- bonusSet.ClaimedHardcore = true;
- else
- {
- bonusSet.Claimed = true;
- bonusSet.ClaimedToon = Toon.DBToon;
- }
-
- //BonusSetsList.CollectionEditions[bonusSet.SetId].Claim(this);
- World.Game.GameDBSession.SessionUpdate(bonusSet);
- //this.InGameClient.SendMessage(new BroadcastTextMessage() { Field0 = "You have been granted with gifts from bonus pack!" });
- }
- }
-
- public HirelingInfo GetHirelingInfo(int type)
- {
- var query = World.Game.GameDBSession.SessionQueryWhere(dbh => dbh.DBToon.Id == Toon.PersistentID && dbh.Class == type).ToList();
- if (query.Count == 0)
- { //returns empty data
- var hireling_empty = new HirelingInfo { HirelingIndex = type, GbidName = 0x0000, Dead = false, Skill1SNOId = -1, Skill2SNOId = -1, Skill3SNOId = -1, Skill4SNOId = -1, annItems = -1 };
- return hireling_empty;
- }
- var hireling_full = new HirelingInfo
- {
- HirelingIndex = type,
- GbidName = 0x0000,
- Dead = false,
- Skill1SNOId = query.First().Skill1SNOId,
- Skill2SNOId = query.First().Skill2SNOId,
- Skill3SNOId = query.First().Skill3SNOId,
- Skill4SNOId = query.First().Skill4SNOId,
- annItems = -1
- };
- return hireling_full;
- }
-
- private List Unserialize(string data)
- {
- string[] recparts = data.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
- List ret = new List();
- foreach (string recid in recparts)
- {
- ret.Add(Convert.ToInt32(recid, 10));
- }
- return ret;
- }
-
- private string Serialize(List data)
- {
- string serialized = "";
- foreach (int id in data)
- {
- serialized += id;
- serialized += ";";
- }
- return serialized;
- }
-
- private List UnserializeBytes(byte[] data)
- {
- return Enumerable.Range(0, data.Length / 4).Select(i => BitConverter.ToInt32(data, i * 4)).ToList();
- }
-
- private byte[] SerializeBytes(List data)
- {
- return data.SelectMany(BitConverter.GetBytes).ToArray();
- }
-
- public void LearnRecipe(ArtisanType? artisan, int recipe)
- {
- Logger.Trace("Learning recipe #{0}, Artisan type: {1}", recipe, artisan);
- /*var query = this.World.Game.GameDBSession.SessionQuerySingle(
- dbi =>
- dbi.DBGameAccount.Id == this.Toon.GameAccount.PersistentID &&
- dbi.Artisan == artisan &&
- dbi.isHardcore == this.World.Game.IsHardcore);*/
- if (artisan == ArtisanType.Blacksmith)
- {
- learnedBlacksmithRecipes.Add(recipe);
- blacksmith_data.LearnedRecipes = SerializeBytes(learnedBlacksmithRecipes);
- World.Game.GameDBSession.SessionUpdate(blacksmith_data);
- UpdateAchievementCounter(404, 1, 0);
- }
- else if (artisan == ArtisanType.Jeweler)
- {
- learnedJewelerRecipes.Add(recipe);
- jeweler_data.LearnedRecipes = SerializeBytes(learnedJewelerRecipes);
- World.Game.GameDBSession.SessionUpdate(jeweler_data);
- UpdateAchievementCounter(404, 1, 1);
- }
-
- LoadCrafterData();
- }
-
- public bool RecipeAvailable(GameBalance.RecipeTable recipe_definition)
- {
- if (recipe_definition.Flags == 0) return true;
- return (learnedBlacksmithRecipes.Contains(recipe_definition.Hash) || learnedJewelerRecipes.Contains(recipe_definition.Hash));
- }
-
- public PlayerBannerMessage GetPlayerBanner()
- {
- var playerBanner = D3.GameMessage.PlayerBanner.CreateBuilder()
- .SetPlayerIndex((uint)PlayerIndex)
- .SetBanner(Toon.GameAccount.BannerConfigurationField.Value)
- .Build();
-
- return new PlayerBannerMessage() { PlayerBanner = playerBanner };
- }
-
- private List learnedBlacksmithRecipes = new List();
- private List learnedJewelerRecipes = new List();
- private List learnedTransmogs = new List();
-
- private DBCraft blacksmith_data = null;
- private DBCraft jeweler_data = null;
- private DBCraft mystic_data = null;
- private Dictionary artisanTrainHelpers = new();
-
- public void LoadCrafterData()
- {
- if (blacksmith_data == null)
- {
- List craft_data = World.Game.GameDBSession.SessionQueryWhere(dbc => dbc.DBGameAccount.Id == Toon.GameAccount.PersistentID);
-
- blacksmith_data = craft_data.Single(dbc => dbc.Artisan == "Blacksmith" && dbc.isHardcore == World.Game.IsHardcore && dbc.isSeasoned == World.Game.IsSeasoned);
- jeweler_data = craft_data.Single(dbc => dbc.Artisan == "Jeweler" && dbc.isHardcore == World.Game.IsHardcore && dbc.isSeasoned == World.Game.IsSeasoned);
- mystic_data = craft_data.Single(dbc => dbc.Artisan == "Mystic" && dbc.isHardcore == World.Game.IsHardcore && dbc.isSeasoned == World.Game.IsSeasoned);
-
- artisanTrainHelpers[ArtisanType.Blacksmith] = new ArtisanTrainHelper(blacksmith_data, ArtisanType.Blacksmith);
- artisanTrainHelpers[ArtisanType.Jeweler] = new ArtisanTrainHelper(jeweler_data, ArtisanType.Jeweler);
- artisanTrainHelpers[ArtisanType.Mystic] = new ArtisanTrainHelper(mystic_data, ArtisanType.Mystic);
- }
-
-
-
- D3.ItemCrafting.CrafterData blacksmith = D3.ItemCrafting.CrafterData.CreateBuilder()
- .SetLevel(InGameClient.Game.CurrentAct == 3000 ? BlacksmithUnlocked == false && blacksmith_data.Level < 1 ? 1 : blacksmith_data.Level : blacksmith_data.Level)
- .SetCooldownEnd(0)
- .AddRangeRecipes(UnserializeBytes(blacksmith_data.LearnedRecipes))
- .Build();
- learnedBlacksmithRecipes = UnserializeBytes(blacksmith_data.LearnedRecipes);
- D3.ItemCrafting.CrafterData jeweler = D3.ItemCrafting.CrafterData.CreateBuilder()
- .SetLevel(InGameClient.Game.CurrentAct == 3000 ? JewelerUnlocked == false && jeweler_data.Level < 1 ? 1 : jeweler_data.Level : jeweler_data.Level)
- .SetCooldownEnd(0)
- .AddRangeRecipes(UnserializeBytes(jeweler_data.LearnedRecipes))
- .Build();
- learnedJewelerRecipes = UnserializeBytes(jeweler_data.LearnedRecipes);
- D3.ItemCrafting.CrafterData mystic = D3.ItemCrafting.CrafterData.CreateBuilder()
- .SetLevel(InGameClient.Game.CurrentAct == 3000 ? MysticUnlocked == false && mystic_data.Level < 1 ? 1 : mystic_data.Level : mystic_data.Level)
- .SetCooldownEnd(0)
- .Build();
-
- D3.ItemCrafting.CrafterSavedData transmog = D3.ItemCrafting.CrafterSavedData.CreateBuilder()
- .SetTransmogData(D3.GameBalance.BitPackedGbidArray.CreateBuilder().SetBitfield(ByteString.CopyFrom(mystic_data.LearnedRecipes)))
- //.AddRangeUnlockedTransmogs(this.UnserializeBytes(mystic_data.LearnedRecipes))
- .Build();
- learnedTransmogs = UnserializeBytes(mystic_data.LearnedRecipes);
-
- if (BlacksmithUnlocked || InGameClient.Game.CurrentAct == 3000)
- InGameClient.SendMessage(new GenericBlobMessage(Opcodes.CraftingDataBlacksmithInitialMessage) { Data = blacksmith.ToByteArray() });
-
- if (JewelerUnlocked || InGameClient.Game.CurrentAct == 3000)
- InGameClient.SendMessage(new GenericBlobMessage(Opcodes.CraftingDataJewelerInitialMessage) { Data = jeweler.ToByteArray() });
-
- if (MysticUnlocked || InGameClient.Game.CurrentAct == 3000)
- {
- InGameClient.SendMessage(new GenericBlobMessage(Opcodes.CraftingDataMysticInitialMessage) { Data = mystic.ToByteArray() });
- InGameClient.SendMessage(new GenericBlobMessage(Opcodes.CraftingDataTransmogInitialMessage) { Data = transmog.ToByteArray() });
- }
- }
-
- public void LoadCurrencyData()
- {
- int bloodShards = 0;
- bloodShards = this.Toon.GameAccount.BloodShards;
- this.Inventory.UpdateCurrencies();
- }
-
- public void LoadMailData()
- {
- List mail_data = World.Game.GameDBSession.SessionQueryWhere(dbm => dbm.DBToon.Id == Toon.PersistentID && dbm.Claimed == false);
- var mails = D3.Items.Mails.CreateBuilder();
- foreach (var mail in mail_data)
- {
- var mail_row = D3.Items.Mail.CreateBuilder()
- .SetAccountTo(Toon.D3EntityID)
- .SetAccountFrom(Toon.D3EntityID)
- .SetMailId(mail.Id)
- .SetTitle(mail.Title)
- .SetBody(mail.Body);
- if (mail.ItemGBID != -1)
- mail_row.SetAttachments(D3.Items.MailAttachments.CreateBuilder()
- .SetItems(D3.Items.ItemList.CreateBuilder()
- .AddItems(D3.Items.SavedItem.CreateBuilder()
- .SetId(D3.OnlineService.ItemId.CreateBuilder().SetIdLow(0).SetIdHigh(0x3C000002517A294))
- .SetHirelingClass(0)
- .SetItemSlot(0)
- .SetSquareIndex(0)
- .SetUsedSocketCount(0)
- .SetGenerator(D3.Items.Generator.CreateBuilder()
- .SetGbHandle(D3.GameBalance.Handle.CreateBuilder().SetGbid(mail.ItemGBID).SetGameBalanceType(2))
- .SetFlags(2147483647)
- .SetSeed(0)
- .SetDurability(0)
- .SetStackSize(0)
- )
- )
- )
- );
- mails.AddMailsProp(mail_row);
- }
- var mail_contents = D3.GameMessage.MailContents.CreateBuilder()
- .SetAppendMessages(false)
- .SetMails(mails)
- .Build();
-
- InGameClient.SendMessage(new MailDigestMessage() { MailContents = mail_contents }) ;
- }
- //*/
- public void LoadStashIconsData()
- {
- var dbGAcc = Toon.GameAccount.DBGameAccount;
- if (dbGAcc.StashIcons == null) return;
-
- //this.InGameClient.SendMessage(new StashIconStateMessage() { StashIcons = dbGAcc.StashIcons });
- }
-
- public void NotifyMaintenance()
- {
- if (GameServer.ClientSystem.GameServer.MaintenanceTime > 0 && GameServer.ClientSystem.GameServer.MaintenanceTime > (int)DateTime.Now.ToUnixTime())
- InGameClient.SendMessage(new LogoutTickTimeMessage()
- {
- Field0 = false, // true - logout with party?
- Ticks = 0, // delay 1, make this equal to 0 for instant logout
- Field2 = 10000, // delay 2
- Field3 = (GameServer.ClientSystem.GameServer.MaintenanceTime - (int)DateTime.Now.ToUnixTime()) * 60 //maintenance counter
- });
- }
-
- public void LoadShownTutorials()
- {
- List tutorials = new List();
- tutorials.Add(64);
- for (int i = 0; i < 15; i++)
- tutorials.Add(0);
- var seenTutorials = Toon.GameAccount.DBGameAccount.SeenTutorials;
-
- D3.GameMessage.TutorialState state = D3.GameMessage.TutorialState.CreateBuilder()
- .SetSeenTutorials(ByteString.CopyFrom(seenTutorials))
- .Build();
- InGameClient.SendMessage(new GenericBlobMessage(Opcodes.TutorialStateMessage) { Data = state.ToByteArray() });
- }
-
- private List _unlockedAchievements = new List();
- private List _unlockedCriterias = new List();
-
- private Dictionary AchievementCounters = new Dictionary();
-
- public int DodgesInARow = 0;
- public int BlocksInARow = 0;
-
- public void GrantAchievement(ulong id)
- {
- if (_unlockedAchievements.Contains(id)) return;
- if (InGameClient.BnetClient.Account.GameAccount.Achievements.Where(a => a.AchievementId == id && a.Completion != -1).Count() > 0) return;
- if (_unlockedAchievements.Contains(id)) return;
- _unlockedAchievements.Add(id);
- try
- {
- var Achievement = AchievementSystem.AchievementManager.GetAchievementById(id);
- long Platinum = -1;
- foreach (var attr in Achievement.AttributesList)
- if (attr.Key == "Reward Currency Quantity")
- Platinum = Int64.Parse(attr.Value);
- InGameClient.SendMessage(new MessageSystem.Message.Definitions.Platinum.PlatinumAchievementAwardedMessage
- {
- CurrentPlatinum = InGameClient.BnetClient.Account.GameAccount.Platinum,
- idAchievement = id,
- PlatinumIncrement = Platinum
- });
- if (Platinum > 0)
- {
- InGameClient.BnetClient.Account.GameAccount.Platinum += (int)Platinum;
- Inventory.UpdateCurrencies();
- }
- ClientSystem.GameServer.GSBackend.GrantAchievement(Toon.GameAccount.PersistentID, id);
-
- }
- catch (Exception e)
- {
- Logger.WarnException(e, "Exception on GrantAchievement(): ");
- }
- }
-
- public void AddAchievementCounter(ulong id, uint count)
- {
- lock (AchievementCounters)
- {
- if (!AchievementCounters.ContainsKey(id))
- AchievementCounters.Add(id, count);
- else
- AchievementCounters[id] += count;
- }
- }
-
- public void CheckAchievementCounters()
- {
- lock (AchievementCounters)
- {
- foreach (var counter in AchievementCounters)
- {
- if (counter.Value == 0) continue;
- UpdateSingleAchievementCounter(counter.Key, counter.Value);
- }
- AchievementCounters.Clear();
- }
- }
-
- public void GrantCriteria(ulong id)
- {
- if (_unlockedCriterias.Contains(id)) return;
- _unlockedCriterias.Add(id);
- try
- {
- GameServer.ClientSystem.GameServer.GSBackend.GrantCriteria(Toon.GameAccount.PersistentID, id);
- }
- catch (Exception e)
- {
- Logger.WarnException(e, "Exception on GrantCriteria(): ");
- }
- }
-
- public void UpdateQuantity(ulong id, uint counter)
- {
- try
- {
- GameServer.ClientSystem.GameServer.GSBackend.UpdateQuantity(Toon.GameAccount.PersistentID, id, counter);
- }
- catch (Exception e)
- {
- Logger.WarnException(e, "Exception on UpdateQuantity(): ");
- }
- }
-
- public void UpdateAchievementCounter(int type, uint addCounter, int comparand = -1, ulong achiId = 0)
- {
- try
- {
- GameServer.ClientSystem.GameServer.GSBackend.UpdateAchievementCounter(Toon.GameAccount.PersistentID, type, addCounter, comparand, achiId);
- }
- catch (Exception e)
- {
- Logger.WarnException(e, "Exception on UpdateAchievementCounter(): ");
- }
- }
-
- public void UpdateSingleAchievementCounter(ulong achievementId, uint addCounter)
- {
- try
- {
- GameServer.ClientSystem.GameServer.GSBackend.UpdateSingleAchievementCounter(Toon.GameAccount.PersistentID, achievementId, addCounter);
- }
- catch (Exception e)
- {
- Logger.WarnException(e, "Exception on UpdateSingleAchievementCounter(): ");
- }
- }
-
- public void CheckQuestCriteria(int questId)
- {
- try
- {
- GameServer.ClientSystem.GameServer.GSBackend.CheckQuestCriteria(Toon.GameAccount.PersistentID, questId, World.Game.Players.Count > 1);
- }
- catch (Exception e)
- {
- Logger.WarnException(e, "Exception on CheckQuestCriteria(): ");
- }
- }
-
- public void CheckKillMonsterCriteria(ActorSno actorSno, int type)
- {
- try
- {
- ClientSystem.GameServer.GSBackend.CheckKillMonsterCriteria(Toon.GameAccount.PersistentID, (int)actorSno, type, World.Game.IsHardcore);
- }
- catch (Exception e)
- {
- Logger.WarnException(e, "Exception on CheckKillMonsterCriteria(): ");
- }
- }
-
- public void CheckLevelCap()
- {
- try
- {
- GameServer.ClientSystem.GameServer.GSBackend.CheckLevelCap(Toon.GameAccount.PersistentID);
- }
- catch (Exception e)
- {
- Logger.WarnException(e, "Exception on CheckLevelCap(): ");
- }
- }
-
- public void CheckSalvageItemCriteria(int itemId)
- {
- try
- {
- GameServer.ClientSystem.GameServer.GSBackend.CheckSalvageItemCriteria(Toon.GameAccount.PersistentID, itemId);
- }
- catch (Exception e)
- {
- Logger.WarnException(e, "Exception on CheckSalvageItemCriteria(): ");
- }
- }
-
- public void CheckConversationCriteria(int convId)
- {
- try
- {
- GameServer.ClientSystem.GameServer.GSBackend.CheckConversationCriteria(Toon.GameAccount.PersistentID, convId);
- }
- catch (Exception e)
- {
- Logger.WarnException(e, "Exception on CheckConversationCriteria(): ");
- }
- }
-
- public void CheckLevelAreaCriteria(int laId)
- {
- try
- {
- GameServer.ClientSystem.GameServer.GSBackend.CheckLevelAreaCriteria(Toon.GameAccount.PersistentID, laId);
- }
- catch (Exception e)
- {
- Logger.WarnException(e, "Exception on CheckLevelAreaCriteria(): ");
- }
- }
-
- public void ParagonLevelUp()
- {
- try
- {
- GameServer.ClientSystem.GameServer.GSBackend.ParagonLevelUp(Toon.GameAccount.PersistentID);
- }
- catch (Exception e)
- {
- Logger.WarnException(e, "Exception on ParagonLevelUp(): ");
- }
- }
-
- public void UniqueItemIdentified(ulong itemId)
- {
- try
- {
- GameServer.ClientSystem.GameServer.GSBackend.UniqueItemIdentified(Toon.GameAccount.PersistentID, itemId);
- }
- catch (Exception e)
- {
- Logger.WarnException(e, "Exception on UniqueItemIdentified(): ");
- }
- }
-
- public void SetProgress(int act, int difficulty)
- {
- if (act > 400) return;
- var dbGAcc = World.Game.GameDBSession.SessionGet(Toon.GameAccount.PersistentID);
- var progress = dbGAcc.BossProgress;
- if (progress[(act / 100)] == 0xff || progress[(act / 100)] < (byte)difficulty)
- {
- progress[(act / 100)] = (byte)difficulty;
-
- dbGAcc.BossProgress = progress;
- World.Game.GameDBSession.SessionUpdate(dbGAcc);
- }
- }
-
- public int CastingSnoPower = -1;
-
- public void StartCasting(int durationTicks, Action result, int skillsno = -1)
- {
- IsCasting = true;
- CastResult = result;
- Attributes[GameAttribute.Looping_Animation_Start_Time] = World.Game.TickCounter;
- Attributes[GameAttribute.Looping_Animation_End_Time] = World.Game.TickCounter + durationTicks;
- CastingSnoPower = skillsno;
- if (CastingSnoPower != -1)
- {
- Attributes[GameAttribute.Buff_Icon_Start_Tick0, CastingSnoPower] = World.Game.TickCounter;
- Attributes[GameAttribute.Buff_Icon_End_Tick0, CastingSnoPower] = World.Game.TickCounter + durationTicks;
- Attributes[GameAttribute.Buff_Icon_Count0, CastingSnoPower] = 1;
- Attributes[GameAttribute.Power_Buff_0_Visual_Effect_None, CastingSnoPower] = true;
-
- }
- Attributes.BroadcastChangedIfRevealed();
- }
-
- public void StopCasting()
- {
- IsCasting = false;
- Attributes[GameAttribute.Looping_Animation_Start_Time] = -1;
- Attributes[GameAttribute.Looping_Animation_End_Time] = -1;
- if (CastingSnoPower != -1)
- {
- Attributes[GameAttribute.Buff_Icon_Start_Tick0, CastingSnoPower] = -1;
- Attributes[GameAttribute.Buff_Icon_End_Tick0, CastingSnoPower] = -1;
- Attributes[GameAttribute.Buff_Icon_Count0, CastingSnoPower] = 0;
- Attributes[GameAttribute.Power_Buff_0_Visual_Effect_None, CastingSnoPower] = false;
- }
- Attributes.BroadcastChangedIfRevealed();
- }
-
- private void UpdateCastState()
- {
- if (Attributes[GameAttribute.Looping_Animation_End_Time] <= World.Game.TickCounter)
- {
- StopCasting();
- CastResult.Invoke();
- CastResult = null;
- }
- }
-
- public void ShowConfirmation(uint actorId, Action result)
- {
- ConfirmationResult = result;
-
- InGameClient.SendMessage(new ConfirmMessage()
- {
- ActorID = actorId
- });
- }
-
-#endregion
-
-#region generic properties
-
- public int ClassSNO => Toon.Gender == 0 ? Toon.HeroTable.SNOMaleActor : Toon.HeroTable.SNOFemaleActor;
-
- public int AdditionalLootItems
- {
- get
- {
- if (World.BuffManager.HasBuff(this))
- {
- return Math.Max(World.BuffManager.GetFirstBuff(this).StackCount - 3, 0);
- }
- else return 0;
- }
- }
-
- public float ModelScale =>
- Toon.Class switch
- {
- ToonClass.Barbarian => 1.2f,
- ToonClass.Crusader => 1.2f,
- ToonClass.DemonHunter => 1.35f,
- ToonClass.Monk => 1.43f,
- ToonClass.WitchDoctor => 1.1f,
- ToonClass.Wizard => 1.3f,
- _ => 1.43f
- };
-
- public int PrimaryResourceID => (int)Toon.HeroTable.PrimaryResource;
-
- public int SecondaryResourceID => (int)Toon.HeroTable.SecondaryResource;
-
- [Obsolete]
- public bool IsInTown
- {
- get
- {
- var townAreas = new List { 19947, 168314, 92945, 197101 };
- var proximity = new RectangleF(Position.X - 1f, Position.Y - 1f, 2f, 2f);
- var scenes = World.QuadTree.Query(proximity);
- if (scenes.Count == 0) return false;
-
- var scene = scenes[0];
-
- if (scenes.Count == 2) // What if it's a subscene?
- {
- if (scenes[1].ParentChunkID != 0xFFFFFFFF)
- scene = scenes[1];
- }
-
- return townAreas.Contains(scene.Specification.SNOLevelAreas[0]);
- }
- }
-
-#endregion
-
-#region experience handling
-
- //Max((Resource_Max + ((Level#NONE - 1) * Resource_Factor_Level) + Resource_Max_Bonus) * (Resource_Max_Percent_Bonus + 1), 0)
- private float GetMaxResource(int resourceId)
- {
- if (resourceId == 2) return 0;
- return (Math.Max((Attributes[GameAttribute.Resource_Max, resourceId] + ((Attributes[GameAttribute.Level] - 1) * Attributes[GameAttribute.Resource_Factor_Level, resourceId]) + Attributes[GameAttribute.Resource_Max_Bonus, resourceId]) * (Attributes[GameAttribute.Resource_Max_Percent_Bonus, resourceId] + 1), 0));
- }
-
- public static List LevelBorders = new List{
- 0, 280, 2700, 4500, 6600, 9000, 11700, 14000, 16500, 19200, 22100, /* Level 0-10 */
- 25200, 28500, 32000, 35700, 39600, 43700, 48000, 52500, 57200, 62100, /* Level 11-20 */
- 67200, 72500, 78000, 83700, 89600, 95700, 102000, 108500, 115200, 122100, /* Level 21-30 */
- 150000, 157500, 180000, 203500, 228000, 273000, 320000, 369000, 420000, 473000, /* Level 31-40 */
- 528000, 585000, 644000, 705000, 768000, 833000, 900000, 1453500, 2080000, 3180000, /* Level 41-50 */
- 4050000, 5005000, 6048000, 7980000, 10092000, 12390000, 14880000, 17019000, 20150000, 24586000, /* Level 51-60 */
- 27000000, 29400000, 31900000, 39100000, 46800000, 55000000, 63700000, 72900000, 82600000, 100000000, /* Level 61-70 */
+ HirelingData = new HirelingSavedData()
+ {
+ HirelingInfos = HirelingInfo,
+ ActiveHireling = 0x00000000,
+ AvailableHirelings = 0x00000004
+ },
+
+ TimeLastLevel = 0,
+ LearnedLore = LearnedLore,
+
+ ActiveSkills = SkillSet.ActiveSkills,
+ snoTraits = SkillSet.PassiveSkills,
+ GBIDLegendaryPowers = new int[4] { -1, -1, -1, -1 },
+
+ SavePointData = new SavePointData { snoWorld = -1, SavepointId = -1 },
+ EventFlags = 0
};
- public static List ParagonLevelBorders = new List
- {
- //7200000,8640000,10800000,11520000,12960000,14400000,15840000,17280000,18720000,20160000,21600000,23040000,24480000,25920000,27360000,
- //28800000,30240000,31680000,33120000,34560000,36000000,37440000,38880000,40320,41760000,43200000,41760000,43200000,44640000,46080000,
- //47520000,48960000,50400000,51840000,53280000,54720000,56160000,57600000,59040000,60480000,61920000,63360000,64800000,66240000,67680000,
- //69120000,70560000,72000000,73440000,76320000,77760000,79200000,80640000,82080000,83520000,84960000,86400000,87840000
- };
- public static void GeneratePLB()
- {
- long previousExp = 7200000;
- ParagonLevelBorders.Add(7200000);
- for (int i = 0; i < 59; i++)
- {
- previousExp += 1440000;
- ParagonLevelBorders.Add(previousExp);
- }
- for (int i = 0; i < 10; i++)
- {
- previousExp += 2880000;
- ParagonLevelBorders.Add(previousExp);
- }
- for (int i = 0; i < 3; i++)
- {
- previousExp += 5040000;
- ParagonLevelBorders.Add(previousExp);
- }
- previousExp += 3660000;
- ParagonLevelBorders.Add(previousExp);
- for (int i = 0; i < 75; i++)
- {
- previousExp += 1020000;
- ParagonLevelBorders.Add(previousExp);
- }
- for (int i = 0; i < 101; i++)
- {
- previousExp += 2040000;
- ParagonLevelBorders.Add(previousExp);
- }
- for (int i = 0; i < 100; i++)
- {
- previousExp += 4080000;
- ParagonLevelBorders.Add(previousExp);
- }
- for (int i = 0; i < 99; i++)
- {
- previousExp += 6120000;
- ParagonLevelBorders.Add(previousExp);
- }
- for (int i = 0; i < 51; i++)
- {
- previousExp += 8160000;
- ParagonLevelBorders.Add(previousExp);
- }
- for (int i = 0; i < 50; i++)
- {
- previousExp += 20400000;
- ParagonLevelBorders.Add(previousExp);
- }
- for (int i = 0; i < 50; i++)
- {
- previousExp += 40800000;
- ParagonLevelBorders.Add(previousExp);
- }
- for (int i = 0; i < 50; i++)
- {
- previousExp += 61200000;
- ParagonLevelBorders.Add(previousExp);
- }
- for (int i = 0; i < 50; i++)
- {
- previousExp += 81600000;
- ParagonLevelBorders.Add(previousExp);
- }
- for (int i = 0; i < 50; i++)
- {
- previousExp += 102000000;
- ParagonLevelBorders.Add(previousExp);
- }
- for (int i = 0; i < 1500; i++)
- {
- previousExp += 122400000;
- ParagonLevelBorders.Add(previousExp);
- }
- long boosterofup = 229500000;
- for (int i = 0; i < 17750; i++)
- {
- boosterofup += 102000;
- previousExp += boosterofup;
- ParagonLevelBorders.Add(previousExp);
- }
- }
- //public static List ParagonLevelBorders = ((GameBalance)DiIiS_NA.Core.MPQ.MPQStorage.Data.Assets[SNOGroup.GameBalance][252616].Data).Experience.Select(row => row.DeltaXP).ToList();
-
- public static int[] LevelUpEffects =
- {
- 85186, 85186, 85186, 85186, 85186, 85190, 85190, 85190, 85190, 85190, /* Level 1-10 */
- 85187, 85187, 85187, 85187, 85187, 85187, 85187, 85187, 85187, 85187, /* Level 11-20 */
- 85192, 85192, 85192, 85192, 85192, 85192, 85192, 85192, 85192, 85192, /* Level 21-30 */
- 85192, 85192, 85192, 85192, 85192, 85192, 85192, 85192, 85192, 85192, /* Level 31-40 */
- 85192, 85192, 85192, 85192, 85192, 85192, 85192, 85192, 85192, 85192, /* Level 41-50 */
- 85194, 85194, 85194, 85194, 85194, 85194, 85194, 85194, 85194, 85194, /* Level 51-60 */
- 85194, 85194, 85194, 85194, 85194, 85194, 85194, 85194, 85194, 85194 /* Level 61-70 */
- };
-
- public void AddRestExperience()
- {
- long exp_needed = 0;
- if (Attributes[GameAttribute.Level] == Attributes[GameAttribute.Level_Cap])
- exp_needed = ParagonLevelBorders[Attributes[GameAttribute.Alt_Level]];
- else
- exp_needed = LevelBorders[Attributes[GameAttribute.Level]];
-
- Attributes[GameAttribute.Rest_Experience_Lo] = Math.Min(Attributes[GameAttribute.Rest_Experience_Lo] + (int)(exp_needed / 10), (int)exp_needed);
- Attributes[GameAttribute.Rest_Experience_Bonus_Percent] = 0.25f;
- Attributes.BroadcastChangedIfRevealed();
- }
-
- private object _XPlock = new object();
-
- public void UpdateExp(int addedExp)
- {
- lock (_XPlock)
- {
- if (Dead) return;
- if (World.Game.IsHardcore && Attributes[GameAttribute.Level] >= 70)
- addedExp *= 5;
-
- if (Attributes[GameAttribute.Alt_Level] >= 515)
- {
- var XPcap = (91.262575239831f * Math.Pow(Attributes[GameAttribute.Alt_Level], 3)) - (44301.083380565047f * Math.Pow(Attributes[GameAttribute.Alt_Level], 2)) + (3829010.395566940308f * Attributes[GameAttribute.Alt_Level]) + 322795582.543823242188f;
- addedExp = (int)((float)(ParagonLevelBorders[Attributes[GameAttribute.Alt_Level]] / XPcap) * addedExp);
- }
-
- if (Attributes[GameAttribute.Rest_Experience_Lo] > 0)
- {
- var multipliedExp = (int)Math.Min(addedExp * Attributes[GameAttribute.Rest_Experience_Bonus_Percent], Attributes[GameAttribute.Rest_Experience_Lo]);
- addedExp += multipliedExp;
- Attributes[GameAttribute.Rest_Experience_Lo] -= multipliedExp;
- }
-
- if (Attributes[GameAttribute.Level] == Attributes[GameAttribute.Level_Cap])
- Attributes[GameAttribute.Alt_Experience_Next_Lo] -= addedExp;
- else
- Attributes[GameAttribute.Experience_Next_Lo] -= addedExp;
-
- // Levelup
- while ((Attributes[GameAttribute.Level] >= Attributes[GameAttribute.Level_Cap]) ? (Attributes[GameAttribute.Alt_Experience_Next_Lo] <= 0) : (Attributes[GameAttribute.Experience_Next_Lo] <= 0))
- {
-
- // No more levelup at Level_Cap
- if (Attributes[GameAttribute.Level] >= Attributes[GameAttribute.Level_Cap])
- {
- ParagonLevel++;
- Toon.ParagonLevelUp();
- ParagonLevelUp();
- Attributes[GameAttribute.Alt_Level]++;
- InGameClient.SendMessage(new ParagonLevel()
- {
- PlayerIndex = PlayerIndex,
- Level = ParagonLevel
- });
- Conversations.StartConversation(0x0002A777); //LevelUp Conversation
-
- Attributes[GameAttribute.Alt_Experience_Next_Lo] = Attributes[GameAttribute.Alt_Experience_Next_Lo] + (int)ParagonLevelBorders[Attributes[GameAttribute.Alt_Level]];
- // On level up, health is set to max
- Attributes[GameAttribute.Hitpoints_Cur] = Attributes[GameAttribute.Hitpoints_Max_Total];
- // set resources to max as well
- Attributes[GameAttribute.Resource_Cur, Attributes[GameAttribute.Resource_Type_Primary] - 1] = Attributes[GameAttribute.Resource_Max_Total, Attributes[GameAttribute.Resource_Type_Primary] - 1];
- Attributes[GameAttribute.Resource_Cur, Attributes[GameAttribute.Resource_Type_Secondary] - 1] = Attributes[GameAttribute.Resource_Max_Total, Attributes[GameAttribute.Resource_Type_Secondary] - 1];
-
- ExperienceNext = Attributes[GameAttribute.Alt_Experience_Next_Lo];
- Attributes.BroadcastChangedIfRevealed();
-
- PlayEffect(Effect.ParagonLevelUp, null, false);
- World.PowerManager.RunPower(this, 252038); //g_LevelUp_AA.pow 252038
- return;
- }
-
- Level++;
- Attributes[GameAttribute.Level]++;
- Toon.LevelUp();
- if ((World.Game.MonsterLevel + 1) == Attributes[GameAttribute.Level]) //if this is suitable level to update
- World.Game.UpdateLevel(Attributes[GameAttribute.Level]);
-
- InGameClient.SendMessage(new PlayerLevel()
- {
- PlayerIndex = PlayerIndex,
- Level = Level
- });
-
-
- //Test Update Monster Level
- if (PlayerIndex == 0)
- {
- InGameClient.Game.InitialMonsterLevel = Level;
- InGameClient.SendMessage(new GameSyncedDataMessage
- {
- SyncedData = new GameSyncedData
- {
- GameSyncedFlags = InGameClient.Game.IsSeasoned ? InGameClient.Game.IsHardcore ? 3 : 2 : InGameClient.Game.IsHardcore ? 1 : 0,
- Act = Math.Min(InGameClient.Game.CurrentAct, 3000), //act id
- InitialMonsterLevel = InGameClient.Game.InitialMonsterLevel, //InitialMonsterLevel
- MonsterLevel = 0x64E4425E, //MonsterLevel
- RandomWeatherSeed = InGameClient.Game.WeatherSeed, //RandomWeatherSeed
- OpenWorldMode = InGameClient.Game.CurrentAct == 3000 ? 1 : 0, //OpenWorldMode
- OpenWorldModeAct = -1, //OpenWorldModeAct
- OpenWorldModeParam = -1, //OpenWorldModeParam
- OpenWorldTransitionTime = 0x00000064, //OpenWorldTransitionTime
- OpenWorldDefaultAct = 100, //OpenWorldDefaultAct
- OpenWorldBonusAct = -1, //OpenWorldBonusAct
- SNODungeonFinderLevelArea = 0x00000001, //SNODungeonFinderLevelArea
- LootRunOpen = InGameClient.Game.GameMode == Game.Mode.Portals ? 0 : -1, //LootRunOpen //0 - Великий Портал
- OpenLootRunLevel = 1, //OpenLootRunLevel
- LootRunBossDead = 0, //LootRunBossDead
- HunterPlayerIdx = 0, //HunterPlayerIdx
- LootRunBossActive = -1, //LootRunBossActive
- TieredLootRunFailed = -1, //TieredLootRunFailed
- LootRunChallengeCompleted = -1, //LootRunChallengeCompleted
- SetDungeonActive = -1, //SetDungeonActive
- Pregame = 0, //Pregame
- PregameEnd = 0, //PregameEnd
- RoundStart = 0, //RoundStart
- RoundEnd = 0, //RoundEnd
- PVPGameOver = 0x0, //PVPGameOver
- field_v273 = 0x0,
- TeamWins = new[] { 0x0, 0x0 }, //TeamWins
- TeamScore = new[] { 0x0, 0x0 }, //TeamScore
- PVPGameResult = new[] { 0x0, 0x0 }, //PVPGameResult
- PartyGuideHeroId = 0x0, //PartyGuideHeroId //new EntityId() { High = 0, Low = (long)this.Players.Values.First().Toon.PersistentID }
- TiredRiftPaticipatingHeroID = new long[] { 0x0, 0x0, 0x0, 0x0 }, //TiredRiftPaticipatingHeroID
- }
- });
- }
- Conversations.StartConversation(0x0002A777); //LevelUp Conversation
-
- if (Attributes[GameAttribute.Level] >= Attributes[GameAttribute.Level_Cap])
- {
- Attributes[GameAttribute.Alt_Experience_Next_Lo] = (int)ParagonLevelBorders[Toon.ParagonLevel];
- Toon.ExperienceNext = (int)ParagonLevelBorders[Toon.ParagonLevel];
- }
- else
- {
- Attributes[GameAttribute.Experience_Next_Lo] += (int)LevelBorders[Attributes[GameAttribute.Level]];
- Toon.ExperienceNext = Attributes[GameAttribute.Experience_Next_Lo];
- }
-
- // 4 main attributes are incremented according to class
- Attributes[GameAttribute.Strength] = Strength;
- Attributes[GameAttribute.Intelligence] = Intelligence;
- Attributes[GameAttribute.Vitality] = Vitality;
- Attributes[GameAttribute.Dexterity] = Dexterity;
-
- // On level up, health is set to max
- Attributes[GameAttribute.Hitpoints_Cur] = Attributes[GameAttribute.Hitpoints_Max_Total];
-
- // force GameAttributeMap to re-calc resources for the active resource types
- Attributes[GameAttribute.Resource_Max, Attributes[GameAttribute.Resource_Type_Primary] - 1] = Attributes[GameAttribute.Resource_Max, Attributes[GameAttribute.Resource_Type_Primary] - 1];
- Attributes[GameAttribute.Resource_Max, Attributes[GameAttribute.Resource_Type_Secondary] - 1] = Attributes[GameAttribute.Resource_Max, Attributes[GameAttribute.Resource_Type_Secondary] - 1];
-
- // set resources to max as well
- Attributes[GameAttribute.Resource_Cur, Attributes[GameAttribute.Resource_Type_Primary] - 1] = Attributes[GameAttribute.Resource_Max_Total, Attributes[GameAttribute.Resource_Type_Primary] - 1];
- Attributes[GameAttribute.Resource_Cur, Attributes[GameAttribute.Resource_Type_Secondary] - 1] = Attributes[GameAttribute.Resource_Max_Total, Attributes[GameAttribute.Resource_Type_Secondary] - 1];
-
- Attributes[GameAttribute.Hitpoints_Factor_Vitality] = 10f + Math.Max(Level - 35, 0);
-
- Attributes.BroadcastChangedIfRevealed();
-
- PlayEffect(Effect.LevelUp, null, false);
- World.PowerManager.RunPower(this, 85954); //g_LevelUp.pow 85954
-
-
- switch (Level)
- {
- case 10:
- GrantAchievement(World.Game.IsHardcore ? (ulong)74987243307034 : (ulong)74987243307105);
- break;
- case 20:
- GrantAchievement(World.Game.IsHardcore ? (ulong)74987243307035 : (ulong)74987243307104);
- break;
- case 30:
- GrantAchievement(World.Game.IsHardcore ? (ulong)74987243307036 : (ulong)74987243307103);
- break;
- case 40:
- GrantAchievement(World.Game.IsHardcore ? (ulong)74987243307037 : (ulong)74987243307102);
- break;
- case 50:
- GrantAchievement(World.Game.IsHardcore ? (ulong)74987243307038 : (ulong)74987243307101);
- if (World.Game.IsSeasoned)
- GrantCriteria(74987250038929);
- break;
- case 60:
- if (World.Game.IsHardcore)
- {
- GrantAchievement(74987243307039);
- if (!Toon.GameAccount.Flags.HasFlag(GameAccount.GameAccountFlags.HardcoreTormentUnlocked))
- Toon.GameAccount.Flags |= GameAccount.GameAccountFlags.HardcoreTormentUnlocked;
- }
- else
- {
- GrantAchievement(74987243307100);
- if (!Toon.GameAccount.Flags.HasFlag(GameAccount.GameAccountFlags.TormentUnlocked))
- Toon.GameAccount.Flags |= GameAccount.GameAccountFlags.TormentUnlocked;
- }
- CheckLevelCap();
- break;
- case 70:
- GrantCriteria(74987254853541);
- break;
- default:
- break;
- }
- }
-
- ExperienceNext = (Attributes[GameAttribute.Level] == 70 ? Attributes[GameAttribute.Alt_Experience_Next_Lo] : Attributes[GameAttribute.Experience_Next_Lo]);
- Attributes.BroadcastChangedIfRevealed();
- Toon.GameAccount.NotifyUpdate();
-
- //this.Attributes.SendMessage(this.InGameClient, this.DynamicID); kills the player atm
- }
- }
-
- #endregion
-
- #region gold, heath-glob collection
- public void VacuumPickupHealthOrb(float radius = -1)
- {
- if (Math.Abs(radius - (-1)) < 0.001)
- radius = Attributes[GameAttribute.Gold_PickUp_Radius];
- var itemList = GetItemsInRange(radius);
- foreach (Item item in itemList)
- {
- if (Item.IsHealthGlobe(item.ItemType))
- {
- var playersAffected = GetPlayersInRange(26f);
- foreach (Player player in playersAffected)
- {
- foreach (Player targetAffected in playersAffected)
- {
- player.InGameClient.SendMessage(new PlayEffectMessage()
- {
- ActorId = targetAffected.DynamicID(player),
- Effect = Effect.HealthOrbPickup
- });
- }
-
- //every summon and mercenary owned by you must broadcast their green text to you /H_DANILO
- player.AddPercentageHP((int)item.Attributes[GameAttribute.Health_Globe_Bonus_Health]);
- //passive abilities
- if (player.SkillSet.HasPassive(208478)) //wizard PowerHungry
- player.World.BuffManager.AddBuff(this, this, new HungryBuff());
- if (player.SkillSet.HasPassive(208594)) //wd GruesomeFeast
- {
- player.GeneratePrimaryResource(player.Attributes[GameAttribute.Resource_Max_Total, (int)player.Toon.HeroTable.PrimaryResource + 1] * 0.1f);
- player.World.BuffManager.AddBuff(player, player, new GruesomeFeastIntBuff());
- }
- if (player.SkillSet.HasPassive(205205)) //barbarian PoundOfFlesh
- player.AddPercentageHP((int)(item.Attributes[GameAttribute.Health_Globe_Bonus_Health] * 0.5f));
- if (player.SkillSet.HasPassive(155714)) //dh Vengeance
- {
- player.GeneratePrimaryResource(20f);
- player.GenerateSecondaryResource(2f);
- }
- }
- item.Destroy();
- }
- }
- }
-
- public void VacuumPickup()
- {
-
- var itemList = GetItemsInRange(Attributes[GameAttribute.Gold_PickUp_Radius]);
- foreach (Item item in itemList)
- {
- if (Item.IsGold(item.ItemType))
- {
- if (!GroundItems.ContainsKey(item.GlobalID)) continue;
-
- InGameClient.SendMessage(new FloatingAmountMessage()
- {
- Place = new WorldPlace()
- {
- Position = Position,
- WorldID = World.DynamicID(this),
- },
-
- Amount = item.Attributes[GameAttribute.Gold],
- Type = FloatingAmountMessage.FloatType.Gold,
- });
- InGameClient.SendMessage(new PlayEffectMessage()
- {
- ActorId = DynamicID(this),
- Effect = Effect.GoldPickup,
- PlayerId = 0
- });
- PlayEffect(Effect.Sound, 36726);
- Inventory.PickUpGold(item);
- GroundItems.Remove(item.GlobalID);
- item.Destroy();
- }
-
- else if (Item.IsBloodShard(item.ItemType) || item.ItemDefinition.Name == "HoradricRelic")
- {
- if (!GroundItems.ContainsKey(item.GlobalID)) continue;
-
- InGameClient.SendMessage(new FloatingAmountMessage()
- {
- Place = new WorldPlace()
- {
- Position = Position,
- WorldID = World.DynamicID(this),
- },
-
- Amount = item.Attributes[GameAttribute.ItemStackQuantityLo],
- Type = FloatingAmountMessage.FloatType.BloodStone,
- });
-
- Inventory.PickUpBloodShard(item);
- GroundItems.Remove(item.GlobalID);
- item.Destroy();
- }
-
- else if (item.ItemDefinition.Name == "Platinum")
- {
-
- InGameClient.SendMessage(new FloatingAmountMessage()
- {
- Place = new WorldPlace()
- {
- Position = Position,
- WorldID = World.DynamicID(this),
- },
-
- Amount = item.Attributes[GameAttribute.ItemStackQuantityLo],
- Type = FloatingAmountMessage.FloatType.Platinum,
- });
- PlayEffect(Effect.Sound, 433266);
-
- Inventory.PickUpPlatinum(item);
- GroundItems.Remove(item.GlobalID);
- item.Destroy();
- }
-
- else if (item.ItemDefinition.Name == "Crafting_Looted_Reagent_01")
- {
- /*
- this.InGameClient.SendMessage(new FloatingAmountMessage()
- {
- Place = new WorldPlace()
- {
- Position = this.Position,
- WorldID = this.World.DynamicID(this),
- },
-
- Amount = item.Attributes[GameAttribute.ItemStackQuantityLo],
- Type = (FloatingAmountMessage.FloatType)22,
- });
- //*/
- Toon.GameAccount.CraftItem4++;
- Inventory.UpdateCurrencies();
- item.Destroy();
- }
-
- else if (Item.IsHealthGlobe(item.ItemType))
- {
- var playersAffected = GetPlayersInRange(26f);
- foreach (Player player in playersAffected)
- {
- foreach (Player targetAffected in playersAffected)
- {
- player.InGameClient.SendMessage(new PlayEffectMessage()
- {
- ActorId = targetAffected.DynamicID(player),
- Effect = Effect.HealthOrbPickup
- });
- }
-
- //every summon and mercenary owned by you must broadcast their green text to you /H_DANILO
- player.AddPercentageHP((int)item.Attributes[GameAttribute.Health_Globe_Bonus_Health]);
- //passive abilities
- if (player.SkillSet.HasPassive(208478)) //wizard PowerHungry
- player.World.BuffManager.AddBuff(this, this, new HungryBuff());
- if (player.SkillSet.HasPassive(208594)) //wd GruesomeFeast
- {
- player.GeneratePrimaryResource(player.Attributes[GameAttribute.Resource_Max_Total, (int)player.Toon.HeroTable.PrimaryResource + 1] * 0.1f);
- player.World.BuffManager.AddBuff(player, player, new GruesomeFeastIntBuff());
- }
- if (player.SkillSet.HasPassive(205205)) //barbarian PoundOfFlesh
- player.AddPercentageHP((int)(item.Attributes[GameAttribute.Health_Globe_Bonus_Health] * 0.5f));
- if (player.SkillSet.HasPassive(155714)) //dh Vengeance
- {
- player.GeneratePrimaryResource(20f);
- player.GenerateSecondaryResource(2f);
- }
- }
- item.Destroy();
- }
-
- else if (item.ItemDefinition.Name == "ArcaneGlobe" && Toon.Class == ToonClass.Wizard)
- {
- GeneratePrimaryResource(50f);
- item.Destroy();
- }
-
- else if (item.ItemDefinition.Name == "p1_normal_rifts_Orb" || item.ItemDefinition.Name == "p1_tiered_rifts_Orb")
- {
- if (InGameClient.Game.ActiveNephalemTimer && InGameClient.Game.ActiveNephalemKilledMobs == false)
- {
- InGameClient.Game.ActiveNephalemProgress += 15f;
- foreach (var plr in InGameClient.Game.Players.Values)
- {
- plr.InGameClient.SendMessage(new FloatDataMessage(Opcodes.DunggeonFinderProgressGlyphPickUp)
- {
- Field0 = InGameClient.Game.ActiveNephalemProgress
- });
-
- plr.InGameClient.SendMessage(new SimpleMessage(Opcodes.KillCounterRefresh)
- {
-
- });
- plr.InGameClient.SendMessage(new FloatDataMessage(Opcodes.DungeonFinderProgressMessage)
- {
- Field0 = InGameClient.Game.ActiveNephalemProgress
- });
- }
- if (InGameClient.Game.ActiveNephalemProgress > 650)
- {
- InGameClient.Game.ActiveNephalemKilledMobs = true;
- foreach (var plr in InGameClient.Game.Players.Values)
- {
- if (InGameClient.Game.NephalemGreater)
- {
- plr.InGameClient.SendMessage(new QuestCounterMessage()
- {
- snoQuest = 0x00052654,
- snoLevelArea = 0x000466E2,
- StepID = 13,
- TaskIndex = 0,
- Checked = 1,
- Counter = 1
- });
- plr.InGameClient.SendMessage(new QuestUpdateMessage()
- {
- snoQuest = 0x00052654,
- snoLevelArea = 0x000466E2,
- StepID = 16,
- DisplayButton = true,
- Failed = false
- });
-
-
- }
- else
- {
- plr.InGameClient.SendMessage(new QuestCounterMessage()
- {
- snoQuest = 0x00052654,
- snoLevelArea = 0x000466E2,
- StepID = 1,
- TaskIndex = 0,
- Checked = 1,
- Counter = 1
- });
- plr.InGameClient.SendMessage(new QuestUpdateMessage()
- {
- snoQuest = 0x00052654,
- snoLevelArea = 0x000466E2,
- StepID = 3,
- DisplayButton = true,
- Failed = false
- });
- }
-
-
- plr.InGameClient.SendMessage(new PlayMusicMessage(Opcodes.PlayMusicMessage)
- {
- SNO = 0x0005BBD8
- });
-
- plr.InGameClient.SendMessage(new DisplayGameTextMessage(Opcodes.DisplayGameChatTextMessage) { Message = "Messages:LR_BossSpawned" });
- plr.InGameClient.SendMessage(new DisplayGameTextMessage(Opcodes.DisplayGameTextMessage) { Message = "Messages:LR_BossSpawned" });
-
- }
- StartConversation(World, 366542);
- SpawnNephalemBoss(World);
- //358489
- }
- }
- item.Destroy();
-
- }
-
- else if (item.ItemDefinition.Name == "PowerGlobe_v2_x1_NoFlippy")
- {
- World.BuffManager.AddBuff(this, this, new NephalemValorBuff());
- item.Destroy();
- }
-
- else if (Item.IsPotion(item.ItemType))
- {
- if ((!GroundItems.ContainsKey(item.GlobalID) && World.Game.Players.Count > 1) || !Inventory.HasInventorySpace(item)) continue;
- Inventory.PickUp(item);
- }
- }
-
- //
- foreach (var skill in SkillSet.ActiveSkills)
- {
- if (skill.snoSkill == 460757 && skill.snoRune == 3)
- {
- //Play Aura - 472217
- //this.PlayEffectGroup(472217);
- var Fleshes = GetActorsInRange(15f + (Attributes[GameAttribute.Gold_PickUp_Radius] * 0.5f));//454066
- foreach (var flesh in Fleshes)
- {
- InGameClient.SendMessage(new EffectGroupACDToACDMessage()
- {
- EffectSNOId = 470480,
- TargetID = DynamicID(this),
- ActorID = flesh.DynamicID(this)
- });
- flesh.PlayEffectGroup(470482);
- Attributes[GameAttribute.Resource_Cur, (int)Toon.HeroTable.PrimaryResource] += 11f;
- Attributes.BroadcastChangedIfRevealed();
- flesh.Destroy();
- }
- }
- }
- }
-
- public Actor SpawnNephalemBoss(World world)
- {
- var Boss = world.SpawnMonster(ActorSnoExtensions.nephalemPortalBosses[RandomHelper.Next(0, ActorSnoExtensions.nephalemPortalBosses.Length - 1)], Position);
- Boss.Attributes[GameAttribute.Bounty_Objective] = true;
- Boss.Attributes[GameAttribute.Is_Loot_Run_Boss] = true;
- Boss.Attributes.BroadcastChangedIfRevealed();
-
-
- foreach (var plr in world.Players.Values)
- plr.InGameClient.SendMessage(new WorldSyncedDataMessage()
- {
- WorldID = world.GlobalID,
- SyncedData = new WorldSyncedData()
- {
- SnoWeatherOverride = 362462,
- WeatherIntensityOverride = 0,
- WeatherIntensityOverrideEnd = 0
- }
- });
-
-
- return Boss;
- }
-
- public bool StartConversation(World world, int conversationId)
- {
- foreach (var plr in world.Players)
- plr.Value.Conversations.StartConversation(conversationId);
- return true;
- }
-
- public void AddPercentageHP(int percentage, bool GuidingLight = false)
- {
- float quantity = (percentage * Attributes[GameAttribute.Hitpoints_Max_Total]) / 100;
- AddHP(quantity, GuidingLight);
- }
-
- public void AddPercentageHP(float percentage, bool GuidingLight = false)
- {
- float quantity = (percentage * Attributes[GameAttribute.Hitpoints_Max_Total]) / 100;
- AddHP(quantity, GuidingLight);
- }
-
- public override void AddHP(float quantity, bool guidingLight = false)
- {
- if (Dead) return;
- if (quantity == 0) return;
- if (quantity > 0)
- {
- if (Attributes[GameAttribute.Hitpoints_Cur] < Attributes[GameAttribute.Hitpoints_Max_Total])
- {
- if (Toon.Class == ToonClass.Barbarian)
- if (SkillSet.HasPassive(205217))
- quantity += 0.01f * Attributes[GameAttribute.Health_Globe_Bonus_Health];
-
- if (guidingLight) //Monk -> Guiding Light
- {
- float missingHP = (Attributes[GameAttribute.Hitpoints_Max_Total] - Attributes[GameAttribute.Hitpoints_Cur]) / Attributes[GameAttribute.Hitpoints_Max_Total];
- if (missingHP > 0.05f)
- if (!World.BuffManager.HasBuff(this))
- World.BuffManager.AddBuff(this, this, new GuidingLightBuff(Math.Min(missingHP, 0.3f), TickTimer.WaitSeconds(World.Game, 10.0f)));
- }
-
- Attributes[GameAttribute.Hitpoints_Cur] = Math.Min(
- Attributes[GameAttribute.Hitpoints_Cur] + quantity,
- Attributes[GameAttribute.Hitpoints_Max_Total]);
-
- Attributes.BroadcastChangedIfRevealed();
- InGameClient.SendMessage(new FloatingNumberMessage
- {
- ActorID = DynamicID(this),
- Number = quantity,
- Type = FloatingNumberMessage.FloatType.Green
- });
- }
- }
- else
- {
- Attributes[GameAttribute.Hitpoints_Cur] = Math.Max(
- Attributes[GameAttribute.Hitpoints_Cur] + quantity,
- 0);
-
- Attributes.BroadcastChangedIfRevealed();
- }
- }
-
- //only for WD passive
- public void RestoreMana(float quantity, int secs)
- {
- Attributes[GameAttribute.Resource_Regen_Per_Second, 0] += quantity / secs;
- System.Threading.Tasks.Task.Delay(1000 * secs).ContinueWith(t =>
- {
- Attributes[GameAttribute.Resource_Regen_Per_Second, 0] -= quantity / secs;
- });
- }
-
-#endregion
-
-#region Resource Generate/Use
-
- int _DisciplineSpent = 0;
- int _HatredSpent = 0;
- int _WrathSpent = 0;
-
- public void GeneratePrimaryResource(float amount)
- {
- if (Toon.Class == ToonClass.Barbarian)
- if (World.BuffManager.HasBuff(this))
- World.BuffManager.GetFirstBuff(this).GainedFury += amount;
-
- if (Toon.Class == ToonClass.Monk)
- if (World.BuffManager.HasBuff(this)) //Monk -> The Guardian's Path 2H
- amount *= 1.35f;
-
- _ModifyResourceAttribute(PrimaryResourceID, amount);
- }
-
- public void UsePrimaryResource(float amount, bool tick = false)
- {
- amount = Math.Max((amount - Attributes[GameAttribute.Resource_Cost_Reduction_Amount]) * (1f - Attributes[GameAttribute.Resource_Cost_Reduction_Percent_Total, (int)Toon.HeroTable.PrimaryResource + 1]), 0);
- amount = amount * (1f - DecreaseUseResourcePercent);
- if (Toon.Class == ToonClass.Crusader)
- {
- _WrathSpent += (int)amount;
- if (!tick && SkillSet.HasPassive(310775)) //Wrathful passive
- AddHP(_WrathSpent * 15f * Attributes[GameAttribute.Level]);
-
- //Laws of Hope -> Faith's reward
- if (!tick && World.BuffManager.HasBuff(this))
- if (World.BuffManager.GetFirstBuff(this).HealPerWrath)
- AddHP(_WrathSpent * 15f * Attributes[GameAttribute.Level]);
-
- if (_WrathSpent >= 20) //Akarat Champion -> Fire Starter
- if (!tick && World.BuffManager.HasBuff(this))
- World.BuffManager.GetFirstBuff(this).wrathBlast = true;
- }
-
- if (Toon.Class == ToonClass.DemonHunter)
- {
- _HatredSpent += (int)amount;
-
- if (_HatredSpent >= 150 && _DisciplineSpent >= 50)
- GrantAchievement(74987243307068);
-
- AddTimedAction(6f, new Action((q) => _HatredSpent -= (int)amount));
- }
-
- if (Toon.Class == ToonClass.Barbarian)
- {
- if (SkillSet.HasPassive(105217) && !tick) //Bloodthirst (Burb)
- AddHP(amount * 1.93f * Attributes[GameAttribute.Level]);
-
- if (!tick && World.BuffManager.HasBuff(this))
- if (Attributes[GameAttribute.Rune_E, 79528] > 0) //IgnorePain
- AddHP(amount * 13.76f * Attributes[GameAttribute.Level]);
- }
-
- if (Toon.Class == ToonClass.Wizard)
- {
- if (World.BuffManager.HasBuff(this)) //Power Hungry
- {
- amount = 0f;
- World.BuffManager.RemoveStackFromBuff(this, World.BuffManager.GetFirstBuff(this));
- }
- }
-
- if (Toon.Class == ToonClass.Monk)
- {
- if (SkillSet.HasPassive(209250)) //Transcendence (Monk)
- AddHP(amount * (50f + (Attributes[GameAttribute.Health_Globe_Bonus_Health] * 0.004f)));
- }
-
- if (SkillSet.HasPassive(208628)) //PierceTheVeil (WD)
- amount *= 1.3f;
- if (SkillSet.HasPassive(208568)) //BloodRitual (WD)
- {
- amount *= 0.9f;
- AddHP(amount * -0.1f);
- }
-
- if (SkillSet.HasPassive(205398) && Attributes[GameAttribute.Hitpoints_Cur] < (Attributes[GameAttribute.Hitpoints_Max_Total] * 0.35f)) //Relentless (Barbarian)
- amount *= 0.25f;
- _ModifyResourceAttribute(PrimaryResourceID, -amount);
- }
-
- public void GenerateSecondaryResource(float amount)
- {
- _ModifyResourceAttribute(SecondaryResourceID, amount);
- }
-
- public void UseSecondaryResource(float amount)
- {
- amount = Math.Max((amount - Attributes[GameAttribute.Resource_Cost_Reduction_Amount]) * (1f - Attributes[GameAttribute.Resource_Cost_Reduction_Percent_Total, (int)Toon.HeroTable.SecondaryResource]), 0);
-
- if (SkillSet.HasPassive(155722)) //dh - Perfectionist
- amount *= 0.9f;
-
- if (Toon.Class == ToonClass.DemonHunter)
- {
- _DisciplineSpent += (int)amount;
-
- if (_HatredSpent >= 150 && _DisciplineSpent >= 50)
- GrantAchievement(74987243307068);
-
- AddTimedAction(6f, new Action((q) => _DisciplineSpent -= (int)amount));
- }
-
- _ModifyResourceAttribute(SecondaryResourceID, -amount);
- }
-
- private void _ModifyResourceAttribute(int resourceID, float amount)
- {
- if (resourceID == -1 || amount == 0) return;
- float current = Attributes[GameAttribute.Resource_Cur, resourceID];
- if (amount > 0f)
- {
- Attributes[GameAttribute.Resource_Cur, resourceID] = Math.Min(
- Attributes[GameAttribute.Resource_Cur, resourceID] + amount,
- Attributes[GameAttribute.Resource_Max_Total, resourceID]);
- }
- else
- {
- Attributes[GameAttribute.Resource_Cur, resourceID] = Math.Max(
- Attributes[GameAttribute.Resource_Cur, resourceID] + amount,
- 0f);
- }
-
- if (current == Attributes[GameAttribute.Resource_Cur, resourceID]) return;
-
- Attributes.BroadcastChangedIfRevealed();
- }
-
-
- int _fullFuryFirstTick = 0;
- int _ArmorFirstTick = 0;
-
- private void _UpdateResources()
- {
- // will crash client when loading if you try to update resources too early
- if (World == null) return;
-
- if (InGameClient.Game.Paused) return;
-
- if (!(InGameClient.Game.TickCounter % 30 == 0)) return;
-
- if (InGameClient.Game.TickCounter % 60 == 0)
- LastSecondCasts = 0;
-
- if (Toon.Class == ToonClass.Barbarian)
- {
- if (Attributes[GameAttribute.Resource_Cur, 2] < Attributes[GameAttribute.Resource_Max_Total, 2])
- _fullFuryFirstTick = InGameClient.Game.TickCounter;
-
- if ((InGameClient.Game.TickCounter - _fullFuryFirstTick) >= 18000)
- GrantAchievement(74987243307047);
- }
-
- if (Toon.Class == ToonClass.Wizard)
- {
- if (!World.BuffManager.HasBuff(this) &&
- !World.BuffManager.HasBuff(this) &&
- !World.BuffManager.HasBuff(this))
- _ArmorFirstTick = InGameClient.Game.TickCounter;
-
- if ((InGameClient.Game.TickCounter - _ArmorFirstTick) >= 72000)
- GrantAchievement(74987243307588);
- }
-
- // 1 tick = 1/60s, so multiply ticks in seconds against resource regen per-second to get the amount to update
- float tickSeconds = 1f / 60f * (InGameClient.Game.TickCounter - _lastResourceUpdateTick);
- _lastResourceUpdateTick = InGameClient.Game.TickCounter;
-
- GeneratePrimaryResource(Math.Max(tickSeconds * Attributes[GameAttribute.Resource_Regen_Total, Attributes[GameAttribute.Resource_Type_Primary] - 1], 0));
- GenerateSecondaryResource(Math.Max(tickSeconds * Attributes[GameAttribute.Resource_Regen_Total, Attributes[GameAttribute.Resource_Type_Secondary] - 1], 0));
-
- float totalHPregen = //(this.Attributes[GameAttribute.Hitpoints_Regen_Per_Second] +
- Attributes[GameAttribute.Hitpoints_Regen_Per_Second_Bonus]//)
- * (1 + Attributes[GameAttribute.Hitpoints_Regen_Bonus_Percent]);
- if (!Dead && !World.Game.PvP) AddHP(Math.Max(tickSeconds * totalHPregen, 0));
-
- if (Toon.Class == ToonClass.Barbarian)
- if (SkillSet.HasPassive(205300)) //barbarian fury
- GeneratePrimaryResource(tickSeconds * 1.80f);
- else
- UsePrimaryResource(tickSeconds * 0.90f, true);
- }
-
-#endregion
-
-#region lore
-
- ///
- /// Checks if player has lore
- ///
- ///
- ///
- public bool HasLore(int loreSNOId)
- {
- return LearnedLore.m_snoLoreLearned.Contains(loreSNOId);
- }
-
- ///
- /// Plays lore to player
- ///
- ///
- /// if false, lore will have new lore button
- public void PlayLore(int loreSNOId, bool immediately)
- {
- // play lore to player
- InGameClient.SendMessage(new LoreMessage
- {
- LoreSNOId = loreSNOId
- });
- if (!HasLore(loreSNOId))
- {
- AddLore(loreSNOId);
- if (MPQStorage.Data.Assets[SNOGroup.Lore].ContainsKey(loreSNOId))
- {
- CheckConversationCriteria((MPQStorage.Data.Assets[SNOGroup.Lore][loreSNOId].Data as DiIiS_NA.Core.MPQ.FileFormats.Lore).SNOConversation);
- }
- }
- }
-
- ///
- /// Adds lore to player's state
- ///
- ///
- public void AddLore(int loreSNOId)
- {
- if (LearnedLore.Count < LearnedLore.m_snoLoreLearned.Length)
- {
- LearnedLore.m_snoLoreLearned[LearnedLore.Count] = loreSNOId;
- LearnedLore.Count++; // Count
- UpdateHeroState();
- Logger.Trace("Learning lore #{0}", loreSNOId);
- var dbToon = Toon.DBToon;
- dbToon.Lore = SerializeBytes(LearnedLore.m_snoLoreLearned.Take(LearnedLore.Count).ToList());
- World.Game.GameDBSession.SessionUpdate(dbToon);
- }
- }
-
-#endregion
-
-#region StoneOfRecall
-
- public void EnableStoneOfRecall()
- {
- Attributes[GameAttribute.Skill, 0x0002EC66] = 1;
- Attributes.SendChangedMessage(InGameClient);
- }
-
- public void DisableStoneOfRecall()
- {
- Attributes[GameAttribute.Skill, 0x0002EC66] = 0;
- Attributes.SendChangedMessage(InGameClient);
- }
-
-#endregion
-
-#region Minions and Hirelings handling
-
- public void AddFollower(Actor source)
- {
- //Rangged Power - 30599
- if (source == null) return;
-
- var minion = new Minion(World, source.SNO, this, source.Tags, true);
- minion.SetBrain(new MinionBrain(minion));
- minion.Brain.DeActivate();
- minion.WalkSpeed *= 4;
- minion.Position = Position;
- minion.Attributes[GameAttribute.TeamID] = Attributes[GameAttribute.TeamID];
- minion.Attributes[GameAttribute.Untargetable] = true;
- minion.Attributes[GameAttribute.No_Damage] = true;
- minion.Attributes[GameAttribute.Invulnerable] = true;
- minion.Attributes[GameAttribute.TeamID] = 2;
- minion.Attributes[GameAttribute.NPC_Is_Escorting] = true;
- minion.Attributes[GameAttribute.Pet_Creator] = 1;
- minion.Attributes[GameAttribute.Pet_Owner] = 1;
- minion.Attributes[GameAttribute.Pet_Type] = 25;
-
- //*/
- minion.Attributes[GameAttribute.Effect_Owner_ANN] = (int)DynamicID(this);
- minion.EnterWorld(minion.Position);
- (minion as Minion).Brain.Activate();
-
- source.Hidden = true;
- source.SetVisible(false);
-
- minion.SetVisible(true);
- minion.Hidden = false;
-
- if (minion.SNO == ActorSno._leah) // (4580) Act I Leah
- {
- (minion.Brain as MinionBrain).PresetPowers.Clear();
- (minion.Brain as MinionBrain).AddPresetPower(30599);
- }
-
- if ((Followers.Count >= 6 && ActiveHireling != null) || (Followers.Count >= 7))
- {
- if (Toon.Class == ToonClass.WitchDoctor)
- {
- GrantAchievement(74987243307563);
- }
- }
- }
-
- public bool HaveFollower(ActorSno sno)
- {
- return Followers.ContainsValue(sno);
- }
-
- public void DestroyFollower(ActorSno sno)
- {
- if (Followers.ContainsValue(sno))
- {
- var dynId = Followers.Where(x => x.Value == sno).First().Key;
- var actor = World.GetActorByGlobalId(dynId);
- if (actor != null)
- actor.Destroy();
- Followers.Remove(dynId);
- }
- }
-
- public void SetFollowerIndex(ActorSno sno)
- {
- if (!HaveFollower(sno))
- {
- for (int i = 1; i < 8; i++)
- if (!_followerIndexes.ContainsKey(i))
- {
- _followerIndexes.Add(i, sno);
- return;
- }
- }
- }
-
- public void FreeFollowerIndex(ActorSno sno)
- {
- if (!HaveFollower(sno))
- {
- _followerIndexes.Remove(FindFollowerIndex(sno));
- }
- }
-
- private Dictionary _followerIndexes = new Dictionary();
-
- public int FindFollowerIndex(ActorSno sno)
- {
- if (HaveFollower(sno))
- {
- return _followerIndexes.Where(i => i.Value == sno).FirstOrDefault().Key;
- }
- else return 0;
- }
-
- public int CountFollowers(ActorSno sno)
- {
- return Followers.Values.Where(f => f == sno).Count();
- }
-
- public int CountAllFollowers()
- {
- return Followers.Count();
- }
-
- public void DestroyFollowerById(uint dynId)
- {
- if (Followers.ContainsKey(dynId))
- {
- var actor = World.GetActorByGlobalId(dynId);
- Followers.Remove(dynId);
- if (actor != null)
- {
- FreeFollowerIndex(actor.SNO);
- actor.Destroy();
- }
- }
- }
-
- public void DestroyFollowersBySnoId(ActorSno sno)
- {
- var fol_list = Followers.Where(f => f.Value == sno).Select(f => f.Key).ToList();
- foreach (var fol in fol_list)
- DestroyFollowerById(fol);
- }
-
-#endregion
-
- public void Heal()
- {
- Attributes[GameAttribute.Hitpoints_Cur] = Attributes[GameAttribute.Hitpoints_Max_Total];
- Attributes[GameAttribute.Hitpoints_Total_From_Level] = Attributes[GameAttribute.Hitpoints_Max_Total];
- Attributes.BroadcastChangedIfRevealed();
- }
- }
-}
+ }
+
+ public SavePointData SavePointData { get; set; }
+
+ public LearnedLore LearnedLore = new()
+ {
+ Count = 0x00000000,
+ m_snoLoreLearned = new int[512]
+ {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
+ }
+ };
+
+ public void SaveStats() //Save 6 primary stats into DB for showing on hero screen
+ {
+ //Logger.Debug("SaveStats(): Strength {0}", this.Inventory.GetItemBonus(GameAttribute.Strength_Item).ToString("F0"));
+ var damageFromWeapon =
+ (Inventory.GetItemBonus(GameAttribute.Damage_Weapon_Min_Total, 0) +
+ Inventory.GetItemBonus(GameAttribute.Damage_Weapon_Delta_Total, 0)) * (1f + PrimaryAttribute / 100f);
+
+ var totalDamage =
+ (damageFromWeapon
+ + damageFromWeapon * Inventory.GetItemBonus(GameAttribute.Weapon_Crit_Chance) *
+ (1.5f + Inventory.GetItemBonus(GameAttribute.Crit_Damage_Percent)))
+ * Inventory.GetItemBonus(GameAttribute.Attacks_Per_Second_Total);
+
+ var serialized = "";
+ serialized += Inventory.GetItemBonus(GameAttribute.Strength_Item).ToString("F0");
+ serialized += ";";
+ serialized += Inventory.GetItemBonus(GameAttribute.Dexterity_Item).ToString("F0");
+ serialized += ";";
+ serialized += Inventory.GetItemBonus(GameAttribute.Intelligence_Item).ToString("F0");
+ serialized += ";";
+ serialized += Inventory.GetItemBonus(GameAttribute.Vitality_Item).ToString("F0");
+ serialized += ";";
+ serialized += Inventory.GetItemBonus(GameAttribute.Armor_Item).ToString("F0");
+ serialized += ";";
+ serialized += totalDamage.ToString("F0");
+ var dbStats = Toon.DBToon;
+ dbStats.Stats = serialized;
+ World.Game.GameDBSession.SessionUpdate(dbStats);
+ }
+
+ public List QuestRewardHistory
+ {
+ get
+ {
+ var result = new List();
+ var quests = InGameClient.Game.QuestManager.Quests.Where(q => q.Value.Completed).ToList();
+ foreach (var quest in quests)
+ {
+ InGameClient.SendMessage(new QuestUpdateMessage()
+ {
+ snoQuest = quest.Key,
+ snoLevelArea = -1,
+ StepID = quest.Value.Steps.Last().Key,
+ DisplayButton = false,
+ Failed = false
+ });
+
+ result.Add(new PlayerQuestRewardHistoryEntry()
+ {
+ snoQuest = quest.Key,
+ Field1 = 0,
+ Field2 = (PlayerQuestRewardHistoryEntry.Difficulty)InGameClient.Game.Difficulty
+ });
+ }
+
+ return result;
+ }
+ }
+
+ private HirelingInfo[] _hirelingInfo = null;
+
+ public HirelingInfo[] HirelingInfo
+ {
+ get
+ {
+ if (_hirelingInfo == null)
+ {
+ _hirelingInfo = new HirelingInfo[4];
+ for (var i = 0; i < 4; i++)
+ _hirelingInfo[i] = GetHirelingInfo(i);
+ }
+
+ return _hirelingInfo;
+ }
+ set => _hirelingInfo = value;
+ }
+
+ #endregion
+
+ #region cooked messages
+
+ public void StopMoving()
+ {
+ World.BroadcastIfRevealed(plr => new ACDTranslateNormalMessage
+ {
+ ActorId = DynamicID(plr),
+ Position = Position,
+ SnapFacing = false,
+ MovementSpeed = 0,
+ AnimationTag = -1
+ }, this);
+ }
+
+ public void CheckBonusSets()
+ {
+ var sets = World.Game.GameDBSession
+ .SessionQueryWhere(dbi => dbi.DBAccount.Id == Toon.GameAccount.AccountId).ToList();
+ foreach (var bonusSet in sets)
+ {
+ if (World.Game.IsHardcore)
+ {
+ if (bonusSet.ClaimedHardcore) continue;
+ }
+ else
+ {
+ if (bonusSet.Claimed) continue;
+ }
+
+ //if (!BonusSetsList.CollectionEditions.ContainsKey(bonusSet.SetId)) continue;
+
+ if (bonusSet.SetId == 6 && World.Game.IsHardcore) continue;
+
+ //if (!(bonusSet.Claimed || bonusSet.ClaimedHardcore))
+ // BonusSetsList.CollectionEditions[bonusSet.SetId].ClaimOnce(this);
+
+ if (World.Game.IsHardcore)
+ {
+ bonusSet.ClaimedHardcore = true;
+ }
+ else
+ {
+ bonusSet.Claimed = true;
+ bonusSet.ClaimedToon = Toon.DBToon;
+ }
+
+ //BonusSetsList.CollectionEditions[bonusSet.SetId].Claim(this);
+ World.Game.GameDBSession.SessionUpdate(bonusSet);
+ //this.InGameClient.SendMessage(new BroadcastTextMessage() { Field0 = "You have been granted with gifts from bonus pack!" });
+ }
+ }
+
+ public HirelingInfo GetHirelingInfo(int type)
+ {
+ var query = World.Game.GameDBSession
+ .SessionQueryWhere(dbh => dbh.DBToon.Id == Toon.PersistentID && dbh.Class == type).ToList();
+ if (query.Count == 0)
+ {
+ //returns empty data
+ var hireling_empty = new HirelingInfo
+ {
+ HirelingIndex = type, GbidName = 0x0000, Dead = false, Skill1SNOId = -1, Skill2SNOId = -1,
+ Skill3SNOId = -1, Skill4SNOId = -1, annItems = -1
+ };
+ return hireling_empty;
+ }
+
+ var hireling_full = new HirelingInfo
+ {
+ HirelingIndex = type,
+ GbidName = 0x0000,
+ Dead = false,
+ Skill1SNOId = query.First().Skill1SNOId,
+ Skill2SNOId = query.First().Skill2SNOId,
+ Skill3SNOId = query.First().Skill3SNOId,
+ Skill4SNOId = query.First().Skill4SNOId,
+ annItems = -1
+ };
+ return hireling_full;
+ }
+
+ private List Unserialize(string data)
+ {
+ var recparts = data.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
+ var ret = new List();
+ foreach (var recid in recparts) ret.Add(Convert.ToInt32(recid, 10));
+ return ret;
+ }
+
+ private string Serialize(List data)
+ {
+ var serialized = "";
+ foreach (var id in data)
+ {
+ serialized += id;
+ serialized += ";";
+ }
+
+ return serialized;
+ }
+
+ private List UnserializeBytes(byte[] data)
+ {
+ return Enumerable.Range(0, data.Length / 4).Select(i => BitConverter.ToInt32(data, i * 4)).ToList();
+ }
+
+ private byte[] SerializeBytes(List data)
+ {
+ return data.SelectMany(BitConverter.GetBytes).ToArray();
+ }
+
+ public void LearnRecipe(ArtisanType? artisan, int recipe)
+ {
+ Logger.Trace("Learning recipe #{0}, Artisan type: {1}", recipe, artisan);
+ /*var query = this.World.Game.GameDBSession.SessionQuerySingle(
+ dbi =>
+ dbi.DBGameAccount.Id == this.Toon.GameAccount.PersistentID &&
+ dbi.Artisan == artisan &&
+ dbi.isHardcore == this.World.Game.IsHardcore);*/
+ if (artisan == ArtisanType.Blacksmith)
+ {
+ learnedBlacksmithRecipes.Add(recipe);
+ blacksmith_data.LearnedRecipes = SerializeBytes(learnedBlacksmithRecipes);
+ World.Game.GameDBSession.SessionUpdate(blacksmith_data);
+ UpdateAchievementCounter(404, 1, 0);
+ }
+ else if (artisan == ArtisanType.Jeweler)
+ {
+ learnedJewelerRecipes.Add(recipe);
+ jeweler_data.LearnedRecipes = SerializeBytes(learnedJewelerRecipes);
+ World.Game.GameDBSession.SessionUpdate(jeweler_data);
+ UpdateAchievementCounter(404, 1, 1);
+ }
+
+ LoadCrafterData();
+ }
+
+ public bool RecipeAvailable(GameBalance.RecipeTable recipe_definition)
+ {
+ if (recipe_definition.Flags == 0) return true;
+ return learnedBlacksmithRecipes.Contains(recipe_definition.Hash) ||
+ learnedJewelerRecipes.Contains(recipe_definition.Hash);
+ }
+
+ public PlayerBannerMessage GetPlayerBanner()
+ {
+ var playerBanner = D3.GameMessage.PlayerBanner.CreateBuilder()
+ .SetPlayerIndex((uint)PlayerIndex)
+ .SetBanner(Toon.GameAccount.BannerConfigurationField.Value)
+ .Build();
+
+ return new PlayerBannerMessage() { PlayerBanner = playerBanner };
+ }
+
+ private List learnedBlacksmithRecipes = new();
+ private List learnedJewelerRecipes = new();
+ private List learnedTransmogs = new();
+
+ private DBCraft blacksmith_data = null;
+ private DBCraft jeweler_data = null;
+ private DBCraft mystic_data = null;
+ private Dictionary artisanTrainHelpers = new();
+
+ public void LoadCrafterData()
+ {
+ if (blacksmith_data == null)
+ {
+ var craft_data =
+ World.Game.GameDBSession.SessionQueryWhere(dbc =>
+ dbc.DBGameAccount.Id == Toon.GameAccount.PersistentID);
+
+ blacksmith_data = craft_data.Single(dbc =>
+ dbc.Artisan == "Blacksmith" && dbc.isHardcore == World.Game.IsHardcore &&
+ dbc.isSeasoned == World.Game.IsSeasoned);
+ jeweler_data = craft_data.Single(dbc =>
+ dbc.Artisan == "Jeweler" && dbc.isHardcore == World.Game.IsHardcore &&
+ dbc.isSeasoned == World.Game.IsSeasoned);
+ mystic_data = craft_data.Single(dbc =>
+ dbc.Artisan == "Mystic" && dbc.isHardcore == World.Game.IsHardcore &&
+ dbc.isSeasoned == World.Game.IsSeasoned);
+
+ artisanTrainHelpers[ArtisanType.Blacksmith] =
+ new ArtisanTrainHelper(blacksmith_data, ArtisanType.Blacksmith);
+ artisanTrainHelpers[ArtisanType.Jeweler] = new ArtisanTrainHelper(jeweler_data, ArtisanType.Jeweler);
+ artisanTrainHelpers[ArtisanType.Mystic] = new ArtisanTrainHelper(mystic_data, ArtisanType.Mystic);
+ }
+
+
+ var blacksmith = D3.ItemCrafting.CrafterData.CreateBuilder()
+ .SetLevel(InGameClient.Game.CurrentAct == 3000
+ ? BlacksmithUnlocked == false && blacksmith_data.Level < 1 ? 1 : blacksmith_data.Level
+ : blacksmith_data.Level)
+ .SetCooldownEnd(0)
+ .AddRangeRecipes(UnserializeBytes(blacksmith_data.LearnedRecipes))
+ .Build();
+ learnedBlacksmithRecipes = UnserializeBytes(blacksmith_data.LearnedRecipes);
+ var jeweler = D3.ItemCrafting.CrafterData.CreateBuilder()
+ .SetLevel(InGameClient.Game.CurrentAct == 3000
+ ? JewelerUnlocked == false && jeweler_data.Level < 1 ? 1 : jeweler_data.Level
+ : jeweler_data.Level)
+ .SetCooldownEnd(0)
+ .AddRangeRecipes(UnserializeBytes(jeweler_data.LearnedRecipes))
+ .Build();
+ learnedJewelerRecipes = UnserializeBytes(jeweler_data.LearnedRecipes);
+ var mystic = D3.ItemCrafting.CrafterData.CreateBuilder()
+ .SetLevel(InGameClient.Game.CurrentAct == 3000
+ ? MysticUnlocked == false && mystic_data.Level < 1 ? 1 : mystic_data.Level
+ : mystic_data.Level)
+ .SetCooldownEnd(0)
+ .Build();
+
+ var transmog = D3.ItemCrafting.CrafterSavedData.CreateBuilder()
+ .SetTransmogData(D3.GameBalance.BitPackedGbidArray.CreateBuilder()
+ .SetBitfield(ByteString.CopyFrom(mystic_data.LearnedRecipes)))
+ //.AddRangeUnlockedTransmogs(this.UnserializeBytes(mystic_data.LearnedRecipes))
+ .Build();
+ learnedTransmogs = UnserializeBytes(mystic_data.LearnedRecipes);
+
+ if (BlacksmithUnlocked || InGameClient.Game.CurrentAct == 3000)
+ InGameClient.SendMessage(new GenericBlobMessage(Opcodes.CraftingDataBlacksmithInitialMessage)
+ { Data = blacksmith.ToByteArray() });
+
+ if (JewelerUnlocked || InGameClient.Game.CurrentAct == 3000)
+ InGameClient.SendMessage(new GenericBlobMessage(Opcodes.CraftingDataJewelerInitialMessage)
+ { Data = jeweler.ToByteArray() });
+
+ if (MysticUnlocked || InGameClient.Game.CurrentAct == 3000)
+ {
+ InGameClient.SendMessage(new GenericBlobMessage(Opcodes.CraftingDataMysticInitialMessage)
+ { Data = mystic.ToByteArray() });
+ InGameClient.SendMessage(new GenericBlobMessage(Opcodes.CraftingDataTransmogInitialMessage)
+ { Data = transmog.ToByteArray() });
+ }
+ }
+
+ public void LoadCurrencyData()
+ {
+ var bloodShards = 0;
+ bloodShards = Toon.GameAccount.BloodShards;
+ Inventory.UpdateCurrencies();
+ }
+
+ public void LoadMailData()
+ {
+ var mail_data =
+ World.Game.GameDBSession.SessionQueryWhere(dbm =>
+ dbm.DBToon.Id == Toon.PersistentID && dbm.Claimed == false);
+ var mails = D3.Items.Mails.CreateBuilder();
+ foreach (var mail in mail_data)
+ {
+ var mail_row = D3.Items.Mail.CreateBuilder()
+ .SetAccountTo(Toon.D3EntityID)
+ .SetAccountFrom(Toon.D3EntityID)
+ .SetMailId(mail.Id)
+ .SetTitle(mail.Title)
+ .SetBody(mail.Body);
+ if (mail.ItemGBID != -1)
+ mail_row.SetAttachments(D3.Items.MailAttachments.CreateBuilder()
+ .SetItems(D3.Items.ItemList.CreateBuilder()
+ .AddItems(D3.Items.SavedItem.CreateBuilder()
+ .SetId(D3.OnlineService.ItemId.CreateBuilder().SetIdLow(0).SetIdHigh(0x3C000002517A294))
+ .SetHirelingClass(0)
+ .SetItemSlot(0)
+ .SetSquareIndex(0)
+ .SetUsedSocketCount(0)
+ .SetGenerator(D3.Items.Generator.CreateBuilder()
+ .SetGbHandle(D3.GameBalance.Handle.CreateBuilder().SetGbid(mail.ItemGBID)
+ .SetGameBalanceType(2))
+ .SetFlags(2147483647)
+ .SetSeed(0)
+ .SetDurability(0)
+ .SetStackSize(0)
+ )
+ )
+ )
+ );
+ mails.AddMailsProp(mail_row);
+ }
+
+ var mail_contents = D3.GameMessage.MailContents.CreateBuilder()
+ .SetAppendMessages(false)
+ .SetMails(mails)
+ .Build();
+
+ InGameClient.SendMessage(new MailDigestMessage() { MailContents = mail_contents });
+ }
+
+ //*/
+ public void LoadStashIconsData()
+ {
+ var dbGAcc = Toon.GameAccount.DBGameAccount;
+ if (dbGAcc.StashIcons == null) return;
+
+ //this.InGameClient.SendMessage(new StashIconStateMessage() { StashIcons = dbGAcc.StashIcons });
+ }
+
+ public void NotifyMaintenance()
+ {
+ if (GameServer.ClientSystem.GameServer.MaintenanceTime > 0 &&
+ GameServer.ClientSystem.GameServer.MaintenanceTime > (int)DateTime.Now.ToUnixTime())
+ InGameClient.SendMessage(new LogoutTickTimeMessage()
+ {
+ Field0 = false, // true - logout with party?
+ Ticks = 0, // delay 1, make this equal to 0 for instant logout
+ Field2 = 10000, // delay 2
+ Field3 = (GameServer.ClientSystem.GameServer.MaintenanceTime - (int)DateTime.Now.ToUnixTime()) *
+ 60 //maintenance counter
+ });
+ }
+
+ public void LoadShownTutorials()
+ {
+ var tutorials = new List();
+ tutorials.Add(64);
+ for (var i = 0; i < 15; i++)
+ tutorials.Add(0);
+ var seenTutorials = Toon.GameAccount.DBGameAccount.SeenTutorials;
+
+ var state = D3.GameMessage.TutorialState.CreateBuilder()
+ .SetSeenTutorials(ByteString.CopyFrom(seenTutorials))
+ .Build();
+ InGameClient.SendMessage(new GenericBlobMessage(Opcodes.TutorialStateMessage) { Data = state.ToByteArray() });
+ }
+
+ private List _unlockedAchievements = new();
+ private List _unlockedCriterias = new();
+
+ private Dictionary AchievementCounters = new();
+
+ public int DodgesInARow = 0;
+ public int BlocksInARow = 0;
+
+ public void GrantAchievement(ulong id)
+ {
+ if (_unlockedAchievements.Contains(id)) return;
+ if (InGameClient.BnetClient.Account.GameAccount.Achievements
+ .Where(a => a.AchievementId == id && a.Completion != -1).Count() > 0) return;
+ if (_unlockedAchievements.Contains(id)) return;
+ _unlockedAchievements.Add(id);
+ try
+ {
+ var Achievement = AchievementSystem.AchievementManager.GetAchievementById(id);
+ long Platinum = -1;
+ foreach (var attr in Achievement.AttributesList)
+ if (attr.Key == "Reward Currency Quantity")
+ Platinum = long.Parse(attr.Value);
+ InGameClient.SendMessage(new MessageSystem.Message.Definitions.Platinum.PlatinumAchievementAwardedMessage
+ {
+ CurrentPlatinum = InGameClient.BnetClient.Account.GameAccount.Platinum,
+ idAchievement = id,
+ PlatinumIncrement = Platinum
+ });
+ if (Platinum > 0)
+ {
+ InGameClient.BnetClient.Account.GameAccount.Platinum += (int)Platinum;
+ Inventory.UpdateCurrencies();
+ }
+
+ ClientSystem.GameServer.GSBackend.GrantAchievement(Toon.GameAccount.PersistentID, id);
+ }
+ catch (Exception e)
+ {
+ Logger.WarnException(e, "Exception on GrantAchievement(): ");
+ }
+ }
+
+ public void AddAchievementCounter(ulong id, uint count)
+ {
+ lock (AchievementCounters)
+ {
+ if (!AchievementCounters.ContainsKey(id))
+ AchievementCounters.Add(id, count);
+ else
+ AchievementCounters[id] += count;
+ }
+ }
+
+ public void CheckAchievementCounters()
+ {
+ lock (AchievementCounters)
+ {
+ foreach (var counter in AchievementCounters)
+ {
+ if (counter.Value == 0) continue;
+ UpdateSingleAchievementCounter(counter.Key, counter.Value);
+ }
+
+ AchievementCounters.Clear();
+ }
+ }
+
+ public void GrantCriteria(ulong id)
+ {
+ if (_unlockedCriterias.Contains(id)) return;
+ _unlockedCriterias.Add(id);
+ try
+ {
+ GameServer.ClientSystem.GameServer.GSBackend.GrantCriteria(Toon.GameAccount.PersistentID, id);
+ }
+ catch (Exception e)
+ {
+ Logger.WarnException(e, "Exception on GrantCriteria(): ");
+ }
+ }
+
+ public void UpdateQuantity(ulong id, uint counter)
+ {
+ try
+ {
+ GameServer.ClientSystem.GameServer.GSBackend.UpdateQuantity(Toon.GameAccount.PersistentID, id, counter);
+ }
+ catch (Exception e)
+ {
+ Logger.WarnException(e, "Exception on UpdateQuantity(): ");
+ }
+ }
+
+ public void UpdateAchievementCounter(int type, uint addCounter, int comparand = -1, ulong achiId = 0)
+ {
+ try
+ {
+ GameServer.ClientSystem.GameServer.GSBackend.UpdateAchievementCounter(Toon.GameAccount.PersistentID, type,
+ addCounter, comparand, achiId);
+ }
+ catch (Exception e)
+ {
+ Logger.WarnException(e, "Exception on UpdateAchievementCounter(): ");
+ }
+ }
+
+ public void UpdateSingleAchievementCounter(ulong achievementId, uint addCounter)
+ {
+ try
+ {
+ GameServer.ClientSystem.GameServer.GSBackend.UpdateSingleAchievementCounter(Toon.GameAccount.PersistentID,
+ achievementId, addCounter);
+ }
+ catch (Exception e)
+ {
+ Logger.WarnException(e, "Exception on UpdateSingleAchievementCounter(): ");
+ }
+ }
+
+ public void CheckQuestCriteria(int questId)
+ {
+ try
+ {
+ GameServer.ClientSystem.GameServer.GSBackend.CheckQuestCriteria(Toon.GameAccount.PersistentID, questId,
+ World.Game.Players.Count > 1);
+ }
+ catch (Exception e)
+ {
+ Logger.WarnException(e, "Exception on CheckQuestCriteria(): ");
+ }
+ }
+
+ public void CheckKillMonsterCriteria(ActorSno actorSno, int type)
+ {
+ try
+ {
+ ClientSystem.GameServer.GSBackend.CheckKillMonsterCriteria(Toon.GameAccount.PersistentID, (int)actorSno,
+ type, World.Game.IsHardcore);
+ }
+ catch (Exception e)
+ {
+ Logger.WarnException(e, "Exception on CheckKillMonsterCriteria(): ");
+ }
+ }
+
+ public void CheckLevelCap()
+ {
+ try
+ {
+ GameServer.ClientSystem.GameServer.GSBackend.CheckLevelCap(Toon.GameAccount.PersistentID);
+ }
+ catch (Exception e)
+ {
+ Logger.WarnException(e, "Exception on CheckLevelCap(): ");
+ }
+ }
+
+ public void CheckSalvageItemCriteria(int itemId)
+ {
+ try
+ {
+ GameServer.ClientSystem.GameServer.GSBackend.CheckSalvageItemCriteria(Toon.GameAccount.PersistentID,
+ itemId);
+ }
+ catch (Exception e)
+ {
+ Logger.WarnException(e, "Exception on CheckSalvageItemCriteria(): ");
+ }
+ }
+
+ public void CheckConversationCriteria(int convId)
+ {
+ try
+ {
+ GameServer.ClientSystem.GameServer.GSBackend.CheckConversationCriteria(Toon.GameAccount.PersistentID,
+ convId);
+ }
+ catch (Exception e)
+ {
+ Logger.WarnException(e, "Exception on CheckConversationCriteria(): ");
+ }
+ }
+
+ public void CheckLevelAreaCriteria(int laId)
+ {
+ try
+ {
+ GameServer.ClientSystem.GameServer.GSBackend.CheckLevelAreaCriteria(Toon.GameAccount.PersistentID, laId);
+ }
+ catch (Exception e)
+ {
+ Logger.WarnException(e, "Exception on CheckLevelAreaCriteria(): ");
+ }
+ }
+
+ public void ParagonLevelUp()
+ {
+ try
+ {
+ GameServer.ClientSystem.GameServer.GSBackend.ParagonLevelUp(Toon.GameAccount.PersistentID);
+ }
+ catch (Exception e)
+ {
+ Logger.WarnException(e, "Exception on ParagonLevelUp(): ");
+ }
+ }
+
+ public void UniqueItemIdentified(ulong itemId)
+ {
+ try
+ {
+ GameServer.ClientSystem.GameServer.GSBackend.UniqueItemIdentified(Toon.GameAccount.PersistentID, itemId);
+ }
+ catch (Exception e)
+ {
+ Logger.WarnException(e, "Exception on UniqueItemIdentified(): ");
+ }
+ }
+
+ public void SetProgress(int act, int difficulty)
+ {
+ if (act > 400) return;
+ var dbGAcc = World.Game.GameDBSession.SessionGet(Toon.GameAccount.PersistentID);
+ var progress = dbGAcc.BossProgress;
+ if (progress[act / 100] == 0xff || progress[act / 100] < (byte)difficulty)
+ {
+ progress[act / 100] = (byte)difficulty;
+
+ dbGAcc.BossProgress = progress;
+ World.Game.GameDBSession.SessionUpdate(dbGAcc);
+ }
+ }
+
+ public int CastingSnoPower = -1;
+
+ public void StartCasting(int durationTicks, Action result, int skillsno = -1)
+ {
+ IsCasting = true;
+ CastResult = result;
+ Attributes[GameAttribute.Looping_Animation_Start_Time] = World.Game.TickCounter;
+ Attributes[GameAttribute.Looping_Animation_End_Time] = World.Game.TickCounter + durationTicks;
+ CastingSnoPower = skillsno;
+ if (CastingSnoPower != -1)
+ {
+ Attributes[GameAttribute.Buff_Icon_Start_Tick0, CastingSnoPower] = World.Game.TickCounter;
+ Attributes[GameAttribute.Buff_Icon_End_Tick0, CastingSnoPower] = World.Game.TickCounter + durationTicks;
+ Attributes[GameAttribute.Buff_Icon_Count0, CastingSnoPower] = 1;
+ Attributes[GameAttribute.Power_Buff_0_Visual_Effect_None, CastingSnoPower] = true;
+ }
+
+ Attributes.BroadcastChangedIfRevealed();
+ }
+
+ public void StopCasting()
+ {
+ IsCasting = false;
+ Attributes[GameAttribute.Looping_Animation_Start_Time] = -1;
+ Attributes[GameAttribute.Looping_Animation_End_Time] = -1;
+ if (CastingSnoPower != -1)
+ {
+ Attributes[GameAttribute.Buff_Icon_Start_Tick0, CastingSnoPower] = -1;
+ Attributes[GameAttribute.Buff_Icon_End_Tick0, CastingSnoPower] = -1;
+ Attributes[GameAttribute.Buff_Icon_Count0, CastingSnoPower] = 0;
+ Attributes[GameAttribute.Power_Buff_0_Visual_Effect_None, CastingSnoPower] = false;
+ }
+
+ Attributes.BroadcastChangedIfRevealed();
+ }
+
+ private void UpdateCastState()
+ {
+ if (Attributes[GameAttribute.Looping_Animation_End_Time] <= World.Game.TickCounter)
+ {
+ StopCasting();
+ CastResult.Invoke();
+ CastResult = null;
+ }
+ }
+
+ public void ShowConfirmation(uint actorId, Action result)
+ {
+ ConfirmationResult = result;
+
+ InGameClient.SendMessage(new ConfirmMessage()
+ {
+ ActorID = actorId
+ });
+ }
+
+ #endregion
+
+ #region generic properties
+
+ public int ClassSNO => Toon.Gender == 0 ? Toon.HeroTable.SNOMaleActor : Toon.HeroTable.SNOFemaleActor;
+
+ public int AdditionalLootItems
+ {
+ get
+ {
+ if (World.BuffManager.HasBuff(this))
+ return Math.Max(World.BuffManager.GetFirstBuff(this).StackCount - 3, 0);
+ else return 0;
+ }
+ }
+
+ public float ModelScale =>
+ Toon.Class switch
+ {
+ ToonClass.Barbarian => 1.2f,
+ ToonClass.Crusader => 1.2f,
+ ToonClass.DemonHunter => 1.35f,
+ ToonClass.Monk => 1.43f,
+ ToonClass.WitchDoctor => 1.1f,
+ ToonClass.Wizard => 1.3f,
+ _ => 1.43f
+ };
+
+ public int PrimaryResourceID => (int)Toon.HeroTable.PrimaryResource;
+
+ public int SecondaryResourceID => (int)Toon.HeroTable.SecondaryResource;
+
+ [Obsolete]
+ public bool IsInTown
+ {
+ get
+ {
+ var townAreas = new List { 19947, 168314, 92945, 197101 };
+ var proximity = new RectangleF(Position.X - 1f, Position.Y - 1f, 2f, 2f);
+ var scenes = World.QuadTree.Query(proximity);
+ if (scenes.Count == 0) return false;
+
+ var scene = scenes[0];
+
+ if (scenes.Count == 2) // What if it's a subscene?
+ if (scenes[1].ParentChunkID != 0xFFFFFFFF)
+ scene = scenes[1];
+
+ return townAreas.Contains(scene.Specification.SNOLevelAreas[0]);
+ }
+ }
+
+ #endregion
+
+ #region experience handling
+
+ //Max((Resource_Max + ((Level#NONE - 1) * Resource_Factor_Level) + Resource_Max_Bonus) * (Resource_Max_Percent_Bonus + 1), 0)
+ private float GetMaxResource(int resourceId)
+ {
+ if (resourceId == 2) return 0;
+ return Math.Max(
+ (Attributes[GameAttribute.Resource_Max, resourceId] +
+ (Attributes[GameAttribute.Level] - 1) * Attributes[GameAttribute.Resource_Factor_Level, resourceId] +
+ Attributes[GameAttribute.Resource_Max_Bonus, resourceId]) *
+ (Attributes[GameAttribute.Resource_Max_Percent_Bonus, resourceId] + 1), 0);
+ }
+
+ public static List LevelBorders = new()
+ {
+ 0, 280, 2700, 4500, 6600, 9000, 11700, 14000, 16500, 19200, 22100, /* Level 0-10 */
+ 25200, 28500, 32000, 35700, 39600, 43700, 48000, 52500, 57200, 62100, /* Level 11-20 */
+ 67200, 72500, 78000, 83700, 89600, 95700, 102000, 108500, 115200, 122100, /* Level 21-30 */
+ 150000, 157500, 180000, 203500, 228000, 273000, 320000, 369000, 420000, 473000, /* Level 31-40 */
+ 528000, 585000, 644000, 705000, 768000, 833000, 900000, 1453500, 2080000, 3180000, /* Level 41-50 */
+ 4050000, 5005000, 6048000, 7980000, 10092000, 12390000, 14880000, 17019000, 20150000,
+ 24586000, /* Level 51-60 */
+ 27000000, 29400000, 31900000, 39100000, 46800000, 55000000, 63700000, 72900000, 82600000,
+ 100000000 /* Level 61-70 */
+ };
+
+ public static List ParagonLevelBorders = new()
+ {
+ //7200000,8640000,10800000,11520000,12960000,14400000,15840000,17280000,18720000,20160000,21600000,23040000,24480000,25920000,27360000,
+ //28800000,30240000,31680000,33120000,34560000,36000000,37440000,38880000,40320,41760000,43200000,41760000,43200000,44640000,46080000,
+ //47520000,48960000,50400000,51840000,53280000,54720000,56160000,57600000,59040000,60480000,61920000,63360000,64800000,66240000,67680000,
+ //69120000,70560000,72000000,73440000,76320000,77760000,79200000,80640000,82080000,83520000,84960000,86400000,87840000
+ };
+
+ public static void GeneratePLB()
+ {
+ long previousExp = 7200000;
+ ParagonLevelBorders.Add(7200000);
+ for (var i = 0; i < 59; i++)
+ {
+ previousExp += 1440000;
+ ParagonLevelBorders.Add(previousExp);
+ }
+
+ for (var i = 0; i < 10; i++)
+ {
+ previousExp += 2880000;
+ ParagonLevelBorders.Add(previousExp);
+ }
+
+ for (var i = 0; i < 3; i++)
+ {
+ previousExp += 5040000;
+ ParagonLevelBorders.Add(previousExp);
+ }
+
+ previousExp += 3660000;
+ ParagonLevelBorders.Add(previousExp);
+ for (var i = 0; i < 75; i++)
+ {
+ previousExp += 1020000;
+ ParagonLevelBorders.Add(previousExp);
+ }
+
+ for (var i = 0; i < 101; i++)
+ {
+ previousExp += 2040000;
+ ParagonLevelBorders.Add(previousExp);
+ }
+
+ for (var i = 0; i < 100; i++)
+ {
+ previousExp += 4080000;
+ ParagonLevelBorders.Add(previousExp);
+ }
+
+ for (var i = 0; i < 99; i++)
+ {
+ previousExp += 6120000;
+ ParagonLevelBorders.Add(previousExp);
+ }
+
+ for (var i = 0; i < 51; i++)
+ {
+ previousExp += 8160000;
+ ParagonLevelBorders.Add(previousExp);
+ }
+
+ for (var i = 0; i < 50; i++)
+ {
+ previousExp += 20400000;
+ ParagonLevelBorders.Add(previousExp);
+ }
+
+ for (var i = 0; i < 50; i++)
+ {
+ previousExp += 40800000;
+ ParagonLevelBorders.Add(previousExp);
+ }
+
+ for (var i = 0; i < 50; i++)
+ {
+ previousExp += 61200000;
+ ParagonLevelBorders.Add(previousExp);
+ }
+
+ for (var i = 0; i < 50; i++)
+ {
+ previousExp += 81600000;
+ ParagonLevelBorders.Add(previousExp);
+ }
+
+ for (var i = 0; i < 50; i++)
+ {
+ previousExp += 102000000;
+ ParagonLevelBorders.Add(previousExp);
+ }
+
+ for (var i = 0; i < 1500; i++)
+ {
+ previousExp += 122400000;
+ ParagonLevelBorders.Add(previousExp);
+ }
+
+ long boosterofup = 229500000;
+ for (var i = 0; i < 17750; i++)
+ {
+ boosterofup += 102000;
+ previousExp += boosterofup;
+ ParagonLevelBorders.Add(previousExp);
+ }
+ }
+ //public static List ParagonLevelBorders = ((GameBalance)DiIiS_NA.Core.MPQ.MPQStorage.Data.Assets[SNOGroup.GameBalance][252616].Data).Experience.Select(row => row.DeltaXP).ToList();
+
+ public static int[] LevelUpEffects =
+ {
+ 85186, 85186, 85186, 85186, 85186, 85190, 85190, 85190, 85190, 85190, /* Level 1-10 */
+ 85187, 85187, 85187, 85187, 85187, 85187, 85187, 85187, 85187, 85187, /* Level 11-20 */
+ 85192, 85192, 85192, 85192, 85192, 85192, 85192, 85192, 85192, 85192, /* Level 21-30 */
+ 85192, 85192, 85192, 85192, 85192, 85192, 85192, 85192, 85192, 85192, /* Level 31-40 */
+ 85192, 85192, 85192, 85192, 85192, 85192, 85192, 85192, 85192, 85192, /* Level 41-50 */
+ 85194, 85194, 85194, 85194, 85194, 85194, 85194, 85194, 85194, 85194, /* Level 51-60 */
+ 85194, 85194, 85194, 85194, 85194, 85194, 85194, 85194, 85194, 85194 /* Level 61-70 */
+ };
+
+ public void AddRestExperience()
+ {
+ long exp_needed = 0;
+ if (Attributes[GameAttribute.Level] == Attributes[GameAttribute.Level_Cap])
+ exp_needed = ParagonLevelBorders[Attributes[GameAttribute.Alt_Level]];
+ else
+ exp_needed = LevelBorders[Attributes[GameAttribute.Level]];
+
+ Attributes[GameAttribute.Rest_Experience_Lo] =
+ Math.Min(Attributes[GameAttribute.Rest_Experience_Lo] + (int)(exp_needed / 10), (int)exp_needed);
+ Attributes[GameAttribute.Rest_Experience_Bonus_Percent] = 0.25f;
+ Attributes.BroadcastChangedIfRevealed();
+ }
+
+ private object _XPlock = new();
+
+ public void UpdateExp(int addedExp)
+ {
+ lock (_XPlock)
+ {
+ if (Dead) return;
+ if (World.Game.IsHardcore && Attributes[GameAttribute.Level] >= 70)
+ addedExp *= 5;
+
+ if (Attributes[GameAttribute.Alt_Level] >= 515)
+ {
+ var XPcap = 91.262575239831f * Math.Pow(Attributes[GameAttribute.Alt_Level], 3) -
+ 44301.083380565047f * Math.Pow(Attributes[GameAttribute.Alt_Level], 2) +
+ 3829010.395566940308f * Attributes[GameAttribute.Alt_Level] + 322795582.543823242188f;
+ addedExp = (int)((float)(ParagonLevelBorders[Attributes[GameAttribute.Alt_Level]] / XPcap) * addedExp);
+ }
+
+ if (Attributes[GameAttribute.Rest_Experience_Lo] > 0)
+ {
+ var multipliedExp = (int)Math.Min(addedExp * Attributes[GameAttribute.Rest_Experience_Bonus_Percent],
+ Attributes[GameAttribute.Rest_Experience_Lo]);
+ addedExp += multipliedExp;
+ Attributes[GameAttribute.Rest_Experience_Lo] -= multipliedExp;
+ }
+
+ if (Attributes[GameAttribute.Level] == Attributes[GameAttribute.Level_Cap])
+ Attributes[GameAttribute.Alt_Experience_Next_Lo] -= addedExp;
+ else
+ Attributes[GameAttribute.Experience_Next_Lo] -= addedExp;
+
+ // Levelup
+ while (Attributes[GameAttribute.Level] >= Attributes[GameAttribute.Level_Cap]
+ ? Attributes[GameAttribute.Alt_Experience_Next_Lo] <= 0
+ : Attributes[GameAttribute.Experience_Next_Lo] <= 0)
+ {
+ // No more levelup at Level_Cap
+ if (Attributes[GameAttribute.Level] >= Attributes[GameAttribute.Level_Cap])
+ {
+ ParagonLevel++;
+ Toon.ParagonLevelUp();
+ ParagonLevelUp();
+ Attributes[GameAttribute.Alt_Level]++;
+ InGameClient.SendMessage(new ParagonLevel()
+ {
+ PlayerIndex = PlayerIndex,
+ Level = ParagonLevel
+ });
+ Conversations.StartConversation(0x0002A777); //LevelUp Conversation
+
+ Attributes[GameAttribute.Alt_Experience_Next_Lo] =
+ Attributes[GameAttribute.Alt_Experience_Next_Lo] +
+ (int)ParagonLevelBorders[Attributes[GameAttribute.Alt_Level]];
+ // On level up, health is set to max
+ Attributes[GameAttribute.Hitpoints_Cur] = Attributes[GameAttribute.Hitpoints_Max_Total];
+ // set resources to max as well
+ Attributes[GameAttribute.Resource_Cur, Attributes[GameAttribute.Resource_Type_Primary] - 1] =
+ Attributes[GameAttribute.Resource_Max_Total,
+ Attributes[GameAttribute.Resource_Type_Primary] - 1];
+ Attributes[GameAttribute.Resource_Cur, Attributes[GameAttribute.Resource_Type_Secondary] - 1] =
+ Attributes[GameAttribute.Resource_Max_Total,
+ Attributes[GameAttribute.Resource_Type_Secondary] - 1];
+
+ ExperienceNext = Attributes[GameAttribute.Alt_Experience_Next_Lo];
+ Attributes.BroadcastChangedIfRevealed();
+
+ PlayEffect(Effect.ParagonLevelUp, null, false);
+ World.PowerManager.RunPower(this, 252038); //g_LevelUp_AA.pow 252038
+ return;
+ }
+
+ Level++;
+ Attributes[GameAttribute.Level]++;
+ Toon.LevelUp();
+ if (World.Game.MonsterLevel + 1 ==
+ Attributes[GameAttribute.Level]) //if this is suitable level to update
+ World.Game.UpdateLevel(Attributes[GameAttribute.Level]);
+
+ InGameClient.SendMessage(new PlayerLevel()
+ {
+ PlayerIndex = PlayerIndex,
+ Level = Level
+ });
+
+
+ //Test Update Monster Level
+ if (PlayerIndex == 0)
+ {
+ InGameClient.Game.InitialMonsterLevel = Level;
+ InGameClient.SendMessage(new GameSyncedDataMessage
+ {
+ SyncedData = new GameSyncedData
+ {
+ GameSyncedFlags = InGameClient.Game.IsSeasoned ? InGameClient.Game.IsHardcore ? 3 : 2 :
+ InGameClient.Game.IsHardcore ? 1 : 0,
+ Act = Math.Min(InGameClient.Game.CurrentAct, 3000), //act id
+ InitialMonsterLevel = InGameClient.Game.InitialMonsterLevel, //InitialMonsterLevel
+ MonsterLevel = 0x64E4425E, //MonsterLevel
+ RandomWeatherSeed = InGameClient.Game.WeatherSeed, //RandomWeatherSeed
+ OpenWorldMode = InGameClient.Game.CurrentAct == 3000 ? 1 : 0, //OpenWorldMode
+ OpenWorldModeAct = -1, //OpenWorldModeAct
+ OpenWorldModeParam = -1, //OpenWorldModeParam
+ OpenWorldTransitionTime = 0x00000064, //OpenWorldTransitionTime
+ OpenWorldDefaultAct = 100, //OpenWorldDefaultAct
+ OpenWorldBonusAct = -1, //OpenWorldBonusAct
+ SNODungeonFinderLevelArea = 0x00000001, //SNODungeonFinderLevelArea
+ LootRunOpen =
+ InGameClient.Game.GameMode == Game.Mode.Portals
+ ? 0
+ : -1, //LootRunOpen //0 - Великий Портал
+ OpenLootRunLevel = 1, //OpenLootRunLevel
+ LootRunBossDead = 0, //LootRunBossDead
+ HunterPlayerIdx = 0, //HunterPlayerIdx
+ LootRunBossActive = -1, //LootRunBossActive
+ TieredLootRunFailed = -1, //TieredLootRunFailed
+ LootRunChallengeCompleted = -1, //LootRunChallengeCompleted
+ SetDungeonActive = -1, //SetDungeonActive
+ Pregame = 0, //Pregame
+ PregameEnd = 0, //PregameEnd
+ RoundStart = 0, //RoundStart
+ RoundEnd = 0, //RoundEnd
+ PVPGameOver = 0x0, //PVPGameOver
+ field_v273 = 0x0,
+ TeamWins = new[] { 0x0, 0x0 }, //TeamWins
+ TeamScore = new[] { 0x0, 0x0 }, //TeamScore
+ PVPGameResult = new[] { 0x0, 0x0 }, //PVPGameResult
+ PartyGuideHeroId =
+ 0x0, //PartyGuideHeroId //new EntityId() { High = 0, Low = (long)this.Players.Values.First().Toon.PersistentID }
+ TiredRiftPaticipatingHeroID =
+ new long[] { 0x0, 0x0, 0x0, 0x0 } //TiredRiftPaticipatingHeroID
+ }
+ });
+ }
+
+ Conversations.StartConversation(0x0002A777); //LevelUp Conversation
+
+ if (Attributes[GameAttribute.Level] >= Attributes[GameAttribute.Level_Cap])
+ {
+ Attributes[GameAttribute.Alt_Experience_Next_Lo] = (int)ParagonLevelBorders[Toon.ParagonLevel];
+ Toon.ExperienceNext = (int)ParagonLevelBorders[Toon.ParagonLevel];
+ }
+ else
+ {
+ Attributes[GameAttribute.Experience_Next_Lo] += (int)LevelBorders[Attributes[GameAttribute.Level]];
+ Toon.ExperienceNext = Attributes[GameAttribute.Experience_Next_Lo];
+ }
+
+ // 4 main attributes are incremented according to class
+ Attributes[GameAttribute.Strength] = Strength;
+ Attributes[GameAttribute.Intelligence] = Intelligence;
+ Attributes[GameAttribute.Vitality] = Vitality;
+ Attributes[GameAttribute.Dexterity] = Dexterity;
+
+ // On level up, health is set to max
+ Attributes[GameAttribute.Hitpoints_Cur] = Attributes[GameAttribute.Hitpoints_Max_Total];
+
+ // force GameAttributeMap to re-calc resources for the active resource types
+ Attributes[GameAttribute.Resource_Max, Attributes[GameAttribute.Resource_Type_Primary] - 1] =
+ Attributes[GameAttribute.Resource_Max, Attributes[GameAttribute.Resource_Type_Primary] - 1];
+ Attributes[GameAttribute.Resource_Max, Attributes[GameAttribute.Resource_Type_Secondary] - 1] =
+ Attributes[GameAttribute.Resource_Max, Attributes[GameAttribute.Resource_Type_Secondary] - 1];
+
+ // set resources to max as well
+ Attributes[GameAttribute.Resource_Cur, Attributes[GameAttribute.Resource_Type_Primary] - 1] =
+ Attributes[GameAttribute.Resource_Max_Total, Attributes[GameAttribute.Resource_Type_Primary] - 1];
+ Attributes[GameAttribute.Resource_Cur, Attributes[GameAttribute.Resource_Type_Secondary] - 1] =
+ Attributes[GameAttribute.Resource_Max_Total, Attributes[GameAttribute.Resource_Type_Secondary] - 1];
+
+ Attributes[GameAttribute.Hitpoints_Factor_Vitality] = 10f + Math.Max(Level - 35, 0);
+
+ Attributes.BroadcastChangedIfRevealed();
+
+ PlayEffect(Effect.LevelUp, null, false);
+ World.PowerManager.RunPower(this, 85954); //g_LevelUp.pow 85954
+
+
+ switch (Level)
+ {
+ case 10:
+ GrantAchievement(World.Game.IsHardcore ? (ulong)74987243307034 : (ulong)74987243307105);
+ break;
+ case 20:
+ GrantAchievement(World.Game.IsHardcore ? (ulong)74987243307035 : (ulong)74987243307104);
+ break;
+ case 30:
+ GrantAchievement(World.Game.IsHardcore ? (ulong)74987243307036 : (ulong)74987243307103);
+ break;
+ case 40:
+ GrantAchievement(World.Game.IsHardcore ? (ulong)74987243307037 : (ulong)74987243307102);
+ break;
+ case 50:
+ GrantAchievement(World.Game.IsHardcore ? (ulong)74987243307038 : (ulong)74987243307101);
+ if (World.Game.IsSeasoned)
+ GrantCriteria(74987250038929);
+ break;
+ case 60:
+ if (World.Game.IsHardcore)
+ {
+ GrantAchievement(74987243307039);
+ if (!Toon.GameAccount.Flags.HasFlag(GameAccount.GameAccountFlags.HardcoreTormentUnlocked))
+ Toon.GameAccount.Flags |= GameAccount.GameAccountFlags.HardcoreTormentUnlocked;
+ }
+ else
+ {
+ GrantAchievement(74987243307100);
+ if (!Toon.GameAccount.Flags.HasFlag(GameAccount.GameAccountFlags.TormentUnlocked))
+ Toon.GameAccount.Flags |= GameAccount.GameAccountFlags.TormentUnlocked;
+ }
+
+ CheckLevelCap();
+ break;
+ case 70:
+ GrantCriteria(74987254853541);
+ break;
+ default:
+ break;
+ }
+ }
+
+ ExperienceNext = Attributes[GameAttribute.Level] == 70
+ ? Attributes[GameAttribute.Alt_Experience_Next_Lo]
+ : Attributes[GameAttribute.Experience_Next_Lo];
+ Attributes.BroadcastChangedIfRevealed();
+ Toon.GameAccount.NotifyUpdate();
+
+ //this.Attributes.SendMessage(this.InGameClient, this.DynamicID); kills the player atm
+ }
+ }
+
+ #endregion
+
+ #region gold, heath-glob collection
+
+ public void VacuumPickupHealthOrb(float radius = -1)
+ {
+ if (Math.Abs(radius - -1) < 0.001)
+ radius = Attributes[GameAttribute.Gold_PickUp_Radius];
+ var itemList = GetItemsInRange(radius);
+ foreach (var item in itemList)
+ if (Item.IsHealthGlobe(item.ItemType))
+ {
+ var playersAffected = GetPlayersInRange(26f);
+ foreach (var player in playersAffected)
+ {
+ foreach (var targetAffected in playersAffected)
+ player.InGameClient.SendMessage(new PlayEffectMessage()
+ {
+ ActorId = targetAffected.DynamicID(player),
+ Effect = Effect.HealthOrbPickup
+ });
+
+ //every summon and mercenary owned by you must broadcast their green text to you /H_DANILO
+ player.AddPercentageHP((int)item.Attributes[GameAttribute.Health_Globe_Bonus_Health]);
+ //passive abilities
+ if (player.SkillSet.HasPassive(208478)) //wizard PowerHungry
+ player.World.BuffManager.AddBuff(this, this, new HungryBuff());
+ if (player.SkillSet.HasPassive(208594)) //wd GruesomeFeast
+ {
+ player.GeneratePrimaryResource(player.Attributes[GameAttribute.Resource_Max_Total,
+ (int)player.Toon.HeroTable.PrimaryResource + 1] * 0.1f);
+ player.World.BuffManager.AddBuff(player, player, new GruesomeFeastIntBuff());
+ }
+
+ if (player.SkillSet.HasPassive(205205)) //barbarian PoundOfFlesh
+ player.AddPercentageHP((int)(item.Attributes[GameAttribute.Health_Globe_Bonus_Health] * 0.5f));
+ if (player.SkillSet.HasPassive(155714)) //dh Vengeance
+ {
+ player.GeneratePrimaryResource(20f);
+ player.GenerateSecondaryResource(2f);
+ }
+ }
+
+ item.Destroy();
+ }
+ }
+
+ public void VacuumPickup()
+ {
+ var itemList = GetItemsInRange(Attributes[GameAttribute.Gold_PickUp_Radius]);
+ foreach (var item in itemList)
+ if (Item.IsGold(item.ItemType))
+ {
+ if (!GroundItems.ContainsKey(item.GlobalID)) continue;
+
+ InGameClient.SendMessage(new FloatingAmountMessage()
+ {
+ Place = new WorldPlace()
+ {
+ Position = Position,
+ WorldID = World.DynamicID(this)
+ },
+
+ Amount = item.Attributes[GameAttribute.Gold],
+ Type = FloatingAmountMessage.FloatType.Gold
+ });
+ InGameClient.SendMessage(new PlayEffectMessage()
+ {
+ ActorId = DynamicID(this),
+ Effect = Effect.GoldPickup,
+ PlayerId = 0
+ });
+ PlayEffect(Effect.Sound, 36726);
+ Inventory.PickUpGold(item);
+ GroundItems.Remove(item.GlobalID);
+ item.Destroy();
+ }
+
+ else if (Item.IsBloodShard(item.ItemType) || item.ItemDefinition.Name == "HoradricRelic")
+ {
+ if (!GroundItems.ContainsKey(item.GlobalID)) continue;
+
+ InGameClient.SendMessage(new FloatingAmountMessage()
+ {
+ Place = new WorldPlace()
+ {
+ Position = Position,
+ WorldID = World.DynamicID(this)
+ },
+
+ Amount = item.Attributes[GameAttribute.ItemStackQuantityLo],
+ Type = FloatingAmountMessage.FloatType.BloodStone
+ });
+
+ Inventory.PickUpBloodShard(item);
+ GroundItems.Remove(item.GlobalID);
+ item.Destroy();
+ }
+
+ else if (item.ItemDefinition.Name == "Platinum")
+ {
+ InGameClient.SendMessage(new FloatingAmountMessage()
+ {
+ Place = new WorldPlace()
+ {
+ Position = Position,
+ WorldID = World.DynamicID(this)
+ },
+
+ Amount = item.Attributes[GameAttribute.ItemStackQuantityLo],
+ Type = FloatingAmountMessage.FloatType.Platinum
+ });
+ PlayEffect(Effect.Sound, 433266);
+
+ Inventory.PickUpPlatinum(item);
+ GroundItems.Remove(item.GlobalID);
+ item.Destroy();
+ }
+
+ else if (item.ItemDefinition.Name == "Crafting_Looted_Reagent_01")
+ {
+ /*
+ this.InGameClient.SendMessage(new FloatingAmountMessage()
+ {
+ Place = new WorldPlace()
+ {
+ Position = this.Position,
+ WorldID = this.World.DynamicID(this),
+ },
+
+ Amount = item.Attributes[GameAttribute.ItemStackQuantityLo],
+ Type = (FloatingAmountMessage.FloatType)22,
+ });
+ //*/
+ Toon.GameAccount.CraftItem4++;
+ Inventory.UpdateCurrencies();
+ item.Destroy();
+ }
+
+ else if (Item.IsHealthGlobe(item.ItemType))
+ {
+ var playersAffected = GetPlayersInRange(26f);
+ foreach (var player in playersAffected)
+ {
+ foreach (var targetAffected in playersAffected)
+ player.InGameClient.SendMessage(new PlayEffectMessage()
+ {
+ ActorId = targetAffected.DynamicID(player),
+ Effect = Effect.HealthOrbPickup
+ });
+
+ //every summon and mercenary owned by you must broadcast their green text to you /H_DANILO
+ player.AddPercentageHP((int)item.Attributes[GameAttribute.Health_Globe_Bonus_Health]);
+ //passive abilities
+ if (player.SkillSet.HasPassive(208478)) //wizard PowerHungry
+ player.World.BuffManager.AddBuff(this, this, new HungryBuff());
+ if (player.SkillSet.HasPassive(208594)) //wd GruesomeFeast
+ {
+ player.GeneratePrimaryResource(player.Attributes[GameAttribute.Resource_Max_Total,
+ (int)player.Toon.HeroTable.PrimaryResource + 1] * 0.1f);
+ player.World.BuffManager.AddBuff(player, player, new GruesomeFeastIntBuff());
+ }
+
+ if (player.SkillSet.HasPassive(205205)) //barbarian PoundOfFlesh
+ player.AddPercentageHP((int)(item.Attributes[GameAttribute.Health_Globe_Bonus_Health] * 0.5f));
+ if (player.SkillSet.HasPassive(155714)) //dh Vengeance
+ {
+ player.GeneratePrimaryResource(20f);
+ player.GenerateSecondaryResource(2f);
+ }
+ }
+
+ item.Destroy();
+ }
+
+ else if (item.ItemDefinition.Name == "ArcaneGlobe" && Toon.Class == ToonClass.Wizard)
+ {
+ GeneratePrimaryResource(50f);
+ item.Destroy();
+ }
+
+ else if (item.ItemDefinition.Name == "p1_normal_rifts_Orb" ||
+ item.ItemDefinition.Name == "p1_tiered_rifts_Orb")
+ {
+ if (InGameClient.Game.ActiveNephalemTimer && InGameClient.Game.ActiveNephalemKilledMobs == false)
+ {
+ InGameClient.Game.ActiveNephalemProgress += 15f;
+ foreach (var plr in InGameClient.Game.Players.Values)
+ {
+ plr.InGameClient.SendMessage(new FloatDataMessage(Opcodes.DunggeonFinderProgressGlyphPickUp)
+ {
+ Field0 = InGameClient.Game.ActiveNephalemProgress
+ });
+
+ plr.InGameClient.SendMessage(new SimpleMessage(Opcodes.KillCounterRefresh)
+ {
+ });
+ plr.InGameClient.SendMessage(new FloatDataMessage(Opcodes.DungeonFinderProgressMessage)
+ {
+ Field0 = InGameClient.Game.ActiveNephalemProgress
+ });
+ }
+
+ if (InGameClient.Game.ActiveNephalemProgress > 650)
+ {
+ InGameClient.Game.ActiveNephalemKilledMobs = true;
+ foreach (var plr in InGameClient.Game.Players.Values)
+ {
+ if (InGameClient.Game.NephalemGreater)
+ {
+ plr.InGameClient.SendMessage(new QuestCounterMessage()
+ {
+ snoQuest = 0x00052654,
+ snoLevelArea = 0x000466E2,
+ StepID = 13,
+ TaskIndex = 0,
+ Checked = 1,
+ Counter = 1
+ });
+ plr.InGameClient.SendMessage(new QuestUpdateMessage()
+ {
+ snoQuest = 0x00052654,
+ snoLevelArea = 0x000466E2,
+ StepID = 16,
+ DisplayButton = true,
+ Failed = false
+ });
+ }
+ else
+ {
+ plr.InGameClient.SendMessage(new QuestCounterMessage()
+ {
+ snoQuest = 0x00052654,
+ snoLevelArea = 0x000466E2,
+ StepID = 1,
+ TaskIndex = 0,
+ Checked = 1,
+ Counter = 1
+ });
+ plr.InGameClient.SendMessage(new QuestUpdateMessage()
+ {
+ snoQuest = 0x00052654,
+ snoLevelArea = 0x000466E2,
+ StepID = 3,
+ DisplayButton = true,
+ Failed = false
+ });
+ }
+
+
+ plr.InGameClient.SendMessage(new PlayMusicMessage(Opcodes.PlayMusicMessage)
+ {
+ SNO = 0x0005BBD8
+ });
+
+ plr.InGameClient.SendMessage(new DisplayGameTextMessage(Opcodes.DisplayGameChatTextMessage)
+ { Message = "Messages:LR_BossSpawned" });
+ plr.InGameClient.SendMessage(new DisplayGameTextMessage(Opcodes.DisplayGameTextMessage)
+ { Message = "Messages:LR_BossSpawned" });
+ }
+
+ StartConversation(World, 366542);
+ SpawnNephalemBoss(World);
+ //358489
+ }
+ }
+
+ item.Destroy();
+ }
+
+ else if (item.ItemDefinition.Name == "PowerGlobe_v2_x1_NoFlippy")
+ {
+ World.BuffManager.AddBuff(this, this, new NephalemValorBuff());
+ item.Destroy();
+ }
+
+ else if (Item.IsPotion(item.ItemType))
+ {
+ if ((!GroundItems.ContainsKey(item.GlobalID) && World.Game.Players.Count > 1) ||
+ !Inventory.HasInventorySpace(item)) continue;
+ Inventory.PickUp(item);
+ }
+
+ //
+ foreach (var skill in SkillSet.ActiveSkills)
+ if (skill.snoSkill == 460757 && skill.snoRune == 3)
+ {
+ //Play Aura - 472217
+ //this.PlayEffectGroup(472217);
+ var Fleshes =
+ GetActorsInRange(15f + Attributes[GameAttribute.Gold_PickUp_Radius] *
+ 0.5f); //454066
+ foreach (var flesh in Fleshes)
+ {
+ InGameClient.SendMessage(new EffectGroupACDToACDMessage()
+ {
+ EffectSNOId = 470480,
+ TargetID = DynamicID(this),
+ ActorID = flesh.DynamicID(this)
+ });
+ flesh.PlayEffectGroup(470482);
+ Attributes[GameAttribute.Resource_Cur, (int)Toon.HeroTable.PrimaryResource] += 11f;
+ Attributes.BroadcastChangedIfRevealed();
+ flesh.Destroy();
+ }
+ }
+ }
+
+ public Actor SpawnNephalemBoss(World world)
+ {
+ var Boss = world.SpawnMonster(
+ ActorSnoExtensions.nephalemPortalBosses[
+ RandomHelper.Next(0, ActorSnoExtensions.nephalemPortalBosses.Length - 1)], Position);
+ Boss.Attributes[GameAttribute.Bounty_Objective] = true;
+ Boss.Attributes[GameAttribute.Is_Loot_Run_Boss] = true;
+ Boss.Attributes.BroadcastChangedIfRevealed();
+
+
+ foreach (var plr in world.Players.Values)
+ plr.InGameClient.SendMessage(new WorldSyncedDataMessage()
+ {
+ WorldID = world.GlobalID,
+ SyncedData = new WorldSyncedData()
+ {
+ SnoWeatherOverride = 362462,
+ WeatherIntensityOverride = 0,
+ WeatherIntensityOverrideEnd = 0
+ }
+ });
+
+
+ return Boss;
+ }
+
+ public bool StartConversation(World world, int conversationId)
+ {
+ foreach (var plr in world.Players)
+ plr.Value.Conversations.StartConversation(conversationId);
+ return true;
+ }
+
+ public void AddPercentageHP(int percentage, bool GuidingLight = false)
+ {
+ var quantity = percentage * Attributes[GameAttribute.Hitpoints_Max_Total] / 100;
+ AddHP(quantity, GuidingLight);
+ }
+
+ public void AddPercentageHP(float percentage, bool GuidingLight = false)
+ {
+ var quantity = percentage * Attributes[GameAttribute.Hitpoints_Max_Total] / 100;
+ AddHP(quantity, GuidingLight);
+ }
+
+ public override void AddHP(float quantity, bool guidingLight = false)
+ {
+ if (Dead) return;
+ if (quantity == 0) return;
+ if (quantity > 0)
+ {
+ if (Attributes[GameAttribute.Hitpoints_Cur] < Attributes[GameAttribute.Hitpoints_Max_Total])
+ {
+ if (Toon.Class == ToonClass.Barbarian)
+ if (SkillSet.HasPassive(205217))
+ quantity += 0.01f * Attributes[GameAttribute.Health_Globe_Bonus_Health];
+
+ if (guidingLight) //Monk -> Guiding Light
+ {
+ var missingHP =
+ (Attributes[GameAttribute.Hitpoints_Max_Total] - Attributes[GameAttribute.Hitpoints_Cur]) /
+ Attributes[GameAttribute.Hitpoints_Max_Total];
+ if (missingHP > 0.05f)
+ if (!World.BuffManager.HasBuff(this))
+ World.BuffManager.AddBuff(this, this,
+ new GuidingLightBuff(Math.Min(missingHP, 0.3f),
+ TickTimer.WaitSeconds(World.Game, 10.0f)));
+ }
+
+ Attributes[GameAttribute.Hitpoints_Cur] = Math.Min(
+ Attributes[GameAttribute.Hitpoints_Cur] + quantity,
+ Attributes[GameAttribute.Hitpoints_Max_Total]);
+
+ Attributes.BroadcastChangedIfRevealed();
+ InGameClient.SendMessage(new FloatingNumberMessage
+ {
+ ActorID = DynamicID(this),
+ Number = quantity,
+ Type = FloatingNumberMessage.FloatType.Green
+ });
+ }
+ }
+ else
+ {
+ Attributes[GameAttribute.Hitpoints_Cur] = Math.Max(
+ Attributes[GameAttribute.Hitpoints_Cur] + quantity,
+ 0);
+
+ Attributes.BroadcastChangedIfRevealed();
+ }
+ }
+
+ //only for WD passive
+ public void RestoreMana(float quantity, int secs)
+ {
+ Attributes[GameAttribute.Resource_Regen_Per_Second, 0] += quantity / secs;
+ System.Threading.Tasks.Task.Delay(1000 * secs).ContinueWith(t =>
+ {
+ Attributes[GameAttribute.Resource_Regen_Per_Second, 0] -= quantity / secs;
+ });
+ }
+
+ #endregion
+
+ #region Resource Generate/Use
+
+ private int _DisciplineSpent = 0;
+ private int _HatredSpent = 0;
+ private int _WrathSpent = 0;
+
+ public void GeneratePrimaryResource(float amount)
+ {
+ if (Toon.Class == ToonClass.Barbarian)
+ if (World.BuffManager.HasBuff(this))
+ World.BuffManager.GetFirstBuff(this).GainedFury += amount;
+
+ if (Toon.Class == ToonClass.Monk)
+ if (World.BuffManager.HasBuff(this)) //Monk -> The Guardian's Path 2H
+ amount *= 1.35f;
+
+ _ModifyResourceAttribute(PrimaryResourceID, amount);
+ }
+
+ public void UsePrimaryResource(float amount, bool tick = false)
+ {
+ amount = Math.Max(
+ (amount - Attributes[GameAttribute.Resource_Cost_Reduction_Amount]) * (1f -
+ Attributes[GameAttribute.Resource_Cost_Reduction_Percent_Total,
+ (int)Toon.HeroTable.PrimaryResource + 1]), 0);
+ amount = amount * (1f - DecreaseUseResourcePercent);
+ if (Toon.Class == ToonClass.Crusader)
+ {
+ _WrathSpent += (int)amount;
+ if (!tick && SkillSet.HasPassive(310775)) //Wrathful passive
+ AddHP(_WrathSpent * 15f * Attributes[GameAttribute.Level]);
+
+ //Laws of Hope -> Faith's reward
+ if (!tick && World.BuffManager.HasBuff(this))
+ if (World.BuffManager.GetFirstBuff(this).HealPerWrath)
+ AddHP(_WrathSpent * 15f * Attributes[GameAttribute.Level]);
+
+ if (_WrathSpent >= 20) //Akarat Champion -> Fire Starter
+ if (!tick && World.BuffManager.HasBuff(this))
+ World.BuffManager.GetFirstBuff(this).wrathBlast = true;
+ }
+
+ if (Toon.Class == ToonClass.DemonHunter)
+ {
+ _HatredSpent += (int)amount;
+
+ if (_HatredSpent >= 150 && _DisciplineSpent >= 50)
+ GrantAchievement(74987243307068);
+
+ AddTimedAction(6f, new Action