diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..107612b --- /dev/null +++ b/.gitignore @@ -0,0 +1,343 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- Backup*.rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# ACT +References/ACT/ diff --git a/Data/DcDuty-English.json b/Data/DcDuty-English.json new file mode 100644 index 0000000..4e0c444 --- /dev/null +++ b/Data/DcDuty-English.json @@ -0,0 +1,1778 @@ +{ + "version": "202102171", + "language": "English", + "roulettes": { + "1": "Leveling", + "2": "Level 50/60/70 Dungeons", + "3": "Main Scenario", + "4": "Guildhests", + "5": "Expert", + "6": "Trials", + "7": "Frontline", + "8": "Level 80 Dungeons", + "9": "Mentor", + "10": "The Feast (Training)", + "11": "The Feast (Training)", + "13": "The Feast (Ranked)", + "15": "Alliance Raids", + "16": "The Feast (Team Ranked)", + "17": "Normal Raids", + "18": "Chocobo Race: Sagolii Road", + "19": "Chocobo Race: Costa del Sol", + "20": "Chocobo Race: Tranquil Paths", + "21": "Chocobo Race: Random", + "22": "Chocobo Race: Sagolii Road (No Rewards)", + "23": "Chocobo Race: Costa del Sol (No Rewards)", + "24": "Chocobo Race: Tranquil Paths (No Rewards)", + "25": "Chocobo Race: Random (No Rewards)", + "26": "Chocobo Race: Random", + "27": "Chocobo Race: Random", + "28": "Chocobo Race: Random", + "29": "Chocobo Race: Random", + "30": "Chocobo Race: Random", + "31": "Chocobo Race: Random", + "32": "Chocobo Race: Random", + "33": "Chocobo Race: Random", + "34": "Chocobo Race: Random", + "35": "Chocobo Race: Random", + "36": "Chocobo Race: Random", + "37": "Chocobo Race: Random", + "38": "Chocobo Race: Random" + }, + "instances": { + "1": "The Thousand Maws of Toto-Rak", + "2": "The Tam-Tara Deepcroft", + "3": "Copperbell Mines", + "4": "Sastasha", + "5": "The Aurum Vale", + "6": "Haukke Manor", + "7": "Halatali", + "8": "Brayflox`s Longstop", + "9": "Sunken Temple of Qarn", + "10": "The Wanderer`s Palace", + "11": "The Stone Vigil", + "12": "Cutter`s Cry", + "13": "Dzemael Darkhold", + "14": "Amdapor Keep", + "15": "Castrum Meridianum", + "16": "The Praetorium", + "17": "Pharos Sirius", + "18": "Copperbell Mines (Hard)", + "19": "Haukke Manor (Hard)", + "20": "Brayflox`s Longstop (Hard)", + "21": "Halatali (Hard)", + "22": "The Lost City of Amdapor", + "23": "Hullbreaker Isle", + "24": "The Tam-Tara Deepcroft (Hard)", + "25": "The Stone Vigil (Hard)", + "26": "Sunken Temple of Qarn (Hard)", + "27": "Snowcloak", + "28": "Sastasha (Hard)", + "29": "Amdapor Keep (Hard)", + "30": "The Wanderer`s Palace (Hard)", + "31": "The Great Gubal Library", + "32": "The Keeper of the Lake", + "33": "Neverreap", + "34": "The Vault", + "35": "The Fractal Continuum", + "36": "The Dusk Vigil", + "37": "Sohm Al", + "38": "Aetherochemical Research Facility", + "39": "The Aery", + "40": "Pharos Sirius (Hard)", + "41": "Saint Mocianne`s Arboretum", + "42": "Basic Training: Enemy Parties", + "43": "Under the Armor", + "44": "Basic Training: Enemy Strongholds", + "45": "Hero on the Half Shell", + "46": "Pulling Poison Posies", + "47": "Stinging Back", + "48": "All`s Well that Ends in the Well", + "49": "Flicking Sticks and Taking Names", + "50": "More than a Feeler", + "51": "Annoy the Void", + "52": "Shadow and Claw", + "53": "Long Live the Queen", + "54": "Ward Up", + "55": "Solemn Trinity", + "56": "The Bowl of Embers", + "57": "The Navel", + "58": "The Howling Eye", + "59": "The Bowl of Embers (Hard)", + "60": "The Navel (Hard)", + "61": "The Howling Eye (Hard)", + "62": "Cape Westwind", + "63": "The Bowl of Embers (Extreme)", + "64": "The Navel (Extreme)", + "65": "The Howling Eye (Extreme)", + "66": "Thornmarch (Hard)", + "67": "Thornmarch (Extreme)", + "68": "The Minstrel`s Ballad: Ultima`s Bane", + "72": "The Whorleater (Hard)", + "73": "The Whorleater (Extreme)", + "74": "A Relic Reborn: the Chimera", + "75": "A Relic Reborn: the Hydra", + "76": "Battle on the Big Bridge", + "77": "The Striking Tree (Hard)", + "78": "The Striking Tree (Extreme)", + "79": "Akh Afah Amphitheatre (Hard)", + "80": "Akh Afah Amphitheatre (Extreme)", + "81": "The Dragon`s Neck", + "82": "Urth`s Fount", + "83": "The Steps of Faith", + "84": "The Chrysalis", + "85": "Battle in the Big Keep", + "86": "Thok ast Thok (Hard)", + "87": "Thok ast Thok (Extreme)", + "88": "The Limitless Blue (Hard)", + "89": "The Limitless Blue (Extreme)", + "90": "The Singularity Reactor", + "91": "The Minstrel`s Ballad: Thordan`s Reign", + "92": "The Labyrinth of the Ancients", + "93": "Binding Coil of Bahamut - T1", + "94": "Binding Coil of Bahamut - T2", + "95": "Binding Coil of Bahamut - T3", + "96": "Binding Coil of Bahamut - T4", + "97": "Binding Coil of Bahamut - T5", + "98": "Second Coil of Bahamut - T1", + "99": "Second Coil of Bahamut - T2", + "100": "Second Coil of Bahamut - T3", + "101": "Second Coil of Bahamut - T4", + "102": "Syrcus Tower", + "103": "Second Coil of Bahamut S - T1", + "104": "Second Coil of Bahamut S - T2", + "105": "Second Coil of Bahamut S - T3", + "106": "Second Coil of Bahamut S - T4", + "107": "Final Coil of Bahamut - T1", + "108": "Final Coil of Bahamut - T2", + "109": "Final Coil of Bahamut - T3", + "110": "Final Coil of Bahamut - T4", + "111": "The World of Darkness", + "112": "A - Fist of the Father", + "113": "A - Cuff of the Father", + "114": "A - Arm of the Father", + "115": "A - Burden of the Father", + "116": "A - Fist of the Father (Savage)", + "117": "A - Cuff of the Father (Savage)", + "118": "A - Arm of the Father (Savage)", + "119": "A - Burden of the Father (Savage)", + "120": "The Void Ark", + "127": "The Borderland Ruins (Secure)", + "130": "Seal Rock (Seize)", + "131": "The Diadem (Easy)", + "132": "The Diadem", + "133": "The Diadem (Hard)", + "134": "Containment Bay S1T7", + "135": "Containment Bay S1T7 (Extreme)", + "136": "A - Fist of the Son", + "137": "A - Cuff of the Son", + "138": "A - Arm of the Son", + "139": "A - Burden of the Son", + "140": "Lost City of Amdapor (Hard)", + "141": "The Antitower", + "143": "The Feast (4 on 4 - Training)", + "145": "The Feast (4 on 4 - Ranked)", + "147": "A - Fist of the Son (Savage)", + "148": "A - Cuff of the Son (Savage)", + "149": "A - Arm of the Son (Savage)", + "150": "A - Burden of the Son (Savage)", + "151": "Avoid Area of Effect Attacks", + "152": "Execute a Combo to Increase Enmity", + "153": "Execute a Combo in Battle", + "154": "Accrue Enmity from Multiple Targets", + "155": "Engage Multiple Targets", + "156": "Execute a Ranged Attack to Increase Enmity", + "157": "Engage Enemy Reinforcements", + "158": "Assist Allies in Defeating a Target", + "159": "Defeat an Occupied Target", + "160": "Avoid Engaged Targets", + "161": "Engage Enemy Reinforcements", + "162": "Interact with the Battlefield", + "163": "Heal an Ally", + "164": "Heal Multiple Allies", + "165": "Avoid Engaged Targets", + "166": "Final Exercise", + "168": "The Weeping City of Mhach", + "169": "The Final Steps of Faith", + "170": "The Minstrel`s Ballad: Nidhogg`s Rage", + "171": "Sohr Khai", + "172": "Hullbreaker Isle (Hard)", + "174": "The Palace of the Dead B1~B10", + "175": "The Palace of the Dead B11~B20", + "176": "The Palace of the Dead B21~B30", + "177": "The Palace of the Dead B31~B40", + "178": "The Palace of the Dead B41~B50", + "179": "The Aquapolis", + "180": "The Fields of Glory (Shatter)", + "181": "Haunted Manor", + "182": "Xelphatol", + "183": "Containment Bay P1T6", + "184": "Containment Bay P1T6 (Extreme)", + "186": "A - Eyes of the Creator", + "187": "A - Breath of the Creator", + "188": "A - Heart of the Creator", + "189": "A - Soul of the Creator", + "190": "A- Eyes of the Creator (Savage)", + "191": "A - Breath of the Creator (Savage)", + "192": "A - Heart of the Creator (Savage)", + "193": "A - Soul of the Creator (Savage)", + "195": "Triple Triad", + "196": "The Great Gubal Library (Hard)", + "201": "The Feast (Custom Match - Feasting Grounds)", + "204": "The Palace of the Dead B51~B60", + "205": "The Palace of the Dead B61~B70", + "206": "The Palace of the Dead B71~B80", + "207": "The Palace of the Dead B81~B90", + "208": "The Palace of the Dead B91~B100", + "209": "The Palace of the Dead B101~B110", + "210": "The Palace of the Dead B111~B120", + "211": "The Palace of the Dead B121~B130", + "212": "The Palace of the Dead B131~B140", + "213": "The Palace of the Dead B141~B150", + "214": "The Palace of the Dead B151~B160", + "215": "The Palace of the Dead B161~B170", + "216": "The Palace of the Dead B171~B180", + "217": "The Palace of the Dead B181~B190", + "218": "The Palace of the Dead B191~B200", + "219": "Baelsar`s Wall", + "220": "Dun Scaith", + "221": "Sohm Al (Hard)", + "223": "Containment Bay Z1T9", + "224": "Containment Bay Z1T9 (Extreme)", + "228": "The Feast (4 on 4 - Training)", + "230": "The Feast (4 on 4 - Ranked)", + "233": "The Feast (Custom Match - Lichenweed)", + "235": "Shisui of the Violet Tides", + "236": "The Temple of the Fist", + "238": "The Sirensong Sea", + "239": "The Royal Menagerie", + "240": "Bardam`s Mettle", + "241": "Doma Castle", + "242": "Castrum Abania", + "243": "The Pool of Tribute", + "244": "The Pool of Tribute (Extreme)", + "247": "Ala Mhigo", + "252": "Deltascape V1.0", + "253": "Deltascape V2.0", + "254": "Deltascape V3.0", + "255": "Deltascape V4.0", + "256": "Deltascape V1.0 (Savage)", + "257": "Deltascape V2.0 (Savage)", + "258": "Deltascape V3.0 (Savage)", + "259": "Deltascape V4.0 (Savage)", + "262": "Kugane Castle", + "263": "Emanation", + "264": "Emanation (Extreme)", + "268": "The Lost Canals of Uznair", + "276": "The Hidden Canals of Uznair", + "277": "Astragalos", + "278": "The Minstrel`s Ballad: Shinryu`s Domain", + "279": "The Drowned City of Skalla", + "280": "Unending Coil of Bahamut (Ultimate)", + "281": "The Royal City of Rabanastre", + "283": "The Forbidden Land, Eureka Anemos", + "284": "Hells` Lid", + "285": "the Fractal Continuum (Hard)", + "286": "Sigmascape V1.0", + "287": "Sigmascape V2.0", + "288": "Sigmascape V3.0", + "289": "Sigmascape V4.0", + "290": "Jade Stoa", + "291": "Jade Stoa (Extreme)", + "292": "Sigmascape V1.0 (Savage)", + "293": "Sigmascape V2.0 (Savage)", + "294": "Sigmascape V3.0 (Savage)", + "295": "Sigmascape V4.0 (Savage)", + "473": "The Valentione`s Ceremony", + "474": "The Great Hunt", + "475": "The Great Hunt (Extreme)", + "476": "The Feast (Team Ranked)", + "478": "The Feast (Ranked)", + "479": "The Feast (Training)", + "480": "The Feast (Custom Match - Crystal Tower)", + "481": "Chocobo Race: Tutorial", + "482": "Race 1 - Hugging the Inside", + "483": "Race 2 - Keep Away", + "484": "Race 3 - Inability", + "485": "Race 4 - Heavy Hooves", + "486": "Race 5 - Defending the Rush", + "487": "Race 6 - Road Rivals", + "488": "Race 7 - Field of Dreams", + "489": "Race 8 - Playing Both Ends", + "490": "Race 9 - Stamina", + "491": "Race 10 - Cat and Mouse", + "492": "Race 11 - Mad Dash", + "493": "Race 12 - Bag of Tricks", + "494": "Race 13 - Tag Team", + "495": "Race 14 - Heavier Hooves", + "496": "Race 15 - Ultimatum", + "497": "Chocobo Race: Sagolii Road", + "498": "Chocobo Race: Costa del Sol", + "499": "Chocobo Race: Tranquil Paths", + "500": "Chocobo Race: Sagolii Road", + "501": "Chocobo Race: Costa del Sol", + "502": "Chocobo Race: Tranquil Paths", + "503": "Chocobo Race: Sagolii Road", + "504": "Chocobo Race: Costa del Sol", + "505": "Chocobo Race: Tranquil Paths", + "506": "Chocobo Race: Sagolii Road", + "507": "Chocobo Race: Costa del Sol", + "508": "Chocobo Race: Tranquil Paths", + "509": "Chocobo Race: Sagolii Road", + "510": "Chocobo Race: Costa del Sol", + "511": "Chocobo Race: Tranquil Paths", + "512": "Chocobo Race: Sagolii Road", + "513": "Chocobo Race: Costa del Sol", + "514": "Chocobo Race: Tranquil Paths", + "515": "Chocobo Race: Sagolii Road", + "516": "Chocobo Race: Costa del Sol", + "517": "Chocobo Race: Tranquil Paths", + "518": "Chocobo Race: Sagolii Road", + "519": "Chocobo Race: Costa del Sol", + "520": "Chocobo Race: Tranquil Paths", + "521": "Chocobo Race: Sagolii Road", + "522": "Chocobo Race: Costa del Sol", + "523": "Chocobo Race: Tranquil Paths", + "524": "Chocobo Race: Sagolii Road", + "525": "Chocobo Race: Costa del Sol", + "526": "Chocobo Race: Tranquil Paths", + "527": "Chocobo Race: Sagolii Road", + "528": "Chocobo Race: Costa del Sol", + "529": "Chocobo Race: Tranquil Paths", + "530": "Chocobo Race: Sagolii Road", + "531": "Chocobo Race: Costa del Sol", + "532": "Chocobo Race: Tranquil Paths", + "533": "Chocobo Race: Sagolii Road", + "534": "Chocobo Race: Costa del Sol", + "535": "Chocobo Race: Tranquil Paths", + "536": "The Swallow`s Compass", + "537": "Castrum Fluminis", + "538": "the Minstrel`s Ballad: Tsukuyomi`s Pain", + "539": "The Weapon`s Refrain (Ultimate)", + "540": "Heaven-on-High (1-10)", + "541": "Heaven-on-High (11-20)", + "542": "Heaven-on-High (21-30)", + "543": "Heaven-on-High (31-40)", + "544": "Heaven-on-High (41-50)", + "545": "Heaven-on-High (51-60)", + "546": "Heaven-on-High (61-70)", + "547": "Heaven-on-High (71-80)", + "548": "Heaven-on-High (81-90)", + "549": "Heaven-on-High (91-100)", + "550": "The Ridorana Lighthouse", + "552": "Stage 1: Tutorial", + "553": "Stage 2: Hatching a Plan", + "554": "Stage 3: The First Move", + "555": "Stage 4: Little Big Beast", + "556": "Stage 5: Turning Tribes", + "557": "Stage 6: Off the Deepcroft", + "558": "Stage 7: Rivals", + "559": "Stage 8: Always Darkest", + "560": "Stage 9: Mine Your Minions", + "561": "Stage 10: Children of Mandragora", + "562": "Stage 11: The Queen and I", + "563": "Stage 12: Breakout", + "564": "Stage 13: My Name Is Cid", + "565": "Stage 14: Like a Nut", + "566": "Stage 15: Urth\u0027s Spout", + "567": "Stage 16: Exodus", + "568": "Stage 17: Over the Wall", + "569": "Stage 18: The Hunt", + "570": "Stage 19: Battle on the Bitty Bridge", + "571": "Stage 20: Guiding Light", + "572": "Stage 21: Wise Words", + "573": "Stage 22: World of Poor Lighting", + "574": "Stage 23: The Binding Coil", + "575": "Stage 24: The Final Coil", + "576": "LoVM: Master Battle", + "577": "LoVM: Master Battle (Hard)", + "578": "LoVM: Master Battle (Extreme)", + "579": "LoVM: Master Tournament", + "580": "The Feast (Team Custom Match - Crystal Tower)", + "581": "The Forbidden Land, Eureka Pagos", + "584": "Saint Mocianne`s Arboretum (Hard)", + "585": "The Burn", + "587": "Alphascape V1.0", + "588": "Alphascape V2.0", + "589": "Alphascape V3.0", + "590": "Alphascape V4.0", + "591": "Alphascape V1.0 (Savage)", + "592": "Alphascape V2.0 (Savage)", + "593": "Alphascape V3.0 (Savage)", + "594": "Alphascape V4.0 (Savage)", + "595": "Kugane Ohashi", + "596": "Hells` Kier", + "597": "Hells` Kier (Extreme)", + "598": "The Forbidden Land, Eureka Pyros", + "599": "Hidden Gorge", + "600": "Leap of Faith", + "601": "Leap of Faith", + "602": "Leap of Faith", + "603": "Leap of Faith", + "604": "Leap of Faith", + "605": "Leap of Faith", + "606": "Leap of Faith", + "607": "Leap of Faith", + "608": "Leap of Faith", + "610": "All`s Well That Starts Well", + "611": "The Ghimlyt Dark", + "612": "Much Ado About Pudding", + "613": "Waiting for Golem", + "614": "Gentlemen Prefer Swords", + "615": "The Threepenny Turtles", + "616": "Eye Society", + "617": "A Chorus Slime", + "618": "Bomb-edy of Errors", + "619": "To Kill a Mockingslime", + "620": "A Little Knight Music", + "621": "Some Like It Excruciatingly Hot", + "622": "The Plant-om of the Opera", + "623": "Beauty and a Beast", + "624": "Blobs in the Woods", + "625": "The Me Nobody Nodes", + "626": "Sunset Bull-evard", + "627": "The Sword of Music", + "628": "Midsummer Night`s Explosion", + "629": "On a Clear Day You Can Smell Forever", + "630": "Miss Typhon", + "631": "Chimera on a Hot Tin Roof", + "632": "Here Comes the Boom", + "633": "Behemoths and Broomsticks", + "634": "Amazing Technicolor Pit Fiends", + "635": "Dirty Rotten Azulmagia", + "636": "The Orbonne Monastery", + "637": "The Wreath of Snakes", + "638": "The Wreath of Snakes (Extreme)", + "639": "The Forbidden Land, Eureka Hydatos", + "640": "Air Force One", + "641": "Air Force One", + "642": "Air Force One", + "643": "Novice Mahjong (Ranked)", + "644": "Advanced Mahjong (Ranked)", + "645": "Four-player Mahjong (Kuitan Enabled)", + "649": "Dohn Mheg", + "650": "Four-player Mahjong (Kuitan Disabled)", + "651": "the Qitana Ravel", + "652": "Amaurot", + "653": "Eden`s Gate: Resurrection", + "654": "Eden`s Gate: Resurrection (Savage)", + "655": "the Twinning", + "656": "Malikah`s Well", + "657": "the Dancing Plague", + "658": "the Dancing Plague (Extreme)", + "659": "Mt. Gulg", + "661": "Akadaemia Anyder", + "666": "the Crown of the Immaculate", + "667": "the Crown of the Immaculate (Extreme)", + "676": "Holminster Switch", + "682": "Eden`s Gate: Inundation", + "683": "Eden`s Gate: Inundation (Savage)", + "684": "Eden`s Gate: Descent", + "685": "Eden`s Gate: Descent (Savage)", + "687": "the Dying Gasp", + "689": "Eden`s Gate: Sepulture", + "690": "Eden`s Gate: Sepulture (Savage)", + "692": "The Grand Cosmos", + "693": "The Minstrel`s Ballad: Hades`s Elegy", + "694": "The Epic of Alexander (Ultimate)", + "695": "Papa Mia", + "696": "Lock up Your Snorters", + "697": "Dangerous When Dead", + "698": "Red, Fraught, and Blue", + "699": "The Catch of the Siegfried", + "700": "The Copied Factory", + "701": "Onsal Hakair (Danshig Naadam)", + "702": "Vows of Virtue, Deeds of Cruelty", + "703": "As the Heart Bids", + "705": "Leap of Faith", + "706": "Leap of Faith", + "707": "Leap of Faith", + "708": "Leap of Faith", + "709": "Leap of Faith", + "710": "Leap of Faith", + "711": "Leap of Faith", + "712": "Leap of Faith", + "713": "Leap of Faith", + "714": "Anamnesis Anyder", + "715": "Eden`s Verse: Fulmination", + "716": "Eden`s Verse: Fulmination (Savage)", + "717": "Cinder Drift", + "718": "Cinder Drift (Extreme)", + "719": "Eden`s Verse: Furor", + "720": "Eden`s Verse: Furor (Savage)", + "721": "Ocean Fishing", + "722": "the Diadem", + "724": "A Sleep Disturbed", + "725": "Memoria Misera (Extreme)", + "726": "Eden`s Verse: Iconoclasm", + "727": "Eden`s Verse: Iconoclasm (Savage)", + "728": "Eden`s Verse: Refulgence", + "729": "Eden`s Verse: Refulgence (Savage)", + "730": "Ocean Fishing", + "731": "Ocean Fishing", + "732": "Ocean Fishing", + "733": "Ocean Fishing", + "734": "Ocean Fishing", + "735": "The Bozjan Southern Front", + "736": "the Puppets' Bunker", + "737": "the Heroes' Gauntlet", + "738": "the Seat of Sacrifice", + "739": "the Seat of Sacrifice (Extreme)", + "742": "Diadem", + "744": "the Akh Afah Amphitheatre (Unreal)", + "745": "the Shifting Oubliettes of Lyhe Ghiah", + "746": "Matoya's Relict", + "747": "Eden's Promise: Litany", + "748": "Eden's Promise: Litany (Savage)", + "749": "Eden's Promise: Umbra", + "750": "Eden's Promise: Umbra (Savage)", + "751": "Eden's Promise: Anamorphosis", + "752": "Eden's Promise: Anamorphosis (Savage)", + "753": "Diadem", + "754": "Anything Gogo's", + "755": "Triple Triad Open Tournament", + "756": "Triple Triad Invitational Parlor", + "757": "the Navel (Unreal)", + "758": "Eden`s Promise: Eternity", + "759": "Eden`s Promise: Eternity (Savage)", + "762": "Castrum Marinum", + "763": "Castrum Marinum (Extreme)", + "766": "Novice Mahjong (Quick Ranked Match)", + "767": "Advanced Mahjong (Quick Ranked Match)", + "768": "Four-player Mahjong (Quick Match, Kuitan Enabled)", + "769": "Four-player Mahjong (Quick Match, Kuitan Disabled)", + "770": "Ocean Fishing", + "771": "Ocean Fishing", + "772": "Ocean Fishing", + "773": "Ocean Fishing", + "774": "Ocean Fishing", + "775": "Ocean Fishing", + "760": "Delubrum Reginae", + "761": "Delubrum Reginae (Savage)" + }, + "areas": { + "134": { + "name": "Middle La Noscea", + "fates": { + "220": "Menuis at Work", + "221": "Overnight Migration", + "222": "Go Wespe", + "223": "A Mad, Mad, Mad Sergeant", + "225": "Thwack-a-Mole", + "226": "Yellow-bellied Greenbacks", + "227": "On the Lamb", + "229": "The Orange Boxes", + "231": "Shearing Is Caring", + "233": "The Boy Who Cried Jackal", + "235": "Sister Crustacean", + "237": "Hello, Work", + "238": "The Truth Is out There", + "239": "Taking It to the Streams", + "240": "Crying over Spilled Salt", + "533": "Return of the King", + "649": "Sister Crustacean", + "687": "Embiggened Spriggans", + "688": "Tower of Power", + "693": "Stay Frosty", + "717": "Gloria in Eggcelsis" + } + }, + "135": { + "name": "Lower La Noscea", + "fates": { + "245": "One Prince", + "246": "Fight the Flower", + "249": "You Call That a Toad", + "250": "Caving In", + "251": "Man of the Flour", + "257": "I Melt with You", + "260": "Away in a Bilge Hold", + "261": "In the Name of Love", + "262": "Don`t Drink the Water", + "264": "Enter Beastman", + "265": "One Pickman Enters", + "333": "Under the Bridge", + "534": "Return of the King", + "666": "Brick by Brick", + "667": "Brick by Stone Brick", + "694": "Stay Frosty", + "718": "Gloria in Eggcelsis" + } + }, + "137": { + "name": "Eastern La Noscea", + "fates": { + "267": "Finding Wine", + "268": "The Thirst", + "271": "Thrill of the Hunt", + "272": "The Pelican Briefing", + "274": "Them", + "278": "Careless Whiskers", + "279": "No Lip", + "280": "Jewels of the Isle", + "282": "Crab and Go", + "286": "Follow the Light", + "287": "Just a Matter of Rut", + "334": "Consigned, Sealed, and Undelivered", + "335": "It`s Not Lupus", + "532": "Return of the King", + "560": "9 to 5", + "561": "Closing Time", + "562": "Sweeter than Honey", + "563": "Ho Ho Ho", + "564": "Say My Name", + "565": "Long Way Home", + "566": "Cliff Hanger", + "689": "Embiggened Spriggans", + "690": "Tower of Power", + "701": "What`s Yours Is Mine", + "913": "The Sarong Song", + "914": "The Belle of the Beach", + "915": "Sparking Up the Wrong Beach", + "916": "It Came from Beneath the Deep", + "917": "Life`s a Beach", + "918": "Feeling Groggy", + "945": "-----", + "946": "-----" + } + }, + "138": { + "name": "Western La Noscea", + "fates": { + "289": "Absolutely, Positively", + "290": "Tender Buttons", + "291": "The Killing Fields", + "295": "(I Just) Died in Six Arms Tonight", + "297": "Iron Contra Affair", + "298": "Don`t Call Him a Fishback", + "303": "Letters from Tidegate", + "304": "The Last Straw", + "306": "Barometz Soup", + "308": "Goblin Chain", + "309": "Tryp Fantastic", + "310": "Between Aurochs", + "312": "In the Sac", + "336": "The Mandragoras", + "568": "Gauging North Tidegate", + "569": "Breaching North Tidegate", + "570": "Gauging South Tidegate", + "571": "Breaching South Tidegate", + "572": "Sharknado", + "574": "Tail of a Whale", + "575": "Watch Your Tongue", + "576": "Dead Man`s Rest", + "577": "The King`s Justice", + "578": "Making Waves", + "650": "Tender Buttons", + "702": "Eggcelsior" + } + }, + "139": { + "name": "Upper La Noscea", + "fates": { + "314": "Simurgh Is the Word", + "317": "Surprise", + "320": "The Road More Traveled", + "321": "Nine-ilm Snails", + "322": "Truth in Faerie Tales", + "323": "Giant Enemy Crab", + "329": "Shell Shocked", + "331": "Peeping Ja", + "332": "Hop, Skip, and a Jump", + "451": "Poor Maid`s Mess", + "452": "Poor Maid`s Mishap", + "453": "Poor Maid`s Misfortune", + "454": "Poor Maid`s Misadventure", + "668": "Brick by Brick", + "669": "Brick by Stone Brick", + "670": "Brick by Brick", + "671": "Brick by Gold Brick", + "703": "What`s Yours Is Mine" + } + }, + "140": { + "name": "Western Thanalan", + "fates": { + "342": "Needles to Slay", + "343": "Things that Make You Go Home", + "344": "Deface the Facts", + "345": "Please Hammers", + "346": "The Cores", + "347": "Doomed", + "348": "The Villain", + "349": "Copied Peistes", + "350": "Dog Eat Dog", + "352": "Bigger Fish to Fry", + "353": "Bubble Trouble", + "354": "Tripped up by the Fruit of Another", + "355": "Juggernaut Down", + "356": "A Matter of Rust", + "357": "There Might Be Giants", + "361": "Pound for Pound", + "366": "He`s Got Legs", + "367": "Staying Dead", + "683": "Embiggened Spriggans", + "684": "Tower of Power", + "704": "What`s Yours Is Mine", + "911": "Recurring Bugs" + } + }, + "141": { + "name": "Central Thanalan", + "fates": { + "370": "Something to Prove", + "373": "Like an Eft out of Water", + "374": "Wrecked Rats", + "375": "Survivor Rats", + "376": "Cracked", + "377": "Orobon Part Two: The Spawning", + "378": "Let them Eat Cactus", + "379": "For the Queen", + "381": "A Few Arrows Short of a Quiver", + "383": "Big Time", + "385": "Cold-blooded", + "389": "A Warm Welcome", + "393": "Leaving the Nest", + "535": "Return of the King", + "660": "Brick by Brick", + "661": "Brick by Stone Brick", + "695": "Stay Frosty", + "719": "Gloria in Eggcelsis", + "912": "Recurring Bugs" + } + }, + "145": { + "name": "Eastern Thanalan", + "fates": { + "191": "Attack on Highbridge: Prelude", + "192": "Attack on Highbridge: Act I", + "193": "Attack on Highbridge: Act II", + "194": "Attack on Highbridge: Act III", + "195": "Attack on Highbridge: Denouement", + "394": "Men Who See Goats", + "395": "License to Quill", + "397": "Westward Bound", + "398": "Bad Camp", + "400": "Bazaar Blood Triangle", + "401": "Grim Undertakings", + "402": "Simple Minds", + "406": "Manifest Destiny", + "407": "Spare the Hair", + "409": "Desert Rose", + "412": "Almost Paradise", + "413": "Deep in the Heart of Sagolii", + "536": "Return of the King", + "540": "Quartz Coupling", + "541": "A Man Rides Through", + "542": "Bad Hair Day", + "543": "The Big Bagoly Theory", + "652": "Lightning Strikes - Armored Beast", + "696": "Stay Frosty", + "705": "Eggcelsior", + "720": "Gloria in Eggcelsis" + } + }, + "146": { + "name": "Southern Thanalan", + "fates": { + "419": "Adventures in Throat Slitting", + "420": "The Corpse Bribe", + "421": "Downwind", + "422": "Soul Man", + "423": "Bigger than Life", + "424": "Heroes of the 2nd", + "427": "Diamond in the Rough", + "429": "Children of the Sands", + "430": "Return to Cinder", + "431": "Hunters and the Hunted", + "432": "From Point A", + "434": "Run Like a Flame", + "436": "Blood, Augur, Hex, Magicks", + "437": "Fish out of Water", + "441": "Harder, Bigger, Faster, Stronger", + "455": "Revenge of the Worms", + "456": "Bump and Grind", + "545": "Call Me, Mayhaps", + "546": "Book of Pride", + "548": "Tempered, Tempered", + "549": "Full of Rigor Mortis", + "550": "An Inconvenient Truth", + "551": "Future Shock", + "552": "Taken", + "553": "Gyve Talk", + "554": "Spark off the Bench", + "555": "Fallen Corpses Writhe in Style", + "557": "Quenching the Flame", + "558": "He`s a Firestarter", + "651": "Lightning Strikes - Armored Beast", + "685": "Embiggened Spriggans", + "686": "Tower of Power", + "706": "What`s Yours Is Mine" + } + }, + "147": { + "name": "Northern Thanalan", + "fates": { + "446": "With One Eye Open", + "447": "Under the Nails", + "449": "Boom Goes the Ceruleum", + "450": "Knock on Steel", + "457": "Reverse Engineering", + "556": "Core Blimey", + "637": "The Red Baron", + "638": "Just a Sip", + "639": "East Meets Worst", + "641": "Twinkle, Twinkle Little Trap", + "642": "The Ceruleum Road", + "643": "Dark Devices - The Plea", + "644": "Devices - The Bait", + "645": "Dark Devices - The Switch", + "646": "Dark Devices - The End", + "647": "Go, Go, Gorgimera" + } + }, + "148": { + "name": "Central Shroud", + "fates": { + "120": "Clever Girls", + "121": "One Enchanted Eve", + "122": "Sprig Cleaning", + "123": "Something in the Water", + "124": "The Sting", + "125": "Asipatra Attacks", + "126": "Leader of the Pack", + "127": "A Mother Scorned", + "128": "Alux of the Draw", + "130": "영원그늘 수확제", + "131": "Lethe on My Mind", + "136": "Training Day", + "137": "Bleeding Green", + "138": "Tastes Like Chick", + "139": "Sleep Tight", + "140": "Spirithold Run", + "141": "Love is in the Air", + "142": "There`s Something about Lou", + "196": "Steel Reign", + "197": "Steel Reign", + "208": "Lady Killer", + "209": "My Baby Green", + "537": "Return of the King", + "600": "The Lindwurm Has Turned", + "601": "What`s Your Poison", + "602": "Revenant Things", + "603": "If I Only Had a Soul", + "604": "In Spite of It All", + "672": "Brick by Brick", + "673": "Brick by Stone Brick", + "697": "Stay Frosty", + "707": "What`s Yours Is Mine", + "1325": "-----" + } + }, + "152": { + "name": "East Shroud", + "fates": { + "143": "Now I See Bees I Won", + "144": "Royal Rumble", + "145": "전장까지 앞으로 몇 말름?", + "148": "What a Bee Wants", + "149": "Stopping the Spread", + "150": "Jack of All Trades", + "151": "줄다리 사투", + "152": "Protecting the Patch", + "198": "Steel Reign", + "199": "Steel Reign", + "200": "Steel Reign", + "212": "Ivy League", + "213": "Thunderstruck", + "214": "Carrion Baggage", + "217": "What Have You Done for Mead Lately", + "218": "Lazy for You", + "607": "Collecting Keepsakes", + "608": "All Vine and No Popotoes", + "609": "The Squirrel Trapper`s Wife", + "610": "The Enemy of My Enemy", + "611": "The Enmity of My Enemy", + "612": "Below His Station", + "615": "Got Milkroot", + "616": "Breaking Dawn", + "618": "Handful of Dreams", + "619": "Bush Blade", + "620": "Everything`s Better", + "622": "The Gale that Rocks the Cradle", + "679": "Embiggened Spriggans", + "680": "Tower of Power", + "691": "A Wrench in the Works", + "692": "What a Boar" + } + }, + "153": { + "name": "South Shroud", + "fates": { + "153": "The Hunted", + "154": "Eft for Dead", + "158": "The Negotiators", + "159": "Breaching the Hive", + "160": "Clearing the Hive", + "161": "Defending the Hive", + "162": "Keeping the Hive", + "163": "Kickin` It with the Kedtraps", + "164": "The Coeurl King", + "166": "Another Round", + "167": "Stag Parting", + "168": "Hide and Seek", + "169": "A Tale of Two-tails", + "170": "To Whom the Toll Goes", + "171": "Eat In, Hide Out", + "172": "Robbin` Goblins", + "190": "Where the Stone Rolls", + "201": "Steel Reign", + "202": "Steel Reign", + "203": "Steel Reign", + "204": "Steel Reign", + "215": "Conspiracy Theory", + "624": "Rogue on the Water", + "626": "To Train a Tortoise", + "627": "Fate Is a Fecal Mistress", + "628": "What Gored Before", + "681": "Embiggened Spriggans", + "682": "Tower of Power", + "708": "What`s Yours Is Mine" + } + }, + "154": { + "name": "North Shroud", + "fates": { + "174": "No Birds Allowed", + "178": "Dschubba Snacks", + "179": "Now Fall", + "180": "That Which Binds Us", + "183": "Breaking Bud", + "184": "The Magical Fruit", + "185": "Micromanaging", + "187": "The Big Issue", + "188": "It Ziz What It Is", + "189": "Hare Today", + "205": "Steel Reign", + "206": "Steel Reign", + "207": "Steel Reign", + "216": "Waiting for a Moon to Fall", + "538": "Return of the King", + "631": "Don`t Disturb This Grove", + "632": "Rude Awakening", + "633": "Air Supply", + "634": "Smells Like Tree Spirit", + "674": "Brick by Brick", + "675": "Brick by Stone Brick", + "676": "Brick by Brick", + "677": "Brick by Gold Brick", + "698": "Stay Frosty", + "722": "Gloria in Eggcelsis" + } + }, + "155": { + "name": "Coerthas Central Highlands", + "fates": { + "460": "Twelve Ilms of Snow", + "463": "Baa Baa Black Sheep", + "464": "Gavial", + "465": "Whiteout", + "466": "A Log Up", + "467": "Croc-y Road", + "469": "The Grey", + "470": "Simply Red", + "472": "Spring Forward, Fall Back", + "473": "Fire in the Distance", + "474": "Coming to a Head", + "475": "Bellyful", + "479": "A Freeze Is Coming", + "480": "Giant Seps", + "482": "Riddle Me This", + "483": "Judge, Jury, and Executioner", + "484": "In the Saint`s Wake", + "486": "Tower of Power", + "487": "Turn Off Your Hearthlight", + "489": "What`s on Your Mind", + "490": "The Bigger They Are", + "491": "Wish Upon a Star", + "493": "The Taste of Fear", + "494": "Roc of Ages", + "496": "Front and Center", + "497": "If This Wall Could Talk", + "498": "Does Anyone Hear It", + "499": "The Four Winds", + "500": "Inspector Hatchet", + "501": "Svara`s Flight", + "502": "Svara`s Fear", + "503": "Svara`s Fall", + "504": "Svara`s Fury", + "505": "Behold Now Behemoth", + "506": "He Taketh It with His Eyes", + "507": "The Eyes Have It", + "508": "The Storm Caller", + "653": "Lightning Strikes - Dread on Arrival", + "654": "Lightning Strikes - Dread on Arrival", + "699": "Stay Frosty", + "709": "Eggcelsior" + } + }, + "156": { + "name": "Mor Dhona", + "fates": { + "512": "Toll Collector", + "514": "Mud about You", + "516": "Black and Nburu", + "517": "Good to Be Bud", + "520": "Standing Guard", + "521": "Another Notch on the Torch", + "522": "One Giant Leap", + "523": "Among Giants", + "524": "Another Day, Another Demon", + "525": "That`s What Adventurers Are For", + "526": "Home Is Where the Horn Is", + "527": "Gone with the Shadow", + "529": "The Prodigal Son", + "530": "V for Vinedetta", + "655": "Lightning Strikes - Anubys Assault", + "656": "Lightning Strikes - Anubys Assault", + "657": "Lightning Strikes - On Wings of Chaos", + "658": "Lightning Strikes - On Wings of Chaos" + } + }, + "180": { + "name": "Outer La Noscea", + "fates": { + "580": "The Only Way Is Up", + "581": "By a Whisker", + "583": "When the Coeurl`s Away", + "586": "The Miner in the Mirror", + "587": "Schism", + "588": "Fire in the Hole", + "589": "Make It Rain", + "591": "Peryton, Perhaps", + "593": "Restless in O`Ghomoro", + "594": "I`m a Rock, Not a Number", + "595": "Overlooking the Obvious", + "597": "Full Metal Alchemist", + "598": "Spandy Balidet", + "599": "Stopping the Shakes", + "700": "Making the Rounds" + } + }, + "397": { + "name": "Coerthas Western Highlands", + "fates": { + "787": "Eye in the Sky", + "788": "A Dung Deal", + "789": "Land of the Freeze", + "791": "Dawn of the Mylodons", + "792": "Don of the Mylodons", + "793": "We Fought a Dzu", + "794": "True Convictions", + "795": "The Polar Express", + "796": "Apparent Trap", + "798": "Abominable Me", + "800": "Requiem for a Dragon", + "801": "Follow the Sleet", + "802": "Sick Pack", + "805": "In Command", + "807": "What You See Is What You Get", + "809": "Panic Rheum", + "810": "Sugar, Sugar", + "811": "Unsilent Vigil", + "812": "Pico de Gallows", + "813": "Run, Riders, Run", + "814": "One Whiskey, One Goat, One Spear", + "815": "No Ifs, Ands, or Butts", + "816": "Null and Void", + "817": "Dishonored", + "908": "Sphenopalatine Ganglioneuralgia", + "909": "A Stihi Situation" + } + }, + "398": { + "name": "The Dravanian Forelands", + "fates": { + "818": "By the Horns", + "819": "Ladies First", + "820": "Run, Run Away", + "821": "Birds of a Feather", + "822": "Glawackus On, Glawackus Off", + "823": "Bear Apparent", + "824": "Who`s the Moss", + "825": "The Rite Stuff", + "826": "Dead Meat", + "827": "The Whole Truth", + "828": "Nothing but the Truth", + "829": "Drone Under", + "830": "El Miacid", + "831": "Cerf`s Up", + "832": "Elephant in the Brume", + "833": "The Migas Touch", + "834": "Hearing Voices", + "835": "The Mourning After", + "836": "Stamp the Yard", + "837": "Come to My Arms", + "838": "Special Tarasque Force", + "902": "Long Live the Coeurl", + "903": "Coeurls Chase Boys", + "904": "Coeurls Chase Boys", + "905": "Coeurls Chase Boys Chase Coeurls", + "906": "Coeurls Chase Boys Chase Coeurls", + "907": "Coeurls Chase Boys Chase Coeurls", + "910": "Ware the Maiden Fair" + } + }, + "399": { + "name": "The Dravanian Hinterlands", + "fates": { + "756": "Metal Gears Rising", + "757": "Metal Gears Revengeance", + "758": "Metal Gears Revengeance 2", + "759": "Tarantula Hawk, Pro Stinger", + "760": "Wild Wilde Death", + "761": "Gets the Red Out", + "762": "Makes the Very Best...Nests", + "763": "Olympus Has Pollen", + "764": "Feed Me, See More", + "766": "Pop Goes the Whizzle", + "767": "Revenge of the Vengeful Revengeance", + "768": "Ratel and Hum", + "769": "Dobharch Did It for the Best", + "770": "Infant Vangob", + "771": "Morbol Man", + "772": "On Melancholic Hill", + "773": "Sun Bear, Sun Bear, What Do You Eat", + "774": "The Bear Up There", + "775": "The Birds and the Bears", + "777": "Poroggo Stuck", + "778": "Frog Days of Summer", + "779": "Toss `Em Back", + "780": "Tome Raider", + "781": "Cockatrice Block", + "782": "Come Shells or High Water", + "783": "Toad Alone", + "784": "How Do You Feed a Hungry Manlike Monster", + "785": "Out of the Woodwork", + "786": "Silkworm" + } + }, + "400": { + "name": "The Churning Mists", + "fates": { + "725": "Wave Good-bye", + "726": "The Nuts", + "727": "Glycon Air", + "728": "Coin Toss", + "731": "Supper Time", + "732": "Sprite Club", + "735": "Whole Food", + "736": "Say it Tulihand", + "737": "Vouivre Believre", + "738": "Waugyl Waugyl Waugyl", + "740": "How to Cane Your Dragon", + "741": "Aevis Has Left the Building", + "742": "Asah, I Came, I Conquered", + "744": "Waiting for Fjalar to Stall", + "746": "Don`t Know Wyvern", + "747": "From Dusk Till", + "748": "Treehouse of the Spirits", + "751": "As the World Burns", + "752": "It`s the Moogle, Reinvented", + "753": "Corporal Pomishment", + "754": "Infamous", + "755": "Ain`t Misbehaving", + "868": "Darkscale Descendeth", + "869": "Darkscale Disappeareth", + "870": "Darkscale Devoureth", + "871": "Vedrfolnir Devoteth", + "872": "End of the Rainbow", + "873": "Rastaban Vibration", + "874": "Mogicide" + } + }, + "401": { + "name": "The Sea of Clouds", + "fates": { + "839": "Mint Condition", + "840": "Saved the Nests for Last", + "841": "One Turned Over the Cloudkin`s Nest", + "842": "Food Fight", + "843": "Leech the Sky", + "844": "Anzu Trois", + "845": "Youth Must Be Severed", + "846": "A Long Way Down", + "847": "This Is How We Gundu", + "851": "Come to My Window", + "852": "Obey their Thirst", + "853": "The Fugitive", + "854": "Zuns on the Run", + "855": "On Dangerous Ground", + "856": "Leather and Mace", + "857": "Hearts Like Steel, Fists Like Thunder", + "860": "Bones", + "861": "The Limitless Blueing Time", + "862": "Let There Be Acolytes", + "863": "A Disturbing Lack of Faith", + "864": "Guano a Mano", + "865": "The Sound of Madness", + "866": "You Eat What You Aren`t", + "867": "A Dream, Perchance to Eat", + "875": "Rebel Yehl" + } + }, + "402": { + "name": "Azys Lla", + "fates": { + "877": "Prey Online", + "878": "Prey Online", + "879": "Prey Online", + "880": "A Bug`s Death", + "881": "The Late Escape", + "882": "Still Ticking", + "883": "Life of Brain", + "884": "The Monster Mass", + "885": "Pet, Smart", + "886": "The Root of Evil", + "887": "The Mystery Machine", + "888": "Rampant Speculation", + "889": "Put the Knives Down", + "890": "Scared Sylla", + "891": "Phi Slamma Gamma East", + "892": "Phi Slamma Gamma West", + "893": "Phi Slamma Gamma South", + "894": "Yak it Up", + "895": "No Greater Goryshche", + "897": "Harvest Moon", + "898": "Out of Sight, Out of Mind", + "899": "A Room Without Books", + "900": "Curiously Strong Things", + "901": "Do Spinners Dream of Electric Rooks" + } + }, + "411": { + "name": "The Fringes", + "fates": { + "1112": "Showing the Recruits What For", + "1113": "Showing the Officers What For", + "1114": "Showing the Commanders What For", + "1115": "Death Beckons", + "1116": "Unbearable", + "1117": "The Secret Life of Plants", + "1118": "Dizzy Miss Grizzly", + "1119": "Roid Rage", + "1120": "Keeping the Peace", + "1121": "Keeping More Peace", + "1122": "Double Dhara", + "1124": "Bold This Way", + "1125": "The Morning After", + "1126": "Thank You for Not Mossling", + "1127": "The Mail Must Get Through", + "1128": "Diakka Round", + "1129": "The Evil Seed", + "1130": "The Spiderweb Chronicles", + "1131": "The Antlion`s Share", + "1132": "Really Don`t Keratyrannos", + "1133": "Get Sharp", + "1134": "The Tele-tale Hunt", + "1135": "Pop the Trunk", + "1136": "A Pain in the Neck", + "1137": "Flappy Berda", + "1138": "Ananta and Her Sisters", + "1139": "Raisin` Hell", + "1140": "Yes, This Is Dogs", + "1141": "M Bop" + } + }, + "412": { + "name": "The Peaks", + "fates": { + "1173": "A New Leaf", + "1174": "Salad Days", + "1175": "A Bone to Pick", + "1176": "And the Bandits Played On", + "1177": "Of Mice and Men", + "1178": "Churlish Chapuli", + "1179": "Down with the Sickness", + "1180": "Child`s Plague", + "1181": "You Don`t Know Jack", + "1182": "Winging It", + "1184": "Beat Boxes", + "1185": "Barbershoppe", + "1186": "Fletching Returns", + "1187": "Days of Fluturini Past", + "1188": "Diceman Cometh", + "1189": "Stuck in the Muud", + "1190": "Eat Big or Go Home", + "1191": "Love Me, Tindalos", + "1193": "Home on the Range", + "1194": "Rattle and Humbaba", + "1195": "Forget-me-not", + "1196": "The Day of the Griffins", + "1197": "Venting", + "1198": "Breakneck", + "1199": "Attack of the Groans", + "1200": "Moth to a Flame", + "1201": "Resist, Die, Repeat", + "1202": "Slaughterwife-five", + "1203": "Das Bhoot", + "1204": "5-year Energy", + "1205": "Mouth for Water", + "1207": "The Magitek Is Back" + } + }, + "413": { + "name": "The Lochs", + "fates": { + "1103": "A Horse Outside", + "1104": "A Horse Outside", + "1105": "A Horse Outside", + "1272": "Off Their Yabby", + "1273": "Foul Bachelor Frogamander", + "1274": "Old Bucket of Boruta", + "1275": "Dusk Till Abaddon", + "1276": "The Smell That Leeched Her Heart", + "1277": "Tall Tale", + "1278": "Taking Kurrea Business", + "1279": "Dude, Where`s My Karya", + "1280": "Sisyphus Cooling", + "1281": "Minotaurs on My Mind", + "1282": "Dive In", + "1283": "Pounding Salt", + "1284": "Lalla Land", + "1285": "When It Pains It Pours", + "1286": "Sob Story", + "1287": "Par for the Course", + "1288": "Sip When I`m Dead", + "1289": "Who`s Phoebad", + "1290": "Yabby Hunters", + "1291": "Enemy Territory", + "1292": "One Bad Mother Chukwa", + "1293": "Give Bees a Chance", + "1294": "About Face", + "1295": "No Time Is a Good Time", + "1296": "Mazeless Runner", + "1297": "Kingsgrave", + "1298": "Fate No Morpho", + "1299": "I Can Feel the Earth Move", + "1300": "To Leech His Own", + "1301": "Tellus a Tale", + "1302": "OK, Golem", + "1303": "Ancelot`s Fear", + "1304": "Ancelot`s Folly", + "1305": "Ancelot`s Finale" + } + }, + "421": { + "name": "The Ruby Sea", + "fates": { + "1142": "Wet", + "1143": "Clean Bill of Health", + "1144": "Quoth the Raven", + "1145": "Lay of the Lang", + "1146": "Pool Party", + "1147": "Soak Up the Sun", + "1148": "Agni`s Philosophy", + "1149": "The Coral High Ground", + "1150": "The Big Banquet Theory", + "1151": "Uncivil Serpents", + "1152": "Ray Band", + "1153": "Princess, Princess", + "1154": "Kill the Messenger", + "1155": "The F-bomb", + "1156": "Raise the Red Flag", + "1157": "Double Dream Clams", + "1158": "There Be Dragonflies", + "1159": "Bilge-hold Jin", + "1160": "Days of Plunder", + "1161": "Forever Younglier", + "1162": "Treasure Island", + "1163": "Sailor Marooned", + "1164": "Jumping the Shark", + "1165": "Red Cliff", + "1166": "Ranging Bull", + "1167": "Another One Bites the Dust", + "1168": "Turtle Power", + "1170": "Crab Mentality", + "1171": "Independence Ray", + "1172": "Never Say Daimyo" + } + }, + "422": { + "name": "Yanxia", + "fates": { + "1106": "Foxy Lady", + "1107": "Foxy Lady", + "1108": "Foxy Lady", + "1109": "Outfoxed", + "1110": "Freedom Flies", + "1111": "More to Offer", + "1208": "A Tisket, A Tasket", + "1209": "A Fish to Fry", + "1210": "Falling Drown", + "1211": "Scared Straightheart", + "1212": "Wolves of a Feather", + "1213": "Goodwill Hunterling", + "1214": "Stay of Eggsecution", + "1215": "Get Ready for a Nu Wave", + "1216": "Deep Red Sea", + "1217": "To Catch a Weasel", + "1218": "Footing the Bills", + "1219": "Tiger Need", + "1220": "Leave the Meters Running", + "1221": "The Long and Rhino Road", + "1222": "Raze the Red Lantern", + "1223": "Long Hands, Long Fingers", + "1224": "Rice and Shine", + "1225": "In One Basket", + "1226": "Tsurubebi Snugly", + "1227": "Motherly Love", + "1228": "Killer Apsaras", + "1229": "Linquan Continental", + "1230": "This Is a Da, This Is a Peng", + "1231": "Oneblade Wonder", + "1232": "Mister Whiskers", + "1233": "Crying Wolves", + "1234": "Mada`s Ilk", + "1235": "Tora Tora Tora", + "1236": "Ragoh to Extremes", + "1237": "Très Bian", + "1238": "Curiosity Killed the Catfish", + "1239": "The Virgin Homicides", + "1240": "Dead to Rites: Kiyofusa", + "1241": "Dead to Rites: Koja" + } + }, + "423": { + "name": "The Azim Steppe", + "fates": { + "1242": "Don`t You Mean Kirata", + "1243": "The State of Reunion", + "1244": "Cold Comes the Wind", + "1245": "A Tall Order", + "1246": "Duck and Cover", + "1247": "Feel the Noise", + "1248": "Get Out the Vochu", + "1249": "Buzzkill", + "1250": "A Good Day to Die", + "1251": "Wooly Boys", + "1252": "Razing the Baras", + "1253": "The Fangover", + "1254": "Hat`s Off", + "1255": "Rock for Food", + "1256": "Purbol Reign", + "1257": "Eat You Better", + "1258": "Man to Mangas", + "1259": "Not Just a Tribute", + "1260": "Good Day to Mate", + "1261": "Killing Dzo", + "1262": "Burn After Evening", + "1263": "Hey, Manzasiri", + "1264": "Khan Artist", + "1265": "Hook, Like, and Stinker", + "1266": "Fired", + "1267": "Wham, Bam, Thank You, Mammoth", + "1268": "More than You Chaochu", + "1269": "They Shall Not Want", + "1270": "A Walk Through the Valley", + "1271": "Live for the Mettle", + "1306": "The Dataqi Chronicles: Departures", + "1307": "The Dataqi Chronicles: Distractions", + "1308": "The Dataqi Chronicles: Duty", + "1309": "The Dataqi Chronicles: Deprivation", + "1310": "The Dataqi Chronicles: Deterrence", + "1311": "The Dataqi Chronicles: Desperation", + "1312": "The Dataqi Chronicles: Distress", + "1313": "The Dataqi Chronicles: Displacement", + "1315": "The Dataqi Chronicles: Diplomacy", + "1316": "The Dataqi Chronicles: Decimation", + "1318": "The Dataqi Chronicles: Divergence", + "1319": "The Dataqi Chronicles: Declarations", + "1320": "The Dataqi Chronicles: Dominion" + } + }, + "501": { + "name": "Lakeland", + "fates": { + "1496": "Looming Nightshade", + "1497": "Creeping Nightshade", + "1498": "Draconian Measures", + "1499": "Cry Not Wolf", + "1500": "Pick-up Sticks", + "1501": "Flowering Nightshade", + "1502": "Subtle Nightshade", + "1503": "Toxic Nightshade", + "1504": "Deadly Nightshade", + "1505": "Economic Peril", + "1506": "Don`t Feed the Gremlins", + "1507": "A Beast among Men", + "1508": "Little Gate of Horrors", + "1509": "Behind Anemone Lines", + "1510": "Calm a Chameleon" + } + }, + "502": { + "name": "Kholusia", + "fates": { + "1462": "Foes Most Formidable", + "1463": "A Family Most Formidable", + "1464": "A Finale Most Formidable", + "1465": "Shadow Over Stilltide", + "1466": "Shadow Over Stilltide", + "1467": "The Wright Stuff", + "1468": "The Wright Stuff", + "1469": "Bitter Barley", + "1470": "JELL-NO", + "1471": "Roadside Dinner", + "1472": "One-punch Mantis", + "1473": "Knockout", + "1474": "Season of Our Discord", + "1475": "The Amity Village Horror", + "1476": "Not Today", + "1477": "Ironbeard Builders - Rebuilt", + "1478": "Ironbeard Builders - Resist", + "1479": "Ironbeard Builders - Revolt" + } + }, + "503": { + "name": "Amh Araeng", + "fates": { + "1511": "Scavengers Hunted", + "1512": "Reptilian Roadblock", + "1513": "Cactus Makes Perfect", + "1514": "Theft from Above", + "1515": "Sand and Deliver", + "1516": "This Time, It`s Personal", + "1517": "Armadillo Peccadillo", + "1518": "The Elderblade", + "1519": "Harbingers of Bloom", + "1520": "Pray Destroy the Waking Sands", + "1521": "Tolba No. 1", + "1522": "Bayawak Attack", + "1523": "Bloody Simple", + "1524": "Baddie Longlegs", + "1525": "The Odd Couple", + "1526": "Anti-eruption Measures", + "1527": "Let`s Dance (with Swords)" + } + }, + "504": { + "name": "Il Mheg", + "fates": { + "1480": "Frog Standard", + "1481": "Great Daens", + "1482": "Fuath of Habit", + "1483": "Back and Fuath", + "1484": "Brute Fuath", + "1485": "Breaking the Fuath Wall", + "1486": "Go Fuath a Conqueror", + "1487": "Fuath to Be Reckoned With", + "1488": "Mad Magic", + "1489": "Bear Necessities", + "1490": "Weave `Em and Weep", + "1491": "Locus Terribilis", + "1492": "Twice Upon a Time", + "1493": "Hedge Mazed", + "1494": "Thrice Upon a Time", + "1495": "Once Upon a Time", + "1531": "Great Daens", + "1532": "Fuath of Habit", + "1533": "Back and Fuath" + } + }, + "505": { + "name": "The Rak`tika Greatwood", + "fates": { + "1441": "Barking Mad", + "1442": "Creepy Crawlers", + "1443": "Pluck of the Draw", + "1444": "The End of the Sentry", + "1445": "Tojil War", + "1446": "Tojil Annihilation", + "1447": "Tojil Annihilation", + "1448": "Tojil Carnage", + "1449": "Tojil Carnage", + "1450": "Tojil Eclipse", + "1451": "I`ll Be Bark", + "1452": "We Are Venom", + "1453": "Picking up the Pieces", + "1454": "Six Fulm Turkeys", + "1455": "Dark Matters", + "1456": "Attack of the Killer Tomatl", + "1457": "Queen of the Harpies", + "1458": "Nest of Kin", + "1459": "Monkeying Around", + "1460": "Shot Through the Hart", + "1461": "Attack the Block", + "1528": "Tojil Carnage", + "1529": "Tojil Carnage", + "1530": "Tojil Eclipse" + } + }, + "506": { + "name": "The Tempest", + "fates": { + "1426": "Where Has the Dagon", + "1427": "Ondo of Blood", + "1428": "Lookin` Back on the Track", + "1429": "Coral Support", + "1430": "Low Coral Fiber", + "1431": "Nothing Like a Trappin` Life", + "1432": "The Head, the Tail, the Whole Damned Thing", + "1433": "The Devil in the Deep Blue Sea", + "1434": "The Seashells He Sells", + "1435": "Pearls Apart", + "1436": "My Friend`s Enemy is Anemone of Mine", + "1437": "The Nets Best Thing", + "1438": "Hydrozoan of the Enders", + "1439": "A Lot to Swallow", + "1440": "Natural Prawn Killers" + } + }, + "996": { + "name": "Hydatos", + "fates": { + "1412": "I Ink, Therefore I Am", + "1413": "From Tusk till Dawn", + "1414": "Bullheaded Berserker", + "1415": "Mad, Bad, and Fabulous to Know", + "1416": "Fearful Symmetry", + "1417": "Crawling Chaos", + "1418": "Duty-free", + "1419": "Leukewarm Reception", + "1420": "Robber Barong", + "1421": "Stone-cold Killer", + "1422": "The Baldesion Arsenal: Expedition Support", + "1423": "Crystalline Provenance", + "1424": "I Don`t Want to Believe", + "1425": "Drink Me" + } + }, + "997": { + "name": "Pyros", + "fates": { + "1388": "Medias Res", + "1389": "High Voltage", + "1390": "On the Non-existent", + "1391": "Creepy Doll", + "1392": "Quiet, Please", + "1393": "Up and Batym", + "1394": "Rondo Aetolus", + "1395": "Scorchpion King", + "1396": "Burning Hunger", + "1397": "Dry Iris", + "1398": "Thirty Whacks", + "1399": "Put Up Your Dux", + "1400": "You Do Know Jack", + "1401": "Mister Bright-eyes", + "1402": "Haunter of the Dark", + "1403": "Heavens` Warg", + "1404": "Lost Epic", + "1407": "We`re All Mad Here", + "1408": "Uncommon Nonsense" + } + }, + "998": { + "name": "Pagos", + "fates": { + "1351": "Eternity", + "1352": "Cows for Concern", + "1353": "Ash the Magic Dragon", + "1354": "Conqueror Worm", + "1355": "Melting Point", + "1356": "Disorder in the Court", + "1357": "Does It Have to Be a Snowman", + "1358": "Brothers", + "1359": "Eye of Horus", + "1360": "Morte Arthro", + "1361": "Apocalypse Cow", + "1362": "Third Impact", + "1363": "Eye Scream for Ice Cream", + "1364": "Louhi on Ice", + "1365": "Cassie and the Copycats", + "1366": "The Wobbler in Darkness", + "1367": "Down the Rabbit Hole", + "1368": "Curiouser and Curiouser", + "1369": "Cairn Blight 451" + } + }, + "999": { + "name": "Anemos", + "fates": { + "1328": "The Swarm Never Sets", + "1329": "Wall in the Willows", + "1331": "Wine and Honey", + "1332": "Unsafety Dance", + "1333": "Teles House", + "1334": "Prove Your Amemettle", + "1335": "Caym What May", + "1336": "The Killing of a Sacred Bombardier", + "1337": "Sing, Muse", + "1338": "Drama Lamashtu", + "1339": "Short Serket 2", + "1340": "I Amarok", + "1341": "To the Mat", + "1342": "Simurghasbord", + "1343": "When You Ride Alone", + "1344": "One Missed Callisto", + "1345": "Disinherit the Wind", + "1346": "Don`t Judge Me, Morbol", + "1347": "By Numbers", + "1348": "The Shadow over Anemos" + } + }, + "1001": { + "name": "The Bozjan Southern Front", + "fates": { + "1597": "Sneak & Spell", + "1598": "None of Them Knew They Were Robots", + "1599": "The Bests Must Die", + "1600": "Unrest for the Wicked", + "1601": "{More Machine Now than Man}", + "1602": "Can Carnivorous Plants", + "1603": "Seeq and Destroy", + "1604": "{All Pets Are Off}", + "1605": "Conflicting with the First Law", + "1606": "Brought to Heal", + "1607": "The Monster Mash", + "1608": "{Red(Chocobo) Alert}", + "1609": "{Unicorn Flakes}", + "1610": "Parts and Recreation", + "1611": "The Element of Supplies", + "1612": "Heavy Boots of Lead", + "1613": "No Camping Allowed", + "1614": "Scavengers of Human Sorrow", + "1615": "Help Wanted", + "1616": "{Pyromancer Supreme}", + "1617": "Waste the Rainbow", + "1618": "The Wild Bunch", + "1619": "My Family and Other Animals", + "1620": "{I'm Mechanical Man}", + "1621": "Murder Death Kill", + "1622": "Desperately Seeking Something", + "1623": "Supplies Party", + "1624": "Demonstrably Demonic", + "1625": "For Absent Friend", + "1626": "{Of Steel and Flame}", + "1627": "Let Slip the Dogs of War", + "1628": "The War Against the Machines", + "30000": "The Battle of Castrum Lacus Litore ", + "30001": "Kill It with Fire", + "30002": "The Baying of the Hound(s)", + "30003": "Vigil for the Lost ", + "30004": "Aces High", + "30005": "The Shadow of Death's Hand ", + "30006": "The Final Furlong", + "30007": "The Hunt for Red Choctober ", + "30008": "Beast of Man", + "30009": "The Fires of War", + "30010": "Patriot Games", + "30011": "Trampled under Hoof", + "30012": "And the Flames Went Higher ", + "30013": "Metal Fox Chaos", + "30014": "Rise of the Robots", + "30015": "Where Strode the Behemoth " + } + } + } +} diff --git a/Data/DcDuty-Japanese.json b/Data/DcDuty-Japanese.json new file mode 100644 index 0000000..5b06441 --- /dev/null +++ b/Data/DcDuty-Japanese.json @@ -0,0 +1,1778 @@ +{ + "version": "202102171", + "language": "日本語", + "roulettes": { + "1": "レベリング", + "2": "レベル50・60・70ダンジョン", + "3": "メインクエスト", + "4": "ギルドオーダー", + "5": "エキスパート", + "6": "討伐・討滅戦", + "7": "フロントライン", + "8": "レベル80ダンジョン", + "9": "メンター", + "10": "ザ・フィースト (カジュアルマッチ)", + "11": "ザ・フィースト (カジュアルマッチ)", + "13": "ザ・フィースト (ランクマッチ)", + "15": "アライアンスレイド", + "16": "ザ・フィースト (チームランクマッチ)", + "17": "ノーマルレイド", + "18": "チョコボレース:サゴリーロード", + "19": "チョコボレース:コスタ・デル・ソル", + "20": "チョコボレース:トランキルパス", + "21": "チョコボレース:コースルーレット", + "22": "チョコボレース:サゴリーロード (報酬なし)", + "23": "チョコボレース:コスタ・デル・ソル (報酬なし)", + "24": "チョコボレース:トランキルパス (報酬なし)", + "25": "チョコボレース:コースルーレット (報酬なし)", + "26": "チョコボレース:コースルーレット", + "27": "チョコボレース:コースルーレット", + "28": "チョコボレース:コースルーレット", + "29": "チョコボレース:コースルーレット", + "30": "チョコボレース:コースルーレット", + "31": "チョコボレース:コースルーレット", + "32": "チョコボレース:コースルーレット", + "33": "チョコボレース:コースルーレット", + "34": "チョコボレース:コースルーレット", + "35": "チョコボレース:コースルーレット", + "36": "チョコボレース:コースルーレット", + "37": "チョコボレース:コースルーレット", + "38": "チョコボレース:コースルーレット" + }, + "instances": { + "1": "監獄廃墟 トトラクの千獄", + "2": "地下霊殿 タムタラの墓所", + "3": "封鎖坑道 カッパーベル銅山", + "4": "天然要害 サスタシャ浸食洞", + "5": "霧中行軍 オーラムヴェイル", + "6": "名門屋敷 ハウケタ御用邸", + "7": "魔獣領域 ハラタリ修練所", + "8": "奪還支援 ブレイフロクスの野営地", + "9": "遺跡探索 カルン埋没寺院", + "10": "旅神聖域 ワンダラーパレス", + "11": "城塞攻略 ストーンヴィジル", + "12": "流砂迷宮 カッターズクライ", + "13": "掃討作戦 ゼーメル要塞", + "14": "邪教排撃 古城アムダプール", + "15": "外郭攻略 カストルム・メリディアヌム", + "16": "最終決戦 魔導城プラエトリウム", + "17": "怪鳥巨塔 シリウス大灯台", + "18": "封鎖坑道 カッパーベル銅山 (Hard)", + "19": "名門屋敷 ハウケタ御用邸 (Hard)", + "20": "奪還支援 ブレイフロクスの野営地 (Hard)", + "21": "魔獣領域 ハラタリ修練所 (Hard)", + "22": "腐敗遺跡 古アムダプール市街", + "23": "財宝伝説 ハルブレーカー・アイル", + "24": "地下霊殿 タムタラの墓所 (Hard)", + "25": "城塞攻略 ストーンヴィジル (Hard)", + "26": "遺跡救援 カルン埋没寺院 (Hard)", + "27": "氷結潜窟 スノークローク大氷壁", + "28": "天然要害 サスタシャ浸食洞 (Hard)", + "29": "邪教排撃 古城アムダプール (Hard)", + "30": "旅神聖域 ワンダラーパレス (Hard)", + "31": "禁書回収 グブラ幻想図書館", + "32": "幻龍残骸 黙約の塔", + "33": "神域浮島 ネバーリープ", + "34": "強硬突入 イシュガルド教皇庁", + "35": "博物戦艦 フラクタル・コンティニアム", + "36": "廃砦捜索 ダスクヴィジル", + "37": "霊峰踏破 ソーム・アル", + "38": "蒼天聖戦 魔科学研究所", + "39": "邪竜血戦 ドラゴンズエアリー", + "40": "怪鳥巨塔 シリウス大灯台 (Hard)", + "41": "草木庭園 聖モシャーヌ植物園", + "42": "集団戦訓練をくぐり抜けろ!", + "43": "彷徨う死霊を討て!", + "44": "全関門を突破し、最深部の敵を討て!", + "45": "ギルガメを捕獲せよ!", + "46": "有毒妖花を駆除せよ!", + "47": "無法者「似我蜂団」を撃滅せよ!", + "48": "夢幻のブラキシオを討て!", + "49": "爆弾魔ゴブリン軍団を撃滅せよ!", + "50": "汚染源モルボルを討て!", + "51": "坑道に現れた妖異ブソを討て!", + "52": "無敵の眷属を従えし、大型妖異を討て!", + "53": "ボムを率いる「ボムクイーン」を討て!", + "54": "不気味な陣形を組む妖異をせん滅せよ!", + "55": "三つ巴の巨人族を制し、遺物を守れ!", + "56": "イフリート討伐戦", + "57": "タイタン討伐戦", + "58": "ガルーダ討伐戦", + "59": "真イフリート討滅戦", + "60": "真タイタン討滅戦", + "61": "真ガルーダ討滅戦", + "62": "リットアティン強襲戦", + "63": "極イフリート討滅戦", + "64": "極タイタン討滅戦", + "65": "極ガルーダ討滅戦", + "66": "善王モグル・モグXII世討滅戦", + "67": "極王モグル・モグXII世討滅戦", + "68": "究極幻想 アルテマウェポン破壊作戦", + "72": "真リヴァイアサン討滅戦", + "73": "真リヴァイアサン討滅戦", + "74": "ドルムキマイラ討伐戦", + "75": "ハイドラ討伐戦", + "76": "ギルガメッシュ討伐戦", + "77": "真ラムウ討滅戦", + "78": "極ラムウ討滅戦", + "79": "真シヴァ討滅戦", + "80": "極シヴァ討滅戦", + "81": "アマジナ杯闘技会決勝戦", + "82": "闘神オーディン討滅戦", + "83": "皇都イシュガルド防衛戦", + "84": "アシエン・ナプリアレス討伐戦", + "85": "真ギルガメッシュ討滅戦", + "86": "真ラーヴァナ討滅戦", + "87": "極ラーヴァナ討滅戦", + "88": "真ビスマルク討滅戦", + "89": "極ビスマルク討滅戦", + "90": "ナイツ・オブ・ラウンド討滅戦", + "91": "蒼天幻想 ナイツ・オブ・ラウンド討滅戦", + "92": "クリスタルタワー:古代の民の迷宮", + "93": "大迷宮バハムート:邂逅編1", + "94": "大迷宮バハムート:邂逅編2", + "95": "大迷宮バハムート:邂逅編3", + "96": "大迷宮バハムート:邂逅編4", + "97": "大迷宮バハムート:邂逅編5", + "98": "大迷宮バハムート:侵攻編1", + "99": "大迷宮バハムート:侵攻編2", + "100": "大迷宮バハムート:侵攻編3", + "101": "大迷宮バハムート:侵攻編4", + "102": "クリスタルタワー:シルクスの塔", + "103": "大迷宮バハムート零式:侵攻編1", + "104": "大迷宮バハムート零式:侵攻編2", + "105": "大迷宮バハムート零式:侵攻編3", + "106": "大迷宮バハムート零式:侵攻編4", + "107": "大迷宮バハムート:真成編1", + "108": "大迷宮バハムート:真成編2", + "109": "大迷宮バハムート:真成編3", + "110": "大迷宮バハムート:真成編4", + "111": "クリスタルタワー:闇の世界", + "112": "機工城アレキサンダー:起動編1", + "113": "機工城アレキサンダー:起動編2", + "114": "機工城アレキサンダー:起動編3", + "115": "機工城アレキサンダー:起動編4", + "116": "機工城アレキサンダー零式:起動編1", + "117": "機工城アレキサンダー零式:起動編2", + "118": "機工城アレキサンダー零式:起動編3", + "119": "機工城アレキサンダー零式:起動編4", + "120": "魔航船ヴォイドアーク", + "127": "外縁遺跡群 (制圧戦)", + "130": "シールロック (争奪戦)", + "131": "ディアデム諸島(Easy)", + "132": "ディアデム諸島", + "133": "ディアデム諸島 (Hard)", + "134": "魔神セフィロト討滅戦", + "135": "極魔神セフィロト討滅戦", + "136": "機工城アレキサンダー:律動編1", + "137": "機工城アレキサンダー:律動編2", + "138": "機工城アレキサンダー:律動編3", + "139": "機工城アレキサンダー:律動編4", + "140": "神聖遺跡 古アムダプール市街 (Hard)", + "141": "星海観測 逆さの塔", + "143": "ザ・フィースト (4対4 / カジュアルマッチ)", + "145": "ザ・フィースト (4対4 / ランクマッチ)", + "147": "機工城アレキサンダー零式:律動編1", + "148": "機工城アレキサンダー零式:律動編2", + "149": "機工城アレキサンダー零式:律動編3", + "150": "機工城アレキサンダー零式:律動編4", + "151": "範囲攻撃を避けよう!", + "152": "コンボで敵視を集めよう!", + "153": "実戦でコンボに挑戦しよう!", + "154": "複数の敵から敵視を集めよう!", + "155": "実戦で複数の敵と戦ってみよう!", + "156": "遠距離から敵視を集めよう!", + "157": "敵の増援に対応しよう!", + "158": "味方と協力して敵を倒そう!", + "159": "味方が引きつけている敵を倒そう!", + "160": "敵の攻撃を避けながら戦おう!", + "161": "敵の増援に対応しよう!", + "162": "ギミックを活用して戦おう!", + "163": "味方を回復しよう!", + "164": "複数の味方を回復しよう!", + "165": "敵の攻撃を避けながら戦おう!", + "166": "最終訓練!", + "168": "禁忌都市マハ", + "169": "ニーズヘッグ征竜戦", + "170": "極ニーズヘッグ征竜戦", + "171": "天竜宮殿 ソール・カイ", + "172": "財宝伝説 ハルブレーカー・アイル (Hard)", + "174": "死者の宮殿 B1~B10", + "175": "死者の宮殿 B11~B20", + "176": "死者の宮殿 B21~B30", + "177": "死者の宮殿 B31~B40", + "178": "死者の宮殿 B41~B50", + "179": "宝物庫 アクアポリス", + "180": "フィールド・オブ・グローリー (砕氷戦)", + "181": "亡霊屋敷 ホーンテッドマナー", + "182": "峻厳渓谷 ゼルファトル", + "183": "女神ソフィア討滅戦", + "184": "極女神ソフィア討滅戦", + "186": "機工城アレキサンダー:天動編1", + "187": "機工城アレキサンダー:天動編2", + "188": "機工城アレキサンダー:天動編3", + "189": "機工城アレキサンダー:天動編4", + "190": "機工城アレキサンダー零式:天動編1", + "191": "機工城アレキサンダー零式:天動編2", + "192": "機工城アレキサンダー零式:天動編3", + "193": "機工城アレキサンダー零式:天動編4", + "195": "トリプルトライアド", + "196": "禁書回収 グブラ幻想図書館 (Hard)", + "201": "ザ・フィースト (ウルヴズジェイル演習場:カスタムマッチ)", + "204": "死者の宮殿 B51~B60", + "205": "死者の宮殿 B61~B70", + "206": "死者の宮殿 B71~B80", + "207": "死者の宮殿 B81~B90", + "208": "死者の宮殿 B91~B100", + "209": "死者の宮殿 B101~B110", + "210": "死者の宮殿 B111~B120", + "211": "死者の宮殿 B121~B130", + "212": "死者の宮殿 B131~B140", + "213": "死者の宮殿 B141~B150", + "214": "死者の宮殿 B151~B160", + "215": "死者の宮殿 B161~B170", + "216": "死者の宮殿 B171~B180", + "217": "死者の宮殿 B181~B190", + "218": "死者の宮殿 B191~B200", + "219": "巨大防壁 バエサルの長城", + "220": "影の国ダン・スカー", + "221": "霊峰踏破 ソーム・アル (Hard)", + "223": "鬼神ズルワーン討滅戦", + "224": "極鬼神ズルワーン討滅戦", + "228": "ザ・フィースト (4対4 / カジュアルマッチ)", + "230": "ザ・フィースト (4対4 / ランクマッチ)", + "233": "ザ・フィースト (ライケンウィード演習場:カスタムマッチ)", + "235": "海底宮殿 紫水宮", + "236": "壊神修行 星導山寺院", + "238": "漂流海域 セイレーン海", + "239": "神龍討滅戦", + "240": "伝統試練 バルダム覇道", + "241": "解放決戦 ドマ城", + "242": "巨砲要塞 カストルム・アバニア", + "243": "スサノオ討滅戦", + "244": "極スサノオ討滅戦", + "247": "紅蓮決戦 アラミゴ", + "252": "次元の狭間オメガ:デルタ編1", + "253": "次元の狭間オメガ:デルタ編2", + "254": "次元の狭間オメガ:デルタ編3", + "255": "次元の狭間オメガ:デルタ編4", + "256": "次元の狭間オメガ零式:デルタ編1", + "257": "次元の狭間オメガ零式:デルタ編2", + "258": "次元の狭間オメガ零式:デルタ編3", + "259": "次元の狭間オメガ零式:デルタ編4", + "262": "悪党成敗 クガネ城", + "263": "ラクシュミ討滅戦", + "264": "極ラクシュミ討滅戦", + "268": "宝物庫 ウズネアカナル", + "276": "宝物庫 ウズネアカナル深層", + "277": "アストラガロス (機工戦)", + "278": "極神龍討滅戦", + "279": "水没遺構 スカラ", + "280": "絶バハムート討滅戦", + "281": "失われた都 ラバナスタ", + "283": "禁断の地 エウレカ:アネモス編", + "284": "紅玉火山 獄之蓋", + "285": "博物戦艦 フラクタル・コンティニアム (Hard)", + "286": "次元の狭間オメガ:シグマ編1", + "287": "次元の狭間オメガ:シグマ編2", + "288": "次元の狭間オメガ:シグマ編3", + "289": "次元の狭間オメガ:シグマ編4", + "290": "白虎精魂戰", + "291": "極白虎精魂戰", + "292": "次元の狭間オメガ零式:シグマ編1", + "293": "次元の狭間オメガ零式:シグマ編2", + "294": "次元の狭間オメガ零式:シグマ編3", + "295": "次元の狭間オメガ零式:シグマ編4", + "473": "The Valentione`s Ceremony", + "474": "リオレウス狩猟戦", + "475": "極リオレウス狩猟戦", + "476": "ザ・フィースト (チーム用ランクマッチ)", + "478": "ザ・フィースト (ランクマッチ)", + "479": "ザ・フィースト (カジュアルマッチ)", + "480": "ザ・フィースト (クリスタルタワー演習場:カスタムマッチ)", + "481": "チョコボレース:チュートリアル", + "482": "第1節:インコースを狙え", + "483": "第2節:範囲攻撃を避けろ", + "484": "第3節:アビリティに頼るな", + "485": "第4節:ヘヴィなレース", + "486": "第5節:とんずらを阻止せよ", + "487": "第6節:ライバルを叩け", + "488": "第7節:フィールド・オブ・ドリームズ", + "489": "第8節:漁夫の利を狙え", + "490": "第9節:スタミナの戦い", + "491": "第10節:逃げる者と追う者と", + "492": "第11節:全速で駆け抜けろ", + "493": "第12節:アビリティを駆使せよ", + "494": "第13節:連携プレイに勝利せよ", + "495": "第14節:続ヘヴィなレース", + "496": "第15節:究極のレース", + "497": "チョコボレース:サゴリーロード", + "498": "チョコボレース:コスタ・デル・ソル", + "499": "チョコボレース:トランキルパス", + "500": "チョコボレース:サゴリーロード", + "501": "チョコボレース:コスタ・デル・ソル", + "502": "チョコボレース:トランキルパス", + "503": "チョコボレース:サゴリーロード", + "504": "チョコボレース:コスタ・デル・ソル", + "505": "チョコボレース:トランキルパス", + "506": "チョコボレース:サゴリーロード", + "507": "チョコボレース:コスタ・デル・ソル", + "508": "チョコボレース:トランキルパス", + "509": "チョコボレース:サゴリーロード", + "510": "チョコボレース:コスタ・デル・ソル", + "511": "チョコボレース:トランキルパス", + "512": "チョコボレース:サゴリーロード", + "513": "チョコボレース:コスタ・デル・ソル", + "514": "チョコボレース:トランキルパス", + "515": "チョコボレース:サゴリーロード", + "516": "チョコボレース:コスタ・デル・ソル", + "517": "チョコボレース:トランキルパス", + "518": "チョコボレース:サゴリーロード", + "519": "チョコボレース:コスタ・デル・ソル", + "520": "チョコボレース:トランキルパス", + "521": "チョコボレース:サゴリーロード", + "522": "チョコボレース:コスタ・デル・ソル", + "523": "チョコボレース:トランキルパス", + "524": "チョコボレース:サゴリーロード", + "525": "チョコボレース:コスタ・デル・ソル", + "526": "チョコボレース:トランキルパス", + "527": "チョコボレース:サゴリーロード", + "528": "チョコボレース:コスタ・デル・ソル", + "529": "チョコボレース:トランキルパス", + "530": "チョコボレース:サゴリーロード", + "531": "チョコボレース:コスタ・デル・ソル", + "532": "チョコボレース:トランキルパス", + "533": "チョコボレース:サゴリーロード", + "534": "チョコボレース:コスタ・デル・ソル", + "535": "チョコボレース:トランキルパス", + "536": "風水霊殿 ガンエン廟", + "537": "ツクヨミ討滅戦", + "538": "極ツクヨミ討滅戦", + "539": "絶アルテマウェポン破壊作戦", + "540": "アメノミハシラ (1-10)", + "541": "アメノミハシラ (11-20)", + "542": "アメノミハシラ (21-30)", + "543": "アメノミハシラ (31-40)", + "544": "アメノミハシラ (41-50)", + "545": "アメノミハシラ (51-60)", + "546": "アメノミハシラ (61-70)", + "547": "アメノミハシラ (71-80)", + "548": "アメノミハシラ (81-90)", + "549": "アメノミハシラ (91-100)", + "550": "封じられた聖塔 リドルアナ", + "552": "第1節:チュートリアル", + "553": "第2節:チョコチョコチョコチョコボ", + "554": "第3節:序盤にありそうな戦い", + "555": "第4節:小さな巨獣", + "556": "第5節:蛮族たちの反乱", + "557": "第6節:恐怖、タラタラの墓所", + "558": "第7節:ライバルたちの共闘", + "559": "第8節:暁は光と闇とを分かつ", + "560": "第9節:爆破、カパカパベル銅山", + "561": "第10節:マンドラ帝国の逆襲", + "562": "第11節:女王陛下万歳!", + "563": "第12節:デモンズブロック崩し", + "564": "第13節:筆頭機工師ガーロンド", + "565": "第14節:ナッツの味にはもう飽きた", + "566": "第15節:極小オーディン討滅戦", + "567": "第16節:チョコボ大行進", + "568": "第17節:融解、スノークローク小氷壁", + "569": "第18節:小さなモブハント", + "570": "第19節:極小ギルガメッシュ討滅戦", + "571": "第20節:汝にクリスタルの導きあれ", + "572": "第21節:賢人ルイゾワの試練", + "573": "第22節:薄闇の世界", + "574": "第23節:大迷惑バハムート邂逅編", + "575": "第24節:大迷惑バハムート真成編", + "576": "LoVM:ミニオンクラス (Easy)", + "577": "LoVM:真ミニオンクラス (Normal)", + "578": "LoVM:極ミニオンクラス (Hard)", + "579": "LoVM:大会対戦 (CPU対戦)", + "580": "ザ・フィースト (クリスタルタワー演習場:チーム用カスタムマッチ)", + "581": "禁断の地 エウレカ:パゴス編", + "584": "草木汚染 聖モシャーヌ植物園 (Hard)", + "585": "永久焦土 ザ・バーン", + "587": "次元の狭間オメガ:アルファ編1", + "588": "次元の狭間オメガ:アルファ編2", + "589": "次元の狭間オメガ:アルファ編3", + "590": "次元の狭間オメガ:アルファ編4", + "591": "次元の狭間オメガ零式:アルファ編1", + "592": "次元の狭間オメガ零式:アルファ編2", + "593": "次元の狭間オメガ零式:アルファ編3", + "594": "次元の狭間オメガ零式:アルファ編4", + "595": "真ヨウジンボウ討滅戦", + "596": "朱雀征魂戦", + "597": "極朱雀征魂戦", + "598": "禁断の地 エウレカ:ピューロス編", + "599": "ヒデン・ゴージ", + "600": "挑戦!ジャンピングアスレチック", + "601": "挑戦!ジャンピングアスレチック", + "602": "挑戦!ジャンピングアスレチック", + "603": "挑戦!ジャンピングアスレチック", + "604": "挑戦!ジャンピングアスレチック", + "605": "挑戦!ジャンピングアスレチック", + "606": "挑戦!ジャンピングアスレチック", + "607": "挑戦!ジャンピングアスレチック", + "608": "挑戦!ジャンピングアスレチック", + "610": "デビューマッチ", + "611": "境界戦線 ギムリトダーク", + "612": "プリン・アラモード", + "613": "最初の岩壁「シパクナー」", + "614": "怪力の鉄巨人「クレイオス」", + "615": "ギルガメブラザーズ", + "616": "ブラインド・フューリー", + "617": "シアーハートアタック", + "618": "青い牙、赤い牙", + "619": "七色の甘味「ギモーヴ」", + "620": "偶像の王者「クロムドゥーブ」", + "621": "爆ボム・ファーストアタック", + "622": "寄生植物「ヒドノラ」", + "623": "紅の死妖姫「カーミラ」", + "624": "死なばもろともーッ!", + "625": "アラグの脅威「闘獣システム」", + "626": "豪腕の獣王「ティクバラン」", + "627": "豪柔の鉄巨人「クレイオス改」", + "628": "爆破デスマッチ", + "629": "魅惑の芳香「リフレクティブ・レベッカ」", + "630": "名コンビ「オルトロス&テュポーン」", + "631": "憤怒の合成獣「アペデマク」", + "632": "爆発の対消滅「グランパボム」", + "633": "魔獣の皇太子「クロンプリンツ・ベヒーモス」", + "634": "異形の人形師「エペロギ」", + "635": "悪の青魔道士「アポカリョープス」", + "636": "楽欲の僧院 オーボンヌ", + "637": "青龍征魂戦", + "638": "極青龍征魂戦", + "639": "禁断の地 エウレカ:ヒューダトス編", + "640": "出撃! エアフォースパイロット", + "641": "出撃! エアフォースパイロット", + "642": "出撃! エアフォースパイロット", + "643": "ドマ式麻雀:一般卓(段位変動有り)", + "644": "ドマ式麻雀:有段卓(段位変動有り)", + "645": "ドマ式麻雀:4人セット卓(クイタン有り)", + "649": "水妖幻園 ドォーヌ・メグ", + "650": "ドマ式麻雀:4人セット卓(クイタン無し)", + "651": "古跡探索 キタンナ神影洞", + "652": "終末幻想 アーモロート", + "653": "希望の園エデン:覚醒編1", + "654": "希望の園エデン零式:覚醒編1", + "655": "異界遺構 シルクス・ツイニング", + "656": "爽涼離宮 マリカの大井戸", + "657": "ティターニア討滅戦", + "658": "極ティターニア討滅戦", + "659": "偽造天界 グルグ火山", + "661": "創造機関 アナイダアカデミア", + "666": "イノセンス討滅戦", + "667": "極イノセンス討滅戦", + "676": "殺戮郷村 ホルミンスター", + "682": "希望の園エデン:覚醒編3", + "683": "希望の園エデン零式:覚醒編3", + "684": "希望の園エデン:覚醒編2", + "685": "希望の園エデン零式:覚醒編2", + "687": "ハーデス討滅戦", + "689": "希望の園エデン:覚醒編4", + "690": "希望の園エデン零式:覚醒編4", + "692": "魔法宮殿 グラン・コスモス", + "693": "極ハーデス討滅戦", + "694": "絶アレキサンダー討滅戦", + "695": "フンババ・パパ", + "696": "はないき爆破デスマッチ", + "697": "至妙の傀儡子「ドゥリン」", + "698": "水と炎の歌", + "699": "ジークフリード", + "700": "複製サレタ工場廃墟", + "701": "オンサル・ハカイル (終節戦)", + "702": "白き誓約、黒き密約", + "703": "この心が望むがままに", + "705": "挑戦! ジャンピングアスレチック", + "706": "挑戦! ジャンピングアスレチック", + "707": "挑戦! ジャンピングアスレチック", + "708": "挑戦! ジャンピングアスレチック", + "709": "挑戦! ジャンピングアスレチック", + "710": "挑戦! ジャンピングアスレチック", + "711": "挑戦! ジャンピングアスレチック", + "712": "挑戦! ジャンピングアスレチック", + "713": "挑戦! ジャンピングアスレチック", + "714": "黒風海底 アニドラス・アナムネーシス", + "715": "希望の園エデン:共鳴編1", + "716": "希望の園エデン零式:共鳴編1", + "717": "ルビーウェポン破壊作戦", + "718": "極ルビーウェポン破壊作戦", + "719": "希望の園エデン:共鳴編2", + "720": "希望の園エデン零式:共鳴編2", + "721": "オーシャンフィッシング", + "722": "雲海採集 ディアデム諸島", + "724": "汝、英雄の眠り妨げるは", + "725": "極シタデル・ボズヤ追憶戦", + "726": "希望の園エデン:共鳴編3", + "727": "希望の園エデン零式:共鳴編3", + "728": "希望の園エデン:共鳴編4", + "729": "希望の園エデン零式:共鳴編4", + "730": "オーシャンフィッシング", + "731": "オーシャンフィッシング", + "732": "オーシャンフィッシング", + "733": "オーシャンフィッシング", + "734": "オーシャンフィッシング", + "735": "南方ボズヤ戦線", + "736": "人形タチノ軍事基地", + "737": "漆黒決戦 ノルヴラント", + "738": "ウォーリア・オブ・ライト討滅戦", + "739": "極ウォーリア・オブ・ライト討滅戦", + "742": "雲海採集 ディアデム諸島", + "744": "幻シヴァ討滅戦", + "745": "宝物庫 リェー・ギア・ダンジョン祭殿", + "746": "魔術工房 マトーヤのアトリエ", + "747": "希望の園エデン:再生編2", + "748": "希望の園エデン零式:再生編2", + "749": "希望の園エデン:再生編1", + "750": "希望の園エデン零式:再生編1", + "751": "希望の園エデン:再生編3", + "752": "希望の園エデン零式:再生編3", + "753": "雲海採集 ディアデム諸島", + "754": "Anything Gogo's", + "755": "トリプルトライアド:オフィシャルトーナメント", + "756": "トリプルトライアド:カスタムトーナメントルーム", + "757": "幻タイタン討滅戦", + "758": "希望の園エデン:再生編4", + "759": "希望の園エデン零式:再生編4", + "762": "エメラルドウェポン破壊作戦", + "763": "極エメラルドウェポン破壊作戦", + "766": "ドマ式麻雀:東風戦一般卓(段位変動有り)", + "767": "ドマ式麻雀:東風戦有段卓(段位変動有り)", + "768": "ドマ式麻雀:東風戦4人セット卓(クイタン有り)", + "769": "ドマ式麻雀:東風戦4人セット卓(クイタン無し)", + "770": "オーシャンフィッシング", + "771": "オーシャンフィッシング", + "772": "オーシャンフィッシング", + "773": "オーシャンフィッシング", + "774": "オーシャンフィッシング", + "775": "オーシャンフィッシング", + "760": "グンヒルド・ディルーブラム", + "761": "グンヒルド・ディルーブラム零式" + }, + "areas": { + "134": { + "name": "中央ラノシア", + "fates": { + "220": "巨躯の猛牛「メヌイス」", + "221": "サマーフォードの怪", + "222": "ヴェスパとイエロージャケット", + "223": "デネベール関門防衛訓練", + "225": "果てなきモグラ叩き", + "226": "海軍式の通過儀礼", + "227": "羊たちの騒乱", + "229": "上には上がある", + "231": "切断狂「シアリング・シェリダン」", + "233": "追う者と追われる者", + "235": "その水棲動物を見よ", + "237": "農場にかける橋", + "238": "血濡れの猛犬「チュパカブラ」", + "239": "麗しのローグ川", + "240": "クラゲが飛んだ日", + "533": "帰ってきた大炎獣「キングボンバード」", + "649": "その水棲動物を見よ", + "687": "黒い悪魔:実験の成果", + "688": "黒い悪魔:過激な淑女", + "693": "星芒祭:魔法の雪だるま", + "717": "ジャイアントエッグハント" + } + }, + "135": { + "name": "低地ラノシア", + "fates": { + "245": "不吉なる王子「マンドラプリンス」", + "246": "危ない野良仕事", + "249": "蛙の子は蛙", + "250": "黒い翼", + "251": "小麦粉戦争", + "257": "浮かぶ胃袋「クアハック」", + "260": "迷惑千万「密航のアクトシュティム」", + "261": "俺たちゃ海賊", + "262": "水場の争い", + "264": "シダーウッドの戦い", + "265": "精強なる山師「ピックマン426 ブ・ガ」", + "333": "豪然たる魔犬「パッドフット」", + "534": "帰ってきた大炎獣「キングボンバード」", + "666": "不思議な魔物「ゴーレム」", + "667": "不思議な魔物「ストーンマン」", + "694": "星芒祭:魔法の雪だるま", + "718": "ジャイアントエッグハント" + } + }, + "137": { + "name": "東ラノシア", + "fates": { + "267": "ワインよこせ!", + "268": "ワイン飲みてぇ!", + "271": "新鮮な生肉", + "272": "エッグモンスター", + "274": "ミクロの決死隊", + "278": "白い巨塔", + "279": "コリブリたちの食卓", + "280": "彷徨の業師「弾指のココルン」", + "282": "海辺のスニッパー", + "286": "死者の代弁者", + "287": "愛はさだめ、さだめは死", + "334": "夏への扉", + "335": "死顔の簒奪者「キャンサー」", + "532": "帰ってきた大炎獣「キングボンバード」", + "560": "野蛮な餓えた傭兵の反乱", + "561": "酒飲み魔獣「セクメト」", + "562": "蜜蜂誘う甘い蜜", + "563": "深緑の巨獣「ジョリーグリーン」", + "564": "不吉な球根「メツハルジャス」", + "565": "お家に帰ろう", + "566": "球根つぶし", + "689": "黒い悪魔:実験の成果", + "690": "黒い悪魔:過激な淑女", + "701": "狂乱のエッグハント", + "913": "紅蓮祭「良俗の守護者」", + "914": "紅蓮祭「一夏の熱狂」", + "915": "紅蓮祭「危険な火遊び」", + "916": "紅蓮祭「海獣の調教師」", + "917": "紅蓮祭「軟派者の末路」", + "918": "紅蓮祭「海賊の密造酒」", + "945": "-----", + "946": "-----" + } + }, + "138": { + "name": "西ラノシア", + "fates": { + "289": "補給線を支えろ", + "290": "暴食の怪鳥「グルタナスガーティ」", + "291": "小麦畑でつかまえて", + "295": "古強者「オールドシックスアームズ」", + "297": "税関公社の強制捜査", + "298": "敵は海賊・海蛇の舌", + "303": "故郷からの手紙", + "304": "ドードーの巣破壊命令", + "306": "死活の罠「バロメッツ」", + "308": "交渉決裂", + "309": "愚鈍な用心棒「間抜のトリップティックス」", + "310": "決闘デネベール街道", + "312": "昆虫軍団現わる", + "336": "野菜革命「マンドラーズ」", + "568": "北防波壁の戦い:威力偵察", + "569": "北防波壁の戦い:本隊強襲", + "570": "南防波壁の戦い:威力偵察", + "571": "南防波壁の戦い:本隊強襲", + "572": "冷徹なる戦略家「鮫肌のヴォル」", + "574": "海蛇の末路", + "575": "海蛇の船長「刻印のエルムスイス」", + "576": "死の行進", + "577": "異国の魔蟲「マンティスキング」", + "578": "水神呼びし者「水鬼のヤァル」", + "650": "暴食の怪鳥「グルタナスガーティ」", + "702": "賢者のタマゴ「ジョーカー・エッガー」" + } + }, + "139": { + "name": "高地ラノシア", + "fates": { + "314": "豹喰いの妖鳥「シームルグ」", + "317": "輸送部隊防衛命令", + "320": "昨日の友は今日の敵", + "321": "湯煙温泉殺貝事件", + "322": "石緑湖の主「オアンネス」", + "323": "脅威の元食材「カルキノス」", + "329": "温泉の申し子「ゾレドナイト」", + "331": "悲運の傭兵「美男のブガージャ」", + "332": "湖面を駆けろ!", + "451": "プアメイドミル復興:食料防衛", + "452": "プアメイドミル復興:ゲ・ブ排撃", + "453": "プアメイドミル復興:クァール討伐", + "454": "プアメイドミル復興:野牛討伐", + "668": "不思議な魔物「ゴーレム」", + "669": "不思議な魔物「ストーンマン」", + "670": "不思議な魔物「ゴーレム」", + "671": "不思議な魔物「ゴールドマン」", + "703": "狂乱のエッグハント" + } + }, + "140": { + "name": "西ザナラーン", + "fates": { + "342": "緊急停止", + "343": "強制立ち退き", + "344": "階級的怒りの鉄槌", + "345": "大地のハンマー", + "346": "ミッション・アース", + "347": "謎の巨大生物「ドゥーム・ギガントード」", + "348": "砂漠の覇王「カクター・ジャック」", + "349": "荒野の用心棒", + "350": "野良犬たちの挽歌", + "352": "罪のない残虐", + "353": "飽食の大蟹「バブリーバーニー」", + "354": "負傷者を護送せよ", + "355": "戦いは、なおも続いた", + "356": "コブラン族の大移動", + "357": "黄金兜の大巨人「悲嘆のブリアレオス」", + "361": "ハンマーチャンス", + "366": "足長おやじ「ダディーロングレッグ」", + "367": "ゴーストバスター", + "683": "黒い悪魔:実験の成果", + "684": "黒い悪魔:過激な淑女", + "704": "狂乱のエッグハント", + "911": "バグフィックス" + } + }, + "141": { + "name": "中央ザナラーン", + "fates": { + "370": "粗野な勝負師「無頼のグリスヒルド」", + "373": "夕飯を渡すな!", + "374": "底無の酒豪「飲んべえググルン」", + "375": "コッファー与えず、コフィンに送れ", + "376": "半熟英雄「半熟のババルン」", + "377": "殺人魚スポーニングキラー", + "378": "サボテンサラダ", + "379": "アリだー!", + "381": "キヴロン家の住人", + "383": "街道をゆく", + "385": "不浄なる大蝦蟇「ヴォジャノーイ」", + "389": "怒れる宝主「スピットファイア」", + "393": "砂城の猛将「ネストコマンダー」", + "535": "帰ってきた大炎獣「キングボンバード」", + "660": "不思議な魔物「ゴーレム」", + "661": "不思議な魔物「ストーンマン」", + "695": "星芒祭:魔法の雪だるま", + "719": "ジャイアントエッグハント", + "912": "バグフィックス" + } + }, + "145": { + "name": "東ザナラーン", + "fates": { + "191": "ハイブリッジの死闘:前哨戦", + "192": "ハイブリッジの死闘:防衛戦", + "193": "ハイブリッジの死闘:ズズルン排撃", + "194": "ハイブリッジの死闘:ナヨク・ロー排撃", + "195": "ハイブリッジの死闘:市民奪還作戦", + "394": "野獣死すべし", + "395": "その硬さ、鋼の如し", + "397": "アマルジャ軍迎撃作戦", + "398": "侵攻作戦を阻止せよ", + "400": "ゴールドバザー防衛戦", + "401": "煉獄の墓掘人「アンダーテイカー」", + "402": "盗賊もどきの成敗", + "406": "東部戦線異状なし", + "407": "毛髪の簒奪者「ゴッサマー」", + "409": "妖花前線", + "412": "楽園の泉", + "413": "長角の古老「エルダー・ロングホーン」", + "536": "帰ってきた大炎獣「キングボンバード」", + "540": "ワサワサドブラン", + "541": "鏡像の騎士", + "542": "金髪の貴公子「アイエテス」", + "543": "醜悪なる合成獣「バドゥ」", + "652": "閃光の影向:巨獣迎撃戦", + "696": "星芒祭:魔法の雪だるま", + "705": "賢者のタマゴ「ジョーカー・エッガー」", + "720": "ジャイアントエッグハント" + } + }, + "146": { + "name": "南ザナラーン", + "fates": { + "419": "骸の頭目「流転のミルウーダ」", + "420": "スープに肉を入れるため", + "421": "リトルアラミゴ防衛戦", + "422": "真理を解き明かせ", + "423": "大らかな圧殺者「アスピドケロン」", + "424": "我ら第二戦闘大隊", + "427": "怒濤の怪力「金剛のネゼド・ガー」", + "429": "砂漠の子供たち", + "430": "運命の代弁者「黒煙のペグジ・チャー」", + "431": "狩る者と狩られる者", + "432": "工神ビエルゴの守護者", + "434": "偵察兵の仕事", + "436": "無道の暗殺者「呪言のマラド・チャー」", + "437": "流れる砂の海", + "441": "まるで我が子の様に", + "455": "砂漠の神皇帝「ウルハドシ」", + "456": "持たざる者「破戒のギスフリッド」", + "545": "荒野の消火活動", + "546": "哀しき闘士「純鉄のビビレゼ」", + "548": "正義についての話をしよう", + "549": "甲羅を蹴飛ばせ!", + "550": "精鋭部隊「ゴアホード」", + "551": "今日の運勢", + "552": "友と、家族と", + "553": "第一関門攻略戦", + "554": "速射の名手「火打のハプグ・ロー」", + "555": "砂の上の足あと", + "557": "アマルジャ軍特殊部隊「炎牙衆」", + "558": "焔神呼びし者「火印のアファジ・コー」", + "651": "閃光の影向:巨獣迎撃戦", + "685": "黒い悪魔:実験の成果", + "686": "黒い悪魔:過激な淑女", + "706": "狂乱のエッグハント" + } + }, + "147": { + "name": "北ザナラーン", + "fates": { + "446": "虚像の眼「アリマスピ」", + "447": "爪切り", + "449": "火の用心", + "450": "新装甲採用機「魔導ヴァンガード試験型」", + "457": "リバースエンジニアリング", + "556": "青燐精製所のお手伝い", + "637": "灼熱の男爵「ボムバロン」", + "638": "ゴクゴクドブラン", + "639": "監視者の影", + "641": "鋼虫の罠", + "642": "セルリウムロード", + "643": "救世神の生贄:誘拐編", + "644": "救世神の生贄:待伏編", + "645": "救世神の生贄:誅殺編", + "646": "救世神の生贄:妖異編", + "647": "荒れ狂う巨獣「ゴーキマイラ」" + } + }, + "148": { + "name": "黒衣森中央森林", + "fates": { + "120": "森駆けるスプリンター", + "121": "楽しいキノコ狩り", + "122": "スプリガンのお引っ越し", + "123": "淀みの奔流「スタグナントスプライト」", + "124": "虫刺されにご用心", + "125": "人喰いの怪鳥「アシパトラ」", + "126": "健脚の暴君「アルファ・アノール」", + "127": "怒りの猪突猛進", + "128": "強大なる小鬼「アルシュ」", + "130": "エバーシェイドの収穫祭", + "131": "忘れ得ぬ地神の忘却", + "136": "怒れる教官「激高のミロードン」", + "137": "病毒の妖花「マタガイガイ」", + "138": "チョコチョコチョコチョコボ", + "139": "あなたの魂に安らぎあれ", + "140": "大脱走", + "141": "ガルヴァンス監視哨の援軍要請", + "142": "軟体の大食漢「ル・カルコル」", + "196": "古の闘神「オーディン」", + "197": "古の闘神「オーディン」", + "208": "レディキラー", + "209": "水源の破壊者「ジェイデッド・ジョディ」", + "537": "帰ってきた大炎獣「キングボンバード」", + "600": "強襲リンドヴルム", + "601": "とても楽しいキノコ狩り", + "602": "送り火と", + "603": "真理を求めて", + "604": "陰険なる魔物「スパイトフル」", + "672": "不思議な魔物「ゴーレム」", + "673": "不思議な魔物「ストーンマン」", + "697": "星芒祭:魔法の雪だるま", + "707": "狂乱のエッグハント", + "1325": "-----" + } + }, + "152": { + "name": "黒衣森東部森林", + "fates": { + "143": "蜂蜜戦争", + "144": "悪疫散布器「プリンス・オブ・ペスト」", + "145": "戦場までは何マルム?", + "148": "秘密の花園", + "149": "繁殖期の終わり", + "150": "若き魔猿「ジャッカネイプス」", + "151": "リトルブリッジの戦い", + "152": "狂える守護者たち", + "198": "古の闘神「オーディン」", + "199": "古の闘神「オーディン」", + "200": "古の闘神「オーディン」", + "212": "ナインティナインアイビー", + "213": "シルフと共に去りぬ", + "214": "禿鷲の饗宴", + "217": "甘い香りの運び人", + "218": "非情な収穫者「レジー・ローレンス」", + "607": "過ぎ去りし日々の光", + "608": "オチュー狩り", + "609": "気まぐれ婦人「カプリシャス・キャシー」", + "610": "ラークスコール遭遇戦", + "611": "続ラークスコール遭遇戦", + "612": "千人隊長「アウルス・レム・ヴルソ」", + "615": "ミルク・クラッシュ", + "616": "幽谷の薬師「覚醒のダキシオ」", + "618": "ビューティフル・ドリーマー", + "619": "幽谷の衛士「葉刃のヴォルキシア」", + "620": "とてとて楽しいキノコ狩り", + "622": "敬虔なる養育者「風狂のプルシオ」", + "679": "黒い悪魔:実験の成果", + "680": "黒い悪魔:過激な淑女", + "691": "高機動試作機「プロトアーマー」", + "692": "狂乱の闘猪「カフレ」" + } + }, + "153": { + "name": "黒衣森南部森林", + "fates": { + "153": "神速の羚羊「シロッコ」", + "154": "根を渡って沼地を越えて", + "158": "密猟売買両成敗", + "159": "レッドベリー砦の戦い:攻略戦", + "160": "レッドベリー砦の戦い:占領戦", + "161": "レッドベリー砦の戦い:防衛戦", + "162": "レッドベリー砦の戦い:迎撃戦", + "163": "最後の一葉", + "164": "秀麗なる無法者「密猟王クァールクロウ」", + "166": "酒房の常連「酔客のスペンサー」", + "167": "愛に時間を", + "168": "動かぬ証拠", + "169": "闇市の元締「双尾のヤビ・カータポ」", + "170": "通行料の支払いは刃で", + "171": "立ち退き要求", + "172": "失われた品を求めて", + "190": "孤独なる石兵「ヌニュヌウィ」", + "201": "古の闘神「オーディン」", + "202": "古の闘神「オーディン」", + "203": "古の闘神「オーディン」", + "204": "古の闘神「オーディン」", + "215": "飛んで火に入る似我蜂団", + "624": "液状化現象", + "626": "カメェェェッー!", + "627": "臭い物にはフタをしろ", + "628": "最後の闘猪王「パイア」", + "681": "黒い悪魔:実験の成果", + "682": "黒い悪魔:過激な淑女", + "708": "狂乱のエッグハント" + } + }, + "154": { + "name": "黒衣森北部森林", + "fates": { + "174": "烏合の衆", + "178": "赤王の幼生「ジュバ」", + "179": "フォールゴウドの守り手", + "180": "山師の願い", + "183": "猿の惑乱", + "184": "みんな大好きムントゥイ豆", + "185": "幻惑の芳香「クルピラ」", + "187": "イクサル族強襲部隊の迎撃", + "188": "餓えたるジズが求めるもの", + "189": "アルダースプリングスの清掃", + "205": "古の闘神「オーディン」", + "206": "古の闘神「オーディン」", + "207": "古の闘神「オーディン」", + "216": "月の反逆者", + "538": "帰ってきた大炎獣「キングボンバード」", + "631": "伐採部隊迎撃戦", + "632": "遺跡の亡霊騎士「ダイダロス」", + "633": "イクサル軍伐採所強襲作戦", + "634": "怒れる守護者「グレートオーク」", + "674": "不思議な魔物「ゴーレム」", + "675": "不思議な魔物「ストーンマン」", + "676": "不思議な魔物「ゴーレム」", + "677": "不思議な魔物「ゴールドマン」", + "698": "星芒祭:魔法の雪だるま", + "722": "ジャイアントエッグハント" + } + }, + "155": { + "name": "クルザス中央高地", + "fates": { + "460": "白狼たちの戦旗", + "463": "黒き弾丸「ダウニーダンスタン」", + "464": "川辺の復讐者「ガビアル」", + "465": "冬物語", + "466": "星に願いを", + "467": "ワイルドダイルダンディー", + "469": "クルザスの白狼", + "470": "動く要塞", + "472": "流れよ我が涙", + "473": "歓喜、慚愧、猛吹雪", + "474": "エイビスキラー", + "475": "大口の悪鬼「ガルガメル」", + "479": "凍てつく波動「リュタン」", + "480": "騎兵の天敵「セプス」", + "482": "血と肉の街道舗装", + "483": "引き起こされた戦争", + "484": "骨貪る者「ロンジュール」", + "486": "アインハルトの意地", + "487": "暖を求めて", + "489": "巡礼の道", + "490": "愚鈍なる勇者「クリュティオス」", + "491": "星の光、今は遠く", + "493": "雪山の襲撃者「セベク」", + "494": "赤い翼「ロック」", + "496": "それは竜の意思!", + "497": "氷づけになるがいい!", + "498": "入植を阻止せよ", + "499": "烈風の勇士「フェロック四姉妹」", + "500": "匠の技「工匠のゴゾル・イツカン」", + "501": "スヴァラ迎撃作戦:工兵護送", + "502": "スヴァラ迎撃作戦:砲撃準備", + "503": "スヴァラ迎撃作戦:砲撃応戦", + "504": "スヴァラ迎撃作戦:人海戦術", + "505": "伝説の魔獣「ベヒーモス」", + "506": "手負いの魔獣「ベヒーモス」", + "507": "帰ってきた男「ステロペス」", + "508": "嵐神呼びし者「風標のコゾル・ノモトル」", + "653": "閃光の影向:機獣討伐戦", + "654": "閃光の影向:機獣討伐戦", + "699": "星芒祭:魔法の雪だるま", + "709": "賢者のタマゴ「ジョーカー・エッガー」" + } + }, + "156": { + "name": "モードゥナ", + "fates": { + "512": "失われた風景", + "514": "タングル湿林の大掃除", + "516": "湿林の怨念「ンブル」", + "517": "モルボル怒りの大増殖", + "520": "統合整備計画", + "521": "残忍なる悪鬼「ポリュス」", + "522": "聖地巡礼", + "523": "巨漢の地上げ屋", + "524": "ヒッポグリフの晩餐会", + "525": "乱れ髪「銀髪のディオネ」", + "526": "銀泪湖ガラガラドッカン", + "527": "夜襲の魔獣「グウィルギ」", + "529": "旅の仲間", + "530": "甘い誘惑「ボラプチュア・ビビアン」", + "655": "閃光の影向:アヌビス殲滅戦", + "656": "閃光の影向:アヌビス殲滅戦", + "657": "閃光の影向:屍竜討滅戦", + "658": "閃光の影向:屍竜討滅戦" + } + }, + "180": { + "name": "外地ラノシア", + "fates": { + "580": "ザ・ロード", + "581": "黒渦団の仇敵「オセ」", + "583": "豹よ、豹よ!", + "586": "土竜の山師「ピックマン59 ベ・ゼ」", + "587": "試掘地強襲作戦", + "588": "ファイア・イン・ザ・ホール", + "589": "雷雨呼ぶ者「ブラウンガー」", + "591": "伝説の巨竜「ペリュトン」", + "593": "狂気の山脈", + "594": "廃棄された実験体「ナンバー128」", + "595": "補給部隊救出命令", + "597": "鋼虫の養殖者「ビーズマン59 ビ・ゴ」", + "598": "目覚めし石像「バリデト」", + "599": "岩神呼びし者「ペイトリアーク05 ゼ・ブ」", + "700": "妖異殺し「ラウンズマン59 ゲ・ガ」" + } + }, + "397": { + "name": "クルザス西部高地", + "fates": { + "787": "誰か見てるぞ!", + "788": "巡礼の騎士", + "789": "凍結スリップ注意!", + "791": "黒鉄橋の戦い", + "792": "剛毛の白獣「ペルダ」", + "793": "ヤク喰い巨人「ズウティ」", + "794": "栄光の聖フィネア連隊", + "795": "熊出没注意", + "796": "雪男の天敵「イエティトラップ」", + "798": "獣人雪男", + "800": "臥竜島の戦い", + "801": "凍った花", + "802": "ダスクの銀狼", + "805": "コマンダー!", + "807": "幻惑の視線「ビホルダー」", + "809": "スノーホワイト", + "810": "人喰い氷菓「タルトゥフォ&ホワイトトリュフ」", + "811": "竜の眷属を討て", + "812": "鳥竜の大王「ピコラトン」", + "813": "氷上の狼", + "814": "酒浸り野獣「ヘイズルーン」", + "815": "若き竜騎士「鋭槍のアランベール」", + "816": "ファルコンネストの脅威", + "817": "功績泥棒「卑怯者のウェルナー」", + "908": "アイスクリーム頭痛", + "909": "冷酷なる氷竜「スティヒ」" + } + }, + "398": { + "name": "高地ドラヴァニア", + "fates": { + "818": "伝説の馬鳥「ブルチョコボ」", + "819": "チョコボの森の番人", + "820": "巧妙なる狩人「ヨーウィ」", + "821": "アンブロークン・アロー", + "822": "孤高の猛獣「グラワッカス」", + "823": "サーモン戦争", + "824": "美しく複雑なアロマ", + "825": "異形の巡礼者", + "826": "いかにも肉って肉", + "827": "敵の敵も敵", + "828": "異端の扇動者「熱狂のウベルティアン」", + "829": "戦いを終わらせるもの", + "830": "境界の川", + "831": "卵をめぐる竜の戦争", + "832": "雲霧街の虐殺者「スヴァローグ」", + "833": "怒れる母「ミガス」", + "834": "地底の足音", + "835": "下克上の眷属「竜人のロベルラン」", + "836": "殺しが五月蠅くやって来る", + "837": "竜虎の争い", + "838": "爆着の甲竜「タラスク」", + "902": "雷獣の女王「クァールレギナ」", + "903": "逆襲の女王「クァールレギナ」", + "904": "逆襲の女王「クァールレギナ」", + "905": "幻影の女王「クァールレギナ」", + "906": "幻影の女王「クァールレギナ」", + "907": "幻影の女王「クァールレギナ」", + "910": "変貌せし乙女「ドラゴンメイデン」" + } + }, + "399": { + "name": "低地ドラヴァニア", + "fates": { + "756": "悪魔の機械", + "757": "リベンジャーズ", + "758": "全面改修機「III号ゴブリガードJ型」", + "759": "タランチュラホークの襲撃", + "760": "ワイルドでいこう!", + "761": "巨眼の魔牛「エパポス」", + "762": "図書館清掃", + "763": "花粉前線異常アリ", + "764": "吸血の浮遊草「ルギニス」", + "766": "ゴブゴブ紛争", + "767": "熟練の戦闘指揮官「八丁のマウンドリンクス」", + "768": "尻尾を立てろ!", + "769": "野獣の家長「ダルウフー」", + "770": "西方電撃戦", + "771": "モルボルをブッコろせ", + "772": "憂鬱なる令嬢「メランコリック・モイラ」", + "773": "イディルシャイア猟友会", + "774": "血濡れの暴君「ドゥーベ」", + "775": "悲しみのベアー", + "777": "使い魔はつらいよ", + "778": "蛙のために弔鐘は鳴る", + "779": "シャーレアンの影", + "780": "ビブロフィリアの憂鬱", + "781": "コカトリスの思い出", + "782": "果しなき流れの果てで", + "783": "主を待つ者「孤独のベロ・ロッゴ」", + "784": "魚喰いの魚人「オプロケプロン」", + "785": "クロウラーの巣", + "786": "糸紡ぎ巧者「ハベロット」" + } + }, + "400": { + "name": "ドラヴァニア雲海", + "fates": { + "725": "キャッチ・アンド・リリース", + "726": "さよならアルケオダイノス", + "727": "黒竜の使徒「グリコン」", + "728": "モーグリ金融道", + "731": "失われた世界", + "732": "雲海に轟く雷鳴", + "735": "飽食の恐竜「アベリスク」", + "736": "トゥリヘンド・スクランブル", + "737": "トゥリヘンド・ベロシティ", + "738": "遺跡の番人「ウォーギル」", + "740": "竜との舞踏", + "741": "続・竜との舞踏", + "742": "甲鱗の猛竜「クエレブレ」", + "744": "夜と霧", + "746": "燃えよワイバーン", + "747": "薄暮の飛竜「ミナルジャ」", + "748": "来たのは誰だ", + "751": "猛炎の焔竜「クシェドレ」", + "752": "吸引力は変わらない", + "753": "雲海の問題児「悪童のモグーシ」", + "754": "聖と邪の交わるひずみ", + "755": "愚行の問題児「悪童のモグーシ」", + "868": "ダークスケール征討戦:白竜支援", + "869": "ダークスケール征討戦:追撃作戦", + "870": "ダークスケール征討戦:総力決戦", + "871": "蒼天の白竜「ヴェズルフェルニル」", + "872": "白亜の宮殿防衛戦:子竜救援", + "873": "白亜の宮殿防衛戦:猛竜討伐", + "874": "白亜の宮殿防衛戦:モーグリ救援" + } + }, + "401": { + "name": "アバラシア雲海", + "fates": { + "839": "猫まっしぐら", + "840": "ガストルニスの巣破壊命令", + "841": "鮮やかなる丸鳥「ディアトリマ」", + "842": "雲海の大乱闘", + "843": "薔薇の血を吸いたくて", + "844": "黒い鳥", + "845": "若気の至り", + "846": "不法投棄者「アポタムキン」", + "847": "雲海の戦士", + "851": "素晴らしい新世界", + "852": "空の上の雲", + "853": "逃亡者", + "854": "追跡者", + "855": "暴食の岩人形「グランズイーター」", + "856": "補給線を断て", + "857": "招かれざる客", + "860": "恐怖の対象「積乱のオヌバリ」", + "861": "雲神の司祭「入道のケナバヌ」", + "862": "ケナバヌの弟子たち", + "863": "復讐の司祭「入道のケナバヌ」", + "864": "絨毯爆撃", + "865": "狂気の歌声「ポダルゲー」", + "866": "雲海の狂風「アケク」", + "867": "不吉な鳥は雲の彼方へ飛ぶ", + "875": "大嘴の怪鳥「イェル」" + } + }, + "402": { + "name": "魔大陸アジス・ラー", + "fates": { + "877": "太古の脅威:ノクチルカ撃滅戦", + "878": "太古の脅威:ノクチルカ撃滅戦", + "879": "太古の脅威:ノクチルカ撃滅戦", + "880": "バグ報告ナンバー壱九九", + "881": "輪廻の蛇", + "882": "アラグ脅威のメカニズム", + "883": "狡知の魔獣「キマイラブレイン」", + "884": "魔獣狩り", + "885": "忠義の妖王「ムチャリンダ」", + "886": "ミュータントフラワーズ", + "887": "スチールシティ", + "888": "ロストテクノロジー", + "889": "全自動手作業", + "890": "魔導技師長「シラ・マル・アルビヌス」", + "891": "ガンマ戦線バースト:東部", + "892": "ガンマ戦線バースト:西部", + "893": "ガンマ戦線バースト:南部", + "894": "無知性化の嵐", + "895": "人造多頭竜「ゴリシュチェ」", + "897": "大量誤発注事件", + "898": "不吉なる実験体「ステンノー」", + "899": "魂なき肉体のごとし", + "900": "ハイアラガンユーザー", + "901": "夢見る無人機「リックスピナー」" + } + }, + "411": { + "name": "ギラバニア辺境地帯", + "fates": { + "1112": "ブートキャンプ:兵卒編", + "1113": "ブートキャンプ:下士編", + "1114": "ブートキャンプ:士官編", + "1115": "ワニワニ、ワニっす!", + "1116": "熊と踊れ", + "1117": "チルドレン・オブ・ザ・サプリア", + "1118": "混交林の大熊「シャープアイ・グリズリー」", + "1119": "悲劇の変異体「ギガゲイター」", + "1120": "辺境パトロール", + "1121": "続・辺境パトロール", + "1122": "次の岩に続く", + "1124": "チョコボではない", + "1125": "トンボ身重く横たわる", + "1126": "実はモス生まれ", + "1127": "果しなき河よ我を誘え", + "1128": "グゥレイト!", + "1129": "樹人の長老「キルニス」", + "1130": "人喰い大蜘蛛「アンカブート」", + "1131": "アントリオンは大人しいんだ", + "1132": "大角の脱走兵「ケラチラノス」", + "1133": "新石器時代", + "1134": "所有せざる人々", + "1135": "暴走の巨象「ランページング・マーリド」", + "1136": "血をわけた姉妹", + "1137": "白銀の人拐い「ベルダ」", + "1138": "鱗斬りの鉤爪「ジャターユ」", + "1139": "太陽の娘「ドリサナ」", + "1140": "野良犬", + "1141": "高い村の女" + } + }, + "412": { + "name": "ギラバニア山岳地帯", + "fates": { + "1173": "完全菜食主義", + "1174": "精進料理", + "1175": "空腹の詐欺師「肉食のミミルン」", + "1176": "死ぬのは奴らだ", + "1177": "血の収穫", + "1178": "農民の悪夢「スパーナル・チャプリ」", + "1179": "ブラッドミュージック", + "1180": "チャプリの移民", + "1181": "沈黙の木樵「ランバージャック」", + "1182": "魔蝶の王妃「エーディン」", + "1184": "アラガーナ防衛線", + "1185": "伝説の藪医者「ブルータルバーバー」", + "1186": "グリフィンの物語", + "1187": "胡蝶の夢", + "1188": "凶悪なる骰子「クラッブス」", + "1189": "拷問者の影", + "1190": "ハイランダー悪魔の虫", + "1191": "不浄なる獣「ティンダロス」", + "1193": "エルカ探検隊の大冒険", + "1194": "豪腕の襲撃者「フンババ」", + "1195": "待ってたんだ!", + "1196": "血より生まれし", + "1197": "暴風の元凶「ウェントゥス」", + "1198": "執行人の家系「ネックブリーカー」", + "1199": "風と共に来たる", + "1200": "優雅なる放火魔「イグナモス」", + "1201": "チャプリの勇敢", + "1202": "復讐の寡男「ネナウニル」", + "1203": "エクソシスト", + "1204": "幸運なる大食漢「エナジェティック・エルカ」", + "1205": "ジャ族の戦士", + "1207": "暴走最終兵器「リーサルウェポン」" + } + }, + "413": { + "name": "ギラバニア湖畔地帯", + "fates": { + "1103": "伝説の雷馬「イクシオン」", + "1104": "伝説の雷馬「イクシオン」", + "1105": "伝説の雷馬「イクシオン」", + "1272": "ロッホ・セル湖畔の戦い", + "1273": "不動の大蝦蟇「フロガマンダー」", + "1274": "悲恋の乙女「ボルータ」", + "1275": "騒音アバドン", + "1276": "死の芳香「アロマ・リーチ」", + "1277": "白色大顔面「トール・マウンテン」", + "1278": "不人気の怪物「クレア」", + "1279": "虚ろなる老木「カリュアー」", + "1280": "剥落せし岩獣「シーシュポス」", + "1281": "雷光の魔牛「アステリオス」", + "1282": "断頭台への招待", + "1283": "過ぎ去りし日々の風", + "1284": "死病の運び手「ラッラミラ」", + "1285": "死を告げる白虫", + "1286": "狂気の鉱虫「クレイジーソブラン」", + "1287": "濡れた魚", + "1288": "死人に口なし", + "1289": "塩の恋人", + "1290": "純白の鉄鋏「ロッホロッホ」", + "1291": "ナンカ移動時代", + "1292": "白き侵略者「チュクワ」", + "1293": "花粉戦争", + "1294": "草の女王", + "1295": "塩湖の金鋸「セラ」", + "1296": "ミノタウロスのお皿", + "1297": "キングズガード", + "1298": "バタフライエフェクト", + "1299": "ミリオンダラ・ソルティ", + "1300": "薬用リーチ", + "1301": "動く震源地「テルース」", + "1302": "マウンテン", + "1303": "アンセロットの嘆き", + "1304": "アンセロットの恐れ", + "1305": "アンセロットの願い" + } + }, + "421": { + "name": "紅玉海", + "fates": { + "1142": "牛鬼の使い「ヌレオンナ」", + "1143": "迷惑な落とし物", + "1144": "不吉な怪鳥「イツマデ」", + "1145": "漁村の脅威「ケイボクロウ」", + "1146": "青い紅玉", + "1147": "敗戦の大兜「ミシルシ」", + "1148": "炎纏う者「アグニ」", + "1149": "赤い珊瑚礁", + "1150": "紅甲羅関所破り", + "1151": "海からの侵略生物", + "1152": "紅甲羅あばれ凧", + "1153": "飛鮫の姫君「ヤヒロノワニ」", + "1154": "渇きの海", + "1155": "指きり拳万", + "1156": "紅甲羅海を渡る", + "1157": "夢の丘", + "1158": "北風のうしろ", + "1159": "無礼なる牛鬼「ジンリンキ」", + "1160": "されど修羅ゆく君は", + "1161": "激流の亀忍者「十代のカタビラ」", + "1162": "紅甲羅千両首", + "1163": "知らぬが仏", + "1164": "スカイシャークズ", + "1165": "不徳の僧侶「ソウゲンビ」", + "1166": "牛鬼泥棒", + "1167": "兵法修行人「一刀のセンバン」", + "1168": "紅甲羅逆手斬り", + "1170": "兜割", + "1171": "海の貴婦人", + "1172": "夢見る大名「ダイミョウユメミ」" + } + }, + "422": { + "name": "ヤンサ", + "fates": { + "1106": "九尾の妖狐「玉藻御前」", + "1107": "九尾の妖狐「玉藻御前」", + "1108": "九尾の妖狐「玉藻御前」", + "1109": "その名はミクズメ", + "1110": "キンコの願い", + "1111": "ギンコの願い", + "1208": "ギョグンの不運", + "1209": "ギョグンの非運", + "1210": "痺れる激情「豊漁のギョグン」", + "1211": "人狼:紅い足跡", + "1212": "人狼:鋼鉄の猟犬", + "1213": "紅い甲羅「刀狩のワキザシ」", + "1214": "ベニツノ凶鳥狩り", + "1215": "鯰狙いの大蛇「ニュ・ワー」", + "1216": "戦慄の血飛沫", + "1217": "扶持の狩手「フチカリ」", + "1218": "遮二無二", + "1219": "虎のゆりかご", + "1220": "怪しい虫", + "1221": "狩って兜の緒を締めよ", + "1222": "猿の大軍団", + "1223": "テナガおじさん", + "1224": "稲生物怪録", + "1225": "ベニツノの卵は誰のもの", + "1226": "田園の怪火「ツルベビ」", + "1227": "紅色の役者「ショウシ」", + "1228": "汚水の精「アプサラス」", + "1229": "青黒の妖犬「リンチュアン」", + "1230": "日食の巨鳥「タイホウ」", + "1231": "狂える案山子「クエビコ」", + "1232": "ナマズオどうしよう", + "1233": "人狼の野武士", + "1234": "烈士伝", + "1235": "トラ、トラ、トラ!", + "1236": "巨頭の暴君「ラゴウ」", + "1237": "精強なる老虎「ヘイカン」", + "1238": "逆心の巨兵「キドウ丸」", + "1239": "妖犬伝説", + "1240": "陰陽師:清房ノ巻", + "1241": "陰陽師:鼓子ノ巻" + } + }, + "423": { + "name": "アジムステップ", + "fates": { + "1242": "狩人を狩る者「キラタ」", + "1243": "再会を阻む者「ナランツェツェグ」", + "1244": "北部の女傑「寒風のクァトゥン」", + "1245": "密猟者たち", + "1246": "大空の誘拐者「サムパティ」", + "1247": "叫声の野人「ルドラ」", + "1248": "除草の達人「ブオチュー」", + "1249": "ザ・フライ", + "1250": "沈黙の制裁", + "1251": "マンモスと暮らすには", + "1252": "草原の赤いイナズマ", + "1253": "鳥", + "1254": "多産の王妃「ステップ・ハタン」", + "1255": "時には懺悔を", + "1256": "プルプルプル", + "1257": "飢えたる根人「フン・ウンデス」", + "1258": "大草原の怪物「マンガス」", + "1259": "石人の英雄「ゲルゲイ・チョロー」", + "1260": "亀がアウラに言ったこと", + "1261": "家路につく牛飼いの少女", + "1262": "赤い砂漠", + "1263": "野獣狩り", + "1264": "残虐な覇者「グログロハーン」", + "1265": "這い寄る悪臭「スティンクスキン」", + "1266": "野火", + "1267": "長牙の圧殺者「マヒシャスラ」", + "1268": "優しき雑草の反抗", + "1269": "つかのまの悪夢", + "1270": "よみがえる悪夢", + "1271": "覇道の帰還者「マニカンタ」", + "1306": "ダタクの旅:バズフライ遭遇", + "1307": "ダタクの旅:ガーダン襲撃", + "1308": "ダタクの旅:羊乳搾り", + "1309": "ダタクの旅:ケナガウシ狩り", + "1310": "ダタクの旅:ガーダン再襲撃", + "1311": "ダタクの旅:ウグンド強襲", + "1312": "ダタクの旅:狩人救出", + "1313": "ダタクの旅:グログロ討伐", + "1315": "ダタクの旅:マタンガ強襲", + "1316": "ダタクの旅:マタンガ遭遇", + "1318": "ダタクの旅:ゴロ族救出", + "1319": "ダタクの旅:マタンガ逆襲", + "1320": "ダタクの旅:大王出陣" + } + }, + "501": { + "name": "レイクランド", + "fates": { + "1496": "紫葉団との戦い:アジト設営", + "1497": "紫葉団との戦い:アジト構築", + "1498": "鮮血の偽竜「オピオン」", + "1499": "狼は泣かず", + "1500": "木こり歌の事", + "1501": "紫葉団との戦い:木こり襲撃", + "1502": "紫葉団との戦い:卑劣な罠", + "1503": "紫葉団との戦い:一斉蜂起", + "1504": "紫葉団との戦い:ワーグ参戦", + "1505": "汚れた血め!", + "1506": "あれってまさか、グレムリン?", + "1507": "高貴なる狼男「ルガルー」", + "1508": "リトル・ゲート・オブ・ホラーズ", + "1509": "ハイエボリューション", + "1510": "激憤の大物「ヌスクナッカー」" + } + }, + "502": { + "name": "コルシア島", + "fates": { + "1462": "激闘フォーミダブル:迫る脅威", + "1463": "激闘動フォーミダブル:新たな情報", + "1464": "激闘フォーミダブル:切り札起動", + "1465": "スティルタイドを覆う影", + "1466": "スティルタイドを覆う影", + "1467": "ライト村を覆う影", + "1468": "ライト村を覆う影", + "1469": "大麦若葉にレイルにゴーヤ", + "1470": "クラゲシネ", + "1471": "ひよこ倶楽部", + "1472": "シャコボクサー", + "1473": "ノッカー・アップ", + "1474": "ディスコード!", + "1475": "アミティーを覆う影", + "1476": "激震の巨虫「クローリングデス」", + "1477": "ビルドウォリアーズ:オートマトン製作", + "1478": "ビルドウォリアーズ:試作品実戦テスト", + "1479": "ビルドウォリアーズ:没収試合" + } + }, + "503": { + "name": "アム・アレーン", + "fates": { + "1511": "拾う者たち:シザージョウの罠", + "1512": "拾う者たち:シムーンの背骨", + "1513": "拾う者たち:クイジャテンダー", + "1514": "拾う者たち:ウェイストピッカー", + "1515": "求める者たち:強盗遭遇", + "1516": "求める者たち:強盗逆襲", + "1517": "求める者たち:遺跡探索", + "1518": "求める者たち:大老の剣", + "1519": "サボテンが花をつけている", + "1520": "流砂の砂漠", + "1521": "トルバNo. 1", + "1522": "砂鱗の女王「バヤワク」", + "1523": "イグアナの夜", + "1524": "ロングレッグ・オーバーライド", + "1525": "異種の僚友「クルカディとムンバ」", + "1526": "エクスプロージョン!", + "1527": "海老ではない" + } + }, + "504": { + "name": "イル・メグ", + "fates": { + "1480": "悪童ダエン兄弟:ピクシーが標的!", + "1481": "悪童ダエン兄弟:アマロが標的!", + "1482": "悪童ダエン兄弟:ン・モゥが標的!", + "1483": "悪童ダエン兄弟:幻惑のローワン", + "1484": "悪童ダエン兄弟:決闘の時", + "1485": "悪童ダエン兄弟:再戦の時", + "1486": "悪童ダエン兄弟:双子の切り札", + "1487": "悪童ダエン兄弟:最後の戦い", + "1488": "根を断つ者「シェムハザ」", + "1489": "がんばれ、ローズベアーズ", + "1490": "バスケットケース", + "1491": "蜜吸の死蝶「ネクロプシュケ」", + "1492": "ピクシーテイル:黄金色の花蜜", + "1493": "マイ・フレンド・フォーエバー", + "1494": "ピクシーテイル:妖精の天敵", + "1495": "ピクシーテイル:魔物包囲網", + "1531": "悪童ダエン兄弟:アマロが標的!", + "1532": "悪童ダエン兄弟:ン・モゥが標的!", + "1533": "悪童ダエン兄弟:幻惑のローワン" + } + }, + "505": { + "name": "ラケティカ大森林", + "fates": { + "1441": "ミャルナの巡察:病毒のエコー", + "1442": "ミャルナの巡察:病原のクロウラー", + "1443": "ミャルナの巡察:矢の補充", + "1444": "ミャルナの巡察:古き護人の護衛", + "1445": "ミャルナの狩猟:トヒル発見", + "1446": "ミャルナの狩猟:トヒル追撃", + "1447": "ミャルナの狩猟:トヒル追撃", + "1448": "ミャルナの狩猟:トヒル猛追撃", + "1449": "ミャルナの狩猟:トヒル猛追撃", + "1450": "ミャルナの狩猟:トヒル討伐", + "1451": "不燃の怪樹「チャンティコ」", + "1452": "スパイダー!", + "1453": "ピンク・フラミンゴ", + "1454": "ラプトルのキッチン", + "1455": "愛と死", + "1456": "アタック・オブ・ザ・キラートマトル", + "1457": "死相の陸鳥「ケライノー」", + "1458": "本能が目を覚ます", + "1459": "伝説が生まれる", + "1460": "キルメとサルメ", + "1461": "火神の眼「ガトルアイ」", + "1528": "ミャルナの狩猟:トヒル猛追撃", + "1529": "ミャルナの狩猟:トヒル猛追撃", + "1530": "ミャルナの狩猟:トヒル討伐" + } + }, + "506": { + "name": "テンペスト", + "fates": { + "1426": "厄災のアルケオタニア:追跡開始", + "1427": "厄災のアルケオタニア:ズムスィー登場", + "1428": "厄災のアルケオタニア:テウスィー防衛", + "1429": "厄災のアルケオタニア:テウスィー護衛", + "1430": "厄災のアルケオタニア:紅血珊瑚の収集", + "1431": "厄災のアルケオタニア:決戦の下準備", + "1432": "厄災のアルケオタニア:深海の討伐戦", + "1433": "深海の美女「ハリメデ」", + "1434": "貝汁物語", + "1435": "パールは永遠の輝き", + "1436": "ディープシー20000匹", + "1437": "ダンバニアファミリー", + "1438": "黒風海産ヒドロ虫類", + "1439": "スワローズ・ライジング", + "1440": "バハ・オンド・シュリンプ" + } + }, + "996": { + "name": "ヒューダトス", + "fates": { + "1412": "奇怪なる烏賊「カラマリ」", + "1413": "暴虐の魔獣「ステゴドン」", + "1414": "落涙の君主「モレク」", + "1415": "極彩色の怪鳥「ピアサ」", + "1416": "孤高の狩人「フロストメーン」", + "1417": "血濡れの妖妃「ダフネ」", + "1418": "異界の鍛冶王「キング・ゴルデマール」", + "1419": "食妖植物「レウケー」", + "1420": "業炎の獅子王「バロン」", + "1421": "魔蛇の女王「ケートー」", + "1422": "「バルデシオンアーセナル」調査支援", + "1423": "水晶の龍「プロヴェナンス・ウォッチャー」", + "1424": "未知なる脅威「オヴニ」", + "1425": "水遊びのしあわせうさぎ" + } + }, + "997": { + "name": "ピューロス", + "fates": { + "1388": "白き叫声「レウコシアー」", + "1389": "獰猛なる雷獣「フラウロス」", + "1390": "妖異の弁論家「ソフィスト」", + "1391": "恐怖の人形「グラッフアカーネ」", + "1392": "書の守護者「アスカラポス」", + "1393": "深淵の大公「グランドデューク・バティム」", + "1394": "稲妻の指揮者「アイトロス」", + "1395": "灼熱の突剣「レサト」", + "1396": "炎熱の巨人「エルドスルス」", + "1397": "落涙の海燕「イリス」", + "1398": "奇跡の生還者「傭兵のレイムプリクス」", + "1399": "電影将軍「ライトニング・ドゥクス」", + "1400": "ランバージャック・デスマッチ", + "1401": "知恵と戦の母「グラウコピス」", + "1402": "相反する双子「イン・ヤン」", + "1403": "嘲りの月狼「スコル」", + "1404": "炎蝶の女王「ペンテシレイア」", + "1407": "珊瑚狙いのしあわせうさぎ", + "1408": "岩封じのしあわせうさぎ" + } + }, + "998": { + "name": "パゴス", + "fates": { + "1351": "白き支配者「雪の女王」", + "1352": "家畜の慈母「スラビー」", + "1353": "灰殻の鱗王「アッシュドラゴン」", + "1354": "地殻変動の謎「グラヴォイド」", + "1355": "雪解けの化身「アナポ」", + "1356": "硬質の病魔「アサグ」", + "1357": "動く雪洞「キングイグルー」", + "1358": "唇亡びて歯寒し", + "1359": "太陽の使者「ホルス」", + "1360": "円卓の霧王「キングアースロ」", + "1361": "野牛の救い主「エウレカの聖牛」", + "1362": "雷雲の魔獣「ハダヨッシュ」", + "1363": "闇眼王「アーチ・アンラ・マンユ」", + "1364": "蒼き氷刃「ロウヒ」", + "1365": "模倣犯「コピーキャット・キャシー」", + "1366": "五行眼の主「ハクタク」", + "1367": "雪上のしあわせうさぎ", + "1368": "宝石狙いのしあわせうさぎ", + "1369": "腐れる読書家「タキシム」" + } + }, + "999": { + "name": "アネモス", + "fates": { + "1328": "疾風の帝王「アネモス・エンペラー」", + "1329": "暴風の魔王「パズズ」", + "1331": "狂乱の暗竜「ファヴニル」", + "1332": "舞踏の大花「サボテンダー・コリード」", + "1333": "最後の美声「テレス」", + "1334": "貪り喰らう者「アメミット」", + "1335": "獣脚の怪人「カイム」", + "1336": "腐臭の賢者「ボンバディール」", + "1337": "高名なる巨人「ポリュペモス」", + "1338": "魔の王妃「ラマシュトゥ」", + "1339": "幻の魔蠍「セルケト」", + "1340": "異界の魔犬「アマロック」", + "1341": "燃える大王「キング・ハズマット」", + "1342": "憤怒の怪鳥「シームルグ・ストライダー」", + "1343": "勝利の騎士「ホワイトライダー」", + "1344": "蠢く死体「カリスト」", + "1345": "強風の妖精「ジャハンナム」", + "1346": "種まき「ジャッジメンタル・ジュリカ」", + "1347": "主なき人形「ナンバーズ」", + "1348": "大蛸の王者「ロード・オブ・アネモス」" + } + }, + "1001": { + "name": "南方ボズヤ戦線", + "fates": { + "1597": "術士大隊との会敵", + "1598": "無人魔導兵器との会敵", + "1599": "忠犬との遭遇", + "1600": "術士大隊への奇襲", + "1601": "{有人魔導兵器の迎撃}", + "1602": "野生生物を排除せよ", + "1603": "豚面の魔獣使い", + "1604": "{華麗なる珍獣使い}", + "1605": "労働十号破壊命令", + "1606": "恩徳の術士たち", + "1607": "忠犬の逆襲", + "1608": "{豚面と赤い馬鳥}", + "1609": "{潔白の脱走兵}", + "1610": "敵新兵器を調査せよ", + "1611": "野営地への先制攻撃", + "1612": "魔導レイバー破壊命令", + "1613": "整備場奇襲作戦", + "1614": "魂喰いの妖異たち", + "1615": "術士大隊の猛攻", + "1616": "最強のパイロマンサー", + "1617": "華麗なるお気に入り", + "1618": "暴走魔獣の排除", + "1619": "豚面の勧誘者", + "1620": "{魔導レイバーB型破壊命令}", + "1621": "強化兵部隊の襲撃", + "1622": "戦場の盗掘者", + "1623": "補給物資強奪作戦", + "1624": "血の匂いに誘われて", + "1625": "燃え上がる南方戦線", + "1626": "{続・燃え上がる南方戦線}", + "1627": "戦場の犬を解き放て", + "1628": "シシニアスの実験場", + "30000": "カストルム・ラクスリトレ攻城戦", + "30001": "腐乱野菜「ピーリフール」", + "30002": "戦争の妖犬「カニスディルス」", + "30003": "{高火力陸戦魔導兵器「ヴィジル」}", + "30004": "新型飛行型魔導アーマー「ガブリエル」", + "30005": "黒き死鳥「アクババ」", + "30006": "怨念の死霊「スパルトイ」", + "30007": "{赤チョコボのヌシ「レッドコメット」}", + "30008": "百獣使い「獣王ライアン」", + "30009": "炎獣使い「火焔百人隊」", + "30010": "拠点防衛魔導兵器「パトリオット」", + "30011": "邪眼の妖獣「エアレー」", + "30012": "老練の魔道士「鉄火のサルトヴォアール」", + "30013": "{鋼鉄の魔獣「ダーインスレイヴ」}", + "30014": "新たなる鉄巨人「魔導レイバーX型」", + "30015": "戦慄の角「チルヴニク」" + } + } + } +} diff --git a/Data/DcDuty-Korean.json b/Data/DcDuty-Korean.json new file mode 100644 index 0000000..e492c21 --- /dev/null +++ b/Data/DcDuty-Korean.json @@ -0,0 +1,1754 @@ +{ + "version": "202102171", + "language": "한국말", + "roulettes": { + "1": "레벨링", + "2": "레벨 50/60/70 던전", + "3": "주요 퀘스트", + "4": "길드 작전", + "5": "숙련자", + "6": "토벌전", + "7": "전장", + "8": "레벨 80 던전", + "9": "멘토", + "10": "더 피스트 - 친선 경기", + "11": "더 피스트 - 친선 경기", + "13": "더 피스트 - 개인", + "15": "24인 레이드", + "16": "더 피스트 - 팀", + "17": "노말 레이드", + "18": "초코보 레이스: 사골리길", + "19": "초코보 레이스: 코스타 델 솔", + "20": "초코보 레이스: 트랑킬로", + "21": "초코보 레이스: 무작위", + "22": "초코보 레이스: 사골리길 (보수없음)", + "23": "초코보 레이스: 코스타 델 솔 (보수없음)", + "24": "초코보 레이스: 트랑킬로 (보수없음)", + "25": "초코보 레이스: 무작위 (보수없음)", + "26": "초코보 레이스: 무작위", + "27": "초코보 레이스: 무작위", + "28": "초코보 레이스: 무작위", + "29": "초코보 레이스: 무작위", + "30": "초코보 레이스: 무작위", + "31": "초코보 레이스: 무작위", + "32": "초코보 레이스: 무작위", + "33": "초코보 레이스: 무작위", + "34": "초코보 레이스: 무작위", + "35": "초코보 레이스: 무작위", + "36": "초코보 레이스: 무작위", + "37": "초코보 레이스: 무작위", + "38": "초코보 레이스: 무작위" + }, + "instances": { + "1": "토토라크 감옥", + "2": "탐타라 묘소", + "3": "구리종 광산", + "4": "사스타샤 침식 동굴", + "5": "금빛 골짜기", + "6": "하우케타 별궁", + "7": "할라탈리 수련장", + "8": "브레이플록스의 야영지", + "9": "카른의 무너진 사원", + "10": "방랑자의 궁전", + "11": "돌방패 경계초소", + "12": "나무꾼의 비명", + "13": "제멜 요새", + "14": "옛 암다포르 성", + "15": "카스트룸 메리디아눔", + "16": "마도성 프라이토리움", + "17": "시리우스 대등대", + "18": "구리종 광산 (어려움)", + "19": "하우케타 별궁 (어려움)", + "20": "브레이플록스의 야영지 (어려움)", + "21": "할라탈리 수련장 (어려움)", + "22": "옛 암다포르 시가지", + "23": "난파선의 섬", + "24": "탐타라 묘소 (어려움)", + "25": "돌방패 경계초소 (어려움)", + "26": "카른의 무너진 사원 (어려움)", + "27": "얼음외투 대빙벽", + "28": "사스타샤 침식 동굴 (어려움)", + "29": "옛 암다포르 성 (어려움)", + "30": "방랑자의 궁전 (어려움)", + "31": "구브라 환상도서관", + "32": "묵약의 탑", + "33": "거두지 않는 섬", + "34": "이슈가르드 교황청", + "35": "무한연속 박물함", + "36": "어스름 요새", + "37": "솜 알", + "38": "마과학 연구소", + "39": "용의 둥지", + "40": "시리우스 대등대 (어려움)", + "41": "성 모샨 식물원", + "42": "집단전 훈련을 완수하라!", + "43": "방황하는 사령을 쓰러뜨려라!", + "44": "관문을 돌파하고 최심부의 적을 쓰러뜨려라!", + "45": "길거북을 사로잡아라!", + "46": "독성 요괴꽃을 제거하라!", + "47": "무법자 집단 `나나니단`을 섬멸하라!", + "48": "몽환의 브라크시오를 쓰러뜨려라!", + "49": "폭탄광 고블린 군단을 섬멸하라!", + "50": "오염원 몰볼을 쓰러뜨려라!", + "51": "갱도에 나타난 요마 부소를 쓰러뜨려라!", + "52": "무적의 부하를 조종하는 요마를 쓰러뜨려라!", + "53": "봄을 거느린 `봄 여왕`을 쓰러뜨려라!", + "54": "불길한 진형을 짜는 요마를 섬멸하라!", + "55": "세 거인족을 제압하여 유물을 지켜내라!", + "56": "이프리트 토벌전", + "57": "타이탄 토벌전", + "58": "가루다 토벌전", + "59": "진 이프리트 토벌전", + "60": "진 타이탄 토벌전", + "61": "진 가루다 토벌전", + "62": "리트아틴 강습전", + "63": "극 이프리트 토벌전", + "64": "극 타이탄 토벌전", + "65": "극 가루다 토벌전", + "66": "선왕 모그루 모그 XII세 토벌전", + "67": "극왕 모그루 모그 XII세 토벌전", + "68": "알테마 웨폰 파괴작전", + "72": "진 리바이어선 토벌전", + "73": "극 리바이어선 토벌전", + "74": "도름 키마이라 토벌전", + "75": "하이드라 토벌전", + "76": "길가메시 토벌전", + "77": "진 라무 토벌전", + "78": "극 라무 토벌전", + "79": "진 시바 토벌전", + "80": "극 시바 토벌전", + "81": "아마지나배 투기대회 결승전", + "82": "투신 오딘 토벌전", + "83": "성도 이슈가르드 방어전", + "84": "아씨엔 나브리알레스 토벌전", + "85": "진 길가메시 토벌전", + "86": "진 라바나 토벌전", + "87": "극 라바나 토벌전", + "88": "진 비스마르크 토벌전", + "89": "극 비스마르크 토벌전", + "90": "나이츠 오브 라운드 토벌전", + "91": "극 나이츠 오브 라운드 토벌전", + "92": "크리스탈 타워: 고대인의 미궁", + "93": "대미궁 바하무트: 해후편 1", + "94": "대미궁 바하무트: 해후편 2", + "95": "대미궁 바하무트: 해후편 3", + "96": "대미궁 바하무트: 해후편 4", + "97": "대미궁 바하무트: 해후편 5", + "98": "대미궁 바하무트: 침공편 1", + "99": "대미궁 바하무트: 침공편 2", + "100": "대미궁 바하무트: 침공편 3", + "101": "대미궁 바하무트: 침공편 4", + "102": "크리스탈 타워: 시르쿠스 탑", + "103": "대미궁 바하무트: 침공편 1 (영웅)", + "104": "대미궁 바하무트: 침공편 2 (영웅)", + "105": "대미궁 바하무트: 침공편 3 (영웅)", + "106": "대미궁 바하무트: 침공편 4 (영웅)", + "107": "대미궁 바하무트: 진성편 1", + "108": "대미궁 바하무트: 진성편 2", + "109": "대미궁 바하무트: 진성편 3", + "110": "대미궁 바하무트: 진성편 4", + "111": "크리스탈 타워: 어둠의 세계", + "112": "기공성 알렉산더: 기동편 1", + "113": "기공성 알렉산더: 기동편 2", + "114": "기공성 알렉산더: 기동편 3", + "115": "기공성 알렉산더: 기동편 4", + "116": "기공성 알렉산더: 기동편 1 (영웅)", + "117": "기공성 알렉산더: 기동편 2 (영웅)", + "118": "기공성 알렉산더: 기동편 3 (영웅)", + "119": "기공성 알렉산더: 기동편 4 (영웅)", + "120": "보이드의 방주", + "127": "외곽 유적지대 (제압전)", + "130": "봉인된 바위섬 (쟁탈전)", + "131": "디아뎀 제도(쉬움)", + "132": "디아뎀 제도", + "133": "디아뎀 제도 (어려움)", + "134": "마신 세피로트 토벌전", + "135": "극 마신 세피로트 토벌전", + "136": "기공성 알렉산더: 율동편 1", + "137": "기공성 알렉산더: 율동편 2", + "138": "기공성 알렉산더: 율동편 3", + "139": "기공성 알렉산더: 율동편 4", + "140": "옛 암다포르 시가지 (어려움)", + "141": "거꾸로 선 탑", + "143": "더 피스트 (4 대 4 / 등급전)", + "145": "더 피스트 (4 대 4 / 일반전)", + "147": "기공성 알렉산더: 율동편(영웅) 1", + "148": "기공성 알렉산더: 율동편(영웅) 2", + "149": "기공성 알렉산더: 율동편(영웅) 3", + "150": "기공성 알렉산더: 율동편(영웅) 4", + "151": "범위 공격을 피하자!", + "152": "콤보를 이어 적개심을 끌자!", + "153": "실전에서 콤보를 사용해보자!", + "154": "다수의 적에게서 적개심을 끌자!", + "155": "실전에서 다수의 적과 싸워보자!", + "156": "멀리서 적개심을 끌자!", + "157": "적 지원군에 대처하자!", + "158": "파티원과 협력하여 적을 물리치자!", + "159": "파티원과 같은 적을 공격하자!", + "160": "적의 공격을 피하면서 싸우자!", + "161": "적 지원군에 대처하자!", + "162": "특수 장치를 활용하며 싸우자!", + "163": "파티원을 회복시키자!", + "164": "다수의 파티원을 회복시키자!", + "165": "적의 공격을 피하면서 싸우자!", + "166": "마지막 훈련!", + "168": "금기도시 마하", + "169": "니드호그 토벌전", + "170": "극 니드호그 토벌전", + "171": "소르 카이", + "172": "난파선의 섬 (어려움)", + "174": "망자의 궁전 B1~B10", + "175": "망자의 궁전 B11~B20", + "176": "망자의 궁전 B21~B30", + "177": "망자의 궁전 B31~B40", + "178": "망자의 궁전 B41~B50", + "179": "보물고 아쿠아폴리스", + "180": "영광의 평원 (쇄빙전)", + "181": "유령의 집", + "182": "젤파톨", + "183": "여신 소피아 토벌전", + "184": "극 여신 소피아 토벌전", + "186": "기공성 알렉산더: 천동편 1", + "187": "기공성 알렉산더: 천동편 2", + "188": "기공성 알렉산더: 천동편 3", + "189": "기공성 알렉산더: 천동편 4", + "190": "기공성 알렉산더: 천동편(영웅) 1", + "191": "기공성 알렉산더: 천동편(영웅) 2", + "192": "기공성 알렉산더: 천동편(영웅) 3", + "193": "기공성 알렉산더: 천동편(영웅) 4", + "195": "도전! 트리플 트라이어드", + "196": "구브라 환상도서관 (어려움)", + "201": "더 피스트 (늑대우리 훈련장: 친선 경기)", + "204": "망자의 궁전 B51~B60", + "205": "망자의 궁전 B61~B70", + "206": "망자의 궁전 B71~B80", + "207": "망자의 궁전 B81~B90", + "208": "망자의 궁전 B91~B100", + "209": "망자의 궁전 B101~B110", + "210": "망자의 궁전 B111~B120", + "211": "망자의 궁전 B121~B130", + "212": "망자의 궁전 B131~B140", + "213": "망자의 궁전 B141~B150", + "214": "망자의 궁전 B151~B160", + "215": "망자의 궁전 B161~B170", + "216": "망자의 궁전 B171~B180", + "217": "망자의 궁전 B181~B190", + "218": "망자의 궁전 B191~B200", + "219": "바일사르 장성", + "220": "둔 스카", + "221": "솜 알 (어려움)", + "223": "귀신 주르반 토벌전", + "224": "극 귀신 주르반 토벌전", + "228": "더 피스트 (4 대 4 / 등급전)", + "230": "더 피스트 (4 대 4 / 일반전)", + "233": "더 피스트 (잡초 훈련장: 친선 경기)", + "235": "시스이 궁", + "236": "성도산 사원", + "238": "세이렌 해", + "239": "신룡 토벌전", + "240": "바르담 패도", + "241": "도마 성", + "242": "카스트룸 아바니아", + "243": "스사노오 토벌전", + "244": "극 스사노오 토벌전", + "247": "알라미고", + "252": "차원의 틈 오메가: 델타편 1", + "253": "차원의 틈 오메가: 델타편 2", + "254": "차원의 틈 오메가: 델타편 3", + "255": "차원의 틈 오메가: 델타편 4", + "256": "오메가: 델타편 1 (영웅)", + "257": "오메가: 델타편 2 (영웅)", + "258": "오메가: 델타편 3 (영웅)", + "259": "오메가: 델타편 4 (영웅)", + "262": "쿠가네 성", + "263": "락슈미 토벌전", + "264": "극 락슈미 토벌전", + "268": "보물고 우즈네어 운하", + "276": "보물고 우즈네어 운하 심층", + "277": "아스트라갈로스(기공전)", + "278": "극 신룡 토벌전", + "279": "스칼라 유적", + "280": "절 바하무트 토벌전", + "281": "왕도 라바나스터", + "283": "금단의 땅 에우레카 : 아네모스", + "284": "지옥뚜껑", + "285": "무한연속 박물함 (어려움)", + "286": "차원의 틈 오메가: 시그마편 1", + "287": "차원의 틈 오메가: 시그마편 2", + "288": "차원의 틈 오메가: 시그마편 3", + "289": "차원의 틈 오메가: 시그마편 4", + "290": "백호 토벌전", + "291": "극 백호 토벌전", + "292": "오메가: 시그마편 1 (영웅)", + "293": "오메가: 시그마편 2 (영웅)", + "294": "오메가: 시그마편 3 (영웅)", + "295": "오메가: 시그마편 4 (영웅)", + "473": "The Valentione`s Ceremony", + "474": "리오레우스 수렵전", + "475": "극 리오레우스 수렵전", + "476": "더 피스트 (팀 등급전)", + "478": "더 피스트 (등급전)", + "479": "더 피스트 (일반전)", + "480": "더 피스트 (크리스탈 타워 훈련장: 친선 경기)", + "481": "초코보 레이스: 튜토리얼", + "482": "제1장", + "483": "제2장", + "484": "제3장", + "485": "제4장", + "486": "제5장", + "487": "제6장", + "488": "제7장", + "489": "제8장", + "490": "제9장", + "491": "제10장", + "492": "제11장", + "493": "제12장", + "494": "제13장", + "495": "제14장", + "496": "제15장", + "497": "초코보 레이스:사골리", + "498": "초코보 레이스:코스타 델 솔", + "499": "초코보 레이스:트랑킬", + "500": "초코보 레이스:사골리", + "501": "초코보 레이스:코스타 델 솔", + "502": "초코보 레이스:트랑킬", + "503": "초코보 레이스:사골리", + "504": "초코보 레이스:코스타 델 솔", + "505": "초코보 레이스:트랑킬", + "506": "초코보 레이스:사골리", + "507": "초코보 레이스:코스타 델 솔", + "508": "초코보 레이스:트랑킬", + "509": "초코보 레이스:사골리", + "510": "초코보 레이스:코스타 델 솔", + "511": "초코보 레이스:트랑킬", + "512": "초코보 레이스:사골리", + "513": "초코보 레이스:코스타 델 솔", + "514": "초코보 레이스:트랑킬", + "515": "초코보 레이스:사골리", + "516": "초코보 레이스:코스타 델 솔", + "517": "초코보 레이스:트랑킬", + "518": "초코보 레이스:사골리", + "519": "초코보 레이스:코스타 델 솔", + "520": "초코보 레이스:트랑킬", + "521": "초코보 레이스:사골리", + "522": "초코보 레이스:코스타 델 솔", + "523": "초코보 레이스:트랑킬", + "524": "초코보 레이스:사골리", + "525": "초코보 레이스:코스타 델 솔", + "526": "초코보 레이스:트랑킬", + "527": "초코보 레이스:사골리", + "528": "초코보 레이스:코스타 델 솔", + "529": "초코보 레이스:트랑킬", + "530": "초코보 레이스:사골리", + "531": "초코보 레이스:코스타 델 솔", + "532": "초코보 레이스:트랑킬", + "533": "초코보 레이스:사골리", + "534": "초코보 레이스:코스타 델 솔", + "535": "초코보 레이스:트랑킬", + "536": "강엔 종묘", + "537": "츠쿠요미 토벌전", + "538": "극 츠쿠요미 토벌전", + "539": "절 알테마 웨폰 파괴 작전", + "540": "천궁탑 (1-10)", + "541": "천궁탑 (11-20)", + "542": "천궁탑 (21-30)", + "543": "천궁탑 (31-40)", + "544": "천궁탑 (41-50)", + "545": "천궁탑 (51-60)", + "546": "천궁탑 (61-70)", + "547": "천궁탑 (71-80)", + "548": "천궁탑 (81-90)", + "549": "천궁탑 (91-100)", + "550": "대등대 리도르아나", + "576": "LoVM: 미니온 클래스 (쉬움)", + "577": "LoVM: 진 미니온 클래스 (보통)", + "578": "LoVM: 극 미니온 클래스 (어려움)", + "579": "LoVM: 대회대전 (CPU대전)", + "580": "★더 피스트 (4 대 4 / 고정 소규모 파티)", + "581": "금단의 땅 에우레카 : 파고스", + "584": "성 모샨 식물원 (어려움)", + "585": "더 번", + "587": "차원의 틈 오메가: 알파편 1", + "588": "차원의 틈 오메가: 알파편 2", + "589": "차원의 틈 오메가: 알파편 3", + "590": "차원의 틈 오메가: 알파편 4", + "591": "오메가: 알파편 1 (영웅)", + "592": "오메가: 알파편 2 (영웅)", + "593": "오메가: 알파편 3 (영웅)", + "594": "오메가: 알파편 4 (영웅)", + "595": "쿠가네 다리 요짐보 토벌전", + "596": "주작 토벌전", + "597": "극 주작 토벌전", + "598": "금단의 땅 에우레카 : 피로스", + "599": "히든 고지", + "600": "도전! 점핑 어슬레틱", + "601": "도전! 점핑 어슬레틱", + "602": "도전! 점핑 어슬레틱", + "603": "도전! 점핑 어슬레틱", + "604": "도전! 점핑 어슬레틱", + "605": "도전! 점핑 어슬레틱", + "606": "도전! 점핑 어슬레틱", + "607": "도전! 점핑 어슬레틱", + "608": "도전! 점핑 어슬레틱", + "610": "데뷔 매치", + "611": "경계전선 김릿 다크", + "612": "브링 알라모드", + "613": "최초의 암벽 「시바그나」", + "614": "괴력의 철거인「클레이오스」", + "615": "길가메시 브라더스", + "616": "블라인드 퓨리", + "617": "시어 하드 어택", + "618": "푸른 이빨, 붉은 이빨", + "619": "일곱 빛깔의 맛「기모브」", + "620": "우상의 왕자「크롬도브」", + "621": "폭탄 봄의 퍼스트 어택", + "622": "기생 식물 「히도노라」", + "623": "주홍색 죽음의 요정 공주 「카밀라」", + "624": "죽어야 제대로!", + "625": "알락의 위협「전투 생물 시스템」", + "626": "호완의 수왕「티크바란」", + "627": "호유의 철거인「크레이오스 Mk-2」", + "628": "폭파 데스매치", + "629": "매혹의 꽃향기「리플렉티브 레베카」", + "630": "명콤비「오르토로스&티폰」", + "631": "분노의 합성수「아베데마크」", + "632": "폭발의 대소멸「그랜버봄」", + "633": "마수의 황태자「크론프린츠 베히모스」", + "634": "이형의 인형사「에베로기」", + "635": "악의 청마도사「아보카료프스」", + "636": "오본느 수도원", + "637": "청룡 정혼전", + "638": "극 청룡 정혼전", + "639": "금단의 땅 에우레카 : 히다토스", + "640": "출격! 에어포스 파일럿", + "641": "출격! 에어포스 파일럿", + "642": "출격! 에어포스 파일럿", + "643": "도마식마작: 일반 탁자 (단위변동있음)", + "644": "도마식마작: 상급 탁자 (단위변동있음)", + "645": "도마식마작: 4인세트 (쿠이탄 있음)", + "649": "도느 메그", + "650": "도마식마작: 4인세트 (쿠이탄 없음)", + "651": "키타나 신굴", + "652": "아모로트", + "653": "희망의 낙원 에덴: 각성편1", + "654": "희망의 낙원 에덴: 각성편1 (영웅)", + "655": "쌍둥이 시르쿠스", + "656": "말리카 큰우물", + "657": "티타니아 토벌전", + "658": "극 티타니아 토벌전", + "659": "굴그 화산", + "661": "애나이더 아카데미아", + "666": "이노센스 토벌전", + "667": "극 이노센스 토벌전", + "676": "홀민스터", + "682": "희망의 낙원 에덴: 각성편3", + "683": "희망의 낙원 에덴: 각성편3 (영웅)", + "684": "희망의 낙원 에덴: 각성편2", + "685": "희망의 낙원 에덴: 각성편2 (영웅)", + "687": "하데스 토벌전", + "689": "희망의 낙원 에덴: 각성편4", + "690": "희망의 낙원 에덴: 각성편4 (영웅)", + "692": "그랑 코스모스", + "693": "극 하데스 토벌전", + "694": "절 알렉산더 토벌전", + "695": "「훔바바파파」", + "696": "콧김 폭파 데스매치", + "697": "절묘한 괴뢰꾼 「두린」", + "698": "물과 불꽃의 노래", + "699": "「지크프리드」", + "700": "복제된 공장 페허", + "701": "온살 하카 (단시그 나담)", + "702": "하얀 맹약, 검은 밀약", + "703": "이 가슴이 원하는 대로", + "705": "도전! 점핑 어슬레틱", + "706": "도전! 점핑 어슬레틱", + "707": "도전! 점핑 어슬레틱", + "708": "도전! 점핑 어슬레틱", + "709": "도전! 점핑 어슬레틱", + "710": "도전! 점핑 어슬레틱", + "711": "도전! 점핑 어슬레틱", + "712": "도전! 점핑 어슬레틱", + "713": "도전! 점핑 어슬레틱", + "714": "애니드라스 아남네시스", + "715": "희망의 낙원 에덴: 공명편1", + "716": "희망의 낙원 에덴: 공명편1 (영웅)", + "717": "루비 웨폰 파괴작전", + "718": "극 루비 웨폰 파괴작전", + "719": "희망의 낙원 에덴: 공명편2", + "720": "희망의 낙원 에덴: 공명편2 (영웅)", + "721": "먼바다 낚시", + "722": "운해채집 디아뎀", + "724": "영웅의 잠을 방해하는건 너로구나", + "725": "극 보즈야 추억전", + "726": "희망의 낙원 에덴: 공명편3", + "727": "희망의 낙원 에덴: 공명편3 (영웅)", + "728": "희망의 낙원 에덴: 공명편4", + "729": "희망의 낙원 에덴: 공명편4 (영웅)", + "730": "먼바다 낚시", + "731": "먼바다 낚시", + "732": "먼바다 낚시", + "733": "먼바다 낚시", + "734": "먼바다 낚시", + "735": "보즈야 남부전선", + "736": "인형들의 군사기지", + "737": "칠흑결전 노르브란트", + "738": "빛의 전사 토벌전", + "739": "극 빛의 전사 토벌전", + "742": "운해채집 디아뎀 제도", + "744": "환 시바 토벌전", + "745": "보물고 리 기어 던전 제전", + "746": "마술공방 마토야의 아틀리에", + "747": "희망의 낙원 에덴: 재생편2", + "748": "희망의 낙원 에덴: 재생편2 (영웅)", + "749": "희망의 낙원 에덴: 재생편1", + "750": "희망의 낙원 에덴: 재생편1 (영웅)", + "751": "희망의 낙원 에덴: 재생편3", + "752": "희망의 낙원 에덴: 재생편3 (영웅)", + "753": "운해채집 디아뎀 제도", + "754": "Anything Gogo's", + "755": "트리플 트라이어드: 공식 토너먼트", + "756": "트리플 트라이어드: 커스텀 토너먼트", + "757": "환 타이탄 토벌전", + "758": "희망의 낙원 에덴: 재생편4", + "759": "희망의 낙원 에덴: 재생편4 (영웅)", + "762": "에메랄드 웨폰 파괴작전", + "763": "극 에메랄드 웨폰 파괴작전", + "766": "도마식마작: 동풍전 일반 탁자 (단위변동있음)", + "767": "도마식마작: 동풍전 상급 탁자 (단위변동있음)", + "768": "도마식마작: 동풍전 4인세트 (쿠이탄 있음)", + "769": "도마식마작: 동풍전 4인세트 (쿠이탄 없음)", + "770": "먼바다 낚시", + "771": "먼바다 낚시", + "772": "먼바다 낚시", + "773": "먼바다 낚시", + "774": "먼바다 낚시", + "775": "먼바다 낚시", + "760": "Delubrum Reginae", + "761": "Delubrum Reginae (영웅)" + }, + "areas": { + "134": { + "name": "중부 라노시아", + "fates": { + "220": "거대한 들소", + "221": "여름여울의 공포", + "222": "대왕땅벌과 노란셔츠", + "223": "데네벨 관문 방어 훈련", + "225": "끝없는 두더지 잡기", + "226": "해군식 통과의례", + "227": "양들의 소란", + "229": "뛰는 놈 위에 나는 놈", + "231": "닥치는 대로 자른다", + "233": "쫓는 자와 쫓기는 자", + "235": "그 바다생물을 보라", + "237": "아젤리스 강의 다리", + "238": "피에 젖은 맹견", + "239": "아름다운 불량배 강", + "240": "해파리가 하늘을 날던 날", + "533": "돌아온 거대 화염마수", + "649": "그 바다생물을 보라", + "687": "검은 악마: 실험 결과", + "688": "검은 악마: 과격한 숙녀", + "693": "별빛축제: 마법 눈사람", + "717": "거대 알 사냥" + } + }, + "135": { + "name": "저지 라노시아", + "fates": { + "245": "불길한 왕자", + "246": "위험한 밭일", + "249": "새끼 치는 두꺼비", + "250": "검은 날개", + "251": "밀가루 전쟁", + "257": "날아다니는 위장", + "260": "골칫덩어리 밀항자", + "261": "우리는 해적이다", + "262": "샘터의 싸움", + "264": "삼나무 숲의 전투", + "265": "강인한 산길잡이", + "333": "기세등등한 마견", + "534": "돌아온 거대 화염마수", + "666": "신비한 마물 `골렘`", + "667": "신비한 마물 `벽돌골렘`", + "694": "별빛축제: 마법 눈사람", + "718": "거대 알 사냥" + } + }, + "137": { + "name": "동부 라노시아", + "fates": { + "267": "포도주 내놔!", + "268": "포도주 마시고 싶어!", + "271": "신선한 고기", + "272": "달걀귀신", + "274": "사마귀 퇴치", + "278": "하얀 거탑", + "279": "콜리브리의 저녁식사", + "280": "떠돌이 소매치기", + "282": "해변의 싹둑게", + "286": "죽은 자의 대변인", + "287": "사랑은 운명, 운명은 죽음", + "334": "여름으로 가는 문", + "335": "죽음의 찬탈자", + "532": "돌아온 거대 화염마수", + "560": "굶주린 용병의 반란", + "561": "술꾼 마수", + "562": "꿀벌을 꾀는 달콤한 꿀", + "563": "심록의 거대 마수", + "564": "불길한 알뿌리", + "565": "집으로", + "566": "알뿌리 으깨기", + "689": "검은 악마: 실험 결과", + "690": "검은 악마: 과격한 숙녀", + "701": "광란의 알 축제", + "913": "불꽃축제: 미풍양속의 수호자", + "914": "불꽃축제: 한여름의 열광", + "915": "불꽃축제: 위험한 불장난", + "916": "불꽃축제: 바다야수 조련사", + "917": "불꽃축제: 호색한의 말로", + "918": "불꽃축제: 해적의 밀주", + "945": "봄바드 습격 경보!", + "946": "소방 전사 출동!" + } + }, + "138": { + "name": "서부 라노시아", + "fates": { + "289": "보급선을 지켜라", + "290": "폭식하는 괴물새", + "291": "밀밭의 파수꾼", + "295": "노련한 무사", + "297": "세관공사 강제수사", + "298": "공공의 적", + "303": "고향에서 보낸 편지", + "304": "도도 둥지 파괴명령", + "306": "생사를 가르는 덫", + "308": "협상 결렬", + "309": "멍청한 경호원", + "310": "데네벨 가도의 결투", + "312": "곤충군단 출현", + "336": "채소혁명 `만드라즈`", + "568": "북쪽 방파벽 전투: 전력 정찰", + "569": "북쪽 방파벽 전투: 주력 부대 습격", + "570": "남쪽 방파벽 전투: 전력 정찰", + "571": "남쪽 방파벽 전투: 주력 부대 습격", + "572": "냉철한 전략가", + "574": "바다뱀의 말로", + "575": "바다뱀 선장", + "576": "죽음의 행진", + "577": "이국에서 온 괴물곤충", + "578": "수신을 부르는 자", + "650": "폭식하는 괴물새", + "702": "현자의 알" + } + }, + "139": { + "name": "고지 라노시아", + "fates": { + "314": "맹수 먹는 요괴새", + "317": "수송부대 방어명령", + "320": "어제의 동지는 오늘의 적", + "321": "시원한 온천조개탕", + "322": "청동호수의 터주", + "323": "위험한 식용게", + "329": "온천이 키운 조개", + "331": "비운의 용병", + "332": "호수 위를 누벼라!", + "451": "가여운 여인의 제재소 부흥: 식량 방어", + "452": "가여운 여인의 제재소 부흥: 게 브 격퇴", + "453": "가여운 여인의 제재소 부흥: 커얼 처치", + "454": "가여운 여인의 제재소 부흥: 야생 물소 처치", + "668": "신비한 마물 `골렘`", + "669": "신비한 마물 `벽돌골렘`", + "670": "신비한 마물 `골렘`", + "671": "신비한 마물 `황금골렘`", + "703": "광란의 달걀 찾기" + } + }, + "140": { + "name": "서부 다날란", + "fates": { + "342": "긴급 점검", + "343": "강제 추방", + "344": "투쟁을 위한 분노의 철퇴", + "345": "대지의 망치", + "346": "땅을 굳게 하는 것", + "347": "수수께끼의 거대 생물", + "348": "사막의 패왕", + "349": "황야의 무법자", + "350": "들개들의 천국", + "352": "악의 없는 아귀", + "353": "식탐 많은 왕게", + "354": "부상자를 호송하라", + "355": "싸움은 계속된다", + "356": "코브란 대이동", + "357": "황금투구를 쓴 거인", + "361": "망치를 두드려라", + "366": "키다리 아저씨", + "367": "고스트 버스터즈", + "683": "검은 악마: 실험 결과", + "684": "검은 악마: 과격한 숙녀", + "704": "광란의 달걀 찾기", + "911": "버그 잡기" + } + }, + "141": { + "name": "중부 다날란", + "fates": { + "370": "천박한 승부사", + "373": "저녁밥을 사수하라!", + "374": "밑 빠진 독 키키룬", + "375": "궤짝 말고 관짝", + "376": "반숙영웅", + "377": "사람 잡는 아귀", + "378": "선인장 샐러드", + "379": "개미다~!", + "381": "키브론 가의 주인", + "383": "가도를 가다", + "385": "부정한 거대 두꺼비", + "389": "성난 보물수호자", + "393": "모래성의 맹장", + "535": "돌아온 거대 화염마수", + "660": "신비한 마물 `골렘`", + "661": "신비한 마물 `벽돌골렘`", + "695": "별빛축제: 마법 눈사람", + "719": "거대 알 사냥", + "912": "버그 잡기" + } + }, + "145": { + "name": "동부 다날란", + "fates": { + "191": "하늘다리 사투: 전초전", + "192": "하늘다리 사투: 방어전", + "193": "하늘다리 사투: 즈즈룬 격퇴", + "194": "하늘다리 사투: 나요크 로 격퇴", + "195": "하늘다리 사투: 시민 구출 작전", + "394": "야수를 죽여라", + "395": "강철의 구멍술사", + "397": "아말쟈군 요격 작전", + "398": "침공 작전을 저지하라", + "400": "금 장터 방어전", + "401": "연옥의 도굴꾼", + "402": "흉내쟁이 혼내주기", + "406": "동부전선 이상 없다", + "407": "악몽의 모발약탈자", + "409": "요괴꽃이 피었습니다", + "412": "낙원의 샘", + "413": "뿔이 긴 어르신", + "536": "돌아온 거대 화염마수", + "540": "꿈틀꿈틀 도브란", + "541": "거울의 기사", + "542": "금발의 귀공자", + "543": "추악한 합성수", + "652": "섬광 강림: 거대 마수 요격전", + "696": "별빛축제: 마법 눈사람", + "705": "현자의 알", + "720": "거대 알 사냥" + } + }, + "146": { + "name": "남부 다날란", + "fates": { + "419": "해골 두목", + "420": "콩 수프는 질렸어", + "421": "리틀 알라미고 방어전", + "422": "진리를 밝혀라", + "423": "느긋한 압살자", + "424": "우리는 제2전투대대", + "427": "끓어오르는 괴력", + "429": "사막의 아이들", + "430": "운명의 대변인", + "431": "잡는 자와 잡히는 자", + "432": "비레고의 수호자", + "434": "정찰병의 임무", + "436": "극악무도한 암살자", + "437": "메마른 바다", + "441": "금쪽같은 내 새끼", + "455": "사막의 황제", + "456": "가지지 못한 자", + "545": "황야의 소화전", + "546": "비운의 투사", + "548": "정의란 무엇인가", + "549": "등딱지를 걷어차라!", + "550": "정예부대 `선혈군단`", + "551": "오늘의 운세", + "552": "친구와 가족", + "553": "제1관문 공략전", + "554": "속사의 달인", + "555": "모래 위의 발자국", + "557": "아말쟈군 특수부대 `불꽃송곳니회`", + "558": "화염신을 부르는 자", + "651": "섬광 강림: 거대 마수 요격전", + "685": "검은 악마: 실험 결과", + "686": "검은 악마: 과격한 숙녀", + "706": "광란의 달걀 찾기" + } + }, + "147": { + "name": "북부 다날란", + "fates": { + "446": "허상의 눈", + "447": "발톱깎이", + "449": "불조심", + "450": "신형 장갑재 시험", + "457": "역공학을 통한 분석", + "556": "청린 정제소 일손 돕기", + "637": "작열하는 귀족", + "638": "꿀꺽꿀꺽 도브란", + "639": "감시자의 눈", + "641": "매복한 도브란", + "642": "무역로 청린수길", + "643": "구세신께 바치는 제물: 납치편", + "644": "구세신께 바치는 제물: 함정편", + "645": "구세신께 바치는 제물: 응징편", + "646": "구세신께 바치는 제물: 요마편", + "647": "미쳐 날뛰는 거대 마수" + } + }, + "148": { + "name": "검은장막 숲 중부삼림", + "fates": { + "120": "숲속의 질주", + "121": "즐거운 버섯따기", + "122": "스프리건 이사하는 날", + "123": "혼탁함의 결정체", + "124": "벌레 조심하세요", + "125": "식인 괴물새", + "126": "다리가 튼튼한 폭군", + "127": "분노한 돼지의 질주", + "128": "강력한 소악마 `아르슈`", + "130": "영원그늘 수확제", + "131": "대지신의 망각을 잊지 말기를", + "136": "공포의 교관", + "137": "병을 퍼뜨리는 요괴꽃", + "138": "초코초코초코초코보", + "139": "그대의 영혼에 평안이 있기를", + "140": "대탈주", + "141": "갈반스 감시초소 지원", + "142": "물컹한 대식가", + "196": "고대의 투신", + "197": "고대의 투신", + "208": "무당벌레의 천적", + "209": "연못 파괴자", + "537": "돌아온 거대 화염마수", + "600": "린드부름의 습격", + "601": "무지 즐거운 버섯따기", + "602": "굿`바이", + "603": "진리를 찾아서", + "604": "음험한 마물", + "672": "신비한 마물 `골렘`", + "673": "신비한 마물 `벽돌골렘`", + "697": "별빛축제: 마법 눈사람", + "707": "광란의 달걀 찾기", + "1325": "별빛축제 `숲의 도둑`" + } + }, + "152": { + "name": "검은장막 숲 동부삼림", + "fates": { + "143": "벌꿀 전쟁", + "144": "전염병 살포기", + "145": "전장까지 앞으로 몇 말름?", + "148": "비밀의 화원", + "149": "번식기의 끝", + "150": "젊은 두목원숭이", + "151": "줄다리 사투", + "152": "광기 어린 수호자들", + "198": "고대의 투신", + "199": "고대의 투신", + "200": "고대의 투신", + "212": "아흔 아홉덩굴", + "213": "실프와 함께 사라지다", + "214": "대머리수리의 만찬", + "217": "달콤한 짐꾼", + "218": "비정한 수확자", + "607": "지나간 날들의 빛", + "608": "오츄 수확", + "609": "제멋대로인 귀부인", + "610": "종달새의 지저귐 조우전", + "611": "계속되는 종달새의 지저귐 조우전", + "612": "제국군 천인대장", + "615": "젖뿌리 뽑기", + "616": "유곡의 약사", + "618": "두꺼비의 꿈", + "619": "유곡의 위병", + "620": "무지무지 즐거운 버섯따기", + "622": "경건한 양육자", + "679": "검은 악마: 실험 결과", + "680": "검은 악마: 과격한 숙녀", + "691": "기동병사 프로토아머", + "692": "광란의 싸움꾼" + } + }, + "153": { + "name": "검은장막 숲 남부삼림", + "fates": { + "153": "날쌘 영양", + "154": "뿌리를 건너고 늪을 지나서", + "158": "밀렵매매 쌍방처벌", + "159": "붉은둔덕 요새 전투: 공략전", + "160": "붉은둔덕 요새 전투: 점령전", + "161": "붉은둔덕 요새 전투: 방어전", + "162": "붉은둔덕 요새 전투: 요격전", + "163": "마지막 잎새", + "164": "수려한 무법자", + "166": "술집의 단골손님", + "167": "사랑엔 시간이 필요해", + "168": "확고한 증거", + "169": "암시장 조합장", + "170": "통행료는 주먹으로 내겠다", + "171": "당장 나가주시죠", + "172": "잃어버린 물건을 찾아서", + "190": "고독한 골렘", + "201": "고대의 투신", + "202": "고대의 투신", + "203": "고대의 투신", + "204": "고대의 투신", + "215": "불 속으로 뛰어드는 나나니단", + "624": "출렁이는 땅", + "626": "거북 네 이노오오옴!", + "627": "냄새의 근원 차단", + "628": "최후의 멧돼지왕", + "681": "검은 악마: 실험 결과", + "682": "검은 악마: 과격한 숙녀", + "708": "광란의 달걀 찾기" + } + }, + "154": { + "name": "검은장막 숲 북부삼림", + "fates": { + "174": "오합지졸", + "178": "붉은 왕이 될 유충", + "179": "가을박 마을 지킴이", + "180": "산길잡이의 부탁", + "183": "혼란탈출", + "184": "너도나도 좋아하는 문투이 콩", + "185": "매혹적인 향기", + "187": "이크살족 강습부대 요격", + "188": "굶주린 지즈가 원하는 것", + "189": "오리나무 샘 청소", + "205": "고대의 투신", + "206": "고대의 투신", + "207": "고대의 투신", + "216": "달의 반역자", + "538": "돌아온 거대 화염마수", + "631": "벌채부대 요격전", + "632": "유적의 망령기사", + "633": "이크살군 벌채장 강습 작전", + "634": "분노한 숲의 수호자", + "674": "신비한 마물 `골렘`", + "675": "신비한 마물 `벽돌골렘`", + "676": "신비한 마물 `골렘`", + "677": "신비한 마물 `황금골렘`", + "698": "별빛축제: 마법 눈사람", + "722": "거대 알 사냥" + } + }, + "155": { + "name": "커르다스 중앙고지", + "fates": { + "460": "늑대들의 전쟁", + "463": "검은 탄환", + "464": "강가의 복수자", + "465": "겨울 이야기", + "466": "별에 소원을", + "467": "야생악어 던디", + "469": "커르다스의 하얀 늑대", + "470": "움직이는 요새", + "472": "흘러라 눈물이여", + "473": "환희, 참회, 거친 눈보라", + "474": "에이비스 킬러", + "475": "입 큰 악귀", + "479": "얼어붙은 파동", + "480": "기병의 천적", + "482": "피 튀는 거리", + "483": "촉발된 전쟁", + "484": "뼈 탐식자", + "486": "아유나르트의 의지", + "487": "따스함을 찾아서", + "489": "순례길", + "490": "어리석은 용사", + "491": "아직은 머나먼 별빛", + "493": "설산의 습격자", + "494": "붉은 날개 `록`", + "496": "용의 뜻에 따라서!", + "497": "얼음땡", + "498": "입식지 확장을 저지하라", + "499": "후엘록 네 자매", + "500": "명장의 기술", + "501": "스바라 요격작전: 공병호송", + "502": "스바라 요격작전: 포격준비", + "503": "스바라 요격작전: 대응사격", + "504": "스바라 요격작전: 인해전술", + "505": "전설의 마수", + "506": "부상당한 마수", + "507": "돌아온 사나이", + "508": "바람신을 부르는 자", + "653": "섬광 강림: 기계 마수 토벌전", + "654": "섬광 강림: 기계 마수 토벌전", + "699": "별빛축제: 마법 눈사람", + "709": "현자의 알" + } + }, + "156": { + "name": "모르도나", + "fates": { + "512": "잃어버린 풍경", + "514": "엉킨덩굴 습지대 대청소", + "516": "늪지대의 원혼", + "517": "몰볼, 분노의 대증식", + "520": "종합정비계획", + "521": "잔인한 악귀", + "522": "성지순례", + "523": "거인의 부동산 확장", + "524": "히포그리프의 만찬", + "525": "흐트러진 은빛 머리칼", + "526": "하팔릿의 남하", + "527": "마수의 야습", + "529": "여행길의 좋은 친구", + "530": "달콤한 유혹", + "655": "섬광 강림: 아누비스 섬멸전", + "656": "섬광 강림: 아누비스 섬멸전", + "657": "섬광 강림: 시룡 토벌전", + "658": "섬광 강림: 시룡 토벌전" + } + }, + "180": { + "name": "외지 라노시아", + "fates": { + "580": "내가 가는 길", + "581": "흑와단의 원수", + "583": "커얼아, 커얼아", + "586": "땅굴단의 산길잡이", + "587": "시굴지 강습 작전", + "588": "전방에 폭탄", + "589": "뇌우를 부르는 자", + "591": "전설의 거룡", + "593": "광기의 산맥", + "594": "폐기된 실험체", + "595": "보급부대 구출명령", + "597": "벌레 양식자", + "598": "깨어난 석상", + "599": "바위신을 부르는 자", + "700": "요마 사냥꾼" + } + }, + "397": { + "name": "커르다스 서부고지", + "fates": { + "787": "지켜보고 있다", + "788": "순례 기사", + "789": "빙판길 주의!", + "791": "흑철교 전투", + "792": "뻣뻣한 흰털짐승", + "793": "야크를 먹는 거인", + "794": "영광의 성 피네아 연대", + "795": "곰 조심", + "796": "예티의 천적", + "798": "수인 예티", + "800": "용이 잠든 섬 전투", + "801": "얼어붙은 꽃", + "802": "어스름 은빛늑대", + "805": "지휘관님!", + "807": "현혹하는 시선", + "809": "백설공포", + "810": "식인 얼음과자", + "811": "용의 졸개 토벌작전", + "812": "조룡의 왕", + "813": "얼음 위의 늑대", + "814": "주정뱅이 야수", + "815": "젊은 용기사", + "816": "매의 보금자리를 위협하는 자", + "817": "네 공도 내 것", + "908": "아이스크림 두통", + "909": "냉혹한 얼음용" + } + }, + "398": { + "name": "고지 드라바니아", + "fates": { + "818": "전설의 초코보", + "819": "초코보 숲의 파수꾼", + "820": "교묘한 사냥꾼", + "821": "부러지지 않는 화살", + "822": "고고한 맹수", + "823": "연어 전쟁", + "824": "복잡미묘한 향기", + "825": "추악한 순례자", + "826": "역시 고기가 최고", + "827": "적의 적도 나의 적", + "828": "이단 선동가", + "829": "싸움을 끝내는 것", + "830": "경계를 나누는 강", + "831": "알 사수 전쟁", + "832": "구름안개 거리의 학살자", + "833": "어머니의 분노", + "834": "지하의 발소리", + "835": "용인의 하극상", + "836": "소란스러운 죽음", + "837": "낙원의 샘", + "838": "강습하는 갑룡", + "902": "번개야수의 여왕", + "903": "역습의 여왕", + "904": "역습의 여왕", + "905": "환영의 여왕", + "906": "환영의 여왕", + "907": "환영의 여왕", + "910": "변모한 처녀" + } + }, + "399": { + "name": "저지 드라바니아", + "fates": { + "756": "악마의 기계", + "757": "보복자들", + "758": "전면 개조형 기체", + "759": "왕대모벌의 습격", + "760": "야성의 충돌", + "761": "왕눈이 마물 소", + "762": "도서관 청소", + "763": "꽃가루 전선 이상 있다", + "764": "피 빠는 부유초", + "766": "고브고브 전쟁", + "767": "숙련된 전투 지휘관", + "768": "꼬리를 세워라!", + "769": "야수의 가장", + "770": "서방 전격전", + "771": "몰볼을 죽여라", + "772": "냄새나는 아가씨", + "773": "이딜샤이어 사냥 협회", + "774": "피에 젖은 폭군", + "775": "곰의 수난", + "777": "사역마는 괴로워", + "778": "개구리를 위하여 종은 울린다", + "779": "샬레이안의 그림자", + "780": "애서가의 우울", + "781": "코카트리스의 추억", + "782": "끝없는 시간의 흐름 끝에서", + "783": "주인을 기다리는 자", + "784": "물고기 포식자", + "785": "누에굴", + "786": "실 뽑는 전문가" + } + }, + "400": { + "name": "드라바니아 구름바다", + "fates": { + "725": "구름 속 수생생물", + "726": "원시공룡이여, 안녕히", + "727": "흑룡의 사도", + "728": "저축왕 모그리", + "731": "잃어버린 세계", + "732": "구름바다에 치는 천둥", + "735": "배부른 공룡", + "736": "긴급출동 툴리핸드", + "737": "긴급출동 뷔브르", + "738": "유적 감시자", + "740": "드래곤과 춤을", + "741": "드래곤과 또다시 춤을", + "742": "사나운 갑주드래곤", + "744": "밤과 안개", + "746": "용쟁혈투", + "747": "황혼의 비룡", + "748": "너는 누구냐", + "751": "맹염의 불꽃용", + "752": "흡입력을 잃지 않는다", + "753": "구름바다의 문제아", + "754": "신성함과 사악함이 교차하는 균열", + "755": "어리석은 문제아", + "868": "검은미늘 토벌전: 백룡 지원", + "869": "검은미늘 토벌전: 추격 작전", + "870": "검은미늘 토벌전: 총력전", + "871": "창천의 백룡", + "872": "하얀 궁전 방어전: 아기용 구출", + "873": "하얀 궁전 방어전: 맹룡 토벌", + "874": "하얀 궁전 방어전: 모그리 구출" + } + }, + "401": { + "name": "아발라시아 구름바다", + "fates": { + "839": "고양이의 돌진", + "840": "가스토르니스 둥지 파괴 명령", + "841": "화려한 뚱보 새", + "842": "구름바다 대난투", + "843": "장미의 피를 마시고 싶어", + "844": "검은 새", + "845": "지나친 혈기", + "846": "불법 투기자", + "847": "구름바다의 전사", + "851": "멋진 신세계", + "852": "하늘 위의 구름", + "853": "도망자", + "854": "추적자", + "855": "폭식자 바위인형", + "856": "보급로를 끊어라", + "857": "초대받지 않은 손님", + "860": "공포의 대명사", + "861": "구름신의 사제", + "862": "케나바누의 제자들", + "863": "복수의 사제", + "864": "융단폭격", + "865": "광기 어린 노랫소리", + "866": "구름바다의 광풍", + "867": "흉조는 구름을 넘고", + "875": "거대한 부리의 괴조" + } + }, + "402": { + "name": "아지스 라", + "fates": { + "877": "태고의 위협: 야광화 격멸전", + "878": "태고의 위협: 야광화 격멸전", + "879": "태고의 위협: 야광화 격멸전", + "880": "제보 번호 199 버그", + "881": "윤회의 뱀", + "882": "알라그 위협의 메커니즘", + "883": "간사한 마수", + "884": "마수 사냥", + "885": "충의의 요괴왕", + "886": "돌연변이 꽃밭", + "887": "강철의 도시", + "888": "잃어버린 기술", + "889": "전자동 수작업", + "890": "마도기사장", + "891": "감마 전선의 격전: 동부", + "892": "감마 전선의 격전: 서부", + "893": "감마 전선의 격전: 남부", + "894": "지성을 잃은 폭풍", + "895": "머리 많은 인조 드래곤", + "897": "대량 발주 오류 사건", + "898": "불길한 실험체", + "899": "영혼 없는 육체", + "900": "상급 알라그 사용자", + "901": "꿈꾸는 무인기" + } + }, + "411": { + "name": "기라바니아 변방지대", + "fates": { + "1112": "동맹군 훈련소: 병사편", + "1113": "동맹군 훈련소: 하사편", + "1114": "동맹군 훈련소: 장교편", + "1115": "악어, 악어, 악어 떼다!", + "1116": "곰과 함께 춤을", + "1117": "사프리아의 아이들", + "1118": "혼합림의 커다란 곰", + "1119": "비극의 돌연변이", + "1120": "변방 경비", + "1121": "변방 경비 외전", + "1122": "다음 바위에 계속", + "1124": "초코보가 아니야", + "1125": "잠자리는 무겁게 짓누른다", + "1126": "실은 이끼 출신", + "1127": "밀서는 전해져야 한다", + "1128": "그레이트!", + "1129": "나무인간 장로", + "1130": "거대 식인 거미", + "1131": "개미귀신은 안 물어요", + "1132": "뿔이 큰 탈주 병사", + "1133": "신석기시대", + "1134": "빼앗긴 자들", + "1135": "폭주하는 거대 코끼리", + "1136": "피를 나눈 자매", + "1137": "백은색 유괴범", + "1138": "비늘을 가르는 발톱", + "1139": "태양의 딸", + "1140": "들개", + "1141": "높은 마을의 여자" + } + }, + "412": { + "name": "기라바니아 산악지대", + "fates": { + "1173": "완전 채식주의", + "1174": "채식요리", + "1175": "배고픈 사기꾼", + "1176": "집으로 가는 길", + "1177": "피의 수확", + "1178": "농민의 악몽", + "1179": "피의 음악", + "1180": "큰메뚜기의 이민", + "1181": "말 없는 나무꾼", + "1182": "나비의 왕비", + "1184": "알라가나 방위선", + "1185": "전설적인 돌팔이 의사", + "1186": "그리핀 이야기", + "1187": "나비의 꿈", + "1188": "흉악한 주사위", + "1189": "고문관의 그림자", + "1190": "고원 악마 벌레", + "1191": "부정한 짐승", + "1193": "에루카 탐색대의 대모험", + "1194": "굵은팔 습격자", + "1195": "해충 박멸", + "1196": "피로부터 생을 얻노라", + "1197": "폭풍의 원흉", + "1198": "집행관의 핏줄", + "1199": "바람과 함께 나타나다", + "1200": "우아한 방화범", + "1201": "용감한 큰메뚜기", + "1202": "복수심에 불타는 홀아비", + "1203": "퇴마사", + "1204": "행운의 대식가", + "1205": "자씨족 전사", + "1207": "폭주하는 최종병기" + } + }, + "413": { + "name": "기라바니아 호반지대", + "fates": { + "1103": "전설의 뇌마", + "1104": "전설의 뇌마", + "1105": "전설의 뇌마", + "1272": "로흐 셀 호숫가의 전투", + "1273": "비키지 않는 거대 두꺼비", + "1274": "비련의 처녀", + "1275": "시끄러운 아바돈", + "1276": "죽음의 향기", + "1277": "하얗고 큰 얼굴", + "1278": "인기 없는 괴물", + "1279": "공허한 노목", + "1280": "떨어져 나온 바위 야수", + "1281": "번갯불의 마물 소", + "1282": "단두대로의 초대", + "1283": "지나간 나날의 바람", + "1284": "죽을 병을 옮기는 자", + "1285": "죽음을 고하는 하얀 벌레", + "1286": "광기 어린 광석 벌레", + "1287": "축축한 물고기", + "1288": "죽은 자는 말이 없다", + "1289": "소금의 연인", + "1290": "새하얀 쇠집게", + "1291": "낭카 이동 시대", + "1292": "하얀 침략자", + "1293": "꽃가루 전쟁", + "1294": "풀의 여왕", + "1295": "염호의 쇠톱", + "1296": "미노타우로스의 접시", + "1297": "근위대", + "1298": "나비 효과", + "1299": "지반이 무너져도 솟아날 구멍이 있다", + "1300": "약용 거머리", + "1301": "움직이는 진원지", + "1302": "산", + "1303": "안셀롯의 한탄", + "1304": "안셀롯의 두려움", + "1305": "안셀롯의 소원" + } + }, + "421": { + "name": "홍옥해", + "fates": { + "1142": "귀신물범의 심부름꾼", + "1143": "매혹적인 유실물", + "1144": "불길한 괴조", + "1145": "어촌의 위협", + "1146": "푸른 홍옥", + "1147": "패배한 투구게", + "1148": "화염을 두른 자", + "1149": "붉은 산호초", + "1150": "붉은등의 침입", + "1151": "바다에서 온 침략 생물", + "1152": "붉은등의 날뛰는 연", + "1153": "비행 상어 공주", + "1154": "화를 부르는 새", + "1155": "해변에서 바늘 찾기", + "1156": "붉은등 바다를 건너다", + "1157": "꿈의 언덕", + "1158": "북풍의 등에서", + "1159": "무례한 귀신물범", + "1160": "그래도 수라의 길을 걷는 너", + "1161": "격류의 거북이 닌자", + "1162": "붉은등의 보물", + "1163": "모르는 게 약", + "1164": "하늘 상어", + "1165": "부도덕한 승려", + "1166": "도둑 귀신물범", + "1167": "병법 수행", + "1168": "붉은등 역날베기", + "1170": "투구 깨기", + "1171": "바다의 귀부인", + "1172": "꿈꾸는 장군" + } + }, + "422": { + "name": "얀샤", + "fates": { + "1106": "아홉 꼬리 여우 요괴", + "1107": "아홉 꼬리 여우 요괴", + "1108": "아홉 꼬리 여우 요괴", + "1109": "그 이름은 미쿠즈메", + "1110": "킨코의 소원", + "1111": "긴코의 소원", + "1208": "교군의 불행", + "1209": "교군의 비운", + "1210": "마비된 격정", + "1211": "인랑: 붉은 발자국", + "1212": "인랑: 강철의 사냥개", + "1213": "붉은등 칼 사냥꾼", + "1214": "붉은뿔부리 흉조 사냥", + "1215": "메기를 노리는 뱀", + "1216": "소름끼치는 비산혈", + "1217": "음식 사냥꾼", + "1218": "마구잡이", + "1219": "호랑이 요람", + "1220": "괴이한 벌레", + "1221": "장수하지 못하리라", + "1222": "원숭이 대군단", + "1223": "긴팔이 아저씨", + "1224": "논메기 모내기", + "1225": "붉은뿔부리 알은 누구의 것", + "1226": "전원의 도깨비불", + "1227": "붉은 배우", + "1228": "오염된 물의 정령", + "1229": "검푸른 요마견", + "1230": "해를 삼키는 새", + "1231": "발광하는 허수아비", + "1232": "나마즈오 어쩌지", + "1233": "인랑족 타락무사", + "1234": "열사전", + "1235": "목욕탕을 지켜줘!", + "1236": "머리 큰 폭군", + "1237": "정정한 호랑이", + "1238": "반역자 거병", + "1239": "요마견 전설", + "1240": "음양사: 키요후사", + "1241": "음양사: 코자" + } + }, + "423": { + "name": "아짐 대초원", + "fates": { + "1242": "사냥꾼을 사냥하는 자", + "1243": "재회를 방해하는 자", + "1244": "북부의 여장부", + "1245": "밀렵꾼들", + "1246": "너른 하늘의 유괴범", + "1247": "울부짖는 야인", + "1248": "김매기 달인", + "1249": "윙윙윙", + "1250": "조용한 제재", + "1251": "매머드와 살려면", + "1252": "초원의 붉은 번개", + "1253": "새", + "1254": "다산의 여왕", + "1255": "때로는 참회를", + "1256": "냄새가 풀풀", + "1257": "굶주린 뿌리인간", + "1258": "대초원의 괴물", + "1259": "돌인간 영웅", + "1260": "거북이가 아우라한테 한 말", + "1261": "귀갓길에 오른 소몰이꾼 소녀", + "1262": "붉은 사막", + "1263": "야수 사냥", + "1264": "잔혹한 패자", + "1265": "다가오는 악취", + "1266": "불놀이야", + "1267": "긴엄니 압살자", + "1268": "우아한 잡초의 반항", + "1269": "순간의 악몽", + "1270": "되살아나는 악몽", + "1271": "패도로 귀환한 자", + "1306": "다타크족의 여행: 윙윙잠자리 조우", + "1307": "다타크족의 여행: 거단 습격 ", + "1308": "다타크족의 여행: 양젖 짜기", + "1309": "다타크족의 여행: 긴털들소 사냥", + "1310": "다타크족의 여행: 거단 재습격", + "1311": "다타크족의 여행: 우군드 강습", + "1312": "다타크족의 여행: 사냥꾼 구출", + "1313": "다타크족의 여행: 굴로굴로 토벌", + "1315": "다타크족의 여행: 마탕가 강습", + "1316": "다타크족의 여행: 마탕가 조우", + "1318": "다타크족의 여행: 고로족 구출", + "1319": "다타크족의 여행: 마탕가 역습", + "1320": "다타크족의 여행: 대왕 출진" + } + }, + "501": { + "name": "레이크랜드", + "fates": { + "1496": "자엽단과의 싸움: 거점 준비", + "1497": "자엽단과의 싸움: 거점 구축", + "1498": "선혈의 가짜 용", + "1499": "늑대는 울지 않는다", + "1500": "나무꾼의 노래", + "1501": "자엽단과의 싸움: 나무꾼 습격", + "1502": "자엽단과의 싸움: 비겁한 함정", + "1503": "자엽단과의 싸움: 일제 봉기", + "1504": "자엽단과의 싸움: 바르그 참전", + "1505": "이 더러운 피!", + "1506": "저건 설마 그렘린?", + "1507": "고귀한 늑대인간", + "1508": "공포의 작은 문", + "1509": "바람꽃", + "1510": "격분한 거물" + } + }, + "502": { + "name": "콜루시아 섬", + "fates": { + "1462": "어마무시한 격투: 다가오는 위협", + "1463": "어마무시한 격투: 새로운 정보", + "1464": "어마무시한 격투: 비장의 수단", + "1465": "멈춘 물결을 뒤덮은 그림자", + "1466": "멈춘 물결을 뒤덮은 그림자", + "1467": "직공 마을을 뒤덮은 그림자", + "1468": "직공 마을을 뒤덮은 그림자", + "1469": "뜸부기의 보릿고개", + "1470": "죽어라 해파리", + "1471": "병아리 유치원", + "1472": "집게발 격투가", + "1473": "똑똑똑", + "1474": "불협화음", + "1475": "정다움 마을을 뒤덮은 그림자", + "1476": "격진하는 거대 지렁이", + "1477": "제작 전사들: 자동인형 제작", + "1478": "제작 전사들: 시제품 실전 시험", + "1479": "제작 전사들: 몰수 시합" + } + }, + "503": { + "name": "아므 아렝", + "fates": { + "1511": "줍는 자들: 가위턱의 덫", + "1512": "줍는 자들: 시뮌의 등뼈", + "1513": "줍는 자들: 엽단선텐더", + "1514": "줍는 자들: 넝마주이의 천적", + "1515": "찾는 자들: 강도 조우", + "1516": "찾는 자들: 강도 역습", + "1517": "찾는 자들: 유적 탐색", + "1518": "찾는 자들: 대장로의 검", + "1519": "꽃피우는 선인장", + "1520": "사막의 수렁", + "1521": "톨바 No. 1", + "1522": "모래비늘 여왕", + "1523": "이구아나의 밤", + "1524": "폭주하는 긴다리", + "1525": "이종의 동료", + "1526": "폭발!", + "1527": "황야의 춤꾼" + } + }, + "504": { + "name": "일 메그", + "fates": { + "1480": "악동 다엔 형제: 표적은 픽시!", + "1481": "악동 다엔 형제: 표적은 아마로!", + "1482": "악동 다엔 형제: 표적은 응 모우!", + "1483": "악동 다엔 형제: 환혹된 마가목", + "1484": "악동 다엔 형제: 결투할 때", + "1485": "악동 다엔 형제: 다시 싸울 때", + "1486": "악동 다엔 형제: 비장의 수단", + "1487": "악동 다엔 형제: 마지막 승부", + "1488": "뿌리를 끊는 자", + "1489": "힘내라, 장미곰", + "1490": "바구니 꽃바구니", + "1491": "꿀 빠는 죽음나방", + "1492": "픽시 이야기: 황금색 꽃꿀", + "1493": "친구여 영원하라", + "1494": "픽시 이야기: 요정의 천적", + "1495": "픽시 이야기: 마물 포위망", + "1531": "악동 다엔 형제: 표적은 아마로!", + "1532": "악동 다엔 형제: 표적은 응 모우!", + "1533": "악동 다엔 형제: 환혹된 마가목" + } + }, + "505": { + "name": "라케티카 대우림", + "fates": { + "1441": "먀르나의 순찰: 병균의 메아리", + "1442": "먀르나의 순찰: 병의 근원 누에", + "1443": "먀르나의 순찰: 화살 보충", + "1444": "먀르나의 순찰: 고대 수호자의 호위", + "1445": "먀르나의 수렵: 토힐 발견", + "1446": "먀르나의 수렵: 토힐 추격", + "1447": "먀르나의 수렵: 토힐 추격", + "1448": "먀르나의 수렵: 토힐 맹추격", + "1449": "먀르나의 수렵: 토힐 맹추격", + "1450": "먀르나의 수렵: 토힐 토벌", + "1528": "먀르나의 수렵: 토힐 맹추격", + "1529": "먀르나의 수렵: 토힐 맹추격", + "1530": "먀르나의 수렵: 토힐 토벌", + "1451": "타지 않는 괴물 나무", + "1452": "거미!", + "1453": "분홍학", + "1454": "랍토르의 주방", + "1455": "사랑과 죽음", + "1456": "살인마 토마틀의 습격", + "1457": "죽음의 육지새", + "1458": "본능이 눈을 뜨다", + "1459": "전설이 태어나다", + "1460": "키르메와 사르메", + "1461": "불의 신의 눈" + } + }, + "506": { + "name": "템페스트", + "fates": { + "1426": "재앙의 아르케오타니아: 추적 개시", + "1427": "재앙의 아르케오타니아: 즈무쉬 등장", + "1428": "재앙의 아르케오타니아: 테우쉬 보호", + "1429": "재앙의 아르케오타니아: 테우쉬 호위", + "1430": "재앙의 아르케오타니아: 홍혈 산호 수집", + "1431": "재앙의 아르케오타니아: 결전 준비", + "1432": "재앙의 아르케오타니아: 심해 토벌전", + "1433": "심해의 미녀", + "1434": "조개의 제왕", + "1435": "진주는 영원히", + "1436": "해저 2만 마리", + "1437": "단바니아 가족", + "1438": "흑풍해산 히드라충류", + "1439": "제비의 각성", + "1440": "온도, 줄인다, 새우" + } + }, + "996": { + "name": "히다토스", + "fates": { + "1412": "기괴한 오징어 `카라마리`", + "1413": "폭력의 마수 `스테고동`", + "1414": "눈물의 군주 `모레크`", + "1415": "극채색의 괴조 `피아사`", + "1416": "고고한 사냥꾼 `프로스트멘`", + "1417": "피흘리는 요괴 귀부인 `다흐네`", + "1418": "이계의 제련왕 `킹 골데마르`", + "1419": "요정을 먹는 식물 `레우게`", + "1420": "업화의 사자왕 `바론`", + "1421": "악마뱀의 여왕 `게이트`", + "1422": "발데시온 아스널: 조사지원", + "1423": "수정의 용 `프로비넌스 워쳐`", + "1424": "미지의 위력 `오브니`", + "1425": "물놀이하는 행운토끼" + } + }, + "997": { + "name": "피로스", + "fates": { + "1388": "하얀 외침", + "1389": "사나운 번개야수", + "1390": "요마 변론가", + "1391": "공포의 인형", + "1392": "책의 수호자", + "1393": "심연의 대공", + "1394": "번개의 지휘자", + "1395": "작열하는 검", + "1396": "염열의 거인", + "1397": "눈물 흘리는 갈매기", + "1398": "기적의 생환자", + "1399": "전광의 사령관", + "1400": "럼버잭 사투", + "1401": "지혜와 전쟁의 어머니", + "1402": "전혀 다른 쌍둥이", + "1403": "비웃는 달의 늑대", + "1404": "불나비 여왕", + "1407": "산호를 노리는 행운토끼", + "1408": "바위에 갇힌 행운토끼" + } + }, + "998": { + "name": "파고스", + "fates": { + "1351": "하얀 지배자", + "1352": "가축의 어머니", + "1353": "잿빛 비늘왕", + "1354": "지각 변동의 수수께끼", + "1355": "해빙의 화신", + "1356": "단단한 병마", + "1357": "움직이는 눈 동굴", + "1358": "순망치한", + "1359": "태양의 사자", + "1360": "원탁의 안개왕", + "1361": "야생 소의 구세주", + "1362": "번개구름의 마수", + "1363": "암안왕", + "1364": "푸른 얼음 칼날", + "1365": "모방범", + "1366": "오행안의 주인", + "1367": "눈 위의 행운토끼", + "1368": "보석을 노리는 행운토끼", + "1369": "부패한 독서가" + } + }, + "999": { + "name": "아네모스", + "fates": { + "1328": "질풍의 황제", + "1329": "폭풍의 마왕", + "1331": "광란의 암룡", + "1332": "춤추는 선인장", + "1333": "마지막 미성", + "1334": "탐식하는 자", + "1335": "수각류 괴인", + "1336": "썩은내 현자", + "1337": "이름 높은 거인", + "1338": "마의 왕비", + "1339": "환상의 전갈 마물", + "1340": "이계의 마견", + "1341": "불타는 대왕", + "1342": "분노한 괴조", + "1343": "승리의 기사", + "1344": "꿈틀거리는 사체", + "1345": "강풍의 요정", + "1346": "씨뿌리기", + "1347": "주인 잃은 인형", + "1348": "거대 문어의 왕" + } + }, + "1001": { + "name": "보즈야 남부전선", + "fates": { + "1597": "Sneak & Spell", + "1598": "None of Them Knew They Were Robots", + "1599": "The Bests Must Die", + "1600": "Unrest for the Wicked", + "1601": "{More Machine Now than Man}", + "1602": "Can Carnivorous Plants", + "1603": "Seeq and Destroy", + "1604": "{All Pets Are Off}", + "1605": "Conflicting with the First Law", + "1606": "Brought to Heal", + "1607": "The Monster Mash", + "1608": "{Red(Chocobo) Alert}", + "1609": "{Unicorn Flakes}", + "1610": "Parts and Recreation", + "1611": "The Element of Supplies", + "1612": "Heavy Boots of Lead", + "1613": "No Camping Allowed", + "1614": "Scavengers of Human Sorrow", + "1615": "Help Wanted", + "1616": "{Pyromancer Supreme}", + "1617": "Waste the Rainbow", + "1618": "The Wild Bunch", + "1619": "My Family and Other Animals", + "1620": "{I'm Mechanical Man}", + "1621": "Murder Death Kill", + "1622": "Desperately Seeking Something", + "1623": "Supplies Party", + "1624": "Demonstrably Demonic", + "1625": "For Absent Friend", + "1626": "{Of Steel and Flame}", + "1627": "Let Slip the Dogs of War", + "1628": "The War Against the Machines", + "30000": "The Battle of Castrum Lacus Litore ", + "30001": "Kill It with Fire", + "30002": "The Baying of the Hound(s)", + "30003": "Vigil for the Lost ", + "30004": "Aces High", + "30005": "The Shadow of Death's Hand ", + "30006": "The Final Furlong", + "30007": "The Hunt for Red Choctober ", + "30008": "Beast of Man", + "30009": "The Fires of War", + "30010": "Patriot Games", + "30011": "Trampled under Hoof", + "30012": "And the Flames Went Higher ", + "30013": "Metal Fox Chaos", + "30014": "Rise of the Robots", + "30015": "Where Strode the Behemoth " + } + } + } +} diff --git a/Data/DcLang-Japanese.txt b/Data/DcLang-Japanese.txt new file mode 100644 index 0000000..f5aef52 --- /dev/null +++ b/Data/DcLang-Japanese.txt @@ -0,0 +1,87 @@ +# 日本語メッセージ +LANG=日本語 + +0=FFXIV dc +1=レディ +2=FFXIV プラグインが見つからないんです! +3=FFXIV プラグインを見つかりました! +4=FFXIV ドユーティー・コンテンツが起動しました! +5=ACT 情報: {0} ({1}) +6=FFXIV プラグイン情報: {0} ({1}) +7=データが壊れました: {0} +8=分析できません! +9=アンノウン・コンテンツ: {0} +10=アンノウン・インスタンス: {0} +11=アンノウン・地役: {0} +12=アンノウン・フェイト: {0} +13=データが読めないんです! +14=データ・ファイルが見つからないんです! {0} +20=ドユーティー・コンテンツ情報: {1}({0}) / A:{2} / R:{3} / I:{4} / F:{5} ({6}) +21=ルーレット +22=インスタンス +23=フェイト +24=スカーミッシュ +25=クリティカル・エンゲージメント +26=基本 + +99=ドユーティー・コンテンツ・プラグイン {0} + +101=WAVEファイルを選んでください +102=WAVファイル (*.wav)|*.wav|全て (*.*)|*.* +103=お知らせテストです!! + +200=設定 +201=表示言語 +202=FFXIVがアクティブ状態じゃない場合、オーバレイを隠します + +300=コンテンツ +301=コンテンツ +302=設定 +303=パゲット +304=データ +305=ログフォント +306=オーバレイ・オン +307=透明度 +308=サウンド・オン +309=インスタンス +310=フェイト +311=ラインお知らせ +312=トーケン +313=テレグラムお知らせ +314=ID +315=トーケン +316=パゲット探し +317=説明 +318=ボズヤ情報 +319=機能 +320=現在 +321=状態 +322=探す +323=CEの名前 +324=状態 +325=人数 +326=進行度 + +10001="{0}" 発生! +10002=待機: {0} +10003=マッチング: {0} +10004=入ります: {0} +10005={0} 発生! +10006=待機: {0} +10007=スタート +10008=キャンセル +10009=適用とセーブ +10010=中央ラノシアリーキまたは南方ボズヤで自動的に探します +10011=皇都イシュガルド防衛戦に解除で入って見てください +10012=マッチング +10013=インスタンス +10014=南方ボズヤでCEをまってください。右のリストにパゲットの候補が表示されたら項目をクリックしてください +10015=項目をクリックすると説明が出ます +10016=確認済 +10017=終わり +10018=登録中 +10019=入場中 +10020=進行中 +10021=アンノウン +10022=このパゲットデータを使いますか?セーブします +10023=選択 diff --git a/Data/DcLang-Korean(Actoz).txt b/Data/DcLang-Korean(Actoz).txt new file mode 100644 index 0000000..1bf447d --- /dev/null +++ b/Data/DcLang-Korean(Actoz).txt @@ -0,0 +1,87 @@ +# 한국말 메시지, 한국어 서비스(액토즈) +LANG=한국어(액토즈) + +0=FFXIV dc +1=준비됐습니다 +2=FFXIV 플러그인이 없어요! +3=FFXIV 플러그인을 찾았어요! +4=FFXIV 듀티 콘텐츠 시작합니다! +5=ACT 정보: {0} ({1}) +6=FFXIV 플러그인 정보: {0} ({1}) +7=잘못된 데이터: {0} +8=분석할 수 없어요 +9=알수없는 임무: {0} +10=알수없는 인스턴스: {0} +11=알수없는 지역: {0} +12=알수없는 돌발: {0} +13=데이터를 읽을 수가 없어요! +14=데이터 파일이 없어요! {0} +20=듀티 콘텐츠 정보: {1}({0}) / A:{2} / R:{3} / I:{4} / F:{5} ({6}) +21=무작위 임무 +22=인스턴스 +23=돌발 +24=돌발 교전 +25=비상 교전 +26=기본 + +99=듀티 콘텐츠 플러그인 {0} + +101=소리 파일을 선택하세요 +102=소리 파일 (*.wav)|*.wav|모든 파일 (*.*)|*.* +103=알림 테스트입니다!! + +200=설정 +201=표시 언어 +202=FFXIV를 보고 있지 않을때 오버레이를 감춥니다 + +300=임무 +301=콘텐츠 +302=설정 +303=패킷 +304=데이터셋 +305=로그 글꼴 +306=오버레이 보기 +307=투명도 +308=소리 듣기 +309=인스턴스 +310=돌발 +311=라인 알림 +312=라인 토큰 +313=텔레그램 알림 +314=텔레그램 ID +315=텔레그램 토큰 +316=패킷 찾기 +317=설명 +318=보즈야 찾기 +319=기능 +320=현재값 +321=상태 +322=찾은값 +323=비상 교전 이름 +324=상태 +325=사람수 +326=진행도 + +10001="{0}" 발생했어요! +10002=찾습니다: {0} +10003=매칭됐어요: {0} +10004=들어가요: {0} +10005={0} 발생했어요! +10006=대기 갯수: {0} +10007=시작 +10008=취소 +10009=적용 및 저장 +10010=중부 라노시아로 가시면 값이 채워집니다. 또는 남부 보즈야 전선의 교전으로도 알 수 있습니다. +10011=토벌전 "성도 이슈가르드 방어전"에 해제로 입장해보세요. +10012=매치 +10013=인스턴스 +10014=남부 보즈야 전선으로 가서 비상 교전을 기다리세요. 오른쪽 보즈야 찾기에 후보 데이터가 뜨면 맞는 데이터를 선택하세요. +10015=설명을 볼 항목을 선택하세요 +10016=확인됨 +10017=끝남 +10018=등록중 +10019=입장하는중 +10020=진행중 +10021=알수없어요 +10022=패킷 데이터를 적용하고 덮어쓰실거예요? +10023=선택함 diff --git a/DcConfig.cs b/DcConfig.cs new file mode 100644 index 0000000..5e1a689 --- /dev/null +++ b/DcConfig.cs @@ -0,0 +1,305 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace DutyContent +{ + class DcConfig + { + public static bool PluginEnable { get; set; } + public static string PluginPath { get; set; } + public static string DataPath { get; set; } + public static string PacketPath { get; set; } + public static string ConfigPath { get; set; } + + // + public static PacketConfig Packet = new PacketConfig(); + public static DutyConfig Duty = new DutyConfig(); + + // + public static ConnectionList Connections = new ConnectionList(); + + // + public static string Language { get; set; } = ""; + + // + public static void SaveConfig(string filename = null) + { + if (filename == null) + filename = ConfigPath; + + using (var sw = new StreamWriter(filename, false, Encoding.UTF8)) + { + sw.WriteLine("# DutyContent configuration: {0}", DateTime.Now.ToString()); + sw.WriteLine(); + + sw.WriteLine("# config"); + sw.WriteLine("Language={0}", Language); + sw.WriteLine(); + + Duty.InternalSaveStream(sw); + } + } + + // + public static void LoadConfig(string filename = null) + { + if (filename == null) + filename = ConfigPath; + + if (!File.Exists(filename)) + SaveConfig(filename); + + var db = new ThirdParty.LineDb(filename, Encoding.UTF8, false); + + Language = db["Language"]; + + Duty.InternalReadFromDb(db); + } + + // + public static void Load() + { + Packet.Load(); + LoadConfig(); + } + + // + public static void ReadLanguage(bool is_in_init = false) + { + if (string.IsNullOrWhiteSpace(DcConfig.Language)) + { + if (!is_in_init) + MesgLog.Initialize(Properties.Resources.DefaultMessage); + } + else + { + string filename = Path.Combine(DcConfig.DataPath, $"DcLang-{DcConfig.Language}.txt"); + + if (File.Exists(filename)) + MesgLog.LoadFile(filename); + else + MesgLog.Initialize(Properties.Resources.DefaultMessage); + } + } + + // + public class PacketConfig + { + // Packet + public string Version { get; set; } = "5.45 HotFix"; + public ushort OpFate { get; set; } = 0x3D5; + public ushort OpDuty { get; set; } = 0x307; + public ushort OpMatch { get; set; } = 0x26E; + public ushort OpInstance { get; set; } = 0x10C; + public ushort OpSouthernBozja { get; set; } = 0x1F5; + + // + public void Save(string filename = null) + { + if (filename == null) + filename = PacketPath; + + using (var sw = new StreamWriter(filename, false, Encoding.UTF8)) + { + sw.WriteLine("# DutyPacket configuration: {0}", DateTime.Now.ToString()); + sw.WriteLine(); + + sw.WriteLine("# packet"); + sw.WriteLine("Version={0}", Version); + sw.WriteLine("OpFate={0}", OpFate); + sw.WriteLine("OpDuty={0}", OpDuty); + sw.WriteLine("OpMatch={0}", OpMatch); + sw.WriteLine("OpInstance={0}", OpInstance); + sw.WriteLine("OpSouthernBozja={0}", OpSouthernBozja); + sw.WriteLine(); + } + } + + // + public void Load(string filename = null) + { + if (filename == null) + filename = PacketPath; + + if (!File.Exists(filename)) + Save(filename); + + var db = new ThirdParty.LineDb(filename, Encoding.UTF8, false); + + Version = db["Version"]; + OpFate = ThirdParty.Converter.ToUshort(db["OpFate"], OpFate); + OpDuty = ThirdParty.Converter.ToUshort(db["OpDuty"], OpDuty); + OpMatch = ThirdParty.Converter.ToUshort(db["OpMatch"], OpMatch); + OpInstance = ThirdParty.Converter.ToUshort(db["OpInstance"], OpInstance); + OpSouthernBozja = ThirdParty.Converter.ToUshort(db["OpSouthernBozja"], OpSouthernBozja); + } + } + + // + public class DutyConfig + { + public string Language { get; set; } = "English"; + public int ActiveFate { get; set; } = 0; + public string LogFontFamily { get; set; } = "Microsoft Sans Serif"; + public float LogFontSize { get; set; } = 12.0f; + public bool EnableOverlay { get; set; } + public bool EnableSound { get; set; } + public string SoundInstanceFile { get; set; } + public int SoundInstanceVolume { get; set; } = 100; + public string SoundFateFile { get; set; } + public int SoundFateVolume { get; set; } = 100; + public bool UseNotifyLine { get; set; } + public string NotifyLineToken { get; set; } + public bool UseNotifyTelegram { get; set; } + public string NotifyTelegramId { get; set; } + public string NotifyTelegramToken { get; set; } + public Point OverlayLocation { get; set; } = new Point(0, 0); + + // + public bool EnableNotify => UseNotifyLine || UseNotifyTelegram; + + // + public FateSelection[] Fates = new FateSelection[4] + { + new FateSelection(0), + new FateSelection(1), + new FateSelection(2), + new FateSelection(3), + }; + + // + internal void InternalSaveStream(StreamWriter sw) + { + sw.WriteLine("# duty"); + sw.WriteLine("DutyLanguage={0}", Language); + sw.WriteLine("DutyActiveFate={0}", ActiveFate); + sw.WriteLine("DutyFate0={0}", Fates[0].Line); + sw.WriteLine("DutyFate1={0}", Fates[1].Line); + sw.WriteLine("DutyFate2={0}", Fates[2].Line); + sw.WriteLine("DutyFate3={0}", Fates[3].Line); + sw.WriteLine("DutyLogFontFamily={0}", LogFontFamily); + sw.WriteLine("DutyLogFontSize={0}", LogFontSize); + sw.WriteLine("DutyEnableOverlay={0}", EnableOverlay); + sw.WriteLine("DutyEnableSound={0}", EnableSound); + sw.WriteLine("DutySoundInstanceFile={0}", SoundInstanceFile); + sw.WriteLine("DutySoundInstanceVolume={0}", SoundInstanceVolume); + sw.WriteLine("DutySoundFateFile={0}", SoundFateFile); + sw.WriteLine("DutySoundFateVolume={0}", SoundFateVolume); + sw.WriteLine("DutyUseNotifyLine={0}", UseNotifyLine); + sw.WriteLine("DutyNotifyLineToken={0}", NotifyLineToken); + sw.WriteLine("DutyUseNotifyTelegram={0}", UseNotifyTelegram); + sw.WriteLine("DutyNotifyTelegramId={0}", NotifyTelegramId); + sw.WriteLine("DutyNotifyTelegramToken={0}", NotifyTelegramToken); + sw.WriteLine("DutyOverlayLocationX={0}", OverlayLocation.X); + sw.WriteLine("DutyOverlayLocationY={0}", OverlayLocation.Y); + sw.WriteLine(); + } + + // + internal void InternalReadFromDb(ThirdParty.LineDb db) + { + Language = db["DutyLanguage"]; + ActiveFate = ThirdParty.Converter.ToInt(db["DutyActiveFate"]); + Fates[0].Line = db["DutyFate0"]; + Fates[1].Line = db["DutyFate1"]; + Fates[2].Line = db["DutyFate2"]; + Fates[3].Line = db["DutyFate3"]; + LogFontFamily = db["DutyLogFontFamily"]; + LogFontSize = ThirdParty.Converter.ToFloat(db["DutyLogFontSize"], LogFontSize); + EnableOverlay = ThirdParty.Converter.ToBool(db["DutyEnableOverlay"]); + EnableSound = ThirdParty.Converter.ToBool(db["DutyEnableSound"]); + SoundInstanceFile = db["DutySoundInstanceFile"]; + SoundFateFile = db["DutySoundFateFile"]; + SoundInstanceVolume = ThirdParty.Converter.ToInt(db["DutySoundInstanceVolume"], 100); + SoundFateVolume = ThirdParty.Converter.ToInt(db["DutySoundFateVolume"], 100); + UseNotifyLine = ThirdParty.Converter.ToBool(db["DutyUseNotifyLine"]); + NotifyLineToken = db["DutyNotifyLineToken"]; + UseNotifyTelegram = ThirdParty.Converter.ToBool(db["DutyUseNotifyTelegram"]); + NotifyTelegramId = db["DutyNotifyTelegramId"]; + NotifyTelegramToken = db["DutyNotifyTelegramToken"]; + OverlayLocation = new Point(ThirdParty.Converter.ToInt(db["DutyOverlayLocationX"]), ThirdParty.Converter.ToInt(db["DutyOverlayLocationY"])); + } + } + + // + public class FateSelection + { + public HashSet Selected { get; } = new HashSet(); + public string Line { get; set; } + public int Index { get; set; } + + public FateSelection(int index) + { + Index = index; + } + + public void MakeSelects(bool clear = false) + { + if (clear) + Selected.Clear(); + + var ss = Line.Split('|'); + foreach (var s in ss) + { + if (!string.IsNullOrWhiteSpace(s) && ThirdParty.Converter.TryInt(s, out int i)) + Selected.Add(i); + } + } + + public void MakeLine() + { + Line = string.Join("|", Selected); + } + } + + // + public class ConnectionList + { + public List Conns = new List(); + + public void GetConnections(Process process) + { + Conns.Clear(); + + var size = 0; + var ret = ThirdParty.NativeMethods.GetExtendedTcpTable(IntPtr.Zero, ref size, true, AddressFamily.InterNetwork, 4); + var buff = Marshal.AllocHGlobal(size); + + try + { + ret = ThirdParty.NativeMethods.GetExtendedTcpTable(buff, ref size, true, AddressFamily.InterNetwork, 4); + if (ret == 0) + { + var tbl = Marshal.PtrToStructure(buff); + var ptr = (IntPtr)((long)buff + Marshal.SizeOf(tbl.entries)); + + for (var i = 0; i < tbl.entries; i++) + { + var row = Marshal.PtrToStructure(ptr); + + if (!IPAddress.IsLoopback(row.RemoteAddress) && + process.Id == row.owningPid) + Conns.Add(row); + + ptr = (IntPtr)((long)ptr + Marshal.SizeOf(row)); + } + } + } + finally + { + if (buff != null) + Marshal.FreeHGlobal(buff); + } + } + } + } +} diff --git a/DcContent.cs b/DcContent.cs new file mode 100644 index 0000000..f8c6af5 --- /dev/null +++ b/DcContent.cs @@ -0,0 +1,244 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace DutyContent +{ + public class DcContent + { + // roulette + public class Roulette + { + public string Name { get; set; } + + public static explicit operator Roulette(string name) + { + return new Roulette { Name = name }; + } + } + + // instance + public class Instance + { + public string Name { get; set; } + + public static explicit operator Instance(string name) + { + return new Instance { Name = name }; + } + } + + // area + public class Area + { + public string Name { get; set; } + + public IReadOnlyDictionary Fates { get; set; } + } + + // fate + public class Fate + { + public Area Area { get; set; } + + public string Name { get; set; } + + public static explicit operator Fate(string name) + { + return new Fate { Name = name }; + } + } + + // group + public class Group + { + public string Version { get; set; } + public string Language { get; set; } + public Dictionary Roulettes { get; set; } + public Dictionary Instances { get; set; } + public Dictionary Areas { get; set; } + } + + // + public static string Version { get; private set; } + public static string Language { get; private set; } + public static IReadOnlyDictionary Roulettes { get; private set; } = new Dictionary(); + public static IReadOnlyDictionary Instances { get; private set; } = new Dictionary(); + public static IReadOnlyDictionary Areas { get; private set; } = new Dictionary(); + public static IReadOnlyDictionary Fates { get; private set; } = new Dictionary(); + public static Dictionary Missions { get; private set; } = new Dictionary(); + + // + public static bool Initialize(string json) + { + if (string.IsNullOrWhiteSpace(json)) + return false; + + bool ret; + + try + { + ret = Fill(json); + } + catch + { + ret = false; + } + + return ret; + } + + + // parse json + private static bool Fill(string json) + { + Group data = JsonConvert.DeserializeObject(json); + + Dictionary fates = new Dictionary(); + + foreach (var area in data.Areas) + { + foreach (var fate in area.Value.Fates) + { + try + { + fate.Value.Area = area.Value; + fates.Add(fate.Key, fate.Value); + } + catch (NullReferenceException /*nex*/) + { + MesgLog.E(7, fate.Key); + return false; + } + catch (Exception ex) + { + MesgLog.Ex(ex, 8); + return false; + } + } + } + + Version = data.Version; + Language = data.Language; + Roulettes = data.Roulettes; + Instances = data.Instances; + Areas = data.Areas; + Fates = fates; + + return true; + } + + // + public static Roulette TryRoulette(int code) + { + return Roulettes.TryGetValue(code, out Roulette roulette) ? roulette : null; + } + + // + public static Instance TryInstance(int code) + { + return Instances.TryGetValue(code, out Instance instance) ? instance : null; + } + + // + public static Area TryArea(int code) + { + return Areas.TryGetValue(code, out Area area) ? area : null; + } + + // + public static Fate TryFate(int code) + { + return Fates.ContainsKey(code) ? Fates[code] : null; + } + + // + public static Roulette GetRoulette(int code) + { + return Roulettes.TryGetValue(code, out Roulette roulette) ? roulette : + new Roulette { Name = MesgLog.Text(9, code) }; + } + + // + public static Instance GetInstance(int code) + { + return Instances.TryGetValue(code, out Instance instance) ? instance : + new Instance { Name = MesgLog.Text(10, code) }; + } + + // + public static Area GetArea(int code) + { + return Areas.TryGetValue(code, out Area area) ? area : + new Area { Name = MesgLog.Text(11, code) }; + } + + // + public static Fate GetFate(int code) + { + return Fates.ContainsKey(code) ? Fates[code] : + new Fate { Name = MesgLog.Text(12, code) }; + } + + // + public static bool ReadContent(string language = null) + { + if (language == null) + language = DcConfig.Duty.Language; + else if (!DcConfig.Duty.Language.Equals(language)) + DcConfig.Duty.Language = language; + + string filename = Path.Combine(DcConfig.DataPath, $"DcDuty-{language}.json"); + + if (!File.Exists(filename)) + { + language = "English"; + filename = Path.Combine(DcConfig.DataPath, $"DcDuty-{language}.json"); + + if (!File.Exists(filename)) + { + MesgLog.E(14, filename); + return false; + } + + if (!DcConfig.Duty.Language.Equals(language)) + DcConfig.Duty.Language = language; + } + + string json = File.ReadAllText(filename, Encoding.UTF8); + + if (!Initialize(json)) + { + MesgLog.E(13); + return false; + } + else + { + MesgLog.I(20, + Language, + Version, + Areas.Count, + Roulettes.Count, + Instances.Count, + Fates.Count, + filename); + return true; + } + } + + public static string CeStatusToString(int s) + { + // 10[1] status 0=end, 1=wait, 2=??, 3=progress + switch (s) + { + case 0: return MesgLog.Text(10017); + case 1: return MesgLog.Text(10018); + case 2: return MesgLog.Text(10019); + case 3: return MesgLog.Text(10020); + default: return MesgLog.Text(10021); + } + } + } +} diff --git a/DcControl.Designer.cs b/DcControl.Designer.cs new file mode 100644 index 0000000..b8b6bca --- /dev/null +++ b/DcControl.Designer.cs @@ -0,0 +1,148 @@ + +namespace DutyContent +{ + partial class DcControl + { + /// + /// 필수 디자이너 변수입니다. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 사용 중인 모든 리소스를 정리합니다. + /// + /// 관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region 구성 요소 디자이너에서 생성한 코드 + + /// + /// 디자이너 지원에 필요한 메서드입니다. + /// 이 메서드의 내용을 코드 편집기로 수정하지 마세요. + /// + private void InitializeComponent() + { + this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.tabMain = new System.Windows.Forms.TabControl(); + this.tabPageDuty = new System.Windows.Forms.TabPage(); + this.tabPageConfig = new System.Windows.Forms.TabPage(); + this.txtMesg = new System.Windows.Forms.RichTextBox(); + this.btnClearMesg = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); + this.splitContainer1.Panel1.SuspendLayout(); + this.splitContainer1.Panel2.SuspendLayout(); + this.splitContainer1.SuspendLayout(); + this.tabMain.SuspendLayout(); + this.SuspendLayout(); + // + // splitContainer1 + // + this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer1.Location = new System.Drawing.Point(0, 0); + this.splitContainer1.Name = "splitContainer1"; + this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal; + // + // splitContainer1.Panel1 + // + this.splitContainer1.Panel1.Controls.Add(this.tabMain); + // + // splitContainer1.Panel2 + // + this.splitContainer1.Panel2.Controls.Add(this.txtMesg); + this.splitContainer1.Panel2.Controls.Add(this.btnClearMesg); + this.splitContainer1.Size = new System.Drawing.Size(792, 567); + this.splitContainer1.SplitterDistance = 497; + this.splitContainer1.TabIndex = 0; + // + // tabMain + // + this.tabMain.Alignment = System.Windows.Forms.TabAlignment.Left; + this.tabMain.Controls.Add(this.tabPageDuty); + this.tabMain.Controls.Add(this.tabPageConfig); + this.tabMain.Dock = System.Windows.Forms.DockStyle.Fill; + this.tabMain.DrawMode = System.Windows.Forms.TabDrawMode.OwnerDrawFixed; + this.tabMain.ItemSize = new System.Drawing.Size(30, 100); + this.tabMain.Location = new System.Drawing.Point(0, 0); + this.tabMain.Multiline = true; + this.tabMain.Name = "tabMain"; + this.tabMain.SelectedIndex = 0; + this.tabMain.Size = new System.Drawing.Size(792, 497); + this.tabMain.SizeMode = System.Windows.Forms.TabSizeMode.Fixed; + this.tabMain.TabIndex = 0; + this.tabMain.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.TabMain_DrawItem); + // + // tabPageDuty + // + this.tabPageDuty.BackColor = System.Drawing.Color.Transparent; + this.tabPageDuty.Location = new System.Drawing.Point(104, 4); + this.tabPageDuty.Name = "tabPageDuty"; + this.tabPageDuty.Padding = new System.Windows.Forms.Padding(3); + this.tabPageDuty.Size = new System.Drawing.Size(684, 489); + this.tabPageDuty.TabIndex = 0; + this.tabPageDuty.Text = "Duty"; + // + // tabPageConfig + // + this.tabPageConfig.Location = new System.Drawing.Point(104, 4); + this.tabPageConfig.Name = "tabPageConfig"; + this.tabPageConfig.Padding = new System.Windows.Forms.Padding(3); + this.tabPageConfig.Size = new System.Drawing.Size(684, 489); + this.tabPageConfig.TabIndex = 1; + this.tabPageConfig.Text = "Config"; + this.tabPageConfig.UseVisualStyleBackColor = true; + // + // txtMesg + // + this.txtMesg.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtMesg.Location = new System.Drawing.Point(104, 3); + this.txtMesg.Name = "txtMesg"; + this.txtMesg.ReadOnly = true; + this.txtMesg.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.Vertical; + this.txtMesg.Size = new System.Drawing.Size(685, 60); + this.txtMesg.TabIndex = 1; + this.txtMesg.Text = ""; + // + // btnClearMesg + // + this.btnClearMesg.Location = new System.Drawing.Point(3, 3); + this.btnClearMesg.Name = "btnClearMesg"; + this.btnClearMesg.Size = new System.Drawing.Size(95, 33); + this.btnClearMesg.TabIndex = 0; + this.btnClearMesg.Text = "Clear Mesg"; + this.btnClearMesg.UseVisualStyleBackColor = true; + // + // DcControl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.splitContainer1); + this.Name = "DcControl"; + this.Size = new System.Drawing.Size(792, 567); + this.splitContainer1.Panel1.ResumeLayout(false); + this.splitContainer1.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); + this.splitContainer1.ResumeLayout(false); + this.tabMain.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.SplitContainer splitContainer1; + private System.Windows.Forms.Button btnClearMesg; + private System.Windows.Forms.TabControl tabMain; + private System.Windows.Forms.TabPage tabPageDuty; + private System.Windows.Forms.TabPage tabPageConfig; + private System.Windows.Forms.RichTextBox txtMesg; + } +} diff --git a/DcControl.cs b/DcControl.cs new file mode 100644 index 0000000..e907ecf --- /dev/null +++ b/DcControl.cs @@ -0,0 +1,299 @@ +using Advanced_Combat_Tracker; +using System; +using System.Data; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Windows.Forms; + +namespace DutyContent +{ + public partial class DcControl : UserControl, IActPluginV1 + { + public static string PluginName => "DutyContent"; + + private static DcControl _self; + public static DcControl Self => _self; + + // + private ActPluginData _ffxiv_plugin_data; + + private bool _is_form_loaded; + private bool _is_plugin_initializing; + private TabPage _act_tab; + private Label _act_label; + + private Timer _update_and_check; + private ThirdParty.NativeMethods.ProcessHandle _game_process; + private bool _game_exist; + private bool _game_active; + private string _game_zone; + + // + public DcControl() + { + _self = this; + + // + RegisterActAssemblies(); + + InitializeComponent(); + + foreach (var f in Application.OpenForms) + { + if (f == ActGlobals.oFormActMain) + { + _is_form_loaded = true; + break; + } + } + + // + Tab.DutyForm dutyform = new Tab.DutyForm(); + tabPageDuty.Controls.Add(dutyform.Controls[0]); + + Tab.ConfigForm configform = new Tab.ConfigForm(); + tabPageConfig.Controls.Add(configform.Controls[0]); + } + + // + public void RegisterActAssemblies() + { + var pin = ActGlobals.oFormActMain.ActPlugins.FirstOrDefault(x => x.pluginFile.Name.Equals("DutyContent.dll")); + DcConfig.PluginPath = pin?.pluginFile.DirectoryName; + + DcConfig.DataPath = Path.Combine(DcConfig.PluginPath, "Data"); + DcConfig.ConfigPath = Path.Combine(DcConfig.PluginPath, "DutyContent.config"); + DcConfig.PacketPath = Path.Combine(DcConfig.PluginPath, "DutyPacket.config"); + } + + // + public void InitPlugin(TabPage tab, Label label) + { + _act_tab = tab; + _act_label = label; + + if (_is_form_loaded) + ActPluginInitialize(); + else + ActGlobals.oFormActMain.Shown += OFormActMain_Shown; + + var actinfo = System.Reflection.Assembly.GetAssembly(typeof(ActGlobals)); + MesgLog.I(5, actinfo.GetName().Version, actinfo.Location); + + if (_ffxiv_plugin_data == null) + { + _ffxiv_plugin_data = ActGlobals.oFormActMain.ActPlugins.Where(x => + x.pluginFile.Name.ToUpper().Contains("FFXIV_ACT_PLUGIN") && + x.lblPluginStatus.Text.ToUpper().Contains("FFXIV PLUGIN STARTED.")) + .Select(x => x) + .FirstOrDefault(); + } + + if (_ffxiv_plugin_data == null) + MesgLog.E(2); // FFXIV plugin is missing! + else + { + var ids = ((FFXIV_ACT_Plugin.FFXIV_ACT_Plugin)_ffxiv_plugin_data.pluginObj).DataSubscription; + ids.NetworkReceived -= FFXIVPlugin_NetworkReceived; + ids.NetworkReceived += FFXIVPlugin_NetworkReceived; + ids.ZoneChanged -= FFXIVPlugin_ZoneChanged; + ids.ZoneChanged += FFXIVPlugin_ZoneChanged; + + MesgLog.I(6, System.Diagnostics.FileVersionInfo.GetVersionInfo(_ffxiv_plugin_data.pluginFile.FullName).FileVersion, _ffxiv_plugin_data.pluginFile.FullName); + } + + _update_and_check = new Timer() + { + Interval = 300, + }; + _update_and_check.Tick += (sender, e) => + { + UpdateAndCheckProc(); + _update_and_check.Interval = _game_exist ? _game_active ? 50 : 300 : 500; + }; + _update_and_check.Start(); + } + + // + public void DeInitPlugin() + { + _update_and_check.Stop(); + + DcConfig.PluginEnable = false; + + Tab.DutyForm.Self?.PluginDeinitialize(); + Tab.ConfigForm.Self?.PluginDeinitialize(); + DcConfig.SaveConfig(); + + MesgLog.SetTextBox(null); + + _act_tab = null; + + if (_act_label != null) + { + _act_label.Text = "Closed"; + _act_label = null; + } + } + + private void OFormActMain_Shown(object sender, EventArgs e) + { + _is_form_loaded = true; + ActPluginInitialize(); + } + + // + private void ActPluginInitialize() + { + if (_is_plugin_initializing) + return; + + _is_plugin_initializing = true; + _act_label.Text = "Starting..."; + + // + MesgLog.SetTextBox(txtMesg); + MesgLog.Initialize(Properties.Resources.DefaultMessage); + + DcConfig.Load(); + DcConfig.ReadLanguage(true); + DcContent.ReadContent(); + + UpdateUiLocale(); + + MesgLog.C(Color.Aquamarine, 4); + + // + Dock = DockStyle.Fill; + + _act_label.Text = MesgLog.Text(1); // Duty ready + _act_tab.Text = MesgLog.Text(0); // FFXIV dc + _act_tab.Controls.Add(this); + + // + Tab.ConfigForm.Self?.PluginInitialize(); + Tab.DutyForm.Self?.PluginInitialize(); + + // + DcConfig.PluginEnable = true; + + _is_plugin_initializing = false; + } + + // + private void TabMain_DrawItem(object sender, DrawItemEventArgs e) + { + var g = e.Graphics; + TabPage p = tabMain.TabPages[e.Index]; + Rectangle r = tabMain.GetTabRect(e.Index); + StringFormat s = new StringFormat() + { + Alignment = StringAlignment.Near, + LineAlignment = StringAlignment.Center, + }; + + Brush b, h; + Font f; + + if (tabMain.SelectedIndex == e.Index) + { + f = new Font(tabMain.Font.FontFamily, 12.0f, FontStyle.Bold, GraphicsUnit.Pixel); +#if false + b = new SolidBrush(Color.Black); + h = SystemBrushes.Window; +#else + b = new SolidBrush(Color.White); + h = SystemBrushes.Highlight; +#endif + } + //else if (p.col) + else + { + f = new Font(tabMain.Font.FontFamily, 12.0f, FontStyle.Regular, GraphicsUnit.Pixel); + b = new SolidBrush(Color.DarkSlateGray); + h = SystemBrushes.Control; + } + + g.FillRectangle(h, r); + g.DrawString(p.Text, f, b, r, new StringFormat(s)); + } + + // + private void UpdateAndCheckProc() + { + if (_game_process == null || _game_process.Process.HasExited) + { + _game_exist = false; + _game_active = false; + + // will be update game status next time + var p = (from x in Process.GetProcessesByName("ffxiv_dx11") where !x.HasExited && x.MainModule != null && x.MainModule.ModuleName == "ffxiv_dx11.exe" select x).FirstOrDefault(); + + if (p != null && p.HasExited) + p = null; + + if (((_game_process == null) != (p == null)) || + (_game_process != null && p != null && _game_process.Process.Id != p.Id)) + { + _game_process = p != null ? new ThirdParty.NativeMethods.ProcessHandle(p) : null; + } + + if (_game_process != null) + { + // + DcConfig.Connections.GetConnections(_game_process.Process); + //MesgLog.L("count: {0}", DcConfig.Connections.Conns.Count); + } + } + else + { + _game_exist = true; + + var fgw = ThirdParty.NativeMethods.GetForegroundWindow(); + ThirdParty.NativeMethods.GetWindowThreadProcessId(fgw, out int id); + _game_active = _game_process.Process.Id == id; + } + + var zone = ActGlobals.oFormActMain.CurrentZone; + if (_game_zone == null || !zone.Equals(_game_zone)) + { +#if false + if (_game_zone != null) + MesgLog.I(1008, _game_zone); + + _game_zone = zone; + MesgLog.I(1007, zone); +#else + _game_zone = zone; +#endif + } + } + + // + private void FFXIVPlugin_NetworkReceived(string connection, long epoch, byte[] message) + { + if (message.Length < 32) + return; + + Tab.DutyForm.Self?.PacketHandler(connection, message); + } + + // + private void FFXIVPlugin_ZoneChanged(uint zone_id, string zone_name) + { + Tab.DutyForm.Self?.ZoneChanged(zone_id, zone_name); + } + + // + public void UpdateUiLocale() + { + tabPageDuty.Text = MesgLog.Text(300); + Tab.DutyForm.Self?.UpdateUiLocale(); + + tabPageConfig.Text= MesgLog.Text(200); + Tab.ConfigForm.Self?.UpdateUiLocale(); + } + } +} diff --git a/DcControl.resx b/DcControl.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/DcControl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/DutyContent.csproj b/DutyContent.csproj new file mode 100644 index 0000000..a1ee3d9 --- /dev/null +++ b/DutyContent.csproj @@ -0,0 +1,174 @@ + + + + + Debug + AnyCPU + {66572F39-C8FD-4F89-BFA1-811C2A27D563} + library + DutyContent + DutyContent + v4.7.2 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + false + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + false + + + + References\ACT\Advanced Combat Tracker.exe + + + References\ACT\FFXIV_ACT_Plugin.dll + + + References\ACT\FFXIV_ACT_Plugin.Common.dll + + + packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll + + + + + + + + + + + + + 4.0 + + + + + + + + + UserControl + + + DcControl.cs + + + Form + + + ConfigForm.cs + + + Form + + + DutyForm.cs + + + + + + + Form + + + DutyOvForm.cs + + + + + + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + DcControl.cs + + + ConfigForm.cs + + + DutyForm.cs + + + DutyOvForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + if exist "%25APPDATA%25\Advanced Combat Tracker\Plugins\DutyContent" copy $(TargetPath) "%25APPDATA%25\Advanced Combat Tracker\Plugins\DutyContent" /y + + + \ No newline at end of file diff --git a/DutyContent.sln b/DutyContent.sln new file mode 100644 index 0000000..ca83af3 --- /dev/null +++ b/DutyContent.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30717.126 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DutyContent", "DutyContent.csproj", "{66572F39-C8FD-4F89-BFA1-811C2A27D563}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {66572F39-C8FD-4F89-BFA1-811C2A27D563}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {66572F39-C8FD-4F89-BFA1-811C2A27D563}.Debug|Any CPU.Build.0 = Debug|Any CPU + {66572F39-C8FD-4F89-BFA1-811C2A27D563}.Release|Any CPU.ActiveCfg = Release|Any CPU + {66572F39-C8FD-4F89-BFA1-811C2A27D563}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A81E51A1-CA63-4713-A000-69BCC7E3F0F8} + EndGlobalSection +EndGlobal diff --git a/Interface/IPacketHandler.cs b/Interface/IPacketHandler.cs new file mode 100644 index 0000000..29dfe9a --- /dev/null +++ b/Interface/IPacketHandler.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DutyContent.Interface +{ + interface IPacketHandler + { + void PacketHandler(string pid, byte[] message); + void ZoneChanged(uint zone_id, string zone_name); + } +} diff --git a/Interface/ISuppActPlugin.cs b/Interface/ISuppActPlugin.cs new file mode 100644 index 0000000..67cca99 --- /dev/null +++ b/Interface/ISuppActPlugin.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DutyContent.Interface +{ + interface ISuppActPlugin + { + void PluginInitialize(); + void PluginDeinitialize(); + } +} diff --git a/Interface/ISuppLocale.cs b/Interface/ISuppLocale.cs new file mode 100644 index 0000000..c846d97 --- /dev/null +++ b/Interface/ISuppLocale.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DutyContent.Interface +{ + interface ISuppLocale + { + void RefreshLocale(); + void UpdateUiLocale(); + } +} diff --git a/MesgLog.cs b/MesgLog.cs new file mode 100644 index 0000000..895a976 --- /dev/null +++ b/MesgLog.cs @@ -0,0 +1,127 @@ +using System; +using System.Drawing; +using System.Text; +using System.Text.RegularExpressions; +using System.Windows.Forms; + +namespace DutyContent +{ + class MesgLog + { + private static ThirdParty.LineDb _lines; + private static RichTextBox _logs; + + private static readonly Regex ExceptionPattern = new Regex(@"\{(.+?)\}"); + + public static string Language { get; private set; } + + public static void Initialize(string text) + { + _lines = new ThirdParty.LineDb(text, true); + } + + public static bool LoadFile(string filename, Encoding enc) + { + if (_lines == null) + return false; + else + { + _lines.LoadFile(filename, enc, true); + return true; + } + } + + public static bool LoadFile(string filename) + { + return LoadFile(filename, Encoding.UTF8); + } + + public static void SetTextBox(RichTextBox textbox) + { + _logs = textbox; + } + + public static string Text(string text) + { + return _lines == null || !_lines.Try(text, out string v) ? $"<{text}>" : v; + } + + public static string Text(string text, params object[] prms) + { + return _lines == null || !_lines.Try(text, out string v) ? $"<{text}>" : string.Format(v, prms); + } + + public static string Text(int key) + { + return _lines == null || !_lines.Try(key, out string v) ? ThirdParty.LineDb.InvalidKey : v; + } + + public static string Text(int key, params object[] prms) + { + return _lines == null || !_lines.Try(key, out string v) ? ThirdParty.LineDb.InvalidKey : string.Format(v, prms); + } + + public static void Write(Color color, string format, params object[] prms) + { + if (_logs == null || _logs.IsDisposed || format == null) + return; + + var text = string.Format(format, prms); + var dt = DateTime.Now.ToString("HH:mm:ss"); + var ms = $"[{dt}] {text}{Environment.NewLine}"; + + WorkerAct.Invoker(() => + { + _logs.SelectionColor = color; + _logs.SelectionStart = _logs.TextLength; + _logs.SelectionLength = 0; + _logs.AppendText(ms); + + _logs.SelectionColor = _logs.ForeColor; + ThirdParty.NativeMethods.ScrollToBottom(_logs); + }); + } + + public static void Write(string format, params object[] prms) + { + Write(Color.White, format, prms); + } + + public static void L(string format, params object[] prms) + { + Write(Color.DarkBlue, format, prms); + } + + // color + public static void C(Color color, int key, params object[] prms) + { + Write(color, Text(key, prms)); + } + + // info / black + public static void I(int key, params object[] prms) + { + Write(Color.Black, Text(key, prms)); + } + + // error / red + public static void E(int key, params object[] prms) + { + Write(Color.Red, Text(key, prms)); + } + + // gray + public static void Y(int key, params object[] prms) + { + Write(Color.Gray, Text(key, prms)); + } + + // exception + public static void Ex(Exception ex, int key, params object[] prms) + { + string text = Text(key, prms); + string msg = ExceptionPattern.Replace(ex.Message, "{{$1}}"); + Write(Color.Red, $"{text}: {msg}"); + } + } +} diff --git a/Overlay/DutyOvForm.Designer.cs b/Overlay/DutyOvForm.Designer.cs new file mode 100644 index 0000000..d7b21eb --- /dev/null +++ b/Overlay/DutyOvForm.Designer.cs @@ -0,0 +1,72 @@ + +namespace DutyContent.Overlay +{ + partial class DutyOvForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.lblText = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // lblText + // + this.lblText.AutoEllipsis = true; + this.lblText.Font = new System.Drawing.Font("Segoe UI", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.lblText.ForeColor = System.Drawing.Color.White; + this.lblText.Location = new System.Drawing.Point(0, 0); + this.lblText.Name = "lblText"; + this.lblText.Size = new System.Drawing.Size(300, 20); + this.lblText.TabIndex = 0; + this.lblText.Text = "Duty Content"; + this.lblText.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + this.lblText.MouseDown += new System.Windows.Forms.MouseEventHandler(this.lblText_MouseDown); + // + // DutyOvForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.Color.Black; + this.ClientSize = new System.Drawing.Size(300, 25); + this.ControlBox = false; + this.Controls.Add(this.lblText); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; + this.Name = "DutyOvForm"; + this.Opacity = 0.5D; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; + this.Text = "DutyOvForm"; + this.TopMost = true; + this.Load += new System.EventHandler(this.DutyOvForm_Load); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Label lblText; + } +} \ No newline at end of file diff --git a/Overlay/DutyOvForm.cs b/Overlay/DutyOvForm.cs new file mode 100644 index 0000000..1b5ec94 --- /dev/null +++ b/Overlay/DutyOvForm.cs @@ -0,0 +1,145 @@ +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace DutyContent.Overlay +{ + public partial class DutyOvForm : Form + { + private const int BlinkTime = 300; + private const int BlinkCount = 20; + + private static readonly Color ColorFate = Color.DarkOrange; + private static readonly Color ColorMatch = Color.Red; + private static readonly Color ColorNone = Color.Black; + + // + private Timer _timer; + private int _blink; + private Color _accent; + + // + public DutyOvForm() + { + InitializeComponent(); + + Location = DcConfig.Duty.OverlayLocation; + + _timer = new Timer { Interval = BlinkTime }; + _timer.Tick += (sender, e) => + { + if (++_blink > BlinkCount) + { + StopBlink(); + } + else + { + BackColor = (BackColor == ColorNone) ? _accent : ColorNone; + } + }; + } + + protected override CreateParams CreateParams + { + get + { + CreateParams cp = base.CreateParams; + cp.ExStyle |= 0x80/*WS_EX_TOOLWINDOW*/ | 0x80000/*WS_EX_LAYERED*/; + return cp; + } + } + + private void DutyOvForm_Load(object sender, EventArgs e) + { + + } + + private void DoMoveDown(MouseEventArgs e) + { + if (e.Button == MouseButtons.Left) + { + ThirdParty.NativeMethods.ReleaseCapture(); + ThirdParty.NativeMethods.SendMessage(Handle, 0xA1/*WM_NCLBUTTONDOWN*/, new IntPtr(0x2/*HT_CAPTION*/), IntPtr.Zero); + } + } + + protected override void OnMouseDown(MouseEventArgs e) + { + base.OnMouseDown(e); + DoMoveDown(e); + } + + protected override void OnLocationChanged(EventArgs e) + { + base.OnLocationChanged(e); + DcConfig.Duty.OverlayLocation = Location; + } + + private void lblText_MouseDown(object sender, MouseEventArgs e) + { + DoMoveDown(e); + } + + public void SetText(string text) + { + lblText.Text = text; + } + + public void StartBlink() + { + _blink = 0; + _timer.Enabled = false; + _timer.Start(); + } + + public void StopBlink() + { + _timer.Stop(); + + BackColor = ColorNone; + + _accent = ColorNone; + lblText.Text = string.Empty; + } + + public void PlayNone() + { + Invoke((MethodInvoker)(() => + { + _accent = ColorNone; + lblText.Text = string.Empty; + StopBlink(); + })); + } + + public void PlayFate(DcContent.Fate f) + { + Invoke((MethodInvoker)(() => + { + _accent = ColorFate; + lblText.Text = f.Name; + StartBlink(); + })); + } + + public void PlayQueue(string name) + { + Invoke((MethodInvoker)(() => + { + _accent = ColorNone; + lblText.Text = name; + })); + } + + public void PlayMatch(string name, bool blink = true) // PlayEnter + { + Invoke((MethodInvoker)(() => + { + _accent = ColorMatch; + lblText.Text = name; + if (blink) + StartBlink(); + })); + } + } +} diff --git a/Overlay/DutyOvForm.resx b/Overlay/DutyOvForm.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/Overlay/DutyOvForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..3888c06 --- /dev/null +++ b/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해 +// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면 +// 이러한 특성 값을 변경하세요. +[assembly: AssemblyTitle("DutyContent")] +[assembly: AssemblyDescription("Duty Content for FFXIV")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("DutyContent")] +[assembly: AssemblyCopyright("Copyright © ksh 2021")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에 +// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면 +// 해당 형식에 대해 ComVisible 특성을 true로 설정하세요. +[assembly: ComVisible(false)] + +//지역화 가능 애플리케이션 빌드를 시작하려면 다음을 설정하세요. +//.csproj 파일에서 내에 CultureYouAreCodingWith를 +//설정하십시오. 예를 들어 소스 파일에서 영어(미국)를 +//사용하는 경우 를 en-US로 설정합니다. 그런 다음 아래 +//NeutralResourceLanguage 특성의 주석 처리를 제거합니다. 아래 줄의 "en-US"를 업데이트하여 +//프로젝트 파일의 UICulture 설정과 일치시킵니다. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly:ThemeInfo( + ResourceDictionaryLocation.None, //테마별 리소스 사전의 위치 + //(페이지 또는 응용 프로그램 리소스 사진에 + // 리소스가 없는 경우에 사용됨) + ResourceDictionaryLocation.SourceAssembly //제네릭 리소스 사전의 위치 + //(페이지 또는 응용 프로그램 리소스 사진에 + // 리소스가 없는 경우에 사용됨) +)] + + +// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다. +// +// 주 버전 +// 부 버전 +// 빌드 번호 +// 수정 버전 +// +// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를 +// 기본값으로 할 수 있습니다. +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Properties/Resources.Designer.cs b/Properties/Resources.Designer.cs new file mode 100644 index 0000000..0efe0c8 --- /dev/null +++ b/Properties/Resources.Designer.cs @@ -0,0 +1,155 @@ +//------------------------------------------------------------------------------ +// +// 이 코드는 도구를 사용하여 생성되었습니다. +// 런타임 버전:4.0.30319.42000 +// +// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면 +// 이러한 변경 내용이 손실됩니다. +// +//------------------------------------------------------------------------------ + +namespace DutyContent.Properties { + using System; + + + /// + /// 지역화된 문자열 등을 찾기 위한 강력한 형식의 리소스 클래스입니다. + /// + // 이 클래스는 ResGen 또는 Visual Studio와 같은 도구를 통해 StronglyTypedResourceBuilder + // 클래스에서 자동으로 생성되었습니다. + // 멤버를 추가하거나 제거하려면 .ResX 파일을 편집한 다음 /str 옵션을 사용하여 ResGen을 + // 다시 실행하거나 VS 프로젝트를 다시 빌드하십시오. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 이 클래스에서 사용하는 캐시된 ResourceManager 인스턴스를 반환합니다. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DutyContent.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 이 강력한 형식의 리소스 클래스를 사용하여 모든 리소스 조회에 대해 현재 스레드의 CurrentUICulture 속성을 + /// 재정의합니다. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// # Default English message + ///LANG=English + /// + ///0=FFXIV dc + ///1=Duty ready + ///2=FFXIV plugin is missing! + ///3=FFXIV plugin found! + ///4=FFXIV Duty Content starting! + ///5=ACT info: {0} ({1}) + ///6=FFXIV plugin info {0} ({1}) + ///7=Invalid data: {0} + ///8=Parsing error + ///9=Unknown roulette: {0} + ///10=Unknown instance: {0} + ///11=Unknown area: {0} + ///12=Unknown FATE: {0} + ///13=Data reading failed! + ///14=Data file not found! {0} + ///20=Duty contents info: {0}({1}) / A:{2} / R:{3} / I:{4} / F:{5} ({6}) + ///21=Roulette + ///22=Instance + ///23=FATE + ///24=Skirmish + ///[나머지 문자열은 잘림]";과(와) 유사한 지역화된 문자열을 찾습니다. + /// + internal static string DefaultMessage { + get { + return ResourceManager.GetString("DefaultMessage", resourceCulture); + } + } + + /// + /// System.Drawing.Bitmap 형식의 지역화된 리소스를 찾습니다. + /// + internal static System.Drawing.Bitmap pix_annotation { + get { + object obj = ResourceManager.GetObject("pix_annotation", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// System.Drawing.Bitmap 형식의 지역화된 리소스를 찾습니다. + /// + internal static System.Drawing.Bitmap pix_magnify { + get { + object obj = ResourceManager.GetObject("pix_magnify", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// System.Drawing.Bitmap 형식의 지역화된 리소스를 찾습니다. + /// + internal static System.Drawing.Bitmap pix_play { + get { + object obj = ResourceManager.GetObject("pix_play", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// System.Drawing.Bitmap 형식의 지역화된 리소스를 찾습니다. + /// + internal static System.Drawing.Bitmap pix_tab_content { + get { + object obj = ResourceManager.GetObject("pix_tab_content", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// System.Drawing.Bitmap 형식의 지역화된 리소스를 찾습니다. + /// + internal static System.Drawing.Bitmap pix_tab_setting { + get { + object obj = ResourceManager.GetObject("pix_tab_setting", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// System.Drawing.Bitmap 형식의 지역화된 리소스를 찾습니다. + /// + internal static System.Drawing.Bitmap pix_tab_tool { + get { + object obj = ResourceManager.GetObject("pix_tab_tool", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/Properties/Resources.resx b/Properties/Resources.resx new file mode 100644 index 0000000..f727112 --- /dev/null +++ b/Properties/Resources.resx @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\resources\mesg.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + + ..\Resources\pix_annotation.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\pix_magnify.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\pix_play.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\resources\pix_tab_content.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\pix_tab_setting.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\pix_tab_tool.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/Properties/Settings.Designer.cs b/Properties/Settings.Designer.cs new file mode 100644 index 0000000..86b3a4e --- /dev/null +++ b/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace DutyContent.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/Properties/Settings.settings b/Properties/Settings.settings new file mode 100644 index 0000000..033d7a5 --- /dev/null +++ b/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/References/ACT/Advanced Combat Tracker.exe b/References/ACT/Advanced Combat Tracker.exe new file mode 100644 index 0000000..b089eba Binary files /dev/null and b/References/ACT/Advanced Combat Tracker.exe differ diff --git a/References/ACT/FFXIV_ACT_Plugin.Common.dll b/References/ACT/FFXIV_ACT_Plugin.Common.dll new file mode 100644 index 0000000..8099cee Binary files /dev/null and b/References/ACT/FFXIV_ACT_Plugin.Common.dll differ diff --git a/References/ACT/FFXIV_ACT_Plugin.Config.dll b/References/ACT/FFXIV_ACT_Plugin.Config.dll new file mode 100644 index 0000000..f1e8558 Binary files /dev/null and b/References/ACT/FFXIV_ACT_Plugin.Config.dll differ diff --git a/References/ACT/FFXIV_ACT_Plugin.LogFile.dll b/References/ACT/FFXIV_ACT_Plugin.LogFile.dll new file mode 100644 index 0000000..1652a60 Binary files /dev/null and b/References/ACT/FFXIV_ACT_Plugin.LogFile.dll differ diff --git a/References/ACT/FFXIV_ACT_Plugin.Memory.dll b/References/ACT/FFXIV_ACT_Plugin.Memory.dll new file mode 100644 index 0000000..2da6ea0 Binary files /dev/null and b/References/ACT/FFXIV_ACT_Plugin.Memory.dll differ diff --git a/References/ACT/FFXIV_ACT_Plugin.Network.dll b/References/ACT/FFXIV_ACT_Plugin.Network.dll new file mode 100644 index 0000000..6b6234d Binary files /dev/null and b/References/ACT/FFXIV_ACT_Plugin.Network.dll differ diff --git a/References/ACT/FFXIV_ACT_Plugin.Overlay.dll b/References/ACT/FFXIV_ACT_Plugin.Overlay.dll new file mode 100644 index 0000000..5e6edf6 Binary files /dev/null and b/References/ACT/FFXIV_ACT_Plugin.Overlay.dll differ diff --git a/References/ACT/FFXIV_ACT_Plugin.Parse.dll b/References/ACT/FFXIV_ACT_Plugin.Parse.dll new file mode 100644 index 0000000..d415644 Binary files /dev/null and b/References/ACT/FFXIV_ACT_Plugin.Parse.dll differ diff --git a/References/ACT/FFXIV_ACT_Plugin.Resource.dll b/References/ACT/FFXIV_ACT_Plugin.Resource.dll new file mode 100644 index 0000000..4831d39 Binary files /dev/null and b/References/ACT/FFXIV_ACT_Plugin.Resource.dll differ diff --git a/References/ACT/FFXIV_ACT_Plugin.dll b/References/ACT/FFXIV_ACT_Plugin.dll new file mode 100644 index 0000000..184eb80 Binary files /dev/null and b/References/ACT/FFXIV_ACT_Plugin.dll differ diff --git a/Resources/mesg.txt b/Resources/mesg.txt new file mode 100644 index 0000000..b678256 --- /dev/null +++ b/Resources/mesg.txt @@ -0,0 +1,87 @@ +# Default English message +LANG=English + +0=FFXIV dc +1=Duty ready +2=FFXIV plugin is missing! +3=FFXIV plugin found! +4=FFXIV Duty Content starting! +5=ACT info: {0} ({1}) +6=FFXIV plugin info {0} ({1}) +7=Invalid data: {0} +8=Parsing error +9=Unknown roulette: {0} +10=Unknown instance: {0} +11=Unknown area: {0} +12=Unknown FATE: {0} +13=Data reading failed! +14=Data file not found! {0} +20=Duty contents info: {1}({0}) / A:{2} / R:{3} / I:{4} / F:{5} ({6}) +21=Roulette +22=Instance +23=FATE +24=Skirmish +25=CE +26=Default + +99=DutyContent Plugin {0} + +101=Select wave file +102=Wave (*.wav)|*.wav|All (*.*)|*.* +103=Notify test!! + +200=Config +201=Display Language +202=Hide overlays when FFXIV client is in the background + +300=Duty +301=Contents +302=Setting +303=Packet +304=Dataset +305=Log font +306=Enable overlay +307=Transparent +308=Enable sound +309=Instance +310=FATE +311=Use LINE notify +312=Token +313=Use Telegram notify +314=ID +315=Token +316=Packet finder +317=Description +318=Bozja Finder +319=Function +320=Current +321=Status +322=Found +323=Name +324=Status +325=Member +326=Progress + +10001="{0}" spawned! +10002=Entry: {0} +10003=Matched: {0} +10004=Enter: {0} +10005={0} spawned! +10006=Duty entries: {0} +10007=Start +10008=Cancel +10009=Apply && Save +10010=Go to Middle La Noscea. Wait for FATEs appear. Also skirmishes in "The Bozjan Southern Front" can be use. +10011=Enter tial "The Steps of Faith" with undersize option. +10012=Match +10013=Instance +10014=Go to "The Bozjan Southern Front" and wait Critical Engagements. Candidates will be appear at right side Bozja finder. +10015=Select item to show description +10016=Ok +10017=End +10018=Register +10019=Entry +10020=Progress +10021=Unknown +10022=Apply and overwrite packet data? +10023=Selected diff --git a/Resources/pix_annotation.png b/Resources/pix_annotation.png new file mode 100644 index 0000000..34a5e8e Binary files /dev/null and b/Resources/pix_annotation.png differ diff --git a/Resources/pix_magnify.png b/Resources/pix_magnify.png new file mode 100644 index 0000000..6a22e58 Binary files /dev/null and b/Resources/pix_magnify.png differ diff --git a/Resources/pix_play.png b/Resources/pix_play.png new file mode 100644 index 0000000..82f65c8 Binary files /dev/null and b/Resources/pix_play.png differ diff --git a/Resources/pix_tab_content.png b/Resources/pix_tab_content.png new file mode 100644 index 0000000..2bb70e7 Binary files /dev/null and b/Resources/pix_tab_content.png differ diff --git a/Resources/pix_tab_setting.png b/Resources/pix_tab_setting.png new file mode 100644 index 0000000..1241cdd Binary files /dev/null and b/Resources/pix_tab_setting.png differ diff --git a/Resources/pix_tab_tool.png b/Resources/pix_tab_tool.png new file mode 100644 index 0000000..f569ccf Binary files /dev/null and b/Resources/pix_tab_tool.png differ diff --git a/Tab/ConfigForm.Designer.cs b/Tab/ConfigForm.Designer.cs new file mode 100644 index 0000000..f9cf76c --- /dev/null +++ b/Tab/ConfigForm.Designer.cs @@ -0,0 +1,103 @@ + +namespace DutyContent.Tab +{ + partial class ConfigForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.panel1 = new System.Windows.Forms.Panel(); + this.lblCurrentLang = new System.Windows.Forms.Label(); + this.cboDispLang = new System.Windows.Forms.ComboBox(); + this.lblDispLang = new System.Windows.Forms.Label(); + this.panel1.SuspendLayout(); + this.SuspendLayout(); + // + // panel1 + // + this.panel1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.panel1.Controls.Add(this.lblCurrentLang); + this.panel1.Controls.Add(this.cboDispLang); + this.panel1.Controls.Add(this.lblDispLang); + this.panel1.Location = new System.Drawing.Point(12, 12); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(776, 158); + this.panel1.TabIndex = 0; + // + // lblCurrentLang + // + this.lblCurrentLang.Location = new System.Drawing.Point(237, 37); + this.lblCurrentLang.Name = "lblCurrentLang"; + this.lblCurrentLang.Size = new System.Drawing.Size(150, 15); + this.lblCurrentLang.TabIndex = 4; + this.lblCurrentLang.Text = "--"; + this.lblCurrentLang.TextAlign = System.Drawing.ContentAlignment.TopRight; + // + // cboDispLang + // + this.cboDispLang.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cboDispLang.FormattingEnabled = true; + this.cboDispLang.Location = new System.Drawing.Point(170, 13); + this.cboDispLang.Name = "cboDispLang"; + this.cboDispLang.Size = new System.Drawing.Size(217, 21); + this.cboDispLang.TabIndex = 1; + this.cboDispLang.SelectedIndexChanged += new System.EventHandler(this.CboDispLang_SelectedIndexChanged); + // + // lblDispLang + // + this.lblDispLang.AutoSize = true; + this.lblDispLang.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.lblDispLang.Location = new System.Drawing.Point(12, 11); + this.lblDispLang.Name = "lblDispLang"; + this.lblDispLang.Size = new System.Drawing.Size(39, 20); + this.lblDispLang.TabIndex = 0; + this.lblDispLang.Text = "201"; + // + // ConfigForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScroll = true; + this.ClientSize = new System.Drawing.Size(800, 450); + this.Controls.Add(this.panel1); + this.Name = "ConfigForm"; + this.Text = "Config"; + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.Label lblDispLang; + private System.Windows.Forms.ComboBox cboDispLang; + private System.Windows.Forms.Label lblCurrentLang; + } +} \ No newline at end of file diff --git a/Tab/ConfigForm.cs b/Tab/ConfigForm.cs new file mode 100644 index 0000000..91a6704 --- /dev/null +++ b/Tab/ConfigForm.cs @@ -0,0 +1,106 @@ +using DutyContent.Interface; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace DutyContent.Tab +{ + public partial class ConfigForm : Form, Interface.ISuppLocale, Interface.ISuppActPlugin + { + private static ConfigForm _self; + public static ConfigForm Self => _self; + + public ConfigForm() + { + _self = this; + + InitializeComponent(); + } + + public void PluginDeinitialize() + { + + } + + public void PluginInitialize() + { + // + lblCurrentLang.Text = MesgLog.Text("LANG"); + + // + var lang = MakeConfigLangList(); + + foreach (var i in lang) + { + var n = cboDispLang.Items.Add(i); + if (i.Equals(DcConfig.Language)) + cboDispLang.SelectedIndex = n; + } + + if (cboDispLang.SelectedIndex < 0) + cboDispLang.SelectedIndex = 0; + } + + public void RefreshLocale() + { + + } + + public void UpdateUiLocale() + { + lblDispLang.Text = MesgLog.Text(201); + } + + public static List MakeConfigLangList() + { + List lst = new List(); + + lst.Add($"<{MesgLog.Text(26)}>"); + + DirectoryInfo di = new DirectoryInfo(DcConfig.DataPath); + + foreach (var fi in di.GetFiles("DcLang-*.txt")) + { + var s = fi.Name.Substring(7, fi.Name.Length - 7 - 4); + lst.Add(s); + } + + return lst; + } + + private void CboDispLang_SelectedIndexChanged(object sender, EventArgs e) + { + if (!DcConfig.PluginEnable) + return; + + if (cboDispLang.SelectedIndex == 0) + { + // default + DcConfig.Language = string.Empty; + } + else + { + var l = (string)cboDispLang.SelectedItem; + + if (string.IsNullOrWhiteSpace(l) || l.Equals(DcConfig.Language)) + return; + + DcConfig.Language = l; + } + + // + DcConfig.ReadLanguage(); + DcControl.Self?.UpdateUiLocale(); + DcConfig.SaveConfig(); + + lblCurrentLang.Text = MesgLog.Text("LANG"); + } + } +} diff --git a/Tab/ConfigForm.resx b/Tab/ConfigForm.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/Tab/ConfigForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Tab/DutyForm.Designer.cs b/Tab/DutyForm.Designer.cs new file mode 100644 index 0000000..07f3d05 --- /dev/null +++ b/Tab/DutyForm.Designer.cs @@ -0,0 +1,935 @@ + +namespace DutyContent.Tab +{ + partial class DutyForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.Windows.Forms.ListViewItem listViewItem1 = new System.Windows.Forms.ListViewItem(new string[] { + "FATE", + "", + "", + ""}, -1); + System.Windows.Forms.ListViewItem listViewItem2 = new System.Windows.Forms.ListViewItem(new string[] { + "Duty", + "", + "", + ""}, -1); + System.Windows.Forms.ListViewItem listViewItem3 = new System.Windows.Forms.ListViewItem(new string[] { + "Match", + "", + "", + ""}, -1); + System.Windows.Forms.ListViewItem listViewItem4 = new System.Windows.Forms.ListViewItem(new string[] { + "Instance", + "", + "", + ""}, -1); + System.Windows.Forms.ListViewItem listViewItem5 = new System.Windows.Forms.ListViewItem(new string[] { + "Southern Bozja", + "", + "", + ""}, -1); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DutyForm)); + this.tabContent = new System.Windows.Forms.TabControl(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.rdoFatePreset4 = new System.Windows.Forms.RadioButton(); + this.rdoFatePreset3 = new System.Windows.Forms.RadioButton(); + this.rdoFatePreset2 = new System.Windows.Forms.RadioButton(); + this.rdoFatePreset1 = new System.Windows.Forms.RadioButton(); + this.treeFates = new System.Windows.Forms.TreeView(); + this.txtContentLog = new System.Windows.Forms.RichTextBox(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.panel4 = new System.Windows.Forms.Panel(); + this.lblTelegramToken = new System.Windows.Forms.Label(); + this.txtTelegramToken = new System.Windows.Forms.TextBox(); + this.lblTelegramId = new System.Windows.Forms.Label(); + this.txtTelegramId = new System.Windows.Forms.TextBox(); + this.chkUseNotifyTelegram = new System.Windows.Forms.CheckBox(); + this.btnTestNotify = new System.Windows.Forms.Button(); + this.lblLineNotifyBotLink = new System.Windows.Forms.LinkLabel(); + this.lblLineToken = new System.Windows.Forms.Label(); + this.txtLineToken = new System.Windows.Forms.TextBox(); + this.chkUseNotifyLine = new System.Windows.Forms.CheckBox(); + this.panel3 = new System.Windows.Forms.Panel(); + this.lblCurrentDataSet = new System.Windows.Forms.Label(); + this.cboDataset = new System.Windows.Forms.ComboBox(); + this.lblDataSet = new System.Windows.Forms.Label(); + this.btnLogFont = new System.Windows.Forms.Button(); + this.lblLogFont = new System.Windows.Forms.Label(); + this.panel2 = new System.Windows.Forms.Panel(); + this.btnSoundPlayFate = new System.Windows.Forms.Button(); + this.btnSoundPlayInstance = new System.Windows.Forms.Button(); + this.btnSoundFindFate = new System.Windows.Forms.Button(); + this.btnSoundFindInstance = new System.Windows.Forms.Button(); + this.lblSoundFate = new System.Windows.Forms.Label(); + this.txtSoundFate = new System.Windows.Forms.TextBox(); + this.txtSoundInstance = new System.Windows.Forms.TextBox(); + this.chkEnableSound = new System.Windows.Forms.CheckBox(); + this.lblSoundInstance = new System.Windows.Forms.Label(); + this.panel1 = new System.Windows.Forms.Panel(); + this.progbOverlayTransparent = new System.Windows.Forms.ProgressBar(); + this.btnOverlayDimming = new System.Windows.Forms.Button(); + this.lblOverlayTransparent = new System.Windows.Forms.Label(); + this.chkEnableOverlay = new System.Windows.Forms.CheckBox(); + this.tabPage3 = new System.Windows.Forms.TabPage(); + this.panel5 = new System.Windows.Forms.Panel(); + this.txtPacketDescription = new System.Windows.Forms.TextBox(); + this.lblPacketDesc = new System.Windows.Forms.Label(); + this.btnPacketApply = new System.Windows.Forms.Button(); + this.btnPacketStart = new System.Windows.Forms.Button(); + this.lstBozjaInfo = new System.Windows.Forms.ListView(); + this.columnHeader5 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader6 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader7 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader8 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.lblPacketBozja = new System.Windows.Forms.Label(); + this.txtPacketInfo = new System.Windows.Forms.TextBox(); + this.lstPacketInfo = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.lblPacketFinder = new System.Windows.Forms.Label(); + this.ilTabContent = new System.Windows.Forms.ImageList(this.components); + this.tabContent.SuspendLayout(); + this.tabPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); + this.splitContainer1.Panel1.SuspendLayout(); + this.splitContainer1.Panel2.SuspendLayout(); + this.splitContainer1.SuspendLayout(); + this.tabPage2.SuspendLayout(); + this.panel4.SuspendLayout(); + this.panel3.SuspendLayout(); + this.panel2.SuspendLayout(); + this.panel1.SuspendLayout(); + this.tabPage3.SuspendLayout(); + this.panel5.SuspendLayout(); + this.SuspendLayout(); + // + // tabContent + // + this.tabContent.Controls.Add(this.tabPage1); + this.tabContent.Controls.Add(this.tabPage2); + this.tabContent.Controls.Add(this.tabPage3); + this.tabContent.Dock = System.Windows.Forms.DockStyle.Fill; + this.tabContent.ImageList = this.ilTabContent; + this.tabContent.Location = new System.Drawing.Point(0, 0); + this.tabContent.Name = "tabContent"; + this.tabContent.SelectedIndex = 0; + this.tabContent.Size = new System.Drawing.Size(800, 502); + this.tabContent.TabIndex = 0; + // + // tabPage1 + // + this.tabPage1.Controls.Add(this.splitContainer1); + this.tabPage1.ImageIndex = 0; + this.tabPage1.Location = new System.Drawing.Point(4, 39); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Padding = new System.Windows.Forms.Padding(3); + this.tabPage1.Size = new System.Drawing.Size(792, 459); + this.tabPage1.TabIndex = 0; + this.tabPage1.Text = "301"; + this.tabPage1.UseVisualStyleBackColor = true; + // + // splitContainer1 + // + this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer1.Location = new System.Drawing.Point(3, 3); + this.splitContainer1.Name = "splitContainer1"; + // + // splitContainer1.Panel1 + // + this.splitContainer1.Panel1.Controls.Add(this.rdoFatePreset4); + this.splitContainer1.Panel1.Controls.Add(this.rdoFatePreset3); + this.splitContainer1.Panel1.Controls.Add(this.rdoFatePreset2); + this.splitContainer1.Panel1.Controls.Add(this.rdoFatePreset1); + this.splitContainer1.Panel1.Controls.Add(this.treeFates); + // + // splitContainer1.Panel2 + // + this.splitContainer1.Panel2.Controls.Add(this.txtContentLog); + this.splitContainer1.Size = new System.Drawing.Size(786, 453); + this.splitContainer1.SplitterDistance = 262; + this.splitContainer1.TabIndex = 0; + // + // rdoFatePreset4 + // + this.rdoFatePreset4.AutoSize = true; + this.rdoFatePreset4.Location = new System.Drawing.Point(116, 6); + this.rdoFatePreset4.Name = "rdoFatePreset4"; + this.rdoFatePreset4.Size = new System.Drawing.Size(31, 17); + this.rdoFatePreset4.TabIndex = 4; + this.rdoFatePreset4.TabStop = true; + this.rdoFatePreset4.Tag = "3"; + this.rdoFatePreset4.Text = "4"; + this.rdoFatePreset4.UseVisualStyleBackColor = true; + this.rdoFatePreset4.CheckedChanged += new System.EventHandler(this.RdoFatePreset4_CheckedChanged); + // + // rdoFatePreset3 + // + this.rdoFatePreset3.AutoSize = true; + this.rdoFatePreset3.Location = new System.Drawing.Point(79, 6); + this.rdoFatePreset3.Name = "rdoFatePreset3"; + this.rdoFatePreset3.Size = new System.Drawing.Size(31, 17); + this.rdoFatePreset3.TabIndex = 3; + this.rdoFatePreset3.TabStop = true; + this.rdoFatePreset3.Tag = "2"; + this.rdoFatePreset3.Text = "3"; + this.rdoFatePreset3.UseVisualStyleBackColor = true; + this.rdoFatePreset3.CheckedChanged += new System.EventHandler(this.RdoFatePreset3_CheckedChanged); + // + // rdoFatePreset2 + // + this.rdoFatePreset2.AutoSize = true; + this.rdoFatePreset2.Location = new System.Drawing.Point(42, 6); + this.rdoFatePreset2.Name = "rdoFatePreset2"; + this.rdoFatePreset2.Size = new System.Drawing.Size(31, 17); + this.rdoFatePreset2.TabIndex = 2; + this.rdoFatePreset2.TabStop = true; + this.rdoFatePreset2.Tag = "1"; + this.rdoFatePreset2.Text = "2"; + this.rdoFatePreset2.UseVisualStyleBackColor = true; + this.rdoFatePreset2.CheckedChanged += new System.EventHandler(this.RdoFatePreset2_CheckedChanged); + // + // rdoFatePreset1 + // + this.rdoFatePreset1.AutoSize = true; + this.rdoFatePreset1.Checked = true; + this.rdoFatePreset1.Location = new System.Drawing.Point(5, 6); + this.rdoFatePreset1.Name = "rdoFatePreset1"; + this.rdoFatePreset1.Size = new System.Drawing.Size(31, 17); + this.rdoFatePreset1.TabIndex = 1; + this.rdoFatePreset1.TabStop = true; + this.rdoFatePreset1.Tag = "0"; + this.rdoFatePreset1.Text = "1"; + this.rdoFatePreset1.UseVisualStyleBackColor = true; + this.rdoFatePreset1.CheckedChanged += new System.EventHandler(this.RdoFatePreset1_CheckedChanged); + // + // treeFates + // + this.treeFates.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.treeFates.CheckBoxes = true; + this.treeFates.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.treeFates.Location = new System.Drawing.Point(0, 29); + this.treeFates.Name = "treeFates"; + this.treeFates.Size = new System.Drawing.Size(260, 424); + this.treeFates.TabIndex = 0; + this.treeFates.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.TreeFates_AfterCheck); + // + // txtContentLog + // + this.txtContentLog.BackColor = System.Drawing.Color.AliceBlue; + this.txtContentLog.Dock = System.Windows.Forms.DockStyle.Fill; + this.txtContentLog.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.txtContentLog.Location = new System.Drawing.Point(0, 0); + this.txtContentLog.Name = "txtContentLog"; + this.txtContentLog.ReadOnly = true; + this.txtContentLog.Size = new System.Drawing.Size(520, 453); + this.txtContentLog.TabIndex = 0; + this.txtContentLog.Text = ""; + // + // tabPage2 + // + this.tabPage2.Controls.Add(this.panel4); + this.tabPage2.Controls.Add(this.panel3); + this.tabPage2.Controls.Add(this.panel2); + this.tabPage2.Controls.Add(this.panel1); + this.tabPage2.ImageIndex = 1; + this.tabPage2.Location = new System.Drawing.Point(4, 39); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Padding = new System.Windows.Forms.Padding(3); + this.tabPage2.Size = new System.Drawing.Size(792, 459); + this.tabPage2.TabIndex = 1; + this.tabPage2.Text = "302"; + this.tabPage2.UseVisualStyleBackColor = true; + // + // panel4 + // + this.panel4.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.panel4.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.panel4.Controls.Add(this.lblTelegramToken); + this.panel4.Controls.Add(this.txtTelegramToken); + this.panel4.Controls.Add(this.lblTelegramId); + this.panel4.Controls.Add(this.txtTelegramId); + this.panel4.Controls.Add(this.chkUseNotifyTelegram); + this.panel4.Controls.Add(this.btnTestNotify); + this.panel4.Controls.Add(this.lblLineNotifyBotLink); + this.panel4.Controls.Add(this.lblLineToken); + this.panel4.Controls.Add(this.txtLineToken); + this.panel4.Controls.Add(this.chkUseNotifyLine); + this.panel4.Location = new System.Drawing.Point(6, 273); + this.panel4.Name = "panel4"; + this.panel4.Size = new System.Drawing.Size(778, 143); + this.panel4.TabIndex = 3; + // + // lblTelegramToken + // + this.lblTelegramToken.AutoSize = true; + this.lblTelegramToken.Location = new System.Drawing.Point(22, 118); + this.lblTelegramToken.Name = "lblTelegramToken"; + this.lblTelegramToken.Size = new System.Drawing.Size(25, 13); + this.lblTelegramToken.TabIndex = 15; + this.lblTelegramToken.Text = "315"; + // + // txtTelegramToken + // + this.txtTelegramToken.Location = new System.Drawing.Point(108, 115); + this.txtTelegramToken.Name = "txtTelegramToken"; + this.txtTelegramToken.Size = new System.Drawing.Size(515, 20); + this.txtTelegramToken.TabIndex = 14; + this.txtTelegramToken.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TxtTelegramToken_KeyDown); + // + // lblTelegramId + // + this.lblTelegramId.AutoSize = true; + this.lblTelegramId.Location = new System.Drawing.Point(23, 92); + this.lblTelegramId.Name = "lblTelegramId"; + this.lblTelegramId.Size = new System.Drawing.Size(25, 13); + this.lblTelegramId.TabIndex = 13; + this.lblTelegramId.Text = "314"; + // + // txtTelegramId + // + this.txtTelegramId.Location = new System.Drawing.Point(108, 89); + this.txtTelegramId.Name = "txtTelegramId"; + this.txtTelegramId.Size = new System.Drawing.Size(515, 20); + this.txtTelegramId.TabIndex = 12; + this.txtTelegramId.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TxtTelegramId_KeyDown); + // + // chkUseNotifyTelegram + // + this.chkUseNotifyTelegram.AutoSize = true; + this.chkUseNotifyTelegram.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.chkUseNotifyTelegram.Location = new System.Drawing.Point(3, 59); + this.chkUseNotifyTelegram.Name = "chkUseNotifyTelegram"; + this.chkUseNotifyTelegram.Size = new System.Drawing.Size(58, 24); + this.chkUseNotifyTelegram.TabIndex = 11; + this.chkUseNotifyTelegram.Text = "313"; + this.chkUseNotifyTelegram.UseVisualStyleBackColor = true; + this.chkUseNotifyTelegram.CheckedChanged += new System.EventHandler(this.ChkUseNotifyTelegram_CheckedChanged); + // + // btnTestNotify + // + this.btnTestNotify.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btnTestNotify.BackgroundImage = global::DutyContent.Properties.Resources.pix_annotation; + this.btnTestNotify.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch; + this.btnTestNotify.Enabled = false; + this.btnTestNotify.Location = new System.Drawing.Point(722, 84); + this.btnTestNotify.Name = "btnTestNotify"; + this.btnTestNotify.Size = new System.Drawing.Size(51, 51); + this.btnTestNotify.TabIndex = 4; + this.btnTestNotify.UseVisualStyleBackColor = true; + this.btnTestNotify.Click += new System.EventHandler(this.BtnTestNotify_Click); + // + // lblLineNotifyBotLink + // + this.lblLineNotifyBotLink.AutoSize = true; + this.lblLineNotifyBotLink.Location = new System.Drawing.Point(496, 9); + this.lblLineNotifyBotLink.Name = "lblLineNotifyBotLink"; + this.lblLineNotifyBotLink.Size = new System.Drawing.Size(127, 13); + this.lblLineNotifyBotLink.TabIndex = 10; + this.lblLineNotifyBotLink.TabStop = true; + this.lblLineNotifyBotLink.Text = "https://notify-bot.line.me/"; + this.lblLineNotifyBotLink.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LblLineNotifyBotLink_LinkClicked); + // + // lblLineToken + // + this.lblLineToken.AutoSize = true; + this.lblLineToken.Location = new System.Drawing.Point(22, 36); + this.lblLineToken.Name = "lblLineToken"; + this.lblLineToken.Size = new System.Drawing.Size(25, 13); + this.lblLineToken.TabIndex = 9; + this.lblLineToken.Text = "312"; + // + // txtLineToken + // + this.txtLineToken.Location = new System.Drawing.Point(108, 33); + this.txtLineToken.Name = "txtLineToken"; + this.txtLineToken.Size = new System.Drawing.Size(515, 20); + this.txtLineToken.TabIndex = 1; + this.txtLineToken.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TxtLineToken_KeyDown); + // + // chkUseNotifyLine + // + this.chkUseNotifyLine.AutoSize = true; + this.chkUseNotifyLine.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.chkUseNotifyLine.Location = new System.Drawing.Point(3, 3); + this.chkUseNotifyLine.Name = "chkUseNotifyLine"; + this.chkUseNotifyLine.Size = new System.Drawing.Size(58, 24); + this.chkUseNotifyLine.TabIndex = 0; + this.chkUseNotifyLine.Text = "311"; + this.chkUseNotifyLine.UseVisualStyleBackColor = true; + this.chkUseNotifyLine.CheckedChanged += new System.EventHandler(this.ChkUseNotifyLine_CheckedChanged); + // + // panel3 + // + this.panel3.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.panel3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.panel3.Controls.Add(this.lblCurrentDataSet); + this.panel3.Controls.Add(this.cboDataset); + this.panel3.Controls.Add(this.lblDataSet); + this.panel3.Controls.Add(this.btnLogFont); + this.panel3.Controls.Add(this.lblLogFont); + this.panel3.Location = new System.Drawing.Point(6, 6); + this.panel3.Name = "panel3"; + this.panel3.Size = new System.Drawing.Size(778, 56); + this.panel3.TabIndex = 2; + // + // lblCurrentDataSet + // + this.lblCurrentDataSet.Location = new System.Drawing.Point(203, 30); + this.lblCurrentDataSet.Name = "lblCurrentDataSet"; + this.lblCurrentDataSet.Size = new System.Drawing.Size(150, 15); + this.lblCurrentDataSet.TabIndex = 3; + this.lblCurrentDataSet.Text = "--"; + this.lblCurrentDataSet.TextAlign = System.Drawing.ContentAlignment.TopRight; + // + // cboDataset + // + this.cboDataset.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cboDataset.FormattingEnabled = true; + this.cboDataset.Location = new System.Drawing.Point(110, 6); + this.cboDataset.Name = "cboDataset"; + this.cboDataset.Size = new System.Drawing.Size(243, 21); + this.cboDataset.TabIndex = 11; + this.cboDataset.SelectedIndexChanged += new System.EventHandler(this.CboDataset_SelectedIndexChanged); + // + // lblDataSet + // + this.lblDataSet.AutoSize = true; + this.lblDataSet.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.lblDataSet.Location = new System.Drawing.Point(22, 4); + this.lblDataSet.Name = "lblDataSet"; + this.lblDataSet.Size = new System.Drawing.Size(39, 20); + this.lblDataSet.TabIndex = 10; + this.lblDataSet.Text = "304"; + // + // btnLogFont + // + this.btnLogFont.Location = new System.Drawing.Point(515, 1); + this.btnLogFont.Name = "btnLogFont"; + this.btnLogFont.Size = new System.Drawing.Size(243, 48); + this.btnLogFont.TabIndex = 3; + this.btnLogFont.Text = "--"; + this.btnLogFont.UseVisualStyleBackColor = true; + this.btnLogFont.Click += new System.EventHandler(this.BtnLogFont_Click); + // + // lblLogFont + // + this.lblLogFont.AutoSize = true; + this.lblLogFont.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.lblLogFont.Location = new System.Drawing.Point(381, 4); + this.lblLogFont.Name = "lblLogFont"; + this.lblLogFont.Size = new System.Drawing.Size(39, 20); + this.lblLogFont.TabIndex = 9; + this.lblLogFont.Text = "305"; + // + // panel2 + // + this.panel2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.panel2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.panel2.Controls.Add(this.btnSoundPlayFate); + this.panel2.Controls.Add(this.btnSoundPlayInstance); + this.panel2.Controls.Add(this.btnSoundFindFate); + this.panel2.Controls.Add(this.btnSoundFindInstance); + this.panel2.Controls.Add(this.lblSoundFate); + this.panel2.Controls.Add(this.txtSoundFate); + this.panel2.Controls.Add(this.txtSoundInstance); + this.panel2.Controls.Add(this.chkEnableSound); + this.panel2.Controls.Add(this.lblSoundInstance); + this.panel2.Location = new System.Drawing.Point(6, 135); + this.panel2.Name = "panel2"; + this.panel2.Size = new System.Drawing.Size(778, 132); + this.panel2.TabIndex = 1; + // + // btnSoundPlayFate + // + this.btnSoundPlayFate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.btnSoundPlayFate.Enabled = false; + this.btnSoundPlayFate.Image = global::DutyContent.Properties.Resources.pix_play; + this.btnSoundPlayFate.Location = new System.Drawing.Point(743, 55); + this.btnSoundPlayFate.Name = "btnSoundPlayFate"; + this.btnSoundPlayFate.Size = new System.Drawing.Size(30, 30); + this.btnSoundPlayFate.TabIndex = 8; + this.btnSoundPlayFate.UseVisualStyleBackColor = true; + this.btnSoundPlayFate.Click += new System.EventHandler(this.BtnSoundPlayFate_Click); + // + // btnSoundPlayInstance + // + this.btnSoundPlayInstance.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.btnSoundPlayInstance.Enabled = false; + this.btnSoundPlayInstance.Image = global::DutyContent.Properties.Resources.pix_play; + this.btnSoundPlayInstance.Location = new System.Drawing.Point(743, 24); + this.btnSoundPlayInstance.Name = "btnSoundPlayInstance"; + this.btnSoundPlayInstance.Size = new System.Drawing.Size(30, 30); + this.btnSoundPlayInstance.TabIndex = 7; + this.btnSoundPlayInstance.UseVisualStyleBackColor = true; + this.btnSoundPlayInstance.Click += new System.EventHandler(this.BtnSoundPlayInstance_Click); + // + // btnSoundFindFate + // + this.btnSoundFindFate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.btnSoundFindFate.Enabled = false; + this.btnSoundFindFate.Image = global::DutyContent.Properties.Resources.pix_magnify; + this.btnSoundFindFate.Location = new System.Drawing.Point(709, 55); + this.btnSoundFindFate.Name = "btnSoundFindFate"; + this.btnSoundFindFate.Size = new System.Drawing.Size(30, 30); + this.btnSoundFindFate.TabIndex = 6; + this.btnSoundFindFate.UseVisualStyleBackColor = true; + this.btnSoundFindFate.Click += new System.EventHandler(this.BtnSoundFindFate_Click); + // + // btnSoundFindInstance + // + this.btnSoundFindInstance.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.btnSoundFindInstance.Enabled = false; + this.btnSoundFindInstance.Image = global::DutyContent.Properties.Resources.pix_magnify; + this.btnSoundFindInstance.Location = new System.Drawing.Point(709, 24); + this.btnSoundFindInstance.Name = "btnSoundFindInstance"; + this.btnSoundFindInstance.Size = new System.Drawing.Size(30, 30); + this.btnSoundFindInstance.TabIndex = 2; + this.btnSoundFindInstance.UseVisualStyleBackColor = true; + this.btnSoundFindInstance.Click += new System.EventHandler(this.BtnSoundFindInstance_Click); + // + // lblSoundFate + // + this.lblSoundFate.AutoSize = true; + this.lblSoundFate.Location = new System.Drawing.Point(22, 64); + this.lblSoundFate.Name = "lblSoundFate"; + this.lblSoundFate.Size = new System.Drawing.Size(25, 13); + this.lblSoundFate.TabIndex = 3; + this.lblSoundFate.Text = "310"; + // + // txtSoundFate + // + this.txtSoundFate.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtSoundFate.Enabled = false; + this.txtSoundFate.Location = new System.Drawing.Point(110, 61); + this.txtSoundFate.Name = "txtSoundFate"; + this.txtSoundFate.ReadOnly = true; + this.txtSoundFate.Size = new System.Drawing.Size(593, 20); + this.txtSoundFate.TabIndex = 4; + // + // txtSoundInstance + // + this.txtSoundInstance.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtSoundInstance.Enabled = false; + this.txtSoundInstance.Location = new System.Drawing.Point(110, 30); + this.txtSoundInstance.Name = "txtSoundInstance"; + this.txtSoundInstance.ReadOnly = true; + this.txtSoundInstance.Size = new System.Drawing.Size(593, 20); + this.txtSoundInstance.TabIndex = 5; + // + // chkEnableSound + // + this.chkEnableSound.AutoSize = true; + this.chkEnableSound.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.chkEnableSound.Location = new System.Drawing.Point(5, 3); + this.chkEnableSound.Name = "chkEnableSound"; + this.chkEnableSound.Size = new System.Drawing.Size(58, 24); + this.chkEnableSound.TabIndex = 4; + this.chkEnableSound.Text = "308"; + this.chkEnableSound.UseVisualStyleBackColor = true; + this.chkEnableSound.CheckedChanged += new System.EventHandler(this.ChkEnableSound_CheckedChanged); + // + // lblSoundInstance + // + this.lblSoundInstance.AutoSize = true; + this.lblSoundInstance.Location = new System.Drawing.Point(22, 33); + this.lblSoundInstance.Name = "lblSoundInstance"; + this.lblSoundInstance.Size = new System.Drawing.Size(25, 13); + this.lblSoundInstance.TabIndex = 2; + this.lblSoundInstance.Text = "309"; + // + // panel1 + // + this.panel1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.panel1.Controls.Add(this.progbOverlayTransparent); + this.panel1.Controls.Add(this.btnOverlayDimming); + this.panel1.Controls.Add(this.lblOverlayTransparent); + this.panel1.Controls.Add(this.chkEnableOverlay); + this.panel1.Location = new System.Drawing.Point(6, 68); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(778, 61); + this.panel1.TabIndex = 0; + // + // progbOverlayTransparent + // + this.progbOverlayTransparent.Enabled = false; + this.progbOverlayTransparent.Location = new System.Drawing.Point(108, 30); + this.progbOverlayTransparent.Maximum = 255; + this.progbOverlayTransparent.Name = "progbOverlayTransparent"; + this.progbOverlayTransparent.Size = new System.Drawing.Size(243, 23); + this.progbOverlayTransparent.TabIndex = 1; + this.progbOverlayTransparent.Click += new System.EventHandler(this.ProgbOverlayTransparent_Click); + // + // btnOverlayDimming + // + this.btnOverlayDimming.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.btnOverlayDimming.BackgroundImage = global::DutyContent.Properties.Resources.pix_annotation; + this.btnOverlayDimming.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch; + this.btnOverlayDimming.Enabled = false; + this.btnOverlayDimming.Location = new System.Drawing.Point(722, 3); + this.btnOverlayDimming.Name = "btnOverlayDimming"; + this.btnOverlayDimming.Size = new System.Drawing.Size(51, 51); + this.btnOverlayDimming.TabIndex = 3; + this.btnOverlayDimming.UseVisualStyleBackColor = true; + this.btnOverlayDimming.Click += new System.EventHandler(this.BtnOverlayDimming_Click); + // + // lblOverlayTransparent + // + this.lblOverlayTransparent.AutoSize = true; + this.lblOverlayTransparent.Location = new System.Drawing.Point(23, 35); + this.lblOverlayTransparent.Name = "lblOverlayTransparent"; + this.lblOverlayTransparent.Size = new System.Drawing.Size(25, 13); + this.lblOverlayTransparent.TabIndex = 2; + this.lblOverlayTransparent.Text = "307"; + // + // chkEnableOverlay + // + this.chkEnableOverlay.AutoSize = true; + this.chkEnableOverlay.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.chkEnableOverlay.Location = new System.Drawing.Point(3, 3); + this.chkEnableOverlay.Name = "chkEnableOverlay"; + this.chkEnableOverlay.Size = new System.Drawing.Size(58, 24); + this.chkEnableOverlay.TabIndex = 0; + this.chkEnableOverlay.Text = "306"; + this.chkEnableOverlay.UseVisualStyleBackColor = true; + this.chkEnableOverlay.CheckedChanged += new System.EventHandler(this.ChkEnableOverlay_CheckedChanged); + // + // tabPage3 + // + this.tabPage3.Controls.Add(this.panel5); + this.tabPage3.ImageIndex = 2; + this.tabPage3.Location = new System.Drawing.Point(4, 39); + this.tabPage3.Name = "tabPage3"; + this.tabPage3.Padding = new System.Windows.Forms.Padding(3); + this.tabPage3.Size = new System.Drawing.Size(792, 459); + this.tabPage3.TabIndex = 2; + this.tabPage3.Text = "303"; + this.tabPage3.UseVisualStyleBackColor = true; + // + // panel5 + // + this.panel5.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.panel5.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.panel5.Controls.Add(this.txtPacketDescription); + this.panel5.Controls.Add(this.lblPacketDesc); + this.panel5.Controls.Add(this.btnPacketApply); + this.panel5.Controls.Add(this.btnPacketStart); + this.panel5.Controls.Add(this.lstBozjaInfo); + this.panel5.Controls.Add(this.lblPacketBozja); + this.panel5.Controls.Add(this.txtPacketInfo); + this.panel5.Controls.Add(this.lstPacketInfo); + this.panel5.Controls.Add(this.lblPacketFinder); + this.panel5.Location = new System.Drawing.Point(6, 6); + this.panel5.Name = "panel5"; + this.panel5.Size = new System.Drawing.Size(780, 261); + this.panel5.TabIndex = 0; + // + // txtPacketDescription + // + this.txtPacketDescription.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtPacketDescription.Enabled = false; + this.txtPacketDescription.Location = new System.Drawing.Point(336, 58); + this.txtPacketDescription.Name = "txtPacketDescription"; + this.txtPacketDescription.Size = new System.Drawing.Size(439, 20); + this.txtPacketDescription.TabIndex = 8; + // + // lblPacketDesc + // + this.lblPacketDesc.AutoSize = true; + this.lblPacketDesc.Location = new System.Drawing.Point(333, 42); + this.lblPacketDesc.Name = "lblPacketDesc"; + this.lblPacketDesc.Size = new System.Drawing.Size(25, 13); + this.lblPacketDesc.TabIndex = 7; + this.lblPacketDesc.Text = "317"; + // + // btnPacketApply + // + this.btnPacketApply.Enabled = false; + this.btnPacketApply.Location = new System.Drawing.Point(287, 6); + this.btnPacketApply.Name = "btnPacketApply"; + this.btnPacketApply.Size = new System.Drawing.Size(123, 30); + this.btnPacketApply.TabIndex = 6; + this.btnPacketApply.Text = "10009"; + this.btnPacketApply.UseVisualStyleBackColor = true; + this.btnPacketApply.Visible = false; + this.btnPacketApply.Click += new System.EventHandler(this.BtnPacketApply_Click); + // + // btnPacketStart + // + this.btnPacketStart.Location = new System.Drawing.Point(158, 5); + this.btnPacketStart.Name = "btnPacketStart"; + this.btnPacketStart.Size = new System.Drawing.Size(123, 30); + this.btnPacketStart.TabIndex = 5; + this.btnPacketStart.Text = "10007"; + this.btnPacketStart.UseVisualStyleBackColor = true; + this.btnPacketStart.Click += new System.EventHandler(this.BtnPacketStart_Click); + // + // lstBozjaInfo + // + this.lstBozjaInfo.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.lstBozjaInfo.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader5, + this.columnHeader6, + this.columnHeader7, + this.columnHeader8}); + this.lstBozjaInfo.Enabled = false; + this.lstBozjaInfo.FullRowSelect = true; + this.lstBozjaInfo.GridLines = true; + this.lstBozjaInfo.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.lstBozjaInfo.HideSelection = false; + this.lstBozjaInfo.Location = new System.Drawing.Point(333, 107); + this.lstBozjaInfo.MultiSelect = false; + this.lstBozjaInfo.Name = "lstBozjaInfo"; + this.lstBozjaInfo.Size = new System.Drawing.Size(442, 148); + this.lstBozjaInfo.TabIndex = 4; + this.lstBozjaInfo.UseCompatibleStateImageBehavior = false; + this.lstBozjaInfo.View = System.Windows.Forms.View.Details; + this.lstBozjaInfo.SelectedIndexChanged += new System.EventHandler(this.LstBozjaInfo_SelectedIndexChanged); + this.lstBozjaInfo.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.LstBozjaInfo_MouseDoubleClick); + // + // columnHeader5 + // + this.columnHeader5.Text = "Name"; + this.columnHeader5.Width = 233; + // + // columnHeader6 + // + this.columnHeader6.Text = "Status"; + this.columnHeader6.Width = 67; + // + // columnHeader7 + // + this.columnHeader7.Text = "Member"; + this.columnHeader7.Width = 55; + // + // columnHeader8 + // + this.columnHeader8.Text = "Progress"; + this.columnHeader8.Width = 56; + // + // lblPacketBozja + // + this.lblPacketBozja.AutoSize = true; + this.lblPacketBozja.Location = new System.Drawing.Point(333, 91); + this.lblPacketBozja.Name = "lblPacketBozja"; + this.lblPacketBozja.Size = new System.Drawing.Size(25, 13); + this.lblPacketBozja.TabIndex = 3; + this.lblPacketBozja.Text = "318"; + // + // txtPacketInfo + // + this.txtPacketInfo.BackColor = System.Drawing.SystemColors.Window; + this.txtPacketInfo.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.txtPacketInfo.Enabled = false; + this.txtPacketInfo.Location = new System.Drawing.Point(3, 166); + this.txtPacketInfo.Multiline = true; + this.txtPacketInfo.Name = "txtPacketInfo"; + this.txtPacketInfo.ReadOnly = true; + this.txtPacketInfo.Size = new System.Drawing.Size(324, 89); + this.txtPacketInfo.TabIndex = 2; + // + // lstPacketInfo + // + this.lstPacketInfo.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2, + this.columnHeader3, + this.columnHeader4}); + this.lstPacketInfo.Enabled = false; + this.lstPacketInfo.FullRowSelect = true; + this.lstPacketInfo.GridLines = true; + this.lstPacketInfo.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.lstPacketInfo.HideSelection = false; + this.lstPacketInfo.Items.AddRange(new System.Windows.Forms.ListViewItem[] { + listViewItem1, + listViewItem2, + listViewItem3, + listViewItem4, + listViewItem5}); + this.lstPacketInfo.Location = new System.Drawing.Point(3, 42); + this.lstPacketInfo.MultiSelect = false; + this.lstPacketInfo.Name = "lstPacketInfo"; + this.lstPacketInfo.Size = new System.Drawing.Size(324, 118); + this.lstPacketInfo.TabIndex = 1; + this.lstPacketInfo.UseCompatibleStateImageBehavior = false; + this.lstPacketInfo.View = System.Windows.Forms.View.Details; + this.lstPacketInfo.SelectedIndexChanged += new System.EventHandler(this.LstPacketInfo_SelectedIndexChanged); + // + // columnHeader1 + // + this.columnHeader1.Text = "Function"; + this.columnHeader1.Width = 100; + // + // columnHeader2 + // + this.columnHeader2.Text = "Current"; + this.columnHeader2.Width = 70; + // + // columnHeader3 + // + this.columnHeader3.Text = "Status"; + this.columnHeader3.Width = 80; + // + // columnHeader4 + // + this.columnHeader4.Text = "Found"; + this.columnHeader4.Width = 70; + // + // lblPacketFinder + // + this.lblPacketFinder.AutoSize = true; + this.lblPacketFinder.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.lblPacketFinder.Location = new System.Drawing.Point(3, -1); + this.lblPacketFinder.Name = "lblPacketFinder"; + this.lblPacketFinder.Size = new System.Drawing.Size(43, 24); + this.lblPacketFinder.TabIndex = 0; + this.lblPacketFinder.Text = "316"; + // + // ilTabContent + // + this.ilTabContent.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("ilTabContent.ImageStream"))); + this.ilTabContent.TransparentColor = System.Drawing.Color.Transparent; + this.ilTabContent.Images.SetKeyName(0, "pix_tab_content.png"); + this.ilTabContent.Images.SetKeyName(1, "pix_tab_setting.png"); + this.ilTabContent.Images.SetKeyName(2, "pix_tab_tool.png"); + // + // DutyForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScroll = true; + this.ClientSize = new System.Drawing.Size(800, 502); + this.Controls.Add(this.tabContent); + this.Name = "DutyForm"; + this.Text = "Duty"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.DutyTabForm_FormClosing); + this.tabContent.ResumeLayout(false); + this.tabPage1.ResumeLayout(false); + this.splitContainer1.Panel1.ResumeLayout(false); + this.splitContainer1.Panel1.PerformLayout(); + this.splitContainer1.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); + this.splitContainer1.ResumeLayout(false); + this.tabPage2.ResumeLayout(false); + this.panel4.ResumeLayout(false); + this.panel4.PerformLayout(); + this.panel3.ResumeLayout(false); + this.panel3.PerformLayout(); + this.panel2.ResumeLayout(false); + this.panel2.PerformLayout(); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + this.tabPage3.ResumeLayout(false); + this.panel5.ResumeLayout(false); + this.panel5.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TabControl tabContent; + private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.TabPage tabPage2; + private System.Windows.Forms.TabPage tabPage3; + private System.Windows.Forms.ImageList ilTabContent; + private System.Windows.Forms.SplitContainer splitContainer1; + private System.Windows.Forms.TreeView treeFates; + private System.Windows.Forms.RichTextBox txtContentLog; + private System.Windows.Forms.RadioButton rdoFatePreset4; + private System.Windows.Forms.RadioButton rdoFatePreset3; + private System.Windows.Forms.RadioButton rdoFatePreset2; + private System.Windows.Forms.RadioButton rdoFatePreset1; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.Button btnOverlayDimming; + private System.Windows.Forms.Label lblOverlayTransparent; + private System.Windows.Forms.CheckBox chkEnableOverlay; + private System.Windows.Forms.ProgressBar progbOverlayTransparent; + private System.Windows.Forms.Panel panel2; + private System.Windows.Forms.Label lblSoundFate; + private System.Windows.Forms.TextBox txtSoundFate; + private System.Windows.Forms.TextBox txtSoundInstance; + private System.Windows.Forms.CheckBox chkEnableSound; + private System.Windows.Forms.Label lblSoundInstance; + private System.Windows.Forms.Button btnSoundPlayFate; + private System.Windows.Forms.Button btnSoundPlayInstance; + private System.Windows.Forms.Button btnSoundFindFate; + private System.Windows.Forms.Button btnSoundFindInstance; + private System.Windows.Forms.Panel panel3; + private System.Windows.Forms.Button btnLogFont; + private System.Windows.Forms.Label lblLogFont; + private System.Windows.Forms.ComboBox cboDataset; + private System.Windows.Forms.Label lblDataSet; + private System.Windows.Forms.Label lblCurrentDataSet; + private System.Windows.Forms.Panel panel4; + private System.Windows.Forms.LinkLabel lblLineNotifyBotLink; + private System.Windows.Forms.Label lblLineToken; + private System.Windows.Forms.TextBox txtLineToken; + private System.Windows.Forms.CheckBox chkUseNotifyLine; + private System.Windows.Forms.Button btnTestNotify; + private System.Windows.Forms.Label lblTelegramToken; + private System.Windows.Forms.TextBox txtTelegramToken; + private System.Windows.Forms.Label lblTelegramId; + private System.Windows.Forms.TextBox txtTelegramId; + private System.Windows.Forms.CheckBox chkUseNotifyTelegram; + private System.Windows.Forms.Panel panel5; + private System.Windows.Forms.ListView lstBozjaInfo; + private System.Windows.Forms.Label lblPacketBozja; + private System.Windows.Forms.TextBox txtPacketInfo; + private System.Windows.Forms.ListView lstPacketInfo; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.ColumnHeader columnHeader3; + private System.Windows.Forms.ColumnHeader columnHeader4; + private System.Windows.Forms.Label lblPacketFinder; + private System.Windows.Forms.Button btnPacketApply; + private System.Windows.Forms.Button btnPacketStart; + private System.Windows.Forms.ColumnHeader columnHeader5; + private System.Windows.Forms.ColumnHeader columnHeader6; + private System.Windows.Forms.ColumnHeader columnHeader7; + private System.Windows.Forms.TextBox txtPacketDescription; + private System.Windows.Forms.Label lblPacketDesc; + private System.Windows.Forms.ColumnHeader columnHeader8; + } +} \ No newline at end of file diff --git a/Tab/DutyForm.cs b/Tab/DutyForm.cs new file mode 100644 index 0000000..3201f69 --- /dev/null +++ b/Tab/DutyForm.cs @@ -0,0 +1,1283 @@ +using DutyContent.Interface; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Net; +using System.Net.Http; +using System.Text; +using System.IO; + +namespace DutyContent.Tab +{ + public partial class DutyForm : Form, Interface.ISuppLocale, Interface.IPacketHandler, Interface.ISuppActPlugin + { + private static DutyForm _self; + public static DutyForm Self => _self; + + // + private bool _is_lock_fate; + private bool _is_skirmish_area; + private bool _is_packet_finder; + private DcConfig.PacketConfig _new_packet; + + private Timer _save_timer; + private Overlay.DutyOvForm _overlay; + + public DutyForm() + { + _self = this; + + InitializeComponent(); + + _overlay = new Overlay.DutyOvForm(); + } + + private void DutyTabForm_FormClosing(object sender, FormClosingEventArgs e) + { + if (_save_timer != null) + _save_timer.Stop(); + } + + public void PluginInitialize() + { + // + lblCurrentDataSet.Text = DcContent.Language; + + // + var lang = MakeDutyLangList(); + + foreach (var i in lang) + { + var n = cboDataset.Items.Add(i); + if (i.Equals(DcConfig.Duty.Language)) + cboDataset.SelectedIndex = n; + } + + // + var font = new Font(DcConfig.Duty.LogFontFamily, DcConfig.Duty.LogFontSize, FontStyle.Regular, GraphicsUnit.Point); + txtContentLog.Font = font; + btnLogFont.Font = font; + btnLogFont.Text = $"{DcConfig.Duty.LogFontFamily}, {DcConfig.Duty.LogFontSize}"; + + // + chkEnableOverlay.Checked = DcConfig.Duty.EnableOverlay; + + progbOverlayTransparent.Enabled = DcConfig.Duty.EnableOverlay; + btnOverlayDimming.Enabled = DcConfig.Duty.EnableOverlay; + + // + _overlay.SetText(MesgLog.Text(99, System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString())); + _overlay.Location = DcConfig.Duty.OverlayLocation; + + if (DcConfig.Duty.EnableOverlay) + _overlay.Show(); + else + _overlay.Hide(); + + // + chkEnableSound.Checked = DcConfig.Duty.EnableSound; + + txtSoundInstance.Text = DcConfig.Duty.SoundInstanceFile; + txtSoundInstance.Enabled = DcConfig.Duty.EnableSound; + btnSoundFindInstance.Enabled = DcConfig.Duty.EnableSound; + btnSoundPlayInstance.Enabled = DcConfig.Duty.EnableSound; + + txtSoundFate.Text = DcConfig.Duty.SoundFateFile; + txtSoundFate.Enabled = DcConfig.Duty.EnableSound; + btnSoundFindFate.Enabled = DcConfig.Duty.EnableSound; + btnSoundPlayFate.Enabled = DcConfig.Duty.EnableSound; + + // + chkUseNotifyLine.Checked = DcConfig.Duty.UseNotifyLine; + txtLineToken.Text = DcConfig.Duty.NotifyLineToken; + //txtLineToken.Enabled = !DcConfig.Duty.UseNotifyLine; + + chkUseNotifyTelegram.Checked = DcConfig.Duty.UseNotifyTelegram; + txtTelegramId.Text = DcConfig.Duty.NotifyTelegramId; + txtTelegramToken.Text = DcConfig.Duty.NotifyTelegramToken; + //txtLineToken.Enabled = !DcConfig.Duty.UseNotifyTelegram; + //txtLineToken.Enabled = !DcConfig.Duty.UseNotifyTelegram; + + btnTestNotify.Enabled = DcConfig.Duty.EnableNotify; + + // + switch (DcConfig.Duty.ActiveFate) + { + case 0: rdoFatePreset1.Checked = true; break; + case 1: rdoFatePreset2.Checked = true; break; + case 2: rdoFatePreset3.Checked = true; break; + case 3: rdoFatePreset4.Checked = true; break; + } + UpdateFates(); + + // + _save_timer = new Timer() { Interval = 5000 }; + _save_timer.Tick += (sender, e) => + { + DcConfig.SaveConfig(); + _save_timer.Enabled = false; + }; + } + + public void PluginDeinitialize() + { + _overlay.Hide(); + _overlay = null; + } + + private void RefreshSaveFile(int interval = 5000) + { + _save_timer.Enabled = false; + _save_timer.Interval = interval; + _save_timer.Start(); + } + + public static List MakeDutyLangList() + { + List lst = new List(); + + DirectoryInfo di = new DirectoryInfo(DcConfig.DataPath); + + foreach (var fi in di.GetFiles("DcDuty-*.json")) + { + var s = fi.Name.Substring(7, fi.Name.Length - 7 - 5); + lst.Add(s); + } + + return lst; + } + + public void RefreshLocale() + { + + } + + public void UpdateUiLocale() + { + tabContent.TabPages[0].Text = MesgLog.Text(301); + tabContent.TabPages[1].Text = MesgLog.Text(302); + tabContent.TabPages[2].Text = MesgLog.Text(303); + + lblDataSet.Text = MesgLog.Text(304); + lblLogFont.Text = MesgLog.Text(305); + + chkEnableOverlay.Text = MesgLog.Text(306); + lblOverlayTransparent.Text = MesgLog.Text(307); + + chkEnableSound.Text = MesgLog.Text(308); + lblSoundInstance.Text = MesgLog.Text(309); + lblSoundFate.Text = MesgLog.Text(310); + + chkUseNotifyLine.Text = MesgLog.Text(311); + lblLineToken.Text = MesgLog.Text(312); + + chkUseNotifyTelegram.Text = MesgLog.Text(313); + lblTelegramId.Text = MesgLog.Text(314); + lblTelegramToken.Text = MesgLog.Text(315); + + lblPacketFinder.Text = MesgLog.Text(316); + lblPacketDesc.Text = MesgLog.Text(317); + lblPacketBozja.Text = MesgLog.Text(318); + + lstPacketInfo.Columns[0].Text = MesgLog.Text(319); + lstPacketInfo.Columns[1].Text = MesgLog.Text(320); + lstPacketInfo.Columns[2].Text = MesgLog.Text(321); + lstPacketInfo.Columns[3].Text = MesgLog.Text(322); + + lstBozjaInfo.Columns[0].Text = MesgLog.Text(323); + lstBozjaInfo.Columns[1].Text = MesgLog.Text(324); + lstBozjaInfo.Columns[2].Text = MesgLog.Text(325); + lstBozjaInfo.Columns[3].Text = MesgLog.Text(326); + + btnPacketStart.Text = MesgLog.Text(10007); + btnPacketApply.Text = MesgLog.Text(10009); + } + + public void PacketHandler(string pid, byte[] message) + { + if (_is_packet_finder) + PacketFinderHandler(message); + + var opcode = BitConverter.ToUInt16(message, 18); + + if (opcode != DcConfig.Packet.OpFate && + opcode != DcConfig.Packet.OpDuty && + opcode != DcConfig.Packet.OpMatch && + opcode != DcConfig.Packet.OpInstance && + opcode != DcConfig.Packet.OpSouthernBozja) + return; + + var data = message.Skip(32).ToArray(); + + // FATE + if (opcode == DcConfig.Packet.OpFate) + { + if (data[0] == 53) + { + var fcode = BitConverter.ToUInt16(data, 4); + + if (fcode > 100) + { + var fate = DcContent.GetFate(fcode); + if (_is_skirmish_area) + LogSkirmish(10001, fate.Name); + else + LogFate(10001, fate.Name); + + if (DcConfig.Duty.Fates[DcConfig.Duty.ActiveFate].Selected.Contains(fcode)) + { + MesgLog.L("{0} - {1}", DcConfig.Duty.ActiveFate, fcode); + PlayEffectSoundFate(); + NotifyFate(fate); + _overlay.PlayFate(fate); + } + } + } + } + + // Duty + else if (opcode == DcConfig.Packet.OpDuty) + { + var rcode = data[8]; + + if (rcode != 0) + { + var roulette = DcContent.GetRoulette(rcode); + LogRoulette(10002, roulette.Name); + _overlay.PlayQueue(roulette.Name); + } + else + { + var insts = new List(); + for (var i = 0; i < 5; i++) + { + var icode = BitConverter.ToUInt16(data, 12 + (i * 4)); + if (icode == 0) + break; + } + + if (insts.Any()) + { + LogInstance(10002, string.Join("/", insts.ToArray())); + _overlay.PlayQueue(MesgLog.Text(10006, $"#{insts.Count}")); + } + } + + DcContent.Missions.Clear(); + } + + // match + else if (opcode == DcConfig.Packet.OpMatch) + { + var rcode = BitConverter.ToUInt16(data, 2); + var icode = BitConverter.ToUInt16(data, 20); + string name; + + if (icode == 0 && rcode != 0) + { + var roulette = DcContent.GetRoulette(rcode); + LogRoulette(10003, roulette.Name); + name = roulette.Name; + } + else if (icode != 0) + { + var instance = DcContent.GetInstance(icode); + LogInstance(10003, instance.Name); + name = instance.Name; + } + else + { + // ??? + name = MesgLog.Text(10003, icode); + } + + PlayEffecSoundInstance(); + NotifyMatch(name); + _overlay.PlayMatch(name); + } + + // instance + else if (opcode == DcConfig.Packet.OpInstance && DcConfig.Packet.OpInstance != 0) + { + // 0[2] instance number + // 2[2] ? + // 4[1] 0=enter, 4=enter, 5=leave + + if (data[4] == 0) + { + var icode = BitConverter.ToUInt16(data, 0); + var instance = DcContent.GetInstance(icode); + LogInstance(10004, instance.Name); + _overlay.PlayMatch(MesgLog.Text(10004, instance.Name)); + + DcContent.Missions.Clear(); + } + else if (data[4] != 4) + { + _overlay.PlayNone(); + } + } + // southen bozja front critical engagement + else if (opcode == DcConfig.Packet.OpSouthernBozja) + { + // 0[4] timestamp + // 4[2] mmss + // 6[2] ? + // 8[1] code + // 9[1] ? + // 10[1] status 0=end, 1=register, 2=entry, 3=progress + // 12[1] progress percentage + + var ce = 30000 + data[8]; + var stat = data[10]; + + if (stat == 0 /* || data[10] == 3 */) + { + if (DcContent.Missions.ContainsKey(ce)) + DcContent.Missions.Remove(ce); + } + else if (stat == 1 || stat == 2) + { + if (!DcContent.Missions.ContainsKey(ce)) + { + DcContent.Missions.Add(ce, 0); + + var fate = DcContent.GetFate(ce); + LogCe(10001, fate.Name); + + if (DcConfig.Duty.Fates[DcConfig.Duty.ActiveFate].Selected.Contains(ce)) + { + PlayEffectSoundFate(); + NotifyFate(fate); + _overlay.PlayFate(fate); + } + } + } + else if (stat == 3) + { + if (DcContent.Missions.ContainsKey(ce)) + { + DcContent.Missions.Add(ce, 0); + + var fate = DcContent.GetFate(ce); + LogCe(10001, fate.Name); + } + } + } + } + + // + public void ZoneChanged(uint zone_id, string zone_name) + { + //_overlay.PlayNone(); + + _is_skirmish_area = + zone_id == 920; // The Bozjan Southern Front + } + + // + private void WriteLog(Color color, string category, string format, params object[] prms) + { + if (txtContentLog == null || txtContentLog.IsDisposed || format == null) + return; + + var fmt = string.Format(format, prms); + var dt = DateTime.Now.ToString("HH:mm:ss"); + var ms = $"[{dt}/{category}] {fmt}{Environment.NewLine}"; + + WorkerAct.Invoker(() => + { + txtContentLog.SelectionColor = color; + txtContentLog.SelectionStart = txtContentLog.TextLength; + txtContentLog.SelectionLength = 0; + txtContentLog.AppendText(ms); + + txtContentLog.SelectionColor = txtContentLog.ForeColor; + ThirdParty.NativeMethods.ScrollToBottom(txtContentLog); + }); + } + + private void WriteLog(Color color, int catkey, int fmtkey, params object[] prms) + { + string catergory = MesgLog.Text(catkey); + string format = MesgLog.Text(fmtkey); + WriteLog(color, catergory, format, prms); + } + + // + private void LogRoulette(int key, params object[] prms) + { + WriteLog(Color.Black, 21, key, prms); + } + + // + private void LogInstance(int key, params object[] prms) + { + WriteLog(Color.Black, 22, key, prms); + } + + // + private void LogFate(int key, params object[] prms) + { + WriteLog(Color.Black, 23, key, prms); + } + + // + private void LogSkirmish(int key, params object[] prms) + { + WriteLog(Color.Black, 24, key, prms); + } + + // + private void LogCe(int key, params object[] prms) + { + WriteLog(Color.Black, 25, key, prms); + } + + // + public void UpdateFates() + { + var fs = DcConfig.Duty.Fates[DcConfig.Duty.ActiveFate]; + + treeFates.Nodes.Clear(); + fs.MakeSelects(true); + + _is_lock_fate = true; + + foreach (var a in DcContent.Areas) + { + var n = treeFates.Nodes.Add(a.Value.Name); + n.Tag = a.Key + 100000; + + if (fs.Selected.Contains((int)n.Tag)) + { + n.Checked = true; + n.Expand(); + } + + foreach (var f in a.Value.Fates) + { + var name = f.Value.Name; + var node = n.Nodes.Add(name); + node.Tag = f.Key; + + if (fs.Selected.Contains((int)node.Tag)) + { + node.Checked = true; + + if (!n.IsExpanded) + n.Expand(); + } + } + } + + MakeFatesSelection(); + + _is_lock_fate = false; + } + + // + private void MakeFatesSelection(bool makeline = false) + { + var fs = DcConfig.Duty.Fates[DcConfig.Duty.ActiveFate]; + + fs.Selected.Clear(); + FateSelectionMakingLoop(treeFates.Nodes); + + if (makeline) + fs.MakeLine(); + } + + // + private void FateSelectionMakingLoop(TreeNodeCollection nodes) + { + var fs = DcConfig.Duty.Fates[DcConfig.Duty.ActiveFate]; + + foreach (TreeNode n in nodes) + { + if (n.Checked) + fs.Selected.Add((int)n.Tag); + FateSelectionMakingLoop(n.Nodes); + } + } + + private void CboDataset_SelectedIndexChanged(object sender, EventArgs e) + { + if (!DcConfig.PluginEnable) + return; + + var l = (string)cboDataset.SelectedItem; + + if (!string.IsNullOrWhiteSpace(l) && !l.Equals(DcConfig.Duty.Language) && DcContent.ReadContent(l)) + { + UpdateFates(); + + lblCurrentDataSet.Text = DcContent.Language; + + RefreshSaveFile(); + } + } + + private void BtnLogFont_Click(object sender, EventArgs e) + { + Font ret = (Font)WorkerAct.Invoker(new WorkerAct.ObjectReturnerDelegate(() => + { + FontDialog dg = new FontDialog + { + Font = txtContentLog.Font, + FontMustExist = true, + AllowVerticalFonts = false + }; + + return (dg.ShowDialog() == DialogResult.OK) ? dg.Font : null; + })); + + if (ret != null) + { + txtContentLog.Font = ret; + + DcConfig.Duty.LogFontFamily = ret.Name; + DcConfig.Duty.LogFontSize = ret.Size; + + RefreshSaveFile(); + + btnLogFont.Font = ret; + btnLogFont.Text = $"{DcConfig.Duty.LogFontFamily}, {DcConfig.Duty.LogFontSize}"; + } + } + + private void TreeFates_AfterCheck(object sender, TreeViewEventArgs e) + { + if (!DcConfig.PluginEnable) + return; + + if (_is_lock_fate) + return; + + _is_lock_fate = true; + + if (((int)e.Node.Tag) > 100000) + { + foreach (TreeNode n in e.Node.Nodes) + n.Checked = e.Node.Checked; + } + else + { + if (!e.Node.Checked) + e.Node.Parent.Checked = false; + else + { + var f = true; + foreach (TreeNode n in e.Node.Parent.Nodes) + f &= n.Checked; + e.Node.Parent.Checked = f; + } + } + + MakeFatesSelection(true); + RefreshSaveFile(); + + _is_lock_fate = false; + } + + // + private void ChangeFatePreset(int index) + { + if (!DcConfig.PluginEnable) + return; + + if (index >= 0 && index < 4) + { + DcConfig.Duty.ActiveFate = index; + UpdateFates(); + + RefreshSaveFile(); + } + } + + private void RdoFatePreset1_CheckedChanged(object sender, EventArgs e) + { + ChangeFatePreset(0); + } + + private void RdoFatePreset2_CheckedChanged(object sender, EventArgs e) + { + ChangeFatePreset(1); + } + + private void RdoFatePreset3_CheckedChanged(object sender, EventArgs e) + { + ChangeFatePreset(2); + } + + private void RdoFatePreset4_CheckedChanged(object sender, EventArgs e) + { + ChangeFatePreset(3); + } + + private void ChkEnableOverlay_CheckedChanged(object sender, EventArgs e) + { + if (!DcConfig.PluginEnable) + return; + + progbOverlayTransparent.Enabled = chkEnableOverlay.Checked; + btnOverlayDimming.Enabled = chkEnableOverlay.Checked; + + if (chkEnableOverlay.Checked) + _overlay.Show(); + else + _overlay.Hide(); + + DcConfig.Duty.EnableOverlay = chkEnableOverlay.Checked; + + RefreshSaveFile(); + } + + private void ProgbOverlayTransparent_Click(object sender, EventArgs e) + { + + } + + private void BtnOverlayDimming_Click(object sender, EventArgs e) + { + _overlay.StartBlink(); + } + + private void ChkEnableSound_CheckedChanged(object sender, EventArgs e) + { + if (!DcConfig.PluginEnable) + return; + + txtSoundInstance.Enabled = chkEnableSound.Checked; + btnSoundFindInstance.Enabled = chkEnableSound.Checked; + btnSoundPlayInstance.Enabled = chkEnableSound.Checked; + txtSoundFate.Enabled = chkEnableSound.Checked; + btnSoundFindFate.Enabled = chkEnableSound.Checked; + btnSoundPlayFate.Enabled = chkEnableSound.Checked; + + DcConfig.Duty.EnableSound = chkEnableSound.Checked; + + RefreshSaveFile(); + } + + // + private void PlayEffectSoundFate() + { + if (DcConfig.Duty.EnableSound) + WorkerAct.PlayEffectSound(DcConfig.Duty.SoundFateFile, DcConfig.Duty.SoundFateVolume); + } + + // + private void PlayEffecSoundInstance() + { + if (DcConfig.Duty.EnableSound) + WorkerAct.PlayEffectSound(DcConfig.Duty.SoundInstanceFile, DcConfig.Duty.SoundInstanceVolume); + } + + private void BtnSoundPlayInstance_Click(object sender, EventArgs e) + { + if (!DcConfig.PluginEnable) + return; + + PlayEffecSoundInstance(); + } + + private void BtnSoundPlayFate_Click(object sender, EventArgs e) + { + if (!DcConfig.PluginEnable) + return; + + PlayEffectSoundFate(); + } + + // + private string SoundFileOpenDialog() + { + string filename = (string)WorkerAct.Invoker(new WorkerAct.ObjectReturnerDelegate(() => + { + var dg = new OpenFileDialog + { + Title = MesgLog.Text(101), + DefaultExt = "wav", + Filter = MesgLog.Text(102) + }; + + return (dg.ShowDialog() == DialogResult.OK) ? dg.FileName : null; + })); + + return filename; + } + + private void BtnSoundFindInstance_Click(object sender, EventArgs e) + { + if (!DcConfig.PluginEnable) + return; + + string filename = SoundFileOpenDialog(); + + DcConfig.Duty.SoundInstanceFile = string.IsNullOrEmpty(filename) ? string.Empty : filename; + txtSoundInstance.Text = DcConfig.Duty.SoundInstanceFile; + + RefreshSaveFile(); + } + + private void BtnSoundFindFate_Click(object sender, EventArgs e) + { + if (!DcConfig.PluginEnable) + return; + + string filename = SoundFileOpenDialog(); + + DcConfig.Duty.SoundFateFile = string.IsNullOrEmpty(filename) ? string.Empty : filename; + txtSoundFate.Text = DcConfig.Duty.SoundFateFile; + + RefreshSaveFile(); + } + + private async void BtnTestNotify_Click(object sender, EventArgs e) + { + if (!DcConfig.PluginEnable) + return; + + string s = MesgLog.Text(103); + + if (DcConfig.Duty.UseNotifyLine) + await NotifyUsingLine(s); + + if (DcConfig.Duty.UseNotifyTelegram) + NotifyUsingTelegram(s); + } + + // + private void SendNotify(string s) + { + if (DcConfig.Duty.UseNotifyLine) + NotifyUsingLine(s).Wait(); + + if (DcConfig.Duty.UseNotifyTelegram) + NotifyUsingTelegram(s); + } + + // + private void NotifyFate(DcContent.Fate f) + { + if (!DcConfig.Duty.EnableNotify) + return; + + string s = MesgLog.Text(10005, f.Name); + SendNotify(s); + } + + // + private void NotifyMatch(string name) + { + if (!DcConfig.Duty.EnableNotify) + return; + + string s = MesgLog.Text(10003, name); + SendNotify(s); + } + + private void ChkUseNotifyLine_CheckedChanged(object sender, EventArgs e) + { + if (!DcConfig.PluginEnable) + return; + + DcConfig.Duty.UseNotifyLine = chkUseNotifyLine.Checked; + txtLineToken.Enabled = chkUseNotifyLine.Checked; + + btnTestNotify.Enabled = DcConfig.Duty.EnableNotify; + + RefreshSaveFile(); + } + + private void LblLineNotifyBotLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + if (!DcConfig.PluginEnable) + return; + + Process.Start(lblLineNotifyBotLink.Text); + } + + private void TxtLineToken_KeyDown(object sender, KeyEventArgs e) + { + if (!DcConfig.PluginEnable) + return; + + if (e.KeyCode == Keys.Enter) + { + DcConfig.Duty.NotifyLineToken = txtLineToken.Text; + RefreshSaveFile(); + } + } + + // + internal async Task NotifyUsingLine(string mesg) + { + if (txtLineToken.TextLength == 0) + return; + + if (!txtLineToken.Text.Equals(DcConfig.Duty.NotifyLineToken)) + { + DcConfig.Duty.NotifyLineToken = txtLineToken.Text; + RefreshSaveFile(); + } + + var hc = new HttpClient(); + hc.DefaultRequestHeaders.Add("Authorization", $"Bearer {DcConfig.Duty.NotifyLineToken}"); + + var param = new Dictionary + { + { "message", mesg } + }; + + await hc.PostAsync("https://notify-api.line.me/api/notify", + new FormUrlEncodedContent(param)).ConfigureAwait(false); + } + + // + private void ChkUseNotifyTelegram_CheckedChanged(object sender, EventArgs e) + { + if (!DcConfig.PluginEnable) + return; + + DcConfig.Duty.UseNotifyTelegram = chkUseNotifyTelegram.Checked; + txtTelegramId.Enabled = chkUseNotifyTelegram.Checked; + txtTelegramToken.Enabled = chkUseNotifyTelegram.Checked; + + btnTestNotify.Enabled = DcConfig.Duty.EnableNotify; + + RefreshSaveFile(); + } + + private void TxtTelegramId_KeyDown(object sender, KeyEventArgs e) + { + if (!DcConfig.PluginEnable) + return; + + if (e.KeyCode == Keys.Enter) + { + DcConfig.Duty.NotifyTelegramId = txtTelegramId.Text; + RefreshSaveFile(); + } + } + + private void TxtTelegramToken_KeyDown(object sender, KeyEventArgs e) + { + if (!DcConfig.PluginEnable) + return; + + if (e.KeyCode == Keys.Enter) + { + DcConfig.Duty.NotifyTelegramToken = txtTelegramToken.Text; + RefreshSaveFile(); + } + } + + // + private static string EncodeJsonChars(string text) + { + return text.Replace("\b", "\\\b") + .Replace("\f", "\\\f") + .Replace("\n", "\\\n") + .Replace("\r", "\\\r") + .Replace("\t", "\\\t") + .Replace("\"", "\\\"") + .Replace("\\", "\\\\"); + } + + // + private bool NotifyUsingTelegram(string mesg) + { + if (txtTelegramId.TextLength == 0 || txtTelegramToken.TextLength == 0) + return false; + + if (!txtTelegramId.Text.Equals(DcConfig.Duty.NotifyTelegramId)) + { + DcConfig.Duty.NotifyTelegramId = txtTelegramId.Text; + RefreshSaveFile(); + } + + if (!txtTelegramToken.Text.Equals(DcConfig.Duty.NotifyTelegramToken)) + { + DcConfig.Duty.NotifyTelegramToken = txtTelegramToken.Text; + RefreshSaveFile(); + } + + // https://codingman.tistory.com/41 + + var json = string.Format("{{\"chat_id\":\"{0}\", \"text\":\"{1}\"}}", + DcConfig.Duty.NotifyTelegramId, EncodeJsonChars(mesg)); + var jbin = Encoding.UTF8.GetBytes(json); + + var url = string.Format("https://api.telegram.org/bot{0}/sendMessage", DcConfig.Duty.NotifyTelegramToken); + HttpWebRequest req = WebRequest.Create(new Uri(url)) as HttpWebRequest; + req.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.NoCacheNoStore); + req.Timeout = 30 * 1000; + req.Method = "POST"; + req.ContentType = "application/json"; + + using (var st = req.GetRequestStream()) + { + st.Write(jbin, 0, jbin.Length); + st.Flush(); + } + + HttpWebResponse res = null; + try + { + res = req.GetResponse() as HttpWebResponse; + if (res.StatusCode == HttpStatusCode.OK) + { + string ss = null; + using (var st = res.GetResponseStream()) + { + using (var rdr = new StreamReader(st, Encoding.UTF8)) + ss = rdr.ReadToEnd(); + } + + if (0 < ss.IndexOf("\"ok\":true")) + return true; + else + return false; + } + else + { + // http status is not ok + return false; + } + } + catch + { + // ??? + return false; + } + finally + { + if (res != null) + res.Close(); + } + } + + // + private void PacketFinderResetUi(bool is_enable) + { + if (!is_enable) + { + btnPacketStart.Text = MesgLog.Text(10007); + btnPacketStart.BackColor = Color.Transparent; + } + else + { + btnPacketStart.Text = MesgLog.Text(10008); + btnPacketStart.BackColor = Color.Salmon; + } + + btnPacketApply.Visible = is_enable; + btnPacketApply.Enabled = is_enable; + lstPacketInfo.Enabled = is_enable; + txtPacketInfo.Enabled = is_enable; + txtPacketDescription.Enabled = is_enable; + lstBozjaInfo.Enabled = is_enable; + } + + // + private void PacketFindClearUi(DcConfig.PacketConfig newpk) + { + // + txtPacketDescription.Text = DcConfig.Packet.Version; + lstBozjaInfo.Items.Clear(); + + // FATE + lstPacketInfo.Items[0].SubItems[1].Text = DcConfig.Packet.OpFate.ToString(); + lstPacketInfo.Items[0].SubItems[2].Text = ""; + lstPacketInfo.Items[0].SubItems[3].Text = newpk.OpFate.ToString(); + + // Duty + lstPacketInfo.Items[1].SubItems[1].Text = DcConfig.Packet.OpDuty.ToString(); + lstPacketInfo.Items[1].SubItems[2].Text = ""; + lstPacketInfo.Items[1].SubItems[3].Text = newpk.OpDuty.ToString(); + + // Match + lstPacketInfo.Items[2].SubItems[1].Text = DcConfig.Packet.OpMatch.ToString(); + lstPacketInfo.Items[2].SubItems[2].Text = ""; + lstPacketInfo.Items[2].SubItems[3].Text = newpk.OpMatch.ToString(); + + // Instance + lstPacketInfo.Items[3].SubItems[1].Text = DcConfig.Packet.OpInstance.ToString(); + lstPacketInfo.Items[3].SubItems[2].Text = ""; + lstPacketInfo.Items[3].SubItems[3].Text = newpk.OpInstance.ToString(); + + // Bozja + lstPacketInfo.Items[4].SubItems[1].Text = DcConfig.Packet.OpSouthernBozja.ToString(); + lstPacketInfo.Items[4].SubItems[2].Text = ""; + lstPacketInfo.Items[4].SubItems[3].Text = newpk.OpSouthernBozja.ToString(); + } + + private void BtnPacketStart_Click(object sender, EventArgs e) + { + if (!_is_packet_finder) + { + _new_packet = new DcConfig.PacketConfig() + { + Version = DcConfig.Packet.Version, + OpFate = 0, + OpDuty = 0, + OpMatch = 0, + OpInstance = 0, + OpSouthernBozja = 0, + }; + + PacketFindClearUi(_new_packet); + } + + _is_packet_finder = !_is_packet_finder; + PacketFinderResetUi(_is_packet_finder); + } + + private void BtnPacketApply_Click(object sender, EventArgs e) + { + var ret = (DialogResult)WorkerAct.Invoker(new WorkerAct.ObjectReturnerDelegate(() => + { + var r = MessageBox.Show(MesgLog.Text(10022), MesgLog.Text(0), MessageBoxButtons.YesNo, MessageBoxIcon.Question); + return r; + })); + + if (ret == DialogResult.Yes) + { + _new_packet.Version = txtPacketDescription.Text; + + DcConfig.Packet.Version = _new_packet.Version; + DcConfig.Packet.OpFate = _new_packet.OpFate; + DcConfig.Packet.OpDuty = _new_packet.OpDuty; + DcConfig.Packet.OpMatch = _new_packet.OpMatch; + DcConfig.Packet.OpInstance = _new_packet.OpInstance; + DcConfig.Packet.OpSouthernBozja = _new_packet.OpSouthernBozja; + DcConfig.Packet.Save(); + + _is_packet_finder = false; + PacketFinderResetUi(false); + } + } + + private void LstPacketInfo_SelectedIndexChanged(object sender, EventArgs e) + { + if (lstPacketInfo.SelectedIndices.Count != 1) + return; + + int m; + + switch (lstPacketInfo.SelectedIndices[0]) + { + case 0: m = 10010; break; + case 1: m = 10011; break; + case 2: m = 10011; break; + case 3: m = 10011; break; + case 4: m = 10014; break; + default: m = 10015; break; + } + + txtPacketInfo.Text = MesgLog.Text(m); + } + + private void LstBozjaInfo_MouseDoubleClick(object sender, MouseEventArgs e) + { + + } + + private void LstBozjaInfo_SelectedIndexChanged(object sender, EventArgs e) + { + if (lstBozjaInfo.SelectedItems.Count != 1) + return; + + ushort opcode = (ushort)lstBozjaInfo.SelectedItems[0].Tag; + + _new_packet.OpSouthernBozja = opcode; + + lstPacketInfo.Items[4].SubItems[2].Text = MesgLog.Text(10023); + lstPacketInfo.Items[4].SubItems[3].Text = _new_packet.OpSouthernBozja.ToString(); + } + + private static readonly short[] _packet_target_fates = + { + // moddle la noscea + 553, 649, 687, 688, 693, 717, + 220, 221, 222, 223, 225, 226, 227, 229, 231, 233, 235, 237, 238, 239, 240, + 1387, + + // southern bozja front + 1597, 1598, 1599, + 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, + 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, 1619, + 1620, 1621, 1622, 1623, 1624, 1625, 1626, 1627, 1628 + }; + + // + private void PacketFinderHandler(byte[] message) + { + var opcode = BitConverter.ToUInt16(message, 18); + var data = message.Skip(32).ToArray(); + + // fate + if (data.Length > 4 && data[0] == 0x3E) + { + var cc = BitConverter.ToInt16(data, 4); + if (_packet_target_fates.Contains(cc)) + { + _new_packet.OpFate = opcode; + + WorkerAct.Invoker(() => + { + lstPacketInfo.Items[0].SubItems[2].Text = MesgLog.Text(10016); + lstPacketInfo.Items[0].SubItems[3].Text = _new_packet.OpFate.ToString(); + }); + + return; + } + } + + // duty + if (data.Length > 12) + { + var rcode = data[8]; + if (rcode == 0) + { + // The Steps of Fath (83) + short m = BitConverter.ToInt16(data, 12); + if (m == 83) + { + _new_packet.OpDuty = opcode; + + WorkerAct.Invoker(() => + { + lstPacketInfo.Items[1].SubItems[2].Text = MesgLog.Text(10016); + lstPacketInfo.Items[1].SubItems[3].Text = _new_packet.OpDuty.ToString(); + }); + + return; + } + } + } + + // match + if (data.Length > 20) + { + var rcode = data[2]; + if (rcode == 0) + { + // The Steps of Fath (83) + short m = BitConverter.ToInt16(data, 20); + if (m == 83) + { + _new_packet.OpMatch = opcode; + + WorkerAct.Invoker(() => + { + lstPacketInfo.Items[2].SubItems[2].Text = MesgLog.Text(10016); + lstPacketInfo.Items[2].SubItems[3].Text = _new_packet.OpMatch.ToString(); + }); + + return; + } + } + } + + // instance + if (data.Length >= 16) + { + // The Steps of Fath (83) + short m = BitConverter.ToInt16(data, 0); + short u = BitConverter.ToInt16(data, 2); + if (m == 83 && u == 0) + { + _new_packet.OpInstance = opcode; + + WorkerAct.Invoker(() => + { + lstPacketInfo.Items[3].SubItems[2].Text = MesgLog.Text(10016); + lstPacketInfo.Items[3].SubItems[3].Text = _new_packet.OpInstance.ToString(); + }); + + return; + } + } + + // critical engagement + if (data.Length >= 12) + { + // 0[4] timestamp + // 4[2] mmss + // 6[2] ? + // 8[1] code + // 9[1] members + // 10[1] status 0=end, 1=register, 2=entry, 3=progress + // 12[1] progress percentage + + var code = data[8]; + + if (code < 0 || code > 15) + { + // not ce + return; + } + + var stat = data[10]; + var prg = data[12]; + var mem = data[9]; + var ok = false; + + /* + if (stat == 0) + { + // end. other conditions unknown + ok = true; + } + else*/ + if (stat == 1) + { + // register. progress must be 0 + if (mem >= 0 && mem <= 48 && prg == 0) + ok = true; + } + else if (stat == 2) + { + // entry. progress must be 0 + if (mem >= 0 && mem <= 48 && prg == 0) + ok = true; + } + else if (stat == 3) + { + // progress. progress must be in 1~99 + if (mem > 0 && mem <= 48 && prg >= 1 && prg < 100) + ok = true; + } + + if (ok) + { + var ce = DcContent.GetFate(code + 30000); + + var li = new ListViewItem(new string[] + { + ce.Name, + DcContent.CeStatusToString(stat), + mem.ToString(), + prg.ToString() + }) + { + Tag = opcode + }; + + WorkerAct.Invoker(() => + { + lstBozjaInfo.Items.Add(li); + lstBozjaInfo.EnsureVisible(lstBozjaInfo.Items.Count - 1); + }); + } + } + } + } +} diff --git a/Tab/DutyForm.resx b/Tab/DutyForm.resx new file mode 100644 index 0000000..c666ff9 --- /dev/null +++ b/Tab/DutyForm.resx @@ -0,0 +1,408 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 + ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAAA + QQAAAk1TRnQBSQFMAgEBAwEAAdABAAHQAQABIAEAASABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAGA + AwABIAMAAQEBAAEgBgABQBoAAzYEWQHEA1UB6gMdAf8DHQH/Ax0B/wMdAf8DHQH/Ax0B/wMdAf8DHQH/ + Ax0B/wMdAf8DHQH/Ax0B/wMdAf8DHQH/Ax0B/wMdAf8DHQH/Ax0B/wMdAf8DHQH/Ax0B/wMdAf8DXQHi + A1QBrgMpAT8IAAMHAQoDSAGFAh0BqgH/AhgBqgH/AhcBpAH/AhcBpAH/AhcBpAH/AhcBpAH/AhcBpAH/ + AhcBpAH/AhcBowH/AhcBogH/AhcBogH/AhcBogH/AhcBogH/AhcBogH/AhcBogH/AhcBogH/AhcBogH/ + AhcBogH/AhcBogH/AhcBowH/AhcBpAH/AhcBpAH/AhcBpAH/AhcBpAH/AhcBpAH/AhcBpAH/AhgBqgH/ + Ah0BqgH/A0gBhQMHAQr/AAUAA04BlwM+Af8DsgH/A80B/wPdAf8D3QH/A90B/wPdAf8D3QH/A90B/wPd + Af8D3QH/A90B/wPdAf8D3QH/A90B/wPdAf8D3QH/A90B/wPdAf8D3QH/A90B/wPdAf8D3QH/A90B/wPd + Af8DyAH/A6IB/wMvAf8DRgGBBAADSAGFAhcBpAH/AhcBogH/AhcBoQH/AhcBoQH/AhcBoQH/AhcBoQH/ + AhcBoQH/AhQBoAH/AhQBngH/AhQBmwH/AhQBmQH/AhQBmQH/AhQBlwH/AhQBlQH/AhQBlQH/AhQBlQH/ + AhQBlQH/AhQBlwH/AhQBmQH/AhQBmQH/AhQBmwH/AhQBngH/AhQBoAH/AhcBoQH/AhcBoQH/AhcBoQH/ + AhcBoQH/AhcBoQH/AhcBogH/AhcBpAH/A0gBhVcAAQEDAgQDBAQBBgMEAQYDAwEEAwEBAgMAAQGMAAM3 + AVoDSgH/A9sB/wOLAf8DNAH/Ax0B/wMdAf8DHQH/Ax0B/wMdAf8DHQH/Ax0B/wMdAf8DHQH/Ax0B/wMd + Af8DHQH/Ax0B/wMdAf8DHQH/Ax0B/wMdAf8DHQH/Ax0B/wMdAf8DHQH/Ax0B/wM0Af8DhwH/A80B/wM2 + Af8DKwFCAhcBpAH/AhcBogH/AhQBnQH/AhIBmAH/AhIBlwH/AhIBlwH/AhIBlwH/AhIBlwH/Ag8BkQH/ + Ag8BjwH/Ag8BjAH/Ag8BigH/Ag8BigH/Ag0BiAH/AgoBhgH/AgoBhgH/AgoBhgH/AgwBhgH/Ag8BiAH/ + Ag8BigH/Ag8BigH/Ag8BjAH/Ag8BjwH/Ag8BlQH/AhIBlwH/AhIBlwH/AhIBlwH/AhIBlwH/AhIBmAH/ + AhQBnQH/AhcBogH/AhcBpAH/UAADAgEDAwYBCAMNARIDGgEkAyMBMwMhATADFgEeAwoBDgMEAQYDAAEB + iAADWQHDA7IB/wOKAf8BWgFIAS4B/wG5AZMBQAH/Ac4BogFGAf8BzgGiAUYB/wHOAaIBRgH/Ac4BogFG + Af8BzgGiAUYB/wHOAaIBRgH/Ac4BogFGAf8BzgGiAUYB/wHOAaIBRgH/Ac4BogFGAf8BvQGVAT4B/wGj + AYABMgH/Ab0BlQE+Af8BzgGiAUYB/wHOAaIBRgH/Ac4BogFGAf8BzgGiAUYB/wHOAaIBRgH/Ac4BogFG + Af8BzgGiAUYB/wHOAaIBRgH/Ac4BogFGAf8BuQGTAUAB/wFlAVABMQH/A4UB/wOjAf8DVAGrAhcBowH/ + AhQBmgH/AhABkQH/AgkBjQH/AggBjQH/AggBigH/AggBhgH/AggBgQH/AggBZAH/AggBYgH/AggBXQH/ + AggBXAH/AggBXAH/AgcBXAH/AgYBWAH/AgYBVQH/AgYBVQH/AgcBWAH/AggBXAH/AggBXAH/AggBXAH/ + AggBXQH/AggBYgH/AggBgAH/AggBhgH/AggBhgH/AggBigH/AggBjQH/AgkBjQH/AhABkQH/AhQBmgH/ + AhcBowH/TAADAgEDAwcBCgMXASADMAFMAUUCRgF+AU8CUQGcAU0CTgGWA0EBcgMqAUEDEgEZAwUBBwMA + AQGEAANBAfkDygH/AzIB/wG5AY8BPwH/AdUBogFHAf8B1QGiAUcB/wHVAaIBRwH/AdUBogFHAf8B1QGi + AUcB/wHVAaIBRwH/AdUBogFHAf8B1QGiAUcB/wHVAaIBRwH/AdUBogFHAf8BxAGVAT8B/wGJAVEBKwH/ + ASYBNQE7Af8BlAFWASoB/wHTAaEBRgH/AdUBogFHAf8B1QGiAUcB/wHVAaIBRwH/AdUBogFHAf8B1QGi + AUcB/wHVAaIBRwH/AdUBogFHAf8B1QGiAUcB/wHVAaIBRwH/AcABkwFBAf8DKwH/A8UB/wNOAfACFQGZ + Af8CCwGLAf8CBgFiAf8CBgFeAf8CBgFWAf8CBgFWAf8CBgFRAf8CBgFOAf8CBgFNAf8CBgFKAf8CBgFG + Af8CBgFGAf8CBgFFAf8CBgFCAf8CBgE+Af8CBgE+Af8CBgE+Af8CBgE+Af8CBgFCAf8CBgFFAf8CBgFG + Af8CBgFGAf8CBgFKAf8CBgFNAf8CBgFQAf8CBgFWAf8CBgFWAf8CBgFWAf8CBgFeAf8CBgFiAf8CCwGL + Af8CFQGZAf9IAAMBAQIDBwEJAxgBIgM4AV4BUwJVAa0BXQJhAeIBbQF/AYIB9wJlAWYB9AFeAmEB2gNQ + AZoDLQFGAw4BEwMDAQSEAAMdAf8DwgH/Ax8B/wHMAZUBRAH/AdUBmwFGAf8B1QGbAUYB/wHVAZsBRgH/ + AdUBmwFGAf8B1QGbAUYB/wHVAZsBRgH/AdUBmwFGAf8B1QGbAUYB/wHVAZsBRgH/Ab8BiwE8Af8BkwFR + ASkB/wElATMBPAH/AQABOwGOAf8BVAFBAS0B/wGVAVIBKQH/Ac8BlwFDAf8B1QGbAUYB/wHVAZsBRgH/ + AdUBmwFGAf8B1QGbAUYB/wHVAZsBRgH/AdUBmwFGAf8B1QGbAUYB/wHVAZsBRgH/AcUBkAFCAf8DJQH/ + A8IB/wMdAf8CEwGRAf8BDQESAYIB/wENASkBhAH/ARMBMgGFAf8BEwEyAYAB/wETATQBgwH/ARMBNAGD + Af8BEwE0AYMB/wETATQBZAH/ARMBNAFkAf8BEwE0AWQB/wETATQBZAH/ARMBNAFfAf8BEwExAVwB/wET + ATEBXAH/ARMBMQFcAf8BEwExAVwB/wETATEBXAH/ARMBMQFcAf8BEwExAVwB/wETATEBYQH/ARMBMQFh + Af8BEwExAWEB/wETATEBYQH/ARMBMgGDAf8BEwE0AYMB/wETATQBgwH/ARMBNAGDAf8BEwE0AYgB/wEP + ASkBhwH/AQ0BEgGDAf8CEwGRAf9HAAEBAwYBCAMWAR4DOAFdA1UBtQNkAfEB8wH4AfwB/wHtA/8B8wP/ + AagBuAHCAf4DXwHgA0gBhQMfASwDBQEHhAADHQH/A7QB/wMdAf8BzgGQAUMB/wHVAZQBRQH/AdUBlAFF + Af8B1QGUAUUB/wHVAZQBRQH/AdUBlAFFAf8B1QGUAUUB/wHUAZMBRQH/AdABkQFDAf8BtAFjATYB/wGK + AUkBKQH/ARsBMQFBAf8BAAEfAV4B/wEAAR8BWQH/AQABJgFfAf8BPgE3ATEB/wGSAUwBKAH/AbkBgAE4 + Af8B0gGSAUQB/wHVAZQBRQH/AdUBlAFFAf8B1QGUAUUB/wHVAZQBRQH/AdUBlAFFAf8B1QGUAUUB/wHF + AYsBQQH/AyQB/wO0Af8DHQH/Ag4BigH/ARIBKwGHAf8BJAGFAakB/wE7AasB1AH/AVQB0QHeAf8BWQHU + AeEB/wFcAdQB4QH/AV4B1AHhAf8BXgHUAeEB/wFcAdQB4QH/AVkB1AHhAf8BWQHUAeEB/wFZAdMB4AH/ + AVkB0QHeAf8BWQHRAd4B/wFZAdEB3gH/AVkB0QHeAf8BWQHRAd4B/wFZAdEB3gH/AVkB0QHeAf8BWQHR + Ad4B/wFZAdEB3gH/AVkB0QHeAf8BWQHRAd4B/wFZAdEB4QH/AVkB1AHhAf8BWQHUAeEB/wFUAdQB4QH/ + ATwBsgHYAf8BJgGFAa8B/wESASsBiwH/Ag4BigH/QwABAQMFAQcDFAEbAzUBVgNUAa8BWgJdAfAB8wH4 + AfwB/wHUA/8BxAH8Av8BxgH+Av8B6AP/AYcBjwGTAfsBVQJWAbEDLQFFAwcBCoQAAx0B/wOnAf8DHQH/ + Ac4BhwFCAf8B1QGLAUQB/wHVAYsBRAH/AcsBhAFAAf8BvQFhATkB/wHEAYABPQH/AcABYwE7Af8BlQFH + ASgB/wGNAUQBKQH/AUIBNQExAf8BAAEpAVYB/wEAAQ4BTAH/ASQBkQGyAf8BWQHVAeYB/wEBAUIBiQH/ + AQABFAFSAf8BBwEtAU0B/wFYATsBLAH/AZIBRgEoAf8BsQFaATQB/wHDAYABPAH/AcMBgAE8Af8BugFg + ATgB/wHTAYoBQwH/AdUBiwFEAf8BxQGCAUAB/wMkAf8DpwH/Ax0B/wINAYEB/wEWATcBkAH/ATcBoQHC + Af8BKAFhAaQB/wEcATMBYgH/AR0BMwGEAf8BHgEzAYgB/wEfATMBiAH/AR8BMwGBAf8BHgEzAYEB/wEd + ATMBgQH/AR0BMwFiAf8BHQEzAWEB/wEdATMBYQH/AR0BMwFhAf8BHQEzAWEB/wEdATMBYQH/AR0BMwFh + Af8BHQEzAWEB/wEdATMBYQH/AR0BMwGBAf8BHQEzAYEB/wEdATMBgQH/AR0BMwGBAf8BHwE0AYgB/wEi + ATcBiAH/AR0BMwGEAf8BHAEzAWIB/wEoAWMBpAH/ATcBoQHDAf8BFgE3AZEB/wINAYEB/z8AAQEDBAEG + AxIBGAMyAVADUgGpAVkCZAHsAagBuAHCAf4B2QP/AcQB/AL/AcMB+wL/AcMB+wL/AdcD/wGrAbIBtgH9 + AVcCWQG/AzIBUAMIAQuEAAMdAf8DmwH/Ax0B/wHOAWUBQAH/AdUBgwFCAf8BywFjAT4B/wGDATwBKQH/ + AU4BNAEsAf8BXAE3ASoB/wFUATUBKwH/ASUBMgE9Af8BAAEsAVoB/wEAARQBVgH/AQABMQFgAf8BUwHQ + AecB/wFeAd0B8QH/AUMBpwGxAf8BZAHhAfcB/wE6AakBxQH/AQABFQFMAf8BAAEgAV0B/wEAAS8BUgH/ + ATYBMgE0Af8BWgE2ASoB/wFbATYBKgH/AUkBNAEwAf8BlAFBASYB/wHTAYIBQQH/AcUBYQE+Af8DIwH/ + A5sB/wMdAf8CDQFkAf8BFwE4AYsB/wEwAZwBvQH/AQ4BHwFPAf8BCQESAVsB/wETATkBmAH/ARIBPAGd + Af8BEgE6AZ0B/wESATkBnAH/ARIBOQGWAf8BEQE4AZUB/wEUATYBkQH/AQYBEAFbAf8CCAFSAf8CCAFS + Af8CCAFSAf8CCAFSAf8CCAFSAf8BBwEOAVkB/wETATIBkgH/ARIBNAGUAf8BDAEqAY0B/wEWAUABmAH/ + AQgBIwGOAf8BFgFAAZ8B/wESATABkwH/AQ4BEwFbAf8CCAFMAf8BDgEdAU0B/wEwAZcBtAH/ARcBNwGI + Af8CDQFkAf87AAEBAwQBBgMQARUDLAFDAU8CUAGbAVgCYgHpAagBuAHCAf4B3gP/AcYB/gL/AcMB+wL/ + AcMB+wL/AcgD/wHsA/8BhwGQAZMB+wFVAlYBsQMtAUUDBwEKhAADHQH/A5MB/wMdAf8BzAFdAT4B/wHT + AWABQAH/Ac4BXQE+Af8BigE5ASYB/wEGAUEBhAH/AQABOQGNAf8BAAExAYgB/wEAAScBgQH/ARUBXAGf + Af8BVwHVAeYB/wGQAe8B/gH/AToBmwG8Af8BRgEcATMB/wGRARgBMQH/ATUBMgFKAf8BUQHKAeYB/wGQ + Ae0B+gH/AUEBtAHKAf8BAQFCAZIB/wEAASkBgQH/AQABMgGHAf8BAAFDAZYB/wEjATMBRgH/AZMBOwEl + Af8B0gFgAUAB/wHDAVkBPAH/AyIB/wOTAf8DHQH/Ag0BZAH/ARcBOQGLAf8BMAGdAb0B/wEOAR8BVgH/ + AREBOAGVAf8BTQHWAekB/wFOAdcB8AH/AU0B0gHwAf8BTQHRAfAB/wFNAdEB7gH/AUoBzQHrAf8BRwHF + AecB/wEIARwBigH/Ag8BXAH/Ag8BXAH/Ag8BXAH/Ag8BXAH/AQ4BEAFdAf8BBgEeAYwB/wFIAcEB4gH/ + AUIBxAHoAf8BIAGKAc8B/wFWAeEB9QH/AQ0BVgHDAf8BWAHhAfUB/wEzAaIB1QH/AQgBHQGSAf8BBwEM + AVgB/wEOAR0BVQH/AS4BlAG0Af8BFwE0AYgB/wINAWQB/zgAAwQBBQMNARIDKAE8A0oBigFeAmEB2gGo + Aa8BtQH9AeID/wHGAf4C/wHDAfsC/wHDAfsC/wHJA/8B6QP/AagBrwG1Af0BXAJhAdwDRwGCAx0BKgMF + AQeEAAMdAf8DjwH/Ax0B/wHJAVoBPQH/AdABXQE/Af8B0AFdAT8B/wGmAUUBLQH/ASsBLwE9Af8BEQFb + AaMB/wFDAasB0gH/AZIB6wH4Af8BiQHqAfcB/wFCAaIBvAH/AUIBLwFIAf8BmgEjAUkB/wG/ATYBiwH/ + AcEBOwGTAf8BuwE0AYIB/wGCARwBOwH/AToBSwFlAf8BUQHDAdsB/wGTAfAB/AH/AYYB4QHzAf8BMAGR + AbkB/wEKAVYBnwH/AVgBMAEoAf8BvAFSATcB/wHQAV0BPwH/AcABVgE7Af8DIgH/A48B/wMdAf8CDQFk + Af8BFwE5AYsB/wEwAZ0BvQH/AQ4BHwFaAf8BDgE6AZ8B/wFUAeIB9QH/AVsB7AL/AWAB7gL/AWEB7gL/ + AWEB7gL/AWEB7gL/AUABwAHrAf8BCAEcAY8B/wIPAWEB/wIPAV4B/wIPAVwB/wIPAV0B/wELARQBggH/ + ASIBYAG+Af8BUgHaAfgB/wEiAZgB3wH/AUEBxAHxAf8BNQG2AeoB/wEtAawB5QH/AU0B1gH5Af8BJwGf + AeEB/wEwAZ8B0wH/AQ4BKQGMAf8BDQEdAVgB/wErAZQBtAH/ARcBNAGIAf8CDQFkAf8kAAMBAQIDAwQE + BAYECAELAw8BFAMkATYBRgJHAYABWAJcAdEBhwGQAZQB+wHpA/8ByAP/AcMB+wL/AcMB+wL/AcwD/wHw + A/8BhwGQAZQB+wFZAl0B1wNMAZIDKwFCAw0BEgMDAQSEAAMdAf8DjwH/Ax0B/wHHAVgBPQH/Ac4BWwE/ + Af8BzgFbAT8B/wGmAUUBLgH/AisBOQH/AQcBSwGQAf8BKgGHAakB/wEdATIBSgH/AVEBFQEsAf8BpQEk + AUwB/wHCATcBjAH/AcsBRgGkAf8B0gFOAbEB/wHUAU8BtAH/AdEBTAGwAf8BygFFAaIB/wG+ATUBhAH/ + AZIBHgFCAf8BQwEaASwB/wEVAUUBYwH/AS8BigGsAf8BAAFAAYgB/wFXATABKAH/Ab0BUQE4Af8BzgFb + AT8B/wG/AVUBOwH/AyIB/wOPAf8DHQH/Ag0BZAH/ARcBOAGLAf8BMAGcAbkB/wEOAR8BVAH/AQ4BOgGf + Af8BVAHhAfUB/wFZAecC/wFaAegC/wFbAegC/wFdAeoC/wFhAe4C/wFAAcAB6wH/AQgBHAGOAf8CDwFb + Af8CDwFaAf8CDwFZAf8CDwFZAf8BCwEVAYEB/wE4AaEB1AH/AVkB5gL/AQ8BUgHBAf8BWQHmAv8BIQGP + AdQB/wFGAckB8QH/AUYByQHxAf8BIQGPAdUB/wFPAdwB9QH/ARMBOAGYAf8BDgEdAVMB/wEvAZQBtAH/ + ARcBNAGIAf8CDQFkAf8cAAMCAQMDBgEIAw0BEQMXASADIgEyAyoBQAMsAUMDMQFOA0cBggFZAlwBzAF2 + AYABjAH6Ae0D/wHJA/8BwwH7Av8BwwH7Av8BzQP/AfgD/wFtAXoBfgH4AVwCXgHOAUgCSQGHAysBQgMR + ARcDBAEGAwABAYQAAx0B/wOQAf8DHQH/AcUBVgE8Af8BzAFZAT4B/wHMAVkBPgH/AaQBQgEtAf8BKAEr + ATsB/wEDAUUBiQH/AQUBSgGNAf8BNAEkAT4B/wG8AS0BYgH/AcQBPQGcAf8B0QFNAa8B/wHcAVkBwQH/ + AeYBYgHNAf8B6QFlAdIB/wHmAWMBzQH/Ad0BWgHBAf8B0AFNAa8B/wHFAT4BmwH/AbMBKQFRAf8BBAEy + AVMB/wEWAVEBkAH/AQABOgGDAf8BVgEvASgB/wG7AVABNwH/AcwBWQE+Af8BvQFTAToB/wMiAf8DkAH/ + Ax0B/wINAWQB/wEXATgBiwH/ATABmwG4Af8BDgEeAVIB/wERATIBkgH/AT0BuwHgAf8BQQG8AeYB/wFB + Ab8B5gH/AUgBvwHkAf8BSAHBAecB/wFIAcUB6wH/AUMBvwHkAf8BCAEZAYQB/wIOAVkB/wINAVkB/wIH + AVkB/wIHAVkB/wEKAQ0BXAH/AQcBFgGFAf8BCAEcAY0B/wEIARcBiAH/AQgBHAGPAf8BCAEYAYsB/wEI + ARsBlAH/AQkBHAGWAf8BDAEcAZMB/wEIARwBkgH/AQYBEAFdAf8BDgEdAVIB/wEwAZQBtAH/ARcBNAGI + Af8CDQFkAf8XAAEBAwQBBQMKAQ4DGgElAzEBTQNEAXkBTwJQAZsBUwJUAawDVAGuA1UBtQFaAl4B2AFt + AXoBggH3AfQD/wHKA/8BwwH7Av8BxAH8Av8B0Qf/AW0BegGCAfcBWAJbAcYDQwF4AyYBOAMQARUDBAEG + AwABAYgAAx0B/wOSAf8DHQH/AcMBUwE7Af8BygFWAT0B/wHIAVUBPAH/AYwBNAEjAf8BEQEqAUcB/wEM + AUoBjAH/AQwBVgGdAf8BUQEiAT4B/wHCATcBkAH/Ac0BSAGrAf8B3gFcAcQB/wHvAYcB2gH/AfsBkwHs + Af8B/QGYAfQB/wH7AZMB7AH/Ae8BhwHaAf8B3gFcAcQB/wHOAUgBrAH/Ab0BNAGEAf8BIAE0AVQB/wEe + AV0BnQH/AQABOQGEAf8BRAErAS0B/wGwAUgBMgH/AcoBVgE9Af8BuwFQATkB/wMiAf8DkgH/Ax0B/wIN + AWQB/wEXATgBigH/ATABlwG2Af8BDgEdAVIB/wEHAQ4BWwH/AQoBGwGPAf8BCgEdAZcB/wEKAR0BlwH/ + AQoBHQGPAf8BCgEdAY8B/wEKAR0BjwH/AQoBGgGIAf8BCgEOAV0B/wIJAVkB/wIGAVkB/wIGAVkB/wIG + AVkB/wIGAVkB/wIJAVkB/wIOAVkB/wIPAVsB/wIPAWEB/wIPAWEB/wIPAWUB/wIPAYMB/wIPAYMB/wIP + AWQB/wIIAVMB/wEOAR0BUgH/ATABlAG0Af8BFwE0AYgB/wINAWQB/xMAAQEDBAEGAw8BFAMkATUBPwJA + AW8DVgGzAVsCYQHhAmUBZgH0AXEBfQGKAfoBbQF6AX4B+AFZAWYBawH1AWgBegGGAvoD/wHNA/8BwwH7 + Av8BxAH8Av8B1AP/AfMB+AH8Af8BWQFnAWwB9QFWAlgBwQNAAXADIAEuAwsBDwMEAQUDAAEBjAADHQH/ + A5YB/wMdAf8BwQFQATsB/wHIAVMBPAH/AcQBUQE6Af8BhwExASMB/wEAATABWgH/AR4BWAGXAf8BEAFT + AZcB/wGAASEBQgH/AcYBPQGaAf8B1QFRAbcB/wHqAYAB0gH/AfwBlgHxAv8BqAH+Av8BrwP/AagB/gH/ + AfwBlgHxAf8B6gGAAdIB/wHWAVEBtwH/AcUBOwGTAf8BNwEtAUkB/wEcAV8BoAH/AQQBRQGNAf8BIgEq + AT4B/wGMATIBIgH/AccBUwE8Af8BuQFNATkB/wMjAf8DlgH/Ax0B/wINAWMB/wEXATYBhQH/AS0BlQG0 + Af8BDQEdAVIB/wIIAVMB/wIPAWQB/wIPAYMB/wIPAYMB/wIPAWEB/wIPAWEB/wIPAV4B/wIPAVoB/wIJ + AVkB/wIGAVkB/wIGAVkB/wIGAVkB/wIGAVkB/wIGAVkB/wIGAVkB/wINAVkB/wIPAVsB/wIPAWEB/wIP + AWEB/wIPAWEB/wIPAYMB/wIPAYMB/wIPAWQB/wIIAVMB/wEOAR0BUgH/ATABlAG0Af8BFwE0AYgB/wIN + AWQB/xAAAwIBAwMLAQ8DIwE0AUQCRQF8AVcCWgHFAW0BfQGDAfcB8wH4AfwB/wHxA/8B5wP/AeoD/wHv + A/8B5AP/Ac0D/wHDAfsC/wHGAf4C/wHaA/8B8wH4AfwB/wFkAWUBZgH0AVYCWAG8Az0BaQMdASoDCgEN + AwMBBJQAAx0B/wOaAf8DHQH/Ab4BTwE6Af8BxQFRATsB/wGvAUUBMgH/AVEBKwEmAf8BAAE6AYsB/wE1 + AYkBqwH/AQ4BQgFlAf8BqQEpAVMB/wHIAUEBoQH/AdoBVgG8Af8B8AGIAdwB/wH+AZ8B+gL/AbQD/wHC + A/8BtAL/Af4BnwH6Af8B8AGIAdwB/wHbAVYBvQH/AckBQAGdAf8BXQEiAUEB/wEYAVwBnQH/ASQBYQGi + Af8BAAEvAVoB/wGGATABIgH/AcMBUAE6Af8BtgFMATgB/wMjAf8DmgH/Ax0B/wINAWIB/wEXATQBgwH/ + AS8BlAG0Af8BDgEdAVIB/wIIAVMB/wIPAWQB/wIPAYMB/wIPAYMB/wIPAWEB/wIPAWEB/wIPAVwB/wIP + AVkB/wIGAVkB/wIGAVkB/wIGAVkB/wIGAVkB/wIGAVkB/wIGAVkB/wIGAVkB/wIHAVkB/wIPAVkB/wIP + AV0B/wIPAWEB/wIPAWEB/wIPAYMB/wIPAYMB/wIPAWQB/wIIAVMB/wEOAR0BUgH/ATABlAG0Af8BFwE0 + AYgB/wINAWQB/xAAAwMBBAMYASEDPQFpAVcCWQG/AXkBgQGMAfoB8QP/Ac4D/wHEAfwC/wHDAfsC/wHD + AfsC/wHDAfsC/wHDAfsC/wHDAfsC/wHGAf4C/wHeA/8BqAG4AcIB/gFOAl0B8AFVAlcBtwM7AWMDGgEl + AwkBDAMDAQSYAAMdAf8DnwH/Ax0B/wG7AUwBOQH/AcABTQE5Af8BhgEvASEB/wEUASkBQgH/AQUBSAGU + Af8BPAGVAbkB/wEsATMBTgH/AbgBLAFgAf8BxwFBAaAB/wHZAVUBuwH/Ae8BhQHaAf8B/gGdAfoC/wGx + A/8BvAP/AbEC/wH+AZ0B+gH/Ae8BhQHaAf8B2QFVAbwB/wHHAUABnwH/AaQBJgFPAf8BFwFMAYkB/wFC + AZcBuAH/AQABOAGKAf8BUAEqAScB/wGtAUMBMQH/AbMBSQE3Af8DIwH/A58B/wMdAf8CDQFiAf8BFwE0 + AYMB/wEwAZQBtAH/AQ4BHQFSAf8BCQEaAWQB/wEWAUQBrAH/ARcBSQG2Af8BFQFHAbAB/wEPATYBogH/ + AQsBIAGOAf8BDAETAWQB/wIPAVsB/wIGAVkB/wIGAVkB/wIGAVkB/wIGAVkB/wIGAVkB/wIGAVkB/wIG + AVkB/wIHAVkB/wIPAVkB/wIPAVwB/wIPAWEB/wIPAWEB/wIPAYMB/wIPAYMB/wIPAWQB/wIIAVMB/wEO + AR0BUgH/AS8BlAG0Af8BFwE0AYgB/wINAWQB/xAAAwQBBgMjATMBTQJOAZUCZQFmAfQE/wHaA/8B2QP/ + AeAD/wHdA/8BzwP/AcUB/QL/AcMB+wL/AcMB+wL/AdMD/wGoAbgBwgH+AU4CXQHwAVUCVwG3AzoBYAMY + ASIDCAELAwIBA5wAAx0B/wOkAf8DHQH/AbkBSQE3Af8BoAE7ASsB/wFLAScBJQH/AQABKQFhAf8BKwFg + AaIB/wETAVEBkgH/AVkBGQEqAf8BtwEsAWMB/wHCAT0BmwH/AdMBTwGzAf8B5gFkAc8B/wH6AZEB6wL/ + AaAB/AL/AagB/gL/AaAB/AH/AfoBkQHrAf8B5gFkAc8B/wHTAU8BtAH/AcMBPAGaAf8BtgEqAVcB/wEt + ASUBOQH/AScBYgGkAf8BCAFGAZEB/wEPASEBPQH/AYQBLQEfAf8BqQFCATIB/wMjAf8DpAH/Ax0B/wIN + AWMB/wEXATQBhQH/ATABlAG0Af8BDgEdAVIB/wEVAToBkgH/AVQB5AH1Af8BWQHpAv8BUgHgAfgB/wE1 + AbEB3wH/AR0BUgG1Af8BDwEhAYoB/wEPAREBWwH/AgkBWQH/AgYBWQH/AgYBWQH/AgYBWQH/AgYBWQH/ + AgYBWQH/AgYBWQH/Ag0BWQH/Ag8BWgH/Ag8BXgH/Ag8BYwH/AQwBFAGEAf8BCwEZAY0B/wELARcBjAH/ + AQ4BEgGDAf8CCAFUAf8BDQEdAVIB/wEtAZUBtAH/ARcBNgGIAf8CDQFkAf8QAAMEAQYDIgEyAUwCTQGR + AmQBZQHxAasBsQG0Af0BnAGxAb8B/gGoAa8BtQH9AYEBjQGTAfsBcAGIAZoB/AHnAfEB+AH/AdUD/wHD + AfsC/wHDAfsC/wHgA/8BXwGIAZEB+wFaAl0B0wNCAXQDGgElAwYBCAMBAQKgAAMdAf8DqgH/Ax0B/wGp + AT8BMAH/AVMBKAElAf8BRAGWAbUB/wFdAcEB5AH/AZQB2AHrAf8BAAE3AYgB/wEGASoBSwH/AaEBIgFK + Af8BvwE1AY4B/wHKAUUBpgH/AdoBVgG8Af8B6AGBAdIB/wH0AYoB4QH/AfkBkAHoAf8B9AGKAeEB/wHo + AYEB0gH/AdoBVgG9Af8BywFFAaUB/wHAATQBigH/AWMBIQE+Af8BAAEoAVgB/wEkAWIBqQH/AZwB4QHv + Af8BTwGwAdYB/wE3ATABOAH/AZABNAEnAf8DJAH/A6oB/wMdAf8CDQFkAf8BFwE0AYgB/wEwAZQBtAH/ + AQ4BHQFSAf8BCwEkAYoB/wEeAYwBzwH/AR4BkwHcAf8BHwGPAdUB/wEVAVwBwwH/AQ8BNgGlAf8BCgEa + AYkB/wEKARABYAH/Ag4BWQH/AgkBWQH/AgYBWQH/AgYBWQH/AgYBWQH/AgYBWQH/AgkBWQH/Ag4BWQH/ + Ag8BWwH/Ag8BYwH/AQ8BHgGOAf8BHAFUAbgB/wEyAZoB0gH/ASkBjQHLAf8BEwE7AaUB/wEIARABXAH/ + AQ4BHQFSAf8BMAGXAbYB/wEXATgBigH/Ag0BZAH/EAADAwEEAxYBHgM2AVkBTwJRAZwBVwJZAb8BWQJc + AckBWgJdAcoBXAJeAc4BWAJfAeMBVwFiAWUB9gHwA/8BwwH7Av8BwwH7Av8B3QP/AXoBlAGgAfwDWQHH + AzcBWwMPARQDAAEBpAADHQH/A7AB/wMdAf8BrwFAATMB/wFiAScBHwH/AUUBIgEkAf8BQAFcAYUB/wGw + Ae4B9wH/AZsB4wHvAf8BAAE6AZEB/wEPATYBTwH/AaUBJgFSAf8BwAE5AZUB/wHLAUcBqQH/AdYBUgG3 + Af8B3gFcAcIB/wHhAV4BxgH/Ad4BXAHCAf8B1gFSAbcB/wHLAUcBqAH/AcMBOAGRAf8BgQEiAUQB/wEA + AUABgAH/ARcBWgGlAf8BtwHzAfoB/wGWAdoB5AH/ATgBLQE1Af8BWAEmASEB/wGjATsBMAH/AyQB/wOw + Af8DHQH/Ag0BZAH/ARcBNAGIAf8BMAGUAbQB/wEOAR0BUgH/AQsBMgGPAf8BPgHHAegB/wFFAdAB8wH/ + AUYBywHyAf8BPAG7AeYB/wEmAY0BzAH/ARIBPQGlAf8BDQEZAYEB/wEIAQ4BWQH/AgcBWQH/AgYBWQH/ + AgYBWQH/AgYBWQH/AgYBWQH/AgcBWQH/AggBWQH/Ag8BWQH/AQwBEgFjAf8BGAFSAbUB/wFHAdAB8QH/ + AVcB6QH9Af8BVAHlAfsB/wEwAakB3AH/AQoBIQGEAf8BDgEeAVIB/wEwAZsBuAH/ARcBOAGLAf8CDQFk + Af8QAAMCAQMDCgENAxwBJwMvAUkDPAFmA0QBegNIAYQBTgJPAZcBWQJcAcwBUwJkAfEE/wHDAfsC/wHD + AfsC/wHXA/8BqwGyAbYB/QNbAcgDNwFaAwsBD6gAAx0B/wO2Af8DHQH/AbABPwEzAf8BsgE/ATIB/wGf + ATYBKgH/AWMBJgEdAf8BKgEiATEB/wGTAdQB6AH/AZYB3gHvAf8BAAFJAZYB/wEiAS0BRAH/AbgBKgFd + Af8BvwE3AZMB/wHGAUABoAH/AcsBRgGmAf8BzQFIAaoB/wHLAUYBpgH/AcYBQAGgAf8BwAE3AZEB/wGd + ASUBTgH/AQUBQgFcAf8BFwFZAagB/wGvAesB+AH/AVYBoAHDAf8BSAIhAf8BZQEmARwB/wGtAT0BMAH/ + AakBPQEyAf8DJAH/A7YB/wMdAf8CDQFkAf8BFwE0AYgB/wEvAZQBtAH/AQ4BHQFSAf8BCQEtAY4B/wE3 + AcMB5wH/AT4BzgHyAf8BPgHIAfIB/wE0AbQB5gH/ASEBigHKAf8BEQE7AZ8B/wEHARUBXwH/AgYBUAH/ + AgYBTgH/AgYBTgH/AgYBTgH/AgYBTgH/AgYBTgH/AgYBTgH/AgYBTgH/AgYBTwH/AQUBDwFdAf8BKAGV + AcsB/wFMAekB/QH/AU4B7gL/AU4B7gL/AUAB1QHwAf8BCQEuAZAB/wEOAR8BUgH/ATABnAG5Af8BFwE4 + AYsB/wINAWQB/xMAAQEDBwEJAxYBHwMvAUkBQQJCAXMBTAJNAZEBUAJSAaMBVQJXAboDXwHgAUkBYgFl + AfYB8wP/AcMB+wL/AcMB+wL/Ad0D/wF6AZQBoAH8AVcCWgG9AzEBTwMJAQyoAAMdAf8DuwH/Ax0B/wGt + ATwBMgH/AbMBPgEzAf8BswE+ATMB/wGoATkBLgH/AWIBIwEcAf8BKgEiATEB/wGRAdEB6gH/AWEBugHd + Af8BAgFSAZMB/wFLAR8BOgH/AbgBKAFgAf8BvAEwAYcB/wHAATIBigH/Ab8BMwGMAf8BwAEyAYoB/wG8 + AS8BhgH/AbQBJwFYAf8BHgEwAUUB/wEMAVgBogH/AZ0B3gHxAf8BVgGgAcYB/wFKASABIQH/AZYBMAEn + Af8BsgE+ATMB/wGzAT4BMwH/AaYBOgExAf8DJQH/A7sB/wMdAf8CDQFkAf8BFwE0AYgB/wErAZQBtAH/ + AQ0BHQFSAf8BAwEfAYUB/wEVAYIBygH/ARQBjgHXAf8BFAGKAdcB/wEUAYYBzwH/ARQBXAHAAf8BDgFD + AaoB/wEKASQBjAH/AgYBSwH/AgYBRQH/AgYBRQH/AgYBRQH/AgYBRQH/AgYBRQH/AgYBRQH/AgYBRwH/ + AgYBSQH/AQMBDAFZAf8BHgGAAcEB/wFBAeMB+wH/AUUB7gL/AUUB7gL/ATIBxgHqAf8BBgEmAYwB/wEO + AR8BVAH/ATABnQG9Af8BFwE5AYsB/wINAWQB/xMAAQEDCgENAyoBQAFOAk8BlwFYAlwB0QNcAeoDZwHy + AVkBZwFsAfUBgQGNAZMB+wHaAeoB9QH/AdgD/wHDAfsC/wHFAf0C/wHvA/8CYgFoAfYBUAJSAaMDJwE6 + AwcBCagAAx0B/wPAAf8DHQH/AakBOgEwAf8BrwE7ATEB/wGvATsBMQH/Aa8BOwExAf8BpQE2AS0B/wFe + ASEBGgH/ASsBNAFJAf8BmAHaAfEB/wE3AY8BvAH/AQgBPQFZAf8BWgEVASsB/wFOASEBPAH/AT0BJwFC + Af8BPQEnAUIB/wFBASYBQQH/AVYBHQE4Af8BRAEYASkB/wECAU0BkAH/AWUBvAHgAf8BhAG7AeEB/wE8 + AR4BJAH/AZEBLQEkAf8BrwE7ATEB/wGvATsBMQH/Aa8BOwExAf8BogE4AS8B/wMlAf8DwAH/Ax0B/wIN + AWUB/wEXATQBiwH/AS4BlAG0Af8BCgEZAU4B/wEJAS0BjAH/ATYB2gHrAf8BOwHkAfUB/wE7AeIB9QH/ + ATYB2QHzAf8BMAHCAekB/wEhAZMB0QH/AREBPQGjAf8BAQEFAUIB/wIBATsB/wIBATsB/wIBATsB/wIB + ATsB/wIBATsB/wIBATsB/wIBAT4B/wIBAT4B/wEAAQUBRgH/AQYBLAGQAf8BIgGeAdYB/wE2AdEB8AH/ + ATABwwHqAf8BFwFdAb0B/wEBARABWwH/AQsBGwFUAf8BMAGdAb0B/wEXATkBjgH/Ag0BZQH/EwABAQMP + ARQDOwFjA14B2AT/AfsD/wHzA/8B7gP/AeID/wHRA/8BxgH+Av8BxAH8Av8B1gP/AecB8QH4Af8BVwJc + Ad8DRAF5AxgBIgMEAQaoAAMdAf8DxwH/Ax0B/wGmATYBLwH/AawBNwEwAf8BrAE3ATAB/wGsATcBMAH/ + AawBNwEwAf8BmgEvASgB/wFVAR8BHQH/AUgBkAGyAf8BlgHSAfEB/wENAVABogH/AQIBSQGLAf8BBQFR + AZMB/wELAVcBmgH/AQ0BWQGcAf8BCgFWAZcB/wEEAVEBkwH/AQEBRAGLAf8BMgGJAbsB/wGYAdgB8wH/ + ASwBOgFQAf8BXQEfARoB/wGrATYBLwH/AawBNwEwAf8BrAE3ATAB/wGsATcBMAH/AZ8BNQEuAf8DJQH/ + A8cB/wMdAf8CDwGFAf8BGwE7AY0B/wEwAZcBtAH/AQgBFwFMAf8BAAEOAU0B/wEJATEBjAH/AQoBMwGS + Af8BCgEzAZIB/wEIATEBkAH/AQcBLAGGAf8BBAEfAV8B/wECARABTwH/AgABOAH/AgABMgH/AgABMgH/ + AgABMgH/AgABMgH/AgABMgH/AgABMgH/AgABMgH/AgABOAH/AQABAQE5Af8BAAEJAUQB/wECARcBXwH/ + AQgBLQGKAf8BBgElAYUB/wEFARABWAH/AQUBBwFFAf8BCAEYAU0B/wEwAZwBuQH/ARsBPAGRAf8CDwGF + Af8TAAEBAw0BEgM4AVwBWAJbAcsBqAG1Ab4B/gHqA/8BzQP/AcQB/AL/AcMB+wL/AcMB+wL/AcYB/gL/ + AdgD/wHzAfgB/AH/A10B8ANSAakDLgFHAwwBEAMCAQOoAAMdAf8DzwH/Ax0B/wGjATMBLQH/AagBNAEu + Af8BqAE0AS4B/wGoATQBLgH/AagBNAEuAf8BqAE0AS4B/wGNAScBIgH/ATABIgEtAf8BjAHSAfMB/wHD + AfAB+AH/AdUB7gH3Af8B4AH3AfwB/wHnA/8B6AP/AeYB/gL/Ad0B8gH6Af8BzQHtAfcB/wG1Ae8B+wH/ + AVYBqwHPAf8BSwEbAR0B/wGWASwBJgH/AagBNAEuAf8BqAE0AS4B/wGoATQBLgH/AagBNAEuAf8BnQEy + ASwB/wMmAf8DzwH/Ax0B/wIVAYoB/wEcAT4BmAH/ATEBlQG2Af8BGwFCAYgB/wENARsBSwH/AQ0BGwFQ + Af8BDQEbAVAB/wENARsBUAH/AQ0BGwFKAf8BDQEbAUoB/wENARsBSgH/AQ0BGwFFAf8BBgEVAUQB/wEG + ARUBRAH/AQYBFQFEAf8BBgEVAUQB/wEGARUBRAH/AQYBFQFEAf8BBgEVAUQB/wEGARUBRAH/AQ0BGwFF + Af8BDQEcAUsB/wENAR0BTAH/AQ0BHQFMAf8BDQEdAVIB/wENAR0BUgH/AQ0BHAFRAf8BDQEbAUsB/wEZ + AUIBhwH/ATABlAG1Af8BHAE+AZgB/wIVAYoB/xMAAQEDBwEKAyYBOANKAYsBWQJcAc8BcgF6AX4B+AHz + AfgB/AH/AfID/wHmA/8B6AP/AfoD/wGoAbgBwgH+A2EB7gNVAbIDOAFcAxUBHQMFAQcDAAEBqAADHQH/ + A9cB/wMdAf8BnwEwASwB/wGkATEBLQH/AaQBMQEtAf8BpAExAS0B/wGkATEBLQH/AaQBMQEtAf8BmQEs + ASgB/wFFARkBHQH/Aa8B3AHkAf8B4gHwAfIB/wGNAaQBrwH/AUkBTwFbAf8BNwEzAUEB/wE4ATQBQgH/ + AToBNwFEAf8BVAFgAYYB/wGlAcABxQH/Ae8C+wH/AUABggGXAf8BVgEaARkB/wGjATABLAH/AaQBMQEt + Af8BpAExAS0B/wGkATEBLQH/AaQBMQEtAf8BmQEvASsB/wMmAf8D1wH/Ax0B/wIWAZQB/wEbATkBmwH/ + ATwBogHDAf8BTwG3Ac0B/wFLAbkBzQH/AUsBuQHNAf8BSQG5Ac0B/wFIAbkBzQH/AUgBuQHNAf8BSAG5 + Ac0B/wFIAbkBzQH/AUgBuQHNAf8BSAG5Ac0B/wFIAbkBzQH/AUgBuQHNAf8BSAG5Ac0B/wFIAbkBzQH/ + AUgBuQHNAf8BSAG5Ac0B/wFIAbkBzQH/AUsBuQHNAf8BSwG8Ac8B/wFLAb8B0gH/AUsBvwHSAf8BSwG/ + AdIB/wFLAb8B0gH/AUkBvAHPAf8BSAG5Ac0B/wFHAbYByAH/ATcBngHAAf8BGwE4AZsB/wIWAZQB/xQA + AwQBBQMRARcDKQE/A0QBeQFVAlYBtAFcAmEB3AFfAWQBagHzAXEBfQGKAfoBcQF9AYoB+gJdAV8B7QFb + Al4B0AFQAlEBnwM2AVkDGAEhAwcBCgMBAQKsAAMdAf8D3wH/Ax0B/wGcAS0BKwH/AaEBLgEsAf8BoQEu + ASwB/wGhAS4BLAH/AaEBLgEsAf8BoQEuASwB/wGbASsBKQH/AUsBGAEbAf8BjwGWAaEB/wE5ARYBHgH/ + AVMCGAH/AVYBGAEXAf8BgQEgAR4B/wGBASABHgH/AYEBIAEeAf8BVQEYARcB/wFQARgBGQH/AS0BIQEw + Af8BXQFhAYgB/wFVARgBFwH/AaABLQErAf8BoQEuASwB/wGhAS4BLAH/AaEBLgEsAf8BoQEuASwB/wGW + ASwBKgH/AycB/wPfAf8DHQH/AhcBngH/ARgBHwGUAf8BJwFBAZ8B/wE6AWEBrgH/AT0BZQGrAf8BPQFl + AasB/wE7AWUBqwH/AToBZQGnAf8BOgFlAaYB/wE4AWIBpgH/ATQBXwGmAf8BNAFfAaIB/wE0AV8BoQH/ + ATQBXwGhAf8BNAFfAaEB/wE0AV8BoQH/ATQBXwGhAf8BNAFfAaEB/wE0AV8BoQH/ATQBXwGhAf8BOAFf + AaIB/wE4AV8BpgH/ATsBYgGmAf8BPQFlAaYB/wE9AWUBpwH/AT0BZQGrAf8BOwFlAasB/wE6AWUBqwH/ + ATcBYQGuAf8BJQFBAZ8B/wEYAR8BlAH/AhcBngH/FwABAQMEAQYDDAEQAxwBKAMxAU0DQgF1A04BmQFT + AlUBrQNSAakDSwGOATwCPQFnAykBPgMUARsDBwEJAwIBA7AAA0wB8wPfAf8DNAH/AYoCJwH/AZsBKQEq + Af8BmwEpASoB/wGbASkBKgH/AZsBKQEqAf8BmwEpASoB/wGaASgBKQH/AVABFQEWAf8BSgEVARgB/wFS + AhUB/wGZASgBKQH/AZoBKQEqAf8BmwEpASoB/wGbASkBKgH/AZsBKQEqAf8BmgEoASkB/wGSASUBJgH/ + AVECFQH/AUcBFQEZAf8BUgIVAf8BmgEpASoB/wGbASkBKgH/AZsBKQEqAf8BmwEpASoB/wGbASkBKgH/ + AWIBJQEmAf8DPAH/A90B/wNOAfACHAGkAf8CFwGeAf8CFgGUAf8CFQGPAf8CFQGMAf8CFQGGAf8CFQGC + Af8CEAFkAf8CDwFkAf8CDgFhAf8CDQFeAf8CDQFcAf8CDQFcAf8CDQFcAf8CDQFcAf8CDQFcAf8CDQFc + Af8CDQFcAf8CDQFcAf8CDQFcAf8CDQFcAf8CDQFeAf8CDgFhAf8CDwFkAf8CEAFkAf8CFQGCAf8CFQGG + Af8CFQGMAf8CFQGPAf8CFgGUAf8CFwGeAf8CHAGkAf8bAAEBAwIBAwMGAQgDDAEQAxYBHgMiATIDKgFA + AykBPgMfASwDEgEZAwoBDQMEAQYDAQECtAADVwG9A78B/wOUAf8BSAEmASgB/wGKASUBKwH/AZMBIwEq + Af8BkwEjASoB/wGTASMBKgH/AZMBIwEqAf8BkwEjASoB/wGSASMBKQH/AY4BIQEoAf8BkgEjASoB/wGT + ASMBKgH/AZMBIwEqAf8BkwEjASoB/wGTASMBKgH/AZMBIwEqAf8BkwEjASoB/wGTASMBKgH/AZIBIwEp + Af8BjQEhAScB/wGSASMBKgH/AZMBIwEqAf8BkwEjASoB/wGTASMBKgH/AZMBIwEqAf8BgAEmASsB/wE9 + ASUBJwH/A7QB/wO0Af8DVAGuAh8BrAH/Ah8BqQH/Ah8BpgH/AhoBpgH/AhkBpgH/AhkBowH/AhkBnwH/ + AhcBngH/AhcBlwH/AhcBlwH/AhcBlgH/AhcBlgH/AhcBjgH/AhcBjgH/AhcBjgH/AhcBjgH/AhcBjgH/ + AhcBjgH/AhcBjgH/AhcBjgH/AhcBlgH/AhcBlgH/AhcBlwH/AhcBlwH/AhcBngH/AhkBnwH/AhkBowH/ + AhkBpgH/AhoBpgH/Ah8BpgH/Ah8BqQH/Ah8BrAH/JAADAQECAwMEBAQGAQgDBgEIAwQBBgMDAQQDAAEB + vAADNAFUA0wB/wPuAf8DkwH/AzMB/wMdAf8DHQH/Ax0B/wMdAf8DHQH/Ax0B/wMdAf8DHQH/Ax0B/wMd + Af8DHQH/Ax0B/wMdAf8DHQH/Ax0B/wMdAf8DHQH/Ax0B/wMdAf8DHQH/Ax0B/wMdAf8DPAH/A7IB/wPq + Af8DPAH/Ay0BRQIfAawB/wIfAawB/wIfAawB/wIfAawB/wIfAawB/wIfAawB/wIfAawB/wIbAagB/wIa + AaQB/wIXAaIB/wIXAZ8B/wIXAZ8B/wIXAZwB/wIXAZwB/wIXAZwB/wIXAZwB/wIXAZwB/wIXAZwB/wIX + AZwB/wIXAZwB/wIXAZ8B/wIXAZ8B/wIXAaIB/wIaAacB/wIbAagB/wIfAawB/wIfAawB/wIfAawB/wIf + AawB/wIfAawB/wIfAawB/wIfAawB//8ABQADSgGNA0sB/wPNAf8D+QH/A/sB/wP7Af8D+wH/A/sB/wP7 + Af8D+wH/A/sB/wP7Af8D+wH/A/sB/wP7Af8D+wH/A/sB/wP7Af8D+wH/A/sB/wP7Af8D+wH/A/sB/wP7 + Af8D+wH/A/sB/wPrAf8DvQH/AzYB/wNIAYcEAANIAYUCHwGsAf8CHwGsAf8CHwGsAf8CHwGsAf8CHwGs + Af8CHwGsAf8CHwGsAf8CHgGpAf8CHAGpAf8CHAGmAf8CGAGkAf8CFwGhAf8CFwGhAf8CFwGhAf8CFwGh + Af8CFwGhAf8CFwGhAf8CFwGhAf8CFwGhAf8CGAGkAf8CHAGmAf8CHAGpAf8CHgGrAf8CHwGsAf8CHwGs + Af8CHwGsAf8CHwGsAf8CHwGsAf8CHwGsAf8CHwGsAf8DSAGF/wAJAAM3AVoDWQHDAysB/AMdAf8DHQH/ + Ax0B/wMdAf8DHQH/Ax0B/wMdAf8DHQH/Ax0B/wMdAf8DHQH/Ax0B/wMdAf8DHQH/Ax0B/wMdAf8DHQH/ + Ax0B/wMdAf8DHQH/Ax0B/wMdAf8DVQHqA1QBrgMtAUUIAAMHAQoDSAGFAh8BrAH/Ah8BrAH/Ah8BrAH/ + Ah8BrAH/Ah8BrAH/Ah8BrAH/Ah8BrAH/Ah8BrAH/Ah8BqwH/Ah4BqgH/Ah0BqgH/Ah0BqAH/Ah0BpAH/ + Ah0BpAH/Ah0BpAH/Ah0BpAH/Ah0BqAH/Ah0BqgH/Ah4BqgH/Ah8BqwH/Ah8BrAH/Ah8BrAH/Ah8BrAH/ + Ah8BrAH/Ah8BrAH/Ah8BrAH/Ah8BrAH/Ah8BrAH/A0gBhQMHAQr/AAEAAUIBTQE+BwABPgMAASgDAAGA + AwABIAMAAQEBAAEBBgABAhYAA/8BAAHAAgABAwQABP8EAAGAAgABAQQAAv8B+AEHDAAC/wHwAQMMAAL/ + AeABAQwAAv8BwAEBDAAC/wGAAQEMAAL/AQABAQwAAf8B/gEAAQEMAAH/AfwBAAEBDAAB/wH8AQABAQwA + Af8BgAEAAQEMAAH+AgABAQwAAfgCAAEDDAAB8AIAAQcMAAHwAgABHwwAAfACAAE/DAAB8AIAAX8MAAHw + AgAB/wwAAfABAAEBAf8MAAHwAQABAwH/DAAB8AEAAQMB/wwAAfABAAEDAf8MAAHwAQABAwH/DAAB8AEA + AQMB/wwAAfABAAEDAf8MAAH4AQABBwH/DAAB+AEAAQ8B/wwAAfwBAAEfAf8MAAH/AYABfwH/DAAE/wQA + AYACAAEBBAAE/wQAAcACAAEDBAAE/wQACw== + + + \ No newline at end of file diff --git a/ThirdParty/Converter.cs b/ThirdParty/Converter.cs new file mode 100644 index 0000000..21ff000 --- /dev/null +++ b/ThirdParty/Converter.cs @@ -0,0 +1,79 @@ +namespace DutyContent.ThirdParty +{ + static class Converter + { + public static bool TryInt(string s, out int ret) + { + ret = 0; + + for (int i = 0; i < s.Length; i++) + { + var n = s[i] - '0'; + if (n < 0 || n > 9) + return false; + + ret = ret * 10 + n; + } + + return true; + } + + public static int ToInt(string s, int failret = 0) + { + int ret = 0; + + for (int i = 0; i < s.Length; i++) + { + var n = s[i] - '0'; + if (n < 0 || n > 9) + return failret; + + ret = ret * 10 + n; + } + + return ret; + } + + public static bool TryUshort(string s, out ushort ret) + { + ret = 0; + + for (int i = 0; i < s.Length; i++) + { + var n = s[i] - '0'; + if (n < 0 || n > 9) + return false; + + ret = (ushort)(ret * 10 + n); + } + + return true; + } + + public static ushort ToUshort(string s, ushort failret=0) + { + int ret = 0; + + for (int i = 0; i < s.Length; i++) + { + var n = s[i] - '0'; + if (n < 0 || n > 9) + return failret; + + ret = ret * 10 + n; + } + + return (ushort)ret; + } + + public static bool ToBool(string s) + { + return s.ToUpper().Equals("TRUE"); + } + + public static float ToFloat(string s, float failret=0.0f) + { + return float.TryParse(s, out float v) ? v : failret; + } + } +} diff --git a/ThirdParty/LineDb.cs b/ThirdParty/LineDb.cs new file mode 100644 index 0000000..9935f2a --- /dev/null +++ b/ThirdParty/LineDb.cs @@ -0,0 +1,223 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace DutyContent.ThirdParty +{ + class LineDb + { + private Dictionary _dbstr = new Dictionary(); + private Dictionary _dbint = new Dictionary(); + + public static string InvalidKey = ""; + + public LineDb(string ctx, bool useintdb) + { + LoadString(ctx, useintdb, false); + } + + public LineDb(string filename, Encoding enc, bool useintdb) + { + LoadFile(filename, enc, useintdb, false); + } + + public void LoadString(string ctx, bool useintdb, bool reset = false) + { + if (reset) + { + _dbstr.Clear(); + _dbint.Clear(); + } + + ParseLines(ctx, useintdb); + } + + public void LoadFile(string filename, Encoding enc, bool useintdb, bool reset = false) + { + try + { + var ctx = File.ReadAllText(filename, enc); + LoadString(ctx, useintdb, reset); + } + catch { } + } + + public bool SaveFile(string filename, Encoding enc, string header = null) + { + if (string.IsNullOrEmpty(filename)) + return false; + + using (var sw = new StreamWriter(filename, false, enc)) + { + if (!string.IsNullOrEmpty(header)) + { + sw.WriteLine(header); + sw.WriteLine(); + } + + foreach (var l in _dbstr) + { + if (l.Key.IndexOf('=') < 0) + sw.WriteLine($"{l.Key}={l.Value}"); + else + sw.WriteLine($"\"{l.Key}\"={l.Value}"); + } + + foreach (var l in _dbint) + sw.WriteLine($"{l.Key}={l.Value}"); + } + + return true; + } + + private void ParseLines(string ctx, bool useintdb) + { + _dbstr.Clear(); + + var ss = ctx.Split(new char[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); + + foreach (var v in ss) + { + string name, value, l = v.TrimStart(); + + if (l[0] == '#' || l.StartsWith("//")) + continue; + + if (l[0] == '"') + { + var qt = l.IndexOf('"', 1); + if (qt < 0) + { + // no end quote? + continue; + } + + value = l.Substring(qt + 1).TrimStart(); + + if (value.Length == 0 || value[0] != '=') + { + // no value + continue; + } + + name = l.Substring(1, qt - 1).Trim(); + value = value.Substring(1).Trim(); + } + else + { + var div = l.IndexOf('='); + if (div <= 0) + continue; + + name = l.Substring(0, div).Trim(); + value = l.Substring(div + 1).Trim(); + } + + if (!useintdb) + { + if (_dbstr.TryGetValue(name, out _)) + _dbstr.Remove(name); + _dbstr.Add(name, value); + } + else + { + if (!Converter.TryInt(name, out int nkey)) + { + if (_dbstr.TryGetValue(name, out _)) + _dbstr.Remove(name); + _dbstr.Add(name, value); + } + else + { + if (_dbint.TryGetValue(nkey, out _)) + _dbint.Remove(nkey); + _dbint.Add(nkey, value); + } + } + } + } + + public string Get(string name) + { + if (!_dbstr.TryGetValue(name, out string value)) + return name; + return value; + } + + public string Get(int key) + { + if (!_dbint.TryGetValue(key, out string value)) + return InvalidKey; + return value; + } + + public bool Try(string name, out string value) + { + return _dbstr.TryGetValue(name, out value); + } + + public bool Try(int key, out string value) + { + return _dbint.TryGetValue(key, out value); + } + + public bool Try(string name, out int value) + { + if (!_dbstr.TryGetValue(name, out string v)) + { + value = 0; + return false; + } + else + { + if (!ThirdParty.Converter.TryInt(v, out value)) + return false; + return true; + } + } + + public bool Try(string name, out ushort value) + { + if (!_dbstr.TryGetValue(name, out string v)) + { + value = 0; + return false; + } + else + { + if (!ThirdParty.Converter.TryUshort(v, out value)) + return false; + return true; + } + } + + public IEnumerator> GetStringDb() + { + return (IEnumerator>)_dbstr; + } + + public IEnumerator> GetIntDb() + { + return (IEnumerator>)_dbint; + } + + public int Count { get { return _dbstr.Count + _dbint.Count; } } + + public string this[string index] + { + get + { + return Try(index, out string v) ? v : ""; + } + } + + public string this[int key] + { + get + { + return Try(key, out string v) ? v : ""; + } + } + } +} diff --git a/ThirdParty/NativeMethods.cs b/ThirdParty/NativeMethods.cs new file mode 100644 index 0000000..1b1f277 --- /dev/null +++ b/ThirdParty/NativeMethods.cs @@ -0,0 +1,114 @@ +using System; +using System.Diagnostics; +using System.Net; +using System.Net.NetworkInformation; +using System.Net.Sockets; +using System.Runtime.InteropServices; +using System.Windows.Forms; + +namespace DutyContent.ThirdParty +{ + class NativeMethods + { + [DllImport("user32.dll", CharSet = CharSet.Auto)] + public static extern IntPtr SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam); + + public static void ScrollToBottom(RichTextBox richTextBox) + { + SendMessage(richTextBox.Handle, 277, (IntPtr)7, IntPtr.Zero); + richTextBox.SelectionStart = richTextBox.Text.Length; + } + + [DllImport("kernel32.dll")] + public static extern IntPtr OpenProcess(uint access_flag, bool inherit_handle, int process_id); + + [DllImport("kernel32.dll")] + public static extern int CloseHandle(IntPtr handle); + + [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] + public static extern IntPtr GetForegroundWindow(); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern int GetWindowThreadProcessId(IntPtr handle, out int process_id); + + [DllImport("user32.dll")] + public static extern bool ReleaseCapture(); + + public class ProcessHandle + { + public Process Process { get; private set; } + public IntPtr Handle { get; private set; } + public System.Net.IPEndPoint EndPoint { get; set; } + + public ProcessHandle(Process p) + { + Process = p; + + if (p != null && !p.HasExited) + Handle = OpenProcess(16, false, p.Id); + } + + ~ProcessHandle() + { + if (Handle != IntPtr.Zero) + CloseHandle(Handle); + } + } + + [DllImport("Iphlpapi.dll", SetLastError = true)] + public static extern uint GetExtendedTcpTable(IntPtr tcpTable, ref int tcpTableLength, bool sort, AddressFamily ipVersion, int tcpTableType, int reserved = 0); + + [StructLayout(LayoutKind.Sequential)] + public struct TcpTable + { + public uint entries; + [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1)] + public TcpRow[] row; + } + + [StructLayout(LayoutKind.Sequential)] + public struct TcpRow : IEquatable + { + public TcpState state; + public uint __localAddr; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] __localPort; + public uint __remoteAddr; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] __remotePort; + public uint owningPid; + + public IPAddress LocalAddress => new IPAddress(__localAddr); + public ushort LocalPort => BitConverter.ToUInt16(new byte[2] { __localPort[1], __localPort[0] }, 0); + + public IPAddress RemoteAddress => new IPAddress(__remoteAddr); + public ushort RemotePort => BitConverter.ToUInt16(new byte[2] { __remotePort[1], __remotePort[0] }, 0); + + public bool Equals(TcpRow right) + { + return + __localAddr == right.__localAddr && LocalPort == right.LocalPort && + __remoteAddr == right.__remoteAddr && RemotePort == right.RemotePort && + owningPid == right.owningPid; + } + + public override bool Equals(object obj) + { + return !(obj is null) && obj is TcpRow && Equals((TcpRow)obj); + } + + public override int GetHashCode() + { + unchecked + { + var h = (int)__localAddr; + h = (h * 397) ^ LocalPort; + h = (h * 397) ^ (int)__remoteAddr; + h = (h * 397) ^ RemotePort; + h = (h * 397) ^ (int)owningPid; + return h; + } + } + } + } +} diff --git a/WorkerAct.cs b/WorkerAct.cs new file mode 100644 index 0000000..e341c62 --- /dev/null +++ b/WorkerAct.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Advanced_Combat_Tracker; + +namespace DutyContent +{ + static class WorkerAct + { + public delegate object ObjectReturnerDelegate(); + + private static object _lock_effect_sound = new object(); + private static long _last_effect_sound; + + // main invoker + public static object Invoker(ObjectReturnerDelegate dgt) + { + return ActGlobals.oFormActMain.Invoke(dgt); + } + + // + public static void Invoker(Action dgt) + { + ActGlobals.oFormActMain.Invoke(dgt); + } + + // + public static void Tts(string msg) + { + ActGlobals.oFormActMain.TTS(msg); + } + + // + public static void PlaySound(string filename, int volume_percent = 100) + { + ActGlobals.oFormActMain.PlaySoundWinApi(filename, volume_percent); + } + + // + public static void PlayEffectSound(string filename, int volume_percent = 100) + { + if (string.IsNullOrWhiteSpace(filename) || !File.Exists(filename)) + return; + + lock (_lock_effect_sound) + { + long now = DateTime.Now.Ticks; + long delta = now - _last_effect_sound; + TimeSpan span = new TimeSpan(delta); + + if (span.TotalSeconds > 2) + { + _last_effect_sound = now; + PlaySound(filename, volume_percent); + } + } + } + } +} diff --git a/packages.config b/packages.config new file mode 100644 index 0000000..a9de8b5 --- /dev/null +++ b/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file