using System; using System.Collections.Generic; namespace NHSE.Core { /// /// Multi-milestone definition for tracking game-play achievements. /// public class LifeSupportAchievement : INamedValue { /// /// Amount of milestones an achievement can have. /// public const int MilestoneMax = 6; public readonly short FlagLand; public readonly short FlagPlayer; public ushort Index { get; } public string Name { get; } /// Total number of milestones for this achievement type. public readonly int AchievementCount; /// First Milestone's Satisfaction Threshold public readonly uint Threshold1; /// Second Milestone's Satisfaction Threshold public readonly uint Threshold2; /// Third Milestone's Satisfaction Threshold public readonly uint Threshold3; /// Fourth Milestone's Satisfaction Threshold public readonly uint Threshold4; /// Fifth Milestone's Satisfaction Threshold public readonly uint Threshold5; public LifeSupportAchievement(ushort index, byte max, uint t1, uint t2, uint t3, uint t4, uint t5, short land, short player, string name) { Index = index; AchievementCount = max; Threshold1 = t1; Threshold2 = t2; Threshold3 = t3; Threshold4 = t4; Threshold5 = t5; FlagLand = land; FlagPlayer = player; Name = name; } public uint MaxThreshold => Math.Max(Threshold1, Math.Max(Threshold2, Math.Max(Threshold3, Math.Max(Threshold4, Threshold5)))); /// /// Gets the Milestone Threshold /// /// Milestone index /// Zero if the milestone does not have a threshold public uint GetThresholdValue(in int index) { return index switch { 0 => Threshold1, 1 => Threshold2, 2 => Threshold3, 3 => Threshold4, 4 => Threshold5, _ => 0, }; } /// /// Checks if the Milestone is satisfied. /// /// Milestone index /// Value stored for the entry /// True if the milestone is satisfied, false if not. public bool GetIsSatisfied(in int index, in uint count) { if ((uint)index >= MilestoneMax) throw new ArgumentOutOfRangeException(nameof(index)); // Threshold value milestone var threshold = GetThresholdValue(index); if (threshold != 0) return count >= threshold; // Bit-toggle milestone var bit = (count >> index) & 1; return bit != 0; } private const string Unknown = "???"; public static readonly IReadOnlyDictionary List = new Dictionary { {0x00, new LifeSupportAchievement(000, 5, 0010, 0100, 0500, 2000, 5000, 3, -1, "CatchFish" )}, // サカナを釣った {0x01, new LifeSupportAchievement(001, 5, 0010, 0100, 0500, 2000, 5000, 3, -1, "CatchInsect" )}, // ムシを捕まえた {0x02, new LifeSupportAchievement(002, 3, 0010, 0050, 0100, 0000, 0000, -1, -1, "CatchFishContinuously" )}, // 連続で釣りを成功させた回数の最高記録 {0x03, new LifeSupportAchievement(003, 5, 0010, 0020, 0040, 0060, 0080, -1, -1, "FillFishList" )}, // サカナ図鑑を埋めた {0x04, new LifeSupportAchievement(004, 5, 0010, 0020, 0040, 0060, 0080, -1, -1, "FillInsectList" )}, // ムシ図鑑を埋めた {0x05, new LifeSupportAchievement(005, 5, 0005, 0020, 0050, 0100, 0300, -1, -1, "ShootDownBalloon" )}, // ふうせんを撃ち落とした {0x06, new LifeSupportAchievement(006, 5, 0010, 0050, 0100, 0200, 0300, 3, -1, "PlantFlowerSeed" )}, // 花の種を植えた {0x07, new LifeSupportAchievement(007, 6, 0000, 0000, 0000, 0000, 0000, -1, -1, "PlantFruit" )}, // 6種類のフルーツを植えた {0x08, new LifeSupportAchievement(008, 3, 0005, 0010, 0030, 0000, 0000, -1, -1, "PlantTreeSeedling" )}, // 木の苗を植えた {0x09, new LifeSupportAchievement(009, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "BuyKabu" )}, // カブを買った {0x0A, new LifeSupportAchievement(010, 5, 1000, 10000, 100000, 1000000, 10000000, -1, -1, "HowmuchSellKabu" )}, // カブで得た累計利益 {0x0B, new LifeSupportAchievement(011, 5, 5000, 50000, 500000, 2000000, 5000000, -1, -1, "HowmuchBuyItem" )}, // これまでの買い物総額 {0x0C, new LifeSupportAchievement(012, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "BuyItemRcm" )}, // まめきちの店で買い物した {0x0D, new LifeSupportAchievement(013, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "SellItemRcm" )}, // まめきちの店で売った {0x0E, new LifeSupportAchievement(014, 5, 0005, 0020, 0050, 0100, 0200, -1, -1, "RemakeFurniture" )}, // リメイクをした {0x0F, new LifeSupportAchievement(015, 5, 0100, 0200, 0300, 0400, 0500, -1, -1, "FillCatalog" )}, // カタログの項目数 {0x10, new LifeSupportAchievement(016, 5, 0001, 0020, 0050, 0100, 0200, -1, -1, "BuyItemCatalog" )}, // 通販を利用した {0x11, new LifeSupportAchievement(017, 5, 0001, 0010, 0030, 0060, 0100, -1, -1, "GotoTotakekeShow" )}, // とたけけのライブを観た {0x12, new LifeSupportAchievement(018, 3, 0001, 0005, 0010, 0000, 0000, -1, -1, "VisitAnotherIsland" )}, // よその島へのおでかけした {0x13, new LifeSupportAchievement(019, 3, 0001, 0005, 0010, 0000, 0000, -1, -1, "InviteFriend" )}, // 島にフレンドを招いた {0x15, new LifeSupportAchievement(021, 5, 0003, 0020, 0050, 0100, 0300, -1, -1, "DayPlayed" )}, // 活動日数 {0x17, new LifeSupportAchievement(023, 5, 0010, 0050, 0100, 0500, 1000, -1, -1, "WaterPlant" )}, // 水やりをした {0x18, new LifeSupportAchievement(024, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "BeStungbyWasp" )}, // ハチに刺された {0x19, new LifeSupportAchievement(025, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "CatchSeminonukegara" )}, // セミのぬけがらを取った {0x1A, new LifeSupportAchievement(026, 3, 0001, 0005, 0010, 0000, 0000, -1, -1, "CatchNomi" )}, // ノミを取ってあげた {0x1B, new LifeSupportAchievement(027, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "BeStungbyPoisonousInsect" )}, // こわいムシで気絶した {0x1F, new LifeSupportAchievement(031, 5, 0001, 0010, 0020, 0030, 0042, -1, -1, "FillReactionList" )}, // リアクションを覚えた {0x20, new LifeSupportAchievement(032, 3, 0003, 0010, 0020, 0000, 0000, -1, -1, "CatchTrash" )}, // ゴミを釣った {0x21, new LifeSupportAchievement(033, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "PayImmigrationCost" )}, // 移住費用を支払った {0x22, new LifeSupportAchievement(034, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "RepayLoan" )}, // ローンを完済した {0x23, new LifeSupportAchievement(035, 1, 0001, 0000, 0000, 0000, 0000, 3, -1, "UseMydesign" )}, // マイデザインを使った {0x24, new LifeSupportAchievement(036, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "UseMydesignPRO" )}, // マイデザインPROを使った {0x25, new LifeSupportAchievement(037, 5, 0050, 0200, 1000, 2000, 3000, -1, -1, "SellWeed" )}, // 雑草を引き取ってもらった {0x27, new LifeSupportAchievement(039, 6, 0000, 0000, 0000, 0000, 0000, -1, -1, "CollectGoldTool" )}, // 6種類の金の道具を集めた {0x28, new LifeSupportAchievement(040, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "GetSRankonHHA" )}, // HHAでSを取った {0x29, new LifeSupportAchievement(041, 4, 0000, 0000, 0000, 0000, 0000, -1, -1, "AttendFishingConvention" )}, // 釣り大会に春夏秋冬参加した {0x2A, new LifeSupportAchievement(042, 4, 0000, 0000, 0000, 0000, 0000, -1, -1, "AttendInsectConvention" )}, // ムシとり大会に6~9月参加した {0x2B, new LifeSupportAchievement(043, 3, 0001, 0010, 0020, 0000, 0000, -1, -1, "HelpGul" )}, // ジョニーを助けた {0x2C, new LifeSupportAchievement(044, 3, 0001, 0010, 0020, 0000, 0000, -1, -1, "HelpGst" )}, // ゆうたろうを助けた {0x2D, new LifeSupportAchievement(045, 3, 0001, 0010, 0020, 0000, 0000, -1, -1, "MakePerfectSnowball" )}, // 最高のゆきだるまを作った {0x2E, new LifeSupportAchievement(046, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "ReachMyBirthday" )}, // 誕生日を迎えた {0x2F, new LifeSupportAchievement(047, 3, 0001, 0010, 0020, 0000, 0000, -1, -1, "CelebrateVillagersBithday" )}, // 村民の誕生日を祝ってあげた {0x30, new LifeSupportAchievement(048, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "AttendCountdownParty" )}, // カウントダウンに参加した {0x31, new LifeSupportAchievement(049, 5, 0001, 0020, 0050, 0100, 0200, -1, -1, "BreakTool" )}, // 道具を壊した {0x32, new LifeSupportAchievement(050, 5, 0005, 0020, 0050, 0100, 0200, -1, -1, "SendLetter" )}, // 手紙を送った {0x33, new LifeSupportAchievement(051, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "MakePitfall" )}, // 落とし穴を作った {0x34, new LifeSupportAchievement(052, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "FallintoPitfall" )}, // 落とし穴に落ちた {0x35, new LifeSupportAchievement(053, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "ImmigratetoIsland" )}, // 島に移住した {0x36, new LifeSupportAchievement(054, 3, 0001, 0002, 0003, 0000, 0000, -1, -1, "BeFriendwithVillager" )}, // どうぶつとなかよしになった {0x37, new LifeSupportAchievement(055, 5, 0010, 0050, 0100, 0150, 0200, -1, -1, "FillRecipeList" )}, // 集めたレシピの数 {0x38, new LifeSupportAchievement(056, 1, 1000, 0000, 0000, 0000, 0000, -1, -1, "BootPhone" )}, // スマホを起動した(上級) {0x39, new LifeSupportAchievement(057, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "StrikeRock8Times" )}, // コイン岩を8連打した {0x3A, new LifeSupportAchievement(058, 5, 0005, 0050, 0200, 1000, 3000, -1, 320, "AchieveAppQuest" )}, // 村活クエストを達成した {0x3B, new LifeSupportAchievement(059, 5, 0001, 0010, 0050, 0100, 0300, -1, -1, "AchieveVillagersQuest" )}, // どうぶつのお願いを聞いた {0x3C, new LifeSupportAchievement(060, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "DigBell" )}, // ベルを掘り出した {0x3D, new LifeSupportAchievement(061, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "DigFossil" )}, // 化石を掘り出した {0x3E, new LifeSupportAchievement(062, 5, 0005, 0030, 0100, 0300, 0500, -1, -1, "JudgeFossil" )}, // 化石を鑑定した {0x3F, new LifeSupportAchievement(063, 5, 0005, 0020, 0050, 0100, 0200, 66, -1, "DigShell" )}, // 潮干狩りをした {0x40, new LifeSupportAchievement(064, 1, 0010, 0000, 0000, 0000, 0000, 3, -1, "PutFurnitureOutside" )}, // 外に家具を置いた {0x43, new LifeSupportAchievement(067, 5, 0020, 0100, 0500, 2000, 5000, -1, -1, "StrikeWood" )}, // 木からもくざいを出した {0x44, new LifeSupportAchievement(068, 5, 0001, 0010, 0020, 0030, 0050, 3, -1, "GreetAllVillager" )}, // 村民全員とあいさつをした {0x45, new LifeSupportAchievement(069, 5, 0010, 0050, 0200, 0500, 1000, 3, -1, "SellShell" )}, // 貝殻を売った {0x46, new LifeSupportAchievement(070, 5, 0020, 0100, 0500, 1000, 3000, 3, -1, "SellFruit" )}, // フルーツを売った {0x47, new LifeSupportAchievement(071, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "CatchBeeContinuously" )}, // ハチを5連続捕まえた {0x48, new LifeSupportAchievement(072, 5, 0005, 0050, 0200, 1000, 3000, -1, -1, "DIYTool" )}, // 道具をDIYした {0x49, new LifeSupportAchievement(073, 5, 0005, 0050, 0200, 1000, 3000, -1, -1, "DIYFurniture" )}, // 家具をDIYした {0x4B, new LifeSupportAchievement(075, 1, 0001, 0000, 0000, 0000, 0000, 3, -1, "TakePicture" )}, // カメラで写真を撮った {0x4C, new LifeSupportAchievement(076, 1, 0010, 0000, 0000, 0000, 0000, -1, -1, "BootPhoneBeginner" )}, // スマホを起動した(初級) {0x4D, new LifeSupportAchievement(077, 5, 0020, 0050, 0100, 0200, 0300, -1, -1, "HouseStorageItem" )}, // 家の倉庫に収納したアイテムの数 {0x4E, new LifeSupportAchievement(078, 5, 0005, 0015, 0030, 0100, 0150, -1, -1, "PlaceFurnitureMyHouse" )}, // 家に飾っている家具の数 {0x4F, new LifeSupportAchievement(079, 5, 0001, 0010, 0020, 0050, 0100, -1, -1, "FallFurnitureLeaf" )}, // 木を揺すって家具(葉っぱ)を落とした回数 {0x50, new LifeSupportAchievement(080, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "DropPresentinWater" )}, // 風船のプレゼントを撃ち水の中に落とした {0x51, new LifeSupportAchievement(081, 3, 0001, 0003, 0005, 0000, 0000, -1, -1, "ReformMyHome" )}, // マイホームをリフォームした {0x52, new LifeSupportAchievement(082, 5, 0001, 0002, 0005, 0006, 0007, -1, -1, "ExtendMyHome" )}, // マイホームを増築した {0x53, new LifeSupportAchievement(083, 1, 0001, 0000, 0000, 0000, 0000, 3, -1, "PostMessageBoard" )}, // 自分の島の掲示板に書き込む {0x54, new LifeSupportAchievement(084, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "UseCloset" )}, // クローゼットで着替える {0x55, new LifeSupportAchievement(085, 3, 0001, 0030, 0200, 0000, 0000, -1, -1, "PrayShootingStar" )}, // 流れ星に祈る {0x56, new LifeSupportAchievement(086, 2, 0000, 0000, 0000, 0000, 0000, 59, -1, "ChangeSymbol" )}, // 島の旗、島メロを変える {0x57, new LifeSupportAchievement(087, 1, 0001, 0000, 0000, 0000, 0000, 3, -1, "UpdatePassport" )}, // パスポートを更新した {0x58, new LifeSupportAchievement(088, 3, 0000, 0000, 0000, 0000, 0000, -1, 513, "ModifyIsland" )}, // 各地形造成をやってみた {0x59, new LifeSupportAchievement(089, 1, 0020, 0000, 0000, 0000, 0000, -1, 478, "BuildFence" )}, // 柵を置く {0x5A, new LifeSupportAchievement(090, 1, 0001, 0000, 0000, 0000, 0000, -1, -1, "DonateFake" )}, // 寄贈しようとした美術品が贋作だった {0x5B, new LifeSupportAchievement(091, 3, 0001, 0010, 0020, 0000, 0000, -1, -1, "BuyatTsunekichiShop" )}, // いなりマーケットで芸術品を買った {0x5C, new LifeSupportAchievement(092, 3, 0001, 0005, 0020, 0000, 0000, -1, -1, "PlantBushSeedling" )}, // 各種低木の苗を植えた {0x5F, new LifeSupportAchievement(095, 5, 0005, 0010, 0020, 0030, 0040, -1, -1, "FillSeafoodList" )}, // 海の幸図鑑を埋めた数 {0x60, new LifeSupportAchievement(096, 3, 0001, 0010, 0020, 0000, 0000, -1, -1, "GiveScallopsToSeo" )}, // ラコスケにホタテを渡した回数 {0x62, new LifeSupportAchievement(098, 5, 0005, 0050, 0250, 1000, 2500, -1, -1, "CatchSeafood" )}, // 海の幸をGETした回数 }; public static string GetName(int index, uint count, IReadOnlyDictionary str) { var dict = List; if (dict.TryGetValue(index, out var val)) { string name = val.Name; if (str.TryGetValue(name, out var translated)) name = translated; return $"{index:00} - {name} = {count}"; } return $"{index:00} - {Unknown} = {count}"; } public static string GetName(int index, uint count) { var dict = List; if (dict.TryGetValue(index, out var val)) return $"{index:00} - {val.Name} = {count}"; return $"{index:00} - {Unknown} = {count}"; } } }