public bool Tick(VMEODNCDanceFloorPlugin p)
        {
            var mat = Matrix.CreateRotationZ(-Direction);
            var ctr = new Vector2(p.ScreenWidth, p.ScreenHeight) / 2 + new Vector2(-0.25f);
            var sd  = p.ScreenDiag;
            var sw  = p.ScreenWidth;
            var sh  = p.ScreenHeight;

            switch (Type)
            {
            case VMEODNCParticleType.Line:
                //by default we're an x line, starting from the bottom and going up.
                var base1 = new Vector2(-sd, sd / 2 - Frame);
                var base2 = new Vector2(sd, sd / 2 - Frame);
                base1 = Vector2.Transform(base1, mat) + ctr;
                base2 = Vector2.Transform(base2, mat) + ctr;
                p.DrawOutline(base1, base2, 0);
                p.DrawLine(base1, base2, Color);
                return(Frame < sd);

            case VMEODNCParticleType.Arrow:
                //draws an arrow towards the correct direction
                var arrowr = Frame;
                var arrow  = new Vector2[]
                {
                    new Vector2(0, 16 - arrowr),
                    new Vector2(0, 8 - arrowr),
                    new Vector2(5, 13 - arrowr),
                    new Vector2(-5, 13 - arrowr),

                    new Vector2(0, 9.25f - arrowr),
                    new Vector2(5, 14.25f - arrowr),
                    new Vector2(-5, 14.25f - arrowr)
                }.Select(x => Vector2.Transform(x, mat) + ctr).ToArray();

                p.DrawOutline(arrow[0], arrow[1], 0);
                p.DrawOutline(arrow[1], arrow[2], 0);
                p.DrawOutline(arrow[1], arrow[3], 0);
                p.DrawOutline(arrow[4], arrow[5], 0);
                p.DrawOutline(arrow[4], arrow[6], 0);

                p.DrawLine(arrow[0], arrow[1], Color);
                p.DrawLine(arrow[1], arrow[2], Color);
                p.DrawLine(arrow[1], arrow[3], Color);
                p.DrawLine(arrow[4], arrow[5], Color);
                p.DrawLine(arrow[4], arrow[6], Color);

                return(Frame < (sd + 8));

            case VMEODNCParticleType.Rect:
                //shrinks a rectangle in from the screen edges
                var rect = new Rectangle(Frame, Frame, sw - Frame * 2, sh - Frame * 2);

                p.DrawRect(new Rectangle(rect.Left - 1, rect.Top - 1, 3, rect.Height), 0);
                p.DrawRect(new Rectangle(rect.Right - 2, rect.Top - 1, 3, rect.Height), 0);
                p.DrawRect(new Rectangle(rect.Left - 1, rect.Top - 1, rect.Width, 3), 0);
                p.DrawRect(new Rectangle(rect.Left - 1, rect.Bottom - 2, rect.Width, 3), 0);

                p.DrawRect(new Rectangle(rect.Left, rect.Top, 1, rect.Height), Color);
                p.DrawRect(new Rectangle(rect.Right - 1, rect.Top, 1, rect.Height), Color);
                p.DrawRect(new Rectangle(rect.Left, rect.Top, rect.Width, 1), Color);
                p.DrawRect(new Rectangle(rect.Left, rect.Bottom - 1, rect.Width, 1), Color);
                return(Frame < sw / 2);

            case VMEODNCParticleType.Colder:
                //pulses out from the center, either at the top or bottom of the dance floor
                var fm   = Frame % (sw / 2);
                var ypos = (GroupID % 2 == 0) ? 0 : sh - 2;

                var xp1 = sw / 2 - fm;
                var xp2 = sw / 2 + fm;

                p.DrawRect(new Rectangle(0, ypos, sw, 2), (byte)0);

                p.DrawRect(new Rectangle(xp1 - 1, ypos, 3, 2), (byte)(Color + 1));
                p.DrawRect(new Rectangle(xp2 - 1, ypos, 3, 2), (byte)(Color + 1));

                p.DrawRect(new Rectangle(xp1, ypos, 1, 2), (byte)(Color));
                p.DrawRect(new Rectangle(xp2, ypos, 1, 2), (byte)(Color));

                return(Frame < sw * 2);
            }
            return(false);
        }
        public override void Tick()
        {
            base.Tick();

            if (!Connected)
            {
                //need to connect to child plugins.
                DanceFloor = Server.vm.EODHost.GetFirstHandler <VMEODNCDanceFloorPlugin>();
                if (DanceFloor != null)
                {
                    Connected = true;

                    /*DancePlatforms = Server.vm.EODHost.GetHandlers<VMEODDancePlatformPlugin>().ToList();
                     * if (DancePlatforms.Count == 4)
                     * {
                     *  DJPlatforms = Server.vm.EODHost.GetHandlers<VMEODDJStationPlugin>().ToList();
                     *  if (DJPlatforms.Count == 4)
                     *  {
                     *      Connected = true;
                     *  }
                     * }*/
                }
            }
            else
            {
                //game behaviour.
                if (RoundActive)
                {
                    var danceCycle = RoundTicks % (30 * 60);
                    if (danceCycle == 0)
                    {
                        //set up a new random dance pattern
                        var rand = new Random();
                        for (int i = 0; i < 3; i++)
                        {
                            var rd = rand.Next(24);
                            while (CurrentWinningDancePatterns.Any(x => x == rd))
                            {
                                rd = rand.Next(24);
                            }
                            CurrentWinningDancePatterns[i] = rd;
                            //the winning pattern will always be new. There is a chance 2 and 3 may be repeats.
                        }
                        if (RoundTicks != 0)
                        {
                            DancePatternNum++;
                        }
                    }

                    if (RoundTicks % (5 + Math.Min(danceCycle / 30, 25)) == 0)
                    {
                        //give a dancer a new dance
                        var rand = new Random();
                        var pct  = rand.Next(100);
                        int i;
                        for (i = 0; i < 3; i++)
                        {
                            if (pct < PatternDancerChance[i])
                            {
                                break;
                            }
                            pct -= PatternDancerChance[i];
                        }
                        var pattern = CurrentWinningDancePatterns[i];
                        var dancer  = Dancers[DancerIndex++];
                        //Console.WriteLine("hint given..");
                        Server.vm.ForwardCommand(new VMNetInteractionCmd()
                        {
                            CalleeID    = dancer.ObjectID,
                            CallerID    = dancer.ObjectID,
                            Global      = false,
                            Interaction = (ushort)(pattern + 4)
                        });
                        if (DancerIndex >= Dancers.Count)
                        {
                            DancerIndex = 0;
                        }
                    }

                    RoundTicks++;
                }
            }
        }