public static void GenerateSpellBurst(int x, int y, int width, int height, MagicSprite.MagicAnimation anim)
        {
            // Create ~6 spell sprites within bounds randomly and play them
            // Debug.WriteLine("Generate burst " + x + ", " + y + ", " + width + ", " + height + ", " + anim.ToString());

            List <Vector2> posList = new List <Vector2>();

            for (int i = 0; i < width / 32; i++)
            {
                for (int j = 0; j < height / 32; j++)
                {
                    int xPos = x + i * 32 + Globals.rnd.Next(4);
                    int yPos = y + j * 32 + Globals.rnd.Next(4);
                    posList.Add(new Vector2(xPos, yPos));
                }
            }

            foreach (Vector2 pos in posList)
            {
                float       delay = (float)Globals.rnd.NextDouble() * 100f;
                MagicSprite mspr  = GetMagicSprite();
                mspr.SetAnimation(anim, delay);
                mspr.SetPosition(pos);
            }
        }
示例#2
0
        private bool ExecuteActions()
        {
            turn = 0;
            foreach (Action action in GetSortedActionArray())
            {
                // Update and display turn number
                turn++;
                turnTotal++;
                TextManager.SetTurnText(turn);

                // If an actor was killed before its turn, ignore the turn
                if (action.Actor == null || action.Actor.IsDead())
                {
                    continue;
                }

                // Apply the action to each target
                foreach (MonoMonster target in action.Targets)
                {
                    // Ignore invalid target and spells against the dead
                    if (target == null || (action.Spell != null && target.IsDead()))
                    {
                        continue;
                    }

                    TextManager.SetActorText(action.Actor.Name);
                    Thread.Sleep(gameTick);

                    // If the action is nothing, display and bail out
                    if (action.Nothing)
                    {
                        TextManager.SetResultsText("Nothing");
                        continue;
                    }

                    TextManager.SetTargetText(target.Name);
                    Thread.Sleep(gameTick);

                    if (action.Physical)
                    {
                        // Physical attacks can target the dead, but are ineffective
                        if (target.IsDead())
                        {
                            TextManager.SetResultsText("Ineffective");
                            continue;
                        }

                        // Apply the attack and display the results
                        AttackResult atkRes = AttackManager.AttackMonster(action.Actor, target);

                        // On a miss, display and bail out
                        if (string.Equals(atkRes.DamageMessage, "Miss"))
                        {
                            TextManager.SetDamageText("Miss");
                            continue;
                        }

                        // Flicker sprite
                        // TODO: Different sounds and animations need to play based on the attack type
                        if (gameTick > 30)
                        {
                            SoundManager.PlaySound(SoundManager.Sound.Physical);
                            target.Flicker(16);
                        }

                        TextManager.SetHitsText(atkRes.HitsMessage);
                        Thread.Sleep(gameTick);

                        TextManager.SetDamageText(atkRes.DamageMessage);
                        Thread.Sleep(gameTick);

                        // Fade the monster if dead
                        // TODO: This is awkward here
                        if (target.IsDead())
                        {
                            target.StartDeath();
                            Thread.Sleep(30); // 300
                        }

                        // Display each result, tearing down existing results as needed
                        for (int i = 0; i < atkRes.Results.Count; i++)
                        {
                            string res = atkRes.Results[i];
                            TextManager.SetResultsText(res);
                            if (i < atkRes.Results.Count - 1)
                            {
                                Thread.Sleep(gameTick * 2);
                                TextManager.TearDownResults();
                                Thread.Sleep(teardownTick);
                            }
                        }

                        break;
                    }
                    else
                    {
                        // Casting a spell
                        TextManager.SetHitsText(action.Spell.Name + " " + action.SpellLevel);
                        Thread.Sleep(gameTick);

                        // Cast the spell and display the results
                        SpellResult spellRes = SpellManager.CastSpell(action.Actor, target, action.Spell, action.SpellLevel, action.Targets.Count > 1);

                        // Set the spell animation and sound based on the spell's effect (kinda). This is awkward but fine for now.
                        MagicSprite.MagicAnimation magicAnim = MagicSprite.MagicAnimation.Attack;
                        SoundManager.Sound         magicSnd  = SoundManager.Sound.AttackSpell;
                        if (action.Spell.Effect == "Buff")
                        {
                            magicAnim = MagicSprite.MagicAnimation.Buff;
                            magicSnd  = SoundManager.Sound.Buff;
                        }
                        if (action.Spell.Effect == "Debuff" || action.Spell.Effect == "TempStatus" || action.Spell.Effect == "PermStatus")
                        {
                            magicAnim = MagicSprite.MagicAnimation.Debuff;
                            magicSnd  = SoundManager.Sound.Debuff;
                        }
                        if (action.Spell.Effect == "Heal" || action.Spell.Effect == "Revive" || action.Spell.Effect == "ItemFullRestore")
                        {
                            magicAnim = MagicSprite.MagicAnimation.Heal;
                            magicSnd  = SoundManager.Sound.Heal;
                        }

                        MagicSpriteManager.GenerateSpellBurst((int)target.Position.X, (int)target.Position.Y, target.Width, target.Height, magicAnim);
                        SoundManager.PlaySound(magicSnd);
                        Thread.Sleep(SPELL_ANIMATION_DELAY);

                        if (spellRes.Damage >= 0)
                        {
                            TextManager.SetDamageText(spellRes.Damage.ToString());
                            Thread.Sleep(gameTick);
                        }

                        // Kill the target if it's dead.
                        // TODO: This is weird here, should be handled by the monster itself?
                        if (target.IsDead())
                        {
                            target.StartDeath();
                            Thread.Sleep(300);
                        }

                        // Display each result, tearing down existing results as needed
                        for (int i = 0; i < spellRes.Results.Count; i++)
                        {
                            string res = spellRes.Results[i];
                            TextManager.SetResultsText(res);
                            if (i < spellRes.Results.Count - 1)
                            {
                                Thread.Sleep(gameTick * 2);
                                TextManager.TearDownResults();
                                Thread.Sleep(teardownTick);
                            }
                        }

                        // Tear down between each target
                        Thread.Sleep(gameTick * 5);
                        while (TextManager.TearDownText())
                        {
                            Thread.Sleep(teardownTick);
                        }
                    }

                    // TODO: If both scenes only contain "Soul" enemies, they cannot kill eachother
                    if (!sceneOne.HasLivingMonsters() || !sceneTwo.HasLivingMonsters() || round >= ROUND_LIMIT)
                    {
                        break;
                    }
                }

                // Turn end, clean up text display
                Thread.Sleep(gameTick * 5);
                while (TextManager.TearDownText())
                {
                    Thread.Sleep(teardownTick);
                }

                if (!sceneOne.HasLivingMonsters() || !sceneTwo.HasLivingMonsters() || round >= ROUND_LIMIT)
                {
                    break;
                }
            }

            return(false);
        }