Skip to content
Matthew Walls edited this page Oct 12, 2018 · 1 revision

Gist

Gives abilities, or UI buttons, to a character.

In Action

Icon artwork is modified from http://www.game-icons.net/

How-to Add Abilities

To give a character abilities, you will need...

  1. C# class so the game knows who gets to have the abilities you've made
  2. XML Defs for the abilities
  3. XML Defs for any ability projectiles
  4. Textures for the buttons

Optional: SoundDef for the cast sound, DamageDef for the damage received, etc.

C# Class

Here is a short C# class that adds a single new ability to a character.

using AbilityUser
    public class CompPsionicUserExample : AbilityUser.CompAbilityUser
    {
        //A simple check boolean to make sure we don't give abilities twice.
        //Starts false because we haven't given abilities yet.
        private bool gaveAbilities = false;

        private bool firstTick = false;
        
        /// <summary>
        /// To be psionic, the character must have a psionic brain.
        /// </summary>
        private bool IsPsionic 
        {
            get
            {
                if (Pawn?.health?.hediffSet == null) return false;
                if (Pawn.health.hediffSet.HasHediff(ThingDef.Named("PsionicBrain"))) return true;
                return false;
            }
        }
        
        /// <summary>
        /// Gives this component class to the character if they are psionic.
        /// </summary>
        public override bool TryTransformPawn() => IsPsionic;

        /// <summary>
        /// After getting the component class, checks 200 ticks
        /// after the game starts.
        /// If the character is psionic, give them the abilities in
        /// the function PostInitalizeTick()
        /// </summary>
        public override void CompTick()
        {
            if (Pawn?.Spawned != true) return;
            if (Find.TickManager.TicksGame > 200)
            {
                if (IsPsionic)
                {
                    if (!firstTick)
                    {
                        PostInitializeTick();
                    }
                    base.CompTick();
                }
            }
        }
        
        /// <summary>
        /// Adds the ability "Psionic Blast" to the character.
        /// Sets gaveAbilities to true, because we gave the abilties.
        /// </summary>
        private void PostInitializeTick()
        {
            if (Pawn?.Spawned != true) return;
            if (Pawn?.story == null) return;
            firstTick = true;
            this.Initialize();
            if (!gaveAbilities)
            {
                gaveAbilities = true;
                this.AddPawnAbility(CultsDefOf.Cults_PsionicBlast);   
            }
        }

        //Use this area to store any extra data you want to load
        //with your component.
        public override void PostExposeData()
        {
            base.PostExposeData();
            Scribe_Values.Look(ref this.gaveAbilities, "gaveAbilities", false);
        }
    }

XML

AbilityDef

Here is a short XML that adds the ability to shoot a projectile.

...
   <AbilityUser.AbilityDef>
    <defName>PsionicBlast</defName>
    <label>Psionic Blast</label>
    <uiIconPath>UI/Icons/Commands/PsionicBlast</uiIconPath>
    <description>Hits the character with a blast of psionic energy.</description>
    <MainVerb Class="AbilityUser.VerbProperties_Ability">
        <abilityDef>PsionicBlast</abilityDef>
	<verbClass>AbilityUser.Verb_UseAbility</verbClass>
	<tooltipShowProjectileDamage>true</tooltipShowProjectileDamage>
	<tooltipShowExtraDamages>false</tooltipShowExtraDamages>
	<tooltipShowHediffsToApply>false</tooltipShowHediffsToApply>
	<tooltipShowMentalStatesToApply>false</tooltipShowMentalStatesToApply>
        <hasStandardCommand>true</hasStandardCommand>
        <defaultProjectile>PsionicBlastProjectile</defaultProjectile>
	<isViolent>true</isViolent>
        <warmupTime>1</warmupTime>
        <SecondsToRecharge>180.0</SecondsToRecharge>
        <range>24</range>
        <burstShotCount>1</burstShotCount>
        <ticksBetweenBurstShots>2</ticksBetweenBurstShots>
        <soundCast>PsionicSound</soundCast>
        <muzzleFlashScale>20</muzzleFlashScale>
        <isPrimary>false</isPrimary>
	<targetParams>
	  <canTargetPawns>true</canTargetPawns>
	  <canTargetBuildings>false</canTargetBuildings>
	  <canTargetItems>false</canTargetItems>
	  <canTargetSelf>false</canTargetSelf>
	</targetParams>
    </MainVerb>
  </AbilityUser.AbilityDef>
...

Projectile ThingDef

Here is the projectile that flies when our ability is cast.

...
  <ThingDef ParentName="BaseBullet" Class="AbilityUser.ProjectileDef_Ability">
   <defName>PsionicBlastProjectile</defName>
   <thingClass>AbilityUser.Projectile_Ability</thingClass>
   <label>psionic blast</label>
   <graphicData>
	<texPath>Projectiles/PsionicBlast</texPath>
	<graphicClass>Graphic_Single</graphicClass>
   </graphicData>
   <projectile>
	<flyOverhead>true</flyOverhead>
	<damageDef>PsionicBlastDamage</damageDef>
	<damageAmountBase>15</damageAmountBase>
	<speed>30</speed>
   </projectile>
 </ThingDef>
...