Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Saga v1.1.0
SagaSixVikings.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using SixVikings; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("SagaSixVikings")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyInformationalVersion("1.1.0+647996836758923c0de9c8ad4e96c94fa372f426")] [assembly: AssemblyProduct("SagaSixVikings")] [assembly: AssemblyTitle("SagaSixVikings")] [assembly: AssemblyVersion("1.1.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SixVikings { internal static class Langue { internal static bool Francais { get { try { return Localization.instance.GetSelectedLanguage() == "French"; } catch (Exception) { return false; } } } internal static string T(string francais, string anglais) { if (!Francais) { return anglais; } return francais; } internal static string Reglage(string anglais, string francais) { return anglais + "\nFR : " + francais; } } } namespace SagaSixVikings { [BepInPlugin("sixvikings.saga", "Saga des Six Vikings", "1.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { [HarmonyPatch(typeof(Player), "OnDeath")] private static class MortDuJoueur { private static void Prefix(Player __instance, out int __state) { __state = (((Object)(object)__instance == (Object)(object)Player.m_localPlayer) ? Stat((PlayerStatType)0) : (-1)); } private static void Postfix(Player __instance, HitData ___m_lastHit, int __state) { try { int num = Stat((PlayerStatType)0); if (__state >= 0 && num > __state) { instance.AnnoncerMort(__instance, ___m_lastHit, num); } } catch (Exception ex) { ((BaseUnityPlugin)instance).Logger.LogError((object)ex); } } } [HarmonyPatch(typeof(Character), "Damage", new Type[] { typeof(HitData) })] private static class CoupPorte { private static void Prefix(Character __instance, HitData hit) { try { instance.NoterTouche(__instance, hit); } catch (Exception ex) { ((BaseUnityPlugin)instance).Logger.LogError((object)ex); } } } [HarmonyPatch(typeof(Game), "RPC_RegisterKill")] private static class MonstreTue { private static void Postfix(string enemyName, int bossNumber) { try { instance.NoterMort(enemyName, bossNumber); } catch (Exception ex) { ((BaseUnityPlugin)instance).Logger.LogError((object)ex); } } } private class CommandeSaga : ConsoleCommand { public override string Name => "saga"; public override string Help => Langue.T("Affiche la saga de mon personnage : morts, boss vaincus, monstres étoilés tués.", "Shows my character's saga: deaths, bosses defeated, starred monsters killed."); public override void Run(string[] args, Terminal context) { try { instance.AfficherSaga(context); } catch (Exception ex) { ((BaseUnityPlugin)instance).Logger.LogError((object)ex); } } } public const string ModGuid = "sixvikings.saga"; public const string ModNom = "Saga des Six Vikings"; public const string ModVersion = "1.1.0"; private const string CleEtoiles1 = "SagaSixVikings.Etoiles1"; private const string CleEtoiles2 = "SagaSixVikings.Etoiles2"; private const string AideJetons = "Jetons : {nom}, {n} (ex. 14e), {lieu} (ex. dans les Marais), {tueur} ; {e} ajoute un e au féminin ; {il/elle} choisit selon le genre du personnage."; private const string AideJetonsAnglais = "Tokens: {name}, {n} (e.g. 14th), {place} (e.g. in the Swamp), {killer}; {he/she}, {his/her}, {him/her} pick by the character's gender."; private const string SectionAnglaise = "Messages (English)"; private static Plugin instance; private ConfigEntry<bool> annonces; private ConfigEntry<bool> sagaPourTous; private readonly Dictionary<string, ConfigEntry<string>> repliques = new Dictionary<string, ConfigEntry<string>>(); private readonly Dictionary<string, ConfigEntry<string>> repliquesAnglaises = new Dictionary<string, ConfigEntry<string>>(); private readonly Random hasard = new Random(); private string derniereReplique; private readonly SuiviEtoiles<ZDOID> etoiles = new SuiviEtoiles<ZDOID>(5f); private readonly int[] etoilesDues = new int[2]; private ZDOMan partieConnue; private void Awake() { //IL_0198: Unknown result type (might be due to invalid IL or missing references) instance = this; annonces = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Annonces", true, Langue.Reglage("Announce my deaths in chat, with a shout every player sees.", "Annoncer mes morts dans le chat, par un cri que tous les joueurs voient.")); sagaPourTous = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "SagaVisibleParTous", true, Langue.Reglage("true: /saga shouts my stats to everyone. false: only I see them.", "true : /saga crie mes stats à tout le monde. false : je suis seul à les voir.")); string[] causes = SagaTexte.Causes; foreach (string text in causes) { repliques[text] = ((BaseUnityPlugin)this).Config.Bind<string>("Messages", text, SagaMessages.Francais[text], Langue.Reglage("French lines for the cause \"" + SagaTexte.Libelle(text, francais: false) + "\", separated by |. Used when the game is in French.", "Répliques pour la cause « " + SagaTexte.Libelle(text) + " », séparées par |. Jetons : {nom}, {n} (ex. 14e), {lieu} (ex. dans les Marais), {tueur} ; {e} ajoute un e au féminin ; {il/elle} choisit selon le genre du personnage.")); string text2 = SagaTexte.Migrer(repliques[text].Value, SagaMessages.Anciennes[text], SagaMessages.Francais[text]); if (text2 != repliques[text].Value) { repliques[text].Value = text2; } repliquesAnglaises[text] = ((BaseUnityPlugin)this).Config.Bind<string>("Messages (English)", text, SagaMessages.Anglais[text], Langue.Reglage("Lines for the cause \"" + SagaTexte.Libelle(text, francais: false) + "\", separated by |. Used when the game is in any language but French. Tokens: {name}, {n} (e.g. 14th), {place} (e.g. in the Swamp), {killer}; {he/she}, {his/her}, {him/her} pick by the character's gender.", "Répliques anglaises pour la cause « " + SagaTexte.Libelle(text) + " », quand le jeu n'est pas en français.")); } CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new CommandeSaga()); new Harmony("sixvikings.saga").PatchAll(typeof(Plugin).Assembly); } private void AnnoncerMort(Player joueur, HitData coup, int morts) { //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) if (annonces.Value && !((Object)(object)Chat.instance == (Object)null)) { bool francais = Langue.Francais; Dictionary<string, ConfigEntry<string>> dictionary = (francais ? repliques : repliquesAnglaises); string text = SagaTexte.Cause(((object)Unsafe.As<HitType, HitType>(ref coup?.m_hitType)/*cast due to .constrained prefix*/).ToString()); Character val = ((coup != null) ? coup.GetAttacker() : null); string text2 = ""; if ((Object)(object)val == (Object)(object)joueur) { text = "SoiMeme"; } else if ((Object)(object)val != (Object)null) { Player val2 = (Player)(object)((val is Player) ? val : null); text2 = (((Object)(object)val2 != (Object)null) ? val2.GetPlayerName() : SagaTexte.NomAvecEtoiles(Localization.instance.Localize(val.GetHoverName()), val.GetLevel(), francais)); } if (text2.Length == 0 && (text == "Monstre" || text == "Joueur")) { text = "Defaut"; } List<string> list = SagaTexte.Decouper(dictionary[text].Value); if (list.Count == 0) { list = SagaTexte.Decouper(dictionary["Defaut"].Value); } string text3 = SagaTexte.Tirer(list, hasard, derniereReplique); if (text3 != null) { derniereReplique = text3; Dictionary<string, string> valeurs = SagaTexte.Valeurs(NomDe(joueur), SagaTexte.Ordinal(morts, francais), text2, SagaTexte.Lieu(((object)joueur.GetCurrentBiome()/*cast due to .constrained prefix*/).ToString(), francais)); Crier(SagaTexte.Rendre(text3, valeurs, joueur.GetPlayerModel() == 1)); } } } private static void Crier(string texte) { Chat.instance.SendText((Type)2, texte.Replace("$", "")); } private static string NomDe(Player joueur) { string text = joueur.GetPlayerName(); if (string.IsNullOrEmpty(text) || text == "...") { PlayerProfile val = (((Object)(object)Game.instance != (Object)null) ? Game.instance.GetPlayerProfile() : null); if (val != null) { text = val.GetName(); } } return text; } private void NoterTouche(Character cible, HitData coup) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) if (cible.GetLevel() < 2 || cible.IsPlayer() || cible.IsTamed()) { return; } Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && coup != null && !((Object)(object)coup.GetAttacker() != (Object)(object)localPlayer)) { OublierSiNouvellePartie(); ZDOID zDOID = cible.GetZDOID(); if (zDOID != ZDOID.None) { etoiles.Noter(zDOID, cible.m_name, cible.GetLevel()); } } } private void NoterMort(string nomEnnemi, int numeroBoss) { OublierSiNouvellePartie(); if (numeroBoss == 0 && ZDOMan.instance != null) { Devoir(etoiles.Annoncer(nomEnnemi, Existe, Time.time)); } } private void Update() { if (!etoiles.EnAttente && etoilesDues[0] + etoilesDues[1] == 0) { return; } try { if ((Object)(object)Game.instance == (Object)null || Game.instance.IsShuttingDown() || ZDOMan.instance == null) { EffacerArdoise(); return; } OublierSiNouvellePartie(); Devoir(etoiles.Regler(Existe, Time.time)); Crediter(); } catch (Exception ex) { EffacerArdoise(); ((BaseUnityPlugin)this).Logger.LogError((object)ex); } } private static bool Existe(ZDOID id) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return ZDOMan.instance.GetZDO(id) != null; } private void Devoir(List<int> niveaux) { foreach (int item in niveaux) { etoilesDues[(item >= 3) ? 1u : 0u]++; } } private void Crediter() { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { Ajouter(localPlayer.m_customData, "SagaSixVikings.Etoiles1", etoilesDues[0]); Ajouter(localPlayer.m_customData, "SagaSixVikings.Etoiles2", etoilesDues[1]); etoilesDues[0] = (etoilesDues[1] = 0); } } private static void Ajouter(Dictionary<string, string> donnees, string cle, int combien) { if (combien > 0) { donnees[cle] = (Compteur(donnees, cle) + combien).ToString(CultureInfo.InvariantCulture); } } private void EffacerArdoise() { etoiles.Oublier(); etoilesDues[0] = (etoilesDues[1] = 0); } private void OublierSiNouvellePartie() { if (ZDOMan.instance != partieConnue) { partieConnue = ZDOMan.instance; etoiles.Oublier(); } } private void AfficherSaga(Terminal terminal) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { if ((Object)(object)terminal != (Object)null) { terminal.AddString(Langue.T("La saga se consulte en jeu, avec un personnage.", "The saga can only be read in game, with a character.")); } return; } bool francais = Langue.Francais; Dictionary<string, int> dictionary = new Dictionary<string, int>(); string[] names = Enum.GetNames(typeof(HitType)); foreach (string text in names) { if (Enum.TryParse<PlayerStatType>("DeathBy" + text, out PlayerStatType result)) { string key = SagaTexte.Cause(text); dictionary.TryGetValue(key, out var value); dictionary[key] = value + Stat(result); } } string text2 = SagaTexte.Resume(NomDe(localPlayer), Stat((PlayerStatType)0), dictionary, Stat((PlayerStatType)85), Compteur(localPlayer.m_customData, "SagaSixVikings.Etoiles1"), Compteur(localPlayer.m_customData, "SagaSixVikings.Etoiles2"), francais); if (sagaPourTous.Value && (Object)(object)Chat.instance != (Object)null) { Crier(text2); } else if ((Object)(object)terminal != (Object)null) { terminal.AddString(text2); } } private static int Stat(PlayerStatType type) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) PlayerProfile val = (((Object)(object)Game.instance != (Object)null) ? Game.instance.GetPlayerProfile() : null); if (val == null || !val.m_playerStats[0].m_stats.TryGetValue(type, out var value)) { return 0; } return (int)value; } private static int Compteur(Dictionary<string, string> donnees, string cle) { if (!donnees.TryGetValue(cle, out var value)) { return 0; } return SagaTexte.LireCompteur(value); } } public class SuiviEtoiles<TId> { private struct Touche { public string Nom; public int Niveau; } private class Attente { public List<TId> Candidats; public float Limite; } private readonly Dictionary<TId, Touche> touches = new Dictionary<TId, Touche>(); private readonly List<Attente> attentes = new List<Attente>(); private readonly float delai; public bool EnAttente => attentes.Count > 0; public SuiviEtoiles(float delai) { this.delai = delai; } public void Noter(TId id, string nom, int niveau) { touches[id] = new Touche { Nom = nom, Niveau = niveau }; } public List<int> Annoncer(string nom, Func<TId, bool> existe, float maintenant) { List<int> result = Regler(existe, maintenant); List<TId> list = (from t in touches where t.Value.Nom == nom && existe(t.Key) select t.Key).ToList(); if (list.Count > 0) { attentes.Add(new Attente { Candidats = list, Limite = maintenant + delai }); } return result; } public List<int> Regler(Func<TId, bool> existe, float maintenant) { List<int> list = new List<int>(); int num = 0; while (num < attentes.Count) { Attente attente = attentes[num]; int num2 = attente.Candidats.FindIndex((TId id) => touches.ContainsKey(id) && !existe(id)); if (num2 >= 0) { TId key = attente.Candidats[num2]; list.Add(touches[key].Niveau); touches.Remove(key); attentes.RemoveAt(num); } else if (maintenant > attente.Limite) { attentes.RemoveAt(num); } else { num++; } } return list; } public void Oublier() { touches.Clear(); attentes.Clear(); } } public static class SagaMessages { public static readonly Dictionary<string, string> Francais = new Dictionary<string, string> { { "Monstre", Liste("{nom} voulait juste dire bonjour. {tueur} n'était pas d'humeur.", "Cause officielle de la {n} mort : {tueur}. Cause réelle : {nom} voulait voir de plus près.", "{nom} a livré un combat digne des dieux {lieu}. {tueur} l'a gagné.", "{nom} contre {tueur} : c'était serré pendant deux secondes.", "{tueur} entre dans la légende. {nom} en sort pour la {n} fois.", "Colis {nom} bien réceptionné {lieu}. Signé : {tueur}.", "{n} strophe de la saga : {nom} rencontre {tueur}. Fin de la strophe.", "{nom} avait un plan {lieu}. {tueur} en avait un meilleur.", "{tueur} ajoute {nom} à son tableau de chasse {lieu}. Un trophée sans grande valeur.", "{nom} a tenté d'apprivoiser {tueur}. {tueur} a décliné l'offre.", "{n} mort pour {nom}. {tueur} réclame sa part du butin.", "Les scaldes chanteront les exploits de {tueur}. {nom} fera les chœurs, depuis le sol.") }, { "Joueur", Liste("{nom} et {tueur} avaient juré de mourir ensemble. {tueur} a pris du retard.", "Règlement de comptes entre amis {lieu}. {tueur} 1, {nom} 0.", "{tueur} visait un monstre. Le monstre va bien, {nom} en est à sa {n} mort.", "Rappel à {tueur} : {nom} figure sur la liste des alliés. Enfin, figurait.", "{nom} meurt pour la {n} fois {lieu}. {tueur} a tenu à participer.", "Tir ami {lieu}. {tueur} a bien visé, mais pas le bon viking. Toutes nos excuses, {nom}.", "{tueur} jure que c'était un accident. {nom} prépare déjà sa vengeance.", "Le conseil du village examinera le cas de {tueur}. {nom} ne pourra pas témoigner.") }, { "Chute", Liste("Odin a vu {nom} tomber {lieu}. Il a compté les rebonds.", "La descente, {nom} maîtrise. C'est l'arrivée qui pose problème.", "Contrôle de la gravité effectué par {nom} {lieu}. Résultat : conforme.", "{nom} n'est toujours pas un corbeau. {n} mort pour le vérifier.", "Les Valkyries emportent les braves au ciel. Pour sa {n} mort, {nom} a pris l'autre sens.", "{nom} a sauté {lieu}. Le sol, prévenu trop tard, n'a pas pu se pousser.", "{n} mort : {nom} regarde toujours où {il/elle} met les pieds. Juste après.", "{nom} a essayé de planer sans planeur {lieu}. Conclusion : il faut le planeur.", "Saut de l'ange signé {nom} {lieu}. L'ange, lui, avait des ailes.", "{nom} descend toujours plus vite que prévu. {n} mort, record personnel battu.") }, { "Noyade", Liste("{nom} pensait avoir pied {lieu}. {Il/Elle} n'avait pas pied.", "Niveau de l'eau : stable. {nom} : nettement en dessous.", "{n} mort pour {nom} {lieu}. Sa pierre tombale flotte, elle.", "Pour la {n} fois, {nom} part pour le Valhalla. En passant par le fond.", "Un radeau, c'est vingt bouts de bois. {nom} a préféré une {n} mort.", "Les corbeaux ont cherché {nom} {lieu}. Ils n'ont trouvé que des bulles.", "Le service des eaux confirme : {nom} sait nager. Pas longtemps, mais {il/elle} sait.", "{nom} voulait attraper un poisson à mains nues {lieu}. Le poisson a gagné.", "Les Nornes avaient prévu une mort glorieuse. {nom} a préféré la baignade.", "{nom} vient de vérifier qu'une armure de fer ne flotte pas {lieu}.") }, { "Arbre", Liste("{nom} a abattu un arbre {lieu}. L'arbre a rendu la politesse.", "Rappel de sécurité : un arbre tombe toujours du côté où se tient {nom}.", "{n} mort pour {nom}. Le bois de chauffage se défend mieux que les trolls.", "Pour la {n} fois, {nom} tombe au combat {lieu}. L'ennemi était un arbre.", "Bilan de coupe : du bois, de la résine, et {nom} en dessous.", "{nom} repose sous sa dernière victime. Les scaldes trouvent ça poétique.", "{nom} y reste pour la {n} fois. Et c'est {lui/elle} qui tenait la hache.", "On dit que les arbres ne bougent pas. {nom} ne le croira plus jamais.", "{nom} a crié « Attention ! » une seconde trop tard {lieu}.") }, { "Defaut", Liste("{nom} est mort{e} {lieu}. Personne n'a vu, personne n'est surpris.", "{nom} est décédé{e}. Affaires à retirer sur place, compétences non remboursées.", "{nom} mourut en brave pour la {n} fois, dit la saga. La saga est polie.", "{nom} avait une seule consigne : rester en vie. {n} mort.", "Ici repose {nom} {lieu}. Enfin, surtout ses affaires.", "{n} mort pour {nom}. Cause inconnue, responsable bien connu{e}.", "Les Nornes avaient tissé un grand destin pour {nom}. Le fil a lâché {lieu}.", "La saga de {nom} gagne un chapitre {lieu}. Il est court.", "{nom} est mort{e}. Les dieux haussent les épaules.", "Odin inscrit une {n} mort au nom de {nom}. Il va manquer de parchemin.") }, { "Feu", Liste("Les dieux ont offert le feu aux mortels. {nom} confirme : mortels.", "Alerte incendie {lieu}. Départ de feu identifié : {nom}.", "On brûlait jadis les héros une fois morts. Pour sa {n} mort, {nom} a inversé l'ordre.", "{nom} s'est approché{e} du feu pour se réchauffer. Objectif largement dépassé.", "{nom}, {n} mort, servi{e} bien cuit{e} {lieu}. Personne n'avait rien commandé.", "{nom} voulait un feu de camp. {Il/Elle} est devenu{e} le feu de camp.", "Pour sa {n} mort, {nom} a confondu se réchauffer et griller.") }, { "Poison", Liste("{nom} gardait son hydromel antipoison pour une grande occasion. C'était sa {n} mort.", "Le poison a agi lentement {lieu}. {nom} a réagi encore plus lentement.", "{nom} rend l'âme pour la {n} fois. Par prudence, les corbeaux ne toucheront à rien.", "{nom} attendait que le poison passe. C'est {lui/elle} qui y est passé{e}.", "Les grands guerriers meurent debout. {nom} est mort{e} en se tenant le ventre.", "{nom} a goûté le champignon douteux {lieu}. Il était douteux.", "Une odeur de marais, un teint verdâtre : {nom} y passe pour la {n} fois.") }, { "Froid", Liste("Températures en baisse {lieu}. {nom} a suivi la tendance.", "{nom} disait qu'il ne faisait pas si froid. {Il/Elle} ne dit plus rien.", "{n} mort : {nom} a claqué des dents, puis claqué tout court.", "{nom} a gelé {lieu}, figé{e} dans une pose héroïque. C'est déjà ça.", "Pour sa {n} mort, {nom} est sorti{e} sans cape. La cape est restée au chaud, dans un coffre.", "{nom} est désormais une statue de glace {lieu}. Très ressemblante.", "Pour sa {n} mort, {nom} a découvert que l'hydromel ne tient pas chaud.") }, { "SoiMeme", Liste("{nom} porte plainte contre {nom}. Les deux parties ne se parlent plus.", "Odin demande qui a tué {nom} pour la {n} fois. {nom} lève la main.", "{nom} s'est occupé{e} de tout {lieu}. Les monstres n'ont rien eu à faire.", "Pour sa {n} mort, {nom} a enfin trouvé un adversaire à sa mesure : {lui/elle}-même.", "{nom} a enfin vaincu son pire ennemi {lieu}. Malheureusement, c'était {lui/elle}.", "Enquête close : {nom} est à la fois la victime et le coupable.") }, { "Fumee", Liste("{nom} a construit quatre murs, un toit et un feu. Il manquait un trou.", "Pour la {n} fois, {nom} rend son dernier souffle. Il fallait le rendre dehors.", "{n} mort pour {nom}, fumé{e} comme un saumon, à domicile.", "Qualité de l'air chez {nom} : médiocre. État de l'occupant{e} : pire.", "{nom} a fumé du poisson toute la nuit. Le poisson va bien.", "{n} mort pour {nom}, terrassé{e} par sa propre maison. La cheminée était en option.") }, { "Lave", Liste("{nom} a mis un pied dans la lave pour voir. On a vu.", "Pour la {n} fois, {nom} se présente devant Odin. Encore fumant{e}.", "Précision utile : le sol orange n'est pas du sol. {nom} y laisse sa {n} vie.", "{nom} a coupé par la lave pour gagner du temps. Du temps, {il/elle} en a maintenant.", "{nom} voulait vérifier la température de la lave {lieu}. Elle est chaude.", "Il reste de {nom} une odeur de grillé et une paire de bottes fondues.") }, { "OceanBouillant", Liste("{nom} voulait entrer dans l'histoire. {Il/Elle} est entré{e} dans la soupe.", "Avis aux navigateurs : la mer bout. {nom} a tenu à s'en assurer.", "Pour sa {n} mort, {nom} a choisi le bain chaud. Version définitive.", "{nom} a plongé dans la mer bouillante {lieu}. Ça sentait le homard.", "Pour sa {n} mort, {nom} a été servi{e} en bouillon.") }, { "BordDuMonde", Liste("La carte s'arrêtait là, {nom} non. {n} mort, la plus lointaine.", "Découverte du jour : le monde a un bord. {nom} ne pourra pas présenter ses conclusions.", "Le drakkar a passé le bord du monde. {nom} tient peut-être encore la barre.", "{nom} voulait voir ce qu'il y avait au bout du monde. Rien, et c'était mortel.") }, { "Chariot", Liste("Thor traverse le ciel sur son char. {nom} a pris le sien sur la tête.", "{nom} tirait le chariot. Dans la descente, le chariot a pris les devants.", "{n} mort pour {nom}, passé{e} sous un chariot. Vitesse au moment des faits : au pas.", "{nom} vient d'apprendre qu'un chariot n'a pas de frein. Ni de klaxon.") }, { "Bateau", Liste("Les grands rois reposent dans leur drakkar. {nom} repose sous le sien.", "{n} mort : {nom} s'est pris un bateau {lieu}. Oui, un bateau.", "Collision entre un bateau et {nom}. Seul le bateau est encore à flot.", "{nom} voulait monter à bord. Le bateau voulait passer. Le bateau est passé.") }, { "Ecrasement", Liste("Les dieux ont envoyé un signe à {nom} {lieu}. Lourd, le signe.", "{nom} se tenait exactement là où ça tombait. {n} mort.", "{nom} n'a rien vu venir {lieu}. C'était pourtant gros et bruyant.", "{nom} a été aplati{e} {lieu}. Les scaldes l'appellent désormais la galette.") }, { "Stalactite", Liste("La stalactite, c'est celle qui tombe. {nom} révise avec sa {n} mort.", "{nom} est entré{e} dans la grotte la tête haute. C'était précisément le problème.", "Inspection du plafond par {nom} : une stalactite manquante, retrouvée depuis.", "{nom} cherchait du fer. {Il/Elle} a trouvé du calcaire, de haut et très vite.") }, { "Baliste", Liste("Notice de la baliste, page 1 : elle tire sur tout ce qui bouge. {nom} bougeait.", "{n} mort pour {nom} {lieu}. La baliste, elle, sait viser.", "{nom} a bâti une baliste pour garder son foyer. Elle le garde bien, même contre {nom}.", "{nom} a oublié de dire à sa baliste qu'{il/elle} était de la famille.") }, { "Catapulte", Liste("{nom} a levé les yeux vers les dieux. C'était un rocher, et il arrivait vite.", "Bulletin météo : chutes de pierres isolées {lieu}, exclusivement sur {nom}.", "La catapulte visait ailleurs. Pour sa {n} mort, {nom} a fait le déplacement.", "{nom} a reçu un rocher {lieu}. Envoi recommandé, sans accusé de réception.") }, { "PontLevis", Liste("Un pont-levis, ça monte et ça redescend. {nom} n'avait retenu que la moitié.", "{n} mort pour {nom} {lieu}. Arme du crime : la porte d'entrée.", "Le pont-levis devait arrêter les envahisseurs. Il a arrêté {nom}, net.", "{nom} attendait sous le pont-levis. Le pont-levis n'attend personne.") }, { "Incinerateur", Liste("{n} mort pour {nom}, foudroyé{e} en sortant les poubelles.", "La saga dira que Thor en personne a foudroyé {nom}. C'était l'Oblitérateur.", "Distance de sécurité de l'Oblitérateur : trois pas. Distance retenue par {nom} : zéro.", "{nom} a voulu récupérer un objet jeté dans l'Oblitérateur. Mauvaise idée.") } }; public static readonly Dictionary<string, string> Anglais = new Dictionary<string, string> { { "Monstre", Liste("{name} just wanted to say hello. {killer} was not in the mood.", "Official cause of the {n} death: {killer}. Real cause: {name} wanted a closer look.", "{name} fought a battle worthy of the gods {place}. {killer} won it.", "{name} versus {killer}: it was close for about two seconds.", "{killer} enters the legend. {name} leaves the world for the {n} time.", "Parcel {name} delivered {place}. Signed for by {killer}.", "The {n} verse of the saga: {name} meets {killer}. The end.", "{name} had a plan {place}. {killer} had a better one.", "{killer} adds {name} to the trophy wall {place}. Not a very valuable trophy.", "{name} tried to tame {killer}. {killer} declined the offer.", "{n} death for {name}. {killer} would like a share of the loot.", "The skalds will sing of {killer}. {name} will hum along, from the ground.") }, { "Joueur", Liste("{name} and {killer} swore to die together. {killer} is running late.", "A friendly disagreement {place}. {killer} 1, {name} 0.", "{killer} was aiming at a monster. The monster is fine. {name} is on {his/her} {n} death.", "Reminder to {killer}: {name} is on the list of allies. Well, was.", "{name} dies for the {n} time {place}. {killer} insisted on helping.", "Friendly fire {place}. {killer} hit the right spot on the wrong viking. Sorry, {name}.", "{killer} swears it was an accident. {name} is already planning revenge.", "The village council will hear the case of {killer}. {name} will not be testifying.") }, { "Chute", Liste("Odin watched {name} fall {place}. He counted the bounces.", "The way down, {name} has mastered. The landing still needs work.", "Gravity inspection carried out by {name} {place}. Result: working as intended.", "{name} is still not a raven. {His/Her} {n} death proves it.", "Valkyries carry the brave up to the sky. For {his/her} {n} death, {name} went the other way.", "{name} jumped {place}. The ground, warned too late, could not get out of the way.", "{n} death: {name} always looks where {he/she} puts {his/her} feet. Right after.", "{name} tried gliding without a glider {place}. Conclusion: you need the glider.", "Swan dive by {name} {place}. The swan, at least, had wings.", "{name} always comes down faster than planned. {n} death, a new personal best.") }, { "Noyade", Liste("{name} thought {he/she} could touch the bottom {place}. {He/She} could not.", "Water level: stable. {name}: well below it.", "{n} death for {name} {place}. At least the gravestone floats.", "For the {n} time, {name} sets off for Valhalla. By way of the seabed.", "A raft is twenty sticks of wood. {name} chose death instead, for the {n} time.", "The ravens searched for {name} {place}. They only found bubbles.", "The harbour master confirms: {name} can swim. Not for long, but {he/she} can.", "{name} tried to catch a fish bare-handed {place}. The fish won.", "The Norns had planned a glorious death. {name} went for a swim instead.", "{name} learned the hard way that iron armour does not float {place}.") }, { "Arbre", Liste("{name} cut down a tree {place}. The tree returned the favour.", "Safety reminder: a tree always falls on the side where {name} is standing.", "{n} death for {name}. Firewood fights back harder than trolls.", "For the {n} time, {name} falls in battle {place}. The enemy was a tree.", "Logging report: wood, resin, and {name} underneath.", "{name} rests beneath {his/her} last victim. The skalds find it poetic.", "{name} goes down for the {n} time. And {he/she} was the one holding the axe.", "They say trees don't move. {name} will never believe that again.", "{name} yelled timber one second too late {place}.") }, { "Defaut", Liste("{name} died {place}. Nobody saw it, nobody is surprised.", "{name} has passed away. Belongings can be collected on site, skills not refunded.", "{name} died bravely for the {n} time, says the saga. The saga is being polite.", "{name} had one job: stay alive. {n} death.", "Here lies {name} {place}. Well, mostly {his/her} stuff.", "{n} death for {name}. Cause unknown, culprit well known.", "The Norns wove a great destiny for {name}. The thread snapped {place}.", "The saga of {name} gains a new chapter {place}. A short one.", "{name} died. The gods shrug.", "Odin writes down {name}'s {n} death. He is running out of parchment.") }, { "Feu", Liste("The gods gave fire to mortals. {name} confirms: mortal.", "Fire alarm {place}. Source of the blaze identified: {name}.", "Heroes used to be burned after they died. For {his/her} {n} death, {name} swapped the order.", "{name} got close to the fire to warm up. Goal massively exceeded.", "{name}, {n} death, served well done {place}. Nobody ordered anything.", "{name} wanted a campfire. {He/She} became the campfire.", "For {his/her} {n} death, {name} mixed up warming up and grilling.") }, { "Poison", Liste("{name} was saving {his/her} poison resistance mead for a special occasion. It was {his/her} {n} death.", "The poison acted slowly {place}. {name} reacted even more slowly.", "{name} gives up the ghost for the {n} time. To be safe, the ravens won't touch anything.", "{name} was waiting for the poison to wear off. {He/She} wore off first.", "Great warriors die standing. {name} died clutching {his/her} stomach.", "{name} tasted the suspicious mushroom {place}. It was suspicious.", "A swampy smell, a greenish glow: {name} goes down for the {n} time.") }, { "Froid", Liste("Temperatures dropping {place}. {name} followed the trend.", "{name} said it wasn't that cold. {He/She} says nothing now.", "{n} death: {name}'s teeth chattered, then everything stopped.", "{name} froze {place}, locked in a heroic pose. That's something.", "For {his/her} {n} death, {name} went out without a cape. The cape stayed warm, in a chest.", "{name} is now an ice statue {place}. A very good likeness.", "For {his/her} {n} death, {name} learned that mead does not keep you warm.") }, { "SoiMeme", Liste("{name} is suing {name}. Both parties have stopped speaking.", "Odin asks who killed {name} for the {n} time. {name} raises a hand.", "{name} took care of everything {place}. The monsters had nothing left to do.", "For {his/her} {n} death, {name} finally found a worthy opponent: {himself/herself}.", "{name} finally defeated {his/her} worst enemy {place}. Unfortunately, it was {himself/herself}.", "Case closed: {name} is both the victim and the culprit.") }, { "Fumee", Liste("{name} built four walls, a roof and a fire. {He/She} forgot the hole.", "For the {n} time, {name} breathes {his/her} last. It should have been done outside.", "{n} death for {name}, smoked like a salmon, at home.", "Air quality at {name}'s place: poor. Condition of the occupant: worse.", "{name} smoked fish all night. The fish are fine.", "{n} death for {name}, done in by {his/her} own house. The chimney was optional.") }, { "Lave", Liste("{name} put a foot in the lava, just to see. We saw.", "For the {n} time, {name} stands before Odin. Still smoking.", "Useful tip: orange ground is not ground. {name} leaves {his/her} {n} life there.", "{name} took a shortcut through the lava to save time. {He/She} has plenty of time now.", "{name} wanted to check the temperature of the lava {place}. It is hot.", "All that is left of {name} is a burnt smell and a pair of melted boots.") }, { "OceanBouillant", Liste("{name} wanted to make history. {He/She} made soup.", "Notice to sailors: the sea is boiling. {name} insisted on checking.", "For {his/her} {n} death, {name} chose a hot bath. The permanent kind.", "{name} dived into the boiling sea {place}. It smelled like lobster.", "For {his/her} {n} death, {name} was served as broth.") }, { "BordDuMonde", Liste("The map ended there, {name} did not. {n} death, the farthest one yet.", "Discovery of the day: the world has an edge. {name} won't be presenting the findings.", "The longship went over the edge of the world. {name} may still be at the helm.", "{name} wanted to see what was at the end of the world. Nothing, and it was deadly.") }, { "Chariot", Liste("Thor crosses the sky in his chariot. {name} took a cart to the head.", "{name} was pulling the cart. On the way down, the cart took the lead.", "{n} death for {name}, run over by a cart. Speed at the time: walking pace.", "{name} just learned that carts have no brakes. Or horns.") }, { "Bateau", Liste("Great kings rest in their longships. {name} rests under {his/hers}.", "{n} death: {name} got hit by a boat {place}. Yes, a boat.", "Collision between a boat and {name}. Only the boat is still afloat.", "{name} wanted to get on board. The boat wanted to get past. The boat got past.") }, { "Ecrasement", Liste("The gods sent {name} a sign {place}. A heavy one.", "{name} stood exactly where it was falling. {n} death.", "{name} never saw it coming {place}. It was big and loud, though.", "{name} was flattened {place}. The skalds now call {him/her} the pancake.") }, { "Stalactite", Liste("Stalactites hang from the ceiling, until they don't. {name} learns it for the {n} time.", "{name} walked into the cave head held high. That was precisely the problem.", "Ceiling inspection by {name}: one stalactite missing, since found.", "{name} was looking for iron. {He/She} found limestone instead, from above and very fast.") }, { "Baliste", Liste("Ballista manual, page 1: it shoots anything that moves. {name} was moving.", "{n} death for {name} {place}. The ballista, at least, knows how to aim.", "{name} built a ballista to guard {his/her} home. It guards it well, even against {name}.", "{name} forgot to tell {his/her} ballista that {he/she} was family.") }, { "Catapulte", Liste("{name} looked up to the gods. It was a rock, and it was coming fast.", "Weather report: scattered falling rocks {place}, exclusively on {name}.", "The catapult was aiming elsewhere. For {his/her} {n} death, {name} made the trip.", "{name} received a rock {place}. Express delivery, no signature required.") }, { "PontLevis", Liste("A drawbridge goes up and comes down. {name} only remembered the first half.", "{n} death for {name} {place}. Murder weapon: the front door.", "The drawbridge was meant to stop invaders. It stopped {name}, dead.", "{name} was waiting under the drawbridge. The drawbridge waits for no one.") }, { "Incinerateur", Liste("{n} death for {name}, struck by lightning while taking out the trash.", "The saga will say Thor himself struck down {name}. It was the Obliterator.", "Obliterator safety distance: three steps. Distance kept by {name}: zero.", "{name} tried to get something back from the Obliterator. Bad idea.") } }; public static readonly Dictionary<string, string> Anciennes = new Dictionary<string, string> { { "Monstre", Liste("{nom} voulait juste dire bonjour. {tueur} n'était pas d'humeur.", "Cause de la {n} mort : {tueur}. Cause réelle : {nom} voulait voir de plus près.", "{nom} a livré un combat digne des dieux {lieu}. {tueur} l'a gagné.", "{nom} contre {tueur} : c'était serré pendant deux secondes.", "{tueur} entre dans la légende. {nom} en sort pour la {n} fois.", "Colis {nom} bien réceptionné {lieu}. Signé : {tueur}.", "{n} strophe de la saga : {nom} rencontre {tueur}. Fin de la strophe.", "{nom} avait un plan {lieu}. {tueur} en avait un meilleur.") }, { "Joueur", Liste("{nom} et {tueur} avaient juré de mourir ensemble. {tueur} a pris du retard.", "Règlement de comptes entre amis {lieu}. {tueur} 1, {nom} 0.", "{tueur} visait un monstre. Le monstre va bien, {nom} en est à sa {n} mort.", "Rappel à {tueur} : {nom} figure sur la liste des alliés. Enfin, figurait.", "{nom} meurt pour la {n} fois {lieu}. {tueur} a tenu à participer.") }, { "Chute", Liste("Odin a vu {nom} tomber {lieu}. Il a compté les rebonds.", "La descente, {nom} maîtrise. C'est l'arrivée qui pose problème.", "Contrôle de la gravité effectué par {nom} {lieu}. Résultat : conforme.", "{nom} n'est toujours pas un corbeau. {n} mort pour le vérifier.", "Les Valkyries emportent les braves au ciel. Pour sa {n} mort, {nom} a pris l'autre sens.", "{nom} a sauté {lieu}. Le sol, prévenu trop tard, n'a pas pu se déplacer.", "{n} mort : {nom} regarde toujours où {il/elle} met les pieds. Juste après.") }, { "Noyade", Liste("{nom} pensait avoir pied {lieu}. {Il/Elle} n'avait pas pied.", "Niveau de l'eau : stable. {nom} : nettement en dessous.", "{n} mort pour {nom} {lieu}. Sa pierre tombale flotte, elle.", "Pour la {n} fois, {nom} part pour le Valhalla. En passant par le fond.", "Un radeau, c'est vingt bouts de bois. {nom} a préféré une {n} mort.", "Les corbeaux ont cherché {nom} {lieu}. Ils n'ont trouvé que des bulles.", "Le service des eaux confirme : {nom} sait nager. Pas longtemps, mais {il/elle} sait.") }, { "Arbre", Liste("{nom} a abattu un arbre {lieu}. L'arbre a rendu la politesse.", "Rappel de sécurité : un arbre tombe toujours du côté où se tient {nom}.", "{n} mort pour {nom}. Le bois de chauffage se défend mieux que les trolls.", "Pour la {n} fois, {nom} tombe au combat {lieu}. L'ennemi était un arbre.", "Bilan de coupe : du bois, de la résine, et {nom} en dessous.", "{nom} repose sous sa dernière victime. Les scaldes trouvent ça poétique.", "{nom} y reste pour la {n} fois. Et c'est {lui/elle} qui tenait la hache.") }, { "Defaut", Liste("{nom} est mort{e} {lieu}. Personne n'a vu, personne n'est surpris.", "{nom} est décédé{e}. Affaires à retirer sur place, compétences non remboursées.", "{nom} mourut en brave pour la {n} fois, dit la saga. La saga est polie.", "{nom} avait une seule consigne : rester en vie. {n} mort.", "Ici repose {nom} {lieu}. Enfin, surtout ses affaires.", "{n} mort pour {nom}. Cause inconnue, responsable bien connu{e}.", "Les Nornes avaient tissé un grand destin pour {nom}. Le fil a lâché {lieu}.") }, { "Feu", Liste("Les dieux ont offert le feu aux mortels. {nom} confirme : mortels.", "Alerte incendie {lieu}. Départ de feu identifié : {nom}.", "On brûlait jadis les héros une fois morts. Pour sa {n} mort, {nom} a inversé l'ordre.", "{nom} s'est approché{e} du feu pour se réchauffer. Objectif largement dépassé.", "{nom}, {n} mort, servi{e} bien cuit{e} {lieu}. Personne n'avait rien commandé.") }, { "Poison", Liste("{nom} gardait son hydromel antipoison pour une grande occasion. C'était sa {n} mort.", "Le poison a agi lentement {lieu}. {nom} a réagi encore plus lentement.", "{nom} rend l'âme pour la {n} fois. Par prudence, les corbeaux ne toucheront à rien.", "{nom} attendait que le poison passe. C'est {lui/elle} qui y est passé{e}.", "Les grands guerriers meurent debout. {nom} est mort{e} en se tenant le ventre.") }, { "Froid", Liste("Températures en baisse {lieu}. {nom} a suivi la tendance.", "{nom} disait qu'il ne faisait pas si froid. {Il/Elle} ne dit plus rien.", "{n} mort : {nom} a claqué des dents, puis claqué tout court.", "{nom} a gelé {lieu}, figé{e} dans une pose héroïque. C'est déjà ça.", "Pour sa {n} mort, {nom} est sorti{e} sans cape. La cape est restée au chaud, dans un coffre.") }, { "SoiMeme", Liste("{nom} porte plainte contre {nom}. Les deux parties ne se parlent plus.", "Odin demande qui a tué {nom} pour la {n} fois. {nom} lève la main.", "{nom} s'est occupé{e} de tout {lieu}. Les monstres n'ont rien eu à faire.", "Pour sa {n} mort, {nom} a enfin trouvé un adversaire à sa mesure : {lui/elle}-même.") }, { "Fumee", Liste("{nom} a construit quatre murs, un toit et un feu. Il manquait un trou.", "Pour la {n} fois, {nom} rend son dernier souffle. Il fallait le rendre dehors.", "{n} mort pour {nom}, fumé{e} comme un saumon, à domicile.", "Qualité de l'air chez {nom} : médiocre. État de l'occupant{e} : pire.") }, { "Lave", Liste("{nom} a mis un pied dans la lave pour voir. On a vu.", "Pour la {n} fois, {nom} se présente devant Odin. Encore fumant{e}.", "Précision utile : le sol orange n'est pas du sol. {nom} y laisse sa {n} vie.", "{nom} a coupé par la lave pour gagner du temps. Du temps, {il/elle} en a maintenant.") }, { "OceanBouillant", Liste("{nom} voulait entrer dans l'histoire. {Il/Elle} est entré{e} dans la soupe.", "Avis aux navigateurs : la mer bout. {nom} a tenu à s'en assurer.", "Pour sa {n} mort, {nom} a choisi le bain chaud. Version définitive.") }, { "BordDuMonde", Liste("La carte s'arrêtait là, {nom} non. {n} mort, la plus lointaine.", "Découverte du jour : le monde a un bord. {nom} ne pourra pas présenter ses conclusions.", "Le drakkar a passé le bord du monde. {nom} tient peut-être encore la barre.") }, { "Chariot", Liste("Thor traverse le ciel sur son char. {nom} a pris le sien sur la tête.", "{nom} tirait le chariot. Dans la descente, le chariot a pris les devants.", "{n} mort pour {nom}, passé{e} sous un chariot. Vitesse au moment des faits : au pas.") }, { "Bateau", Liste("Les grands rois reposent dans leur drakkar. {nom} repose sous le sien.", "{n} mort : {nom} s'est pris un bateau {lieu}. Oui, un bateau.", "Collision entre un bateau et {nom}. Seul le bateau est encore à flot.") }, { "Ecrasement", Liste("Les dieux ont envoyé un signe à {nom} {lieu}. Lourd, le signe.", "{nom} se tenait exactement là où ça tombait. {n} mort.", "{nom} n'a rien vu venir {lieu}. C'était pourtant gros et bruyant.") }, { "Stalactite", Liste("La stalactite, c'est celle qui tombe. {nom} révise avec sa {n} mort.", "{nom} est entré{e} dans la grotte la tête haute. C'était précisément le problème.", "Inspection du plafond par {nom} : une stalactite manquante, retrouvée depuis.") }, { "Baliste", Liste("Notice de la baliste, page 1 : elle tire sur tout ce qui bouge. {nom} bougeait.", "{n} mort pour {nom} {lieu}. La baliste, elle, sait viser.", "{nom} a bâti une baliste pour garder son foyer. Elle le garde bien, même contre {nom}.") }, { "Catapulte", Liste("{nom} a levé les yeux vers les dieux. C'était un rocher, et il arrivait vite.", "Bulletin météo : chutes de pierres isolées {lieu}, exclusivement sur {nom}.", "La catapulte visait ailleurs. Pour sa {n} mort, {nom} a fait le déplacement.") }, { "PontLevis", Liste("Un pont-levis, ça monte et ça redescend. {nom} n'avait retenu que la moitié.", "{n} mort pour {nom} {lieu}. Arme du crime : la porte d'entrée.", "Le pont-levis devait arrêter les envahisseurs. Il a arrêté {nom}, net.") }, { "Incinerateur", Liste("{n} mort pour {nom}, foudroyé{e} en sortant les poubelles.", "La saga dira que Thor en personne a foudroyé {nom}. C'était l'Oblitérateur.", "Distance de sécurité de l'Oblitérateur : trois pas. Distance retenue par {nom} : zéro.") } }; public static Dictionary<string, string> Pour(bool francais) { if (!francais) { return Anglais; } return Francais; } private static string Liste(params string[] repliques) { return string.Join(" | ", repliques); } } public static class SagaTexte { public const string CauseDefaut = "Defaut"; public const string CauseMonstre = "Monstre"; public const string CauseJoueur = "Joueur"; public const string CauseSoiMeme = "SoiMeme"; private static readonly Dictionary<string, string> Libelles = new Dictionary<string, string> { { "Monstre", "monstre" }, { "Joueur", "joueur" }, { "Chute", "chute" }, { "Noyade", "noyade" }, { "Feu", "feu" }, { "Lave", "lave" }, { "OceanBouillant", "océan bouillant" }, { "Froid", "froid" }, { "Poison", "poison" }, { "Fumee", "fumée" }, { "Arbre", "arbre" }, { "BordDuMonde", "bord du monde" }, { "Chariot", "chariot" }, { "Bateau", "bateau" }, { "Ecrasement", "écrasement" }, { "Stalactite", "stalactite" }, { "Baliste", "baliste" }, { "Catapulte", "catapulte" }, { "PontLevis", "pont-levis" }, { "Incinerateur", "incinérateur" }, { "SoiMeme", "soi-même" }, { "Defaut", "mystère" } }; private static readonly Dictionary<string, string> LibellesAnglais = new Dictionary<string, string> { { "Monstre", "monster" }, { "Joueur", "player" }, { "Chute", "fall" }, { "Noyade", "drowning" }, { "Feu", "fire" }, { "Lave", "lava" }, { "OceanBouillant", "boiling sea" }, { "Froid", "cold" }, { "Poison", "poison" }, { "Fumee", "smoke" }, { "Arbre", "tree" }, { "BordDuMonde", "edge of the world" }, { "Chariot", "cart" }, { "Bateau", "boat" }, { "Ecrasement", "crushed" }, { "Stalactite", "stalactite" }, { "Baliste", "ballista" }, { "Catapulte", "catapult" }, { "PontLevis", "drawbridge" }, { "Incinerateur", "obliterator" }, { "SoiMeme", "self" }, { "Defaut", "mystery" } }; public static readonly string[] Causes = Libelles.Keys.ToArray(); private static readonly Dictionary<string, string> CauseParHitType = new Dictionary<string, string> { { "EnemyHit", "Monstre" }, { "PlayerHit", "Joueur" }, { "Fall", "Chute" }, { "Drowning", "Noyade" }, { "Burning", "Feu" }, { "CinderFire", "Feu" }, { "AshlandsLava", "Lave" }, { "AshlandsOcean", "OceanBouillant" }, { "Freezing", "Froid" }, { "Poisoned", "Poison" }, { "Smoke", "Fumee" }, { "Tree", "Arbre" }, { "EdgeOfWorld", "BordDuMonde" }, { "Cart", "Chariot" }, { "Boat", "Bateau" }, { "Impact", "Ecrasement" }, { "Structural", "Ecrasement" }, { "Stalagtite", "Stalactite" }, { "Turret", "Baliste" }, { "Catapult", "Catapulte" }, { "DrawBridge", "PontLevis" }, { "Incinerator", "Incinerateur" }, { "Self", "SoiMeme" } }; private static readonly Dictionary<string, string> Lieux = new Dictionary<string, string> { { "Meadows", "dans les Prairies" }, { "Swamp", "dans les Marais" }, { "Mountain", "en Montagne" }, { "BlackForest", "dans la Forêt noire" }, { "Plains", "dans les Plaines" }, { "AshLands", "dans les Terres de cendres" }, { "DeepNorth", "dans le Grand Nord" }, { "Ocean", "en pleine mer" }, { "Mistlands", "dans les Terres brumeuses" } }; private static readonly Dictionary<string, string> LieuxAnglais = new Dictionary<string, string> { { "Meadows", "in the Meadows" }, { "Swamp", "in the Swamp" }, { "Mountain", "in the Mountains" }, { "BlackForest", "in the Black Forest" }, { "Plains", "on the Plains" }, { "AshLands", "in the Ashlands" }, { "DeepNorth", "in the Deep North" }, { "Ocean", "out at sea" }, { "Mistlands", "in the Mistlands" } }; private static readonly Regex Jeton = new Regex("\\{([^{}]*)\\}"); private const string Voyelles = "aeiouàáâäåæéèêëíîïóôöøœúùûüý"; public static string Ordinal(int n, bool francais = true) { if (n < 1) { n = 1; } if (francais) { if (n != 1) { return n + "e"; } return "1re"; } int num = n % 100; if (num >= 11 && num <= 13) { return n + "th"; } return (n % 10) switch { 1 => n + "st", 2 => n + "nd", 3 => n + "rd", _ => n + "th", }; } public static string Cause(string hitType) { if (hitType == null || !CauseParHitType.TryGetValue(hitType, out var value)) { return "Defaut"; } return value; } public static string Libelle(string cause, bool francais = true) { Dictionary<string, string> dictionary = (francais ? Libelles : LibellesAnglais); if (cause == null || !dictionary.TryGetValue(cause, out var value)) { return dictionary["Defaut"]; } return value; } public static string NomAvecEtoiles(string nom, int niveau, bool francais = true) { if (niveau < 2) { return nom; } if (francais) { return nom + " (" + (niveau - 1) + ((niveau == 2) ? " étoile)" : " étoiles)"); } return nom + " (" + (niveau - 1) + ((niveau == 2) ? " star)" : " stars)"); } public static string Lieu(string biome, bool francais = true) { if (biome == null || !(francais ? Lieux : LieuxAnglais).TryGetValue(biome, out var value)) { return ""; } return value; } public static Dictionary<string, string> Valeurs(string nom, string rang, string tueur, string lieu) { return new Dictionary<string, string> { { "nom", nom }, { "name", nom }, { "n", rang }, { "tueur", tueur }, { "killer", tueur }, { "lieu", lieu }, { "place", lieu } }; } public static string Migrer(string valeur, string ancienne, string nouvelle) { if (!(valeur == ancienne)) { return valeur; } return nouvelle; } public static List<string> Decouper(string liste) { List<string> list = new List<string>(); if (liste == null) { return list; } string[] array = liste.Split(new char[1] { '|' }); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length > 0) { list.Add(text); } } return list; } public static string Tirer(IList<string> messages, Random hasard, string precedent) { if (messages == null || messages.Count == 0) { return null; } List<string> list = messages.Where((string m) => m != precedent).ToList(); if (list.Count == 0) { return messages[0]; } return list[hasard.Next(list.Count)]; } public static string Rendre(string modele, IDictionary<string, string> valeurs, bool feminin) { if (string.IsNullOrEmpty(modele)) { return ""; } return Regex.Replace(Regex.Replace(Jeton.Replace(modele, delegate(Match m) { string value = m.Groups[1].Value; int num = value.IndexOf('/'); if (num >= 0) { if (!feminin) { return value.Substring(0, num); } return value.Substring(num + 1); } if (value == "e") { if (!feminin) { return ""; } return "e"; } if (valeurs != null) { foreach (KeyValuePair<string, string> valeur in valeurs) { if (string.Equals(valeur.Key, value, StringComparison.OrdinalIgnoreCase)) { return valeur.Value ?? ""; } } } return m.Value; }), "\\s{2,}", " "), "\\s+([.,])", "$1").Trim(); } public static int LireCompteur(string valeur) { if (!int.TryParse(valeur, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || result <= 0) { return 0; } return result; } public static string Resume(string nom, int morts, IDictionary<string, int> mortsParCause, int boss, int etoiles1, int etoiles2, bool francais = true) { string text = string.Join(", ", from p in (from p in mortsParCause where p.Value > 0 select new { Texte = Libelle(p.Key, francais), Nombre = p.Value } into p orderby p.Nombre descending select p).ThenBy(p => p.Texte, StringComparer.Ordinal).Take(3) select p.Texte + " x" + p.Nombre); int num = etoiles1 + etoiles2; if (!francais) { return "Saga of " + nom + ": " + Compter(morts, "no deaths", "death", "deaths") + ((text.Length > 0) ? (" (" + text + ")") : "") + " - " + Compter(boss, "no bosses defeated", "boss defeated", "bosses defeated") + " - " + Compter(num, "no starred monsters killed", "starred monster killed", "starred monsters killed") + ((etoiles2 <= 0) ? "" : ((etoiles2 < num) ? (" (" + etoiles2 + " of them with two stars)") : ((num == 1) ? " (with two stars)" : " (all with two stars)"))); } return "Saga " + De(nom) + " : " + Compter(morts, "aucune mort", "mort", "morts") + ((text.Length > 0) ? (" (" + text + ")") : "") + " - " + Compter(boss, "aucun boss vaincu", "boss vaincu", "boss vaincus") + " - " + Compter(num, "aucun monstre étoilé tué", "monstre étoilé tué", "monstres étoilés tués") + ((etoiles2 > 0) ? (" (dont " + etoiles2 + " à deux étoiles)") : ""); } private static string De(string nom) { if (string.IsNullOrEmpty(nom)) { return "de " + nom; } char c = char.ToLowerInvariant(nom[0]); return (("aeiouàáâäåæéèêëíîïóôöøœúùûüý".IndexOf(c) >= 0 || (c == 'y' && nom.Length > 1 && "aeiouàáâäåæéèêëíîïóôöøœúùûüý".IndexOf(char.ToLowerInvariant(nom[1])) < 0)) ? "d'" : "de ") + nom; } private static string Compter(int n, string aucun, string un, string plusieurs) { if (n <= 0) { return aucun; } return n + " " + ((n == 1) ? un : plusieurs); } } }