Changelog:

GameServerConfig.cs and Player.cs:
- StrengthMultiplier / StrengthParagonMultipler
- DexterityMultiplier / DexterityParagonMultiplier
- IntelligenceMultiplier / IntelligenceParagonMultiplier
- VitalityMultiplier / VitalityParagonMultiplier
CommandManager.cs and CommandsConfig.cs:
- Added a command group disable parameter (DisabledGroups). A ranking system should be added later on.
RestSession.cs and Http.cs:
- Added battlenet login POST and GET;
- If no page is found on DEBUG, it returns 502 (Bad GW - if on NAT it could be useful for stopping bots of retrying connection with the server) otherwise returns 404
Others:
!drop minor changes
Cleanups
This commit is contained in:
Lucca Faria Ferri 2023-02-09 21:22:41 -08:00
parent 3d123f409f
commit 6657f17730
22 changed files with 696 additions and 630 deletions

View File

@ -107,7 +107,7 @@ namespace DiIiS_NA.Core.Logging
{
#if DEBUG
var fileName = Path.GetFileName(filePath);
Log(Level.MethodTrace, $"$[underline white]${fileName}:{lineNumber}$[/]$ $[darkolivegreen3_2]${methodName}()$[/]$: $[black on white]$" + message + "$[/]$", null);
Log(Level.MethodTrace, $"$[underline white]${fileName}:{lineNumber}$[/]$ $[darkolivegreen3_2]${methodName}()$[/]$: " + message, null);
#else
Log(Level.MethodTrace, $"$[darkolivegreen3_2]${methodName}()$[/]$: " + message, null);
#endif

View File

@ -13,23 +13,17 @@ namespace DiIiS_NA.Core.Storage
private static Object _globalSessionLock = new object();
private Object _sessionLock = new object();
private IStatelessSession _gameSession = null;
private readonly Logger Logger = LogManager.CreateLogger("DB");
private readonly Logger Logger = LogManager.CreateLogger(nameof(GameDBSession));
public GameDBSession()
{
lock (_globalSessionLock)
{
this._gameSession = AccountDataBase.SessionProvider.SessionFactory.OpenStatelessSession();
_gameSession = AccountDataBase.SessionProvider.SessionFactory.OpenStatelessSession();
}
}
private IStatelessSession GameSession
{
get
{
return this._gameSession;
}
}
private IStatelessSession GameSession => _gameSession;
public void SessionSave(Object obj)
{
@ -39,7 +33,7 @@ namespace DiIiS_NA.Core.Storage
{
try
{
using (IStatelessSession session = AccountDataBase.SessionProvider.SessionFactory.OpenStatelessSession())
using IStatelessSession session = AccountDataBase.SessionProvider.SessionFactory.OpenStatelessSession();
session.Insert(obj);
}
catch (Exception e)
@ -74,7 +68,7 @@ namespace DiIiS_NA.Core.Storage
{
try
{
using (IStatelessSession session = AccountDataBase.SessionProvider.SessionFactory.OpenStatelessSession())
using IStatelessSession session = AccountDataBase.SessionProvider.SessionFactory.OpenStatelessSession();
session.Update(obj);
}
catch (Exception e)
@ -109,7 +103,7 @@ namespace DiIiS_NA.Core.Storage
{
try
{
using (IStatelessSession session = AccountDataBase.SessionProvider.SessionFactory.OpenStatelessSession())
using IStatelessSession session = AccountDataBase.SessionProvider.SessionFactory.OpenStatelessSession();
session.Delete(obj);
}
catch (Exception e)
@ -157,7 +151,7 @@ namespace DiIiS_NA.Core.Storage
{
try
{
using (IStatelessSession session = AccountDataBase.SessionProvider.SessionFactory.OpenStatelessSession())
using IStatelessSession session = AccountDataBase.SessionProvider.SessionFactory.OpenStatelessSession();
return session.Query<T>().ToList();
}
catch (Exception e)
@ -189,7 +183,7 @@ namespace DiIiS_NA.Core.Storage
{
try
{
using (IStatelessSession session = AccountDataBase.SessionProvider.SessionFactory.OpenStatelessSession())
using IStatelessSession session = AccountDataBase.SessionProvider.SessionFactory.OpenStatelessSession();
return session.QueryOver<T>().Where(predicate).List().ToList();
}
catch (Exception e)
@ -221,7 +215,7 @@ namespace DiIiS_NA.Core.Storage
{
try
{
using (IStatelessSession session = AccountDataBase.SessionProvider.SessionFactory.OpenStatelessSession())
using IStatelessSession session = AccountDataBase.SessionProvider.SessionFactory.OpenStatelessSession();
return (T)session.QueryOver<T>().Where(predicate).List().FirstOrDefault();
}
catch (Exception e)

View File

@ -24,18 +24,29 @@ namespace DiIiS_NA.GameServer.CommandManager
foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
{
if (!type.IsSubclassOf(typeof(CommandGroup))) continue;
var attributes = (CommandGroupAttribute[])type.GetCustomAttributes(typeof(CommandGroupAttribute), true);
if (attributes.Length == 0) continue;
var groupAttribute = attributes[0];
if (groupAttribute.Name == null) continue;
if (CommandsConfig.Instance.DisabledGroupsData.Contains(groupAttribute.Name))
{
Logger.Trace($"Command group {groupAttribute.Name} is disabled.");
continue;
}
if (CommandGroups.ContainsKey(groupAttribute))
Logger.Warn("There exists an already registered command group named '{0}'.", groupAttribute.Name);
var commandGroup = (CommandGroup)Activator.CreateInstance(type);
if (commandGroup != null)
{
commandGroup.Register(groupAttribute);
CommandGroups.Add(groupAttribute, commandGroup);
}
else
{
Logger.Warn("Failed to create an instance of command group '{0}'.", groupAttribute.Name);
}
}
}
/// <summary>

View File

@ -4,8 +4,7 @@ using DiIiS_NA.LoginServer.Battle;
namespace DiIiS_NA.GameServer.CommandManager;
[CommandGroup("drop", "Drops an epic item for your class.\nOptionally specify the number of items: !drop [1-20]",
Account.UserLevels.Owner)]
[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]
@ -29,16 +28,16 @@ public class DropCommand : CommandGroup
try
{
for (var i = 0; i < amount; i++)
player.World.SpawnRandomEquip(player, player, 11, player.Level, toonClass: player.Toon.Class,
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,
player.World.SpawnRandomEquip(player, player, 8, /*player.Level,*/ toonClass: player.Toon.Class,
canBeUnidentified: false);
}
return $"Dropped {amount} random equipment.";
return $"Dropped {amount} random epic equipment.";
}
}

View File

@ -14,7 +14,19 @@ namespace DiIiS_NA.GameServer.CommandManager
set => Set(nameof(CommandPrefix), value);
}
public static CommandsConfig Instance = new();
public string DisabledGroups
{
get => GetString(nameof(DisabledGroups), "");
set => Set(nameof(DisabledGroups), value);
}
public string[] DisabledGroupsData
=> DisabledGroups
.Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)
.Select(s=>s.Replace(CommandPrefix.ToString(), ""))
.ToArray();
public static readonly CommandsConfig Instance = new();
private CommandsConfig() : base("Commands") { }
}
}

View File

@ -113,41 +113,24 @@ namespace DiIiS_NA.GameServer.Core.Types.Math
return ((x * x) + (y * y)) + (z * z);
}
public static bool operator ==(Vector3D a, Vector3D b)
{
if (ReferenceEquals(null, a))
return ReferenceEquals(null, b);
return a.Equals(b);
}
public static bool operator ==(Vector3D a, Vector3D b) => a?.Equals(b) ?? ReferenceEquals(null, b);
public static bool operator !=(Vector3D a, Vector3D b)
{
return !(a == b);
}
public static bool operator !=(Vector3D a, Vector3D b) => !(a == b);
public static bool operator >(Vector3D a, Vector3D b)
{
if (ReferenceEquals(null, a))
return !ReferenceEquals(null, b);
return a.X > b.X
return ReferenceEquals(null, a)
? !ReferenceEquals(null, b)
: a.X > b.X
&& a.Y > b.Y
&& a.Z > b.Z;
}
public static Vector3D operator +(Vector3D a, Vector3D b)
{
return new Vector3D(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
}
public static Vector3D operator +(Vector3D a, Vector3D b) => new Vector3D(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
public static Vector3D operator -(Vector3D a, Vector3D b)
{
return new Vector3D(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
}
public static Vector3D operator -(Vector3D a, Vector3D b) => new Vector3D(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
public static bool operator <(Vector3D a, Vector3D b)
{
return !(a > b);
}
public static bool operator <(Vector3D a, Vector3D b) => !(a > b);
public static bool operator >=(Vector3D a, Vector3D b)
{
@ -174,9 +157,9 @@ namespace DiIiS_NA.GameServer.Core.Types.Math
var v = o as Vector3D;
if (v != null)
{
return System.Math.Abs(X - v.X) < 0.0001
&& System.Math.Abs(Y - v.Y) < 0.0001
&& System.Math.Abs(Z - v.Z) < 0.0001;
return System.Math.Abs(X - v.X) < Globals.FLOAT_TOLERANCE
&& System.Math.Abs(Y - v.Y) < Globals.FLOAT_TOLERANCE
&& System.Math.Abs(Z - v.Z) < Globals.FLOAT_TOLERANCE;
}
return false;
}

View File

@ -20690,7 +20690,7 @@ namespace DiIiS_NA.D3_GameServer.Core.Types.SNO
ActorSno._p73_fallenlunatic_a_nonspawner,
};
// all '_vo' and 'voiceo' actors except 'voodoomask` and and cosmetic pets
private static readonly ActorSno[] soundActors = new ActorSno[]
private static readonly ActorSno[] _soundActors = new ActorSno[]
{
ActorSno._lustmissle_volume,
ActorSno._a1dun_caves_nephalem_altar_volume,
@ -20713,7 +20713,7 @@ namespace DiIiS_NA.D3_GameServer.Core.Types.SNO
ActorSno._p43_ad_valor_bloodstone_volume,
};
// all 'door' actors
private static readonly ActorSno[] doors = new ActorSno[]
private static readonly ActorSno[] _doors = new ActorSno[]
{
ActorSno._trdun_cath_wooddoor_a,
ActorSno._door_intactc_caout_towns,
@ -21156,7 +21156,7 @@ namespace DiIiS_NA.D3_GameServer.Core.Types.SNO
ActorSno._kanai_cube_uber_fx,
};
// all 'adventuremode' actors
private static readonly ActorSno[] adventureModeActors = new ActorSno[]
private static readonly ActorSno[] AdventureModeActors = new ActorSno[]
{
ActorSno._x1_lore_adventuremode_zknephalem,
ActorSno._x1_lore_adventuremode_zkplans,
@ -21168,7 +21168,7 @@ namespace DiIiS_NA.D3_GameServer.Core.Types.SNO
ActorSno._x1_adventuremode_hubbantertrigger,
};
#endregion
public static readonly ActorSno[] nephalemPortalBosses = new ActorSno[]
public static readonly ActorSno[] NephalemPortalBosses = new ActorSno[]
{
ActorSno._x1_lr_boss_mistressofpain,
ActorSno._x1_lr_boss_angel_corrupt_a,
@ -21227,17 +21227,17 @@ namespace DiIiS_NA.D3_GameServer.Core.Types.SNO
public static bool IsAdventureModeActor(this ActorSno actorSno)
{
return adventureModeActors.Contains(actorSno);
return AdventureModeActors.Contains(actorSno);
}
public static bool IsTargetable(this ActorSno actorSno)
{
return !spawners.Contains(actorSno) && !soundActors.Contains(actorSno);
return !spawners.Contains(actorSno) && !_soundActors.Contains(actorSno);
}
public static bool IsDoorOrBarricade(this ActorSno actorSno)
{
return doors.Contains(actorSno) || barricades.Contains(actorSno);
return _doors.Contains(actorSno) || barricades.Contains(actorSno);
}
public static bool IsWoodwraithOrWasp(this ActorSno actorSno)

View File

@ -50,11 +50,5 @@ namespace DiIiS_NA.D3_GameServer.GSSystem.ActorSystem.Implementations.Artisans
base.OnCraft(player);
player.CurrentArtisan = ArtisanType.Nephalem;
}
public override bool Reveal(Player player)
{
return base.Reveal(player);
}
}
}

View File

@ -88,7 +88,7 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem
public void UpdateStats()
{
var monsterLevels = (GameBalance)DiIiS_NA.Core.MPQ.MPQStorage.Data.Assets[SNOGroup.GameBalance][19760].Data;
bool fullHp = (Math.Abs(Attributes[GameAttribute.Hitpoints_Cur] - Attributes[GameAttribute.Hitpoints_Max_Total]) < 0.001);
bool fullHp = (Math.Abs(Attributes[GameAttribute.Hitpoints_Cur] - Attributes[GameAttribute.Hitpoints_Max_Total]) < Globals.FLOAT_TOLERANCE);
Attributes[GameAttribute.Level] = World.Game.MonsterLevel;
//this.Attributes[GameAttribute.Hitpoints_Max] = (int)monsterLevels.MonsterLevel[this.World.Game.MonsterLevel - 1].HPMin * (int)this.HPMultiplier * (int)this.World.Game.HPModifier;
int monsterLevel = 1;

View File

@ -1256,7 +1256,7 @@ namespace DiIiS_NA.GameServer.GSSystem.GameSystem
GameAccountId = new GameAccountHandle() { ID = (uint)joinedPlayer.Toon.GameAccount.BnetEntityId.Low, Program = 0x00004433, Region = 1 },
ToonName = joinedPlayer.Toon.Name,
Team = 0x00000002,
Class = joinedPlayer.ClassSNO,
Class = joinedPlayer.ClassSno,
snoActorPortrait = joinedPlayer.Toon.DBToon.Cosmetic4,
Level = joinedPlayer.Toon.Level,
AltLevel = (ushort)joinedPlayer.Toon.ParagonLevel,

View File

@ -386,8 +386,8 @@ namespace DiIiS_NA.GameServer.GSSystem.GeneratorsSystem
RandomSpawnInWorldWithLevelArea(world, ActorSno._x1_deathmaiden_unique_fire_a);
break;
case WorldSno.trdun_leoric_level03: //Setting portal to the third floor of the Agony's Halls near the entrance to the Butcher.
Vector3D Scene0Pos = world.GetSceneBySnoId(78824).Position;
world.SpawnMonster(ActorSno._waypoint, new Vector3D(Scene0Pos.X + 149.0907f, Scene0Pos.Y + 106.7075f, Scene0Pos.Z));
Vector3D sceneOfPos = world.GetSceneBySnoId(78824).Position;
world.SpawnMonster(ActorSno._waypoint, new Vector3D(sceneOfPos.X + 149.0907f, sceneOfPos.Y + 106.7075f, sceneOfPos.Z));
break;
case WorldSno.x1_westm_graveyard_deathorb:
FilterWaypoints(world);
@ -402,9 +402,9 @@ namespace DiIiS_NA.GameServer.GSSystem.GeneratorsSystem
break;
case WorldSno.trout_town: //mercenary
var templar = world.GetActorBySNO(ActorSno._templar);
var hasmalth = world.GetActorBySNO(ActorSno._x1_malthael_npc);
var hasMalthaelNpc = world.GetActorBySNO(ActorSno._x1_malthael_npc);
if (hasmalth == null)
if (hasMalthaelNpc == null)
{
ActorSystem.Implementations.Hirelings.MalthaelHireling malthaelHire = new ActorSystem.Implementations.Hirelings.MalthaelHireling(world, ActorSno._x1_malthael_npc_nocollision, templar.Tags)
{
@ -419,17 +419,17 @@ namespace DiIiS_NA.GameServer.GSSystem.GeneratorsSystem
}
foreach (var door in world.GetActorsBySNO(ActorSno._house_door_trout_newtristram))
door.Destroy();
if (Game.CurrentAct == 3000)
if (Game.CurrentActEnum == ActEnum.OpenWorld)
{
var TownDoor = world.GetActorBySNO(ActorSno._trout_newtristram_gate_town);
TownDoor.Attributes[GameAttribute.Team_Override] = 2;
TownDoor.Attributes[GameAttribute.Untargetable] = true;
TownDoor.Attributes[GameAttribute.NPC_Is_Operatable] = false;
TownDoor.Attributes[GameAttribute.Operatable] = false;
TownDoor.Attributes[GameAttribute.Operatable_Story_Gizmo] = false;
TownDoor.Attributes[GameAttribute.Disabled] = true;
TownDoor.Attributes[GameAttribute.Immunity] = true;
TownDoor.Attributes.BroadcastChangedIfRevealed();
var townDoor = world.GetActorBySNO(ActorSno._trout_newtristram_gate_town);
townDoor.Attributes[GameAttribute.Team_Override] = 2;
townDoor.Attributes[GameAttribute.Untargetable] = true;
townDoor.Attributes[GameAttribute.NPC_Is_Operatable] = false;
townDoor.Attributes[GameAttribute.Operatable] = false;
townDoor.Attributes[GameAttribute.Operatable_Story_Gizmo] = false;
townDoor.Attributes[GameAttribute.Disabled] = true;
townDoor.Attributes[GameAttribute.Immunity] = true;
townDoor.Attributes.BroadcastChangedIfRevealed();
}
break;
case WorldSno.a1trdun_level04: //Cathedral Level 2
@ -504,10 +504,12 @@ namespace DiIiS_NA.GameServer.GSSystem.GeneratorsSystem
zoltunGhost.Attributes.BroadcastChangedIfRevealed();
break;
case WorldSno.a3dun_ruins_frost_city_a_02:
foreach (var waypoint in world.GetActorsBySNO(ActorSno._waypoint)) waypoint.Destroy();
foreach (var waypoint in world.GetActorsBySNO(ActorSno._waypoint))
waypoint.Destroy();
break;
case WorldSno.p43_ad_oldtristram:
foreach (var waypoint in world.GetActorsBySNO(ActorSno._trout_oldtristram_exit_gate)) waypoint.Destroy();
foreach (var waypoint in world.GetActorsBySNO(ActorSno._trout_oldtristram_exit_gate))
waypoint.Destroy();
break;
case WorldSno.x1_tristram_adventure_mode_hub:
@ -561,14 +563,15 @@ namespace DiIiS_NA.GameServer.GSSystem.GeneratorsSystem
public void RandomSpawnInWorldWithLevelArea(World world, ActorSno monsterSno, int levelArea = -1)
{
List<Scene> scenes = world.Scenes.Values.ToList();
if (levelArea != -1) scenes = scenes.Where(sc => sc.Specification.SNOLevelAreas[0] == levelArea && !sc.SceneSNO.Name.ToLower().Contains("filler")).ToList();
else scenes = scenes.Where(sc => !sc.SceneSNO.Name.ToLower().Contains("filler")).ToList();
Vector3D SSV = scenes.PickRandom().Position;
scenes = levelArea != -1
? scenes.Where(sc => sc.Specification.SNOLevelAreas[0] == levelArea && !sc.SceneSNO.Name.ToLower().Contains("filler")).ToList()
: scenes.Where(sc => !sc.SceneSNO.Name.ToLower().Contains("filler")).ToList();
Vector3D randomScene = scenes.PickRandom().Position;
Vector3D startingPoint = null;
while (true)
{
startingPoint = new Vector3D(SSV.X + RandomHelper.Next(0, 240), SSV.Y + RandomHelper.Next(0, 240), SSV.Z);
startingPoint = new Vector3D(randomScene.X + RandomHelper.Next(0, 240), randomScene.Y + RandomHelper.Next(0, 240), randomScene.Z);
if (world.CheckLocationForFlag(startingPoint, DiIiS_NA.Core.MPQ.FileFormats.Scene.NavCellFlags.AllowWalk))
break;
}
@ -1591,7 +1594,7 @@ namespace DiIiS_NA.GameServer.GSSystem.GeneratorsSystem
{
bool busy = false;
foreach (var chunk in world.worldData.SceneParams.SceneChunks)
if (Math.Abs(chunk.PRTransform.Vector3D.X - x) < 0.001 & Math.Abs(chunk.PRTransform.Vector3D.Y - y) < 0.001)
if (Math.Abs(chunk.PRTransform.Vector3D.X - x) < Globals.FLOAT_TOLERANCE & Math.Abs(chunk.PRTransform.Vector3D.Y - y) < Globals.FLOAT_TOLERANCE)
{
busy = true;
break;

View File

@ -552,8 +552,7 @@ namespace DiIiS_NA.GameServer.GSSystem.ItemsSystem
if (ratio > 1f) ratio = 1f;
Attributes[GameAttribute.Block_Amount_Item_Min] +=
Math.Abs(scaleCapMin * ratio - Attributes[GameAttribute.Block_Amount_Item_Min, 0]);
Attributes[GameAttribute.Block_Amount_Item_Delta] += Math.Abs(scaleCapDelta * ratio -
Attributes[GameAttribute.Block_Amount_Item_Delta, 0]);
Attributes[GameAttribute.Block_Amount_Item_Delta] += Math.Abs(scaleCapDelta * ratio - Attributes[GameAttribute.Block_Amount_Item_Delta, 0]);
}
}
}

View File

@ -590,16 +590,13 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
public Actor SpawnMonster(ActorSno monsterSno, Vector3D position)
{
if (monsterSno == ActorSno.__NONE)
{
return null;
}
if (monsterSno == ActorSno.__NONE) return null;
Logger.MethodTrace($"Spawning monster {monsterSno} at {position}");
var monster = ActorFactory.Create(this, monsterSno, new TagMap());
if (monster != null)
{
if (monster == null) return null;
monster.EnterWorld(position);
if (monster.AnimationSet != null)
{
if (monster.AnimationSet == null) return monster;
var animationTag = new[] { AnimationSetKeys.Spawn, AnimationSetKeys.Spawn2 }.FirstOrDefault(x => monster.AnimationSet.TagMapAnimDefault.ContainsKey(x));
if (animationTag != null)
@ -622,8 +619,6 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
}, monster);
}
}
}
return monster;
}
@ -640,19 +635,21 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
player.GroundItems[item.GlobalID] = item; // FIXME: Hacky. /komiga
DropItem(source, null, item);
}
public void PlayPieAnimation(Actor actor, Actor User, int PowerSNO, Vector3D TargetPosition)
[Obsolete("Isn't used anymore. Is it useful?")]
public void PlayPieAnimation(Actor actor, Actor user, int powerSNO, Vector3D targetPosition)
{
BroadcastIfRevealed(plr => new ACDTranslateDetPathPieWedgeMessage
{
ann = (int)actor.DynamicID(plr),
StartPos = User.Position,
FirstTagetPos = User.Position,
StartPos = user.Position,
FirstTagetPos = user.Position,
MoveFlags = 9,
AnimTag = 1,
PieData = new DPathPieData
{
Field0 = TargetPosition,
Field0 = targetPosition,
Field1 = 1,
Field2 = 1,
Field3 = 1

View File

@ -2395,7 +2395,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
var rem = new List<uint>();
foreach (var fol in Followers.Where(f =>
Math.Abs(World.GetActorByGlobalId(f.Key).Attributes[GameAttribute.Summoned_By_SNO] -
oldSNOSkill) < 0.001))
oldSNOSkill) < Globals.FLOAT_TOLERANCE))
rem.Add(fol.Key);
foreach (var rm in rem)
DestroyFollowerById(rm);
@ -2914,13 +2914,13 @@ public class Player : Actor, IMessageConsumer, IUpdateable
//*
private void TrainArtisan(GameClient client, RequestTrainArtisanMessage message)
{
if (CurrentArtisan == null || !artisanTrainHelpers.ContainsKey(CurrentArtisan.Value))
if (CurrentArtisan == null || !_artisanTrainHelpers.ContainsKey(CurrentArtisan.Value))
{
Logger.Warn("Training for artisan {} is not supported", CurrentArtisan);
return;
}
var trainHelper = artisanTrainHelpers[CurrentArtisan.Value];
var trainHelper = _artisanTrainHelpers[CurrentArtisan.Value];
if (trainHelper.HasMaxLevel)
return;
@ -2947,7 +2947,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
if (trainHelper.Criteria is not null)
GrantCriteria(trainHelper.Criteria.Value);
if (artisanTrainHelpers.All(x => x.Value.HasMaxLevel))
if (_artisanTrainHelpers.All(x => x.Value.HasMaxLevel))
GrantCriteria(74987249993545);
client.SendMessage(new CrafterLevelUpMessage
@ -2966,13 +2966,13 @@ public class Player : Actor, IMessageConsumer, IUpdateable
public void UnlockTransmog(int transmogGBID)
{
if (learnedTransmogs.Contains(transmogGBID)) return;
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);
_learnedTransmogs.Add(transmogGBID);
_mysticData.LearnedRecipes = SerializeBytes(_learnedTransmogs);
World.Game.GameDbSession.SessionUpdate(_mysticData);
LoadCrafterData();
}
@ -3067,7 +3067,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
foreach (var timed_out in TimedActions.Where(t => t.TimedOut).ToList())
TimedActions.Remove(timed_out);
// Check the Killstreaks
// Check the kill streaks
ExpBonusData.Check(0);
ExpBonusData.Check(1);
@ -3165,27 +3165,29 @@ public class Player : Actor, IMessageConsumer, IUpdateable
#region Necromancer summons
var switchertobool = false;
var switchertoboolTwo = false;
ActiveSkillSavedData NowSkillGolem = null;
var switcherToBool = false;
var switcherToBool2 = false;
ActiveSkillSavedData nowSkillGolen = null;
foreach (var skill in SkillSet.ActiveSkills)
if (skill.snoSkill == 453801)
switchertobool = true;
switcherToBool = true;
foreach (var skill in SkillSet.ActiveSkills)
if (skill.snoSkill == 451537)
{
switchertoboolTwo = true;
NowSkillGolem = skill;
switcherToBool2 = true;
nowSkillGolen = skill;
}
ActiveSkeletons = switchertobool;
EnableGolem = switchertoboolTwo;
ActiveSkeletons = switcherToBool;
EnableGolem = switcherToBool2;
var Killer = new PowerContext();
Killer.User = this;
Killer.World = World;
Killer.PowerSNO = -1;
var killer = new PowerContext
{
User = this,
World = World,
PowerSNO = -1
};
if (ActiveSkeletons)
{
@ -3255,8 +3257,8 @@ public class Player : Actor, IMessageConsumer, IUpdateable
{
PetId = ActiveGolem.GlobalID
});
Killer.Target = ActiveGolem;
(ActiveGolem as Minion).Kill(Killer);
killer.Target = ActiveGolem;
(ActiveGolem as Minion).Kill(killer);
}
ActiveGolem = null;
@ -3386,20 +3388,14 @@ public class Player : Actor, IMessageConsumer, IUpdateable
#endregion
public T RuneSelect<T>(int PowerSNO, T none, T runeA, T runeB, T runeC, T runeD, T runeE)
public T RuneSelect<T>(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];
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;
if (Attributes[GameAttribute.Rune_A, powerSno] > 0) return runeA;
if (Attributes[GameAttribute.Rune_B, powerSno] > 0) return runeB;
if (Attributes[GameAttribute.Rune_C, powerSno] > 0) return runeC;
if (Attributes[GameAttribute.Rune_D, powerSno] > 0) return runeD;
if (Attributes[GameAttribute.Rune_E, powerSno] > 0) return runeE;
return none;
}
#region enter, leave, reveal handling
@ -3410,11 +3406,11 @@ public class Player : Actor, IMessageConsumer, IUpdateable
public void RevealScenesToPlayer()
{
//List<Scene> scenes_around = this.GetScenesInRegion(DefaultQueryProximityLenght * 2);
var scenes_around = World.Scenes.Values.ToList();
var scenesAround = World.Scenes.Values.ToList();
if (!World.worldData.DynamicWorld)
scenes_around = GetScenesInRegion(DefaultQueryProximityLenght * 3);
scenesAround = GetScenesInRegion(DefaultQueryProximityLenght * 3);
foreach (var scene in scenes_around) // reveal scenes in player's proximity.
foreach (var scene in scenesAround) // 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.
@ -3428,7 +3424,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
foreach (var scene in World.Scenes.Values) // unreveal far scenes
{
if (!scene.IsRevealedToPlayer(this) || scenes_around.Contains(scene))
if (!scene.IsRevealedToPlayer(this) || scenesAround.Contains(scene))
continue;
if (scene.Parent !=
@ -3444,9 +3440,9 @@ public class Player : Actor, IMessageConsumer, IUpdateable
/// </summary>
public void RevealActorsToPlayer()
{
var Range = 200f;
var range = 200f;
if (InGameClient.Game.CurrentEncounter.Activated)
Range = 360f;
range = 360f;
var specialWorlds = new WorldSno[]
{
@ -3457,9 +3453,9 @@ public class Player : Actor, IMessageConsumer, IUpdateable
WorldSno.a1trdun_level05_templar
};
var actors_around = specialWorlds.Contains(World.SNO) ? World.Actors.Values.ToList() : GetActorsInRange(Range);
var actorsAround = specialWorlds.Contains(World.SNO) ? World.Actors.Values.ToList() : GetActorsInRange(range);
foreach (var actor in actors_around) // reveal actors in player's proximity.
foreach (var actor in actorsAround) // reveal actors in player's proximity.
{
if (actor is Player) // if the actors is already revealed, skip it.
continue;
@ -3482,7 +3478,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
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.
actorsAround.Contains(actor)) // if the actors is already revealed, skip it.
continue;
actor.Unreveal(this);
@ -3549,7 +3545,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
world.Reveal(this);
Unreveal(this);
if (_CurrentHPValue == -1f)
if (Math.Abs(_CurrentHPValue - (-1f)) < Globals.FLOAT_TOLERANCE)
DefaultQueryProximityRadius = 60;
InGameClient.SendMessage(new EnterWorldMessage()
@ -3580,7 +3576,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
break;
}
if (_CurrentHPValue == -1f)
if (Math.Abs(_CurrentHPValue - (-1f)) < Globals.FLOAT_TOLERANCE)
AddPercentageHP(100);
DefaultQueryProximityRadius = 100;
@ -3750,7 +3746,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
AllBuffs.Clear();
BetweenWorlds = false;
if (Math.Abs(_CurrentHPValue - (-1)) > 0.0001)
if (Math.Abs(_CurrentHPValue - (-1)) > Globals.FLOAT_TOLERANCE)
{
Attributes[GameAttribute.Hitpoints_Cur] = _CurrentHPValue;
Attributes[GameAttribute.Resource_Cur, (int)Toon.HeroTable.PrimaryResource + 1] = _CurrentResourceValue;
@ -3850,7 +3846,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
}
/// <summary>
/// Allows hero state message to be sent when hero's some property get's updated.
/// Allows hero state message to be sent when hero's some property gets updated.
/// </summary>
public void UpdateHeroState()
{
@ -3940,7 +3936,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
//removing tomb
try
{
GetObjectsInRange<Headstone>(100.0f).Where(h => h.playerIndex == PlayerIndex).First().Destroy();
GetObjectsInRange<Headstone>(100.0f).First(h => h.playerIndex == PlayerIndex).Destroy();
}
catch
{
@ -3949,8 +3945,8 @@ public class Player : Actor, IMessageConsumer, IUpdateable
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 oldSkills = SkillSet.ActiveSkills.Select(s => s.snoSkill).ToList();
foreach (var skill in oldSkills)
{
var power = PowerLoader.CreateImplementationForPowerSNO(skill);
if (power != null && power.EvalTag(PowerKeys.SynergyPower) != -1)
@ -3998,13 +3994,12 @@ public class Player : Actor, IMessageConsumer, IUpdateable
get
{
var baseStrength = 0.0f;
var multiplier = ParagonLevel > 0 ? GameServerConfig.Instance.StrengthParagonMultiplier : GameServerConfig.Instance.StrengthMultiplier;
baseStrength = Toon.HeroTable.CoreAttribute == GameBalance.PrimaryAttribute.Strength
? Toon.HeroTable.Strength + (Level - 1) * 3
: Toon.HeroTable.Strength + (Level - 1);
if (Toon.HeroTable.CoreAttribute == GameBalance.PrimaryAttribute.Strength)
baseStrength = Toon.HeroTable.Strength + (Level - 1) * 3;
else
baseStrength = Toon.HeroTable.Strength + (Level - 1);
return baseStrength;
return baseStrength * multiplier;
}
}
@ -4015,17 +4010,18 @@ public class Player : Actor, IMessageConsumer, IUpdateable
{
get
{
if (Toon.HeroTable.CoreAttribute == GameBalance.PrimaryAttribute.Dexterity)
return Toon.HeroTable.Dexterity + (Level - 1) * 3;
else
return Toon.HeroTable.Dexterity + (Level - 1);
var multiplier = ParagonLevel > 0 ? GameServerConfig.Instance.DexterityParagonMultiplier : GameServerConfig.Instance.DexterityMultiplier;
return Toon.HeroTable.CoreAttribute == GameBalance.PrimaryAttribute.Dexterity
? Toon.HeroTable.Dexterity + (Level - 1) * 3 * multiplier
: Toon.HeroTable.Dexterity + (Level - 1) * multiplier;
}
}
public float TotalDexterity =>
Attributes[GameAttribute.Dexterity] + Inventory.GetItemBonus(GameAttribute.Dexterity_Item);
public float Vitality => Toon.HeroTable.Vitality + (Level - 1) * 2;
public float Vitality => Toon.HeroTable.Vitality + (Level - 1) * 2 * (ParagonLevel > 0 ? GameServerConfig.Instance.VitalityParagonMultiplier : GameServerConfig.Instance.VitalityMultiplier);
public float TotalVitality =>
Attributes[GameAttribute.Vitality] + Inventory.GetItemBonus(GameAttribute.Vitality_Item);
@ -4034,10 +4030,10 @@ public class Player : Actor, IMessageConsumer, IUpdateable
{
get
{
if (Toon.HeroTable.CoreAttribute == GameBalance.PrimaryAttribute.Intelligence)
return Toon.HeroTable.Intelligence + (Level - 1) * 3;
else
return Toon.HeroTable.Intelligence + (Level - 1);
var multiplier = ParagonLevel > 0 ? GameServerConfig.Instance.IntelligenceParagonMultiplier : GameServerConfig.Instance.IntelligenceMultiplier;
return Toon.HeroTable.CoreAttribute == GameBalance.PrimaryAttribute.Intelligence
? Toon.HeroTable.Intelligence + (Level - 1) * 3 * multiplier
: Toon.HeroTable.Intelligence + (Level - 1) * multiplier;
}
}
@ -4325,15 +4321,15 @@ public class Player : Actor, IMessageConsumer, IUpdateable
if (query.Count == 0)
{
//returns empty data
var hireling_empty = new HirelingInfo
var emptyHireling = new HirelingInfo
{
HirelingIndex = type, GbidName = 0x0000, Dead = false, Skill1SNOId = -1, Skill2SNOId = -1,
Skill3SNOId = -1, Skill4SNOId = -1, annItems = -1
};
return hireling_empty;
return emptyHireling;
}
var hireling_full = new HirelingInfo
return new HirelingInfo
{
HirelingIndex = type,
GbidName = 0x0000,
@ -4344,14 +4340,13 @@ public class Player : Actor, IMessageConsumer, IUpdateable
Skill4SNOId = query.First().Skill4SNOId,
annItems = -1
};
return hireling_full;
}
private List<int> Unserialize(string data)
{
var recparts = data.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
var parts = data.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
var ret = new List<int>();
foreach (var recid in recparts) ret.Add(Convert.ToInt32(recid, 10));
foreach (var part in parts) ret.Add(Convert.ToInt32(part, 10));
return ret;
}
@ -4380,34 +4375,35 @@ public class Player : Actor, IMessageConsumer, IUpdateable
public void LearnRecipe(ArtisanType? artisan, int recipe)
{
Logger.Trace("Learning recipe #{0}, Artisan type: {1}", recipe, artisan);
/*var query = this.World.Game.GameDBSession.SessionQuerySingle<DBCraft>(
dbi =>
dbi.DBGameAccount.Id == this.Toon.GameAccount.PersistentID &&
dbi.Artisan == artisan &&
dbi.isHardcore == this.World.Game.IsHardcore);*/
if (artisan == ArtisanType.Blacksmith)
switch (artisan)
{
learnedBlacksmithRecipes.Add(recipe);
blacksmith_data.LearnedRecipes = SerializeBytes(learnedBlacksmithRecipes);
World.Game.GameDbSession.SessionUpdate(blacksmith_data);
case ArtisanType.Blacksmith:
_learnedBlacksmithRecipes.Add(recipe);
_blacksmithData.LearnedRecipes = SerializeBytes(_learnedBlacksmithRecipes);
World.Game.GameDbSession.SessionUpdate(_blacksmithData);
UpdateAchievementCounter(404, 1, 0);
}
else if (artisan == ArtisanType.Jeweler)
{
learnedJewelerRecipes.Add(recipe);
jeweler_data.LearnedRecipes = SerializeBytes(learnedJewelerRecipes);
World.Game.GameDbSession.SessionUpdate(jeweler_data);
break;
case ArtisanType.Jeweler:
_learnedJewelerRecipes.Add(recipe);
_jewelerData.LearnedRecipes = SerializeBytes(_learnedJewelerRecipes);
World.Game.GameDbSession.SessionUpdate(_jewelerData);
UpdateAchievementCounter(404, 1, 1);
break;
}
LoadCrafterData();
}
public bool RecipeAvailable(GameBalance.RecipeTable recipe_definition)
public bool RecipeAvailable(GameBalance.RecipeTable recipeDefinition)
{
if (recipe_definition.Flags == 0) return true;
return learnedBlacksmithRecipes.Contains(recipe_definition.Hash) ||
learnedJewelerRecipes.Contains(recipe_definition.Hash);
if (recipeDefinition.Flags == 0) return true;
return _learnedBlacksmithRecipes.Contains(recipeDefinition.Hash) || _learnedJewelerRecipes.Contains(recipeDefinition.Hash);
}
public PlayerBannerMessage GetPlayerBanner()
@ -4420,69 +4416,69 @@ public class Player : Actor, IMessageConsumer, IUpdateable
return new PlayerBannerMessage() { PlayerBanner = playerBanner };
}
private List<int> learnedBlacksmithRecipes = new();
private List<int> learnedJewelerRecipes = new();
private List<int> learnedTransmogs = new();
private List<int> _learnedBlacksmithRecipes = new();
private List<int> _learnedJewelerRecipes = new();
private List<int> _learnedTransmogs = new();
private DBCraft blacksmith_data = null;
private DBCraft jeweler_data = null;
private DBCraft mystic_data = null;
private Dictionary<ArtisanType, ArtisanTrainHelper> artisanTrainHelpers = new();
private DBCraft _blacksmithData = null;
private DBCraft _jewelerData = null;
private DBCraft _mysticData = null;
private readonly Dictionary<ArtisanType, ArtisanTrainHelper> _artisanTrainHelpers = new();
public void LoadCrafterData()
{
if (blacksmith_data == null)
if (_blacksmithData == null)
{
var craft_data =
World.Game.GameDbSession.SessionQueryWhere<DBCraft>(dbc =>
dbc.DBGameAccount.Id == Toon.GameAccount.PersistentID);
blacksmith_data = craft_data.Single(dbc =>
_blacksmithData = craft_data.Single(dbc =>
dbc.Artisan == "Blacksmith" && dbc.isHardcore == World.Game.IsHardcore &&
dbc.isSeasoned == World.Game.IsSeasoned);
jeweler_data = craft_data.Single(dbc =>
_jewelerData = craft_data.Single(dbc =>
dbc.Artisan == "Jeweler" && dbc.isHardcore == World.Game.IsHardcore &&
dbc.isSeasoned == World.Game.IsSeasoned);
mystic_data = craft_data.Single(dbc =>
_mysticData = 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);
_artisanTrainHelpers[ArtisanType.Blacksmith] =
new ArtisanTrainHelper(_blacksmithData, ArtisanType.Blacksmith);
_artisanTrainHelpers[ArtisanType.Jeweler] = new ArtisanTrainHelper(_jewelerData, ArtisanType.Jeweler);
_artisanTrainHelpers[ArtisanType.Mystic] = new ArtisanTrainHelper(_mysticData, 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)
? BlacksmithUnlocked == false && _blacksmithData.Level < 1 ? 1 : _blacksmithData.Level
: _blacksmithData.Level)
.SetCooldownEnd(0)
.AddRangeRecipes(UnserializeBytes(blacksmith_data.LearnedRecipes))
.AddRangeRecipes(UnserializeBytes(_blacksmithData.LearnedRecipes))
.Build();
learnedBlacksmithRecipes = UnserializeBytes(blacksmith_data.LearnedRecipes);
_learnedBlacksmithRecipes = UnserializeBytes(_blacksmithData.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)
? JewelerUnlocked == false && _jewelerData.Level < 1 ? 1 : _jewelerData.Level
: _jewelerData.Level)
.SetCooldownEnd(0)
.AddRangeRecipes(UnserializeBytes(jeweler_data.LearnedRecipes))
.AddRangeRecipes(UnserializeBytes(_jewelerData.LearnedRecipes))
.Build();
learnedJewelerRecipes = UnserializeBytes(jeweler_data.LearnedRecipes);
_learnedJewelerRecipes = UnserializeBytes(_jewelerData.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)
? MysticUnlocked == false && _mysticData.Level < 1 ? 1 : _mysticData.Level
: _mysticData.Level)
.SetCooldownEnd(0)
.Build();
var transmog = D3.ItemCrafting.CrafterSavedData.CreateBuilder()
.SetTransmogData(D3.GameBalance.BitPackedGbidArray.CreateBuilder()
.SetBitfield(ByteString.CopyFrom(mystic_data.LearnedRecipes)))
.SetBitfield(ByteString.CopyFrom(_mysticData.LearnedRecipes)))
//.AddRangeUnlockedTransmogs(this.UnserializeBytes(mystic_data.LearnedRecipes))
.Build();
learnedTransmogs = UnserializeBytes(mystic_data.LearnedRecipes);
_learnedTransmogs = UnserializeBytes(_mysticData.LearnedRecipes);
if (BlacksmithUnlocked || InGameClient.Game.CurrentAct == 3000)
InGameClient.SendMessage(new GenericBlobMessage(Opcodes.CraftingDataBlacksmithInitialMessage)
@ -4503,27 +4499,26 @@ public class Player : Actor, IMessageConsumer, IUpdateable
public void LoadCurrencyData()
{
var bloodShards = 0;
bloodShards = Toon.GameAccount.BloodShards;
var bloodShards = Toon.GameAccount.BloodShards; // TODO: is this needed? @iamdroppy
Inventory.UpdateCurrencies();
}
public void LoadMailData()
{
var mail_data =
var mailData =
World.Game.GameDbSession.SessionQueryWhere<DBMail>(dbm =>
dbm.DBToon.Id == Toon.PersistentID && dbm.Claimed == false);
var mails = D3.Items.Mails.CreateBuilder();
foreach (var mail in mail_data)
foreach (var mail in mailData)
{
var mail_row = D3.Items.Mail.CreateBuilder()
var mailRow = 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()
mailRow.SetAttachments(D3.Items.MailAttachments.CreateBuilder()
.SetItems(D3.Items.ItemList.CreateBuilder()
.AddItems(D3.Items.SavedItem.CreateBuilder()
.SetId(D3.OnlineService.ItemId.CreateBuilder().SetIdLow(0).SetIdHigh(0x3C000002517A294))
@ -4542,15 +4537,16 @@ public class Player : Actor, IMessageConsumer, IUpdateable
)
)
);
mails.AddMailsProp(mail_row);
mails.AddMailsProp(mailRow);
}
var mail_contents = D3.GameMessage.MailContents.CreateBuilder()
InGameClient.SendMessage(new MailDigestMessage()
{
MailContents = D3.GameMessage.MailContents.CreateBuilder()
.SetAppendMessages(false)
.SetMails(mails)
.Build();
InGameClient.SendMessage(new MailDigestMessage() { MailContents = mail_contents });
.Build()
});
}
//*/
@ -4578,10 +4574,10 @@ public class Player : Actor, IMessageConsumer, IUpdateable
public void LoadShownTutorials()
{
var tutorials = new List<byte>();
tutorials.Add(64);
for (var i = 0; i < 15; i++)
tutorials.Add(0);
// var tutorials = new List<byte>();
// 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()
@ -4590,13 +4586,13 @@ public class Player : Actor, IMessageConsumer, IUpdateable
InGameClient.SendMessage(new GenericBlobMessage(Opcodes.TutorialStateMessage) { Data = state.ToByteArray() });
}
private List<ulong> _unlockedAchievements = new();
private List<ulong> _unlockedCriterias = new();
private readonly List<ulong> _unlockedAchievements = new();
private readonly List<ulong> _unlockCriteria = new();
private Dictionary<ulong, uint> AchievementCounters = new();
private readonly Dictionary<ulong, uint> _achievementCounters = new();
public int DodgesInARow = 0;
public int BlocksInARow = 0;
public int DodgesInARow { get; set; } = 0;
public int BlocksInARow { get; set; }= 0;
public void GrantAchievement(ulong id)
{
@ -4606,20 +4602,20 @@ public class Player : Actor, IMessageConsumer, IUpdateable
_unlockedAchievements.Add(id);
try
{
var Achievement = AchievementSystem.AchievementManager.GetAchievementById(id);
long Platinum = -1;
foreach (var attr in Achievement.AttributesList)
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);
platinum = long.Parse(attr.Value);
InGameClient.SendMessage(new MessageSystem.Message.Definitions.Platinum.PlatinumAchievementAwardedMessage
{
CurrentPlatinum = InGameClient.BnetClient.Account.GameAccount.Platinum,
idAchievement = id,
PlatinumIncrement = Platinum
PlatinumIncrement = platinum
});
if (Platinum > 0)
if (platinum > 0)
{
InGameClient.BnetClient.Account.GameAccount.Platinum += (int)Platinum;
InGameClient.BnetClient.Account.GameAccount.Platinum += (int)platinum;
Inventory.UpdateCurrencies();
}
@ -4633,33 +4629,33 @@ public class Player : Actor, IMessageConsumer, IUpdateable
public void AddAchievementCounter(ulong id, uint count)
{
lock (AchievementCounters)
lock (_achievementCounters)
{
if (!AchievementCounters.ContainsKey(id))
AchievementCounters.Add(id, count);
if (!_achievementCounters.ContainsKey(id))
_achievementCounters.Add(id, count);
else
AchievementCounters[id] += count;
_achievementCounters[id] += count;
}
}
public void CheckAchievementCounters()
{
lock (AchievementCounters)
lock (_achievementCounters)
{
foreach (var counter in AchievementCounters)
foreach (var counter in _achievementCounters)
{
if (counter.Value == 0) continue;
UpdateSingleAchievementCounter(counter.Key, counter.Value);
}
AchievementCounters.Clear();
_achievementCounters.Clear();
}
}
public void GrantCriteria(ulong id)
{
if (_unlockedCriterias.Contains(id)) return;
_unlockedCriterias.Add(id);
if (_unlockCriteria.Contains(id)) return;
_unlockCriteria.Add(id);
try
{
GameServer.ClientSystem.GameServer.GSBackend.GrantCriteria(Toon.GameAccount.PersistentID, id);
@ -4824,13 +4820,13 @@ public class Player : Actor, IMessageConsumer, IUpdateable
public int CastingSnoPower = -1;
public void StartCasting(int durationTicks, Action result, int skillsno = -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;
CastingSnoPower = skillSno;
if (CastingSnoPower != -1)
{
Attributes[GameAttribute.Buff_Icon_Start_Tick0, CastingSnoPower] = World.Game.TickCounter;
@ -4882,7 +4878,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
#region generic properties
public int ClassSNO => Toon.Gender == 0 ? Toon.HeroTable.SNOMaleActor : Toon.HeroTable.SNOFemaleActor;
public int ClassSno => Toon.Gender == 0 ? Toon.HeroTable.SNOMaleActor : Toon.HeroTable.SNOFemaleActor;
public int AdditionalLootItems
{
@ -4910,7 +4906,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
public int SecondaryResourceID => (int)Toon.HeroTable.SecondaryResource;
[Obsolete]
[Obsolete("Not used anymore. Should it be removed?")]
public bool IsInTown
{
get
@ -4945,7 +4941,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
(Attributes[GameAttribute.Resource_Max_Percent_Bonus, resourceId] + 1), 0);
}
public static List<long> LevelBorders = new()
public static readonly List<long> 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 */
@ -4958,7 +4954,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
100000000 /* Level 61-70 */
};
public static List<long> ParagonLevelBorders = new()
public static readonly List<long> 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,
@ -5141,9 +5137,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
});
Conversations.StartConversation(0x0002A777); //LevelUp Conversation
Attributes[GameAttribute.Alt_Experience_Next_Lo] =
Attributes[GameAttribute.Alt_Experience_Next_Lo] +
(int)ParagonLevelBorders[Attributes[GameAttribute.Alt_Level]];
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
@ -5165,8 +5159,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
Level++;
Attributes[GameAttribute.Level]++;
Toon.LevelUp();
if (World.Game.MonsterLevel + 1 ==
Attributes[GameAttribute.Level]) //if this is suitable level to update
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()
@ -5326,7 +5319,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
public void VacuumPickupHealthOrb(float radius = -1)
{
if (Math.Abs(radius - -1) < 0.001)
if (Math.Abs(radius - -1) < Globals.FLOAT_TOLERANCE)
radius = Attributes[GameAttribute.Gold_PickUp_Radius];
var itemList = GetItemsInRange(radius);
foreach (var item in itemList)
@ -5501,12 +5494,11 @@ public class Player : Actor, IMessageConsumer, IUpdateable
item.Destroy();
}
else if (item.ItemDefinition.Name == "p1_normal_rifts_Orb" ||
item.ItemDefinition.Name == "p1_tiered_rifts_Orb")
else if (item.ItemDefinition.Name is "p1_normal_rifts_Orb" or "p1_tiered_rifts_Orb")
{
if (InGameClient.Game.ActiveNephalemTimer && InGameClient.Game.ActiveNephalemKilledMobs == false)
{
InGameClient.Game.ActiveNephalemProgress += 15f;
InGameClient.Game.ActiveNephalemProgress += 15f * GameServerConfig.Instance.NephalemRiftProgressMultiplier;
foreach (var plr in InGameClient.Game.Players.Values)
{
plr.InGameClient.SendMessage(new FloatDataMessage(Opcodes.DunggeonFinderProgressGlyphPickUp)
@ -5630,7 +5622,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
public Actor SpawnNephalemBoss(World world)
{
var boss = world.SpawnMonster(ActorSnoExtensions.nephalemPortalBosses.PickRandom(), Position);
var boss = world.SpawnMonster(ActorSnoExtensions.NephalemPortalBosses.PickRandom(), Position);
boss.Attributes[GameAttribute.Bounty_Objective] = true;
boss.Attributes[GameAttribute.Is_Loot_Run_Boss] = true;
boss.Attributes.BroadcastChangedIfRevealed();
@ -5658,23 +5650,26 @@ public class Player : Actor, IMessageConsumer, IUpdateable
return true;
}
public void AddPercentageHP(int percentage, bool GuidingLight = false)
public void AddPercentageHP(int percentage, bool guidingLight = false)
{
var quantity = percentage * Attributes[GameAttribute.Hitpoints_Max_Total] / 100;
AddHP(quantity, GuidingLight);
AddHP(quantity, guidingLight);
}
public void AddPercentageHP(float percentage, bool GuidingLight = false)
public void AddPercentageHP(float percentage, bool guidingLight = false)
{
var quantity = percentage * Attributes[GameAttribute.Hitpoints_Max_Total] / 100;
AddHP(quantity, GuidingLight);
AddHP(quantity, guidingLight);
}
public override void AddHP(float quantity, bool guidingLight = false)
{
if (Dead) return;
if (quantity == 0) return;
if (quantity > 0)
switch (quantity)
{
case 0:
return;
case > 0:
{
if (Attributes[GameAttribute.Hitpoints_Cur] < Attributes[GameAttribute.Hitpoints_Max_Total])
{
@ -5706,14 +5701,16 @@ public class Player : Actor, IMessageConsumer, IUpdateable
Type = FloatingNumberMessage.FloatType.Green
});
}
break;
}
else
{
default:
Attributes[GameAttribute.Hitpoints_Cur] = Math.Max(
Attributes[GameAttribute.Hitpoints_Cur] + quantity,
0);
Attributes.BroadcastChangedIfRevealed();
break;
}
}
@ -5731,9 +5728,9 @@ public class Player : Actor, IMessageConsumer, IUpdateable
#region Resource Generate/Use
private int _DisciplineSpent = 0;
private int _HatredSpent = 0;
private int _WrathSpent = 0;
private int _disciplineSpent = 0;
private int _hatredSpent = 0;
private int _wrathSpent = 0;
public void GeneratePrimaryResource(float amount)
{
@ -5745,7 +5742,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
if (World.BuffManager.HasBuff<GuardiansPathBuff>(this)) //Monk -> The Guardian's Path 2H
amount *= 1.35f;
_ModifyResourceAttribute(PrimaryResourceID, amount);
ModifyResourceAttribute(PrimaryResourceID, amount);
}
public void UsePrimaryResource(float amount, bool tick = false)
@ -5757,28 +5754,28 @@ public class Player : Actor, IMessageConsumer, IUpdateable
amount = amount * (1f - DecreaseUseResourcePercent);
if (Toon.Class == ToonClass.Crusader)
{
_WrathSpent += (int)amount;
_wrathSpent += (int)amount;
if (!tick && SkillSet.HasPassive(310775)) //Wrathful passive
AddHP(_WrathSpent * 15f * Attributes[GameAttribute.Level]);
AddHP(_wrathSpent * 15f * Attributes[GameAttribute.Level]);
//Laws of Hope -> Faith's reward
if (!tick && World.BuffManager.HasBuff<CrusaderLawsOfHope.LawsShieldBuff>(this))
if (World.BuffManager.GetFirstBuff<CrusaderLawsOfHope.LawsShieldBuff>(this).HealPerWrath)
AddHP(_WrathSpent * 15f * Attributes[GameAttribute.Level]);
AddHP(_wrathSpent * 15f * Attributes[GameAttribute.Level]);
if (_WrathSpent >= 20) //Akarat Champion -> Fire Starter
if (_wrathSpent >= 20) //Akarat Champion -> Fire Starter
if (!tick && World.BuffManager.HasBuff<CrusaderAkaratChampion.AkaratBuff>(this))
World.BuffManager.GetFirstBuff<CrusaderAkaratChampion.AkaratBuff>(this).wrathBlast = true;
}
if (Toon.Class == ToonClass.DemonHunter)
{
_HatredSpent += (int)amount;
_hatredSpent += (int)amount;
if (_HatredSpent >= 150 && _DisciplineSpent >= 50)
if (_hatredSpent >= 150 && _disciplineSpent >= 50)
GrantAchievement(74987243307068);
AddTimedAction(6f, new Action<int>((q) => _HatredSpent -= (int)amount));
AddTimedAction(6f, new Action<int>((q) => _hatredSpent -= (int)amount));
}
if (Toon.Class == ToonClass.Barbarian)
@ -5813,12 +5810,12 @@ public class Player : Actor, IMessageConsumer, IUpdateable
if (SkillSet.HasPassive(205398) && Attributes[GameAttribute.Hitpoints_Cur] <
Attributes[GameAttribute.Hitpoints_Max_Total] * 0.35f) //Relentless (Barbarian)
amount *= 0.25f;
_ModifyResourceAttribute(PrimaryResourceID, -amount);
ModifyResourceAttribute(PrimaryResourceID, -amount);
}
public void GenerateSecondaryResource(float amount)
{
_ModifyResourceAttribute(SecondaryResourceID, amount);
ModifyResourceAttribute(SecondaryResourceID, amount);
}
public void UseSecondaryResource(float amount)
@ -5833,18 +5830,18 @@ public class Player : Actor, IMessageConsumer, IUpdateable
if (Toon.Class == ToonClass.DemonHunter)
{
_DisciplineSpent += (int)amount;
_disciplineSpent += (int)amount;
if (_HatredSpent >= 150 && _DisciplineSpent >= 50)
if (_hatredSpent >= 150 && _disciplineSpent >= 50)
GrantAchievement(74987243307068);
AddTimedAction(6f, new Action<int>((q) => _DisciplineSpent -= (int)amount));
AddTimedAction(6f, new Action<int>((q) => _disciplineSpent -= (int)amount));
}
_ModifyResourceAttribute(SecondaryResourceID, -amount);
ModifyResourceAttribute(SecondaryResourceID, -amount);
}
private void _ModifyResourceAttribute(int resourceID, float amount)
private void ModifyResourceAttribute(int resourceID, float amount)
{
if (resourceID == -1 || amount == 0) return;
var current = Attributes[GameAttribute.Resource_Cur, resourceID];
@ -5857,7 +5854,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
Attributes[GameAttribute.Resource_Cur, resourceID] + amount,
0f);
if (current == Attributes[GameAttribute.Resource_Cur, resourceID]) return;
if (Math.Abs(current - Attributes[GameAttribute.Resource_Cur, resourceID]) < Globals.FLOAT_TOLERANCE) return;
Attributes.BroadcastChangedIfRevealed();
}

View File

@ -266,9 +266,9 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
}, Target);
if (Context?.User != null)
if (Math.Abs(Context.User.Attributes[GameAttribute.Item_Power_Passive, 247640] - 1) < 0.001 ||
Math.Abs(Context.User.Attributes[GameAttribute.Item_Power_Passive, 249963] - 1) < 0.001 ||
Math.Abs(Context.User.Attributes[GameAttribute.Item_Power_Passive, 249954] - 1) < 0.001 ||
if (Math.Abs(Context.User.Attributes[GameAttribute.Item_Power_Passive, 247640] - 1) < Globals.FLOAT_TOLERANCE ||
Math.Abs(Context.User.Attributes[GameAttribute.Item_Power_Passive, 249963] - 1) < Globals.FLOAT_TOLERANCE ||
Math.Abs(Context.User.Attributes[GameAttribute.Item_Power_Passive, 249954] - 1) < Globals.FLOAT_TOLERANCE ||
(float)FastRandom.Instance.NextDouble() < 0.1f ||
Target.World.SNO == WorldSno.a1dun_random_level01)
switch ((int)DeathDamageType.HitEffect)
@ -1066,7 +1066,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
{
//death implementation
Player player = (Player)Target;
if (Math.Abs(player.Attributes[GameAttribute.Item_Power_Passive, 248629] - 1) < 0.001)
if (Math.Abs(player.Attributes[GameAttribute.Item_Power_Passive, 248629] - 1) < Globals.FLOAT_TOLERANCE)
player.PlayEffectGroup(248680);
player.StopCasting();
Target.World.BuffManager.RemoveAllBuffs(Target, false);

View File

@ -24,25 +24,22 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
public class HitPayload : Payload
{
public static readonly Logger Logger = LogManager.CreateLogger();
public float TotalDamage;
public DamageType DominantDamageType;
public Dictionary<DamageType, float> ElementDamages;
public bool IsCriticalHit;
public bool IsDodged;
public bool IsWeaponDamage;
public float TotalDamage { get; set; }
public DamageType DominantDamageType { get; set; }
public Dictionary<DamageType, float> ElementDamages { get; set; }
public bool IsCriticalHit { get; set; }
public bool IsDodged { get; set; }
public bool IsWeaponDamage { get; set; }
public bool Successful = false;
public bool Blocked = false;
public bool Successful { get; set; }
public bool Blocked { get; set; }
public bool AutomaticHitEffects = true;
public Action<DeathPayload> OnDeath = null;
private bool WaitTo(TickTimer timer)
{
while (timer.TimedOut != true)
{
}
while (timer.TimedOut != true) ;
return true;
}
@ -144,7 +141,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
if (criticalHit)
{
TotalDamage *= (1f + Context.User.Attributes[GameAttribute.Crit_Damage_Percent]);
if (Context.User is Player && (Context.User as Player).Toon.Class == ToonClass.Wizard && Context.User.Attributes[GameAttribute.Resource_On_Crit, 1] > 0)
if (Context.User is Player player && player.Toon.Class == ToonClass.Wizard && player.Attributes[GameAttribute.Resource_On_Crit, 1] > 0)
if (FastRandom.Instance.NextDouble() < Context.GetProcCoefficient())
(Context.User as Player).GeneratePrimaryResource(Context.User.Attributes[GameAttribute.Resource_On_Crit, 1]);
}
@ -170,10 +167,9 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
switch (Context.User)
{
case Player:
case Player plr:
if (IsWeaponDamage)
{
var plr = Context.User as Player;
TotalDamage = TotalDamage * (1 + (plr.PrimaryAttribute / 100f));
if (FastRandom.Instance.NextDouble() < Context.GetProcCoefficient())
plr.GeneratePrimaryResource(plr.Attributes[GameAttribute.Resource_On_Hit]);
@ -224,7 +220,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
if (FastRandom.Instance.NextDouble() < Context.GetProcCoefficient())
plr.GenerateSecondaryResource(1f);
if (plr.SkillSet.HasPassive(155721) && Target.Attributes[GameAttribute.Slow] == true)
if (plr.SkillSet.HasPassive(155721) && Target.Attributes[GameAttribute.Slow])
TotalDamage *= 1.20f;
if (plr.SkillSet.HasPassive(155725))
@ -239,12 +235,12 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
if (criticalHit)
{
plr.AddTimedAction(1f, new Action<int>((q) => plr.World.BuffManager.RemoveBuffs(plr, 155715)));
plr.AddTimedAction(2f, new Action<int>((q) =>
plr.AddTimedAction(1f, _ => plr.World.BuffManager.RemoveBuffs(plr, 155715));
plr.AddTimedAction(2f, _ =>
{
if (plr.SkillSet.HasPassive(155715))
plr.World.BuffManager.AddBuff(plr, plr, new SharpshooterBuff());
}));
});
}
break;
case ToonClass.Wizard:
@ -373,17 +369,17 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
if (plr.World.BuffManager.HasBuff<CrusaderAkaratChampion.AkaratBuff>(plr)) //AkaratChampion -> Rally
if (plr.World.BuffManager.GetFirstBuff<CrusaderAkaratChampion.AkaratBuff>(plr).CDRActive)
if (FastRandom.Instance.NextDouble() < 0.5f * Context.GetProcCoefficient())
foreach (var cdBuff in plr.World.BuffManager.GetBuffs<CooldownBuff>(plr))
if (!(cdBuff.TargetPowerSNO == 269032)) //do not CDR AkaratChampionBuff
cdBuff.Reduce(60);
foreach (var cooldownBuff in plr.World.BuffManager.GetBuffs<CooldownBuff>(plr))
if (cooldownBuff.TargetPowerSNO != 269032) //do not CDR AkaratChampionBuff
cooldownBuff.Reduce(60);
break;
}
if (Target is Monster)
if (Target is Monster monster)
{
TotalDamage *= 1 + plr.Attributes[GameAttribute.Damage_Percent_Bonus_Vs_Monster_Type, (Target as Monster).MonsterType];
TotalDamage *= 1 + plr.Attributes[GameAttribute.Damage_Percent_Bonus_Vs_Monster_Type, monster.MonsterType];
if ((Target as Monster).Quality > 0)
if (monster.Quality > 0)
TotalDamage *= 1 + plr.Attributes[GameAttribute.Damage_Percent_Bonus_Vs_Elites];
if (attackPayload.Targets.Actors.Count == 1 && !(attackPayload.Context is Buff) && attackPayload.AutomaticHitEffects)
@ -391,40 +387,37 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
float procCoeff = Context.GetProcCoefficient();
if (FastRandom.Instance.NextDouble() < plr.Attributes[GameAttribute.On_Hit_Fear_Proc_Chance] * procCoeff)
plr.World.BuffManager.AddBuff(plr, Target, new DebuffFeared(TickTimer.WaitSeconds(plr.World.Game, 1.5f)));
plr.World.BuffManager.AddBuff(plr, monster, new DebuffFeared(TickTimer.WaitSeconds(plr.World.Game, 1.5f)));
if (FastRandom.Instance.NextDouble() < plr.Attributes[GameAttribute.On_Hit_Stun_Proc_Chance] * procCoeff)
plr.World.BuffManager.AddBuff(plr, Target, new DebuffStunned(TickTimer.WaitSeconds(plr.World.Game, 1.5f)));
plr.World.BuffManager.AddBuff(plr, monster, new DebuffStunned(TickTimer.WaitSeconds(plr.World.Game, 1.5f)));
if (FastRandom.Instance.NextDouble() < plr.Attributes[GameAttribute.On_Hit_Blind_Proc_Chance] * procCoeff)
plr.World.BuffManager.AddBuff(plr, Target, new DebuffBlind(TickTimer.WaitSeconds(plr.World.Game, 1.5f)));
plr.World.BuffManager.AddBuff(plr, monster, new DebuffBlind(TickTimer.WaitSeconds(plr.World.Game, 1.5f)));
if (FastRandom.Instance.NextDouble() < plr.Attributes[GameAttribute.On_Hit_Freeze_Proc_Chance] * procCoeff)
plr.World.BuffManager.AddBuff(plr, Target, new DebuffFrozen(TickTimer.WaitSeconds(plr.World.Game, 1.5f)));
plr.World.BuffManager.AddBuff(plr, monster, new DebuffFrozen(TickTimer.WaitSeconds(plr.World.Game, 1.5f)));
if (FastRandom.Instance.NextDouble() < plr.Attributes[GameAttribute.On_Hit_Chill_Proc_Chance] * procCoeff)
plr.World.BuffManager.AddBuff(plr, Target, new DebuffChilled(0.3f, TickTimer.WaitSeconds(plr.World.Game, 2f)));
plr.World.BuffManager.AddBuff(plr, monster, new DebuffChilled(0.3f, TickTimer.WaitSeconds(plr.World.Game, 2f)));
if (FastRandom.Instance.NextDouble() < plr.Attributes[GameAttribute.On_Hit_Slow_Proc_Chance] * procCoeff)
plr.World.BuffManager.AddBuff(plr, Target, new DebuffSlowed(0.3f, TickTimer.WaitSeconds(plr.World.Game, 2f)));
plr.World.BuffManager.AddBuff(plr, monster, new DebuffSlowed(0.3f, TickTimer.WaitSeconds(plr.World.Game, 2f)));
if (FastRandom.Instance.NextDouble() < plr.Attributes[GameAttribute.On_Hit_Knockback_Proc_Chance] * procCoeff)
plr.World.BuffManager.AddBuff(plr, Target, new KnockbackBuff(3f));
plr.World.BuffManager.AddBuff(plr, monster, new KnockbackBuff(3f));
}
}
}
break;
case Minion:
var mn = Context.User as Minion;
case Minion mn:
TotalDamage *= (1 + (mn.PrimaryAttribute / 100f));
TotalDamage *= mn.Master.Attributes[GameAttribute.Attacks_Per_Second_Total];
if (mn.Master is Player)
if (mn.Master is Player mstr)
{
var mstr = mn.Master as Player;
if (mstr.SkillSet.HasPassive(209041) && (mn is CorpseSpider || mn is CorpseSpiderQueen))
if (mstr.SkillSet.HasPassive(209041) && mn is CorpseSpider or CorpseSpiderQueen)
mstr.World.BuffManager.AddBuff(mstr, mstr, new VisionQuestBuff());
if (mn.SNO == ActorSno._dh_companion_spider)
@ -438,12 +431,18 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
}
if (Target is Player playerTarget) //check for passives here (incoming damage)
switch (Target)
{
//check for passives here (incoming damage)
case Player playerTarget:
{
if (!playerTarget.Attributes[GameAttribute.Cannot_Dodge] && FastRandom.Instance.NextDouble() < playerTarget.DodgeChance)
IsDodged = true;
if (playerTarget.Toon.Class == ToonClass.Monk) //Monk defensive passives
switch (playerTarget.Toon.Class)
{
//Monk defensive passives
case ToonClass.Monk:
{
TotalDamage *= 0.7f; //Class damage reduction bonus
@ -459,9 +458,10 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
if (playerTarget.World.BuffManager.HasBuff<MantraOfEvasionPassive.MantraOfEvasionBuff>(playerTarget))
if (playerTarget.World.BuffManager.GetFirstBuff<MantraOfEvasionPassive.MantraOfEvasionBuff>(playerTarget).Backlash)
playerTarget.World.BuffManager.GetFirstBuff<MantraOfEvasionPassive.MantraOfEvasionBuff>(playerTarget).BacklashTrigger = true;
break;
}
if (playerTarget.Toon.Class == ToonClass.Barbarian) //Barb defensive passives
//Barb defensive passives
case ToonClass.Barbarian:
{
TotalDamage *= 0.7f; //Class damage reduction bonus
@ -471,9 +471,10 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
if (playerTarget.SkillSet.HasPassive(205398) && (playerTarget.Attributes[GameAttribute.Hitpoints_Cur] - TotalDamage) < (playerTarget.Attributes[GameAttribute.Hitpoints_Max_Total] * 0.2f)) //Relentless (barbarian)
TotalDamage *= 0.5f;
break;
}
if (playerTarget.Toon.Class == ToonClass.Wizard) //Wizard defensive passives
//Wizard defensive passives
case ToonClass.Wizard:
{
if (playerTarget.SkillSet.HasPassive(208471)) //GlassCannon (Wizard)
TotalDamage *= 1.1f;
@ -498,21 +499,25 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
cdBuff.Remove();
}
}
}
if (playerTarget.Toon.Class == ToonClass.WitchDoctor) //Witch Doctor defensive passives
break;
}
//Witch Doctor defensive passives
case ToonClass.WitchDoctor:
{
if (playerTarget.SkillSet.HasPassive(217968)) //JungleFortitude (WD)
TotalDamage *= 0.85f;
break;
}
if (playerTarget.Toon.Class == ToonClass.DemonHunter) //DH defensive passives
//DH defensive passives
case ToonClass.DemonHunter:
{
if (playerTarget.SkillSet.HasPassive(210801) && playerTarget.World.BuffManager.GetFirstBuff<BroodingCooldownBuff>(playerTarget) == null) //Brooding (DH)
playerTarget.World.BuffManager.AddBuff(playerTarget, playerTarget, new BroodingCooldownBuff());
break;
}
if (playerTarget.Toon.Class == ToonClass.Crusader) //Crusader defensive passives
//Crusader defensive passives
case ToonClass.Crusader:
{
TotalDamage *= 0.7f; //Class damage reduction bonus
@ -532,11 +537,15 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
if (!playerTarget.World.BuffManager.GetFirstBuff<CrusaderLawsOfJustice.LawsResBuff>(playerTarget).Primary)
if (playerTarget.World.BuffManager.GetFirstBuff<CrusaderLawsOfJustice.LawsResBuff>(playerTarget).Redirect)
TotalDamage *= 0.8f;
break;
}
}
TotalDamage *= 0.1f;
break;
}
else if (Target is Minion { Master: Player playerOwner }) //check for passives here (incoming damage, minions)
//check for passives here (incoming damage, minions)
case Minion { Master: Player playerOwner }:
{
var plr = playerOwner;
@ -549,26 +558,22 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
TotalDamage *= 0.85f;
TotalDamage *= 0.1f; //hack for unkillable minions
break;
}
}
}
private static float ReductionFromResistance(float resistance, int attackerLevel)
{
return 1f - (resistance / ((5 * attackerLevel) + resistance));
}
private static float ReductionFromResistance(float resistance, int attackerLevel) => 1f - (resistance / ((5 * attackerLevel) + resistance));
private static float ReductionFromArmor(float armor, int attackerLevel)
{
return 1f - (armor / ((50 * attackerLevel) + armor));
}
private static float ReductionFromArmor(float armor, int attackerLevel) => 1f - (armor / ((50 * attackerLevel) + armor));
private void CheckItemProcs(Player user)
{
if (Math.Abs(user.Attributes[GameAttribute.Item_Power_Passive, 247724] - 1) < 0.001 && FastRandom.Instance.NextDouble() < 0.2)
if (Math.Abs(user.Attributes[GameAttribute.Item_Power_Passive, 247724] - 1) < Globals.FLOAT_TOLERANCE && FastRandom.Instance.NextDouble() < 0.2)
{
user.PlayEffectGroup(247770);
}
if (Math.Abs(user.Attributes[GameAttribute.Item_Power_Passive, 245741] - 1) < 0.001 && FastRandom.Instance.NextDouble() < 0.2)
if (Math.Abs(user.Attributes[GameAttribute.Item_Power_Passive, 245741] - 1) < Globals.FLOAT_TOLERANCE && FastRandom.Instance.NextDouble() < 0.2)
{
user.PlayEffectGroup(245747);
}
@ -625,12 +630,12 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
else if (plr.Toon.Class == ToonClass.DemonHunter) //Awareness
{
plr.AddTimedAction(1f, new Action<int>((q) => plr.World.BuffManager.RemoveBuffs(plr, 324770)));
plr.AddTimedAction(2f, new Action<int>((q) =>
plr.AddTimedAction(1f, _ => plr.World.BuffManager.RemoveBuffs(plr, 324770));
plr.AddTimedAction(2f, _ =>
{
if (plr.SkillSet.HasPassive(324770))
plr.World.BuffManager.AddBuff(plr, plr, new AwarenessBuff());
}));
});
}
return;
}
@ -675,12 +680,11 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
}
}
if (Target.World != null)
Target.World.BuffManager.SendTargetPayload(Target, this);
Target.World?.BuffManager?.SendTargetPayload(Target, this);
if (Context.User != null)
Target.World.BuffManager.SendTargetPayload(Context.User, this);
Target.World?.BuffManager?.SendTargetPayload(Context.User, this);
if (Target == null || Target.World == null) return; //in case Target was killed in OnPayload
if (Target?.World == null) return; //in case Target was killed in OnPayload
if (Context.User is Player player)
{
@ -703,19 +707,17 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
hireling.AddHP(hireling.Attributes[GameAttribute.Hitpoints_On_Hit]);
}
// floating damage number
if (Target.World != null)
// make player damage red, all other damage white
var type = Target is Player ?
IsCriticalHit ? FloatingNumberMessage.FloatType.RedCritical : FloatingNumberMessage.FloatType.Red :
IsCriticalHit ? FloatingNumberMessage.FloatType.Golden : FloatingNumberMessage.FloatType.White;
if (Target.World is { } world)
{
Target.World.BroadcastIfRevealed(plr => new FloatingNumberMessage
world.BroadcastIfRevealed(plr => new FloatingNumberMessage
{
ActorID = Target.DynamicID(plr),
Number = TotalDamage,
// make player damage red, all other damage white
Type = IsCriticalHit ?
(Target is Player) ? FloatingNumberMessage.FloatType.RedCritical : FloatingNumberMessage.FloatType.Golden
:
(Target is Player) ? FloatingNumberMessage.FloatType.Red : FloatingNumberMessage.FloatType.White
Type = type
}, Target);
}
@ -737,15 +739,15 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
{
// play override hitsound if any, otherwise just default to playing metal weapon hit for now
int overridenSound = Context.EvalTag(PowerKeys.HitsoundOverride);
int hitsound = overridenSound != -1 ? overridenSound : 1;
if (hitsound > 0)
Target.PlayEffect(Effect.Hit, hitsound);
int hitSound = overridenSound != -1 ? overridenSound : 1;
if (hitSound > 0)
Target.PlayEffect(Effect.Hit, hitSound);
}
}
// update hp
float new_hp = Math.Max(Target.Attributes[GameAttribute.Hitpoints_Cur] - TotalDamage, 0f);
Target.Attributes[GameAttribute.Hitpoints_Cur] = new_hp;
float newHp = Math.Max(Target.Attributes[GameAttribute.Hitpoints_Cur] - TotalDamage, 0f);
Target.Attributes[GameAttribute.Hitpoints_Cur] = newHp;
Target.Attributes.BroadcastChangedIfRevealed();
//thorns
@ -766,21 +768,23 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
*/
// if hp=0 do death
if (new_hp <= 0f)
if (newHp <= 0f)
{
var deathload = new DeathPayload(Context, DominantDamageType, Target, Target.HasLoot);
deathload.AutomaticHitEffects = AutomaticHitEffects;
var deathPayload = new DeathPayload(Context, DominantDamageType, Target, Target.HasLoot)
{
AutomaticHitEffects = AutomaticHitEffects
};
if (deathload.Successful)
if (deathPayload.Successful)
{
Target.Dead = true;
try
{
if (OnDeath != null && AutomaticHitEffects)
OnDeath(deathload);
OnDeath(deathPayload);
}
catch { }
deathload.Apply();
deathPayload.Apply();
}
}
else if (AutomaticHitEffects && Target.World != null && Target is not Player)
@ -800,13 +804,13 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
{
if (Target.IsRevealedToPlayer(plr))
{
float BackSpeed = Target.WalkSpeed;
float backSpeed = Target.WalkSpeed;
Target.WalkSpeed = 0f;
TickTimer Timeout = new SecondsTickTimer(Target.World.Game, 0.3f);
var Boom = Task<bool>.Factory.StartNew(() => WaitTo(Timeout));
Boom.ContinueWith(delegate
TickTimer timeout = new SecondsTickTimer(Target.World.Game, 0.3f);
var boom = Task<bool>.Factory.StartNew(() => WaitTo(timeout));
boom.ContinueWith(_ =>
{
Target.WalkSpeed = BackSpeed;
Target.WalkSpeed = backSpeed;
});
}
}

View File

@ -178,20 +178,17 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem
public EffectActor SpawnEffect(ActorSno actorSNO, Vector3D position, float angle = 0, TickTimer timeout = null)
{
if (Math.Abs(angle - (-1)) < 0.0001)
if (Math.Abs(angle - -1) < Globals.FLOAT_TOLERANCE)
angle = (float)(Rand.NextDouble() * (Math.PI * 2));
if (timeout == null)
{
if (_defaultEffectTimeout == null)
_defaultEffectTimeout = new SecondsTickTimer(World.Game, 2f); // default timeout of 2 seconds for now
_defaultEffectTimeout ??= new SecondsTickTimer(World.Game, 2f);
timeout = _defaultEffectTimeout;
}
var actor = new EffectActor(this, actorSNO, position);
actor.Timeout = timeout;
actor.Spawn(angle);
//187359
return actor;
}

View File

@ -11,35 +11,54 @@ namespace DiIiS_NA.GameServer.GSSystem.SkillsSystem
{
public class SkillSet
{
public ToonClass @Class;
public Toon Toon { get; private set; }
public Player Player { get; private set; }
public ToonClass ToonClass { get; }
public Toon Toon { get; }
public Player Player { get; }
public ActiveSkillSavedData[] ActiveSkills;
public HotbarButtonData[] HotBarSkills;
public int[] PassiveSkills;
public ActiveSkillSavedData[] ActiveSkills { get; }
public HotbarButtonData[] HotBarSkills { get; }
public int[] PassiveSkills { get; }
protected static readonly Logger Logger = LogManager.CreateLogger();
public SkillSet(Player player, ToonClass @class, Toon toon)
public SkillSet(Player player, ToonClass toonClass, Toon toon)
{
@Class = @class;
ToonClass = toonClass;
Player = player;
var dbToon = player.Toon.DBToon;
// var dbToon = player.Toon.DBToon;
var dbActiveSkills = player.Toon.DBActiveSkills;
ActiveSkills = new ActiveSkillSavedData[6] {
new ActiveSkillSavedData { snoSkill = dbActiveSkills.Skill0,
snoRune = dbActiveSkills.Rune0 },
new ActiveSkillSavedData { snoSkill = dbActiveSkills.Skill1,
snoRune = dbActiveSkills.Rune1 },
new ActiveSkillSavedData { snoSkill = dbActiveSkills.Skill2,
snoRune = dbActiveSkills.Rune2 },
new ActiveSkillSavedData { snoSkill = dbActiveSkills.Skill3,
snoRune = dbActiveSkills.Rune3 },
new ActiveSkillSavedData { snoSkill = dbActiveSkills.Skill4,
snoRune = dbActiveSkills.Rune4 },
new ActiveSkillSavedData { snoSkill = dbActiveSkills.Skill5,
snoRune = dbActiveSkills.Rune5 },
ActiveSkills = new ActiveSkillSavedData[6]
{
new()
{
snoSkill = dbActiveSkills.Skill0,
snoRune = dbActiveSkills.Rune0
},
new()
{
snoSkill = dbActiveSkills.Skill1,
snoRune = dbActiveSkills.Rune1
},
new()
{
snoSkill = dbActiveSkills.Skill2,
snoRune = dbActiveSkills.Rune2
},
new()
{
snoSkill = dbActiveSkills.Skill3,
snoRune = dbActiveSkills.Rune3
},
new()
{
snoSkill = dbActiveSkills.Skill4,
snoRune = dbActiveSkills.Rune4
},
new()
{
snoSkill = dbActiveSkills.Skill5,
snoRune = dbActiveSkills.Rune5
},
};
PassiveSkills = new int[4] {
@ -51,18 +70,18 @@ namespace DiIiS_NA.GameServer.GSSystem.SkillsSystem
//}
HotBarSkills = new HotbarButtonData[6] {
new HotbarButtonData { SNOSkill = ActiveSkills[0].snoSkill, ItemAnn = ActiveSkills[0].snoRune, ItemGBId = -1, RuneType = -1 }, // left-click
new HotbarButtonData { SNOSkill = ActiveSkills[1].snoSkill, ItemAnn = ActiveSkills[1].snoRune, ItemGBId = -1, RuneType = -1 }, // right-click
new HotbarButtonData { SNOSkill = ActiveSkills[2].snoSkill, ItemAnn = ActiveSkills[2].snoRune, ItemGBId = -1, RuneType = -1 }, // bar-1
new HotbarButtonData { SNOSkill = ActiveSkills[3].snoSkill, ItemAnn = ActiveSkills[3].snoRune, ItemGBId = -1, RuneType = -1 }, // bar-2
new HotbarButtonData { SNOSkill = ActiveSkills[4].snoSkill, ItemAnn = ActiveSkills[4].snoRune, ItemGBId = -1, RuneType = -1 }, // bar-3
new HotbarButtonData { SNOSkill = ActiveSkills[5].snoSkill, ItemAnn = ActiveSkills[5].snoRune, ItemGBId = -1, RuneType = -1 }, // bar-4
new() { SNOSkill = ActiveSkills[0].snoSkill, ItemAnn = ActiveSkills[0].snoRune, ItemGBId = -1, RuneType = -1 }, // left-click
new() { SNOSkill = ActiveSkills[1].snoSkill, ItemAnn = ActiveSkills[1].snoRune, ItemGBId = -1, RuneType = -1 }, // right-click
new() { SNOSkill = ActiveSkills[2].snoSkill, ItemAnn = ActiveSkills[2].snoRune, ItemGBId = -1, RuneType = -1 }, // bar-1
new() { SNOSkill = ActiveSkills[3].snoSkill, ItemAnn = ActiveSkills[3].snoRune, ItemGBId = -1, RuneType = -1 }, // bar-2
new() { SNOSkill = ActiveSkills[4].snoSkill, ItemAnn = ActiveSkills[4].snoRune, ItemGBId = -1, RuneType = -1 }, // bar-3
new() { SNOSkill = ActiveSkills[5].snoSkill, ItemAnn = ActiveSkills[5].snoRune, ItemGBId = -1, RuneType = -1 }, // bar-4
};
}
public void UpdateSkills(int hotBarIndex, int SNOSkill, int SNORune, Toon toon)
{
Logger.Debug("Update index {0} skill {1} rune {2}", hotBarIndex, SNOSkill, SNORune);
Logger.MethodTrace(string.Format("Update index {0} skill {1} rune {2}", hotBarIndex, SNOSkill, SNORune));
var dbActiveSkills = Player.Toon.DBActiveSkills;
switch (hotBarIndex)
{
@ -119,31 +138,12 @@ namespace DiIiS_NA.GameServer.GSSystem.SkillsSystem
}
}
public bool HasPassive(int passiveId)
{
if (PassiveSkills.Contains(passiveId))
return true;
else
return false;
}
public bool HasPassive(int passiveId) => PassiveSkills.Contains(passiveId);
public bool HasSkill(int skillId)
{
return ActiveSkills.Any(s => s.snoSkill == skillId);
}
public bool HasSkill(int skillId) => ActiveSkills.Any(s => s.snoSkill == skillId);
public bool HasSkillWithRune(int skillId, int runeId)
{
return ActiveSkills.Any(s => s.snoSkill == skillId && s.snoRune == runeId);
}
public bool HasSkillWithRune(int skillId, int runeId) => ActiveSkills.Any(s => s.snoSkill == skillId && s.snoRune == runeId);
public bool HasItemPassiveProc(int passiveId)
{
if ((float)FastRandom.Instance.NextDouble() < Player.Attributes[GameAttribute.Item_Power_Passive, passiveId])
return true;
else
return false;
}
public bool HasItemPassiveProc(int passiveId) => (float)FastRandom.Instance.NextDouble() < Player.Attributes[GameAttribute.Item_Power_Passive, passiveId];
}
}

View File

@ -50,6 +50,14 @@ namespace DiIiS_NA.GameServer
set => Set(nameof(CoreActive), value);
}
public bool IWServer
{
get => GetBoolean(nameof(IWServer), true);
set => Set(nameof(IWServer), value);
}
#region Game Mods
/// <summary>
/// Rate of experience gain.
/// </summary>
@ -101,12 +109,6 @@ namespace DiIiS_NA.GameServer
set => Set(nameof(RateMonsterDMG), value);
}
public bool IWServer
{
get => GetBoolean(nameof(IWServer), true);
set => Set(nameof(IWServer), value);
}
/// <summary>
/// Percentage that a unique, legendary, set or special item created is unidentified
/// </summary>
@ -197,6 +199,79 @@ namespace DiIiS_NA.GameServer
set => Set(nameof(UnlockAllWaypoints), value);
}
/// <summary>
/// Strength multiplier when you're not a paragon.
/// </summary>
public float StrengthMultiplier
{
get => GetFloat(nameof(StrengthMultiplier), 1f);
set => Set(nameof(StrengthMultiplier), value);
}
/// <summary>
/// Strength multiplier when you're a paragon.
/// </summary>
public float StrengthParagonMultiplier
{
get => GetFloat(nameof(StrengthParagonMultiplier), 1f);
set => Set(nameof(StrengthParagonMultiplier), value);
}
/// <summary>
/// Dexterity multiplier when you're not a paragon.
/// </summary>
public float DexterityMultiplier
{
get => GetFloat(nameof(DexterityMultiplier), 1f);
set => Set(nameof(DexterityMultiplier), value);
}
/// <summary>
/// Dexterity multiplier when you're a paragon.
/// </summary>
public float DexterityParagonMultiplier
{
get => GetFloat(nameof(DexterityParagonMultiplier), 1f);
set => Set(nameof(DexterityParagonMultiplier), value);
}
/// <summary>
/// Intelligence multiplier when you're not a paragon.
/// </summary>
public float IntelligenceMultiplier
{
get => GetFloat(nameof(IntelligenceMultiplier), 1f);
set => Set(nameof(IntelligenceMultiplier), value);
}
/// <summary>
/// Intelligence multiplier when you're a paragon.
/// </summary>
public float IntelligenceParagonMultiplier
{
get => GetFloat(nameof(IntelligenceParagonMultiplier), 1f);
set => Set(nameof(IntelligenceParagonMultiplier), value);
}
/// <summary>
/// Vitality multiplier when you're not a paragon.
/// </summary>
public float VitalityMultiplier
{
get => GetFloat(nameof(VitalityMultiplier), 1f);
set => Set(nameof(VitalityMultiplier), value);
}
/// <summary>
/// Vitality multiplier when you're a paragon.
/// </summary>
public float VitalityParagonMultiplier
{
get => GetFloat(nameof(VitalityParagonMultiplier), 1f);
set => Set(nameof(VitalityParagonMultiplier), value);
}
#endregion
public static GameServerConfig Instance { get; } = new();

View File

@ -4,7 +4,8 @@ using System.Configuration;
namespace DiIiS_NA
{
public static class Extensions
internal static class Globals
{
public const float FLOAT_TOLERANCE = 0.0001f;
}
}

View File

@ -30,7 +30,8 @@ namespace DiIiS_NA.REST.Http
Found = 302,
BadRequest = 400,
NotFound = 404,
InternalServerError = 500
InternalServerError = 500,
BadGateway = 502
}
public class HttpHelper

View File

@ -12,6 +12,7 @@ using DiIiS_NA.REST.Data.Authentication;
using DiIiS_NA.REST.JSON;
using DiIiS_NA.LoginServer.AccountsSystem;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Web;
using DiIiS_NA.GameServer.MessageSystem;
@ -41,26 +42,19 @@ namespace DiIiS_NA.REST
}
else
{
Logger.Info($"$[yellow]$REST Request: $[/]$ {httpRequest.Method} {httpRequest.Path}");
Logger.Debug($"$[yellow]$REST Request: $[/]$ {httpRequest.Method} {httpRequest.Path}");
if (httpRequest.Path == "200")
{
}
else if (httpRequest.Path.Contains("/client/alert"))
{
switch (httpRequest.Method)
{
case "GET":
default:
HandleInfoRequest(httpRequest);
break;
}
}
else
else if (httpRequest.Path.Contains("/battlenet/login"))
{
switch (httpRequest.Method)
{
case "GET":
default:
HandleConnectRequest(httpRequest);
break;
@ -69,30 +63,34 @@ namespace DiIiS_NA.REST
return;
}
}
else
{
#if DEBUG
Logger.Info($"$[red]$[404] REST Request: $[/]$ {httpRequest.Method} {httpRequest.Path}");
SendResponseHtml(HttpCode.NotFound, "404 Not Found");
#else
// sends 502 Bad Gateway to the client to prevent the client from trying to connect to the server again - in case it's a crawler or bad bot.
Logger.Info($"$[red]$[404/502] REST Request: $[/]$ {httpRequest.Method} {httpRequest.Path}");
SendResponseHtml(HttpCode.BadGateway, "502 Bad Gateway");
return;
#endif
}
}
AsyncRead();
}
public void HandleConnectRequest(HttpHeader request)
void HandleConnectRequest(HttpHeader request)
{
SendResponse(HttpCode.OK, SessionManager.Instance.GetFormInput());
}
public void HandleInfoRequest(HttpHeader request)
void HandleInfoRequest(HttpHeader request)
{
SendResponseHtml(HttpCode.OK, "Welcome to BlizzLess.Net" +
"\nBuild " + Program.Build +
"\nSupport: 2.7.4");
}
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();
}
void SendResponse<T>(HttpCode code, T response)
{
AsyncWrite(HttpHelper.CreateResponse(code, JSON.Json.CreateString(response)));
@ -107,7 +105,8 @@ namespace DiIiS_NA.REST
{
AsyncRead();
}
public void HandleLoginRequest(HttpHeader request)
void HandleLoginRequest(HttpHeader request)
{
LogonData loginForm = Json.CreateObject<LogonData>(request.Content);
LogonResult loginResult = new LogonResult();