This commit is contained in:
Lucca (Droppy) 2024-06-13 04:26:34 -03:00
parent 03ba08341c
commit 425378eff2
39 changed files with 536 additions and 326 deletions

2
.gitignore vendored
View File

@ -373,3 +373,5 @@ db/pgadmin/*
/src/DiIiS-NA/config.ini
/src/DiIiS-NA/database.Account.config
/src/DiIiS-NA/database.Worlds.config
/src/DiIiS-NA/database.Account.Debug.config
/src/DiIiS-NA/database.Worlds.Debug.config

View File

@ -37,7 +37,7 @@ namespace DiIiS_NA.LoginServer.AccountsSystem
{
ByteStringPresenceField<D3.OnlineService.EntityId> val = null;
if (GameAccount.CurrentToon != null)
val = new ByteStringPresenceField<D3.OnlineService.EntityId>(FieldKeyHelper.Program.D3, FieldKeyHelper.OriginatingClass.Account, 1, 0, GameAccount.CurrentToon.D3EntityID);
val = new ByteStringPresenceField<D3.OnlineService.EntityId>(FieldKeyHelper.Program.D3, FieldKeyHelper.OriginatingClass.Account, 1, 0, GameAccount.CurrentToon.D3EntityId);
else
{
var Fake = D3.OnlineService.EntityId.CreateBuilder().SetIdHigh(0).SetIdLow(0);

View File

@ -90,8 +90,8 @@ public class GameAccount : PersistentRPCObject
public EntityId LastPlayedHeroId =>
CurrentToon == null
? Toons.Count > 0 ? Toons.First().D3EntityID : AccountHasNoToons
: CurrentToon.D3EntityID;
? Toons.Count > 0 ? Toons.First().D3EntityId : AccountHasNoToons
: CurrentToon.D3EntityId;
public ByteStringPresenceField<bgs.protocol.channel.v1.ChannelId> PartyIdField =>
new(FieldKeyHelper.Program.D3, FieldKeyHelper.OriginatingClass.Party, 1, 0)
@ -271,7 +271,7 @@ public class GameAccount : PersistentRPCObject
_currentToonId = value.PersistentID;
lock (DBGameAccount)
{
SetField(x=>x.LastPlayedHero = value.DBToon);
SetField(x=>x.LastPlayedHero = value.DbToon);
}
ChangedFields.SetPresenceFieldValue(LastPlayedHeroIdField);
@ -924,9 +924,9 @@ public class GameAccount : PersistentRPCObject
foreach (var hero in Toons)
profile.AddHeroes(HeroMiniProfile.CreateBuilder()
.SetHeroName(hero.Name)
.SetHeroGbidClass((int)hero.ClassID)
.SetHeroGbidClass((int)hero.ClassId)
.SetHeroFlags((uint)hero.Flags)
.SetHeroId((uint)hero.D3EntityID.IdLow)
.SetHeroId((uint)hero.D3EntityId.IdLow)
.SetHeroLevel(hero.Level)
.SetHeroVisualEquipment(hero.HeroVisualEquipmentField.Value)
);
@ -1423,7 +1423,7 @@ public class GameAccount : PersistentRPCObject
}
else if (queryKey.Group == 3 && queryKey.Field == 1) // Hero's class (GbidClass)
{
field.SetValue(bgs.protocol.Variant.CreateBuilder().SetIntValue(CurrentToon.ClassID).Build());
field.SetValue(bgs.protocol.Variant.CreateBuilder().SetIntValue(CurrentToon.ClassId).Build());
}
else if (queryKey.Group == 3 && queryKey.Field == 2) // Hero's current level
{

View File

@ -46,9 +46,9 @@ namespace DiIiS_NA.LoginServer.GamesSystem
{
this.GameCreateParams = D3.OnlineService.GameCreateParams.ParseFrom(attribute.Value.BlobValue);
if (this.GameCreateParams.CreationFlags == 256 || this.GameCreateParams.CreationFlags == 262400) this.Public = true;
lock (owner.Account.GameAccount.CurrentToon.DBToon)
lock (owner.Account.GameAccount.CurrentToon.DbToon)
{
var toonByClient = owner.Account.GameAccount.CurrentToon.DBToon;
var toonByClient = owner.Account.GameAccount.CurrentToon.DbToon;
toonByClient.CurrentAct = this.GameCreateParams.CampaignOrAdventureMode.Act;
toonByClient.CurrentQuestId = (this.GameCreateParams.CampaignOrAdventureMode.SnoQuest == 0 ? 87700 : this.GameCreateParams.CampaignOrAdventureMode.SnoQuest);
toonByClient.CurrentQuestStepId = (this.GameCreateParams.CampaignOrAdventureMode.QuestStepId == 0 ? -1 : this.GameCreateParams.CampaignOrAdventureMode.QuestStepId);
@ -75,7 +75,7 @@ namespace DiIiS_NA.LoginServer.GamesSystem
public void StartGame(List<BattleClient> clients, ulong objectId)
{
Logger.MethodTrace($"objectId: {objectId}");
var owner = this.Owner.Account.GameAccount.CurrentToon.DBToon;
var owner = this.Owner.Account.GameAccount.CurrentToon.DbToon;
if (Program.BattleBackend.GameServers.Count == 0) return;

View File

@ -60,7 +60,7 @@ namespace DiIiS_NA.LoginServer
public string Motd
{
get => GetString(nameof(Motd),
$"Welcome to Blizzless Server Build {Program.Build} - Stage: {Program.Stage} [{Program.TypeBuild}]!");
$"Welcome to Blizzless Server Build {Program.BUILD} - Stage: {Program.STAGE} [{Program.TypeBuild}]!");
set => Set(nameof(Motd), value);
}

View File

@ -97,9 +97,9 @@ namespace DiIiS_NA.LoginServer.ServicesSystem.Services
var paramsBuilder = D3.OnlineService.GameCreateParams.CreateBuilder(gameCreateParams);
var Mode = D3.OnlineService.CampaignOrAdventureModeCreateParams.CreateBuilder(gameCreateParams.CampaignOrAdventureMode);
lock (((HandlerController) controller).Client.Account.GameAccount.CurrentToon.DBToon)
lock (((HandlerController) controller).Client.Account.GameAccount.CurrentToon.DbToon)
{
DBToon toonByClient = (((HandlerController) controller).Client).Account.GameAccount.CurrentToon.DBToon;
DBToon toonByClient = (((HandlerController) controller).Client).Account.GameAccount.CurrentToon.DbToon;
if(toonByClient.CurrentAct == 400)
toonByClient.CurrentAct = gameCreateParams.CampaignOrAdventureMode.Act;
if (!clear_quests)
@ -152,7 +152,7 @@ namespace DiIiS_NA.LoginServer.ServicesSystem.Services
{
var gameCreateParamsBuilder = D3.OnlineService.GameCreateParams.CreateBuilder();
var toon = (((HandlerController) controller).Client).Account.GameAccount.CurrentToon;
var dbToon = (((HandlerController) controller).Client).Account.GameAccount.CurrentToon.DBToon;
var dbToon = (((HandlerController) controller).Client).Account.GameAccount.CurrentToon.DbToon;
gameCreateParamsBuilder.SetGameType(1);
gameCreateParamsBuilder.SetCreationFlags(0);
gameCreateParamsBuilder.SetCampaignOrAdventureMode(D3.OnlineService.CampaignOrAdventureModeCreateParams.CreateBuilder()
@ -160,7 +160,7 @@ namespace DiIiS_NA.LoginServer.ServicesSystem.Services
.SetAct(dbToon.CurrentAct)
.SetSnoQuest(dbToon.CurrentQuestId)
.SetQuestStepId(dbToon.CurrentQuestStepId)
.SetResumeFromSaveHeroId(toon.D3EntityID)
.SetResumeFromSaveHeroId(toon.D3EntityId)
.SetDeprecatedOpenToFriends(true)
.SetDeprecatedOpenToFriendsMessage("TestGame")
);

View File

@ -64,7 +64,7 @@ namespace DiIiS_NA.LoginServer.ServicesSystem.Services
foreach (Toon t in Client.Account.GameAccount.Toons)
{
d.AddDigestList(t.Digest);
GAS.AddHeroListOrder(t.D3EntityID);
GAS.AddHeroListOrder(t.D3EntityId);
}
Init.SetGameAccountSettings(GAS);
@ -661,7 +661,7 @@ namespace DiIiS_NA.LoginServer.ServicesSystem.Services
if (hero != null)
{
var Snapshot = D3.Leaderboard.HeroSnapshot.CreateBuilder()
.SetHeroId(hero.D3EntityID)
.SetHeroId(hero.D3EntityId)
.AddCosmeticItems(D3.Leaderboard.HeroCosmeticItem.CreateBuilder().SetCosmeticVisualInventorySlot(1)
.SetGbid(hero.Cosmetic1))
.AddCosmeticItems(D3.Leaderboard.HeroCosmeticItem.CreateBuilder().SetCosmeticVisualInventorySlot(2)
@ -671,21 +671,21 @@ namespace DiIiS_NA.LoginServer.ServicesSystem.Services
.AddCosmeticItems(D3.Leaderboard.HeroCosmeticItem.CreateBuilder().SetCosmeticVisualInventorySlot(4)
.SetGbid(hero.Cosmetic4))
.SetActiveSkills(SkillsWithRunes.CreateBuilder()
.AddRunes(SkillWithRune.CreateBuilder().SetSkill(hero.DBActiveSkills.Skill0)
.SetRuneType(hero.DBActiveSkills.Rune0))
.AddRunes(SkillWithRune.CreateBuilder().SetSkill(hero.DBActiveSkills.Skill1)
.SetRuneType(hero.DBActiveSkills.Rune1))
.AddRunes(SkillWithRune.CreateBuilder().SetSkill(hero.DBActiveSkills.Skill2)
.SetRuneType(hero.DBActiveSkills.Rune2))
.AddRunes(SkillWithRune.CreateBuilder().SetSkill(hero.DBActiveSkills.Skill3)
.SetRuneType(hero.DBActiveSkills.Rune3))
.AddRunes(SkillWithRune.CreateBuilder().SetSkill(hero.DBActiveSkills.Skill4)
.SetRuneType(hero.DBActiveSkills.Rune4))
.AddRunes(SkillWithRune.CreateBuilder().SetSkill(hero.DBActiveSkills.Skill5)
.SetRuneType(hero.DBActiveSkills.Rune5)))
.SetActiveTraits(PassiveSkills.CreateBuilder().AddSnoTraits(hero.DBActiveSkills.Passive0)
.AddSnoTraits(hero.DBActiveSkills.Passive1).AddSnoTraits(hero.DBActiveSkills.Passive2)
.AddSnoTraits(hero.DBActiveSkills.Passive3));
.AddRunes(SkillWithRune.CreateBuilder().SetSkill(hero.DbActiveSkills.Skill0)
.SetRuneType(hero.DbActiveSkills.Rune0))
.AddRunes(SkillWithRune.CreateBuilder().SetSkill(hero.DbActiveSkills.Skill1)
.SetRuneType(hero.DbActiveSkills.Rune1))
.AddRunes(SkillWithRune.CreateBuilder().SetSkill(hero.DbActiveSkills.Skill2)
.SetRuneType(hero.DbActiveSkills.Rune2))
.AddRunes(SkillWithRune.CreateBuilder().SetSkill(hero.DbActiveSkills.Skill3)
.SetRuneType(hero.DbActiveSkills.Rune3))
.AddRunes(SkillWithRune.CreateBuilder().SetSkill(hero.DbActiveSkills.Skill4)
.SetRuneType(hero.DbActiveSkills.Rune4))
.AddRunes(SkillWithRune.CreateBuilder().SetSkill(hero.DbActiveSkills.Skill5)
.SetRuneType(hero.DbActiveSkills.Rune5)))
.SetActiveTraits(PassiveSkills.CreateBuilder().AddSnoTraits(hero.DbActiveSkills.Passive0)
.AddSnoTraits(hero.DbActiveSkills.Passive1).AddSnoTraits(hero.DbActiveSkills.Passive2)
.AddSnoTraits(hero.DbActiveSkills.Passive3));
foreach (var item in hero.Profile.Equipment.ItemsList)
{
@ -842,7 +842,7 @@ namespace DiIiS_NA.LoginServer.ServicesSystem.Services
.SetHeroAltLevel((uint)gameAccount2.DBGameAccount.ParagonLevel)
.SetHeroFlags((uint)Hero.Flags)
.SetHeroLevel((uint)Hero.Level)
.SetHeroGbidClass((uint)Hero.ClassID)
.SetHeroGbidClass((uint)Hero.ClassId)
.SetHeroName(Hero.Name)
.SetHeroSnapshotAvailable(true)
.SetHeroVisualEquipment(gameAccount2.Toons[0].Digest.VisualEquipment);
@ -1001,7 +1001,7 @@ namespace DiIiS_NA.LoginServer.ServicesSystem.Services
.SetHeroAltLevel((uint)gameAccount.DBGameAccount.ParagonLevel)
.SetHeroFlags((uint)hero.Flags)
.SetHeroLevel((uint)hero.Level)
.SetHeroGbidClass((uint)hero.ClassID)
.SetHeroGbidClass((uint)hero.ClassId)
.SetHeroName(hero.Name)
.SetHeroSnapshotAvailable(true)
.SetHeroVisualEquipment(gameAccount.Toons[0].Digest.VisualEquipment);
@ -1097,7 +1097,7 @@ namespace DiIiS_NA.LoginServer.ServicesSystem.Services
var newToon = ToonManager.CreateNewToon(createParams.Name, createParams.GbidClass,
createParams.IsFemale ? ToonFlags.Female : ToonFlags.Male, 1, createParams.IsHardcore,
client.Account.GameAccount, createParams.IsSeason ? 1 : 0);
return CreateHeroResponse.CreateBuilder().SetHeroId(newToon.D3EntityID.IdLow).Build().ToByteString();
return CreateHeroResponse.CreateBuilder().SetHeroId(newToon.D3EntityId.IdLow).Build().ToByteString();
}
private ByteString OnHeroDeleteParams(BattleClient client, ByteString data)
@ -3118,7 +3118,7 @@ namespace DiIiS_NA.LoginServer.ServicesSystem.Services
var Response = RebirthHeroResponse.CreateBuilder();
foreach (Toon t in client.Account.GameAccount.Toons)
{
if (t.D3EntityID.IdLow == Request.HeroId)
if (t.D3EntityId.IdLow == Request.HeroId)
{
//t.SetSeason(1);

View File

@ -19,12 +19,12 @@ namespace DiIiS_NA.LoginServer.Toons
public int Cosmetic1
{
get => DBToon.Cosmetic1;
get => DbToon.Cosmetic1;
set
{
lock (DBToon)
lock (DbToon)
{
var dbToon = DBToon;
var dbToon = DbToon;
dbToon.Cosmetic1 = value;
DBSessions.SessionUpdate(dbToon);
}
@ -33,12 +33,12 @@ namespace DiIiS_NA.LoginServer.Toons
public int Cosmetic2
{
get => DBToon.Cosmetic2;
get => DbToon.Cosmetic2;
set
{
lock (DBToon)
lock (DbToon)
{
var dbToon = DBToon;
var dbToon = DbToon;
dbToon.Cosmetic2 = value;
DBSessions.SessionUpdate(dbToon);
}
@ -47,12 +47,12 @@ namespace DiIiS_NA.LoginServer.Toons
public int Cosmetic3
{
get => DBToon.Cosmetic3;
get => DbToon.Cosmetic3;
set
{
lock (DBToon)
lock (DbToon)
{
var dbToon = DBToon;
var dbToon = DbToon;
dbToon.Cosmetic3 = value;
DBSessions.SessionUpdate(dbToon);
}
@ -61,12 +61,12 @@ namespace DiIiS_NA.LoginServer.Toons
public int Cosmetic4
{
get => DBToon.Cosmetic4;
get => DbToon.Cosmetic4;
set
{
lock (DBToon)
lock (DbToon)
{
var dbToon = DBToon;
var dbToon = DbToon;
dbToon.Cosmetic4 = value;
DBSessions.SessionUpdate(dbToon);
}
@ -75,7 +75,7 @@ namespace DiIiS_NA.LoginServer.Toons
#endregion
public DBToon DBToon
public DBToon DbToon
{
get;
/*
@ -93,11 +93,11 @@ namespace DiIiS_NA.LoginServer.Toons
set;
}
private DBToon CachedDBToon { get; set; }
private DBToon CachedDbToon { get; set; }
public bool IsHardcore { get; set; }
public DBActiveSkills DBActiveSkills
public DBActiveSkills DbActiveSkills
{
get { return DBSessions.SessionQuerySingle<DBActiveSkills>(s => s.DBToon.Id == PersistentID); }
set { }
@ -108,7 +108,7 @@ namespace DiIiS_NA.LoginServer.Toons
get
{
var val = new IntPresenceField(FieldKeyHelper.Program.D3, FieldKeyHelper.OriginatingClass.Hero, 1, 0,
ClassID);
ClassId);
return val;
}
}
@ -152,13 +152,13 @@ namespace DiIiS_NA.LoginServer.Toons
FieldKeyHelper.OriginatingClass.Hero, 5, 0, _heroName);
private D3.Hero.VisualEquipment _visualEquipment = null;
public bool _visualEquipmentChanged = true;
public bool VisualEquipmentChanged = true;
public ByteStringPresenceField<D3.Hero.VisualEquipment> HeroVisualEquipmentField
{
get
{
if (_visualEquipmentChanged)
if (VisualEquipmentChanged)
{
var visualItems = new[]
{
@ -171,7 +171,7 @@ namespace DiIiS_NA.LoginServer.Toons
D3.Hero.VisualItem.CreateBuilder().SetEffectLevel(0).Build(), // Shoulders
D3.Hero.VisualItem.CreateBuilder().SetEffectLevel(0).Build(), // Legs
};
var CosmeticItems = new[]
var cosmeticItems = new[]
{
D3.Hero.VisualCosmeticItem.CreateBuilder().SetGbid(Cosmetic1).Build(), // Wings
D3.Hero.VisualCosmeticItem.CreateBuilder().SetGbid(Cosmetic2).Build(), // Flag
@ -197,8 +197,8 @@ namespace DiIiS_NA.LoginServer.Toons
}
_visualEquipment = D3.Hero.VisualEquipment.CreateBuilder().AddRangeVisualItem(visualItems)
.AddRangeCosmeticItem(CosmeticItems).Build();
_visualEquipmentChanged = false;
.AddRangeCosmeticItem(cosmeticItems).Build();
VisualEquipmentChanged = false;
}
return new ByteStringPresenceField<D3.Hero.VisualEquipment>(FieldKeyHelper.Program.D3,
@ -212,19 +212,19 @@ namespace DiIiS_NA.LoginServer.Toons
/// <summary>
/// D3 EntityID encoded id.
/// </summary>
public D3.OnlineService.EntityId D3EntityID { get; private set; }
public D3.OnlineService.EntityId D3EntityId { get; private set; }
/// <summary>
/// True if toon has been recently deleted;
/// </summary>
public bool Deleted
{
get => DBToon.Deleted;
get => DbToon.Deleted;
set
{
lock (DBToon)
lock (DbToon)
{
var dbToon = DBToon;
var dbToon = DbToon;
dbToon.Deleted = value;
DBSessions.SessionUpdate(dbToon);
}
@ -235,12 +235,12 @@ namespace DiIiS_NA.LoginServer.Toons
public int SeasonCreated
{
get => DBToon.CreatedSeason;
get => DbToon.CreatedSeason;
set
{
lock (DBToon)
lock (DbToon)
{
var dbToon = DBToon;
var dbToon = DbToon;
dbToon.CreatedSeason = value;
DBSessions.SessionUpdate(dbToon);
}
@ -249,12 +249,12 @@ namespace DiIiS_NA.LoginServer.Toons
public bool StoneOfPortal
{
get => DBToon.StoneOfPortal;
get => DbToon.StoneOfPortal;
set
{
lock (DBToon)
lock (DbToon)
{
var dbToon = DBToon;
var dbToon = DbToon;
dbToon.StoneOfPortal = value;
DBSessions.SessionUpdate(dbToon);
}
@ -263,12 +263,12 @@ namespace DiIiS_NA.LoginServer.Toons
public bool Dead
{
get => DBToon.Dead;
get => DbToon.Dead;
set
{
lock (DBToon)
lock (DbToon)
{
var dbToon = DBToon;
var dbToon = DbToon;
dbToon.Dead = value;
DBSessions.SessionUpdate(dbToon);
}
@ -280,12 +280,12 @@ namespace DiIiS_NA.LoginServer.Toons
/// </summary>
public bool Archieved
{
get => DBToon.Archieved;
get => DbToon.Archieved;
set
{
lock (DBToon)
lock (DbToon)
{
var dbToon = DBToon;
var dbToon = DbToon;
dbToon.Archieved = value;
DBSessions.SessionUpdate(dbToon);
}
@ -319,9 +319,9 @@ namespace DiIiS_NA.LoginServer.Toons
set
{
_heroName = value;
lock (DBToon)
lock (DbToon)
{
var dbToon = DBToon;
var dbToon = DbToon;
dbToon.Name = value;
DBSessions.SessionUpdate(dbToon);
}
@ -350,9 +350,9 @@ namespace DiIiS_NA.LoginServer.Toons
set
{
GameAccountId = value.PersistentID;
lock (DBToon)
lock (DbToon)
{
var dbToon = DBToon;
var dbToon = DbToon;
dbToon.DBGameAccount = value.DBGameAccount;
DBSessions.SessionUpdate(dbToon);
}
@ -414,9 +414,9 @@ namespace DiIiS_NA.LoginServer.Toons
set
{
_flags = value;
lock (DBToon)
lock (DbToon)
{
var dbToon = DBToon;
var dbToon = DbToon;
dbToon.Flags = value;
DBSessions.SessionUpdate(dbToon);
}
@ -440,7 +440,7 @@ namespace DiIiS_NA.LoginServer.Toons
{
if (_levelChanged || !LoginServerConfig.Instance.Enabled)
{
_cachedLevel = DBToon.Level;
_cachedLevel = DbToon.Level;
_levelChanged = false;
}
@ -448,10 +448,10 @@ namespace DiIiS_NA.LoginServer.Toons
}
private set
{
lock (DBToon)
lock (DbToon)
{
_cachedLevel = value;
var dbToon = DBToon;
var dbToon = DbToon;
dbToon.Level = value;
DBSessions.SessionUpdate(dbToon);
}
@ -459,7 +459,7 @@ namespace DiIiS_NA.LoginServer.Toons
}
private int _cachedParagonLevel = 0;
public bool _paragonLevelChanged = true;
public bool ParagonLevelChanged = true;
/// <summary>
/// Toon's Paragon level.
@ -468,9 +468,9 @@ namespace DiIiS_NA.LoginServer.Toons
{
get
{
if (!_paragonLevelChanged && LoginServerConfig.Instance.Enabled) return _cachedParagonLevel;
if (!ParagonLevelChanged && LoginServerConfig.Instance.Enabled) return _cachedParagonLevel;
_cachedParagonLevel = GameAccount.DBGameAccount.ParagonLevel;
_paragonLevelChanged = false;
ParagonLevelChanged = false;
return _cachedParagonLevel;
}
@ -494,16 +494,16 @@ namespace DiIiS_NA.LoginServer.Toons
/// </summary>
public long ExperienceNext
{
get => (Level >= 70 ? ParagonExperienceNext : DBToon.Experience);
get => (Level >= 70 ? ParagonExperienceNext : DbToon.Experience);
set
{
if (Level >= 70)
ParagonExperienceNext = value;
else
{
lock (DBToon)
lock (DbToon)
{
var dbToon = DBToon;
var dbToon = DbToon;
dbToon.Experience = value;
DBSessions.SessionUpdate(dbToon);
}
@ -530,12 +530,12 @@ namespace DiIiS_NA.LoginServer.Toons
public int CurrentAct
{
get => DBToon.CurrentAct;
get => DbToon.CurrentAct;
set
{
lock (DBToon)
lock (DbToon)
{
var dbToon = DBToon;
var dbToon = DbToon;
dbToon.CurrentAct = value;
DBSessions.SessionUpdate(dbToon);
}
@ -544,12 +544,12 @@ namespace DiIiS_NA.LoginServer.Toons
public int CurrentQuestId
{
get => DBToon.CurrentQuestId;
get => DbToon.CurrentQuestId;
set
{
lock (DBToon)
lock (DbToon)
{
var dbToon = DBToon;
var dbToon = DbToon;
dbToon.CurrentQuestId = value;
DBSessions.SessionUpdate(dbToon);
}
@ -558,12 +558,12 @@ namespace DiIiS_NA.LoginServer.Toons
public int PvERating
{
get => DBToon.PvERating;
get => DbToon.PvERating;
set
{
lock (DBToon)
lock (DbToon)
{
var dbToon = DBToon;
var dbToon = DbToon;
dbToon.PvERating = value;
DBSessions.SessionUpdate(dbToon);
}
@ -572,12 +572,12 @@ namespace DiIiS_NA.LoginServer.Toons
public int CurrentQuestStepId
{
get => DBToon.CurrentQuestStepId;
get => DbToon.CurrentQuestStepId;
set
{
lock (DBToon)
lock (DbToon)
{
var dbToon = DBToon;
var dbToon = DbToon;
dbToon.CurrentQuestStepId = value;
DBSessions.SessionUpdate(dbToon);
}
@ -586,12 +586,12 @@ namespace DiIiS_NA.LoginServer.Toons
public int CurrentDifficulty
{
get => DBToon.CurrentDifficulty;
get => DbToon.CurrentDifficulty;
set
{
lock (DBToon)
lock (DbToon)
{
var dbToon = DBToon;
var dbToon = DbToon;
dbToon.CurrentDifficulty = value;
DBSessions.SessionUpdate(dbToon);
}
@ -606,11 +606,11 @@ namespace DiIiS_NA.LoginServer.Toons
get => GameAccount.DBGameAccount.TotalKilled;
set
{
var dbGA = GameAccount.DBGameAccount;
lock (dbGA)
var dbGa = GameAccount.DBGameAccount;
lock (dbGa)
{
dbGA.TotalKilled = value;
DBSessions.SessionUpdate(dbGA);
dbGa.TotalKilled = value;
DBSessions.SessionUpdate(dbGa);
}
}
}
@ -623,11 +623,11 @@ namespace DiIiS_NA.LoginServer.Toons
get => GameAccount.DBGameAccount.ElitesKilled;
set
{
var dbGA = GameAccount.DBGameAccount;
lock (dbGA)
var dbGa = GameAccount.DBGameAccount;
lock (dbGa)
{
dbGA.ElitesKilled = value;
DBSessions.SessionUpdate(dbGA);
dbGa.ElitesKilled = value;
DBSessions.SessionUpdate(dbGa);
}
}
}
@ -650,19 +650,19 @@ namespace DiIiS_NA.LoginServer.Toons
}
set
{
var dbGA = GameAccount.DBGameAccount;
lock (dbGA)
var dbGa = GameAccount.DBGameAccount;
lock (dbGa)
{
if (IsHardcore)
{
dbGA.TotalBountiesHardcore = value;
dbGa.TotalBountiesHardcore = value;
}
else
{
dbGA.TotalBounties = value;
dbGa.TotalBounties = value;
}
DBSessions.SessionUpdate(dbGA);
DBSessions.SessionUpdate(dbGa);
}
}
}
@ -672,10 +672,10 @@ namespace DiIiS_NA.LoginServer.Toons
/// </summary>
public int SeasonalKills
{
get => DBToon.Kills;
get => DbToon.Kills;
set
{
var dbToon = DBToon;
var dbToon = DbToon;
lock (dbToon)
{
dbToon.Kills = value;
@ -714,12 +714,12 @@ namespace DiIiS_NA.LoginServer.Toons
/// </summary>
public int CollectedGoldSeasonal
{
get => DBToon.GoldGained;
get => DbToon.GoldGained;
set
{
lock (DBToon)
lock (DbToon)
{
var dbToon = DBToon;
var dbToon = DbToon;
dbToon.GoldGained = value;
DBSessions.SessionUpdate(dbToon);
}
@ -731,12 +731,12 @@ namespace DiIiS_NA.LoginServer.Toons
/// </summary>
public int TimePlayed
{
get => DBToon.TimePlayed;
get => DbToon.TimePlayed;
set
{
lock (DBToon)
lock (DbToon)
{
var dbToon = DBToon;
var dbToon = DbToon;
dbToon.TimePlayed = value;
DBSessions.SessionUpdate(dbToon);
}
@ -751,7 +751,7 @@ namespace DiIiS_NA.LoginServer.Toons
/// <summary>
/// Database handler for this toon
/// </summary>
public GameDBSession DBSession { get; set; }
public GameDBSession DbSession { get; set; }
/// <summary>
/// Settings for toon.
@ -772,14 +772,14 @@ namespace DiIiS_NA.LoginServer.Toons
{
get
{
var dbToon = DBToon;
var dbToon = DbToon;
if (IsHardcore) dbToon.Flags |= ToonFlags.Hardcore;
//var isSeason = Convert.ToUInt16(isSeassoned);
var digest = D3.Hero.Digest.CreateBuilder().SetVersion(905)
.SetHeroId(D3EntityID)
.SetHeroId(D3EntityId)
.SetHeroName(Name)
.SetGbidClass((int)ClassID)
.SetGbidClass((int)ClassId)
.SetLevel(Level)
//deprecated //.SetAltLevel(dbToon.ParagonLevel)
.SetPlayerFlags((uint)dbToon.Flags) // + isSeason)
@ -936,7 +936,7 @@ namespace DiIiS_NA.LoginServer.Toons
.SetIdHigh(0x3C000002517A293 + invItem.Id))
.SetHirelingClass(0)
.SetItemSlot(272 + invItem.EquipmentSlot * 16)
.SetOwnerEntityId(D3EntityID)
.SetOwnerEntityId(D3EntityId)
.SetSquareIndex(0)
.SetUsedSocketCount(0);
@ -1014,7 +1014,7 @@ namespace DiIiS_NA.LoginServer.Toons
}
//*/
var dbToon = DBToon;
var dbToon = DbToon;
string[] stats = dbToon.Stats.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
var profile = D3.Profile.HeroProfile.CreateBuilder()
.SetHardcore(IsHardcore)
@ -1022,7 +1022,7 @@ namespace DiIiS_NA.LoginServer.Toons
//deprecated //.SetLife(0)
.SetSnoKillLocation(71150)
.SetKillerInfo(D3.Profile.KillerInfo.CreateBuilder().SetSnoKiller(6031).SetRarity(4))
.SetHeroId(D3EntityID)
.SetHeroId(D3EntityId)
//deprecated //.SetHighestDifficulty(0)
.SetHighestLevel(dbToon.Level)
//.SetMonstersKilled(111)
@ -1045,9 +1045,9 @@ namespace DiIiS_NA.LoginServer.Toons
//.SetResistCold(110)
//.SetResistPoison(111)
.SetEquipment(itemList);
if (DBActiveSkills != null)
if (DbActiveSkills != null)
{
var dbActiveSkills = DBActiveSkills;
var dbActiveSkills = DbActiveSkills;
var skills = new[]
{
D3.Profile.SkillWithRune.CreateBuilder()
@ -1104,7 +1104,7 @@ namespace DiIiS_NA.LoginServer.Toons
}
}
public int ClassID =>
public int ClassId =>
Class switch
{
ToonClass.Barbarian => 0x4FB91EE2,
@ -1118,7 +1118,7 @@ namespace DiIiS_NA.LoginServer.Toons
};
// Used for Conversations
public int VoiceClassID =>
public int VoiceClassId =>
Class switch
{
ToonClass.DemonHunter => 0,
@ -1139,21 +1139,21 @@ namespace DiIiS_NA.LoginServer.Toons
private readonly Dictionary<int, int> _visualToSlotMapping = new() { { 1, 0 }, { 2, 1 }, { 7, 2 }, { 5, 3 }, { 4, 4 }, { 3, 5 }, { 8, 6 }, { 9, 7 } };
private static readonly Core.MPQ.FileFormats.GameBalance HeroData =
public static readonly Core.MPQ.FileFormats.GameBalance HeroData =
(Core.MPQ.FileFormats.GameBalance)MPQStorage.Data.Assets[SNOGroup.GameBalance][19740].Data;
public Toon(DBToon dbToon, GameDBSession DBSession = null)
public Toon(DBToon dbToon, GameDBSession dbSession = null)
: base(dbToon.Id)
{
D3EntityID = D3.OnlineService.EntityId.CreateBuilder().SetIdHigh((ulong)EntityIdHelper.HighIdType.ToonId)
D3EntityId = D3.OnlineService.EntityId.CreateBuilder().SetIdHigh((ulong)EntityIdHelper.HighIdType.ToonId)
.SetIdLow(PersistentID).Build();
_heroName = dbToon.Name;
_flags = dbToon.Flags;
GameAccountId = dbToon.DBGameAccount.Id;
_toonClass = dbToon.Class;
DBToon = dbToon;
this.DBSession = DBSession;
DbToon = dbToon;
this.DbSession = dbSession;
IsHardcore = dbToon.isHardcore;
IsSeasoned = dbToon.isSeasoned;
HeroTable = HeroData.Heros.Find(item => item.Name == Class.ToString());
@ -1190,7 +1190,7 @@ namespace DiIiS_NA.LoginServer.Toons
{
var questHistory = new DBQuestHistory
{
DBToon = DBToon,
DBToon = DbToon,
QuestId = quest,
QuestStep = -1,
isCompleted = true
@ -1209,8 +1209,8 @@ namespace DiIiS_NA.LoginServer.Toons
public void StateChanged()
{
_levelChanged = true;
_paragonLevelChanged = true;
_visualEquipmentChanged = true;
ParagonLevelChanged = true;
VisualEquipmentChanged = true;
}
#region Notifications
@ -1242,7 +1242,7 @@ namespace DiIiS_NA.LoginServer.Toons
#endregion
public static ToonClass GetClassByID(int classId) =>
public static ToonClass GetClassById(int classId) =>
classId switch
{
0x4FB91EE2 => ToonClass.Barbarian,
@ -1257,7 +1257,7 @@ namespace DiIiS_NA.LoginServer.Toons
public override string ToString()
{
return $"{{ Toon: {Name} [lowId: {D3EntityID.IdLow}] }}";
return $"{{ Toon: {Name} [lowId: {D3EntityId.IdLow}] }}";
}
}

View File

@ -240,7 +240,7 @@ namespace DiIiS_NA.LoginServer.Toons
var newDBToon = new DBToon
{
Class = @Toon.GetClassByID(classId),
Class = @Toon.GetClassById(classId),
Name = name,
/*HashCode = GetUnusedHashCodeForToonName(name),*/
Flags = toonFlags,
@ -309,19 +309,19 @@ namespace DiIiS_NA.LoginServer.Toons
public static void CreateStartEquipment(Toon toon, bool isHardcore)
{
DBInventory pants = NewbiePants;
pants.DBToon = toon.DBToon;
pants.DBToon = toon.DbToon;
pants.DBGameAccount = toon.GameAccount.DBGameAccount;
pants.isHardcore = isHardcore;
DBSessions.SessionSave(pants);
DBInventory armor = NewbieArmor;
armor.DBToon = toon.DBToon;
armor.DBToon = toon.DbToon;
armor.DBGameAccount = toon.GameAccount.DBGameAccount;
armor.isHardcore = isHardcore;
DBSessions.SessionSave(armor);
DBInventory weapon;
switch (toon.DBToon.Class)
switch (toon.DbToon.Class)
{
case ToonClass.Barbarian:
weapon = NewbieAxe;
@ -348,14 +348,14 @@ namespace DiIiS_NA.LoginServer.Toons
weapon = NewbieKnife;
break;
}
weapon.DBToon = toon.DBToon;
weapon.DBToon = toon.DbToon;
weapon.DBGameAccount = toon.GameAccount.DBGameAccount;
weapon.isHardcore = isHardcore;
DBSessions.SessionSave(weapon);
if (toon.DBToon.Class == ToonClass.Crusader) //add shield
if (toon.DbToon.Class == ToonClass.Crusader) //add shield
{
weapon = NewbieShield;
weapon.DBToon = toon.DBToon;
weapon.DBToon = toon.DbToon;
weapon.DBGameAccount = toon.GameAccount.DBGameAccount;
weapon.isHardcore = isHardcore;
DBSessions.SessionSave(weapon);
@ -367,7 +367,7 @@ namespace DiIiS_NA.LoginServer.Toons
DBSessions.SessionSave(new DBHireling
{
Class = type,
DBToon = toon.DBToon,
DBToon = toon.DbToon,
Skill1SNOId = -1,
Skill2SNOId = -1,
Skill3SNOId = -1,

View File

@ -219,4 +219,12 @@ namespace DiIiS_NA.Core.Helpers.Math
/// <returns></returns>
public bool Chance(float successPercentage) => Next(100) < successPercentage;
}
public static class NumberExtensions
{
public static float ToFloat(this double value, int decimals = 4) => (float)System.Math.Round(value, decimals);
public static float ToFloat(this float value, int decimals = 4) => (float)System.Math.Round(value, decimals);
public static double ToDouble(this float value, int decimals = 4) => (double)System.Math.Round(value, decimals);
public static double ToDouble(this double value, int decimals = 4) => (double)System.Math.Round(value, decimals);
}
}

View File

@ -23,6 +23,21 @@ public static class RandomHelper
return Random.Next(minValue, maxValue);
}
public static float NextFloat()
{
return (float)Random.NextDouble();
}
public static float NextFloat(float min, float max)
{
return min + (float)Random.NextDouble() * (max - min);
}
public static float NextFloat(float max)
{
return (float)Random.NextDouble() * max;
}
public static void NextBytes(byte[] buffer)
{
Random.NextBytes(buffer);

View File

@ -22,28 +22,19 @@ namespace DiIiS_NA.Core.Logging
/// </summary>
internal readonly static Dictionary<string, Logger> Loggers = new();
/// <summary>
/// Creates and returns a logger named with declaring type.
/// </summary>
/// <returns>A <see cref="Logger"/> instance.</returns>
public static Logger CreateLogger([CallerFilePath] string filePath = "")
{
var frame = new StackFrame(1, false); // read stack frame.
var name = frame.GetMethod().DeclaringType.Name; // get declaring type's name.
if (name == null) // see if we got a name.
throw new Exception("Error getting full name for declaring type.");
return CreateLogger(name, filePath); // return the newly created logger.
}
/// <summary>
/// Creates and returns a logger with given name.
/// </summary>
/// <param name="name"></param>
/// <returns>A <see cref="Logger"/> instance.</returns>
public static Logger CreateLogger(string name, [CallerFilePath] string filePath = "")
public static Logger CreateLogger(string? name = null, [CallerFilePath] string filePath = "")
{
if (name == null)
{
var frame = new StackFrame(1, false); // read stack frame.
name = frame.GetMethod()?.DeclaringType?.Name ?? "Unknown"; // get declaring type's name.
}
if (!Loggers.ContainsKey(name)) // see if we already have instance for the given name.
Loggers.Add(name, new Logger(name, filePath)); // add it to dictionary of loggers.

View File

@ -36,10 +36,7 @@ namespace DiIiS_NA.Core.Storage.AccountDataBase
{
_config = new Configuration();
#if DEBUG
if (File.Exists(Path.Combine(FileHelpers.AssemblyRoot, "database.Account.Debug.config")))
_config = _config.Configure(Path.Combine(FileHelpers.AssemblyRoot, "database.Account.Debug.config"));
else
_config = _config.Configure(Path.Combine(FileHelpers.AssemblyRoot, "database.Account.config"));
_config = _config.Configure(File.Exists(Path.Combine(FileHelpers.AssemblyRoot, "database.Account.Debug.config")) ? Path.Combine(FileHelpers.AssemblyRoot, "database.Account.Debug.config") : Path.Combine(FileHelpers.AssemblyRoot, "database.Account.config"));
#else
_config = _config.Configure(Path.Combine(FileHelpers.AssemblyRoot, "database.Account.config"));
#endif

View File

@ -35,8 +35,11 @@ namespace DiIiS_NA.Core.Storage.WorldSceneBase
if (_config == null)
{
_config = new Configuration();
#if DEBUG
_config = _config.Configure(File.Exists(Path.Combine(FileHelpers.AssemblyRoot, "database.Worlds.Debug.config")) ? Path.Combine(FileHelpers.AssemblyRoot, "database.Worlds.Debug.config") : Path.Combine(FileHelpers.AssemblyRoot, "database.Worlds.config"));
#else
_config = _config.Configure(Path.Combine(FileHelpers.AssemblyRoot, "database.Worlds.config"));
#endif
var replacedProperties = new Dictionary<string, string>();
foreach (var prop in _config.Properties)

View File

@ -281,7 +281,7 @@ namespace DiIiS_NA.GameServer.Core
if (EquipmentSlot == 15)
ownerPlayer.Inventory.SaveItemToDB(ownerPlayer.Toon.GameAccount.DBGameAccount, null, EquipmentSlotId.Stash, item);
else
ownerPlayer.Inventory.SaveItemToDB(ownerPlayer.Toon.GameAccount.DBGameAccount, ownerPlayer.Toon.DBToon, EquipmentSlotId.Inventory, item);
ownerPlayer.Inventory.SaveItemToDB(ownerPlayer.Toon.GameAccount.DBGameAccount, ownerPlayer.Toon.DbToon, EquipmentSlotId.Inventory, item);
}
}

View File

@ -7,6 +7,9 @@ using DiIiS_NA.Core.Storage;
using System;
using System.Numerics;
using DiIiS_NA.Core.Helpers.Math;
using System.Collections.Generic;
using System.Linq;
using DiIiS_NA.GameServer.GSSystem.ActorSystem;
namespace DiIiS_NA.GameServer.Core.Types.Math
{
@ -112,6 +115,18 @@ namespace DiIiS_NA.GameServer.Core.Types.Math
return ((x * x) + (y * y)) + (z * z);
}
public static double Distance(Vector3D vector1, Vector3D vector2)
{
return ((vector1.X * vector2.X) + (vector1.Y * vector2.Y) + (vector1.Z * vector2.Z));
}
public static bool IsInDistanceSquared(Vector3D position, Vector3D relative, double distanceMax, double distanceMin = -1f)
{
var dist = Distance(position, relative);
return dist < distanceMax && dist > distanceMin;
}
private static Random rand = new Random();
public Vector3D Around(float radius)
@ -185,5 +200,34 @@ namespace DiIiS_NA.GameServer.Core.Types.Math
public override string ToString() => $"X:{X:F4}, Y:{Y:F4} Z:{Z:F4}";
public bool IsNear(Vector3D other, float distance) => DistanceSquared(ref other) < distance;
public override int GetHashCode() => HashCode.Combine(X.ToDouble(decimals: 6), Y.ToDouble(decimals: 6), Z.ToDouble(decimals: 6));
}
public static class VectorExtensions
{
/// <summary>
/// Takes all actors from the given collection that are within the specified distance of the reference position.
/// </summary>
/// <typeparam name="TActor"></typeparam>
/// <param name="actors"></param>
/// <param name="referencePosition"></param>
/// <param name="query"></param>
/// <returns></returns>
public static TSearch[] WhereNearbyOf<TActor, TSearch>(
this IEnumerable<TActor> actors,
TSearch[] referenceActors,
Func<TSearch, bool> query,
double maxDistance = 50f,
double minDistance = 1f)
where TActor : Actor
where TSearch : Actor
{
return actors.OfType<TSearch>()
.Where(actor => query(actor))
.Where((actor, dist) =>
referenceActors.Any(refActor => refActor.GlobalID != actor.GlobalID && Vector3D.IsInDistanceSquared(refActor.Position, actor.Position, maxDistance, minDistance)))
.ToArray();
}
}
}

View File

@ -52,7 +52,7 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem.Implementations
World.SpawnRandomEquip(player, player,
FastRandom.Instance.Next(100) < chance ? LootManager.Epic : LootManager.Rare, player.Level);
var toon = player.Toon.DBToon;
var toon = player.Toon.DbToon;
toon.ChestsOpened++;
World.Game.GameDbSession.SessionUpdate(toon);
}

View File

@ -94,7 +94,7 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem.Implementations
if (haveDrop)
{
var dropRates = World.Game.IsHardcore ? LootManager.GetSeasonalDropRates((int)Quality, Program.MaxLevel) : LootManager.GetDropRates((int)Quality, Program.MaxLevel);
var dropRates = World.Game.IsHardcore ? LootManager.GetSeasonalDropRates((int)Quality, Program.MAX_LEVEL) : LootManager.GetDropRates((int)Quality, Program.MAX_LEVEL);
foreach (var rate in dropRates)
foreach (var plr in GetPlayersInRange(30))
{

View File

@ -18,6 +18,16 @@ using DiIiS_NA.GameServer.GSSystem.AISystem.Brains;
using DiIiS_NA.GameServer.GSSystem.ActorSystem.Implementations;
using DiIiS_NA.D3_GameServer.Core.Types.SNO;
using World = DiIiS_NA.GameServer.GSSystem.MapSystem.World;
using DiIiS_NA.Core.Helpers.Math;
using DiIiS_NA.LoginServer.Toons;
using static DiIiS_NA.Core.MPQ.FileFormats.Monster;
using D3.Store;
using DiIiS_NA.GameServer.GSSystem.AISystem;
using DiIiS_NA.GameServer.GSSystem.MapSystem;
using Microsoft.EntityFrameworkCore.Metadata;
using static DiIiS_NA.Core.Logging.Logger;
using System.IO;
using System.Net.NetworkInformation;
namespace DiIiS_NA.GameServer.GSSystem.ActorSystem
{
@ -40,8 +50,8 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem
public int LoreSnoId => Monster.IsValid ? ((MonsterFF)Monster.Target).SNOLore : -1;
public int MonsterType => Monster.IsValid ? (int)((MonsterFF)Monster.Target).Type : -1;
public int MonsterTypeValue => Monster.IsValid ? (int)((MonsterFF)Monster.Target).Type : -1;
public MonsterType MonsterType => (MonsterType)(((MonsterFF)Monster.Target)?.Type ?? MonsterType.Unknown);
public float HpMultiplier => Monster.IsValid ? (1f + ((MonsterFF)Monster.Target).AttributeModifiers[4]) : 1f;
public float DmgMultiplier => Monster.IsValid ? (1f + ((MonsterFF)Monster.Target).AttributeModifiers[55]) : 1f;
@ -87,6 +97,10 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem
public void UpdateStats()
{
// TODO: Level up is getting harder from level 3+. 1 seems stable. check the difficulty.
// TODO: Level up is getting harder from level 3+. 1 seems stable. check the difficulty.
// TODO: Level up is getting harder from level 3+. 1 seems stable. check the difficulty.
var monsterLevels = (GameBalance)DiIiS_NA.Core.MPQ.MPQStorage.Data.Assets[SNOGroup.GameBalance][19760].Data;
bool fullHp = (Math.Abs(Attributes[GameAttributes.Hitpoints_Cur] - Attributes[GameAttributes.Hitpoints_Max_Total]) < Globals.FLOAT_TOLERANCE);
Attributes[GameAttributes.Level] = World.Game.MonsterLevel;
@ -94,40 +108,169 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem
int monsterLevel = 1;
monsterLevel = World.Game.ConnectedPlayers.Length > 1 ? World.Game.ConnectedPlayers[0].Level : World.Game.InitialMonsterLevel;
var connectedPlayers = World.Game.ConnectedPlayers.ToArray();
double maxUsersHealth = 1f;
double deltaDamageUsers = 1f;
int userLevelAverage = 1;
Attributes[GameAttributes.Hitpoints_Max] = (int)((int)monsterLevels.MonsterLevel[monsterLevel].HPMin + DiIiS_NA.Core.Helpers.Math.RandomHelper.Next(0, (int)monsterLevels.MonsterLevel[monsterLevel].HPDelta) * HpMultiplier * World.Game.HpModifier);
Attributes[GameAttributes.Hitpoints_Max_Percent_Bonus_Multiplicative] = ((int)World.Game.ConnectedPlayers.Length + 1) * 1.5f;
Attributes[GameAttributes.Hitpoints_Max_Percent_Bonus_Multiplicative] *= GameModsConfig.Instance.Monster.HealthMultiplier;
if (World.Game.ConnectedPlayers.Length > 1)
Attributes[GameAttributes.Hitpoints_Max_Percent_Bonus_Multiplicative] = Attributes[GameAttributes.Hitpoints_Max_Percent_Bonus_Multiplicative];// / 2f;
var hpMax = Attributes[GameAttributes.Hitpoints_Max];
var hpTotal = Attributes[GameAttributes.Hitpoints_Max_Total];
float damageMin = monsterLevels.MonsterLevel[World.Game.MonsterLevel].Dmg * DmgMultiplier;// * 0.5f;
float damageDelta = damageMin;
Attributes[GameAttributes.Damage_Weapon_Min, 0] = damageMin * World.Game.DmgModifier * GameModsConfig.Instance.Monster.DamageMultiplier;
Attributes[GameAttributes.Damage_Weapon_Delta, 0] = damageDelta;
if (monsterLevel > 30)
if (connectedPlayers.Any())
{
Attributes[GameAttributes.Hitpoints_Max_Percent_Bonus_Multiplicative] = Attributes[GameAttributes.Hitpoints_Max_Percent_Bonus_Multiplicative];// * 0.5f;
Attributes[GameAttributes.Damage_Weapon_Min, 0] = damageMin * World.Game.DmgModifier * GameModsConfig.Instance.Monster.DamageMultiplier;// * 0.2f;
Attributes[GameAttributes.Damage_Weapon_Delta, 0] = damageDelta;
}
if (monsterLevel > 60)
{
Attributes[GameAttributes.Hitpoints_Max_Percent_Bonus_Multiplicative] = Attributes[GameAttributes.Hitpoints_Max_Percent_Bonus_Multiplicative];// * 0.7f;
Attributes[GameAttributes.Damage_Weapon_Min, 0] = damageMin * World.Game.DmgModifier * GameModsConfig.Instance.Monster.DamageMultiplier;// * 0.15f;
//this.Attributes[GameAttribute.Damage_Weapon_Delta, 0] = DamageDelta * 0.5f;
maxUsersHealth = connectedPlayers.Average(x => x.Attributes[GameAttributes.Hitpoints_Max]);
deltaDamageUsers = connectedPlayers.Average(x => x.Attributes[GameAttributes.Damage_Delta]);
userLevelAverage = (int)connectedPlayers.Average(x => x.Level);
Logger.MethodTrace($"$[yellow]${connectedPlayers.Length}$[/]$ $[green]$players online$[/]$: $[blue dim]${maxUsersHealth}$[/]$ $[bold]$avg. max health$[/]$ / $[blue dim italic]${deltaDamageUsers}$[/]$ $[bold]$avg. delta damage$[/]$");
}
_nativeHp = Attributes[GameAttributes.Hitpoints_Max_Total];
_nativeDmg = Attributes[GameAttributes.Damage_Weapon_Min, 0];
var difficulty = World.Game.Difficulty;
var maxHP = (monsterLevels.MonsterLevel[monsterLevel].HPMin +
RandomHelper.NextFloat(0f, monsterLevels.MonsterLevel[monsterLevel].HPDelta)) *
HpMultiplier * World.Game.HpModifier;
var bonus = CalculateLevelAdjustment(LevelAdjustmentEnum.LinearScaling, difficulty, connectedPlayers);
Attributes[GameAttributes.Hitpoints_Max] = maxHP;
Attributes[GameAttributes.Hitpoints_Max_Percent_Bonus_Multiplicative] = bonus;
var baseHp = Attributes[GameAttributes.Hitpoints_Max];
var baseDamage = Attributes[GameAttributes.Damage_Weapon_Min, 0];
// Apply calculated scaling
baseHp *= bonus;
baseDamage *= bonus;
// Apply configuration modifiers
baseHp *= GameModsConfig.Instance.Monster.HealthMultiplier;
baseDamage *= GameModsConfig.Instance.Monster.DamageMultiplier;
// Assign modified values
Attributes[GameAttributes.Hitpoints_Max_Total] = baseHp;
Attributes[GameAttributes.Damage_Weapon_Min, 0] = baseDamage;
//if (full_hp)
Attributes[GameAttributes.Hitpoints_Cur] = Attributes[GameAttributes.Hitpoints_Max_Total];
Attributes.BroadcastChangedIfRevealed();
}
enum LevelAdjustmentEnum { LinearScaling, DiminishedReturns, CurveScaling, LinearScalingAndDiminishedReturnsAfterThreshold }
private float CalculateLevelAdjustment(LevelAdjustmentEnum levelAdjustment, int difficulty = 0, params Player[] players)
{
var playersStats = players.Select(s =>
new
{
s.Attributes,
TotalLevel = s.Level + s.ParagonLevel * 1.05f,
Health = s.Attributes[GameAttributes.Hitpoints_Max],
Damage = s.Attributes[GameAttributes.Damage_Weapon_Min, 0],
Toughness = s.Attributes[GameAttributes.Armor_Total],
DPS = s.Attributes[GameAttributes.DPS]
}
).ToArray();
var monstersNearbyStats = players.WhereNearbyOf(World.Monsters.ToArray(), s => s.Visible && s.Alive && s.Attributes[GameAttributes.Hitpoints_Max] * 0.8 > Attributes[GameAttributes.Hitpoints_Cur], 120f, 1f).ToArray();
var monsterStats = monstersNearbyStats.Select(s =>
new
{
s.Attributes,
Health = s.Attributes[GameAttributes.Hitpoints_Max],
Damage = s.Attributes[GameAttributes.Damage_Weapon_Min, 0],
Toughness = s.Attributes[GameAttributes.Armor_Total],
DPS = s.Attributes[GameAttributes.DPS]
}
).ToArray();
// Define configuration constants
// This is the multiplier for linear scaling. It determines how much the monster's level increases for each player level.
// If you increase this value, monsters will become stronger faster as player levels increase.
const float linearMultiplierConfig = 0.025f;
// This is the multiplier for diminished returns scaling. It determines how much the monster's level increases for each player level,
// but the increase becomes smaller as player levels get higher. If you increase this value, monsters will become stronger faster at lower player levels.
const float diminishedMultiplierConfig = 0.1f;
// This is the base value for diminished returns scaling. It's the starting point for the monster's level before any scaling is applied.
// If you increase this value, monsters will start off stronger before any player level scaling is applied.
const float diminishedBaseConfig = 1.0f;
// This is the multiplier for curve scaling. It determines how much the monster's level increases for each player level,
// but the increase becomes larger as player levels get higher. If you increase this value, monsters will become stronger faster at higher player levels.
const float curveMultiplierConfig = 0.1f;
// This is the base value for curve scaling. It's the starting point for the monster's level before any scaling is applied.
// If you increase this value, monsters will start off stronger before any player level scaling is applied.
const float curveBaseConfig = 30.0f;
// This is the exponent for curve scaling. It determines the shape of the curve for how much the monster's level increases for each player level.
// If you increase this value, the curve will be steeper, meaning monsters will become much stronger at higher player levels.
const float curveExponentConfig = 0.1f;
// This is the multiplier for linear scaling after a certain threshold. It determines how much the monster's level increases for each player level
// after the player level has reached a certain threshold. If you increase this value, monsters will become stronger faster after player levels reach the threshold.
const float linearMultiplierThresholdConfig = 0.005f;
// This is the multiplier for log scaling. It determines how much the monster's level increases for each player level,
// but the increase becomes smaller as player levels get higher. If you increase this value, monsters will become stronger faster at lower player levels.
const float logMultiplierConfig = 0.1f;
// This is the threshold for linear scaling. It determines the player level at which linear scaling starts to apply.
// If you increase this value, linear scaling will start to apply at higher player levels.
const float thresholdConfig = 40.0f;
// This is the ratio for DPS (Damage Per Second) scaling. It determines how much the monster's level increases for each unit of player DPS.
// If you increase this value, monsters will become stronger faster as player DPS increases.
const float dpsRatioConfig = 1.2f;
// This is the ratio for toughness scaling. It determines how much the monster's level increases for each unit of player toughness.
// If you increase this value, monsters will become stronger faster as player toughness increases.
const float toughnessRatioConfig = 0.1f;
// Define variables for average user and monster stats
// float avgUserLevel = playersStats.Average(s => s.TotalLevel);
// float avgUserDPS = playersStats.Average(s => s.DPS);
// float avgUserToughness = playersStats.Average(s => s.Toughness);
//float avgMonsterDPS = playersStats.Average(s => s.DPS);
// float avgMonsterToughness = monsterStats.Average(s => s.Toughness);
//var tierMultiplier = GetMonsterTierMultiplier();
float avgUserLevel = 1f, avgUserDPS = 1f, avgUserToughness = 1f, avgMonsterDPS = 1f, avgMonsterToughness = 1f, tierMultiplier = 1f;
if (playersStats.Any())
{
avgUserLevel = playersStats.Average(s => s.TotalLevel);
avgUserDPS = playersStats.Average(s => s.DPS);
avgUserToughness = playersStats.Average(s => s.Toughness);
}
if (monsterStats.Any())
{
avgMonsterDPS = playersStats.Average(s => s.DPS);
avgMonsterToughness = monsterStats.Average(s => s.Toughness);
tierMultiplier = GetMonsterTierMultiplier();
}
float LevelScaling() => 1.0f + 0.1f * MathF.Log10(avgUserLevel + 1) * tierMultiplier;
float DiminishedReturns() => diminishedBaseConfig + diminishedMultiplierConfig * avgUserLevel;
float CurveScaling() => curveBaseConfig * MathF.Pow(avgUserLevel, curveExponentConfig) * curveMultiplierConfig;
float LinearScalingAndDiminishedReturnsAfterThreshold() => MathF.Max(1.0f, MathF.Min(1.5f, logMultiplierConfig * MathF.Log10(avgUserLevel + 1) + (avgUserLevel - thresholdConfig) * linearMultiplierThresholdConfig) * tierMultiplier);
return levelAdjustment switch
{
LevelAdjustmentEnum.LinearScaling => LevelScaling(),
LevelAdjustmentEnum.DiminishedReturns => DiminishedReturns(),
LevelAdjustmentEnum.CurveScaling => CurveScaling(),
LevelAdjustmentEnum.LinearScalingAndDiminishedReturnsAfterThreshold => LinearScalingAndDiminishedReturnsAfterThreshold(),
_ => LinearScalingAndDiminishedReturnsAfterThreshold()
};
}
private float GetMonsterTierMultiplier()
{
return MonsterType switch
{
MonsterType.Beast => 1.1f,
MonsterType.Demon => 1.15f,
MonsterType.Human => 1.25f,
MonsterType.Undead => 1.4f, // Steeper jump here
_ => 1.0f,
};
}
int _bleedFirstTick = 0;
int _caltropsFirstTick = 0;

View File

@ -26,7 +26,7 @@ namespace DiIiS_NA.GameServer.GSSystem.GameSystem
private bool SenderMessageReceived(byte[] data)
{
string msg = "";
if (data != null && data.Length > 0) msg = Encoding.UTF8.GetString(data);
if (data is { Length: > 0 }) msg = Encoding.UTF8.GetString(data);
Logger.Debug("Message from Battle.net: {0}", msg);
var message = msg.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);

View File

@ -31,7 +31,6 @@ using DiIiS_NA.GameServer.GSSystem.ActorSystem.Implementations.Hirelings;
using DiIiS_NA.GameServer.GSSystem.GeneratorsSystem;
using DiIiS_NA.GameServer.GSSystem.AISystem.Brains;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using DiIiS_NA.Core.MPQ.FileFormats;
using DiIiS_NA.D3_GameServer;
using DiIiS_NA.D3_GameServer.Core.Types.SNO;
@ -40,6 +39,7 @@ using Actor = DiIiS_NA.GameServer.GSSystem.ActorSystem.Actor;
using Monster = DiIiS_NA.GameServer.GSSystem.ActorSystem.Monster;
using Scene = DiIiS_NA.GameServer.GSSystem.MapSystem.Scene;
using World = DiIiS_NA.GameServer.GSSystem.MapSystem.World;
using System.Runtime.CompilerServices;
namespace DiIiS_NA.GameServer.GSSystem.GameSystem
{
@ -138,8 +138,8 @@ namespace DiIiS_NA.GameServer.GSSystem.GameSystem
public int AcceptedPlayers;
};
public readonly Dictionary<WorldSno, List<Action>> OnLoadWorldActions = new();
public readonly Dictionary<int, List<Action>> OnLoadSceneActions = new();
public readonly Dictionary<WorldSno, List<System.Action>> OnLoadWorldActions = new();
public readonly Dictionary<int, List<System.Action>> OnLoadSceneActions = new();
public BossEncounter CurrentEncounter = new() { SnoId = -1, Activated = false, AcceptedPlayers = 0 };
@ -661,7 +661,7 @@ namespace DiIiS_NA.GameServer.GSSystem.GameSystem
/// <param name="joinedPlayer">The new player.</param>
public void Enter(Player joinedPlayer)
{
if (IsHardcore && !joinedPlayer.Toon.DBToon.isHardcore)
if (IsHardcore && !joinedPlayer.Toon.DbToon.isHardcore)
{
return;
}
@ -1270,9 +1270,7 @@ namespace DiIiS_NA.GameServer.GSSystem.GameSystem
public void SetDifficulty(int diff)
{
Difficulty = diff;
if (Difficulty < 0) Difficulty = 0;
if (Difficulty > 19) Difficulty = 19;
Difficulty = Math.Clamp(diff, 0, 19);
diff++;
if (diff > 0)
{
@ -1342,13 +1340,13 @@ namespace DiIiS_NA.GameServer.GSSystem.GameSystem
target.InGameClient.SendMessage(new NewPlayerMessage
{
PlayerIndex = joinedPlayer.PlayerIndex,
NewToonId = (long)joinedPlayer.Toon.D3EntityID.IdLow,
NewToonId = (long)joinedPlayer.Toon.D3EntityId.IdLow,
GameAccountId = new GameAccountHandle()
{ ID = (uint)joinedPlayer.Toon.GameAccount.BnetEntityId.Low, Program = 0x00004433, Region = 1 },
ToonName = joinedPlayer.Toon.Name,
Team = 0x00000002,
Class = joinedPlayer.ClassSno,
snoActorPortrait = joinedPlayer.Toon.DBToon.Cosmetic4,
snoActorPortrait = joinedPlayer.Toon.DbToon.Cosmetic4,
Level = joinedPlayer.Toon.Level,
AltLevel = (ushort)joinedPlayer.Toon.ParagonLevel,
HighestHeroSoloRiftLevel = 0,

View File

@ -10,6 +10,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NHibernate.Util;
namespace DiIiS_NA.GameServer.GSSystem.GameSystem
{

View File

@ -6,7 +6,7 @@ using DiIiS_NA.Core.Logging;
namespace DiIiS_NA.GameServer.GSSystem.GameSystem
{
[Obsolete("Doesn't seem to be used anywhere, and may use more resources.")]
[Obsolete("This class is obsolete and will be removed in the future.")]
public class GameUpdateManager
{
private static readonly Logger Logger = LogManager.CreateLogger<GameUpdateManager>();
@ -22,15 +22,13 @@ namespace DiIiS_NA.GameServer.GSSystem.GameSystem
int CPUCount = Environment.ProcessorCount;
for (int coreId = 0; coreId < CPUCount; coreId++)
{
var thread = new GameUpdateThread
{
CPUAffinity = (1UL << coreId)
};
var thread = new GameUpdateThread();
//thread.CPUAffinity = (1UL << coreId);
_updateWorkers.Add(thread);
var loopThread = new Thread(thread.Run) { Name = "UpdateWorkerThread", IsBackground = true }; ; // create the game update thread.
loopThread.Start();
}
Logger.Info("Using {0} worker threads for game updates.", CPUCount);
Logger.Info("Started {0} threads", CPUCount);
}
public static GameUpdateThread FindWorker()

View File

@ -20,18 +20,24 @@ namespace DiIiS_NA.GameServer.GSSystem.GameSystem
[DllImport("libc.so.6")]
private static extern int sched_setaffinity(int pid, IntPtr cpusetsize, ref ulong cpuset);
private int CurrentTId => RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? GetCurrentThreadId() : getpid();
private int CurrentTId
{
get
{
return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? GetCurrentThreadId() : getpid();
}
}
private static readonly Logger Logger = LogManager.CreateLogger();
public List<Game> Games = new List<Game>();
private object _lock = new object();
public ulong CPUAffinity { get; }
public ulong CPUAffinity = 0;
public void Run()
{
List<Game> InactiveGames = new List<Game>();
List<Game> inactiveGames = new List<Game>();
int missedTicks = 0;
Thread.BeginThreadAffinity();
@ -45,15 +51,15 @@ namespace DiIiS_NA.GameServer.GSSystem.GameSystem
while (true)
{
Stopwatch _tickWatch = new Stopwatch();
_tickWatch.Restart();
Stopwatch stopwatch = new Stopwatch();
stopwatch.Restart();
lock (_lock)
{
foreach (var game in Games)
{
if (!game.Working)
InactiveGames.Add(game);
inactiveGames.Add(game);
else
{
if (!game.UpdateInProgress)
@ -65,7 +71,11 @@ namespace DiIiS_NA.GameServer.GSSystem.GameSystem
{
game.Update();
}
catch { }
catch (Exception ex)
{
Logger.ErrorException(ex, "Error in Game.Update()");
}
game.MissedTicks = 0;
game.UpdateInProgress = false;
});
@ -73,25 +83,33 @@ namespace DiIiS_NA.GameServer.GSSystem.GameSystem
else
{
game.MissedTicks += 6;
}
}
}
foreach (var game in InactiveGames)
Games.Remove(game);
InactiveGames.Clear();
}
_tickWatch.Stop();
var compensation = (int)(100 - _tickWatch.ElapsedMilliseconds); // the compensation value we need to sleep in order to get consistent 100 ms Game.Update().
if (_tickWatch.ElapsedMilliseconds > 100)
if (game.MissedTicks > 60)
{
Logger.Trace("Game.Update() took [{0}ms] more than Game.UpdateFrequency [{1}ms].", _tickWatch.ElapsedMilliseconds, 100);
compensation = (int)(100 - (_tickWatch.ElapsedMilliseconds % 100));
missedTicks = 6 * (int)(_tickWatch.ElapsedMilliseconds / 100);
Logger.Warn("Game.Update() is running too slow. GameId: {0}", game.GameId);
game.MissedTicks = 0;
}
}
}
}
foreach (var game in inactiveGames)
{
game.Working = false;
Games.Remove(game);
}
inactiveGames.Clear();
}
stopwatch.Stop();
var compensation = (int)(100 - stopwatch.ElapsedMilliseconds); // the compensation value we need to sleep in order to get consistent 100 ms Game.Update().
if (stopwatch.ElapsedMilliseconds > 100)
{
Logger.Trace("Game.Update() took [{0}ms] more than Game.UpdateFrequency [{1}ms].", stopwatch.ElapsedMilliseconds, 100);
compensation = (int)(100 - (stopwatch.ElapsedMilliseconds % 100));
missedTicks = 6 * (int)(stopwatch.ElapsedMilliseconds / 100);
Thread.Sleep(Math.Max(0, compensation)); // sleep until next Update().
}
else

View File

@ -360,7 +360,7 @@ namespace DiIiS_NA.D3_GameServer.GSSystem.GameSystem
{
player.World.SpawnRandomEquip(player, player, LootManager.Epic, player.Attributes[GameAttributes.Level]);
}
var toon = player.Toon.DBToon;
var toon = player.Toon.DbToon;
toon.EventsCompleted++;
Game.GameDbSession.SessionUpdate(toon);
player.CheckQuestCriteria(Game.CurrentSideQuest);
@ -850,7 +850,7 @@ namespace DiIiS_NA.D3_GameServer.GSSystem.GameSystem
{
var questHistory = new DBQuestHistory
{
DBToon = player.Toon.DBToon,
DBToon = player.Toon.DbToon,
QuestId = Game.CurrentQuest,
QuestStep = Game.CurrentStep
};

View File

@ -2295,7 +2295,7 @@ namespace DiIiS_NA.GameServer.GSSystem.GeneratorsSystem
}
}
if (gizmoLocations.Count > 0 && world.Game.MonsterLevel >= Program.MaxLevel && FastRandom.Instance.Next(100) < 30)
if (gizmoLocations.Count > 0 && world.Game.MonsterLevel >= Program.MAX_LEVEL && FastRandom.Instance.Next(100) < 30)
{
var handleChest = new SNOHandle(96993); //leg chest
if (handleChest == null) continue;

View File

@ -1353,7 +1353,7 @@ namespace DiIiS_NA.GameServer.GSSystem.ItemsSystem
player.Attributes[GameAttributes.Buff_Icon_Count0, powerId] = activated ? 0 : 1;
player.Attributes.BroadcastChangedIfRevealed();
player.Inventory.SendVisualInventory(player);
var dbToon = player.Toon.DBToon;
var dbToon = player.Toon.DbToon;
dbToon.WingsActive = player.CurrentWingsPowerId;
player.World.Game.GameDbSession.SessionUpdate(dbToon);
return;

View File

@ -868,7 +868,7 @@ namespace DiIiS_NA.GameServer.GSSystem.MapSystem
player.GroundItems[item.GlobalID] = item;
DropItem(source, null, item);
if (source.Attributes[GameAttributes.Level] >= Program.MaxLevel)
if (source.Attributes[GameAttributes.Level] >= Program.MAX_LEVEL)
{
item = ItemGenerator.GenerateRandomCraftItem(player, 35);
if (item == null) return;

View File

@ -65,7 +65,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PlayerSystem
// If there is no matching childnode, there must be one with -1 which only combines all class specific into one
private int GetDuration()
{
var node = currentLineNode.ChildNodes.FirstOrDefault(a => a.ClassFilter == player.Toon.VoiceClassID);
var node = currentLineNode.ChildNodes.FirstOrDefault(a => a.ClassFilter == player.Toon.VoiceClassId);
node ??= currentLineNode.ChildNodes.FirstOrDefault(a => a.ClassFilter == -1);
if (node == null)
@ -74,7 +74,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PlayerSystem
}
return node.CompressedDisplayTimes[(int)manager.ClientLanguage]
.Languages[player.Toon.VoiceClassID * 2 + (player.Toon.Gender == 0 ? 0 : 1)];
.Languages[player.Toon.VoiceClassId * 2 + (player.Toon.Gender == 0 ? 0 : 1)];
}
// This returns the dynamicID of other conversation partners. The client uses its position to identify where you can hear the conversation.
@ -573,10 +573,10 @@ namespace DiIiS_NA.GameServer.GSSystem.PlayerSystem
LineID = currentLineNode.LineID,
Speaker = currentLineNode.LineSpeaker,
LineGender = -1,
AudioClass = (GameBalance.Class)player.Toon.VoiceClassID,
AudioClass = (GameBalance.Class)player.Toon.VoiceClassId,
Gender = (player.Toon.Gender == 0) ? VoiceGender.Male : VoiceGender.Female,
TextClass = currentLineNode.LineSpeaker == Speaker.Player
? (GameBalance.Class)player.Toon.VoiceClassID
? (GameBalance.Class)player.Toon.VoiceClassId
: GameBalance.Class.None,
SNOSpeakerActor = (int)GetSpeaker(currentLineNode.LineSpeaker).SNO,
LineFlags = 0x00000000,

View File

@ -1043,7 +1043,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PlayerSystem
item.Owner = _owner;
InventoryGrid targetGrid = (msg.InvLoc.EquipmentSlot == (int)EquipmentSlotId.Stash) ? _stashGrid : _inventoryGrid;
SaveItemToDB(_owner.Toon.GameAccount.DBGameAccount, _owner.Toon.DBToon, EquipmentSlotId.Inventory, item);
SaveItemToDB(_owner.Toon.GameAccount.DBGameAccount, _owner.Toon.DbToon, EquipmentSlotId.Inventory, item);
ChangeItemLocationDB(msg.InvLoc.Column, msg.InvLoc.Row, item);
item.UpdateStackCount(amount);
targetGrid.PlaceItem(item, msg.InvLoc.Row, msg.InvLoc.Column);
@ -2579,7 +2579,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PlayerSystem
if (slotId == 15)
item.DBInventory.DBToon = null;
else
item.DBInventory.DBToon = (_owner as Player).Toon.DBToon;
item.DBInventory.DBToon = (_owner as Player).Toon.DbToon;
item.Owner.World.Game.GameDbSession.SessionUpdate(item.DBInventory);
//Logger.Debug("ChangeItemSlotDB success, item dbid: {0}", item.DBInventory.Id);

View File

@ -223,9 +223,9 @@ public class Player : Actor, IMessageConsumer, IUpdateable
if (value == null)
{
HirelingId = null;
lock (Toon.DBToon)
lock (Toon.DbToon)
{
var dbToon = Toon.DBToon;
var dbToon = Toon.DbToon;
dbToon.ActiveHireling = null;
DBSessions.SessionUpdate(dbToon);
}
@ -233,9 +233,9 @@ public class Player : Actor, IMessageConsumer, IUpdateable
else if (value != _activeHireling)
{
HirelingId = value.Attributes[GameAttributes.Hireling_Class];
lock (Toon.DBToon)
lock (Toon.DbToon)
{
var dbToon = Toon.DBToon;
var dbToon = Toon.DbToon;
dbToon.ActiveHireling = value.Attributes[GameAttributes.Hireling_Class];
DBSessions.SessionUpdate(dbToon);
}
@ -294,10 +294,10 @@ public class Player : Actor, IMessageConsumer, IUpdateable
PlayerGroupIndex = InGameClient.Game.PlayerGroupIndexCounter;
Toon = bnetToon;
LevelingBoosted = Toon.LevelingBoosted;
var dbToon = Toon.DBToon;
var dbToon = Toon.DbToon;
HirelingId = dbToon.ActiveHireling;
GBHandle.Type = (int)ActorType.Player;
GBHandle.GBID = Toon.ClassID;
GBHandle.GBID = Toon.ClassId;
Level = dbToon.Level;
ParagonLevel = Toon.ParagonLevel;
ExperienceNext = Toon.ExperienceNext;
@ -357,7 +357,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
else if (InGameClient.Game.CurrentAct == 3000)
EnableStoneOfRecall();
var lores = UnserializeBytes(Toon.DBToon.Lore);
var lores = UnserializeBytes(Toon.DbToon.Lore);
var num = 0;
foreach (var lore in lores)
{
@ -1448,10 +1448,10 @@ public class Player : Actor, IMessageConsumer, IUpdateable
Attributes[GameAttributes.Casting_Speed] = 1f;
//Basic stats
Attributes[GameAttributes.Level_Cap] = Program.MaxLevel;
Attributes[GameAttributes.Level_Cap] = Program.MAX_LEVEL;
Attributes[GameAttributes.Level] = Level;
Attributes[GameAttributes.Alt_Level] = ParagonLevel;
if (Level == Program.MaxLevel)
if (Level == Program.MAX_LEVEL)
{
Attributes[GameAttributes.Alt_Experience_Next_Lo] = (int)(ExperienceNext % uint.MaxValue);
Attributes[GameAttributes.Alt_Experience_Next_Hi] = (int)(ExperienceNext / uint.MaxValue);
@ -2196,7 +2196,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
// message.Amount have the value send to add on attr of Paragon tabs.
ParagonBonuses[bonus.Category * 4 + bonus.Index - 1] += (ushort)message.Amount;
var dbToon = Toon.DBToon;
var dbToon = Toon.DbToon;
dbToon.ParagonBonuses = ParagonBonuses;
World.Game.GameDbSession.SessionUpdate(dbToon);
@ -2214,7 +2214,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
{
ParagonBonuses = new ushort[]
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
var dbToon = Toon.DBToon;
var dbToon = Toon.DbToon;
dbToon.ParagonBonuses = ParagonBonuses;
World.Game.GameDbSession.SessionUpdate(dbToon);
@ -2902,7 +2902,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
//*/
private void OnEquipPotion(GameClient client, ChangeUsableItemMessage message)
{
var activeSkills = Toon.DBActiveSkills;
var activeSkills = Toon.DbActiveSkills;
activeSkills.PotionGBID = message.Field1;
World.Game.GameDbSession.SessionUpdate(activeSkills);
}
@ -4225,7 +4225,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
serialized += Inventory.GetItemBonus(GameAttributes.Armor_Item).ToString("F0");
serialized += ";";
serialized += totalDamage.ToString("F0");
var dbStats = Toon.DBToon;
var dbStats = Toon.DbToon;
dbStats.Stats = serialized;
World.Game.GameDbSession.SessionUpdate(dbStats);
}
@ -4322,7 +4322,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
else
{
bonusSet.Claimed = true;
bonusSet.ClaimedToon = Toon.DBToon;
bonusSet.ClaimedToon = Toon.DbToon;
}
//BonusSetsList.CollectionEditions[bonusSet.SetId].Claim(this);
@ -4529,8 +4529,8 @@ public class Player : Actor, IMessageConsumer, IUpdateable
foreach (var mail in mailData)
{
var mailRow = D3.Items.Mail.CreateBuilder()
.SetAccountTo(Toon.D3EntityID)
.SetAccountFrom(Toon.D3EntityID)
.SetAccountTo(Toon.D3EntityId)
.SetAccountFrom(Toon.D3EntityId)
.SetMailId(mail.Id)
.SetTitle(mail.Title)
.SetBody(mail.Body);
@ -5983,7 +5983,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable
LearnedLore.Count++; // Count
UpdateHeroState();
Logger.Trace("Learning lore #{0}", loreSNOId);
var dbToon = Toon.DBToon;
var dbToon = Toon.DbToon;
dbToon.Lore = SerializeBytes(LearnedLore.m_snoLoreLearned.Take(LearnedLore.Count).ToList());
World.Game.GameDbSession.SessionUpdate(dbToon);
}

View File

@ -28,7 +28,7 @@ using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Quest;
using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.World;
using DiIiS_NA.GameServer.MessageSystem.Message.Fields;
using DiIiS_NA.D3_GameServer.Core.Types.SNO;
using static DiIiS_NA.Core.MPQ.FileFormats.Monster.MonsterType;
namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
{
public class DeathPayload : Payload
@ -124,7 +124,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
}
if (Target is Minion { Master: Player masterPlr2 }
and (BaseGolem or IceGolem or BoneGolem or DecayGolem or ConsumeFleshGolem or BloodGolem))
and (BaseGolem or IceGolem or BoneGolem or DecayGolem or ConsumeFleshGolem or DiIiS_NA.GameServer.GSSystem.ActorSystem.Implementations.Minions.BloodGolem))
{
masterPlr2.InGameClient.SendMessage(new MessageSystem.Message.Definitions.Pet.PetDetachMessage()
{
@ -445,7 +445,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
{
if (rangedPlayer.Toon.Class == ToonClass.DemonHunter)
{
if (monster.MonsterType == (int)DiIiS_NA.Core.MPQ.FileFormats.Monster.MonsterType.Demon)
if (monster.MonsterTypeValue == (int)DiIiS_NA.Core.MPQ.FileFormats.Monster.MonsterType.Demon)
rangedPlayer.AddAchievementCounter(74987243307065, 1);
if (PowerMath.Distance2D(rangedPlayer.Position, monster.Position) >= 45f)
@ -1224,7 +1224,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
if (player.World.Game.IsHardcore)
{
player.AddTimedAction(3f, (_) => player.Revive(player.CheckPointPosition));
var toon = player.Toon.DBToon;
var toon = player.Toon.DbToon;
toon.Deaths++;
player.World.Game.GameDbSession.SessionUpdate(toon);
}

View File

@ -376,7 +376,7 @@ namespace DiIiS_NA.GameServer.GSSystem.PowerSystem.Payloads
if (Target is Monster monster)
{
TotalDamage *= 1 + plr.Attributes[GameAttributes.Damage_Percent_Bonus_Vs_Monster_Type, monster.MonsterType];
TotalDamage *= 1 + plr.Attributes[GameAttributes.Damage_Percent_Bonus_Vs_Monster_Type, monster.MonsterTypeValue];
if (monster.Quality > 0)
TotalDamage *= 1 + plr.Attributes[GameAttributes.Damage_Percent_Bonus_Vs_Elites];

View File

@ -26,7 +26,7 @@ namespace DiIiS_NA.GameServer.GSSystem.SkillsSystem
ToonClass = toonClass;
Player = player;
// var dbToon = player.Toon.DBToon;
var dbActiveSkills = player.Toon.DBActiveSkills;
var dbActiveSkills = player.Toon.DbActiveSkills;
ActiveSkills = new ActiveSkillSavedData[6]
{
new()
@ -82,7 +82,7 @@ namespace DiIiS_NA.GameServer.GSSystem.SkillsSystem
public void UpdateSkills(int hotBarIndex, int SNOSkill, int SNORune, Toon toon)
{
Logger.MethodTrace(string.Format("Update index {0} skill {1} rune {2}", hotBarIndex, SNOSkill, SNORune));
var dbActiveSkills = Player.Toon.DBActiveSkills;
var dbActiveSkills = Player.Toon.DbActiveSkills;
switch (hotBarIndex)
{
case 0:
@ -127,7 +127,7 @@ namespace DiIiS_NA.GameServer.GSSystem.SkillsSystem
public void UpdatePassiveSkills(Toon toon)
{
Logger.Debug("Update passive to {0} {1} {2} {3}", PassiveSkills[0], PassiveSkills[1], PassiveSkills[2], PassiveSkills[3]);
var dbActiveSkills = Player.Toon.DBActiveSkills;
var dbActiveSkills = Player.Toon.DbActiveSkills;
dbActiveSkills.Passive0 = PassiveSkills[0];
dbActiveSkills.Passive1 = PassiveSkills[1];
dbActiveSkills.Passive2 = PassiveSkills[2];

View File

@ -56,12 +56,18 @@ public class MonsterConfig
public float AttacksPerSecond { get; set; } = 1.2f;
public float HealthMultiplier { get; set; } = 1;
public float HealthBonusMultiplier { get; set; } = 1;
public float DamageMultiplier { get; set; } = 1;
/// <summary>
/// Attack target range
/// </summary>
public float LookupRange { get; set; } = 50f;
public float LookupRange { get; set; } = 80f;
/// <summary>
/// Total health bonus multiplier that can be applied to a monster
/// </summary>
public float HealthBonusMultiplierCap { get; set; } = 1.025f;
}
public class QuestConfig

View File

@ -48,12 +48,12 @@ namespace DiIiS_NA
}
class Program
{
private static readonly Logger Logger = LogManager.CreateLogger("BZ.Net");
private static readonly Logger Logger = LogManager.CreateLogger("Blizzless");
public static readonly DateTime StartupTime = DateTime.Now;
public static BattleBackend BattleBackend { get; set; }
public bool GameServersAvailable = true;
public const int MaxLevel = 70;
public const int MAX_LEVEL = 70;
public static GameServer.ClientSystem.GameServer GameServer;
public static Watchdog Watchdog;
@ -66,10 +66,10 @@ namespace DiIiS_NA
public static string RestServerIp = RestConfig.Instance.IP;
public static string PublicGameServerIp = DiIiS_NA.GameServer.NATConfig.Instance.PublicIP;
public const int Build = 30;
public const int Stage = 3;
public const int BUILD = 30;
public const int STAGE = 3;
public static TypeBuildEnum TypeBuild => TypeBuildEnum.Beta;
private static bool DiabloCoreEnabled = DiIiS_NA.GameServer.GameServerConfig.Instance.CoreActive;
private static bool _diabloCoreEnabled = DiIiS_NA.GameServer.GameServerConfig.Instance.CoreActive;
private static readonly CancellationTokenSource CancellationTokenSource = new();
public static readonly CancellationToken Token = CancellationTokenSource.Token;
@ -84,8 +84,8 @@ namespace DiIiS_NA
void RightTextRule(string text, string ruleStyle) => AnsiConsole.Write(new Rule(text).RuleStyle(ruleStyle));
string Url(string url) => $"[link={url}]{url}[/]";
RightTextRule("[dodgerblue1]Blizz[/][deepskyblue2]less[/]", "steelblue1");
RightTextRule($"[dodgerblue3]Build [/][deepskyblue3]{Build}[/]", "steelblue1_1");
RightTextRule($"[dodgerblue3]Stage [/][deepskyblue3]{Stage}[/]", "steelblue1_1");
RightTextRule($"[dodgerblue3]Build [/][deepskyblue3]{BUILD}[/]", "steelblue1_1");
RightTextRule($"[dodgerblue3]Stage [/][deepskyblue3]{STAGE}[/]", "steelblue1_1");
RightTextRule($"[deepskyblue3]{TypeBuild}[/]", "steelblue1_1");
RightTextRule($"Diablo III [red]RoS 2.7.4.84161[/] - {Url("https://github.com/blizzless/blizzless-diiis")}",
"red");
@ -100,14 +100,14 @@ namespace DiIiS_NA
DbProviderFactories.RegisterFactory("Npgsql", NpgsqlFactory.Instance);
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
string name = $"Blizzless: Build {Build}, Stage: {Stage} - {TypeBuild}";
string name = $"Blizzless: Build {BUILD}, Stage: {STAGE} - {TypeBuild}";
SetTitle(name);
if (LogConfig.Instance.Targets.Any(x => x.MaximizeWhenEnabled && x.Enabled))
Maximize();
WriteBanner();
InitLoggers();
#if DEBUG
DiabloCoreEnabled = true;
_diabloCoreEnabled = true;
Logger.Info("Forcing Diablo III Core to be $[green]$enabled$[/]$ on debug mode.");
#else
if (!DiabloCoreEnabled)
@ -208,7 +208,7 @@ namespace DiIiS_NA
GuildManager.PreLoadGuilds();
Logger.Info("Loading Diablo III - Core...");
if (DiabloCoreEnabled)
if (_diabloCoreEnabled)
{
if (!MPQStorage.Initialized)
{
@ -241,7 +241,7 @@ namespace DiIiS_NA
BattleBackend = new BattleBackend(loginConfig.BindIP, loginConfig.WebPort);
//Diablo 3 Game-Server
if (DiabloCoreEnabled)
if (_diabloCoreEnabled)
StartGameServer();
else Logger.Fatal("Game server is disabled in the configs.");
@ -385,28 +385,17 @@ namespace DiIiS_NA
if (!targetConfig.Enabled)
continue;
LogTarget target = null;
switch (targetConfig.Target.ToLower())
LogTarget target = targetConfig.Target.ToLower() switch
{
case "ansi":
target = new AnsiTarget(
targetConfig.MinimumLevel,
targetConfig.MaximumLevel,
targetConfig.IncludeTimeStamps,
targetConfig.TimeStampFormat);
break;
case "console":
target = new ConsoleTarget(targetConfig.MinimumLevel, targetConfig.MaximumLevel,
targetConfig.IncludeTimeStamps,
targetConfig.TimeStampFormat);
break;
case "file":
target = new FileTarget(targetConfig.FileName, targetConfig.MinimumLevel,
targetConfig.MaximumLevel, targetConfig.IncludeTimeStamps,
targetConfig.TimeStampFormat,
targetConfig.ResetOnStartup);
break;
}
"ansi" => new AnsiTarget(targetConfig.MinimumLevel, targetConfig.MaximumLevel,
targetConfig.IncludeTimeStamps, targetConfig.TimeStampFormat),
"console" => new ConsoleTarget(targetConfig.MinimumLevel, targetConfig.MaximumLevel,
targetConfig.IncludeTimeStamps, targetConfig.TimeStampFormat),
"file" => new FileTarget(targetConfig.FileName, targetConfig.MinimumLevel,
targetConfig.MaximumLevel, targetConfig.IncludeTimeStamps, targetConfig.TimeStampFormat,
targetConfig.ResetOnStartup),
_ => null
};
if (target != null)
LogManager.AttachLogTarget(target);
@ -464,7 +453,6 @@ namespace DiIiS_NA
const int RESTORE = 9;
private static void Maximize()
{
// if it's running on windows
try
{
if (Environment.OSVersion.Platform == PlatformID.Win32NT)

View File

@ -136,9 +136,7 @@ namespace DiIiS_NA.REST.Extensions
public static void Swap<T>(ref T left, ref T right)
{
T temp = left;
left = right;
right = temp;
(left, right) = (right, left);
}
#region Strings

View File

@ -88,7 +88,7 @@ namespace DiIiS_NA.REST
void HandleInfoRequest(HttpHeader request)
{
SendResponseHtml(HttpCode.OK, "Welcome to BlizzLess.Net" +
"\nBuild " + Program.Build +
"\nBuild " + Program.BUILD +
"\nSupport: 2.7.4");
}

View File

@ -13,7 +13,7 @@ Enabled = true
; IP address on which the server will be bound
BindIP = 127.0.0.1
; Port for web interactions
WebPort = 9800
WebPort = 83
; Port for the server
Port = 1119
@ -37,7 +37,7 @@ MotdRemoteUrl = https://your-site.local/yourmotd
[REST]
IP = 127.0.0.1
PublicIP = 127.0.0.1
PORT = 80
PORT = 83
Public = true
; Game Server Settings
@ -49,7 +49,7 @@ CoreActive = true
; IP address on which the game server will be bound
BindIP = 127.0.0.1
; Port for web interactions
WebPort = 9001
WebPort = 83
; Port for game server connections
Port = 1345
; IP address for IPv6 bindings