This was too easy and too cool to add to not do it :). Monsters now have Skills as well. Here’s an example of a couple of skills that Rabid Dog has:

<MonsterType Id="Mon4" Name="Rabid Dog" Family="Animal" Rarity="Common" HP="0" Tile="DogBrown" CorpseTile="CorpseTile" Level="1-5" Description="tbd: generic monster desc">
    <Skill Id="RDog1" Type="Heal" Name="Lick Wounds" TurnsUntilCanReuse="5" OddsOfUse="0.25">
      <Event Type="UseSkill" OnFireText="The rabid dog licks its wounds" OnFireChat="Heal">
        <Heal Amount="8+1d8" Target="Self" />
      </Event>
    </Skill>
    <Skill Id="RDog2" Type="MeleeAttack" Name="Claw" TurnsUntilCanReuse="5" OddsOfUse="0.25">
      <Event Type="UseSkill" OnFireText="The rabid dog's claws rake against you!" OnFireChat="Claw!">
        <DoDamage Amount="2d16"/>
      </Event>
    </Skill>
  </MonsterType>

Notice The skills and Events are the same the Player’s Skills. Also, notice how in the context of a monster, Skills have a “type” – Attack, Heal, or Escape. This is leveraged by the AI to determine if it should leverage a skill or not. I’ve also added the “TurnsUntilCanReuse” and “OddsOfUse” attributes to Skill to automate skill usage.

The update to the AI to leverage the above was easy to do as well. The following appears at the start of Monster.DecideNextAction:


            if ((float)HitPoints / MaximumHitPoints < .25f)
            {
                // A little bit of simplistic AI: If we have a healing ability and we are low on health, then use it
                if (ConsiderUsingSkillOfType(SkillType.Heal))
                    return;

                // No healing skills - any Skills that help us escape (blink, teleport, stun, etc)?
                // tbd-later: "escape" AI should set "fleeing" mode and toggle back to 'attacking' mode at appropriate point (e.g. when healed enough)
                if (ConsiderUsingSkillOfType(SkillType.Escape))
                    return;
            }

Similarly, when DecideNextAction is about to initiate a melee attack, it considers whether or not to leverage a melee skill instead:

            // If we're right next to the player, then next action is to do melee attack
            if (targetLoc.Neighbors.Contains(Location))
            {
                // A little bit of simplistic AI: If we have a melee attack ability then consider using it
                if (ConsiderUsingSkillOfType(SkillType.MeleeAttack))
                {
                    // Hook up target
                    NextAction.Initialize(this, AggroTarget);
                    return;
                }

                SetNextAction(Action_MeleeAttack.Create(this, AggroTarget));
            }

And finally, the code to determine whether or not to use a Skill of a certain type just iterates over the Monster’s skills to find one of the appropriate type, checks if it’s been long enough since last use, checks the odds of it firing, and if all of that lines up, it sets the skill as the Monster’s next action.

        private bool ConsiderUsingSkillOfType(SkillType skillType)
        {
            // tbd-later: we're using the first 'ready' skill; not quite right if a mob has multiple skills of this type...
            foreach (Skill skill in Skills)
                if (skill.Type == skillType)
                {
                    // Has enough time passed that we can re-use this skill?
                    if (TurnMgr.TurnNumber - skill.LastTurnUsed > skill.TurnsUntilCanReuse)
                    {
                        // Check the odds that we want to use it
                        if (Rand.NextPercent() < skill.OddsOfUse)
                        {
                            SetNextAction(Action_UseSkill.Create(this, skill));
                            return true;
                        }
                    }
                }
            return false;
        }

Given the “OnFireText” and “OnFireChat” events in the Skill definition, we can report to the user that the Skill was used. This will eventually need to support both success and failure cases (right now the Skill is always assumed to succeed). Also, eventually this will ideally be extended to support Animations to run when a Skill is performed.

Here’s what the above looks like when the MeleeAttack skill is used. There was a bit of glue necessary (e.g. addition of the Action_DoDamage class), but probably 30 minutes all told. Not bad to give Monsters the ability to have and somewhat intelligently use Skills! 🙂

I still need to add persistence of Skills (for Monsters too, now :)) – hopefully tonight!

Advertisements