public static string SmartQuote(this string text, SpeechFilter filter = null) { var ret = new StringBuilder(); var open = false; var quoted = new StringBuilder(); text = text.Replace("...", "\x137"); foreach (var ch in text) { if (ch == '\"') { //ret.Append(open ? '\x139' : '\x138'); if (!open) { quoted.Clear(); open = true; ret.Append('\x138'); } else { var q = quoted.ToString(); if (q.StartsWith("<nofilter>")) { ret.Append(q.Substring(10)); } else if (filter == null) { ret.Append(q); } else { ret.Append(filter(q)); } quoted.Clear(); open = false; ret.Append('\x139'); } } else { if (open) { quoted.Append(ch); } else { ret.Append(ch); } } } return(ret.ToString()); }
public static string Viewpoint(this string message, Character top, Character bottom = null) { #if DEBUG var player = NoxicoGame.Me.Player == null ? null : NoxicoGame.Me.Player.Character; #else var player = NoxicoGame.Me.Player.Character; #endif if (top == null) { top = player; } if (bottom == null) { bottom = top; } //var tIP = player == top; //Definitions used to be here. Now they're defined in i18n.lua. #region WordStructor filter var wordStructFilter = new Func <Token, Character, bool>((filter, who) => { var env = Lua.Environment; env.cultureID = who.Culture.ID; env.culture = who.Culture; env.gender = who.Gender; foreach (var stat in env.stats) { var statName = ((Neo.IronLua.LuaTable)stat.Value)["name"].ToString().ToLowerInvariant(); env[statName] = who.GetStat(statName); } env.pussyAmount = who.HasToken("v****a") ? (who.GetToken("v****a").HasToken("dual") ? 2 : 1) : 0; env.penisAmount = who.HasToken("penis") ? (who.GetToken("penis").HasToken("dual") ? 2 : 1) : 0; env.pussyWetness = who.HasToken("v****a") && who.GetToken("v****a").HasToken("wetness") ? who.GetToken("v****a").GetToken("wetness").Value : 0; env.cumAmount = who.CumAmount; env.slime = who.IsSlime; //return env.DoChunk("return " + filter.Text, "lol.lua").ToBoolean(); return(Lua.Run("return " + filter.Text, env)); }); #endregion #region {} parser var regex = new Regex(@"{(?:{)? (?<first>\w*) (?: \| (?<second>\w*) )? }(?:})?", RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline); message = regex.Replace(message, (match => top == player ? (match.Groups["second"].Success ? match.Groups["second"].Value : string.Empty) : match.Groups["first"].Value)); #endregion #region [] parser regex = new Regex(@" \[ (?:(?<target>[tb\?]{1,2}):)? #Optional target and : (?: #One or more subcommands (?:\:?) #Separating :, optional in case target already had one (?<subcom>[\w\/\-_\{\}]+) #Command )* \]", RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline); var allMatches = regex.Matches(message); while (regex.IsMatch(message)) { message = regex.Replace(message, (match => { var target = bottom; var subcom = match.Groups["subcom"].Captures[0].Value; var parms = new List <string>(); var targetGroup = match.Groups["target"].Value; if (targetGroup.StartsWith('?')) { if (i18n.wordStructor == null) { i18n.wordStructor = Mix.GetTokenTree("wordstructor.tml", true); } if (targetGroup.Length == 2 && "tb".Contains(targetGroup[1])) { target = (targetGroup[1] == 't' ? top : bottom); } Lua.Environment.top = top; Lua.Environment.bottom = bottom; Lua.Environment.target = target; var pToks = wordStructor.Where(x => x.Name == match.Groups["subcom"].Value).ToList(); if (pToks.Count == 0) { return(string.Format("<WordStructor fail: {0}>", match.Groups["subcom"].Value)); } var pTok = pToks.PickWeighted(); //pToks[Random.Next(pToks.Count)]; var pRes = pTok.Tokens.Where(x => !x.HasToken("filter") || wordStructFilter(x.GetToken("filter"), target)).ToList(); //Remove all less-specific options if any specific are found. if (pRes.Any(x => x.HasToken("filter"))) { pRes.RemoveAll(x => !x.HasToken("filter")); } return(pRes.PickOne().Text); } else if (targetGroup.StartsWith('t')) { target = top; } Lua.Environment.isPlayer = (target == player); Lua.Environment.target = target; //subcom = targetGroup; //subcom = match.Groups["subcom"].Captures[0].Value; for (var i = 1; i < match.Groups["subcom"].Captures.Count; i++) { var c = match.Groups["subcom"].Captures[i]; //Console.WriteLine(c); parms.Add(c.Value.Replace('(', '[').Replace(')', ']')); } parms.Add(string.Empty); parms.Add(string.Empty); parms.Add(string.Empty); //if (subcoms.ContainsKey(subcom)) return subcoms[subcom](target, parms); if (SubCommands.ContainsKey(subcom)) { return(SubCommands[subcom](target, parms).ToString()); } return(string.Format("(?{0}?)", subcom)); })); } message = Regex.Replace(message, @"\[\!(?<keybinding>.+?)\]", (match => Toolkit.TranslateKey(match.Groups["keybinding"].Value))); #endregion if (!message.Contains('"')) { return(message); } if (top == null) { return(message); } SpeechFilter speechFilter = top.SpeechFilter; if (speechFilter == null) { if (top.Culture.SpeechFilter != null) { speechFilter = new SpeechFilter(x => { Lua.RunFile(top.Culture.SpeechFilter); x = Lua.Environment.SpeechFilter(x); return(x); }); } if (impediments == null) { impediments = Mix.GetTokenTree("impediments.tml"); } foreach (var impediment in impediments) { var apply = true; foreach (var filter in impediment.Tokens.Where(t => t.Name == "have")) { var f = filter.Text.Split('='); var p = top.Path(f[0]); if (p == null || p.Text != f[1]) { apply = false; break; } } if (apply) { var oldFilter = speechFilter; speechFilter = new SpeechFilter(x => { Lua.RunFile(impediment.GetToken("file").Text); x = Lua.Environment.SpeechFilter(x); return(oldFilter(x)); }); } } if (speechFilter == null) //Still? { speechFilter = new SpeechFilter(x => x); //Then just assign a dummy so we don't do this all over and over again. } top.SpeechFilter = speechFilter; } message = message.SmartQuote(speechFilter); return(message); }