mirror of
https://github.com/kwsch/NHSE.git
synced 2026-04-21 07:57:25 -05:00
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.
190 lines
16 KiB
C#
190 lines
16 KiB
C#
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" )}, // ムシとり大会に6~9月参加した
|
||
{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}";
|
||
}
|
||
} |