`ShopCatalogChest`의 레벨/경험치/레벨업과 `SHOP_CATALOG_CHEST`, `SHOP_PRODUCT_CHEST_TYPE` 기반 chest 구매 보상 규칙을 구현할 때 사용한다.
Status: ACTIVE AppliesTo: v10 Type: Design / Runtime SSOT
ShopCatalogChest는 더 이상 SHOP_ITEM_CHEST.reward_group_id를 직접 소비하는 단순 보상 카탈로그가 아니다.
이 문서는 chest catalog progression(level/exp)과 purchase reward routing을 정의한다.
ShopCatalogChest는 현재 ShopCatalogBase thin wrapper다.SHOP_ITEM_CHEST는 현재 Reward_group_id, Amount를 직접 가진다.ShopProductFactory.CreateChestProduct()는 chest row를 일반 ShopRewardProductBase로 만든다.ShopManager.validateShopProductConfig() / buyRewardCatalogAsync()는 reward_group_id non-empty를 전제로 한다.ShopCatalogChestStorageData는 adsRefreshUtcMs, productRemainCounts만 저장한다.따라서 이번 변경은 table 추가만이 아니라 chest 전용 purchase flow 분리가 필요하다.
입력: input/Domains/Game/ENUM_META.json
SHOP_PRODUCT_CHEST_TYPE: [NONE, ADS, ONE, TEN]
TES 표기는 오타로 보고 TEN만 사용한다.입력: input/Domains/Game/ShopTable.xlsx
shop_item_idname_idcurrency_typepriceamountmax_countproductChestType (SHOP_PRODUCT_CHEST_TYPE)reward_group_idADS product는 currency_type=ADS, price=0 유지ONE/TEN은 유료 또는 재화 결제 chest 상품이다.amount는 reward 반복 지급 횟수다. 예를 들어 amount=10이면 선택된 reward group을 10회 적용한 것과 동일한 보상을 준다.amount는 exp 획득량에는 곱하지 않는다. exp는 SHOP_CATALOG_CHEST의 Ads_exp/Gain_exp01/Gain_exp10만 사용한다.입력: input/Domains/Game/ShopTable.xlsx
권장 row shape:
Level (int, pk, 1-base)Ads_exp (int)Gain_exp01 (int)Gain_exp10 (int)Max_exp (int)Reward_ads (string, reward_group_id)Reward_paid01 (string, reward_group_id)Reward_paid10 (string, reward_group_id)Hard rules:
Level이다.TB_SHOP_CATALOG_CHEST.Get(level)로 현재 레벨 row를 읽을 수 있어야 한다.SHOP_CATALOG_CHEST table에 존재하는 최대 Level 값이다.ShopCatalogChest public contract:
public int Level { get; }
public int CurrentExp { get; }
public int Max_exp { get; }
public void LevelUp();
Rules:
Level 기본값은 1CurrentExp 기본값은 0Max_exp는 현재 SHOP_CATALOG_CHEST.Level row의 max_exp를 계산해서 노출한다. 별도 저장하지 않는다.CurrentExp는 누적 lifetime exp가 아니라 현재 레벨 구간 exp다.LevelUp()는 level을 증가시키고 overflow exp를 다음 레벨로 이월한다.while (CurrentExp >= Max_exp && nextRow exists)로 overflow exp를 보존하는 것이다.CurrentExp=0으로 고정한다.Max_exp=0으로 노출하는 것을 권장한다. 진행 필요 exp가 더 이상 없음을 런타임 값에서 명확히 표현할 수 있다.Chest purchase reward source는 SHOP_ITEM_CHEST row가 아니라 현재 chest level row다.
구매 성공 흐름:
ShopCatalogChest instance를 얻는다.Level의 SHOP_CATALOG_CHEST row를 조회한다.SHOP_PRODUCT_CHEST_TYPE으로 reward / exp를 결정한다.SHOP_ITEM_CHEST.amount 횟수만큼 적용한다.Max_exp를 넘기면 자동 레벨업 한다.remainCount, adsRefreshUtcMs, save state를 반영한다.매핑:
ADS -> reward=Reward_ads, exp=Ads_expONE -> reward=Reward_paid01, exp=Gain_exp01TEN -> reward=Reward_paid10, exp=Gain_exp10Hard rules:
SHOP_ITEM_CHEST.amount를 사용한다.Max_exp다.CurrentExp=0을 유지한다.level/currentExp를 storage에 반영해야 한다.adsRefreshUtcMs)와 limited purchase remain semantics(productRemainCounts)는 유지한다.현재 generic reward product model은 chest progression에 맞지 않는다.
구현은 최소한 아래 둘 중 하나를 처리해야 한다.
ShopProductChest : ShopProductBase 추가, SHOP_PRODUCT_CHEST_TYPE Chest_type, int Amount 보유CHEST catalog에 한해 빈 reward_group_id를 허용하고 runtime에서 reward를 동적으로 조회권장 이유:
Reward_group_id를 강제한다.product.Reward_group_id를 직접 적용한다.ShopCatalogChestStorageData 소유 상태:
adsRefreshUtcMsproductRemainCountslevelcurrentExpRules:
ShopStorage.schemaVersion는 증가해야 한다. (11 -> 12 예상)level=1, currentExp=0으로 복원한다.Max_exp는 table 기반 계산값이므로 serialize하지 않는다.catalogs.CHEST.level, catalogs.CHEST.currentExp를 저장/복원해야 한다.level이 최대 레벨 이상이면 최대 레벨로 clamp하고 currentExp=0으로 정규화한다.Data / codegen:
input/Domains/Game/ENUM_META.jsoninput/Domains/Game/ShopTable.xlsxSHOP_ITEM_CHEST, SHOP_CATALOG_CHEST, SHOP_PRODUCT_CHEST_TYPERuntime (3-path mirror):
Runtime/Shop/Catalog/ShopCatalogChest.csRuntime/Shop/Catalog/ShopCatalogBase.cs (공통 helper를 올릴 경우)Runtime/Shop/ShopProduct.csRuntime/Shop/ShopProductFactory.csRuntime/Shop/ShopManager.csRuntime/Shop/ShopStorage.csRuntime/SaveData/JsonCodec/SaveDataJsonCodecShop.csSample table data:
framework-cs/apps/UnityExample/Assets/Bundles/Tables/ndjson/SHOP_ITEM_CHEST.jsonframework-cs/apps/UnityExample/Assets/Bundles/Tables/ndjson/SHOP_CATALOG_CHEST.jsonShopTable.xlsx에서 SHOP_PRODUCT_CHEST_TYPE, SHOP_CATALOG_CHEST, 변경된 SHOP_ITEM_CHEST 스키마를 authoring한다.level/currentExp를 추가한다.Chest_type, Amount를 알 수 있도록 ShopProduct / ShopProductFactory를 정리한다.ShopCatalogChest에 current row lookup, Level, CurrentExp, Max_exp, LevelUp(), max-level clamp를 구현한다.ShopManager의 chest buy path를 generic reward product path와 분리하고 reward multiplier=amount를 반영한다.