public FlashTreasureHunt.ScoreTag[] GetScoreValues()
        {
            var a = CoPlayers.Select(k => new FlashTreasureHunt.ScoreTag
            {
                Kills = k.Kills,
                Name  = k.Identity.name,
                Score = k.Score
            }).ToArray();

            Map.WriteLine("scoretable length: " + a.Length);

            return(a);
        }
Beispiel #2
0
        public Game()
            : base(DefaultWidth, DefaultHeight)
        {
            InitializeRoutedActions();
            InitializeSharedState();

            SoundEnabled = true;

            Action <Sound> play =
                s =>
            {
                if (CanvasOverlay.parent == null)
                {
                    return;
                }

                if (SoundEnabled)
                {
                    s.play();
                }
            };

            var Menu = new MenuSprite(DefaultWidth).AttachTo(base.InfoOverlay);

            Menu.TextExternalLink2.htmlText = LinkPlayMoreGames;

            var DefenseY = 420;

            #region DebugDump
            var DebugDump = new DebugDumpTextField();

            DebugDump.Field.y = DefaultHeight / 4;
            DebugDump.Field.x = 0;

            DebugDump.Field.width  = DefaultWidth;
            DebugDump.Field.height = DefaultHeight / 2;

            DebugDump.Visible.ValueChangedToTrue +=
                delegate
            {
                Menu.TextExternalLink2.htmlText = LinkPoweredByJSC;
                DebugDump.Field.AttachToBefore(BorderOverlay);
                DebugDump.DebugDumpUpdate();
            };

            DebugDump.Visible.ValueChangedToFalse +=
                delegate
            {
                Menu.TextExternalLink2.htmlText = LinkPlayMoreGames;
            };
            #endregion

            RoutedActions.SendTextMessage.Direct =
                e => DebugDump.Write(new { Message = e });

            this.Statusbar = new Statusbar();

            Statusbar.Lives.Value = 3;
            Statusbar.Score.Value = 0;

            Statusbar.Element.AttachTo(InfoOverlay);

            var MenuFader = new DualFader {
                Value = Menu
            };



            #region common keys
            this.InvokeWhenStageIsReady(
                delegate
            {
                stage.click +=
                    delegate
                {
                    if (MenuFader.Value != CanvasOverlay)
                    {
                        MenuFader.Value = CanvasOverlay;
                    }
                };


                stage.keyUp +=
                    e =>
                {
                    if (e.keyCode == Keyboard.ENTER)
                    {
                        MenuFader.Value = CanvasOverlay;
                    }

                    if (e.keyCode == Keyboard.ESCAPE)
                    {
                        MenuFader.Value = Menu;
                    }

                    if (e.keyCode == Keyboard.T)
                    {
                        DebugDump.Visible.Toggle();
                    }

                    if (e.keyCode == Keyboard.M)
                    {
                        SoundEnabled = !SoundEnabled;
                    }

                    if (e.keyCode == Keyboard.C)
                    {
                        play(Sounds.miu);

                        foreach (var v in cloud1.Members)
                        {
                            DebugDump.Write(new { v.Element.x, v.Element.y });
                        }

                        DebugDump.Write(new { PlaysSurvived = this.PlaysSurvived.Value });
                    }
                };
            }
                );

            #endregion



            this.Ego = new PlayerShip(DefaultWidth, DefaultHeight)
            {
                Name = "Ego"
            };

            // addding our entities to list ensures we know under what id to send them
            this.Ego.AddTo(this.SharedState.LocalObjects);
            this.Ego.GoodEgo.AddTo(this.SharedState.LocalObjects);
            this.Ego.EvilEgo.AddTo(this.SharedState.LocalObjects);

            // our ego cannot be hit while the menu is showing
            this.Ego.GodMode.ValueChangedTo +=
                GodMode => DebugDump.Write(new { GodMode });

            // MenuFader.ValueChangedTo += e => this.Ego.GodMode.Value = e == Menu;
            // this.Ego.GodMode.Value = true;



            var ReportedScore = 0;

            #region lives and gameover

            Action <StarShip> ApplyEgoRespawn =
                xego =>
            {
                var WaitingForRespawn = false;

                xego.IsAlive.ValueChangedToFalse +=
                    delegate
                {
                    if (WaitingForRespawn)
                    {
                        return;
                    }

                    WaitingForRespawn = true;

                    this.ApplyFilter(Filters.GrayScaleFilter);
                    this.RoutedActions.SendTextMessage.Direct("waiting for respawn...");

                    if (PlayerInput != null)
                    {
                        PlayerInput.Enabled.Value = false;
                    }

                    Statusbar.Lives.Value--;

                    if (Statusbar.Lives <= 0)
                    {
                        var ScoreMinStep = this.Statusbar.Score.Value / 30;

                        100.AtInterval(
                            t =>
                        {
                            var v = Math.Max((this.Statusbar.Score.Value - ScoreMinStep), 0);

                            Statusbar.Score.Value = v;

                            if (v == 0)
                            {
                                t.stop();
                            }
                        }
                            );
                    }

                    3100.AtDelayDo(
                        delegate
                    {
                        this.RoutedActions.SendTextMessage.Direct("respawn!");


                        if (Statusbar.Lives == 0)
                        {
                            Statusbar.Lives.Value = 3;
                            Statusbar.Score.Value = 0;
                            PlaysSurvived.Value   = 0;
                        }



                        if (Statusbar.Score.Value > 0)
                        {
                            this.RoutedActions.AddRankingScore.Chained(Statusbar.Score.Value - ReportedScore);

                            ReportedScore = Statusbar.Score.Value;
                        }

                        WaitingForRespawn = false;

                        this.RoutedActions.RestoreStarship.Chained(xego);

                        this.filters = null;

                        if (PlayerInput != null)
                        {
                            PlayerInput.Enabled.Value = true;
                        }

                        play(Sounds.insertcoin);
                    }
                        );
                };
            };


            ApplyEgoRespawn(this.Ego.GoodEgo);
            ApplyEgoRespawn(this.Ego.EvilEgo);

            #endregion


            #region input
            RoutedActions.DoPlayerMovement.Direct +=
                (e, p) =>
            {
                e.GoodEgo.MoveToTarget.Value = p;
            };

            Action <double, double> DoEgoPlayerMovement =
                (arc, length) =>
                RoutedActions.DoPlayerMovement.Chained(Ego, Ego.GoodEgo.ToPoint().MoveToArc(arc, Ego.GoodEgo.MaxStep * length));

            this.RoutedActions.RestoreStarship.Direct =
                s =>
            {
                DebugDump.Write("restore starship: " + s.Name);


                s.GodMode.Value = true;
                s.TakeDamage(0);
                s.ApplyFilter(new BlurFilter());
                s.alpha = 1;

                2000.AtDelayDo(
                    delegate
                {
                    s.GodMode.Value = false;
                    s.filters       = null;

                    if (this.CoPlayers.Any(k => s == k.GoodEgo))
                    {
                        s.ApplyFilter(Filters.ColorFillFilter(0xff));
                    }
                }
                    );
            };

            this.InvokeWhenStageIsReady(
                delegate
            {
                PlayerInput = new PlayerInput(stage, Ego, this)
                {
                    StepLeft    = () => DoEgoPlayerMovement(Math.PI, 2),
                    StepLeftEnd = () => DoEgoPlayerMovement(Math.PI, 0.5),

                    StepRight    = () => DoEgoPlayerMovement(0, 2),
                    StepRightEnd = () => DoEgoPlayerMovement(0, 0.5),

                    FireBullet = () => Ego.FireBullet(),

                    SmartMoveTo = (x, y) =>
                    {
                        // ignore mouse while out of bounds
                        if (x < 0)
                        {
                            return;
                        }

                        if (x > DefaultWidth)
                        {
                            return;
                        }

                        RoutedActions.DoPlayerMovement.Chained(Ego, new Point(Ego.Wrapper(x, y), Ego.GoodEgoY));
                    }
                };

                PlayerInput.Enabled.ValueChangedTo +=
                    InputEnabled =>
                {
                    DebugDump.Write(new { InputEnabled });
                };
            }
                );
            #endregion

            this.GroupEnemies.Add(this.Ego.EvilEgo);

            // hide menu for fast start
            // MenuFader.Value = CanvasOverlay;

            this.PlaysSurvived.ValueChangedTo +=
                PlaysSurvived => DebugDump.Write(new { PlaysSurvived });

            this.PlaysSurvived.ValueChangedTo +=
                PlaysSurvived =>
            {
                if (PlaysSurvived == 5)
                {
                    this.RoutedActions.AddAchivementFiver.ChainedOnce();
                }

                if (PlaysSurvived == 1)
                {
                    this.RoutedActions.AddAchivementFirst.ChainedOnce();
                }
            };


            const int ClipMargin = 20;

            #region evilmode

            this.Ego.EvilMode.ValueChangedToTrue +=
                delegate
            {
                play(Sounds.fade);

                #region keep ego here for 10 secs

                this.Ego.GoodEgo.Clip =
                    p =>
                {
                    if (p.x < DefaultWidth / 2)
                    {
                        p.x = Math.Min(p.x, -ClipMargin);
                    }
                    else
                    {
                        p.x = Math.Max(p.x, DefaultWidth + ClipMargin);
                    }

                    return(p);
                };

                5000.AtDelayDo(
                    delegate
                {
                    this.Ego.GoodEgo.Clip = null;
                    play(Sounds.fade);
                }
                    );
                #endregion
            };

            this.Ego.EvilMode.ValueChangedToFalse +=
                delegate
            {
                play(Sounds.insertcoin);
            };

            #endregion

            this.Ego.EvilMode.LinkTo(Statusbar.EvilMode);

            #region evilmode indicator
            this.Ego.EvilMode.ValueChangedToTrue +=
                delegate
            {
                this.filters = new[] { Filters.RedChannelFilter };
            };

            this.Ego.EvilMode.ValueChangedToFalse +=
                delegate
            {
                this.filters = null;
            };
            #endregion

            this.Ego.GoodEgo.FireBullet = RoutedActions.FireBullet;
            this.Ego.GoodEgo.AttachTo(CanvasOverlay);

            this.Ego.EvilEgo.FireBullet = RoutedActions.FireBullet;
            this.Ego.EvilEgo.AttachTo(CanvasOverlay);

            #region  build shared defense buildings
            for (int i = 0; i < 4; i++)
            {
                var offset = DefaultWidth * (i * 2 + 1) / 8;


                foreach (var v in DefenseBlock.CreateDefenseArray(offset, DefenseY))
                {
                    v.AttachTo(CanvasOverlay);
                    v.AddTo(DefenseBlocks);
                    v.AddTo(FragileEntities.Items);

                    // defense blocks like invaders cloud are shared
                    this.SharedState.SharedObjects.Add(v);
                }
            }
            #endregion


            Ego.AddTo(FragileEntities);

            #region Create and Move CoPlayer

            RoutedActions.CreateCoPlayer.Direct =
                (user, handler) =>
            {
                var cp1 = new PlayerShip(DefaultWidth, DefaultHeight)
                {
                    Name = "CoPlayer"
                }.AddTo(CoPlayers);

                cp1.GoodEgo.AttachTo(CanvasOverlay);
                cp1.EvilEgo.AttachTo(CanvasOverlay);

                // we are adding remote controlled objects
                cp1.AddTo(this.SharedState.RemoteObjects[user]);

                cp1.GoodEgo.AddTo(this.SharedState.RemoteObjects[user]);
                cp1.EvilEgo.AddTo(this.SharedState.RemoteObjects[user]);

                // group as enemies
                cp1.EvilEgo.AddTo(this.GroupEnemies);
                cp1.GoodEgo.ApplyFilter(Filters.ColorFillFilter(0xff));
                cp1.AddTo(FragileEntities);

                handler(cp1);

                // this entity only moves when that player wants to move...

                // yet we might need to notify of damage
            };

            RoutedActions.RemoveCoPlayer.Direct =
                user =>
            {
                var CoPlayer = (PlayerShip)this.SharedState.RemoteObjects[user][0];

                this.SharedState.RemoteObjects[user].Clear();

                CoPlayers.Remove(CoPlayer);

                CoPlayer.EvilEgo.Orphanize();
                CoPlayer.GoodEgo.Orphanize();

                GroupEnemies.Remove(CoPlayer.EvilEgo);

                CoPlayer.EvilEgo.RemoveFrom(FragileEntities.Items);
                CoPlayer.GoodEgo.RemoveFrom(FragileEntities.Items);
            };

            RoutedActions.MoveCoPlayer.Direct =
                (ego, p) =>
            {
                ego.GoodEgo.TweenMoveTo(p.x, p.y);
            };

            #endregion



            #region AddEnemy
            RoutedActions.AddEnemy.Direct +=
                (e, p) =>
            {
                e.Name = "Enemy";

                e.TeleportTo(p.x, p.y)
                .AttachTo(CanvasOverlay)
                .AddTo(FragileEntities.Items)
                .AddTo(GroupEnemies);
            };
            #endregion

            #region cloud
            cloud1 = new EnemyCloud
            {
                PlaySound = play
            };

            cloud1.Members.ForEach(
                m =>
            {
                // if a cloud member fires, it will go across network...
                m.Element.FireBullet = RoutedActions.FireBullet;

                this.SharedState.SharedObjects.Add(m.Element);

                // we are adding enemies over network - but they actually are shared objects
                RoutedActions.AddEnemy.Chained(m.Element, m.Element.ToPoint());
            }
                );

            cloud1.TickSounds =
                new Sound[] {
                Sounds.duh0,
                Sounds.duh1,
                Sounds.duh2,
                Sounds.duh3,
            };

            cloud1.AttachTo(this.CanvasOverlay);



            cloud1.TickInterval.ValueChangedTo +=
                e => DebugDump.Write(new { TickInterval = e });



            //var CloudSpeedAcc = 1.04;
            //var CloudSpeed = 12.0;
            //var CloudMove = new Point();

            Action ResetCloudLocal =
                delegate
            {
                cloud1.Speed      = 12;
                cloud1.NextMove.x = cloud1.Speed;
                cloud1.NextMove.y = 0;



                cloud1.TeleportTo(60, 80);
                cloud1.TickInterval.Value = 1000;

                // rebuild defense

                foreach (var v in DefenseBlocks)
                {
                    v.alpha = 1;
                }

                foreach (var v in KnownEgos)
                {
                    v.GoodEgo.alpha = 1;
                    v.EvilEgo.alpha = 1;
                }
            };

            ResetCloudLocal();

            bool ResetCloudSoonDisabled = false;

            RoutedActions.KillAllInvaders.Direct =
                delegate
            {
                cloud1.Members.ForEach(m => m.Element.alpha = 0);
            };

            Action ResetCloudSoon =
                delegate
            {
                if (ResetCloudSoonDisabled)
                {
                    return;
                }

                ResetCloudSoonDisabled = true;

                RoutedActions.KillAllInvaders.Chained();

                // do not count evil mode
                if (!Ego.EvilMode)
                {
                    PlaysSurvived.Value++;
                }

                cloud1.TickInterval.Value = 0;
                cloud1.TeleportTo(60, 80);

                cloud1.Speed      = 12;
                cloud1.NextMove.x = cloud1.Speed;
                cloud1.NextMove.y = 0;


                3000.AtDelayDo(
                    delegate
                {
                    cloud1.ResetColors();

                    ResetCloudLocal();

                    cloud1.ResetLives();

                    ResetCloudSoonDisabled = false;
                }
                    );
            };


            cloud1.Tick +=
                delegate
            {
                var r = cloud1.Warzone;

                if (r == null)
                {
                    ResetCloudSoon();

                    return;
                }

                //this.graphics.clear();
                //this.graphics.beginFill(0xffffff);
                //this.graphics.drawRect(r.x, r.y, r.width, r.height);

                //DebugDump.Write(new { r.left, r.right, cloud1.FrontRow.Length });

                if (r.bottom > DefenseY)
                {
                    ResetCloudSoon();

                    return;
                }

                var Skip = 4 * (CoPlayers.Count + 1);

                if (cloud1.Counter % Skip == 0)
                {
                    // fire some bullets
                    var rr = cloud1.FrontRow.Random();

                    // invaders bullets should have different sound or be silent
                    rr.Element.FireBulletChained(1, new Point(rr.Element.x, rr.Element.y), new Point(rr.Element.x, DefaultHeight), Ego.GoodEgoY);

                    //rb.Silent = true;

                    //AddBullet.Chained(
                    //    rb
                    //);
                }

                var IsFarRight = r.right >= (DefaultWidth - EnemyCloud.DefaultCloudMargin);

                if (cloud1.NextMove.x < 0)
                {
                    IsFarRight = false;
                }

                var IsFarLeft = r.left <= (EnemyCloud.DefaultCloudMargin);

                if (cloud1.NextMove.x > 0)
                {
                    IsFarLeft = false;
                }


                var WillStartVerticalMovement = IsFarLeft || IsFarRight;


                if (WillStartVerticalMovement && cloud1.NextMove.y == 0)
                {
                    cloud1.NextMove.x = 0;
                    cloud1.NextMove.y = 8;

                    cloud1.Speed *= cloud1.SpeedAcc;
                }
                else
                {
                    if (WillStartVerticalMovement)
                    {
                        cloud1.NextMove.y -= cloud1.Speed / 2;
                    }
                    else
                    {
                    }

                    if (cloud1.NextMove.y <= 0)
                    {
                        cloud1.NextMove.y = 0;

                        if (IsFarLeft)
                        {
                            cloud1.NextMove.x = cloud1.Speed;
                        }
                        else if (IsFarRight)
                        {
                            cloud1.NextMove.x = -cloud1.Speed;
                        }
                    }
                }

                //DebugDump.Write(new { CloudMove.x, CloudMove.y });

                cloud1.MoveToOffset(cloud1.NextMove);
            };



            #endregion



            //AddEnemy.Chained(new EnemyA(), new Point(200, 200));
            //AddEnemy.Chained(new EnemyB(), new Point(240, 200));
            //AddEnemy.Chained(new EnemyC(), new Point(280, 200));
            //AddEnemy.Chained(new EnemyUFO(), new Point(160, 200));
            //AddEnemy.Chained(new EnemyBigGun(), new Point(120, 200));

            #region FireBullet

            RoutedActions.FireBullet.Direct =
                (StarShip starship, int Multiplier, Point From, Point To, double Limit, Action <BulletInfo> handler) =>
            {
                var bullet = new SpriteWithMovement();

                Multiplier = Math.Max(Multiplier, 1);

                for (int i = 1; i <= Multiplier; i++)
                {
                    bullet.graphics.beginFill(Colors.Green);
                    bullet.graphics.drawRect((i - Multiplier) * 2, -8, 1, 16);
                }


                bullet.StepMultiplier = 0.3;
                bullet.MaxStep        = 24;

                if (From.y < To.y)
                {
                    bullet.TeleportTo(From.x, From.y);
                    bullet.TweenMoveTo(To.x + 0.00001, To.y);

                    bullet.PositionChanged +=
                        delegate
                    {
                        if (bullet.y > Limit)
                        {
                            bullet.Orphanize();
                        }
                    };
                }
                else
                {
                    bullet.TeleportTo(From.x, From.y);
                    bullet.TweenMoveTo(To.x + 0.00001, To.y);


                    bullet.PositionChanged +=
                        delegate
                    {
                        if (bullet.y < Limit)
                        {
                            bullet.Orphanize();
                        }
                    };
                }

                // it should not be null and provide the correct parent for the bullet
                if (starship == null)
                {
                    starship = this.Ego.ActiveEgo;
                }

                var bulletp = new BulletInfo(bullet.WithParent(starship))
                {
                    Multiplier = Multiplier
                };

                // local only
                FragileEntities.AddBullet(bulletp);

                bulletp.Element.AttachTo(CanvasOverlay);
                bulletp.Element.removed +=
                    delegate
                {
                    FragileEntities.Bullets.Remove(bulletp);
                };

                if (!bulletp.Silent)
                {
                    play(Sounds.firemissile);
                }

                if (handler != null)
                {
                    handler(bulletp);
                }
            };

            #endregion



            #region SetWeaponMultiplier

            RoutedActions.SetWeaponMultiplier.Direct =
                (p, value) =>
            {
                p.CurrentBulletMultiplier.Value = value;
            };
            #endregion

            #region AddDamage
            RoutedActions.AddDamage.Direct +=
                (target, damage, shooter) =>
            {
                target.TakeDamage(damage);

                if (target.HitPoints <= 0)
                {
                    // did we kill anything?
                    // shall we take credit?

                    if (GroupEnemies.Any(k => k == target))
                    {
                        cloud1.TickInterval.Value = Math.Max((cloud1.TickInterval.Value - 25), 200);
                        cloud1.Speed *= cloud1.SpeedAcc;
                    }

                    // we shot a coplayer while in evil mode! yay!
                    if (shooter == Ego.EvilEgo)
                    {
                        if (KnownEgos.Any(k => k.GoodEgo == target))
                        {
                            this.RoutedActions.AddAchivementUFO.Chained();
                        }
                    }

                    #region award localplayer and upgrade weapon
                    if (shooter == Ego.ActiveEgo)
                    {
                        Statusbar.Score.Value += target.ScorePoints;

                        TryUpgradeWeapon();
                    }
                    #endregion


                    play(target.GetDeathSound());
                }
                else
                {
                    play(Sounds.shortwhite);
                }

                //DebugDump.Write(
                //    new
                //    {
                //        From = bullet.Parent.Name,
                //        Delta = bullet.TotalDamage,
                //        target.HitPoints,
                //        To = target.Name
                //    }
                //);
            };
            #endregion



            #region FragileEntities
            this.FragileEntities.AddDamage = RoutedActions.AddDamage;

            this.FragileEntities.PrepareFilter =
                delegate
            {
                var GroupGood = KnownEgos.Select(i => i.GoodEgo).ToArray();
                var GroupEvil = GroupEnemies.ToArray();

                this.FragileEntities.Filter =
                    (source, n) =>
                {
                    // spare yourself
                    var query = source;

                    // spare coplayers in the same mode
                    if (GroupEnemies.Contains(n.Parent))
                    {
                        query = query.Where(x => !GroupEvil.Contains(x));
                    }
                    else
                    {
                        query = query.Where(x => !GroupGood.Contains(x));
                    }

                    return(query);
                };
            };
            #endregion

            this.RoutedActions.AddAchivementFiver.Direct =
                delegate
            {
                play(Sounds.insertcoin);
            };

            this.RoutedActions.AddAchivementMaxGun.Direct =
                delegate
            {
                play(Sounds.insertcoin);
            };

            this.RoutedActions.AddAchivementUFO.Direct =
                delegate
            {
                play(Sounds.mothershiploop);
            };

            Action <RoutedActionInfoBase> BaseHandler =
                e => DebugDump.Write(new { e.EventName });

            // events for network
            // RoutedActions.AddDamage.BaseHandler += BaseHandler;
            RoutedActions.RestoreStarship.BaseHandler     += BaseHandler;
            RoutedActions.AddAchivementFiver.BaseHandler  += BaseHandler;
            RoutedActions.AddAchivementUFO.BaseHandler    += BaseHandler;
            RoutedActions.AddAchivementMaxGun.BaseHandler += BaseHandler;

            //this.AddEnemy.BaseHandler += BaseHandler;
            ////this.AddBullet.BaseHandler += BaseHandler;
            //this.DoPlayerMovement.BaseHandler += BaseHandler;
            //this.SetWeaponMultiplier.BaseHandler += BaseHandler;
        }
Beispiel #3
0
        public void InitializeOtherEvents()
        {
            // todo: events need to automatically
            // queue based on message id and wait timer
            // currently this is done manually.

            Events.ServerPlayerJoined +=
                e =>
            {
                MapInitialized.ContinueWhenDone(
                    delegate
                {
                    //Map.WriteLine("joined: " + e.name);

                    PlayerAdvertise();
                }
                    );
            };

            Events.UserPlayerAdvertise +=
                e =>
            {
                MapInitialized.ContinueWhenDone(
                    delegate
                {
                    PlayerAdvertise(e);
                }
                    );
            };


            Events.ServerPlayerLeft +=
                e =>
            {
                if (UserEnterEndLevelMode_LastSender != null)
                {
                    if (UserEnterEndLevelMode_LastSender.Identity.user == e.user)
                    {
                        Map.WriteLine("bummer, map owner left...");
                        // bummer, he was gonna send us a map!
                        // in next 1 to 5 secs we try to use our map
                        1000.AtDelayDo(
                            delegate
                        {
                            Convert.ToInt32(new Random().NextDouble() * 4000).AtDelayDo(
                                delegate
                            {
                                if (UserEnterEndLevelMode_LastSender == null)
                                {
                                    return;
                                }

                                UserEnterEndLevelMode_LastSender = null;

                                Map.WriteLine("sending our map...");

                                UseOurMapForNextLevel();
                            }
                                );
                        }
                            );
                    }
                }

                //Map.WriteLine("left: " + e.name);

                // self kill the player guard, and remove the coplayer entity
                this.CoPlayers.Where(k => k.Identity.user == e.user).Where(k => k.Guard != null).ToArray().ForEach(k => k.RemoveFrom(CoPlayers).Guard.TakeDamage(k.Guard.Health, k.WeaponIdentity));

                if (this.CoPlayers.Count == 1)
                {
                    // if ego is left alone reveal exit

                    if (this.Map.HalfOfTheTreasureCollected != null)
                    {
                        this.Map.HalfOfTheTreasureCollected();
                    }
                }
            };

            Events.ServerSendMap +=
                e =>
            {
                // we have been chosen to tell the new guy about current map
                MapInitializedAndLoaded.ContinueWhenDone(
                    delegate
                {
                    if (FirstMapLoader.Ready)
                    {
                        WriteSync();
                    }
                    else
                    {
                        this.Map.WriteLine("we are not ready to send out a map - between levels");
                    }
                }
                    );
            };

            Events.UserSendMap +=
                e =>
            {
                // got a map, no need to worry about not getting one
                UserEnterEndLevelMode_LastSender = null;

                // stop showing score and keep map in sync instead by loading a new map
                if (this.Map.EnterEndLevelMode_ReadyToContinue != null)
                {
                    this.Map.EnterEndLevelMode_ReadyToContinue();
                    this.Map.WriteLine("did we speed up the end game menu?");
                }
                else
                {
                    this.Map.WriteLine("looks like we cannot speed up the end game menu?");
                }

                var bytestream = e.bytestream;

                this.Map.WriteLine("got UserSendMap");

                FirstMapLoader.Signal(
                    delegate
                {
                    ReadSync(bytestream);
                }
                    );
            };

            // note: you should not listen to non user, non server events

            Events.UserTakeAmmo +=
                e =>
            {
                this.Map.AmmoSprites.Where(k => k.ConstructorIndexForSync == e.index).ToArray().ForEach(
                    i => i.RemoveFrom(this.Map.AmmoSprites).RemoveFrom(this.Map.EgoView.Sprites)
                    );
            };

            Events.UserTakeGold +=
                e =>
            {
                CoPlayers.Where(k => k.Identity.user == e.user).ForEach(k => k.Score += FlashTreasureHunt.ScoreForGold);

                this.Map.GoldSprites.Where(k => k.ConstructorIndexForSync == e.index).ToArray().ForEach(
                    i => i.RemoveFrom(this.Map.GoldSprites).RemoveFrom(this.Map.EgoView.Sprites)
                    );
            };

            Events.UserAddDamageToCoPlayer +=
                e =>
            {
                this.MapInitializedAndLoaded.ContinueWhenDone(
                    delegate
                {
                    var DamageOwner = CoPlayers.Single(k => k.Identity.user == e.user).WeaponIdentity;

                    this.DisableAddDamageToCoPlayer = true;
                    this.CoPlayers.Where(k => k.Identity.user == e.target).Where(k => k.Guard != null).ForEach(k => k.Guard.TakeDamage(e.damage, DamageOwner));
                    this.DisableAddDamageToCoPlayer = false;
                }
                    );
            };

            Events.UserFireWeapon +=
                e =>
            {
                Assets.Default.Sounds.gunshot.play();

                this.CoPlayers.Where(k => k.Identity.user == e.user).ForEach(k => k.Guard.PlayShootingAnimation());
            };

            Events.UserWalkTo += UserWalkTo;
            Events.UserLookAt += UserLookAt;

            Events.UserGuardWalkTo    += UserGuardWalkTo;
            Events.UserGuardLookAt    += UserGuardLookAt;
            Events.UserGuardAddDamage +=
                e =>
            {
                this.MapInitializedAndLoaded.ContinueWhenDone(
                    delegate
                {
                    this.Map.WriteLine("got UserGuardAddDamage " + e);

                    var DamageOwner = CoPlayers.Single(k => k.Identity.user == e.user).WeaponIdentity;

                    this.DisableGuardAddDamage = true;
                    this.Map.GuardSprites.Where(k => k.ConstructorIndexForSync == e.index).ForEach(k => k.TakeDamage(e.damage, DamageOwner));
                    this.DisableGuardAddDamage = false;
                }
                    );
            };

            Events.UserEnterEndLevelMode +=
                e =>
            {
                var sender = this.CoPlayers.SingleOrDefault(k => k.Identity.user == e.user);

                if (sender == null)
                {
                    Map.WriteLine("must wait until next level is generated");

                    if (!MapInitializedAndLoaded.Ready)
                    {
                        if (!FirstMapLoader.Ready)
                        {
                            FirstMapLoader.Wait(TimeoutAction.LongOperation);
                        }
                    }

                    return;
                }

                sender.Score += FlashTreasureHunt.ScoreForEndLevel;

                Map.WriteLine("got UserEnterEndLevelMode from " + sender.Identity.name);

                UserEnterEndLevelMode_LastSender = sender;

                if (this.AbortGhostMode != null)
                {
                    this.AbortGhostMode();
                }

                DisableEnterEndLevelMode = true;
                this.Map.EnterEndLevelMode();
                DisableEnterEndLevelMode = false;
            };
        }