Rifts improvement.

- Finishes the rift automatically if config.ini has NephalemAutoFinish is set to true, if it's true, if there are less than NephalemRiftAutoFinish monsters alive, finishes rift (and goes to boss). Disabled by default.
- Added NephalemRiftOrbsChance (rate at which a orb is spawned).
- SpawnGenerator.cs added hexmaze
- DeathPayload.cs improvement
This commit is contained in:
Lucca Faria Ferri 2023-02-09 22:48:41 -08:00
parent 0f807d56b0
commit e2d3344974
4 changed files with 393 additions and 251 deletions

View File

@ -26,6 +26,7 @@ using System.Linq;
using DiIiS_NA.Core.MPQ; using DiIiS_NA.Core.MPQ;
using DiIiS_NA.Core.MPQ.FileFormats; using DiIiS_NA.Core.MPQ.FileFormats;
using DiIiS_NA.D3_GameServer.GSSystem.GameSystem; using DiIiS_NA.D3_GameServer.GSSystem.GameSystem;
using DiIiS_NA.LoginServer.Battle;
using Circle = DiIiS_NA.GameServer.Core.Types.Misc.Circle; using Circle = DiIiS_NA.GameServer.Core.Types.Misc.Circle;
using Player = DiIiS_NA.GameServer.GSSystem.PlayerSystem.Player; using Player = DiIiS_NA.GameServer.GSSystem.PlayerSystem.Player;
using Scene = DiIiS_NA.GameServer.GSSystem.MapSystem.Scene; using Scene = DiIiS_NA.GameServer.GSSystem.MapSystem.Scene;
@ -143,6 +144,7 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem
public bool HasLoot { get; set; } public bool HasLoot { get; set; }
public bool Dead = false; public bool Dead = false;
public bool Alive => !Dead;
/// <summary> /// <summary>
/// Gets whether the actor is visible by questrange, privately set on quest progress /// Gets whether the actor is visible by questrange, privately set on quest progress
@ -213,14 +215,15 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem
public int? MarkerSetIndex { get; private set; } public int? MarkerSetIndex { get; private set; }
private int snoTriggeredConversation = -1; private int _snoTriggeredConversation = -1;
/// <summary> /// <summary>
/// Creates a new actor. /// Creates a new actor.
/// </summary> /// </summary>
/// <param name="world">The world that initially belongs to.</param> /// <param name="world">The world that initially belongs to.</param>
/// <param name="sno">SNOId of the actor.</param> /// <param name="sno">SNOId of the actor.</param>
/// <param name="tags">TagMapEntry dictionary read for the actor from MPQ's..</param> /// <param name="tags">TagMapEntry dictionary read for the actor from MPQ's..</param>
/// <param name="isMarker">Is Marker</param>
protected Actor(World world, ActorSno sno, TagMap tags, bool isMarker = false) protected Actor(World world, ActorSno sno, TagMap tags, bool isMarker = false)
: base(world, world.IsPvP ? World.NewActorPvPID : world.Game.NewActorGameId) : base(world, world.IsPvP ? World.NewActorPvPID : world.Game.NewActorGameId)
{ {
@ -313,7 +316,7 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem
public virtual void EnterWorld(Vector3D position) public virtual void EnterWorld(Vector3D position)
{ {
var Quest = MPQStorage.Data.Assets[SNOGroup.Quest][74128]; // var quest = MPQStorage.Data.Assets[SNOGroup.Quest][74128];
if (World != null) if (World != null)
{ {
@ -530,11 +533,11 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem
if (Dicts.DictSNOEffectGroup.ContainsValue(effectGroupSNO)) if (Dicts.DictSNOEffectGroup.ContainsValue(effectGroupSNO))
{ {
var effectGroupKey = Dicts.DictSNOEffectGroup.FirstOrDefault(x => x.Value == effectGroupSNO).Key; var effectGroupKey = Dicts.DictSNOEffectGroup.FirstOrDefault(x => x.Value == effectGroupSNO).Key;
Logger.Warn($"PlayEffectGroup {effectGroupSNO} on {GetType().Name}. Type: {effectGroupKey}"); Logger.MethodTrace($"{effectGroupSNO} on {GetType().Name}. Type: $[green]${effectGroupKey}$[/]$");
} }
else else
{ {
Logger.Warn($"PlayEffectGroup {effectGroupSNO} on {GetType().Name}. Type: Unknown"); Logger.MethodTrace($"{effectGroupSNO} on {GetType().Name}. Type: $[red]$Unknown$[/]$");
} }
#endif #endif
PlayEffect(Effect.PlayEffectGroup, effectGroupSNO); PlayEffect(Effect.PlayEffectGroup, effectGroupSNO);
@ -1305,7 +1308,7 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem
if (Tags.ContainsKey(MarkerKeys.TriggeredConversation)) if (Tags.ContainsKey(MarkerKeys.TriggeredConversation))
snoTriggeredConversation = Tags[MarkerKeys.TriggeredConversation].Id; _snoTriggeredConversation = Tags[MarkerKeys.TriggeredConversation].Id;
} }
#endregion #endregion

View File

@ -30,24 +30,15 @@ namespace DiIiS_NA.GameServer.GSSystem.GeneratorsSystem
return total; return total;
} }
public static bool IsMelee(int la, int monsterId) public static bool IsMelee(int la, int monsterId) => Spawns[la].melee.Contains(monsterId);
{
return Spawns[la].melee.Contains(monsterId);
}
public static bool IsRange(int la, int monsterId) public static bool IsRange(int la, int monsterId) => Spawns[la].range.Contains(monsterId);
{
return Spawns[la].range.Contains(monsterId);
}
public static bool IsDangerous(int la, int monsterId) public static bool IsDangerous(int la, int monsterId) => Spawns[la].dangerous.Contains(monsterId);
{
return Spawns[la].dangerous.Contains(monsterId);
}
public static void RegenerateDensity() public static void RegenerateDensity()
{ {
//Logger.Info("Regenerating spawn density map..."); Logger.Info("Regenerating spawn density map...");
foreach (var spawn in Spawns) foreach (var spawn in Spawns)
{ {
Spawns[spawn.Key].additional_density = FastRandom.Instance.Next(0, 6); Spawns[spawn.Key].additional_density = FastRandom.Instance.Next(0, 6);
@ -55,7 +46,7 @@ namespace DiIiS_NA.GameServer.GSSystem.GeneratorsSystem
} }
// key is WorldSno, LevelArea // key is WorldSno, LevelArea
public static Dictionary<int, MonsterLayout> Spawns = new Dictionary<int, MonsterLayout> public static readonly Dictionary<int, MonsterLayout> Spawns = new()
{ {
#region Act I #region Act I
{91324, new MonsterLayout{ lazy_load = false, additional_density = 0, can_spawn_goblin = false, melee = new List<int>{ 6652, 203121, 6644 }, range = new List<int>{ 219725 }, dangerous = new List<int>{ 218339 }}}, //REMOVED 4982 QUILL FIEND (OP damage) //road to Old Tristram ruins {91324, new MonsterLayout{ lazy_load = false, additional_density = 0, can_spawn_goblin = false, melee = new List<int>{ 6652, 203121, 6644 }, range = new List<int>{ 219725 }, dangerous = new List<int>{ 218339 }}}, //REMOVED 4982 QUILL FIEND (OP damage) //road to Old Tristram ruins
@ -241,6 +232,7 @@ namespace DiIiS_NA.GameServer.GSSystem.GeneratorsSystem
//x1_lr_tileset_zoltruins //x1_lr_tileset_zoltruins
{288823, new MonsterLayout{ lazy_load = false, additional_density = 0, can_spawn_goblin = true, melee = new List<int>{ 5396, 5432, 208962, 208963, 204944, 5512 }, range = new List<int>{ 5428 }, dangerous = new List<int>{}}}, {288823, new MonsterLayout{ lazy_load = false, additional_density = 0, can_spawn_goblin = true, melee = new List<int>{ 5396, 5432, 208962, 208963, 204944, 5512 }, range = new List<int>{ 5428 }, dangerous = new List<int>{}}},
//x1_lr_tileset_hexmaze //x1_lr_tileset_hexmaze
{331389, new MonsterLayout{ lazy_load = false, additional_density = 0, can_spawn_goblin = true, melee = new List<int>{ 241288, 305579, 340920, 299231 }, range = new List<int>{ }, dangerous = new List<int>{ 363374, 363378, 363228, 363232, 363367, 360243, 360244, 360241, 363230 }}},
//x1_lr_tileset_icecave //x1_lr_tileset_icecave
{275960, new MonsterLayout{ lazy_load = false, additional_density = 0, can_spawn_goblin = true, melee = new List<int>{ 191592, 3342, 5239, 3850 }, range = new List<int>{ }, dangerous = new List<int>{}}}, {275960, new MonsterLayout{ lazy_load = false, additional_density = 0, can_spawn_goblin = true, melee = new List<int>{ 191592, 3342, 5239, 3850 }, range = new List<int>{ }, dangerous = new List<int>{}}},

View File

@ -121,14 +121,17 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
}); });
masterPlr.NecroSkeletons.Remove(skeletonA); masterPlr.NecroSkeletons.Remove(skeletonA);
} }
if (Target is Minion { Master: Player masterPlr2 } and (BaseGolem or IceGolem or BoneGolem or DecayGolem or ConsumeFleshGolem or BloodGolem))
{ if (Target is Minion { Master: Player masterPlr2 }
and (BaseGolem or IceGolem or BoneGolem or DecayGolem or ConsumeFleshGolem or BloodGolem))
{
masterPlr2.InGameClient.SendMessage(new MessageSystem.Message.Definitions.Pet.PetDetachMessage() masterPlr2.InGameClient.SendMessage(new MessageSystem.Message.Definitions.Pet.PetDetachMessage()
{ {
PetId = Target.DynamicID((Target as Minion).Master as Player) PetId = Target.DynamicID((Target as Minion).Master as Player)
}); });
masterPlr2.ActiveGolem = null; masterPlr2.ActiveGolem = null;
} }
if (Target is Player user) if (Target is Player user)
{ {
if (user.SkillSet.HasPassive(208779)) //Grenadier (DH) if (user.SkillSet.HasPassive(208779)) //Grenadier (DH)
@ -143,7 +146,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
} }
if (Context != null) if (Context != null)
if (Context.User is Player player) //Hitpoints_On_Kill if (Context.User is Player player) //Hitpoints_On_Kill
if (player.Attributes[GameAttribute.Hitpoints_On_Kill] > 0) if (player.Attributes[GameAttribute.Hitpoints_On_Kill] > 0)
player.AddHP(player.Attributes[GameAttribute.Hitpoints_On_Kill]); player.AddHP(player.Attributes[GameAttribute.Hitpoints_On_Kill]);
@ -172,11 +175,12 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
if (Target is Minion minionTarget) if (Target is Minion minionTarget)
{ {
if (minionTarget.Master != null && minionTarget.Master is Player) if (minionTarget.Master != null && minionTarget.Master is Player player)
{ {
(minionTarget.Master as Player).Followers.Remove(minionTarget.GlobalID); player.Followers.Remove(minionTarget.GlobalID);
(minionTarget.Master as Player).FreeFollowerIndex(minionTarget.SNO); player.FreeFollowerIndex(minionTarget.SNO);
} }
if (minionTarget.Brain != null) if (minionTarget.Brain != null)
minionTarget.Brain.Kill(); minionTarget.Brain.Kill();
@ -185,7 +189,8 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
if (Target is Champion) if (Target is Champion)
{ {
bool championsAlive = Target.GetActorsInRange<Champion>(1000).Where(c => c.GroupId == Target.GroupId && c.Attributes[GameAttribute.Hitpoints_Cur] > 0).ToList().Count > 0; bool championsAlive = Target.GetActorsInRange<Champion>(1000).Where(c =>
c.GroupId == Target.GroupId && c.Attributes[GameAttribute.Hitpoints_Cur] > 0).ToList().Count > 0;
if (championsAlive) if (championsAlive)
LootAndExp = false; LootAndExp = false;
} }
@ -219,8 +224,8 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
case ActorSno._triunevessel_event31: case ActorSno._triunevessel_event31:
//Падшие //Падшие
case ActorSno._fallengrunt_a: case ActorSno._fallengrunt_a:
Target.PlayAnimation(11, AnimationSno.triunesummoner_death_02_persistentblood, 1f); Target.PlayAnimation(11, AnimationSno.triunesummoner_death_02_persistentblood, 1f);
break; break;
//Разнощик чумы //Разнощик чумы
case ActorSno._fleshpitflyer_b: case ActorSno._fleshpitflyer_b:
//Пчелы //Пчелы
@ -230,8 +235,8 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
break; break;
//X1_LR_Boss_Angel_Corrupt_A //X1_LR_Boss_Angel_Corrupt_A
case ActorSno._x1_lr_boss_angel_corrupt_a: case ActorSno._x1_lr_boss_angel_corrupt_a:
Target.PlayAnimation(11, AnimationSno.angel_corrupt_death_01, 1f); Target.PlayAnimation(11, AnimationSno.angel_corrupt_death_01, 1f);
break; break;
default: default:
var animation = FindBestDeathAnimationSNO(); var animation = FindBestDeathAnimationSNO();
if (animation != AnimationSno._NONE) if (animation != AnimationSno._NONE)
@ -240,6 +245,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
{ {
Logger.Warn("Death animation not found: ActorSNOId = {0}", Target.SNO); Logger.Warn("Death animation not found: ActorSNOId = {0}", Target.SNO);
} }
break; break;
} }
@ -266,24 +272,56 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
}, Target); }, Target);
if (Context?.User != null) if (Context?.User != null)
if (Math.Abs(Context.User.Attributes[GameAttribute.Item_Power_Passive, 247640] - 1) < Globals.FLOAT_TOLERANCE || if (Math.Abs(Context.User.Attributes[GameAttribute.Item_Power_Passive, 247640] - 1) <
Math.Abs(Context.User.Attributes[GameAttribute.Item_Power_Passive, 249963] - 1) < Globals.FLOAT_TOLERANCE || Globals.FLOAT_TOLERANCE ||
Math.Abs(Context.User.Attributes[GameAttribute.Item_Power_Passive, 249954] - 1) < Globals.FLOAT_TOLERANCE || Math.Abs(Context.User.Attributes[GameAttribute.Item_Power_Passive, 249963] - 1) <
(float)FastRandom.Instance.NextDouble() < 0.1f || Globals.FLOAT_TOLERANCE ||
Target.World.SNO == WorldSno.a1dun_random_level01) 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) switch ((int)DeathDamageType.HitEffect)
{ {
case 0: Target.World.BroadcastIfRevealed(plr => new PlayEffectMessage() { ActorId = Target.DynamicID(plr), Effect = Effect.Gore }, Target); break; case 0:
case 1: Target.World.BroadcastIfRevealed(plr => new PlayEffectMessage() { ActorId = Target.DynamicID(plr), Effect = Effect.GoreFire }, Target); break; Target.World.BroadcastIfRevealed(
case 2: Target.World.BroadcastIfRevealed(plr => new PlayEffectMessage() { ActorId = Target.DynamicID(plr), Effect = Effect.GoreElectro }, Target); break; plr => new PlayEffectMessage()
case 3: Target.World.BroadcastIfRevealed(plr => new PlayEffectMessage() { ActorId = Target.DynamicID(plr), Effect = Effect.IceBreak }, Target); break; { ActorId = Target.DynamicID(plr), Effect = Effect.Gore }, Target);
case 4: Target.World.BroadcastIfRevealed(plr => new PlayEffectMessage() { ActorId = Target.DynamicID(plr), Effect = Effect.GorePoison }, Target); break; break;
case 5: Target.World.BroadcastIfRevealed(plr => new PlayEffectMessage() { ActorId = Target.DynamicID(plr), Effect = Effect.GoreArcane }, Target); break; case 1:
case 6: Target.World.BroadcastIfRevealed(plr => new PlayEffectMessage() { ActorId = Target.DynamicID(plr), Effect = Effect.GoreHoly }, Target); break; Target.World.BroadcastIfRevealed(
plr => new PlayEffectMessage()
{ ActorId = Target.DynamicID(plr), Effect = Effect.GoreFire }, Target);
break;
case 2:
Target.World.BroadcastIfRevealed(
plr => new PlayEffectMessage()
{ ActorId = Target.DynamicID(plr), Effect = Effect.GoreElectro }, Target);
break;
case 3:
Target.World.BroadcastIfRevealed(
plr => new PlayEffectMessage()
{ ActorId = Target.DynamicID(plr), Effect = Effect.IceBreak }, Target);
break;
case 4:
Target.World.BroadcastIfRevealed(
plr => new PlayEffectMessage()
{ ActorId = Target.DynamicID(plr), Effect = Effect.GorePoison }, Target);
break;
case 5:
Target.World.BroadcastIfRevealed(
plr => new PlayEffectMessage()
{ ActorId = Target.DynamicID(plr), Effect = Effect.GoreArcane }, Target);
break;
case 6:
Target.World.BroadcastIfRevealed(
plr => new PlayEffectMessage()
{ ActorId = Target.DynamicID(plr), Effect = Effect.GoreHoly }, Target);
break;
} }
if (Context != null) if (Context != null)
if (Context.User is Player player && Math.Abs(player.Attributes[GameAttribute.Level] - Target.Attributes[GameAttribute.Level]) < 5) if (Context.User is Player player &&
Math.Abs(player.Attributes[GameAttribute.Level] - Target.Attributes[GameAttribute.Level]) < 5)
player.KilledSeasonalTempCount++; player.KilledSeasonalTempCount++;
if (Context?.User is Player plr2) if (Context?.User is Player plr2)
@ -303,7 +341,9 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
if (Target.World.SNO == WorldSno.a4dun_garden_of_hope_01) if (Target.World.SNO == WorldSno.a4dun_garden_of_hope_01)
{ {
//Check if there are portals //Check if there are portals
var portalToHell = Target.World.GetActorsBySNO(ActorSno._a4_heaven_gardens_hellportal); //{[Actor] [Type: Gizmo] SNOId:224890 DynamicId: 280 Position: x:696,681 y:695,4387 z:0,2636871 Name: a4_Heaven_Gardens_HellPortal} var portalToHell =
Target.World.GetActorsBySNO(ActorSno
._a4_heaven_gardens_hellportal); //{[Actor] [Type: Gizmo] SNOId:224890 DynamicId: 280 Position: x:696,681 y:695,4387 z:0,2636871 Name: a4_Heaven_Gardens_HellPortal}
if (portalToHell.Count == 0) if (portalToHell.Count == 0)
{ {
var corruptions = Target.World.GetActorsBySNO(ActorSno._a4dun_garden_corruption_monster); var corruptions = Target.World.GetActorsBySNO(ActorSno._a4dun_garden_corruption_monster);
@ -311,7 +351,8 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
{ {
if (RandomHelper.Next(0, 30) > 26) if (RandomHelper.Next(0, 30) > 26)
{ {
Portal hellPortal = new Portal(Target.World, ActorSno._a4_heaven_gardens_hellportal, Target.World.StartingPoints[0].Tags); Portal hellPortal = new Portal(Target.World, ActorSno._a4_heaven_gardens_hellportal,
Target.World.StartingPoints[0].Tags);
hellPortal.EnterWorld(Target.Position); hellPortal.EnterWorld(Target.Position);
Context.User.World.SpawnMonster(ActorSno._diablo_vo, Context.User.Position); Context.User.World.SpawnMonster(ActorSno._diablo_vo, Context.User.Position);
StartConversation(Target.World, 217226); StartConversation(Target.World, 217226);
@ -319,7 +360,8 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
} }
else else
{ {
Portal hellPortal = new Portal(Target.World, ActorSno._a4_heaven_gardens_hellportal, Target.World.StartingPoints[0].Tags); Portal hellPortal = new Portal(Target.World, ActorSno._a4_heaven_gardens_hellportal,
Target.World.StartingPoints[0].Tags);
hellPortal.EnterWorld(Target.Position); hellPortal.EnterWorld(Target.Position);
Context.User.World.SpawnMonster(ActorSno._diablo_vo, Context.User.Position); Context.User.World.SpawnMonster(ActorSno._diablo_vo, Context.User.Position);
StartConversation(Target.World, 217226); StartConversation(Target.World, 217226);
@ -328,8 +370,11 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
} }
//Second floor of the gardens of hope //Second floor of the gardens of hope
else if (Target.World.SNO == WorldSno.a4dun_garden_of_hope_random) else if (Target.World.SNO == WorldSno.a4dun_garden_of_hope_random)
{ //Check if there are portals {
var portalToHell = Target.World.GetActorsBySNO(ActorSno._a4_heaven_gardens_hellportal); //{[Actor] [Type: Gizmo] SNOId:224890 DynamicId: 280 Position: x:696,681 y:695,4387 z:0,2636871 Name: a4_Heaven_Gardens_HellPortal} //Check if there are portals
var portalToHell =
Target.World.GetActorsBySNO(ActorSno
._a4_heaven_gardens_hellportal); //{[Actor] [Type: Gizmo] SNOId:224890 DynamicId: 280 Position: x:696,681 y:695,4387 z:0,2636871 Name: a4_Heaven_Gardens_HellPortal}
if (portalToHell.Count == 0) if (portalToHell.Count == 0)
{ {
var corruptions = Target.World.GetActorsBySNO(ActorSno._a4dun_garden_corruption_monster); var corruptions = Target.World.GetActorsBySNO(ActorSno._a4dun_garden_corruption_monster);
@ -337,7 +382,8 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
{ {
if (RandomHelper.Next(0, 30) > 26) if (RandomHelper.Next(0, 30) > 26)
{ {
Portal hellPortal = new Portal(Target.World, ActorSno._a4_heaven_gardens_hellportal, Target.World.StartingPoints[0].Tags); Portal hellPortal = new Portal(Target.World, ActorSno._a4_heaven_gardens_hellportal,
Target.World.StartingPoints[0].Tags);
hellPortal.EnterWorld(Target.Position); hellPortal.EnterWorld(Target.Position);
if (Context.User.World.GetActorsBySNO(ActorSno._diablo_vo).Count == 0) if (Context.User.World.GetActorsBySNO(ActorSno._diablo_vo).Count == 0)
Context.User.World.SpawnMonster(ActorSno._diablo_vo, Context.User.Position); Context.User.World.SpawnMonster(ActorSno._diablo_vo, Context.User.Position);
@ -346,7 +392,8 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
} }
else else
{ {
Portal hellPortal = new Portal(Target.World, ActorSno._a4_heaven_gardens_hellportal, Target.World.StartingPoints[0].Tags); Portal hellPortal = new Portal(Target.World, ActorSno._a4_heaven_gardens_hellportal,
Target.World.StartingPoints[0].Tags);
hellPortal.EnterWorld(Target.Position); hellPortal.EnterWorld(Target.Position);
if (Context.User.World.GetActorsBySNO(ActorSno._diablo_vo).Count == 0) if (Context.User.World.GetActorsBySNO(ActorSno._diablo_vo).Count == 0)
Context.User.World.SpawnMonster(ActorSno._diablo_vo, Context.User.Position); Context.User.World.SpawnMonster(ActorSno._diablo_vo, Context.User.Position);
@ -362,9 +409,14 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
{ {
int grantedExp = 0; int grantedExp = 0;
if (plr.Attributes[GameAttribute.Level] <= Target.Attributes[GameAttribute.Level]) if (plr.Attributes[GameAttribute.Level] <= Target.Attributes[GameAttribute.Level])
grantedExp = (int)(Player.LevelBorders[plr.Attributes[GameAttribute.Level]] / (40 * Target.Attributes[GameAttribute.Level] * 0.85f) * (Target is Monster ? Math.Min((Target as Monster).HpMultiplier, 3f) : 1f)); grantedExp = (int)(Player.LevelBorders[plr.Attributes[GameAttribute.Level]] /
(40 * Target.Attributes[GameAttribute.Level] * 0.85f) *
(Target is Monster monster1 ? Math.Min(monster1.HpMultiplier, 3f) : 1f));
else else
grantedExp = (int)(Player.LevelBorders[plr.Attributes[GameAttribute.Level]] / (40 * Target.Attributes[GameAttribute.Level] * 0.85f) * (1 - Math.Abs(plr.Attributes[GameAttribute.Level] - Target.Attributes[GameAttribute.Level]) / 20)); grantedExp = (int)(Player.LevelBorders[plr.Attributes[GameAttribute.Level]] /
(40 * Target.Attributes[GameAttribute.Level] * 0.85f) * (1 -
Math.Abs(plr.Attributes[GameAttribute.Level] - Target.Attributes[GameAttribute.Level]) /
20));
grantedExp = (int)(grantedExp * (plr.Attributes[GameAttribute.Experience_Bonus_Percent] + 1)); grantedExp = (int)(grantedExp * (plr.Attributes[GameAttribute.Experience_Bonus_Percent] + 1));
grantedExp += (int)plr.Attributes[GameAttribute.Experience_Bonus]; grantedExp += (int)plr.Attributes[GameAttribute.Experience_Bonus];
@ -412,16 +464,20 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
plr.AddTimedAction(5f, new Action<int>((q) => plr.SpikeTrapsKilled--)); plr.AddTimedAction(5f, new Action<int>((q) => plr.SpikeTrapsKilled--));
} }
} }
if (plr.Toon.Class == ToonClass.Monk) if (plr.Toon.Class == ToonClass.Monk)
{ {
if (plr.Attributes[GameAttribute.Resource_Cur, 3] < plr.Attributes[GameAttribute.Resource_Max_Total, 3]) if (plr.Attributes[GameAttribute.Resource_Cur, 3] <
plr.Attributes[GameAttribute.Resource_Max_Total, 3])
plr.AddAchievementCounter(74987243307550, 1); plr.AddAchievementCounter(74987243307550, 1);
} }
if (plr.Toon.Class == ToonClass.Wizard) if (plr.Toon.Class == ToonClass.Wizard)
{ {
if (monster.Attributes[GameAttribute.Frozen]) if (monster.Attributes[GameAttribute.Frozen])
plr.AddAchievementCounter(74987243307585, 1); plr.AddAchievementCounter(74987243307585, 1);
} }
if (plr.Toon.Class == ToonClass.WitchDoctor) if (plr.Toon.Class == ToonClass.WitchDoctor)
{ {
if (Context.User.Attributes[GameAttribute.Team_Override] == 1) if (Context.User.Attributes[GameAttribute.Team_Override] == 1)
@ -444,7 +500,8 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
if (Target is Unique) if (Target is Unique)
{ {
if (LoreRegistry.Lore.ContainsKey(Target.World.SNO) && LoreRegistry.Lore[Target.World.SNO].chests_lore.ContainsKey(Target.SNO)) if (LoreRegistry.Lore.ContainsKey(Target.World.SNO) &&
LoreRegistry.Lore[Target.World.SNO].chests_lore.ContainsKey(Target.SNO))
foreach (int loreId in LoreRegistry.Lore[Target.World.SNO].chests_lore[Target.SNO]) foreach (int loreId in LoreRegistry.Lore[Target.World.SNO].chests_lore[Target.SNO])
if (!plr.HasLore(loreId)) if (!plr.HasLore(loreId))
{ {
@ -453,7 +510,8 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
} }
} }
if (plr.SkillSet.HasPassive(218191) && PowerMath.Distance2D(plr.Position, Target.Position) <= 20f + plr.Attributes[GameAttribute.Gold_PickUp_Radius]) //GraveInjustice (WD) if (plr.SkillSet.HasPassive(218191) && PowerMath.Distance2D(plr.Position, Target.Position) <=
20f + plr.Attributes[GameAttribute.Gold_PickUp_Radius]) //GraveInjustice (WD)
{ {
plr.AddHP(plr.Attributes[GameAttribute.Hitpoints_Max_Total] / 100f); plr.AddHP(plr.Attributes[GameAttribute.Hitpoints_Max_Total] / 100f);
plr.GeneratePrimaryResource(plr.Attributes[GameAttribute.Resource_Max_Total, 0] / 100f); plr.GeneratePrimaryResource(plr.Attributes[GameAttribute.Resource_Max_Total, 0] / 100f);
@ -461,7 +519,8 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
cdBuff.Reduce(60); cdBuff.Reduce(60);
} }
if (plr.SkillSet.HasPassive(357218) && PowerMath.Distance2D(plr.Position, Target.Position) <= 15f) //Fervor (Crusader) if (plr.SkillSet.HasPassive(357218) &&
PowerMath.Distance2D(plr.Position, Target.Position) <= 15f) //Fervor (Crusader)
{ {
plr.World.BuffManager.AddBuff(plr, plr, new FervorBuff()); plr.World.BuffManager.AddBuff(plr, plr, new FervorBuff());
} }
@ -477,7 +536,8 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
} }
if (Target.World.BuffManager.HasBuff<CrusaderJudgment.JudgedDebuffRooted>(Target)) //Crusader -> Judgment -> Conversion if (Target.World.BuffManager
.HasBuff<CrusaderJudgment.JudgedDebuffRooted>(Target)) //Crusader -> Judgment -> Conversion
if (Target.World.BuffManager.GetFirstBuff<CrusaderJudgment.JudgedDebuffRooted>(Target).conversion) if (Target.World.BuffManager.GetFirstBuff<CrusaderJudgment.JudgedDebuffRooted>(Target).conversion)
if (FastRandom.Instance.Next() < 0.2f) if (FastRandom.Instance.Next() < 0.2f)
{ {
@ -488,7 +548,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
avatar.EnterWorld(avatar.Position); avatar.EnterWorld(avatar.Position);
Task.Delay(1000).ContinueWith(d => Task.Delay(1000).ContinueWith(d =>
{ {
(avatar as Minion).Brain.Activate(); (avatar as Minion).Brain.Activate();
avatar.Attributes[GameAttribute.Untargetable] = false; avatar.Attributes[GameAttribute.Untargetable] = false;
@ -496,7 +556,10 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
}); });
} }
if (plr.SkillSet.HasPassive(208571) && PowerMath.Distance2D(plr.Position, Target.Position) <= 12f + plr.Attributes[GameAttribute.Gold_PickUp_Radius] && FastRandom.Instance.Next(100) < 5) //CircleOfLife (WD) if (plr.SkillSet.HasPassive(208571) &&
PowerMath.Distance2D(plr.Position, Target.Position) <=
12f + plr.Attributes[GameAttribute.Gold_PickUp_Radius] &&
FastRandom.Instance.Next(100) < 5) //CircleOfLife (WD)
{ {
var dog = new ZombieDog(plr.World, plr, 0); var dog = new ZombieDog(plr.World, plr, 0);
dog.Brain.DeActivate(); dog.Brain.DeActivate();
@ -506,7 +569,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
dog.PlayActionAnimation(AnimationSno.zombiedog_summon_01); dog.PlayActionAnimation(AnimationSno.zombiedog_summon_01);
Context.DogsSummoned++; Context.DogsSummoned++;
Task.Delay(1000).ContinueWith(d => Task.Delay(1000).ContinueWith(d =>
{ {
dog.Brain.Activate(); dog.Brain.Activate();
dog.Attributes[GameAttribute.Untargetable] = false; dog.Attributes[GameAttribute.Untargetable] = false;
@ -524,12 +587,15 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
{ {
plr.World.BuffManager.AddBuff(plr, plr, new RampageBuff()); plr.World.BuffManager.AddBuff(plr, plr, new RampageBuff());
} }
if (Context != null) if (Context != null)
if (Context.DogsSummoned >= 3) if (Context.DogsSummoned >= 3)
plr.GrantAchievement(74987243307567); plr.GrantAchievement(74987243307567);
} }
Logger.Trace( Logger.Trace(
$"$[green3_1]${Context?.User?.GetType().Name}$[/]$ killed monster, id: $[red]${{0}}$[/]$, level $[red]${{1}}$[/]$", Target.SNO, Target.Attributes[GameAttribute.Level]); $"$[green3_1]${Context?.User?.GetType().Name}$[/]$ killed monster, id: $[red]${{0}}$[/]$, level $[red]${{1}}$[/]$",
Target.SNO, Target.Attributes[GameAttribute.Level]);
//handling quest triggers //handling quest triggers
@ -542,8 +608,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
if (trigger.count == Target.World.Game.QuestProgress.QuestTriggers[(int)Target.SNO].counter) if (trigger.count == Target.World.Game.QuestProgress.QuestTriggers[(int)Target.SNO].counter)
trigger.questEvent.Execute(Target.World); // launch a questEvent trigger.questEvent.Execute(Target.World); // launch a questEvent
} }
else else if (trigger.triggerType == DiIiS_NA.Core.MPQ.FileFormats.QuestStepObjectiveType.MonsterFromGroup)
if (trigger.triggerType == DiIiS_NA.Core.MPQ.FileFormats.QuestStepObjectiveType.MonsterFromGroup)
{ {
Target.World.Game.QuestProgress.UpdateCounter((int)Target.SNO); Target.World.Game.QuestProgress.UpdateCounter((int)Target.SNO);
} }
@ -558,108 +623,112 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
trigger.questEvent.Execute(Target.World); // launch a questEvent trigger.questEvent.Execute(Target.World); // launch a questEvent
} }
} }
if (Target.World == null) if (Target.World == null)
return; return;
foreach (var bounty in Target.World.Game.QuestManager.Bounties) foreach (var bounty in Target.World.Game.QuestManager.Bounties)
{ if (Target.OriginalLevelArea == -1) {
if (Target.OriginalLevelArea == -1)
Target.OriginalLevelArea = Target.CurrentScene.Specification.SNOLevelAreas[0]; Target.OriginalLevelArea = Target.CurrentScene.Specification.SNOLevelAreas[0];
bounty.CheckKill((int)Target.SNO, Target.OriginalLevelArea, Target.World.SNO); bounty.CheckKill((int)Target.SNO, Target.OriginalLevelArea, Target.World.SNO);
} }
//Nephalem Rift //Nephalem Rift
if ((Target.CurrentScene.Specification.SNOLevelAreas[0] is 332339 or 288482) && Target.World.Game.ActiveNephalemTimer && Target.World.Game.ActiveNephalemKilledMobs == false) if ((Target.CurrentScene.Specification.SNOLevelAreas[0] is 332339 or 288482) &&
Target.World.Game.ActiveNephalemTimer && Target.World.Game.ActiveNephalemKilledMobs == false)
{ {
Target.World.Game.ActiveNephalemProgress += GameServerConfig.Instance.NephalemRiftProgressMultiplier * (Target.Quality + 1); Target.World.Game.ActiveNephalemProgress +=
GameServerConfig.Instance.NephalemRiftProgressMultiplier * (Target.Quality + 1);
Player master = null; Player master = null;
foreach (var plr in Target.World.Game.Players.Values) foreach (var plr in Target.World.Game.Players.Values)
{ {
if (plr.PlayerIndex == 0) if (plr.PlayerIndex == 0)
master = plr; master = plr;
plr.InGameClient.SendMessage(new SimpleMessage(Opcodes.KillCounterRefresh) if (GameServerConfig.Instance.NephalemRiftAutoFinish && Target.World.Monsters.Count(s => !s.Dead) <= GameServerConfig.Instance.NephalemRiftAutoFinishThreshold) Target.World.Game.ActiveNephalemProgress = 651;
{ plr.InGameClient.SendMessage(new SimpleMessage(Opcodes.KillCounterRefresh));
});
plr.InGameClient.SendMessage(new FloatDataMessage(Opcodes.DungeonFinderProgressMessage) plr.InGameClient.SendMessage(new FloatDataMessage(Opcodes.DungeonFinderProgressMessage)
{ {
Field0 = Target.World.Game.ActiveNephalemProgress Field0 = Target.World.Game.ActiveNephalemProgress
}); });
if (Target.World.Game.ActiveNephalemProgress > 650) if (Target.World.Game.ActiveNephalemProgress <= 650) continue;
Target.World.Game.ActiveNephalemKilledMobs = true;
if (Target.World.Game.NephalemGreater)
{ {
Target.World.Game.ActiveNephalemKilledMobs = true; plr.InGameClient.SendMessage(new QuestCounterMessage()
if (Target.World.Game.NephalemGreater)
{ {
plr.InGameClient.SendMessage(new QuestCounterMessage() snoQuest = 0x00052654,
{ snoLevelArea = 0x000466E2,
snoQuest = 0x00052654, StepID = 13,
snoLevelArea = 0x000466E2, TaskIndex = 0,
StepID = 13, Checked = 1,
TaskIndex = 0, Counter = 1
Checked = 1,
Counter = 1
});
plr.InGameClient.SendMessage(new QuestUpdateMessage()
{
snoQuest = 0x00052654,
snoLevelArea = 0x000466E2,
StepID = 16,
DisplayButton = true,
Failed = false
});
}
else
{
plr.InGameClient.SendMessage(new QuestCounterMessage()
{
snoQuest = 0x00052654,
snoLevelArea = 0x000466E2,
StepID = 1,
TaskIndex = 0,
Checked = 1,
Counter = 1
});
plr.InGameClient.SendMessage(new QuestUpdateMessage()
{
snoQuest = 0x00052654,
snoLevelArea = 0x000466E2,
StepID = 3,
DisplayButton = true,
Failed = false
});
}
plr.InGameClient.SendMessage(new PlayMusicMessage(Opcodes.PlayMusicMessage)
{
SNO = 0x0005BBD8
}); });
plr.InGameClient.SendMessage(new QuestUpdateMessage()
plr.InGameClient.SendMessage(new DisplayGameTextMessage(Opcodes.DisplayGameChatTextMessage) { Message = "Messages:LR_BossSpawned" });
plr.InGameClient.SendMessage(new DisplayGameTextMessage(Opcodes.DisplayGameTextMessage) { Message = "Messages:LR_BossSpawned" });
StartConversation(Target.World, 366542);
if (plr.PlayerIndex == 0)
{ {
plr.SpawnNephalemBoss(Target.World); snoQuest = 0x00052654,
} snoLevelArea = 0x000466E2,
StepID = 16,
DisplayButton = true,
Failed = false
});
}
else
{
plr.InGameClient.SendMessage(new QuestCounterMessage()
{
snoQuest = 0x00052654,
snoLevelArea = 0x000466E2,
StepID = 1,
TaskIndex = 0,
Checked = 1,
Counter = 1
});
plr.InGameClient.SendMessage(new QuestUpdateMessage()
{
snoQuest = 0x00052654,
snoLevelArea = 0x000466E2,
StepID = 3,
DisplayButton = true,
Failed = false
});
}
plr.InGameClient.SendMessage(new PlayMusicMessage(Opcodes.PlayMusicMessage)
{
SNO = 0x0005BBD8
});
plr.InGameClient.SendMessage(new DisplayGameTextMessage(Opcodes.DisplayGameChatTextMessage)
{ Message = "Messages:LR_BossSpawned" });
plr.InGameClient.SendMessage(new DisplayGameTextMessage(Opcodes.DisplayGameTextMessage)
{ Message = "Messages:LR_BossSpawned" });
StartConversation(Target.World, 366542);
if (plr.PlayerIndex == 0)
{
plr.SpawnNephalemBoss(Target.World);
} }
} }
if (Target.Quality > 1) if (Target.Quality > 1 || FastRandom.Instance.Chance(GameServerConfig.Instance.NephalemRiftOrbsChance))
{ {
//spawn spheres for mining indicator //spawn spheres for mining indicator
for (int i = 0; i < Target.Quality + 1; i++) for (int i = 0; i < Target.Quality + 1; i++)
{ {
var position = new Core.Types.Math.Vector3D(Target.Position.X + (float)RandomHelper.NextDouble() * 30f, var position = new Core.Types.Math.Vector3D(
Target.Position.Y + (float)RandomHelper.NextDouble() * 30f, Target.Position.X + (float)RandomHelper.NextDouble() * 30f,
Target.Position.Z); Target.Position.Y + (float)RandomHelper.NextDouble() * 30f,
Item item = ItemGenerator.Cook(master, Target.World.Game.NephalemGreater ? "p1_tiered_rifts_Orb" : "p1_normal_rifts_Orb"); Target.Position.Z);
if (item != null) Item item = ItemGenerator.Cook(master,
item.EnterWorld(position); Target.World.Game.NephalemGreater ? "p1_tiered_rifts_Orb" : "p1_normal_rifts_Orb");
item?.EnterWorld(position);
} }
} }
} }
//Nephalem Rift Boss Killed //Nephalem Rift Boss Killed
if (Target.Attributes[GameAttribute.Is_Loot_Run_Boss]) if (Target.Attributes[GameAttribute.Is_Loot_Run_Boss])
{ {
@ -696,7 +765,10 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
if (plr.InGameClient.Game.NephalemBuff) if (plr.InGameClient.Game.NephalemBuff)
plr.Attributes[GameAttribute.Jewel_Upgrades_Bonus]++; plr.Attributes[GameAttribute.Jewel_Upgrades_Bonus]++;
plr.InGameClient.Game.LastTieredRiftTimeout = (int)((plr.InGameClient.Game.TiredRiftTimer.TimeoutTick - plr.InGameClient.Game.TickCounter) / plr.InGameClient.Game.TickRate / plr.InGameClient.Game.UpdateFrequency * 10f); plr.InGameClient.Game.LastTieredRiftTimeout =
(int)((plr.InGameClient.Game.TiredRiftTimer.TimeoutTick -
plr.InGameClient.Game.TickCounter) / plr.InGameClient.Game.TickRate /
plr.InGameClient.Game.UpdateFrequency * 10f);
plr.InGameClient.Game.TiredRiftTimer.Stop(); plr.InGameClient.Game.TiredRiftTimer.Stop();
plr.InGameClient.Game.TiredRiftTimer = null; plr.InGameClient.Game.TiredRiftTimer = null;
@ -722,10 +794,11 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
var portal = new Portal(Target.World, ActorSno._x1_openworld_lootrunportal, newTagMap); var portal = new Portal(Target.World, ActorSno._x1_openworld_lootrunportal, newTagMap);
portal.EnterWorld(new Core.Types.Math.Vector3D(Target.Position.X + 10f, Target.Position.Y + 10f, Target.Position.Z)); portal.EnterWorld(new Core.Types.Math.Vector3D(Target.Position.X + 10f, Target.Position.Y + 10f,
Target.Position.Z));
} }
else else
{ {
plr.InGameClient.SendMessage(new QuestCounterMessage() plr.InGameClient.SendMessage(new QuestCounterMessage()
{ {
snoQuest = 0x00052654, snoQuest = 0x00052654,
@ -772,43 +845,56 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
Target.World.SpawnGold(Target, plr); Target.World.SpawnGold(Target, plr);
plr.Toon.GameAccount.BigPortalKey++; plr.Toon.GameAccount.BigPortalKey++;
Target.World.Game.ActiveNephalemProgress = 0f; Target.World.Game.ActiveNephalemProgress = 0f;
plr.InGameClient.BnetClient.SendServerWhisper(
"You have completed the Nephalem Rift! You have been rewarded with a Big Portal Key and 10-30 Blood Shards!");
} }
} }
if (Context != null) if (Context != null)
{ {
if (Context.User is Player && Target.World.Game.MonsterLevel >= 70 && Context.User.Attributes[GameAttribute.Level] == 70) //keys if (Context.User is Player && Target.World.Game.MonsterLevel >= 70 &&
Context.User.Attributes[GameAttribute.Level] == 70) //keys
{ {
if (Target is Unique) switch (Target)
{ {
int chance = Target.World.Game.IsHardcore ? 30 : 10; case Unique unique:
if (Target.SNO != ActorSno._terrordemon_a_unique_1000monster && (Target as Unique).CanDropKey && FastRandom.Instance.Next(100) < chance) {
Target.World.DropItem(Target, null, ItemGenerator.CreateItem(Context.User, ItemGenerator.GetItemDefinition(-110888638))); int chance = unique.World.Game.IsHardcore ? 30 : 10;
} if (unique.SNO != ActorSno._terrordemon_a_unique_1000monster && unique.CanDropKey &&
FastRandom.Instance.Chance(chance))
if (Target is Rare) unique.World.DropItem(unique, null,
{ ItemGenerator.CreateItem(Context.User,
int chance = Target.World.Game.IsHardcore ? 15 : 5; ItemGenerator.GetItemDefinition(-110888638)));
if (FastRandom.Instance.Next(1000) < chance) break;
Target.World.DropItem(Target, null, ItemGenerator.CreateItem(Context.User, ItemGenerator.GetItemDefinition(-110888638))); }
case Rare:
{
int chance = Target.World.Game.IsHardcore ? 15 : 5;
if (FastRandom.Instance.Chance(chance))
Target.World.DropItem(Target, null,
ItemGenerator.CreateItem(Context.User,
ItemGenerator.GetItemDefinition(-110888638)));
break;
}
} }
} }
if (LootAndExp) if (LootAndExp)
{ {
if (Context.User is Player || Context.User is Minion || Context.User is Hireling || Context.User == Target) if (Context.User is Player || Context.User is Minion || Context.User is Hireling ||
Context.User == Target)
{ {
Player player = null; Player player = null;
if (Context.User is Minion) switch (Context.User)
{ {
if ((Context.User as Minion).Master is Player) case Minion minion when minion.Master is Player master:
player = (Player)(Context.User as Minion).Master; player = master;
else return; break;
} case Minion:
else return;
{ case Player contextUser:
if (Context.User is Player) player = contextUser;
player = (Player)Context.User; break;
} }
if (player != null) if (player != null)
@ -817,9 +903,10 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
if (FastRandom.Instance.Next(1, 100) < 10) if (FastRandom.Instance.Next(1, 100) < 10)
Target.World.SpawnHealthGlobe(Target, player, Target.Position); Target.World.SpawnHealthGlobe(Target, player, Target.Position);
int chance = 2; //Crusader -> Laws of Valor -> Answered Prayer int chance = 2; //Crusader -> Laws of Valor -> Answered Prayer
if (player.World.BuffManager.HasBuff<CrusaderLawsOfValor.LawsApsBuff>(player)) if (player.World.BuffManager.HasBuff<CrusaderLawsOfValor.LawsApsBuff>(player))
if (player.World.BuffManager.GetFirstBuff<CrusaderLawsOfValor.LawsApsBuff>(player).Glory) if (player.World.BuffManager.GetFirstBuff<CrusaderLawsOfValor.LawsApsBuff>(player)
.Glory)
chance += 20; chance += 20;
if (FastRandom.Instance.Next(1, 100) < chance) if (FastRandom.Instance.Next(1, 100) < chance)
Target.World.SpawnPowerGlobe(Target, player, Target.Position); Target.World.SpawnPowerGlobe(Target, player, Target.Position);
@ -842,14 +929,17 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
if (FastRandom.Instance.NextDouble() < 0.04) if (FastRandom.Instance.NextDouble() < 0.04)
Target.World.SpawnRandomGem(Target, plr); Target.World.SpawnRandomGem(Target, plr);
//Logger.Debug("seed: {0}", seed); //Logger.Debug("seed: {0}", seed);
var dropRates = Target.World.Game.IsSeasoned ? LootManager.GetSeasonalDropRates((int)Target.Quality, Target.Attributes[GameAttribute.Level]) : LootManager.GetDropRates((int)Target.Quality, Target.Attributes[GameAttribute.Level]); var dropRates = Target.World.Game.IsSeasoned
? LootManager.GetSeasonalDropRates((int)Target.Quality,
Target.Attributes[GameAttribute.Level])
: LootManager.GetDropRates((int)Target.Quality, Target.Attributes[GameAttribute.Level]);
float seed = (float)FastRandom.Instance.NextDouble(); float seed = (float)FastRandom.Instance.NextDouble();
foreach (float rate in dropRates) foreach (float rate in dropRates)
{ {
// if seed is less than the drop rate, drop the item // if seed is less than the drop rate, drop the item
if (seed < rate * (1f if (seed < rate * (1f
+ plr.Attributes[GameAttribute.Magic_Find]) + plr.Attributes[GameAttribute.Magic_Find])
* GameServerConfig.Instance.RateDrop) * GameServerConfig.Instance.RateDrop)
{ {
//Logger.Debug("rate: {0}", rate); //Logger.Debug("rate: {0}", rate);
@ -868,7 +958,10 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
if ((int)Target.Quality >= 4 && plr.AdditionalLootItems > 0) if ((int)Target.Quality >= 4 && plr.AdditionalLootItems > 0)
for (int d = 0; d < plr.AdditionalLootItems; d++) for (int d = 0; d < plr.AdditionalLootItems; d++)
{ {
var lootQuality = Target.World.Game.IsHardcore ? LootManager.GetSeasonalLootQuality((int)Target.Quality, Target.World.Game.Difficulty) : LootManager.GetLootQuality((int)Target.Quality, Target.World.Game.Difficulty); var lootQuality = Target.World.Game.IsHardcore
? LootManager.GetSeasonalLootQuality((int)Target.Quality,
Target.World.Game.Difficulty)
: LootManager.GetLootQuality((int)Target.Quality, Target.World.Game.Difficulty);
Target.World.SpawnRandomEquip(Target, plr, lootQuality); Target.World.SpawnRandomEquip(Target, plr, lootQuality);
} }
@ -881,9 +974,9 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
} }
if (Target.World.Game.IsSeasoned) if (Target.World.Game.IsSeasoned)
{ {
switch(Target.SNO) switch (Target.SNO)
{ {
case ActorSno._despair: //Rakanot case ActorSno._despair: //Rakanot
plr.GrantCriteria(74987254022737); plr.GrantCriteria(74987254022737);
break; break;
@ -897,9 +990,9 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
plr.GrantCriteria(74987252384014); plr.GrantCriteria(74987252384014);
break; break;
} }
} }
if ((int)Target.Quality >= 4) if ((int)Target.Quality >= 4)
{ {
if (Target.SNO == ActorSno._lacunifemale_c_unique) //Chiltara if (Target.SNO == ActorSno._lacunifemale_c_unique) //Chiltara
if ((float)FastRandom.Instance.NextDouble() < 0.5f) if ((float)FastRandom.Instance.NextDouble() < 0.5f)
@ -957,102 +1050,130 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
} }
if (Context.User is Player & Target is Monster) if (Context.User is Player & Target is Monster)
if (RandomHelper.Next(0, 100) > 40 & (Context.User as Player).Toon.Class == ToonClass.Necromancer) if (RandomHelper.Next(0, 100) > 40 && ((Player)Context.User).Toon.Class == ToonClass.Necromancer)
{ {
var flesh = Context.User.World.SpawnMonster(ActorSno._p6_necro_corpse_flesh, positionOfDeath); var flesh = Context.User.World.SpawnMonster(ActorSno._p6_necro_corpse_flesh, positionOfDeath);
flesh.Attributes[GameAttribute.Necromancer_Corpse_Source_Monster_SNO] = (int)Target.SNO; flesh.Attributes[GameAttribute.Necromancer_Corpse_Source_Monster_SNO] = (int)Target.SNO;
flesh.Attributes.BroadcastChangedIfRevealed(); flesh.Attributes.BroadcastChangedIfRevealed();
} }
} }
if (Target is Monster)
(Target as Monster).PlayLore(); if (Target is Monster target1)
target1.PlayLore();
bool isCoop = Target.World.Game.Players.Count > 1; bool isCoop = Target.World.Game.Players.Count > 1;
bool isHardcore = Target.World.Game.IsHardcore; bool isHardcore = Target.World.Game.IsHardcore;
bool isSeasoned = Target.World.Game.IsSeasoned; bool isSeasoned = Target.World.Game.IsSeasoned;
//114917 //114917
if (Target.Quality == 7 || Target.Quality == 2 || Target.Quality == 4) // if (Target.Quality is 7 or 2 or 4)
{ // {
//
// }
} if (Target is not Boss) return;
if (Target is Boss) foreach (Player plr in players)
foreach (Player plr in players) switch (Target.SNO)
switch (Target.SNO) {
{ case ActorSno._skeletonking: //Leoric
case ActorSno._skeletonking: //Leoric if (Context.PowerSNO == 93885) //weapon throw
if (Context.PowerSNO == 93885) //weapon throw plr.GrantAchievement(74987243307050);
plr.GrantAchievement(74987243307050); if (isCoop) plr.GrantAchievement(74987252301189);
if (isCoop) plr.GrantAchievement(74987252301189); if (isHardcore) plr.GrantAchievement(74987243307489); else plr.GrantAchievement(74987249381288); if (isHardcore) plr.GrantAchievement(74987243307489);
break; else plr.GrantAchievement(74987249381288);
case ActorSno._butcher: //Butcher break;
if (Context.PowerSNO == 93885) //weapon throw case ActorSno._butcher: //Butcher
plr.GrantAchievement(74987243307050); if (Context.PowerSNO == 93885) //weapon throw
if (Context.PowerSNO == 71548) //spectral blade plr.GrantAchievement(74987243307050);
plr.GrantCriteria(74987243307946); if (Context.PowerSNO == 71548) //spectral blade
if (isCoop) plr.GrantAchievement(74987252696819); if (isHardcore) plr.GrantAchievement(74987254551339); else plr.GrantAchievement(74987258164419); plr.GrantCriteria(74987243307946);
plr.SetProgress(1, Target.World.Game.Difficulty); if (isCoop) plr.GrantAchievement(74987252696819);
break; if (isHardcore) plr.GrantAchievement(74987254551339);
case ActorSno._maghda: //Maghda else plr.GrantAchievement(74987258164419);
if (Context.PowerSNO == 93885) //weapon throw plr.SetProgress(1, Target.World.Game.Difficulty);
plr.GrantAchievement(74987243307050); break;
if (isCoop) plr.GrantAchievement(74987255855515); if (isHardcore) plr.GrantAchievement(74987243307507); else plr.GrantAchievement(74987246434969); case ActorSno._maghda: //Maghda
break; if (Context.PowerSNO == 93885) //weapon throw
case ActorSno._zoltunkulle: //Zoltun Kulle plr.GrantAchievement(74987243307050);
if (isCoop) plr.GrantAchievement(74987246137208); if (isHardcore) plr.GrantAchievement(74987243307509); else plr.GrantAchievement(74987252195665); if (isCoop) plr.GrantAchievement(74987255855515);
break; if (isHardcore) plr.GrantAchievement(74987243307507);
case ActorSno._belial: //Belial (big) else plr.GrantAchievement(74987246434969);
if (Context.PowerSNO == 93885) //weapon throw break;
plr.GrantAchievement(74987243307050); case ActorSno._zoltunkulle: //Zoltun Kulle
if (Context.PowerSNO == 71548) //spectral blade if (isCoop) plr.GrantAchievement(74987246137208);
plr.GrantCriteria(74987243310916); if (isHardcore) plr.GrantAchievement(74987243307509);
if (isCoop) plr.GrantAchievement(74987256826382); if (isHardcore) plr.GrantAchievement(74987244906887); else plr.GrantAchievement(74987244645044); else plr.GrantAchievement(74987252195665);
plr.SetProgress(2, Target.World.Game.Difficulty); break;
break; case ActorSno._belial: //Belial (big)
case ActorSno._gluttony: //Gluttony if (Context.PowerSNO == 93885) //weapon throw
if (isCoop) plr.GrantAchievement(74987249112946); if (isHardcore) plr.GrantAchievement(74987243307519); else plr.GrantAchievement(74987259418615); plr.GrantAchievement(74987243307050);
break; if (Context.PowerSNO == 71548) //spectral blade
case ActorSno._siegebreakerdemon: //Siegebreaker plr.GrantCriteria(74987243310916);
if (Context.PowerSNO == 93885) //weapon throw if (isCoop) plr.GrantAchievement(74987256826382);
plr.GrantAchievement(74987243307050); if (isHardcore) plr.GrantAchievement(74987244906887);
if (isCoop) plr.GrantAchievement(74987253664242); if (isHardcore) plr.GrantAchievement(74987243307521); else plr.GrantAchievement(74987248255991); else plr.GrantAchievement(74987244645044);
break; plr.SetProgress(2, Target.World.Game.Difficulty);
case ActorSno._mistressofpain: //Cydaea break;
if (Context.PowerSNO == 93885) //weapon throw case ActorSno._gluttony: //Gluttony
plr.GrantAchievement(74987243307050); if (isCoop) plr.GrantAchievement(74987249112946);
if (isCoop) plr.GrantAchievement(74987257890442); if (isHardcore) plr.GrantAchievement(74987243307523); else plr.GrantAchievement(74987254675042); if (isHardcore) plr.GrantAchievement(74987243307519);
break; else plr.GrantAchievement(74987259418615);
case ActorSno._azmodan: //Azmodan break;
if (Context.PowerSNO == 93885) //weapon throw case ActorSno._siegebreakerdemon: //Siegebreaker
plr.GrantAchievement(74987243307050); if (Context.PowerSNO == 93885) //weapon throw
if (Context.PowerSNO == 71548) //spectral blade plr.GrantAchievement(74987243307050);
plr.GrantCriteria(74987243310915); if (isCoop) plr.GrantAchievement(74987253664242);
if (isCoop) plr.GrantAchievement(74987247100576); if (isHardcore) plr.GrantAchievement(74987251893684); else plr.GrantAchievement(74987247855713); if (isHardcore) plr.GrantAchievement(74987243307521);
plr.SetProgress(3, Target.World.Game.Difficulty); else plr.GrantAchievement(74987248255991);
break; break;
case ActorSno._terrordemon_a_unique_1000monster: //Iskatu case ActorSno._mistressofpain: //Cydaea
if (isCoop) plr.GrantAchievement(74987255392558); if (isHardcore) plr.GrantAchievement(74987248632930); else plr.GrantAchievement(74987246017001); if (Context.PowerSNO == 93885) //weapon throw
break; plr.GrantAchievement(74987243307050);
case ActorSno._despair: //Rakanoth if (isCoop) plr.GrantAchievement(74987257890442);
if (Context.PowerSNO == 93885) //weapon throw if (isHardcore) plr.GrantAchievement(74987243307523);
plr.GrantAchievement(74987243307050); else plr.GrantAchievement(74987254675042);
if (isCoop) plr.GrantAchievement(74987248781143); if (isHardcore) plr.GrantAchievement(74987243307533); else plr.GrantAchievement(74987256508058); break;
break; case ActorSno._azmodan: //Azmodan
case ActorSno._bigred_izual: //Izual if (Context.PowerSNO == 93885) //weapon throw
if (isCoop) plr.GrantAchievement(74987254969009); if (isHardcore) plr.GrantAchievement(74987247989681); else plr.GrantAchievement(74987244988685); plr.GrantAchievement(74987243307050);
if (isSeasoned) plr.GrantCriteria(74987249642121); if (Context.PowerSNO == 71548) //spectral blade
break; plr.GrantCriteria(74987243310915);
case ActorSno._diablo: //Diablo if (isCoop) plr.GrantAchievement(74987247100576);
if (Context.PowerSNO == 93885) //weapon throw if (isHardcore) plr.GrantAchievement(74987251893684);
plr.GrantAchievement(74987243307050); else plr.GrantAchievement(74987247855713);
if (isCoop) plr.GrantAchievement(74987250386944); if (isHardcore) plr.GrantAchievement(74987250070969); else plr.GrantAchievement(74987248188984); plr.SetProgress(3, Target.World.Game.Difficulty);
plr.SetProgress(4, Target.World.Game.Difficulty); break;
if (isSeasoned) plr.GrantCriteria(74987250915380); case ActorSno._terrordemon_a_unique_1000monster: //Iskatu
break; if (isCoop) plr.GrantAchievement(74987255392558);
default: if (isHardcore) plr.GrantAchievement(74987248632930);
break; else plr.GrantAchievement(74987246017001);
} break;
case ActorSno._despair: //Rakanoth
if (Context.PowerSNO == 93885) //weapon throw
plr.GrantAchievement(74987243307050);
if (isCoop) plr.GrantAchievement(74987248781143);
if (isHardcore) plr.GrantAchievement(74987243307533);
else plr.GrantAchievement(74987256508058);
break;
case ActorSno._bigred_izual: //Izual
if (isCoop) plr.GrantAchievement(74987254969009);
if (isHardcore) plr.GrantAchievement(74987247989681);
else plr.GrantAchievement(74987244988685);
if (isSeasoned) plr.GrantCriteria(74987249642121);
break;
case ActorSno._diablo: //Diablo
if (Context.PowerSNO == 93885) //weapon throw
plr.GrantAchievement(74987243307050);
if (isCoop) plr.GrantAchievement(74987250386944);
if (isHardcore) plr.GrantAchievement(74987250070969);
else plr.GrantAchievement(74987248188984);
plr.SetProgress(4, Target.World.Game.Difficulty);
if (isSeasoned) plr.GrantCriteria(74987250915380);
break;
default:
break;
}
} }
public bool StartConversation(MapSystem.World world, Int32 conversationId) public bool StartConversation(MapSystem.World world, Int32 conversationId)

View File

@ -271,9 +271,35 @@ namespace DiIiS_NA.GameServer
set => Set(nameof(VitalityParagonMultiplier), value); set => Set(nameof(VitalityParagonMultiplier), value);
} }
/// <summary>
/// Auto finishes nephalem rift when there's <see cref="NephalemRiftAutoFinishThreshold"></see> or less monsters left.
/// </summary>
public bool NephalemRiftAutoFinish
{
get => GetBoolean(nameof(NephalemRiftAutoFinish), false);
set => Set(nameof(NephalemRiftAutoFinish), value);
}
/// <summary>
/// If <see cref="NephalemRiftAutoFinish"></see> is enabled, this is the threshold.
/// </summary>
public int NephalemRiftAutoFinishThreshold
{
get => GetInt(nameof(NephalemRiftAutoFinishThreshold), 2);
set => Set(nameof(NephalemRiftAutoFinishThreshold), value);
}
/// <summary>
/// Nephalem Rifts chance of spawning a orb.
/// </summary>
public float NephalemRiftOrbsChance
{
get => GetFloat(nameof(NephalemRiftOrbsChance), 0f);
set => Set(nameof(NephalemRiftOrbsChance), value);
}
#endregion #endregion
public static GameServerConfig Instance { get; } = new(); public static GameServerConfig Instance { get; } = new();
private GameServerConfig() : base("Game-Server") private GameServerConfig() : base("Game-Server")
{ {