Beispiel #1
0
        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);
        }
Beispiel #2
0
 public override void SaveToFile(BinaryWriter stream)
 {
     Toolkit.SaveExpectation(stream, "PLAY");
     base.SaveToFile(stream);
     stream.Write(PlayingTime.Ticks);
 }
Beispiel #3
0
        public override void Move(Direction targetDirection, SolidityCheck check = SolidityCheck.Walker)
        {
            if (Posture != Posture.Upright)
            {
                NoxicoGame.AddMessage(i18n.GetString("yougetup"));
                Energy -= Posture == Posture.Seated ? 1200 : 2000;
                Posture = Posture.Upright;
                return;
            }

            var lx = XPosition;
            var ly = YPosition;

            check = SolidityCheck.Walker;
            if (Character.IsSlime)
            {
                check = SolidityCheck.DryWalker;
            }
            if (Character.HasToken("flying"))
            {
                check = SolidityCheck.Flyer;
            }

            #region Inter-board travel
            var   n          = NoxicoGame.Me;
            Board otherBoard = null;
            if (ly == 0 && targetDirection == Direction.North && this.ParentBoard.ToNorth > -1)
            {
                otherBoard = n.GetBoard(this.ParentBoard.ToNorth);
                if (this.CanMove(otherBoard, lx, otherBoard.Height - 1, check) != null)
                {
                    return;
                }
                this.YPosition = otherBoard.Height;
                OpenBoard(this.ParentBoard.ToNorth);
            }
            else if (ly == ParentBoard.Height - 1 && targetDirection == Direction.South && this.ParentBoard.ToSouth > -1)
            {
                otherBoard = n.GetBoard(this.ParentBoard.ToSouth);
                if (this.CanMove(otherBoard, lx, 0, check) != null)
                {
                    return;
                }
                this.YPosition = -1;
                OpenBoard(this.ParentBoard.ToSouth);
            }
            else if (lx == 0 && targetDirection == Direction.West && this.ParentBoard.ToWest > -1)
            {
                otherBoard = n.GetBoard(this.ParentBoard.ToWest);
                if (this.CanMove(otherBoard, otherBoard.Width - 1, ly, check) != null)
                {
                    return;
                }
                this.XPosition = otherBoard.Width;
                OpenBoard(this.ParentBoard.ToWest);
            }
            else if (lx == ParentBoard.Width - 1 && targetDirection == Direction.East && this.ParentBoard.ToEast > -1)
            {
                otherBoard = n.GetBoard(this.ParentBoard.ToEast);
                if (this.CanMove(otherBoard, 0, ly, check) != null)
                {
                    return;
                }
                this.XPosition = -1;
                OpenBoard(this.ParentBoard.ToEast);
            }
            #endregion

            if (Character.HasToken("tutorial"))
            {
                Character.GetToken("tutorial").Value++;
            }

            var newX = this.XPosition;
            var newY = this.YPosition;
            Toolkit.PredictLocation(newX, newY, targetDirection, ref newX, ref newY);
            foreach (var entity in ParentBoard.Entities.Where(x => x.XPosition == newX && x.YPosition == newY))
            {
                if (entity.Blocking)
                {
                    NoxicoGame.ClearKeys();
                    if (entity is BoardChar)
                    {
                        var bc = (BoardChar)entity;
                        if (bc.Character.HasToken("hostile") || (bc.Character.HasToken("teambehavior") && bc.Character.DecideTeamBehavior(Character, TeamBehaviorClass.Attacking) != TeamBehaviorAction.Nothing))
                        {
                            //Strike at your foes!
                            AutoTravelling = false;
                            MeleeAttack(bc);
                            EndTurn();
                            return;
                        }
                        if (!bc.OnPlayerBump.IsBlank())
                        {
                            bc.RunScript(bc.OnPlayerBump);
                            return;
                        }
                        //Displace!
                        NoxicoGame.AddMessage(i18n.Format("youdisplacex", bc.Character.GetKnownName(false, false, true)), bc.GetEffectiveColor());
                        bc.XPosition = this.XPosition;
                        bc.YPosition = this.YPosition;
                    }
                }
            }
            base.Move(targetDirection, check);
            ParentBoard.AimCamera(XPosition, YPosition);

            EndTurn();

            if (Character.HasToken("squishy") || (Character.Path("skin/type") != null && Character.Path("skin/type").Text == "slime"))
            {
                NoxicoGame.Sound.PlaySound("set://Squish");
            }
            else
            {
                NoxicoGame.Sound.PlaySound("set://Step");
            }

            if (lx != XPosition || ly != YPosition)
            {
                ParentBoard.UpdateLightmap(this, true);
                this.DijkstraMap.Hotspots[0] = new Point(XPosition, YPosition);
                this.DijkstraMap.Update();
            }
            else if (AutoTravelling)
            {
                AutoTravelling = false;
#if DEBUG
                NoxicoGame.AddMessage("* TEST: couldn't go any further. *");
#endif
            }

            NoxicoGame.ContextMessage = null;
            if (OnWarp())
            {
                NoxicoGame.ContextMessage = i18n.GetString("context_warp");
            }
            else if (ParentBoard.Entities.OfType <DroppedItem>().FirstOrDefault(c => c.XPosition == XPosition && c.YPosition == YPosition) != null)
            {
                NoxicoGame.ContextMessage = i18n.GetString("context_droppeditem");
            }
            else if (ParentBoard.Entities.OfType <Container>().FirstOrDefault(c => c.XPosition == XPosition && c.YPosition == YPosition) != null)
            {
                if (ParentBoard.Entities.OfType <Container>().FirstOrDefault(c => c.XPosition == XPosition && c.YPosition == YPosition).Token.HasToken("corpse"))
                {
                    NoxicoGame.ContextMessage = i18n.GetString("context_corpse");
                }
                else
                {
                    NoxicoGame.ContextMessage = i18n.GetString("context_container");
                }
            }
            //else if (ParentBoard.Entities.OfType<Clutter>().FirstOrDefault(c => c.XPosition == XPosition && c.YPosition == YPosition && c.Glyph == 0x147) != null)
            else if (ParentBoard.Entities.OfType <Clutter>().FirstOrDefault(c => c.XPosition == XPosition && c.YPosition == YPosition && c.DBRole == "bed") != null)
            {
                NoxicoGame.ContextMessage = i18n.GetString("context_bed");
            }
            if (NoxicoGame.ContextMessage != null)
            {
                NoxicoGame.ContextMessage = Toolkit.TranslateKey(KeyBinding.Activate, false, false) + " - " + NoxicoGame.ContextMessage;
            }
        }
Beispiel #4
0
        public override void Update()
        {
            //base.Update();
            if (NoxicoGame.Mode != UserMode.Walkabout)
            {
                return;
            }

            //START
            if (NoxicoGame.IsKeyDown(KeyBinding.Pause) || Vista.Triggers == XInputButtons.Start)
            {
                NoxicoGame.ClearKeys();
                Pause.Open();
                return;
            }

            var increase = 200 + (int)Character.GetStat("speed");

            if (Character.HasToken("haste"))
            {
                increase *= 2;
            }
            else if (Character.HasToken("slow"))
            {
                increase /= 2;
            }
            Energy += increase;
            if (Energy < 5000)
            {
                var wasNight = Toolkit.IsNight();

                NoxicoGame.InGameTime = NoxicoGame.InGameTime.AddMilliseconds(increase);

                if (wasNight && !Toolkit.IsNight())
                {
                    ParentBoard.UpdateLightmap(this, true);
                    ParentBoard.Redraw();
                }
                EndTurn();
                return;
            }
            else
            {
                if (!NoxicoGame.PlayerReady)
                {
                    NoxicoGame.AgeMessages();
                }
                NoxicoGame.PlayerReady = true;
                Energy = 5000;
            }

            CheckForTimedItems();
            CheckForCopiers();
            if (Character.UpdateSex())
            {
                return;
            }

            var sleeping = Character.Path("sleeping");

            if (sleeping != null)
            {
                Character.Heal(2);
                sleeping.Value--;
                if (sleeping.Value <= 0)
                {
                    Character.RemoveToken("sleeping");
                    Character.RemoveToken("helpless");
                    NoxicoGame.AddMessage(i18n.GetString("yougetup"));
                }
                NoxicoGame.InGameTime = NoxicoGame.InGameTime.AddMinutes(5);
                EndTurn();
                return;                 //07-04-13 no more sleepwalking
            }

            var helpless = Character.HasToken("helpless");

            if (helpless)
            {
                if (Random.NextDouble() < 0.05)
                {
                    Character.Heal(2);
                    NoxicoGame.AddMessage(i18n.GetString("yougetup"));
                    Character.RemoveToken("helpless");
                    helpless = false;
                }
            }
            var flying = Character.HasToken("flying");

#if DEBUG
            if (NoxicoGame.KeyMap[Keys.Z])
            {
                NoxicoGame.ClearKeys();
                NoxicoGame.InGameTime = NoxicoGame.InGameTime.AddMinutes(30);
            }
#endif
            //Pause menu moved up so you can pause while <5000.

            //RIGHT
            if ((NoxicoGame.IsKeyDown(KeyBinding.Travel) || Vista.Triggers == XInputButtons.RightShoulder))
            {
                NoxicoGame.ClearKeys();
                if (!this.ParentBoard.AllowTravel)
                {
                    if (this.ParentBoard.BoardType == BoardType.Dungeon)
                    {
                        NoxicoGame.AddMessage(i18n.GetString("travel_notfromdungeon"));
                    }
                    else
                    {
                        NoxicoGame.AddMessage(i18n.GetString("travel_notfromwilds"));
                    }
                    return;
                }
                Travel.Open();
                return;
            }

            //LEFT
            if (NoxicoGame.IsKeyDown(KeyBinding.Rest) || Vista.Triggers == XInputButtons.LeftShoulder)
            {
                NoxicoGame.ClearKeys();
                Energy -= 1000;
                EndTurn();
                return;
            }

            //GREEN
            if (NoxicoGame.IsKeyDown(KeyBinding.Interact) || Vista.Triggers == XInputButtons.A)
            {
                NoxicoGame.ClearKeys();
                //NoxicoGame.Messages.Add("[Aim message]");
                NoxicoGame.Mode = UserMode.Aiming;
                NoxicoGame.Cursor.ParentBoard = this.ParentBoard;
                NoxicoGame.Cursor.XPosition   = this.XPosition;
                NoxicoGame.Cursor.YPosition   = this.YPosition;
                NoxicoGame.Cursor.PopulateTabstops();
                NoxicoGame.Cursor.Point();
                if (Character.HasToken("tutorial") && !Character.GetToken("tutorial").HasToken("interactmode"))
                {
                    Character.GetToken("tutorial").AddToken("dointeractmode");
                    NoxicoGame.CheckForTutorialStuff();
                }
                return;
            }

            //BLUE
            if (NoxicoGame.IsKeyDown(KeyBinding.Items) || Vista.Triggers == XInputButtons.X)
            {
                NoxicoGame.ClearKeys();
                NoxicoGame.Mode      = UserMode.Subscreen;
                NoxicoGame.Subscreen = Inventory.Handler;
                Subscreens.FirstDraw = true;
                return;
            }

            //YELLOW
            if ((NoxicoGame.IsKeyDown(KeyBinding.Fly) || Vista.Triggers == XInputButtons.Y) && !helpless)
            {
                NoxicoGame.ClearKeys();
                if (Character.HasToken("flying"))
                {
                    LandFromFlight();
                }
                else
                {
                    if (Character.HasToken("hover"))
                    {
                        if (Character.GetToken("wings").HasToken("small"))
                        {
                            NoxicoGame.AddMessage(i18n.GetString("wingsaretoosmall"));
                            return;
                        }
                        var tile = ParentBoard.Tilemap[XPosition, YPosition];
                        if (tile.Definition.Ceiling)
                        {
                            if (Character.GetStat("mind") < 10 ||
                                (Character.GetStat("mind") < 20 && Random.NextDouble() < 0.5))
                            {
                                Hurt(2, "death_crackedagainstceiling", null, false);
                                NoxicoGame.AddMessage(i18n.GetString("hittheceiling"));
                            }
                            else
                            {
                                NoxicoGame.AddMessage(i18n.GetString("cantflyinside"));
                            }
                            return;
                        }
                        //Take off
                        Character.AddToken("flying").Value = 100;
                        NoxicoGame.AddMessage(i18n.GetString("youfly"));
                        return;
                    }
                    NoxicoGame.AddMessage(i18n.GetString("flyneedswings"));
                }
                return;
            }

            //RED
            if ((NoxicoGame.IsKeyDown(KeyBinding.Activate) || Vista.Triggers == XInputButtons.B) && !helpless && !flying)
            {
                NoxicoGame.ClearKeys();

                if (OnWarp())
                {
                    CheckWarps();
                }

                var container = ParentBoard.Entities.OfType <Container>().FirstOrDefault(c => c.XPosition == XPosition && c.YPosition == YPosition);
                if (container != null)
                {
                    NoxicoGame.ClearKeys();
                    ContainerMan.Setup(container);
                    return;
                }

                //Find dropped items
                var itemsHere = DroppedItem.GetItemsAt(ParentBoard, XPosition, YPosition);
                if (itemsHere.Count == 1)
                {
                    var drop = itemsHere[0];
                    if (drop != null)
                    {
                        drop.Take(this.Character, ParentBoard);
                        NoxicoGame.Me.Player.Energy -= 1000;
                        NoxicoGame.AddMessage(i18n.Format("youpickup_x", drop.Item.ToString(drop.Token, true)));
                        NoxicoGame.Sound.PlaySound("set://GetItem");
                        ParentBoard.Redraw();
                        return;
                    }
                }
                else if (itemsHere.Count > 1)
                {
                    DroppedItem.PickItemsFrom(itemsHere);
                    return;
                }

                //Find bed
                //var bed = ParentBoard.Entities.OfType<Clutter>().FirstOrDefault(c => c.XPosition == XPosition && c.YPosition == YPosition && c.Glyph == 0x147);
                var bed = ParentBoard.Entities.OfType <Clutter>().FirstOrDefault(c => c.XPosition == XPosition && c.YPosition == YPosition && c.DBRole == "bed");
                if (bed != null)
                {
                    Character.Posture = Posture.Prone;
                    var prompt  = "It's " + NoxicoGame.InGameTime.ToShortTimeString() + ", " + NoxicoGame.InGameTime.ToLongDateString() + ". Sleep for how long?";
                    var options = new Dictionary <object, string>();
                    foreach (var interval in new[] { 1, 2, 4, 8, 12 })
                    {
                        options[interval] = Toolkit.Count(interval).Titlecase() + (interval == 1 ? " hour" : " hours");
                    }
                    options[-1] = "Cancel";
                    MessageBox.List(prompt, options, () =>
                    {
                        if ((int)MessageBox.Answer != -1)
                        {
                            Character.AddToken("helpless");
                            Character.AddToken("sleeping").Value = (int)MessageBox.Answer * 12;
                        }
                    }, true, true, i18n.GetString("Bed"));
                }

                //TODO: find chair, allow sitting in 'em.
                return;
            }

#if DEBUG
            if (NoxicoGame.KeyMap[Keys.F3])
            {
                NoxicoGame.ClearKeys();
                ParentBoard.DumpToHtml(string.Empty);
                NoxicoGame.AddMessage("Board dumped.");
                return;
            }
#endif
            if (helpless)
            {
                EndTurn();
                return;
            }

            if (!AutoTravelling)
            {
                if (NoxicoGame.IsKeyDown(KeyBinding.Left) || Vista.DPad == XInputButtons.Left)
                {
                    this.Move(Direction.West);
                }
                else if (NoxicoGame.IsKeyDown(KeyBinding.Right) || Vista.DPad == XInputButtons.Right)
                {
                    this.Move(Direction.East);
                }
                else if (NoxicoGame.IsKeyDown(KeyBinding.Up) || Vista.DPad == XInputButtons.Up)
                {
                    this.Move(Direction.North);
                }
                else if (NoxicoGame.IsKeyDown(KeyBinding.Down) || Vista.DPad == XInputButtons.Down)
                {
                    this.Move(Direction.South);
                }
                //And now, attempting to fire a long range weapon in a cardinal.
                else if (NoxicoGame.IsKeyDown(KeyBinding.ShootLeft))
                {
                    this.QuickFire(Direction.West);
                }
                else if (NoxicoGame.IsKeyDown(KeyBinding.ShootRight))
                {
                    this.QuickFire(Direction.East);
                }
                else if (NoxicoGame.IsKeyDown(KeyBinding.ShootUp))
                {
                    this.QuickFire(Direction.North);
                }
                else if (NoxicoGame.IsKeyDown(KeyBinding.ShootDown))
                {
                    this.QuickFire(Direction.South);
                }
            }
            else
            {
                if (NoxicoGame.IsKeyDown(KeyBinding.Left) || NoxicoGame.IsKeyDown(KeyBinding.Right) || NoxicoGame.IsKeyDown(KeyBinding.Up) || NoxicoGame.IsKeyDown(KeyBinding.Down))                //(NoxicoGame.KeyMap[(int)Keys.Left] || NoxicoGame.KeyMap[(int)Keys.Right] || NoxicoGame.KeyMap[(int)Keys.Up] || NoxicoGame.KeyMap[(int)Keys.Down])
                {
                    AutoTravelling = false;
                    return;
                }
                var x   = XPosition;
                var y   = YPosition;
                var dir = Direction.North;
                if (AutoTravelMap.RollDown(y, x, ref dir))
                {
                    Move(dir);
                }
                else
                {
                    AutoTravelling = false;
                    if ((int)AutoTravelLeave > -1)
                    {
                        this.Move(AutoTravelLeave);
                    }
                }
            }
        }
Beispiel #5
0
        public static void Open()
        {
            var host   = NoxicoGame.HostForm;
            var nox    = host.Noxico;
            var player = nox.Player.Character;

            var hpNow  = player.Health;
            var hpMax  = player.MaximumHealth;
            var health = hpNow + " / " + hpMax;

            if (hpNow <= hpMax / 4)
            {
                health = "<cRed>" + health + "<cSilver>";
            }
            else if (hpNow <= hpMax / 2)
            {
                health = "<cYellow>" + health + "<cSilver>";
            }

            var sb = new StringBuilder();

            sb.AppendLine(i18n.GetString("pause_name").PadEffective(20) + player.Name);
            sb.AppendLine(i18n.GetString("pause_gender").PadEffective(20) + player.Gender);
            sb.AppendLine(i18n.GetString("pause_health").PadEffective(20) + health);
            sb.AppendLine(i18n.GetString("pause_money").PadEffective(20) + player.GetToken("money").Value.ToString("C"));
            sb.AppendLine(i18n.GetString("pause_playtime").PadEffective(20) + nox.Player.PlayingTime.ToString());
            sb.AppendLine(i18n.GetString("pause_worldtime").PadEffective(20) + NoxicoGame.InGameTime.ToString());
            sb.AppendLine();

            player.RecalculateStatBonuses();
            player.CheckHasteSlow();
            foreach (var stat in Lua.Environment.stats)
            {
                if (stat.Value.panel == null)
                {
                    continue;
                }
                string properName = stat.Value.name.ToString();
                string statName   = properName.ToLowerInvariant();
                if (!player.HasToken(statName))
                {
                    sb.AppendLine(properName.PadEffective(20) + "<cGray>-?-");
                }
                else
                {
                    var bonus     = string.Empty;
                    var statBonus = player.GetToken(statName + "bonus").Value;
                    var statBase  = player.GetToken(statName).Value;
                    var total     = statBase + statBonus;
                    if (statBonus > 0)
                    {
                        bonus = "<cGray> (" + statBase + "+" + statBonus + ")<cSilver>";
                    }
                    else if (statBonus < 0)
                    {
                        bonus = "<cFirebrick> (" + statBase + "-" + (-statBonus) + ")<cSilver>";
                    }
                    sb.AppendLine(properName.PadEffective(20) + total + bonus);
                }
            }

            pages[i18n.GetString("pause_charstats")] = sb.ToString();

            sb.Clear();
            foreach (var skill in player.GetToken("skills").Tokens)
            {
                if ((int)skill.Value > 0)
                {
                    var skillName = i18n.GetString("skill_" + skill.Name);
                    if (skillName[0] == '[')                     //Ignore missing skill translations for now.
                    {
                        skillName = skillName.Substring(7, skillName.Length - 8);
                    }
                    sb.AppendLine(skillName.Replace('_', ' ').Titlecase().PadEffective(30) + ((int)skill.Value).ToString());
                }
            }
            pages[i18n.GetString("pause_skills")] = sb.ToString();

            sb.Clear();
            for (var i = 0; i < 4; i++)
            {
                sb.Append(Toolkit.TranslateKey((KeyBinding)i));
            }
            sb.AppendLine("         - " + i18n.GetString("pause_keymove"));
            sb.AppendLine(Toolkit.TranslateKey(KeyBinding.Interact, true).PadEffective(12) + " - " + i18n.GetString("pause_keyinteract"));
            sb.AppendLine(Toolkit.TranslateKey(KeyBinding.Activate, true).PadEffective(12) + " - " + i18n.GetString("pause_keyactivate"));
            sb.AppendLine(Toolkit.TranslateKey(KeyBinding.Rest, true).PadEffective(12) + " - " + i18n.GetString("pause_keyrest"));
            sb.AppendLine(Toolkit.TranslateKey(KeyBinding.Fly, true).PadEffective(12) + " - " + i18n.GetString("pause_keyfly"));
            sb.AppendLine(Toolkit.TranslateKey(KeyBinding.Items, true).PadEffective(12) + " - " + i18n.GetString("pause_keyitems"));
            sb.AppendLine(Toolkit.TranslateKey(KeyBinding.Travel, true).PadEffective(12) + " - " + i18n.GetString("pause_keytravel"));
            sb.AppendLine(Toolkit.TranslateKey(KeyBinding.Accept, true).PadEffective(12) + " - " + i18n.GetString("pause_keyaccept"));
            sb.AppendLine(Toolkit.TranslateKey(KeyBinding.Back, true).PadEffective(12) + " - " + i18n.GetString("pause_keyback"));
            pages[i18n.GetString("pause_keys1")] = sb.ToString();
            sb.Clear();
            sb.AppendLine(Toolkit.TranslateKey(KeyBinding.Pause, true).PadEffective(8) + " - " + i18n.GetString("pause_keypause"));
#if DEBUG
            sb.AppendLine(Toolkit.TranslateKey(System.Windows.Forms.Keys.F3, true).PadEffective(8) + " - Dump board to HTML (debug only)");
#endif
            sb.AppendLine(Toolkit.TranslateKey(KeyBinding.Screenshot, true).PadEffective(8) + " - " + i18n.GetString("pause_keyscreenshot"));
            pages[i18n.GetString("pause_keys2")] = sb.ToString();

#if DEBUG
            var entities = 0;
            var tokens   = 0;
            foreach (var x in nox.Boards.Where(x => x != null))
            {
                if (x == null)
                {
                    continue;
                }
                entities += x.Entities.Count;
                foreach (var c in x.Entities.OfType <BoardChar>())
                {
                    tokens += c.Character.Tokens.Count;
                    foreach (var t in c.Character.Tokens)
                    {
                        tokens += CountTokens(t);
                    }
                }
            }
            ;
            NoxicoGame.KnownItems.ForEach(x =>
            {
                tokens += x.Tokens.Count;
                foreach (var t in x.Tokens)
                {
                    tokens += CountTokens(t);
                }
            });

            pages[i18n.GetString("pause_memstats")] = i18n.Format("pause_memstatscontent",
                                                                  nox.Boards.Count.ToString("G"),
                                                                  nox.Boards.Where(b => b != null).Count().ToString("G"),
                                                                  NoxicoGame.KnownItems.Count.ToString("G"),
                                                                  entities.ToString("G"),
                                                                  tokens.ToString("G"));
#endif

            if (!IniFile.GetValue("misc", "rememberpause", true))
            {
                page = 0;
            }

            NoxicoGame.Subscreen = Handler;
            NoxicoGame.Mode      = UserMode.Subscreen;
            Subscreens.FirstDraw = true;
            NoxicoGame.ClearKeys();
        }