Versions Compared
Key
- This line was added.
- This line was removed.
- Formatting was changed.
...
First, include a mutations.xml in your mod that defines a new mutation.
Code Block | |
---|---|
|
...
|
...
|
...
|
...
<?xml version="1.0" encoding="utf-8" ?>
<mutations>
<category Name="Physical">
<mutation Name="Udder" Cost="1" MaxSelected="1" Class="FreeholdTutorial_Udder" Exclusions="" Code="ea"></mutation>
</category>
</mutations> |
Then add a new .cs file in your mod that implements the class. Here's a skeletal implementation of the entry above. It must be in the XRL.World.Parts.Mutation namespace and must ultimately descend from BaseMutation. (Though not necessarily directly, if you have a very complex mod)
Code Block | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
using System; using System.Collections.Generic; using System.Text; using XRL.Rules; using XRL.Messages; using ConsoleLib.Console; namespace XRL.World.Parts.Mutation { [Serializable] class FreeholdTutorial_Udder : BaseMutation { public FreeholdTutorial_Udder() |
...
|
...
|
...
|
...
{ |
...
Name = "FreeholdTutorial_Udder"; |
...
|
...
|
...
|
...
|
...
DisplayName |
...
= "Udder"; } public override void Register(GameObject Object) { } |
...
|
...
public override string |
...
GetDescription() { |
...
return " |
...
" |
...
;
}
public override string |
...
GetLevelText(int Level) { |
...
string Ret = "You |
...
have udders.\n"; return Ret; } public override |
...
bool |
...
BeforeRender( |
...
Event |
...
E) { |
...
if (ParentObject.IsPlayer()) { |
...
|
...
|
...
|
...
|
...
if (ParentObject.pPhysics != null && ParentObject.pPhysics.CurrentCell != null) |
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
{ |
...
|
...
|
...
|
...
|
...
ParentObject.pPhysics.CurrentCell.ParentZone.AddLight(ParentObject.pPhysics.CurrentCell.X, ParentObject.pPhysics.CurrentCell.Y, Level, LightLevel.Darkvision); |
...
|
...
|
...
} |
...
|
...
|
...
|
...
|
...
|
...
} |
...
return true; |
...
|
...
|
...
|
...
} |
...
|
...
public override bool FireEvent(Event E) |
...
|
...
|
...
|
...
|
...
|
...
{ |
...
|
...
|
...
return |
...
base. |
...
FireEvent( |
...
E); } |
...
...
|
...
|
...
|
...
|
...
public override bool ChangeLevel(int NewLevel) { |
...
...
|
...
|
...
return true; |
...
} public override bool Mutate(GameObject GO, |
...
int Level) { |
...
|
...
|
...
|
...
|
...
return true; } |
...
public override |
...
bool Unmutate(GameObject GO) { |
...
return true; } } |
...
}
|
Here's a full example of the Flaming Hands mutation from the game's source code.
Code Block | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
using System; using System.Collections.Generic; using XRL.UI; using ConsoleLib.Console; namespace XRL.World.Parts.Mutation { [Serializable] class FlamingHands : BaseMutation { |
...
public FlamingHands( |
...
) |
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
{ Name = "FlamingHands"; DisplayName = "Flaming |
...
Hands"; |
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
} public Guid FlamingHandsActivatedAbilityID = Guid.Empty; public ActivatedAbilityEntry FlamingHandsActivatedAbility = null; |
...
|
...
|
...
|
...
|
...
|
...
public |
...
override |
...
void Register(GameObject Object) { Object.RegisterPartEvent(this, "BeginEquip"); |
...
Object.RegisterPartEvent(this, "CommandFlamingHands"); |
...
Object.RegisterPartEvent(this, "AIGetOffensiveMutationList"); |
...
} |
...
|
...
|
...
|
...
public override string GetDescription() { return "You emit jets of flame from your hands."; |
...
|
...
|
...
|
...
|
...
} public override string GetLevelText(int Level) |
...
{ string Ret = "Emits a 9-square |
...
ray |
...
of |
...
flame |
...
in the direction of your choice\n"; Ret += "Cooldown: |
...
10 rounds\n"; Ret += "Damage: " + Level |
...
+ "d6\n"; Ret += "Cannot wear gloves"; |
...
|
...
|
...
|
...
return Ret; } public void Flame(Cell |
...
C, ScreenBuffer Buffer) { string Damage = Level + |
...
" |
...
d6" |
...
; Body pBody = ParentObject.GetPart("Body") as Body; |
...
|
...
int nHandCount = pBody.GetPart("Hands").Count-1; if (nHandCount |
...
> 0) Damage += "+" + nHandCount.ToString(); if (C != null) |
...
{ |
...
List<GameObject> Objects = C.GetObjectsInCell(); |
...
foreach (GameObject GO in Objects) |
...
{ |
...
|
...
|
...
|
...
|
...
|
...
if( GO.PhasedMatches( ParentObject ) ) |
...
...
|
...
|
...
|
...
{ |
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
GO.FireEvent(Event.New("TemperatureChange", "Amount", 310 + (30 * Level), "Owner", ParentObject)); |
...
|
...
|
...
|
...
|
...
|
...
|
...
for (int x = 0; x < 5; x++) GO.ParticleText("&r |
...
" + (char)(219 + Rules.Stat.Random( |
...
0, 4)), 2.9f, |
...
1); |
...
|
...
|
...
|
...
|
...
|
...
|
...
for (int x = 0; x < |
...
5; x++) GO.ParticleText("&R" + (char)(219 + Rules.Stat.Random(0, 4)), 2.9f, 1); |
...
|
...
|
...
|
...
|
...
|
...
|
...
for |
...
(int |
...
x = |
...
0; x < 5; x++) GO.ParticleText("&W" + (char)(219 + Rules.Stat.Random(0, 4)), 2.9f, 1); |
...
|
...
} } |
...
|
...
|
...
|
...
|
...
|
...
foreach (GameObject GO in |
...
C.GetObjectsWithPart("Combat")) |
...
{ |
...
if( GO.PhasedMatches( |
...
ParentObject ) ) |
...
|
...
|
...
|
...
|
...
{
|
...
...
|
...
|
...
Damage Dmg = new |
...
Damage(Rules.Stat.Roll(Damage)); |
...
|
...
|
...
Dmg.AddAttribute("Fire"); |
...
|
...
|
...
|
...
Dmg. |
...
AddAttribute(" |
...
Heat") |
...
; |
...
Event eTakeDamage = |
...
Event.New("TakeDamage"); |
...
|
...
|
...
|
...
|
...
|
...
|
...
eTakeDamage.AddParameter("Damage", Dmg); |
...
|
...
eTakeDamage.AddParameter("Owner", ParentObject); |
...
|
...
|
...
|
...
|
...
eTakeDamage.AddParameter("Attacker", ParentObject); |
...
|
...
eTakeDamage.AddParameter("Message", "from %o flames!"); |
...
|
...
GO.FireEvent(eTakeDamage); |
...
|
...
|
...
|
...
|
...
} |
...
|
...
|
...
|
...
|
...
|
...
} |
...
|
...
|
...
|
...
} |
...
|
...
Buffer.Goto(C.X, C.Y); |
...
|
...
|
...
|
...
string sColor = "&C"; |
...
int r = Rules.Stat.Random(1, 3); if ( |
...
r == 1) sColor = "&R"; if (r == 2) sColor = "&r"; |
...
if (r == 3) sColor = "&W"; |
...
|
...
r = Rules.Stat.Random(1, 3); if (r == 1) sColor |
...
+= "^R"; if (r == 2) sColor += "^r"; if (r == 3) sColor |
...
+= "^W"; if( C.ParentZone == XRL.Core.XRLCore.Core.Game.ZoneManager.ActiveZone ) { |
...
|
...
r = Rules.Stat.Random(1, 3); |
...
Buffer.Write(sColor + (char)(219 + Rules.Stat.Random(0, 4))); |
...
Popup._TextConsole.DrawBuffer(Buffer); |
...
System.Threading.Thread.Sleep(10); } } public override bool |
...
FireEvent(Event |
...
E) { if (E.ID == "AIGetOffensiveMutationList") { |
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
int |
...
Distance |
...
= (int)E.GetParameter("Distance"); GameObject Target = E.GetParameter("Target") as GameObject; |
...
List<XRL.World.AI.GoalHandlers.AICommandList> CommandList = (List<XRL.World.AI.GoalHandlers.AICommandList>)E.GetParameter("List"); |
...
|
...
|
...
|
...
|
...
|
...
if (FlamingHandsActivatedAbility != |
...
null && FlamingHandsActivatedAbility.Cooldown <= 0 && Distance <= 9 && ParentObject.HasLOSTo(Target) ) CommandList.Add(new XRL.World.AI.GoalHandlers.AICommandList("CommandFlamingHands", 1)); |
...
return true; } |
...
|
...
|
...
|
...
if (E.ID == "CommandFlamingHands") |
...
|
...
{ |
...
ScreenBuffer Buffer = new ScreenBuffer(80, 25); |
...
Core.XRLCore.Core.RenderMapToBuffer(Buffer); List<Cell> TargetCell = PickLine(9, AllowVis.Any); |
...
if (TargetCell == null) return true; if |
...
(TargetCell.Count <= |
...
0) return true; if (TargetCell != null) |
...
{ if (TargetCell.Count == 1) |
...
{ |
...
|
...
if (ParentObject.IsPlayer()) |
...
|
...
if (UI.Popup.ShowYesNoCancel("Are you sure you want to target yourself?") != DialogResult.Yes) |
...
|
...
|
...
|
...
|
...
{ |
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
return true; |
...
|
...
|
...
|
...
} |
...
|
...
} |
...
|
...
if( FlamingHandsActivatedAbility != null |
...
) FlamingHandsActivatedAbility.Cooldown = 110; |
...
ParentObject.FireEvent(Event.New("UseEnergy", "Amount", 1000, "Type", "Physical Mutation")); |
...
|
...
for (int x = |
...
0; x < 9 && x < TargetCell.Count; x++) |
...
|
...
{ |
...
|
...
if (TargetCell.Count == 1 || TargetCell[x] != ParentObject.pPhysics.CurrentCell) |
...
|
...
|
...
|
...
Flame(TargetCell[x],Buffer); |
...
|
...
|
...
|
...
foreach( |
...
GameObject |
...
GO |
...
in TargetCell[x].GetObjectsWithPart("Physics") ) |
...
|
...
|
...
|
...
{ |
...
|
...
|
...
|
...
|
...
|
...
if (GO.pPhysics.Solid) |
...
|
...
|
...
...
|
...
|
...
|
...
{ |
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
x = 999; |
...
|
...
|
...
|
...
|
...
|
...
|
...
break; |
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
} |
...
} |
...
|
...
|
...
} |
...
|
...
|
...
} } |
...
if (E.ID == "BeginEquip") |
...
|
...
{ |
...
|
...
|
...
|
...
GameObject |
...
Equipment |
...
= E.GetParameter("Object") as GameObject; |
...
string BodyPartName = |
...
E. |
...
GetParameter(" |
...
BodyPartName") as string; |
...
if |
...
(BodyPartName == |
...
" |
...
Hands") |
...
{ |
...
if |
...
(IsPlayer()) |
...
{ |
...
|
...
|
...
|
...
UI.Popup. |
...
Show(" |
...
Your |
...
flaming hands prevents you from equipping " + Equipment.DisplayName + "!"); |
...
|
...
|
...
|
...
} |
...
|
...
|
...
|
...
|
...
E.bCancelled = |
...
true; |
...
|
...
|
...
|
...
|
...
return false; |
...
|
...
|
...
|
...
} } |
...
|
...
|
...
|
...
return true; |
...
} |
...
int |
...
OldFlame |
...
= -1 |
...
;
|
...
int OldVapor |
...
= -1 |
...
; |
...
|
...
|
...
public override bool ChangeLevel(int NewLevel) |
...
|
...
|
...
{ Physics pPhysics |
...
= ParentObject.GetPart("Physics") as Physics; TemperatureOnHit pTemp = |
...
FlamesObject.GetPart("TemperatureOnHit") as TemperatureOnHit; |
...
pTemp.Amount = (Level*2) + "d8"; return base.ChangeLevel(NewLevel); } |
...
|
...
|
...
|
...
|
...
|
...
public override bool Mutate(GameObject GO, int Level) |
...
|
...
|
...
|
...
{ |
...
Unmutate(GO); |
...
ActivatedAbilities |
...
pAA = |
...
GO. |
...
GetPart(" |
...
ActivatedAbilities") |
...
as ActivatedAbilities; Physics pPhysics |
...
= GO.GetPart("Physics") as Physics; |
...
if ( |
...
pPhysics != null) { |
...
OldFlame = pPhysics.FlameTemperature; |
...
OldVapor = pPhysics.VaporTemperature; } |
...
Body pBody = |
...
GO. |
...
GetPart("Body") as Body; if (pBody != null) |
...
{ GO.FireEvent(Event.New("CommandForceUnequipObject", |
...
"BodyPartName", "Hands")); |
...
FlamesObject = GameObjectFactory.Factory.CreateObject("Ghostly Flames"); |
...
Event eCommandEquipObject = Event.New("CommandEquipObject"); |
...
|
...
|
...
|
...
eCommandEquipObject.AddParameter("Object", FlamesObject); |
...
|
...
eCommandEquipObject.AddParameter("BodyPartName", "Hands"); |
...
GO. |
...
FireEvent( |
...
eCommandEquipObject); } |
...
|
...
|
...
FlamingHandsActivatedAbilityID = pAA.AddAbility("Flaming Hands", "CommandFlamingHands", |
...
"Physical Mutation"); FlamingHandsActivatedAbility |
...
= pAA.AbilityByGuid[FlamingHandsActivatedAbilityID]; |
...
return |
...
...
Code Block |
---|
using System;
using System.Collections.Generic;
using XRL.UI;
using ConsoleLib.Console;
namespace XRL.World.Parts.Mutation
{
[Serializable]
class FlamingHands : BaseMutation
{ |
Get level text is called to generate the text for a given level of the mutation.
...
true; } public GameObject FlamesObject = null; public override bool Unmutate(GameObject GO) |
...
|
...
|
...
|
...
{ |
...
|
...
Physics pPhysics = GO.GetPart("Physics") as Physics; |
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
if |
...
(pPhysics |
...
!= |
...
null) |
...
|
...
{ |
...
|
...
|
...
|
...
|
...
if |
...
(OldFlame != -1) pPhysics.FlameTemperature = OldFlame; if |
...
(OldVapor |
...
!= |
...
-1) pPhysics.BrittleTemperature = OldVapor; OldFlame |
...
= |
...
-1; |
...
Change level is called any time the mutation changes level.
...
OldVapor = -1; |
...
|
...
|
...
|
...
pPhysics.Temperature = 25; |
...
} |
...
|
...
|
...
|
...
|
...
|
...
|
...
Body |
...
pBody = |
...
GO.GetPart(" |
...
Body") as |
...
Body; if |
...
(pBody != |
...
null) |
...
|
...
{ |
...
BodyPart pMainBody = pBody.GetPartByName("Hands"); |
...
Mutate and Unmutate are called on an object when it gains or loses the mutation.
...
if( pMainBody != null )
if (pMainBody.Equipped != null)
{
if (pMainBody.Equipped.Blueprint == "Ghostly Flames")
{
pMainBody.Equipped.FireEvent(Event.New("Unequipped", "UnequippingObject", ParentObject, "BodyPart", pMainBody));
pMainBody.Unequip();
}
}
}
if (FlamingHandsActivatedAbilityID != Guid.Empty)
{
ActivatedAbilities pAA = GO.GetPart("ActivatedAbilities") as ActivatedAbilities;
pAA.RemoveAbility(FlamingHandsActivatedAbilityID);
FlamingHandsActivatedAbilityID = Guid.Empty;
}
return true;
}
}
} |
Your namespace should be XRL.World.Parts.Mutations, the class should be marked serializeable and derived from BaseMutation.
Code Block |
---|
using System;
using System.Collections.Generic;
using XRL.UI;
using ConsoleLib.Console;
namespace XRL.World.Parts.Mutation
{
[Serializable]
class FlamingHands : BaseMutation
{ |
GetDescription and GetLevelText are called to generate the descriptive for a given level of the mutation.
Code Block |
---|
public override string GetDescription()
{
return "You emit jets of flame from your hands.";
}
public override string GetLevelText(int Level)
{
string Ret = "Emits a 9-square ray of flame in the direction of your choice\n";
Ret += "Cooldown: 10 rounds\n";
Ret += "Damage: " + Level + "d6\n";
Ret += "Cannot wear gloves";
return Ret;
} |
Change level is called any time the mutation changes level.
Code Block |
---|
public override bool ChangeLevel(int NewLevel)
{
Physics pPhysics = ParentObject.GetPart("Physics") as Physics;
TemperatureOnHit pTemp = FlamesObject.GetPart("TemperatureOnHit") as TemperatureOnHit;
pTemp.Amount = (Level*2) + "d8";
return base.ChangeLevel(NewLevel);
} |
Mutate and Unmutate are called on an object when it gains or loses the mutation.
Code Block |
---|
public override bool Mutate(GameObject GO, int Level)
public override bool Unmutate(GameObject GO) |
BaseMutation derives from Part, so the typical event registration and handling functions are available
Code Block |
---|
public override void Register(GameObject Object)
public override bool FireEvent(Event E) |
Info | ||
---|---|---|
You can remove mutations by including a tag with just the Name of the mutation you want with a - in front. For example:
|