NHSE/NHSE.Core/Structures/Records/LifeSupportAchievement.cs
Kurt b88c518d5c
Update FieldItemEditor for 3.0.0 (#716)
Updates the Field Item Editor to render layers based on the entire map, and the per-patch positioning of each layer.
Import/export will gracefully handle upgrade/downgrade, and viewport import/export will gracefully update tiles rather than a per-acre basis.

Performance has also been slightly improved; no allocation is done anymore when updating the image.
2026-01-25 16:55:38 -06:00

190 lines
16 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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