User:MomBun/Sandbox: Difference between revisions

117 bytes added ,  12:02, 5 August 2022
(adding skeletal example with comments (Thank you Gnarf!))
 
(8 intermediate revisions by 2 users not shown)
Line 7: Line 7:
<mutations>
<mutations>
   <category Name="[CATEGORY]">
   <category Name="[CATEGORY]">
     <mutation Name="[NAME]" Cost="[NUMBER]" MaxSelected="[NUMBER]" Class="[C# ID]" Tile="Mutations/"YOUR_IMAGE_HERE"></mutation>
     <mutation Name="[NAME]" Cost="[NUMBER]" MaxSelected="[NUMBER]" Class="[CS CLASS]" Tile="Mutations/YOUR_IMAGE_HERE" Foreground="COLOR" Background="COLOR" </mutation>
  </category>
  </category>
</mutations>
</mutations>
Line 39: Line 39:
The tile you will be using for said mutation in-game.
The tile you will be using for said mutation in-game.


By default most mutations use gold/yellow for detail and brown for foreground but this can be customized for any color of your choice, see [[Modding:Tiles]] and [[Modding:Colors_%26_Object_Rendering]] for furtherr info on this.
By default most mutations use gold/yellow for background and brown for foreground but this can be customized for any color of your choice, see [[Modding:Tiles]] and [[Modding:Colors_%26_Object_Rendering]] for further info on this.
 
=== Constructor ===
This element should be a string argument (or a comma-delimited string of arguments, if there are more than one) to pass to the mutation's class constructor. All such arguments are received as string parameters in the mutation class constructor. For example, Corrosive Gas Generation and Sleep Gas Generation both use the same mutation class, GasGeneration. However, Mutations.xml passes a different argument to the constructor, which indicates which type of gas should be used.
 
Here are an example of how this is constructed from both <code>Mutations.XML</code> and <code>GasGeneration.cs</code>
<syntaxhighlight lang="xml">
<mutation Name="Sleep Gas Generation" Cost="2" MaxSelected="1" Class="GasGeneration" Constructor="SleepGas" Exclusions="Corrosive Gas Generation" BearerDescription="those who expel sleep gas" Code="bu"></mutation>
</syntaxhighlight>
 
<syntaxhighlight lang="csharp">
namespace XRL.World.Parts.Mutation
{
[Serializable]
public class GasGeneration : BaseMutation
{
public GasGeneration(string _GasObject)
{
this.GasObject = _GasObject;
this.SyncFromBlueprint();
}
</syntaxhighlight>
 
The GasObject property is set to to "SleepGas" in this case, because that was the value provided in the Constructor element of Mutations.xml.
 
Theoretically you could create a new mutation that generates any type of gas simply by adding a single <mutation> tag to a Mutations.xml file. For example, this Mutations.xml file alone would create a new mutation called "Confusion Gas Generation"


=== Exclusions ===
=== Exclusions ===
Line 71: Line 46:
=== BearerDescription ===
=== BearerDescription ===
It appears that this description is used in some of the random generation algorithms for villages and history in the game. For example, if a village reveres mutants with the Multiple Arms mutation, they might use the string defined in Mutations.xml ("the many-armed") to describe them in their praises or monuments.
It appears that this description is used in some of the random generation algorithms for villages and history in the game. For example, if a village reveres mutants with the Multiple Arms mutation, they might use the string defined in Mutations.xml ("the many-armed") to describe them in their praises or monuments.
=== Constructor ===
This is used by very few mutations, and its use case is as a string argument (or a comma-delimited string of arguments, if there are more than one) to pass to the mutation's class constructor. All such arguments are received as string parameters in the mutation class constructor.
It should be noted that this parameter is both advance and old, and it shouldn't be necessary and potentially avoided.
   
   
== C# Scripting, and Making The Mutation ==
== C# Scripting, and Making The Mutation ==


Here is an example of a mutation that will add udders to your character, editing the title of your character "With Udders" and occasionally moo
Here is an example of a mutation that will add udders to your character, which will edit the title of your character to add udders, and make you moo occasionally.
<syntaxhighlight lang="csharp">
<syntaxhighlight lang="csharp">
using System;
using System;
Line 90: Line 71:
     [Serializable]
     [Serializable]
     // This defines the class that you will call in Mutations.XML
     // This defines the class that you will call in Mutations.XML
     class TEST_Udders : BaseMutation
     class QudWiki_Udders : BaseMutation
     {
     {


Line 99: Line 80:
         }
         }


         // This sets the description for what exactly your mutation does
         // This sets the description for what exactly your mutation does.
        // It is good idea to make helper functions like the "ChanceToMoo" to make dynamic descriptions for changing rules for a mutation.
         public override string GetLevelText(int Level)
         public override string GetLevelText(int Level)
         {
         {
             return  "Occasionally you will moo";
             return  "{{rules|You have a " + ChanceToMoo(Level) + "% chance to moo per turn}}";
        }
 
        public int ChanceToMoo(int Level)
        {
          return Level;
        }
 
        // This is called every time the mutation changes level, and can be used to change things like damage.
        // We don't use "ChanceToMoo" in this example so we can allow GetLevelText to use it.
        public override bool ChangeLevel(int NewLevel)
        {
            return true;
        }
 
        // These two are called upon when an object gains said mutation and what happens, and is used to add or remove things as necessary
        public override bool Mutate(GameObject MUTANT, int Level)
        {
            return base.Mutate(MUTANT, Level);
        }
 
        public override bool Unmutate(GameObject MUTANT)
        {
            return Base.Unmutate(MUTANT);
         }
         }


Line 144: Line 149:
             if (E.ID == "EndTurn")
             if (E.ID == "EndTurn")
             {
             {
                 // 1 in 100 chance to get "You moo." printed to the message log.
                 // Reusing the same method we used in GetLevelText means that both of them will remain accurate.
                 if (1.in100()) DidX("moo");
                 if (ChanceToMoo(Level).in100()) DidX("moo");
             }
             }
             return base.FireEvent(E);
             return base.FireEvent(E);
        }
        // This is called every time the mutation changes level, and can be used to change things like damage.
        public override bool ChangeLevel(int NewLevel)
        {
            return true;
        }
        // These two are called upon when an object gains said mutation and what happens, and is used to add or remove things as necessary
        public override bool Mutate(GameObject PLAYER, int Level)
        {
            return true;
        }
        public override bool Unmutate(GameObject PLAYER)
        {
            return true;
         }
         }
     }
     }
}
}
</syntaxhighlight>
</syntaxhighlight>
== Bigger Example ==


TODO: Re-work the huge file of flaminghands.cs to be have comments and explain it , possibly with Gnarf's help if they are okay/free to do so
TODO: Re-work the huge file of flaminghands.cs to be have comments and explain it , possibly with Gnarf's help if they are okay/free to do so
Line 182: Line 173:
{
{


    /// <summary>
    ///  FlamingHands powers the "Flaming Ray" mutation.  You can now choose a variant from hands, feet or face.
    /// </summary>
     [Serializable]
     [Serializable]
     public class FlamingHands : BaseDefaultEquipmentMutation
     public class FlamingHands : BaseDefaultEquipmentMutation
     {
     {
        public FlamingHands()
        {
            DisplayName = "Flaming Ray";
        }


        /// <summary>The <see cref="BodyPart.Type" /> we replace (chosen by variant selection.)</summary>
         public string BodyPartType = "Hands";
         public string BodyPartType = "Hands";
        /// <summary>Do we still need to create the object? Setup as a public for serialization purposes.</summary>
         public bool CreateObject = true;
         public bool CreateObject = true;
        /// <summary>Sound file to play when attacking.</summary>
         public string Sound = "Abilities/sfx_ability_mutation_flamingRay_attack";
         public string Sound = "Abilities/sfx_ability_mutation_flamingRay_attack";
        [NonSerialized] private static GameObject _Projectile;


         public Guid FlamingHandsActivatedAbilityID = Guid.Empty;
         /// <summary>Create or retrive the already created Projectile game object.</summary>
 
        [NonSerialized] private static GameObject _Projectile;
         private static GameObject Projectile
         private static GameObject Projectile
         {
         {
Line 204: Line 205:
             }
             }
         }
         }
 
        /// <summary>We are request to be re-mutated automatically when our body is rebuilt. Thanks slog.</summary>
         public override bool GeneratesEquipment()
         public override bool GeneratesEquipment()
         {
         {
             return true;
             return true;
        }
        public FlamingHands()
        {
            DisplayName = "Flaming Ray";
         }
         }


Line 223: Line 219:
         }
         }


        /// <summary>Show selected variant in character creation.</summary>
         public override string GetCreateCharacterDisplayName()
         public override string GetCreateCharacterDisplayName()
         {
         {
Line 241: Line 238:
         }
         }


         public override string GetLevelText(int Level)
         public override string GetLevelText(int level)
         {
         {
             string Ret = "Emits a 9-square ray of flame in the direction of your choice.\n";             
             string Ret = "Emits a 9-square ray of flame in the direction of your choice.\n";             
             Ret += "Damage: {{rules|" + ComputeDamage(Level) + "}}\n";
             Ret += "Damage: {{rules|" + ComputeDamage(level) + "}}\n";
             Ret += "Cooldown: 10 rounds\n";
             Ret += "Cooldown: 10 rounds\n";
             Ret += "Melee attacks heat opponents by {{rules|" + GetHeatOnHitAmount(Level) + "}} degrees";
             Ret += "Melee attacks heat opponents by {{rules|" + GetHeatOnHitAmount(level) + "}} degrees";
             return Ret;
             return Ret;
         }
         }


         public string GetHeatOnHitAmount(int Level)
         public string GetHeatOnHitAmount(int level)
         {
         {
             return (Level * 2) + "d8";
             return (level * 2) + "d8";
         }
         }


         public string ComputeDamage(int UseLevel)
         public string ComputeDamage(int level)
         {
         {
             string Result = UseLevel + "d4";
             string Result = level + "d4";
             if (ParentObject != null)
             if (ParentObject != null)
             {
             {
Line 273: Line 270:
         }
         }


         public string ComputeDamage()
         public string ComputeDamage() => ComputeDamage(Level);
        {
            return ComputeDamage(Level);
        }


         public void Flame(Cell C, ScreenBuffer Buffer, bool doEffect = true)
         public void Flame(Cell C, ScreenBuffer Buffer, bool doEffect = true)
Line 363: Line 357:
                 }
                 }
             }
             }
             mutation.CooldownMyActivatedAbility(mutation.FlamingHandsActivatedAbilityID, Turns: 10);
             mutation.CooldownMyActivatedAbility(mutation.ActivatedAbilityID, Turns: 10);
             mutation.UseEnergy(1000, "Physical Mutation Flaming Hands");
             mutation.UseEnergy(1000, "Physical Mutation Flaming Hands");
             mutation.PlayWorldSound(mutation.Sound, combat: true);
             mutation.PlayWorldSound(mutation.Sound, combat: true);
Line 386: Line 380:
         {
         {
             if( !CreateObject) return true;
             if( !CreateObject) return true;
             return HasRegisteredSlot(BodyPartType) && GetRegisteredSlot(BodyPartType,false) != null;
             return HasRegisteredSlot(BodyPartType) && GetRegisteredSlot(BodyPartType, false) != null;
         }
         }


Line 416: Line 410:
                     CheckObjectProperlyEquipped()
                     CheckObjectProperlyEquipped()
                     && E.GetIntParameter("Distance") <= 9
                     && E.GetIntParameter("Distance") <= 9
                     && IsMyActivatedAbilityAIUsable(FlamingHandsActivatedAbilityID)
                     && IsMyActivatedAbilityAIUsable(ActivatedAbilityID)
                     && ParentObject.HasLOSTo(E.GetGameObjectParameter("Target"), UseTargetability: true)
                     && ParentObject.HasLOSTo(E.GetGameObjectParameter("Target"), UseTargetability: true)
                 )
                 )
Line 440: Line 434:
             }
             }
             return base.FireEvent(E);
             return base.FireEvent(E);
        }
        public override bool ChangeLevel(int NewLevel)
        {
            return base.ChangeLevel(NewLevel);
         }
         }


         private void AddAbility()
         private void AddAbility()
         {
         {
             FlamingHandsActivatedAbilityID = AddMyActivatedAbility(
             ActivatedAbilityID = AddMyActivatedAbility(
                 Name: "Flaming Ray",
                 Name: "Flaming Ray",
                 Command: "CommandFlamingHands",
                 Command: "CommandFlamingHands",
                 Class: "Physical Mutation",
                 Class: "Physical Mutation",
                 Icon: "" + (char) 168
                 Icon: "" + (char) 168,
                Description: GetLevelText(Level)
             );
             );
        }
        public override bool ChangeLevel(int NewLevel)
        {
            var result = base.ChangeLevel(NewLevel);
            // Update the ability description
            if (MyActivatedAbility(ActivatedAbilityID) is ActivatedAbilityEntry ability) ability.Description = GetLevelText(Level);
            return result;
         }
         }


Line 463: Line 461:
             return variants;
             return variants;
         }
         }


         public override void SetVariant(int n)
         public override void SetVariant(int n)
Line 476: Line 473:
             }
             }
             base.SetVariant(n);
             base.SetVariant(n);
        }
        public override void OnRegenerateDefaultEquipment(Body body)
        {
            base.OnRegenerateDefaultEquipment(body);
         }
         }


Line 552: Line 544:
         public override bool Unmutate(GameObject GO)
         public override bool Unmutate(GameObject GO)
         {
         {
             RemoveMyActivatedAbility(ref FlamingHandsActivatedAbilityID);
             RemoveMyActivatedAbility(ref ActivatedAbilityID);
             return base.Unmutate(GO);
             return base.Unmutate(GO);
         }
         }
Line 559: Line 551:


}
}
</syntaxhighlight>
</syntaxhighlight>




{{Modding Navbox}}
{{Modding Navbox}}