diff --git a/src/DiIiS-NA/Core/Logging/FileTarget.cs b/src/DiIiS-NA/Core/Logging/FileTarget.cs
index efaf281..15c723e 100644
--- a/src/DiIiS-NA/Core/Logging/FileTarget.cs
+++ b/src/DiIiS-NA/Core/Logging/FileTarget.cs
@@ -2,6 +2,7 @@
using System;
using System.Collections.Concurrent;
using System.IO;
+using System.Text.RegularExpressions;
using System.Threading;
namespace DiIiS_NA.Core.Logging
@@ -24,48 +25,55 @@ namespace DiIiS_NA.Core.Logging
/// Reset log file on application startup?
public FileTarget(string fileName, Logger.Level minLevel, Logger.Level maxLevel, bool includeTimeStamps, bool reset = false)
{
- this.MinimumLevel = minLevel;
- this.MaximumLevel = maxLevel;
- this.IncludeTimeStamps = includeTimeStamps;
- this._fileName = fileName;
- this._fileTimestamp = DateTime.Now.ToString("yyyyMMdd_HHmm");
- this._filePath = string.Format("{0}/{1}/{2}", LogConfig.Instance.LoggingRoot, this._fileTimestamp, _fileName);
- this._fileIndex = 0;
+ MinimumLevel = minLevel;
+ MaximumLevel = maxLevel;
+ IncludeTimeStamps = includeTimeStamps;
+ _fileName = fileName;
+ _fileTimestamp = DateTime.Now.ToString("yyyy-MM-dd_HH-mm");
+ _filePath = $"{LogConfig.Instance.LoggingRoot}/{_fileTimestamp}/{_fileName}";
+ _fileIndex = 0;
if (!Directory.Exists(LogConfig.Instance.LoggingRoot)) // create logging directory if it does not exist yet.
Directory.CreateDirectory(LogConfig.Instance.LoggingRoot);
- if (!Directory.Exists(string.Format("{0}/{1}", LogConfig.Instance.LoggingRoot, this._fileTimestamp))) // create logging directory if it does not exist yet.
- Directory.CreateDirectory(string.Format("{0}/{1}", LogConfig.Instance.LoggingRoot, this._fileTimestamp));
+ if (!Directory.Exists($"{LogConfig.Instance.LoggingRoot}/{_fileTimestamp}")) // create logging directory if it does not exist yet.
+ Directory.CreateDirectory($"{LogConfig.Instance.LoggingRoot}/{_fileTimestamp}");
- this._fileStream = new FileStream(_filePath, reset ? FileMode.Create : FileMode.Append, FileAccess.Write, FileShare.Read); // init the file stream.
- this._logStream = new StreamWriter(this._fileStream) { AutoFlush = true }; // init the stream writer.
- this.TaskQueue = new ConcurrentQueue();
- this.LoggerThread = new Thread(this.CheckQueue) { Name = "Logger", IsBackground = true };
- this.LoggerThread.Start();
+ _fileStream = new FileStream(_filePath, reset ? FileMode.Create : FileMode.Append, FileAccess.Write, FileShare.Read); // init the file stream.
+ _logStream = new StreamWriter(_fileStream) { AutoFlush = true }; // init the stream writer.
+ TaskQueue = new ConcurrentQueue();
+ LoggerThread = new Thread(CheckQueue) { Name = "Logger", IsBackground = true };
+ LoggerThread.Start();
}
public void CheckQueue()
{
while (true)
{
- Action action = null;
- if (this.TaskQueue.TryDequeue(out action))
+ if (TaskQueue.TryDequeue(out var action))
action.Invoke();
Thread.Sleep(1);
}
}
+ ///
+ /// Replace the colors from AnsiColor so they do not appear in the log file.
+ ///
+ ///
+ ///
+ private string NoColors(string message) => Regex.Replace(message, @"\$\[[\w\W\d\s_\-\/]+\]\$", "");
+
/// Log level.
/// Source of the log message.
/// Log message.
public override void LogMessage(Logger.Level level, string logger, string message)
{
- this.TaskQueue.Enqueue(() =>
+ TaskQueue.Enqueue(() =>
{
- var timeStamp = this.IncludeTimeStamps ? "[" + DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss.fff") + "] " : "";
- if (!this._disposed) // make sure we're not disposed.
+ message = NoColors(message);
+ var timeStamp = IncludeTimeStamps ? "[" + DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss.fff") + "] " : "";
+ if (!_disposed) // make sure we're not disposed.
{
/*
if (this._fileStream.Length >= 20971520) //20 MB limit
@@ -77,9 +85,9 @@ namespace DiIiS_NA.Core.Logging
}
//*/
if (level > Logger.Level.ChatMessage)
- this._logStream.WriteLine(string.Format("{0}[{1}] [{2}]: {3}", timeStamp, level.ToString().PadLeft(5), logger, message));
+ _logStream.WriteLine($"{timeStamp}[{level.ToString(),5}] [{logger}]: {message}");
else
- this._logStream.WriteLine(string.Format("{0}{1}", timeStamp, message));
+ _logStream.WriteLine($"{timeStamp}{message}");
}
});
}
@@ -90,12 +98,13 @@ namespace DiIiS_NA.Core.Logging
/// Exception to be included with log message.
public override void LogException(Logger.Level level, string logger, string message, Exception exception)
{
- this.TaskQueue.Enqueue(() =>
+ TaskQueue.Enqueue(() =>
{
- var timeStamp = this.IncludeTimeStamps ? "[" + DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss.fff") + "] " : "";
- if (!this._disposed) // make sure we're not disposed.
+ message = NoColors(message);
+ var timeStamp = IncludeTimeStamps ? "[" + DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss.fff") + "] " : "";
+ if (!_disposed) // make sure we're not disposed.
{
- this._logStream.WriteLine(
+ _logStream.WriteLine(
$"{timeStamp}[{level.ToString(),5}] [{logger}]: {message} - [Exception] {exception}");
}
});
@@ -109,23 +118,23 @@ namespace DiIiS_NA.Core.Logging
public void Dispose()
{
Dispose(true);
- GC.SuppressFinalize(this); // Take object out the finalization queue to prevent finalization code for it from executing a second time.
+ GC.SuppressFinalize(this); // Take object out the finalization queue to prevent finalization code for it from executing (~FileTarget).
}
private void Dispose(bool disposing)
{
- if (this._disposed) return; // if already disposed, just return
+ if (_disposed) return; // if already disposed, just return
if (disposing) // only dispose managed resources if we're called from directly or in-directly from user code.
{
- this._logStream.Close();
- this._logStream.Dispose();
- this._fileStream.Close();
- this._fileStream.Dispose();
+ _logStream.Close();
+ _logStream.Dispose();
+ _fileStream.Close();
+ _fileStream.Dispose();
}
- this._logStream = null;
- this._fileStream = null;
+ _logStream = null;
+ _fileStream = null;
_disposed = true;
}
diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/GameCommands.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/GameCommands.cs
index 7377b6c..620f29e 100644
--- a/src/DiIiS-NA/D3-GameServer/CommandManager/GameCommands.cs
+++ b/src/DiIiS-NA/D3-GameServer/CommandManager/GameCommands.cs
@@ -16,6 +16,7 @@ using DiIiS_NA.LoginServer.Battle;
using System;
using System.Collections.Generic;
using System.Linq;
+using DiIiS_NA.GameServer.GSSystem.ActorSystem.Implementations;
using DiIiS_NA.GameServer.GSSystem.GameSystem;
using DiIiS_NA.GameServer.GSSystem.ObjectsSystem;
using DiIiS_NA.GameServer.GSSystem.PlayerSystem;
@@ -25,6 +26,74 @@ using Actor = DiIiS_NA.Core.MPQ.FileFormats.Actor;
namespace DiIiS_NA.GameServer.CommandManager;
+[CommandGroup("doors", "Information about all doors in the vicinity. This is useful for testing purposes.. Useful for testing.", Account.UserLevels.Tester)]
+public class OpenDoorCommand : CommandGroup
+{
+ [Command("all", "Activate all doors. This is useful for testing purposes.\nUsage: !open all", Account.UserLevels.Tester)]
+ public string OpenAllDoors(string[] @params, BattleClient invokerClient)
+ {
+ if (invokerClient?.InGameClient?.Player is not { } player)
+ return "You are not in game.";
+ var world = player.World;
+ var openedDoors = world.OpenAllDoors();
+ if (openedDoors.Length == 0)
+ return "No doors found.";
+ return $"Opened {openedDoors.Length} doors: {string.Join(", ", openedDoors.Select(d => (int)d.SNO + " - " + d.SNO))}";
+ }
+
+ [Command("near", "Activate all nearby doors in the vicinity. This is useful for testing purposes.\nUsage: !open near [distance:50]", Account.UserLevels.Tester)]
+ public string OpenAllDoorsNear(string[] @params, BattleClient invokerClient)
+ {
+ if (invokerClient?.InGameClient?.Player is not { } player)
+ return "You are not in game.";
+ var world = player.World;
+
+ var distance = 50f;
+
+ if (@params.Length > 0)
+ {
+ if (!float.TryParse(@params[0], out distance) || distance < 1)
+ return "Invalid distance. Distance must be greater than 1.";
+ }
+
+ var openedDoors = player.OpenNearDoors(distance);
+ if (openedDoors.Length == 0)
+ return "No doors found.";
+ return $"Opened {openedDoors.Count()} in a distance of {distance:0.0000} doors: {string.Join(", ", openedDoors)}";
+ }
+
+ [Command("info", "Retrieve all world doors in proximity, sorted in descending order.\nUsage: !open info [distance:50]", Account.UserLevels.Tester)]
+ public string InfoDoorsNear(string[] @params, BattleClient invokerClient)
+ {
+ if (invokerClient?.InGameClient?.Player is not { } player)
+ return "You are not in game.";
+ var world = player.World;
+ var distance = 50f;
+
+ if (@params.Length > 0)
+ {
+ if (!float.TryParse(@params[0], out distance) || distance < 1)
+ return "Invalid distance. Distance must be greater than 1.";
+ }
+
+ var doors = player.GetNearDoors(distance);
+ if (doors.Length == 0)
+ return "No doors found.";
+ return $"{doors.Length} doors in a distance of {distance:0.0000} doors: \n{string.Join("\n", doors.Select(s=>
+ {
+ var position = player.Position;
+ return s.Position.DistanceSquared(ref position) + " distance - [" + (int)s.SNO + "] " + s.SNO;;
+ }))}";
+ }
+
+ [DefaultCommand()]
+ public string DefaultCommand(string[] @params, BattleClient invokerClient)
+ {
+ return "!doors all - Activate all doors. This is useful for testing purposes.\n" +
+ "!doors near [distance:50] - Activate all nearby doors in the vicinity. This is useful for testing purposes.\n" +
+ "!doors info [distance:50] - Retrieve all world doors in proximity, sorted in descending order.";
+ }
+}
[CommandGroup("powerful", "Makes your character with absurd amount of damage. Useful for testing.",
Account.UserLevels.Tester)]
public class PowerfulCommand : CommandGroup
diff --git a/src/DiIiS-NA/D3-GameServer/Config.cs b/src/DiIiS-NA/D3-GameServer/Config.cs
index 9040f1f..dba074a 100644
--- a/src/DiIiS-NA/D3-GameServer/Config.cs
+++ b/src/DiIiS-NA/D3-GameServer/Config.cs
@@ -133,7 +133,25 @@ namespace DiIiS_NA.GameServer
get => GetInt(nameof(ResurrectionCharges), 3);
set => Set(nameof(ResurrectionCharges), value);
}
+
+ ///
+ /// Boss Health Multiplier
+ ///
+ public float BossHealthMultiplier
+ {
+ get => GetFloat(nameof(BossHealthMultiplier), 6f);
+ set => Set(nameof(BossHealthMultiplier), value);
+ }
+ ///
+ /// Boss Damage Multiplier
+ ///
+ public float BossDamageMultiplier
+ {
+ get => GetFloat(nameof(BossDamageMultiplier), 3f);
+ set => Set(nameof(BossDamageMultiplier), value);
+ }
+
public static Config Instance { get; } = new();
private Config() : base("Game-Server")
diff --git a/src/DiIiS-NA/D3-GameServer/Core/Types/Math/Vector3D.cs b/src/DiIiS-NA/D3-GameServer/Core/Types/Math/Vector3D.cs
index e581c84..9bcdc55 100644
--- a/src/DiIiS-NA/D3-GameServer/Core/Types/Math/Vector3D.cs
+++ b/src/DiIiS-NA/D3-GameServer/Core/Types/Math/Vector3D.cs
@@ -104,7 +104,7 @@ namespace DiIiS_NA.GameServer.Core.Types.Math
///
/// the second
/// the distance squared between the vectors
- public float DistanceSquared(ref Vector3D point)
+ public float DistanceSquared(ref Vector3D point) // todo: remove ref
{
float x = point.X - X,
y = point.Y - Y,
@@ -183,8 +183,6 @@ namespace DiIiS_NA.GameServer.Core.Types.Math
public override string ToString() => $"X:{X:F4}, Y:{Y:F4} Z:{Z:F4}";
- public bool IsNear(Vector3D other, float distance) => DistanceSquared(ref other) < distance * distance;
-
- public bool IsNearSquared(Vector3D other, float distanceSquared) => DistanceSquared(ref other) < distanceSquared;
+ public bool IsNear(Vector3D other, float distance) => DistanceSquared(ref other) < distance;
}
}
diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Implementations/Boss.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Implementations/Boss.cs
index f29dd16..fe4ea7b 100644
--- a/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Implementations/Boss.cs
+++ b/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Implementations/Boss.cs
@@ -69,6 +69,7 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem.Implementations
public sealed class Boss : Monster
{
private static readonly Logger Logger = LogManager.CreateLogger(nameof(Boss));
+
public Boss(MapSystem.World world, ActorSno sno, TagMap tags)
: base(world, sno, tags)
{
@@ -77,106 +78,113 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem.Implementations
//this.Attributes[GameAttribute.Immune_To_Charm] = true;
Attributes[GameAttribute.using_Bossbar] = true;
Attributes[GameAttribute.InBossEncounter] = true;
- Attributes[GameAttribute.Hitpoints_Max] *= 4f;
- Attributes[GameAttribute.Damage_Weapon_Min, 0] *= 3f;
- Attributes[GameAttribute.Damage_Weapon_Delta, 0] *= 3f;
+ Attributes[GameAttribute.Hitpoints_Max] *= Config.Instance.BossHealthMultiplier;
+ Attributes[GameAttribute.Damage_Weapon_Min, 0] *= Config.Instance.BossDamageMultiplier;
+ Attributes[GameAttribute.Damage_Weapon_Delta, 0] *= Config.Instance.BossDamageMultiplier;
Attributes[GameAttribute.Hitpoints_Cur] = Attributes[GameAttribute.Hitpoints_Max_Total];
Attributes[GameAttribute.TeamID] = 10;
-
+
WalkSpeed *= 0.5f;
- MonsterBrain monsterBrain = (Brain as MonsterBrain);
- switch (sno)
+ if (Brain is MonsterBrain monsterBrain)
{
- case ActorSno._diablo: //Diablo
- //(Brain as MonsterBrain).RemovePresetPower(30592);
- //(Brain as MonsterBrain).AddPresetPower(136189); //[136189] Diablo_ClawRip
- monsterBrain.AddPresetPower(136223); //Diablo_RingOfFire
- monsterBrain.AddPresetPower(136226); //Diablo_HellSpikes
- ;
+ switch (sno)
+ {
+ case ActorSno._diablo: //Diablo
+ //(Brain as MonsterBrain).RemovePresetPower(30592);
+ //(Brain as MonsterBrain).AddPresetPower(136189); //[136189] Diablo_ClawRip
+ monsterBrain.AddPresetPower(136223); //Diablo_RingOfFire
+ monsterBrain.AddPresetPower(136226); //Diablo_HellSpikes
+ ;
- /*
- [199476] Diablo_StompAndStun
- [219598] Diablo_Teleport
- [167560] Diablo_LightningBreath_v2
- [185997] Diablo_ExpandingFireRing
- [169212] Diablo_Smash_Puny_Destructible
- [136828] Diablo_CurseOfAnguish
- [136829] Diablo_CurseOfPain
- [136830] Diablo_CurseOfHate
- [136831] Diablo_CurseOfDestruction
-
- [439719] Diablo_LightningBreath_LR_TerrorDemon_Clone
- [214831] Diablo_FireMeteor
- [161174] Diablo_CorruptionShield
- [136219] Diablo_LightningBreath
- [136223] Diablo_RingOfFire
- [136226] Diablo_HellSpikes
-
- [214668] Diablo_GetHit
-
- [136237] Diablo_ShadowVanish
- [136281] Diablo_ShadowClones
- [142582] Diablo_ShadowVanish_Charge
- [136849] Diablo_ShadowVanish_Grab
-
- [141865] Diablo_Phase1Buff
- [136850] Diablo_Phase2Buff
- [136852] Diablo_Phase3Buff
- [478072] Diablo_StompAndStunMB313
-
- [478410] Diablo_LightningBreath_Turret_MB313
- [195816] Diablo_Charge
- [428985] Diablo_LightningBreath_LR_TerrorDemon
- [376396] Uber_Gluttony_Gas_Cloud_Diablo
- [375473] Uber_SkeletonKing_Summon_Skeleton_Diablo
- [375493] Uber_Maghda_Summon_Beserker_Diablo
- [365978] Uber_Diablo_StompAndStun
- [375537] Uber_Despair_SummonMinion_Diablo
- [375929] UberDiablo_MirrorImage
- [376039] Uber_Despair_TeleportEnrage_Diablo
- [376043] Uber_ZoltunKulle_SlowTime_Diablo
- [376056] Uber_Despair_Volley_Diablo
- [375439] x1_Uber_Diablo_HellSpikes
- [375904] Diablo_LightningBreath_Uber
- [375905] Diablo_ClawRip_Uber
- [375907] Diablo_RingOfFire_Uber
- [375908] Diablo_ExpandingFireRing_Uber
-
- [453765] p43_d1_Diablo_ClawRip
-
- [328715] x1_Malthael_Diablo_AIState
- [334760] x1_Malthael_Diablo_TeleportFireNovaLightning
-
-
- */
- break;
- case ActorSno._skeletonking://Leoric King
- monsterBrain.RemovePresetPower(30592);
- monsterBrain.AddPresetPower(30496);
- monsterBrain.AddPresetPower(30504);
- monsterBrain.AddPresetPower(73824);
- monsterBrain.AddPresetPower(79334);
- break;
- case ActorSno._butcher://Butcher
- monsterBrain.AddPresetPower(83008);
- break;
- case ActorSno._belial_trueform://Belial (small)
- HasLoot = false;
- break;
- case ActorSno._belial://Belial (big)
- monsterBrain.AddPresetPower(152540);
- break;
- case ActorSno._maghda://Maghda
- monsterBrain.AddPresetPower(131744); //summon berserker
- //(Brain as MonsterBrain).AddPresetPower(131745); //mothDust
- monsterBrain.AddPresetPower(131749); //teleport
- break;
- case ActorSno._gluttony://Gluttony
- monsterBrain.AddPresetPower(93676); //gas cloud
- monsterBrain.AddPresetPower(211292); //slime spawn
- break;
- default:
- break;
+ /*
+ [199476] Diablo_StompAndStun
+ [219598] Diablo_Teleport
+ [167560] Diablo_LightningBreath_v2
+ [185997] Diablo_ExpandingFireRing
+ [169212] Diablo_Smash_Puny_Destructible
+ [136828] Diablo_CurseOfAnguish
+ [136829] Diablo_CurseOfPain
+ [136830] Diablo_CurseOfHate
+ [136831] Diablo_CurseOfDestruction
+
+ [439719] Diablo_LightningBreath_LR_TerrorDemon_Clone
+ [214831] Diablo_FireMeteor
+ [161174] Diablo_CorruptionShield
+ [136219] Diablo_LightningBreath
+ [136223] Diablo_RingOfFire
+ [136226] Diablo_HellSpikes
+
+ [214668] Diablo_GetHit
+
+ [136237] Diablo_ShadowVanish
+ [136281] Diablo_ShadowClones
+ [142582] Diablo_ShadowVanish_Charge
+ [136849] Diablo_ShadowVanish_Grab
+
+ [141865] Diablo_Phase1Buff
+ [136850] Diablo_Phase2Buff
+ [136852] Diablo_Phase3Buff
+ [478072] Diablo_StompAndStunMB313
+
+ [478410] Diablo_LightningBreath_Turret_MB313
+ [195816] Diablo_Charge
+ [428985] Diablo_LightningBreath_LR_TerrorDemon
+ [376396] Uber_Gluttony_Gas_Cloud_Diablo
+ [375473] Uber_SkeletonKing_Summon_Skeleton_Diablo
+ [375493] Uber_Maghda_Summon_Beserker_Diablo
+ [365978] Uber_Diablo_StompAndStun
+ [375537] Uber_Despair_SummonMinion_Diablo
+ [375929] UberDiablo_MirrorImage
+ [376039] Uber_Despair_TeleportEnrage_Diablo
+ [376043] Uber_ZoltunKulle_SlowTime_Diablo
+ [376056] Uber_Despair_Volley_Diablo
+ [375439] x1_Uber_Diablo_HellSpikes
+ [375904] Diablo_LightningBreath_Uber
+ [375905] Diablo_ClawRip_Uber
+ [375907] Diablo_RingOfFire_Uber
+ [375908] Diablo_ExpandingFireRing_Uber
+
+ [453765] p43_d1_Diablo_ClawRip
+
+ [328715] x1_Malthael_Diablo_AIState
+ [334760] x1_Malthael_Diablo_TeleportFireNovaLightning
+
+
+ */
+ break;
+ case ActorSno._skeletonking: //Leoric King
+ monsterBrain.RemovePresetPower(30592);
+ monsterBrain.AddPresetPower(30496);
+ monsterBrain.AddPresetPower(30504);
+ monsterBrain.AddPresetPower(73824);
+ monsterBrain.AddPresetPower(79334);
+ break;
+ case ActorSno._butcher: //Butcher
+ monsterBrain.AddPresetPower(83008);
+ break;
+ case ActorSno._belial_trueform: //Belial (small)
+ HasLoot = false;
+ break;
+ case ActorSno._belial: //Belial (big)
+ monsterBrain.AddPresetPower(152540);
+ break;
+ case ActorSno._maghda: //Maghda
+ monsterBrain.AddPresetPower(131744); //summon berserker
+ //(Brain as MonsterBrain).AddPresetPower(131745); //mothDust
+ monsterBrain.AddPresetPower(131749); //teleport
+ break;
+ case ActorSno._gluttony: //Gluttony
+ monsterBrain.AddPresetPower(93676); //gas cloud
+ monsterBrain.AddPresetPower(211292); //slime spawn
+ break;
+ default:
+ Logger.Warn($"Unhandled boss type {sno}");
+ break;
+ }
+ }
+ else
+ {
+ Logger.Error($"Boss $[underline red]${GetType().Name}$[/]$ ({sno}) has no monster brain!");
}
}
diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Implementations/Door.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Implementations/Door.cs
index 3bf4ada..4eca667 100644
--- a/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Implementations/Door.cs
+++ b/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Implementations/Door.cs
@@ -16,7 +16,7 @@ using System.Threading.Tasks;
namespace DiIiS_NA.GameServer.GSSystem.ActorSystem.Implementations
{
[HandledSNO(ActorSno._caout_stingingwinds_khamsin_gate)]
- class Door : Gizmo
+ public class Door : Gizmo
{
public bool isOpened = false;
public Portal NearestPortal = null;
@@ -75,12 +75,13 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem.Implementations
public void Open()
{
+ Logger.MethodTrace($"Opening door $[underline green]${SNO}$[/]$ in world $[underline green]{World.SNO}$[/]$");
World.BroadcastIfRevealed(plr => new PlayAnimationMessage
{
ActorID = DynamicID(plr),
AnimReason = 5,
UnitAniimStartTime = 0,
- tAnim = new PlayAnimationMessageSpec[]
+ tAnim = new[]
{
new PlayAnimationMessageSpec()
{
@@ -115,8 +116,8 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem.Implementations
TickerSystem.TickTimer Timeout = new TickerSystem.SecondsTickTimer(World.Game, 1.8f);
if (NearestPortal != null)
{
- var Boom = Task.Factory.StartNew(() => WaitToSpawn(Timeout));
- Boom.ContinueWith(delegate
+ var nearestPortalOpen = Task.Factory.StartNew(() => WaitToSpawn(Timeout));
+ nearestPortalOpen.ContinueWith(delegate
{
NearestPortal.SetVisible(true);
foreach (var plr in World.Players.Values)
diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/MapSystem/World.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/MapSystem/World.cs
index 9b274c1..a2e744b 100644
--- a/src/DiIiS-NA/D3-GameServer/GSSystem/MapSystem/World.cs
+++ b/src/DiIiS-NA/D3-GameServer/GSSystem/MapSystem/World.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
+using System.Collections.Immutable;
using System.Drawing;
using System.Linq;
using System.Reflection;
@@ -1495,5 +1496,21 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
{
return $"[World] SNOId: {WorldSNO.Id} GlobalId: {GlobalID} Name: {WorldSNO.Name}";
}
+
+ public ImmutableArray GetAllDoors() =>
+ Actors.Select(a => a.Value).Where(a => a is Door).Cast().ToImmutableArray();
+ public ImmutableArray OpenAllDoors()
+ {
+ List openedDoors = new();
+ var doors = GetAllDoors();
+
+ foreach (var door in doors)
+ {
+ openedDoors.Add(door);
+ door.Open();
+ }
+
+ return openedDoors.ToImmutableArray();
+ }
}
}
diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/PlayerSystem/Player.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/PlayerSystem/Player.cs
index 45cd36c..2df5cf3 100644
--- a/src/DiIiS-NA/D3-GameServer/GSSystem/PlayerSystem/Player.cs
+++ b/src/DiIiS-NA/D3-GameServer/GSSystem/PlayerSystem/Player.cs
@@ -3,6 +3,7 @@
using System;
//Blizzless Project 2022
using System.Collections.Generic;
+using System.Collections.Immutable;
//Blizzless Project 2022
using System.Linq;
//Blizzless Project 2022
@@ -6181,4 +6182,23 @@ public class Player : Actor, IMessageConsumer, IUpdateable
Attributes[GameAttribute.Hitpoints_Total_From_Level] = Attributes[GameAttribute.Hitpoints_Max_Total];
Attributes.BroadcastChangedIfRevealed();
}
+
+ public ImmutableArray GetNearDoors(float distance = 50f)
+ {
+ var doors = World.GetAllDoors();
+ List doorList = doors.Where(door => door.Position.IsNear(Position, distance)).ToList();
+ return doorList.ToImmutableArray();
+ }
+
+ public ImmutableArray OpenNearDoors(float distance = 50f)
+ {
+ List openedDoors = new();
+ foreach (var door in GetNearDoors(distance))
+ {
+ openedDoors.Add(door);
+ door.Open();
+ }
+
+ return openedDoors.ToImmutableArray();
+ }
}
\ No newline at end of file
diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/QuestSystem/ActI.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/QuestSystem/ActI.cs
index b7e7361..8373087 100644
--- a/src/DiIiS-NA/D3-GameServer/GSSystem/QuestSystem/ActI.cs
+++ b/src/DiIiS-NA/D3-GameServer/GSSystem/QuestSystem/ActI.cs
@@ -1070,7 +1070,7 @@ namespace DiIiS_NA.GameServer.GSSystem.QuestSystem
});
- ListenKill(ActorSno._skeletonking_shield_skeleton, 4, new Advance());
+ ListenKill(ActorSno._skeletonking_shield_skeleton, 1, new Advance());
}
});
@@ -1082,11 +1082,8 @@ namespace DiIiS_NA.GameServer.GSSystem.QuestSystem
Objectives = new List { Objective.Default() },
OnAdvance = () =>
{ //take crown on Leoric's head
- Game.AddOnLoadWorldAction(WorldSno.a1trdun_king_level08, () =>
- {
- Open(Game.GetWorld(WorldSno.a1trdun_king_level08), ActorSno._trdun_cath_gate_b_skeletonking);
- });
- //Open(this.Game.GetWorld(73261), 172645);
+
+ OpenAll(this.Game.GetWorld(WorldSno.a1trdun_king_level08));
ListenInteract(ActorSno._skeletonkinggizmo, 1, new Advance());
}
});
@@ -1111,6 +1108,7 @@ namespace DiIiS_NA.GameServer.GSSystem.QuestSystem
Objectives = new List { Objective.Default() },
OnAdvance = () =>
{ //go to fallen star room
+ Open(Game.GetWorld(WorldSno.a1trdun_king_level08), ActorSno._trdun_cath_gate_b_skeletonking);
Game.CurrentEncounter.Activated = false;
ListenTeleport(117411, new Advance());
Game.AddOnLoadWorldAction(WorldSno.a1trdun_king_level08, () =>
diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/QuestSystem/QuestProgress.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/QuestSystem/QuestProgress.cs
index 031ce79..c1ea0a0 100644
--- a/src/DiIiS-NA/D3-GameServer/GSSystem/QuestSystem/QuestProgress.cs
+++ b/src/DiIiS-NA/D3-GameServer/GSSystem/QuestSystem/QuestProgress.cs
@@ -181,6 +181,13 @@ namespace DiIiS_NA.GameServer.GSSystem.QuestSystem
(actor as Door).Open();
return true;
}
+
+ //opening all doors
+ protected void OpenAll(World world)
+ {
+ foreach (var actor in world.Actors.Select(s=>s.Value).Where(t=>t is Door).Cast())
+ (actor).Open();
+ }
protected bool OpenAll(World world, ActorSno sno)
{