add frida script, basic raid stuff

This commit is contained in:
raphaeIl 2024-05-21 22:25:30 +08:00
parent 7ad2f87d6b
commit b493b49ee1
9 changed files with 927 additions and 91 deletions

View File

@ -1 +1,4 @@
# SCHALE.GameServer
# SCHALE.GameServer
## Connecting
- Run the game with this [frida script](https://gist.githubusercontent.com/raphaeIl/c4ca030411186c9417da22d8d7864c4d/raw/00b69c5bacdf79c24972411bd80d785eed3841ce/ba.js)

View File

@ -68,7 +68,8 @@ namespace SCHALE.Common.Database
.WithOne(x => x.Account)
.HasForeignKey(x => x.AccountServerId)
.IsRequired();
modelBuilder.Entity<AccountDB>(x => x.Property(b => b.RaidInfo).HasJsonConversion());
modelBuilder.Entity<ItemDB>().Property(x => x.ServerId).ValueGeneratedOnAdd();
modelBuilder.Entity<EquipmentDB>().Property(x => x.ServerId).ValueGeneratedOnAdd();
modelBuilder.Entity<WeaponDB>().Property(x => x.ServerId).ValueGeneratedOnAdd();

View File

@ -13,13 +13,130 @@ namespace SCHALE.Common.Database
}
// Battle? probably need to implement these our selves
public class BattleSummary
public struct RaidBossResult : IEquatable<RaidBossResult>
{
[JsonIgnore]
public int Index { get; set; }
[JsonIgnore]
public long GivenDamage { get; set; }
[JsonIgnore]
public long GivenGroggyPoint { get; set; }
//public RaidDamage RaidDamage { get; set; }
public long EndHpRateRawValue { readonly get; set; }
public long GroggyRateRawValue { readonly get; set; }
public int GroggyCount { readonly get; set; }
public List<long> SubPartsHPs { readonly get; set; }
public long AIPhase { readonly get; set; }
public bool Equals(RaidBossResult other)
{
return this.Index == other.Index;
}
}
public class RaidBossResultCollection : KeyedCollection<int, RaidBossResult>
{
[JsonIgnore]
public int LastIndex { get; set; }
[JsonIgnore]
public long TotalDamage { get; set; }
[JsonIgnore]
public long CurrentDamage { get; set; }
[JsonIgnore]
public long TotalGroggyPoint { get; set; }
[JsonIgnore]
public long CurrentGroggyPoint { get; set; }
[JsonIgnore]
public int TotalGroggyCount { get; set; }
protected override int GetKeyForItem(RaidBossResult item)
{
return item.Index;
}
}
public class RaidSummary
{
public long RaidSeasonId { get; set; }
public long GivenDamage { get; set; }
public int TotalGroggyCount { get; set; }
public int RaidBossIndex { get; set; }
public RaidBossResultCollection RaidBossResults { get; set; }
}
// Battle? probably need to implement these our selves
public class BattleSummary : IEquatable<BattleSummary>
{
public long HashKey { get; set; }
public bool IsBossBattle { get; set; }
//public BattleTypes BattleType { get; set; }
public long StageId { get; set; }
public long GroundId { get; set; }
//public GroupTag Winner { get; set; }
[JsonIgnore]
public bool IsPlayerWin { get; set; }
//public BattleEndType EndType { get; set; }
public int EndFrame { get; set; }
//public GroupSummary Group01Summary { get; set; }
//public GroupSummary Group02Summary { get; set; }
//public WeekDungeonSummary WeekDungeonSummary { get; set; }
public RaidSummary RaidSummary { get; set; }
//public ArenaSummary ArenaSummary { get; set; }
[JsonIgnore]
public TimeSpan EndTime { get; set; }
public int ContinueCount { get; set; }
public float ElapsedRealtime { get; set; }
[JsonIgnore]
public string FindGiftClearText { get; set; }
[JsonIgnore]
public long EventContentId { get; set; }
[JsonIgnore]
public long FixedEchelonId { get; set; }
public bool IsAbort { get; set; }
public bool Equals(BattleSummary? other)
{
return this.HashKey == other.HashKey;
}
}
// probably just a simple json wrapper
public class TypedJsonWrapper
{
@ -189,6 +306,19 @@ namespace SCHALE.Common.Database
public Dictionary<CurrencyTypes, DateTime> UpdateTimeDict { get; set; }
}
public class RaidInfo // custom class for all raid stuff needed
{
public long SeasonId { get; set; }
public long CurrentRaidUniqueId { get; set; }
public Difficulty CurrentDifficulty { get; set; }
public long BestRankingPoint { get; set; }
public long TotalRankingPoint { get; set; }
}
public class AccountDB
{
[JsonIgnore]
@ -212,9 +342,8 @@ namespace SCHALE.Common.Database
[JsonIgnore]
public virtual ICollection<GearDB> Gears { get; }
[JsonIgnore]
public long RaidSeasonId { get; set; } // idk where to store this
public virtual RaidInfo RaidInfo { get; set; }
public AccountDB() { }
@ -225,6 +354,12 @@ namespace SCHALE.Common.Database
Level = 1;
LastConnectTime = DateTime.Now;
CreateDate = DateTime.Now;
RaidInfo = new()
{
SeasonId = 1, // default
BestRankingPoint = 0,
TotalRankingPoint = 0,
};
}
[Key]

View File

@ -0,0 +1,522 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using SCHALE.Common.Database;
#nullable disable
namespace SCHALE.Common.Migrations
{
[DbContext(typeof(SCHALEContext))]
[Migration("20240519215605_AccountDB_RaidInfo")]
partial class AccountDB_RaidInfo
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.2")
.HasAnnotation("Proxies:ChangeTracking", false)
.HasAnnotation("Proxies:CheckEquality", false)
.HasAnnotation("Proxies:LazyLoading", true)
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("SCHALE.Common.Database.AccountDB", b =>
{
b.Property<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<DateTime?>("BirthDay")
.HasColumnType("datetime2");
b.Property<string>("CallName")
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("CallNameUpdateTime")
.HasColumnType("datetime2");
b.Property<string>("Comment")
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("CreateDate")
.HasColumnType("datetime2");
b.Property<string>("DevId")
.HasColumnType("nvarchar(max)");
b.Property<long>("Exp")
.HasColumnType("bigint");
b.Property<DateTime>("LastConnectTime")
.HasColumnType("datetime2");
b.Property<int>("Level")
.HasColumnType("int");
b.Property<DateTime?>("LinkRewardDate")
.HasColumnType("datetime2");
b.Property<int>("LobbyMode")
.HasColumnType("int");
b.Property<long>("MemoryLobbyUniqueId")
.HasColumnType("bigint");
b.Property<string>("Nickname")
.HasColumnType("nvarchar(max)");
b.Property<long>("PublisherAccountId")
.HasColumnType("bigint");
b.Property<string>("RaidInfo")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("RepresentCharacterServerId")
.HasColumnType("int");
b.Property<int?>("RetentionDays")
.HasColumnType("int");
b.Property<int>("State")
.HasColumnType("int");
b.Property<int?>("UnReadMailCount")
.HasColumnType("int");
b.Property<int?>("VIPLevel")
.HasColumnType("int");
b.HasKey("ServerId");
b.ToTable("Accounts");
});
modelBuilder.Entity("SCHALE.Common.Database.CharacterDB", b =>
{
b.Property<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<string>("EquipmentServerIds")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("EquipmentSlotAndDBIds")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("ExSkillLevel")
.HasColumnType("int");
b.Property<long>("Exp")
.HasColumnType("bigint");
b.Property<int>("ExtraPassiveSkillLevel")
.HasColumnType("int");
b.Property<long>("FavorExp")
.HasColumnType("bigint");
b.Property<int>("FavorRank")
.HasColumnType("int");
b.Property<bool>("IsFavorite")
.HasColumnType("bit");
b.Property<bool>("IsLocked")
.HasColumnType("bit");
b.Property<int>("LeaderSkillLevel")
.HasColumnType("int");
b.Property<int>("Level")
.HasColumnType("int");
b.Property<int>("PassiveSkillLevel")
.HasColumnType("int");
b.Property<string>("PotentialStats")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("PublicSkillLevel")
.HasColumnType("int");
b.Property<int>("StarGrade")
.HasColumnType("int");
b.Property<long>("UniqueId")
.HasColumnType("bigint");
b.HasKey("ServerId");
b.HasIndex("AccountServerId");
b.ToTable("Characters");
});
modelBuilder.Entity("SCHALE.Common.Database.EchelonDB", b =>
{
b.Property<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<long>("EchelonNumber")
.HasColumnType("bigint");
b.Property<int>("EchelonType")
.HasColumnType("int");
b.Property<int>("ExtensionType")
.HasColumnType("int");
b.Property<long>("LeaderServerId")
.HasColumnType("bigint");
b.Property<string>("MainSlotServerIds")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("SkillCardMulliganCharacterIds")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("SupportSlotServerIds")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<long>("TSSInteractionServerId")
.HasColumnType("bigint");
b.Property<int>("UsingFlag")
.HasColumnType("int");
b.HasKey("ServerId");
b.HasIndex("AccountServerId");
b.ToTable("Echelons");
});
modelBuilder.Entity("SCHALE.Common.Database.EquipmentDB", b =>
{
b.Property<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<long>("BoundCharacterServerId")
.HasColumnType("bigint");
b.Property<long>("Exp")
.HasColumnType("bigint");
b.Property<bool>("IsLocked")
.HasColumnType("bit");
b.Property<int>("Level")
.HasColumnType("int");
b.Property<long>("StackCount")
.HasColumnType("bigint");
b.Property<int>("Tier")
.HasColumnType("int");
b.Property<long>("UniqueId")
.HasColumnType("bigint");
b.HasKey("ServerId");
b.HasIndex("AccountServerId");
b.ToTable("Equipment");
});
modelBuilder.Entity("SCHALE.Common.Database.GearDB", b =>
{
b.Property<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<long>("BoundCharacterServerId")
.HasColumnType("bigint");
b.Property<long>("Exp")
.HasColumnType("bigint");
b.Property<int>("Level")
.HasColumnType("int");
b.Property<long>("SlotIndex")
.HasColumnType("bigint");
b.Property<int>("Tier")
.HasColumnType("int");
b.Property<long>("UniqueId")
.HasColumnType("bigint");
b.HasKey("ServerId");
b.HasIndex("AccountServerId");
b.ToTable("Gears");
});
modelBuilder.Entity("SCHALE.Common.Database.ItemDB", b =>
{
b.Property<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<bool>("IsLocked")
.HasColumnType("bit");
b.Property<long>("StackCount")
.HasColumnType("bigint");
b.Property<long>("UniqueId")
.HasColumnType("bigint");
b.HasKey("ServerId");
b.HasIndex("AccountServerId");
b.ToTable("Items");
});
modelBuilder.Entity("SCHALE.Common.Database.MissionProgressDB", b =>
{
b.Property<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<bool>("Complete")
.HasColumnType("bit");
b.Property<long>("MissionUniqueId")
.HasColumnType("bigint");
b.Property<string>("ProgressParameters")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("StartTime")
.HasColumnType("datetime2");
b.HasKey("ServerId");
b.HasIndex("AccountServerId");
b.ToTable("MissionProgresses");
});
modelBuilder.Entity("SCHALE.Common.Database.Models.AccountTutorial", b =>
{
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<string>("TutorialIds")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("AccountServerId");
b.ToTable("AccountTutorials");
});
modelBuilder.Entity("SCHALE.Common.Database.Models.GuestAccount", b =>
{
b.Property<long>("Uid")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Uid"));
b.Property<string>("DeviceId")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Token")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Uid");
b.ToTable("GuestAccounts");
});
modelBuilder.Entity("SCHALE.Common.Database.WeaponDB", b =>
{
b.Property<long>("ServerId")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("ServerId"));
b.Property<long>("AccountServerId")
.HasColumnType("bigint");
b.Property<long>("BoundCharacterServerId")
.HasColumnType("bigint");
b.Property<long>("Exp")
.HasColumnType("bigint");
b.Property<bool>("IsLocked")
.HasColumnType("bit");
b.Property<int>("Level")
.HasColumnType("int");
b.Property<int>("StarGrade")
.HasColumnType("int");
b.Property<long>("UniqueId")
.HasColumnType("bigint");
b.HasKey("ServerId");
b.HasIndex("AccountServerId");
b.ToTable("Weapons");
});
modelBuilder.Entity("SCHALE.Common.Database.CharacterDB", b =>
{
b.HasOne("SCHALE.Common.Database.AccountDB", "Account")
.WithMany("Characters")
.HasForeignKey("AccountServerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Account");
});
modelBuilder.Entity("SCHALE.Common.Database.EchelonDB", b =>
{
b.HasOne("SCHALE.Common.Database.AccountDB", "Account")
.WithMany("Echelons")
.HasForeignKey("AccountServerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Account");
});
modelBuilder.Entity("SCHALE.Common.Database.EquipmentDB", b =>
{
b.HasOne("SCHALE.Common.Database.AccountDB", "Account")
.WithMany("Equipment")
.HasForeignKey("AccountServerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Account");
});
modelBuilder.Entity("SCHALE.Common.Database.GearDB", b =>
{
b.HasOne("SCHALE.Common.Database.AccountDB", "Account")
.WithMany("Gears")
.HasForeignKey("AccountServerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Account");
});
modelBuilder.Entity("SCHALE.Common.Database.ItemDB", b =>
{
b.HasOne("SCHALE.Common.Database.AccountDB", "Account")
.WithMany("Items")
.HasForeignKey("AccountServerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Account");
});
modelBuilder.Entity("SCHALE.Common.Database.MissionProgressDB", b =>
{
b.HasOne("SCHALE.Common.Database.AccountDB", "Account")
.WithMany("MissionProgresses")
.HasForeignKey("AccountServerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Account");
});
modelBuilder.Entity("SCHALE.Common.Database.WeaponDB", b =>
{
b.HasOne("SCHALE.Common.Database.AccountDB", "Account")
.WithMany("Weapons")
.HasForeignKey("AccountServerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Account");
});
modelBuilder.Entity("SCHALE.Common.Database.AccountDB", b =>
{
b.Navigation("Characters");
b.Navigation("Echelons");
b.Navigation("Equipment");
b.Navigation("Gears");
b.Navigation("Items");
b.Navigation("MissionProgresses");
b.Navigation("Weapons");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,40 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace SCHALE.Common.Migrations
{
/// <inheritdoc />
public partial class AccountDB_RaidInfo : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "RaidSeasonId",
table: "Accounts");
migrationBuilder.AddColumn<string>(
name: "RaidInfo",
table: "Accounts",
type: "nvarchar(max)",
nullable: false,
defaultValue: "");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "RaidInfo",
table: "Accounts");
migrationBuilder.AddColumn<long>(
name: "RaidSeasonId",
table: "Accounts",
type: "bigint",
nullable: false,
defaultValue: 0L);
}
}
}

View File

@ -75,8 +75,9 @@ namespace SCHALE.Common.Migrations
b.Property<long>("PublisherAccountId")
.HasColumnType("bigint");
b.Property<long>("RaidSeasonId")
.HasColumnType("bigint");
b.Property<string>("RaidInfo")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("RepresentCharacterServerId")
.HasColumnType("int");

View File

@ -20,7 +20,7 @@ namespace SCHALE.GameServer.Commands
public override void Execute()
{
PropertyInfo? targetProperty = typeof(AccountDB).GetProperty(Property) ?? typeof(AccountDB).GetProperty(Property.Capitalize());
if (targetProperty != null)
{
TypeConverter converter = TypeDescriptor.GetConverter(targetProperty.PropertyType);
@ -39,9 +39,30 @@ namespace SCHALE.GameServer.Commands
{
throw new ArgumentException("Invalid Value");
}
}
}
}
else if (Property.Equals("raidseasonid", StringComparison.CurrentCultureIgnoreCase)) // temp raid stuff
{
if (long.TryParse(Value, out long seasonId))
{
connection.Account.RaidInfo = new RaidInfo()
{
SeasonId = seasonId,
BestRankingPoint = 0,
TotalRankingPoint = 0,
};
connection.SendChatMessage($"Set Raid SeasonId to: {seasonId}");
connection.Context.SaveChanges();
}
else
{
throw new ArgumentException("Invalid Value");
}
}
else
{
throw new ArgumentException("Invalid Player Property!");

View File

@ -1,6 +1,7 @@
using SCHALE.Common.Database;
using SCHALE.Common.FlatData;
using SCHALE.Common.NetworkProtocol;
using SCHALE.GameServer.Managers;
using SCHALE.GameServer.Services;
namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
@ -23,24 +24,87 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
{
var account = sessionKeyService.GetAccount(req.SessionKey);
var raidSeasonInfo = excelTableService.GetTable<RaidSeasonManageExcelTable>().UnPack().DataList;
var targetSeason = raidSeasonInfo.FirstOrDefault(x => x.SeasonId == account.RaidSeasonId);
var raidSeasonExcel = excelTableService.GetTable<RaidSeasonManageExcelTable>().UnPack().DataList;
var targetSeason = raidSeasonExcel.FirstOrDefault(x => x.SeasonId == account.RaidInfo.SeasonId);
return new RaidLobbyResponse()
{
SeasonType = RaidSeasonType.Open,
RaidLobbyInfoDB = new()
{
SeasonId = account.RaidSeasonId,
Tier = 2,
Ranking = 1,
BestRankingPoint = 1_000_000,
TotalRankingPoint = 10_000_000,
ReceiveRewardIds = targetSeason.SeasonRewardId,
PlayableHighestDifficulty = new() {
{ targetSeason.OpenRaidBossGroup.FirstOrDefault(), Difficulty.Torment }
}
}
RaidLobbyInfoDB = RaidManager.Instance.GetLobby(account.RaidInfo, targetSeason),
};
}
[ProtocolHandler(Protocol.Raid_CreateBattle)]
public ResponsePacket CreateBattleHandler(RaidCreateBattleRequest req)
{
var account = sessionKeyService.GetAccount(req.SessionKey);
account.RaidInfo.CurrentRaidUniqueId = req.RaidUniqueId;
account.RaidInfo.CurrentDifficulty = req.Difficulty;
context.Entry(account).Property(x => x.RaidInfo).IsModified = true; // force update
context.SaveChanges();
var raid = RaidManager.Instance.CreateRaid(account.RaidInfo, account.ServerId, account.Nickname, req.IsPractice, req.RaidUniqueId);
var battle = RaidManager.Instance.CreateBattle(account.ServerId, account.Nickname, req.RaidUniqueId);
return new RaidCreateBattleResponse()
{
RaidDB = raid,
RaidBattleDB = battle,
AssistCharacterDB = new () { }
};
}
[ProtocolHandler(Protocol.Raid_EnterBattle)] // clicked restart
public ResponsePacket EnterBattleHandler(RaidEnterBattleRequest req)
{
var raid = RaidManager.Instance.RaidDB;
var battle = RaidManager.Instance.RaidBattleDB;
return new RaidEnterBattleResponse()
{
RaidDB = raid,
RaidBattleDB = battle,
AssistCharacterDB = new() { }
};
}
[ProtocolHandler(Protocol.Raid_EndBattle)]
public ResponsePacket EndBattleHandler(RaidEndBattleRequest req)
{
var account = sessionKeyService.GetAccount(req.SessionKey);
var raidStageTable = excelTableService.GetTable<RaidStageExcelTable>().UnPack().DataList;
var currentRaidData = raidStageTable.FirstOrDefault(x => x.Id == account.RaidInfo.CurrentRaidUniqueId);
var timeScore = RaidManager.CalculateTimeScore(req.Summary.ElapsedRealtime, account.RaidInfo.CurrentDifficulty);
var hpPercentScorePoint = currentRaidData.HPPercentScore;
var defaultClearPoint = currentRaidData.DefaultClearScore;
var rankingPoint = timeScore + hpPercentScorePoint + defaultClearPoint;
account.RaidInfo.BestRankingPoint = rankingPoint > account.RaidInfo.BestRankingPoint ? rankingPoint : account.RaidInfo.BestRankingPoint;
account.RaidInfo.TotalRankingPoint += rankingPoint;
context.Entry(account).Property(x => x.RaidInfo).IsModified = true; // force update
context.SaveChanges();
// saving battle result to continue on next attempt doesn't work
var battle = RaidManager.Instance.RaidBattleDB;
var bossResult = req.Summary.RaidSummary.RaidBossResults.FirstOrDefault();
battle.CurrentBossHP = bossResult.EndHpRateRawValue;
battle.CurrentBossGroggy = bossResult.GroggyRateRawValue;
battle.CurrentBossAIPhase = bossResult.AIPhase;
battle.SubPartsHPs = bossResult.SubPartsHPs;
return new RaidEndBattleResponse()
{
RankingPoint = rankingPoint,
BestRankingPoint = account.RaidInfo.BestRankingPoint,
ClearTimePoint = timeScore,
HPPercentScorePoint = hpPercentScorePoint,
DefaultClearPoint = defaultClearPoint
};
}
@ -52,71 +116,5 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
OpponentUserDBs = []
};
}
[ProtocolHandler(Protocol.Raid_CreateBattle)]
public ResponsePacket CreateBattleHandller(RaidCreateBattleRequest req)
{
var account = sessionKeyService.GetAccount(req.SessionKey);
var raidStageTable = excelTableService.GetTable<RaidStageExcelTable>().UnPack().DataList;
var currentRaid = raidStageTable.FirstOrDefault(x => x.Id == req.RaidUniqueId);
return new RaidCreateBattleResponse()
{
RaidDB = new()
{
Owner = new()
{
AccountId = account.ServerId,
AccountName = account.Nickname,
},
ContentType = ContentType.Raid,
UniqueId = req.RaidUniqueId,
SeasonId = account.RaidSeasonId,
PlayerCount = 1,
RaidState = RaidStatus.Playing,
IsPractice = req.IsPractice,
RaidBossDBs = [
new() {
ContentType = ContentType.Raid,
BossCurrentHP = long.MaxValue
}
],
AccountLevelWhenCreateDB = account.Level,
},
RaidBattleDB = new()
{
ContentType = ContentType.Raid,
RaidUniqueId = req.RaidUniqueId,
CurrentBossHP = long.MaxValue,
RaidMembers = [
new() {
AccountId = account.ServerId,
AccountName = account.Nickname,
}
]
},
AssistCharacterDB = new () { }
};
}
[ProtocolHandler(Protocol.Raid_EnterBattle)] // clicked restart
public ResponsePacket EnterBattleHandler(RaidEnterBattleRequest req)
{
return new RaidEnterBattleResponse()
{
};
}
[ProtocolHandler(Protocol.Raid_EndBattle)]
public ResponsePacket EndBattleHandler(RaidEndBattleRequest req)
{
return new RaidEndBattleResponse()
{
};
}
}
}

View File

@ -0,0 +1,115 @@
using SCHALE.Common.Database;
using SCHALE.Common.FlatData;
using SCHALE.Common.NetworkProtocol;
using SCHALE.GameServer.Controllers.Api.ProtocolHandlers;
using SCHALE.GameServer.Utils;
namespace SCHALE.GameServer.Managers
{
public class RaidManager : Singleton<RaidManager>
{
public SingleRaidLobbyInfoDB RaidLobbyInfoDB { get; private set; }
public RaidDB RaidDB { get; private set; }
public RaidBattleDB RaidBattleDB { get; private set; }
public SingleRaidLobbyInfoDB GetLobby(RaidInfo raidInfo, RaidSeasonManageExcelT targetSeasonData)
{
if (RaidLobbyInfoDB == null || RaidLobbyInfoDB.SeasonId != raidInfo.SeasonId)
{
RaidLobbyInfoDB = new SingleRaidLobbyInfoDB()
{
Tier = 0,
Ranking = 1,
SeasonId = raidInfo.SeasonId,
BestRankingPoint = 0,
TotalRankingPoint = 0,
ReceiveRewardIds = targetSeasonData.SeasonRewardId,
PlayableHighestDifficulty = new()
{
{ targetSeasonData.OpenRaidBossGroup.FirstOrDefault(), Difficulty.Torment }
}
};
}
else
{
RaidLobbyInfoDB.BestRankingPoint = raidInfo.BestRankingPoint;
RaidLobbyInfoDB.TotalRankingPoint = raidInfo.TotalRankingPoint;
}
return RaidLobbyInfoDB;
}
public RaidDB CreateRaid(RaidInfo raidInfo, long ownerId, string ownerNickname, bool isPractice, long raidId)
{
if (RaidDB == null)
{
RaidDB = new()
{
Owner = new()
{
AccountId = ownerId,
AccountName = ownerNickname,
},
ContentType = ContentType.Raid,
UniqueId = raidId,
SeasonId = raidInfo.SeasonId,
RaidState = RaidStatus.Playing,
IsPractice = isPractice,
BossDifficulty = raidInfo.CurrentDifficulty,
RaidBossDBs = [
new() {
ContentType = ContentType.Raid,
BossCurrentHP = long.MaxValue
}
],
};
}
else
{
RaidDB.BossDifficulty = raidInfo.CurrentDifficulty;
RaidDB.UniqueId = raidId;
RaidDB.IsPractice = isPractice;
}
return RaidDB;
}
public RaidBattleDB CreateBattle(long ownerId, string ownerNickname, long raidId)
{
if (RaidBattleDB == null)
{
RaidBattleDB = new()
{
ContentType = ContentType.Raid,
RaidUniqueId = raidId,
CurrentBossHP = long.MaxValue,
RaidMembers = [
new() {
AccountId = ownerId,
AccountName = ownerNickname,
}
]
};
}
else
{
RaidBattleDB.RaidUniqueId = raidId;
}
return RaidBattleDB;
}
public static long CalculateTimeScore(float duration, Difficulty difficulty)
{
int[] multipliers = [120, 240, 480, 960, 1440, 1920, 2400]; // from wiki
return (long)((3600f - duration) * multipliers[(int)difficulty]);
}
}
}