Sealed orange chests in BBM can drop BBM jewelry, configurable in JSON, also add isPaidReset to database for tracking

This commit is contained in:
Jun 2026-06-21 14:44:48 -07:00 committed by Paul Campbell
parent 5cbcbff0a0
commit 60851f63c7
14 changed files with 60 additions and 11 deletions

View file

@ -13,7 +13,7 @@ public static class DdonDatabaseBuilder
{
private const string DefaultSchemaFile = "Script/schema_sqlite.sql";
public const uint Version = 63;
public const uint Version = 64;
private static readonly ILogger Logger = LogProvider.Logger<Logger>(typeof(DdonDatabaseBuilder));
public static IDatabase Build(DatabaseSetting settings)

View file

@ -0,0 +1 @@
ALTER TABLE "ddon_bbm_progress" ADD COLUMN "is_paid_reset" BOOLEAN NOT NULL DEFAULT 0;

View file

@ -447,7 +447,8 @@ public interface IDatabase
BattleContentMode contentMode,
uint tier,
bool killedDeath,
ulong lastTicketTime
ulong lastTicketTime,
bool isPaidReset
);
bool UpdateBBMProgress(uint characterId, BitterblackMazeProgress progress, DbConnection? connectionIn = null);

View file

@ -8,7 +8,7 @@ public partial class DdonSqlDb : SqlDb
{
protected static readonly string[] BitterBlackMazeProgressFields =
[
"character_id", "start_time", "content_id", "content_mode", "tier", "killed_death", "last_ticket_time"
"character_id", "start_time", "content_id", "content_mode", "tier", "killed_death", "last_ticket_time", "is_paid_reset"
];
private readonly string SqlDeleteBBMProgress = "DELETE FROM \"ddon_bbm_progress\" WHERE \"character_id\"=@character_id;";
@ -20,14 +20,14 @@ public partial class DdonSqlDb : SqlDb
private readonly string SqlUpdateBBMProgress = $"UPDATE \"ddon_bbm_progress\" SET {BuildQueryUpdate(BitterBlackMazeProgressFields)} WHERE \"character_id\"=@character_id;";
public override bool InsertBBMProgress(uint characterId, ulong startTime, uint contentId, BattleContentMode contentMode, uint tier, bool killedDeath, ulong lastTicketTime)
public override bool InsertBBMProgress(uint characterId, ulong startTime, uint contentId, BattleContentMode contentMode, uint tier, bool killedDeath, ulong lastTicketTime, bool isPaidReset)
{
using DbConnection connection = OpenNewConnection();
return InsertBBMProgress(connection, characterId, startTime, contentId, contentMode, tier, killedDeath, lastTicketTime);
return InsertBBMProgress(connection, characterId, startTime, contentId, contentMode, tier, killedDeath, lastTicketTime, isPaidReset);
}
public bool InsertBBMProgress(DbConnection connection, uint characterId, ulong startTime, uint contentId, BattleContentMode contentMode, uint tier, bool killedDeath,
ulong lastTicketTime)
ulong lastTicketTime, bool isPaidReset)
{
return ExecuteNonQuery(connection, SqlInsertBBMProgress, command =>
{
@ -38,16 +38,17 @@ public partial class DdonSqlDb : SqlDb
AddParameter(command, "tier", tier);
AddParameter(command, "killed_death", killedDeath);
AddParameter(command, "last_ticket_time", lastTicketTime);
AddParameter(command, "is_paid_reset", isPaidReset);
}) == 1;
}
public override bool UpdateBBMProgress(uint characterId, BitterblackMazeProgress progress, DbConnection? connectionIn = null)
{
return UpdateBBMProgress(characterId, progress.StartTime, progress.ContentId, progress.ContentMode, progress.Tier, progress.KilledDeath, progress.LastTicketTime,
return UpdateBBMProgress(characterId, progress.StartTime, progress.ContentId, progress.ContentMode, progress.Tier, progress.KilledDeath, progress.LastTicketTime, progress.IsPaidReset,
connectionIn);
}
public bool UpdateBBMProgress(uint characterId, ulong startTime, uint contentId, BattleContentMode contentMode, uint tier, bool killedDeath, ulong lastTicketTime,
public bool UpdateBBMProgress(uint characterId, ulong startTime, uint contentId, BattleContentMode contentMode, uint tier, bool killedDeath, ulong lastTicketTime, bool isPaidReset,
DbConnection? connectionIn = null)
{
return ExecuteQuerySafe(connectionIn, connection =>
@ -61,6 +62,7 @@ public partial class DdonSqlDb : SqlDb
AddParameter(command, "tier", tier);
AddParameter(command, "killed_death", killedDeath);
AddParameter(command, "last_ticket_time", lastTicketTime);
AddParameter(command, "is_paid_reset", isPaidReset);
}) == 1;
});
}
@ -98,6 +100,7 @@ public partial class DdonSqlDb : SqlDb
result.Tier = GetUInt32(reader, "tier");
result.KilledDeath = GetBoolean(reader, "killed_death");
result.LastTicketTime = GetUInt64(reader, "last_ticket_time");
result.IsPaidReset = GetBoolean(reader, "is_paid_reset");
}
});
});

View file

@ -0,0 +1,16 @@
using System.Data.Common;
namespace Arrowgene.Ddon.Database.Sql.Core.Migration;
public class BbmPaidResetMigration(DatabaseSetting databaseSetting) : IMigrationStrategy
{
public uint From => 63;
public uint To => 64;
public bool Migrate(IDatabase db, DbConnection conn)
{
string adaptedSchema = DdonDatabaseBuilder.GetAdaptedSchema(databaseSetting, "Script/migration_bbm_paid_reset.sql");
db.Execute(conn, adaptedSchema, true);
return true;
}
}

View file

@ -566,7 +566,7 @@ public abstract class SqlDb : IDatabase
public abstract bool InsertBBMCharacterId(uint characterId, uint bbmCharacterId);
public abstract uint SelectBBMCharacterId(uint characterId, DbConnection? connectionIn = null);
public abstract uint SelectBBMNormalCharacterId(uint bbmCharacterId);
public abstract bool InsertBBMProgress(uint characterId, ulong startTime, uint contentId, BattleContentMode contentMode, uint tier, bool killedDeath, ulong lastTicketTime);
public abstract bool InsertBBMProgress(uint characterId, ulong startTime, uint contentId, BattleContentMode contentMode, uint tier, bool killedDeath, ulong lastTicketTime, bool isPaidReset);
public abstract bool UpdateBBMProgress(uint characterId, BitterblackMazeProgress progress, DbConnection? connectionIn = null);
public abstract BitterblackMazeProgress SelectBBMProgress(uint characterId);
public abstract bool RemoveBBMProgress(uint characterId);

View file

@ -464,6 +464,23 @@ namespace Arrowgene.Ddon.GameServer.Characters
}
else
{
//Sealed Orange chests can have a chance at giving an earring/bracelet if the JSON is configured to do so and the character is doing a Paid Reset of BBM
if( character.BbmProgress.IsPaidReset &&
chestType == ChestType.Orange &&
assets.LootRanges[stageId.Id].SealedChestJewelryChance > 0 &&
RollRewardChance(assets.LootRanges[stageId.Id].SealedChestJewelryChance))
{
uint itemId = (character.BbmProgress.ContentMode == BattleContentMode.Rotunda)
? BitterblackMazeManager.BitterblackBraceletItemId
: BitterblackMazeManager.BitterblackEarringItemId;
results.Add(new InstancedGatheringItem()
{
ItemId = (ItemId)itemId,
ItemNum = 1,
Quality = 1,
});
}
uint picks = (uint)Random.Shared.Next(4);
for (int i = 0; i < picks; i++)
{

View file

@ -118,6 +118,7 @@ namespace Arrowgene.Ddon.GameServer.Handler
client.Character.BbmProgress.ContentId = 0;
client.Character.BbmProgress.Tier = 0;
client.Character.BbmProgress.KilledDeath = false;
client.Character.BbmProgress.IsPaidReset = isPaidRequest;
Server.Database.UpdateBBMProgress(client.Character.CharacterId, client.Character.BbmProgress, connection);
// Update the situation information

View file

@ -518,7 +518,7 @@ namespace Arrowgene.Ddon.LoginServer.Handler
Logger.Error("Failed to seed first MSQ for player");
}
if (!Database.InsertBBMProgress(character.CharacterId, 0, 0, 0, 0, false, 0))
if (!Database.InsertBBMProgress(character.CharacterId, 0, 0, 0, 0, false, 0, true))
{
Logger.Error("Failed to insert BBM progress");
}

View file

@ -39,6 +39,7 @@ namespace Arrowgene.Ddon.Shared.Asset
public (uint Min, uint Max) SealedRange;
public double RareChance { get; set; }
public double JewelryChance { get; set; }
public double SealedChestJewelryChance { get; set; }
public (uint Gold, uint Silver, uint Red) Marks { get; set; }
}

View file

@ -70,6 +70,7 @@ namespace Arrowgene.Ddon.Shared.AssetReader
NormalRange = (lootRange.GetProperty("normal").GetProperty("min").GetUInt32(), lootRange.GetProperty("normal").GetProperty("max").GetUInt32()),
SealedRange = (lootRange.GetProperty("sealed").GetProperty("min").GetUInt32(), lootRange.GetProperty("sealed").GetProperty("max").GetUInt32()),
JewelryChance = lootRange.GetProperty("jewelry_chance").GetDouble(),
SealedChestJewelryChance = lootRange.GetProperty("sealed_chest_jewelry_chance").GetDouble(),
RareChance = lootRange.GetProperty("rare_chance").GetDouble(),
Marks = (lootRange.GetProperty("marks").GetProperty("gold").GetUInt32(), lootRange.GetProperty("marks").GetProperty("silver").GetUInt32(), lootRange.GetProperty("marks").GetProperty("red").GetUInt32())
};

View file

@ -1091,6 +1091,7 @@
{
"comment": "Rotunda 1",
"jewelry_chance": 1.0,
"sealed_chest_jewelry_chance": 0.0,
"rare_chance": 0.01,
"stage_ids": [
603,
@ -1115,6 +1116,7 @@
{
"comment": "Rotunda 2",
"jewelry_chance": 1.0,
"sealed_chest_jewelry_chance": 0.0,
"rare_chance": 0.01,
"stage_ids": [
604,
@ -1139,6 +1141,7 @@
{
"comment": "Rotunda 3",
"jewelry_chance": 1.0,
"sealed_chest_jewelry_chance": 0.0,
"rare_chance": 0.01,
"stage_ids": [
605,
@ -1166,6 +1169,7 @@
{
"comment": "Abyss 1",
"jewelry_chance": 1.0,
"sealed_chest_jewelry_chance": 0.0,
"rare_chance": 0.01,
"stage_ids": [
682,
@ -1190,6 +1194,7 @@
{
"comment": "Abyss 2",
"jewelry_chance": 1.0,
"sealed_chest_jewelry_chance": 0.0,
"rare_chance": 0.01,
"stage_ids": [
683,
@ -1214,6 +1219,7 @@
{
"comment": "Abyss 3",
"jewelry_chance": 1.0,
"sealed_chest_jewelry_chance": 0.0,
"rare_chance": 0.01,
"stage_ids": [
684,
@ -1238,6 +1244,7 @@
{
"comment": "Abyss 4",
"jewelry_chance": 1.0,
"sealed_chest_jewelry_chance": 0.0,
"rare_chance": 0.01,
"stage_ids": [
685,

View file

@ -18,5 +18,6 @@ namespace Arrowgene.Ddon.Shared.Model.BattleContent
public uint Tier { get; set; }
public bool KilledDeath { get; set; }
public ulong LastTicketTime { get; set; }
public bool IsPaidReset { get; set; }
}
}

View file

@ -428,7 +428,7 @@ namespace Arrowgene.Ddon.Test.Database
public bool InsertBBMCharacterId(uint characterId, uint bbmCharacterId) { return false; }
public uint SelectBBMCharacterId(uint characterId, DbConnection? connectionIn = null) { return 0; }
public uint SelectBBMNormalCharacterId(uint bbmCharacterId) { return 0; }
public bool InsertBBMProgress(uint characterId, ulong startTime, uint contentId, BattleContentMode contentMode, uint tier, bool killedDeath, ulong lastTicketTime) { return true; }
public bool InsertBBMProgress(uint characterId, ulong startTime, uint contentId, BattleContentMode contentMode, uint tier, bool killedDeath, ulong lastTicketTime, bool isPaidReset) { return true; }
public bool UpdateBBMProgress(uint characterId, BitterblackMazeProgress progress, DbConnection? connectionIn = null) { return true; }
public bool RemoveBBMProgress(uint characterId) { return true; }
public BitterblackMazeProgress SelectBBMProgress(uint characterId) { return new BitterblackMazeProgress(); }