(C#) How do i expand code?

Started by Evul, June 23, 2014, 06:29:41 PM

Previous topic - Next topic

Evul

How do i add text to for example RaceProperties without copying and rewriting the entire code?

using System;
using RaceProperties;


namespace Verse
{
public class RaceProperties
{
public bool mylittlerace;
}
}

Haplo

#1
You want to extend an existing class, right?
You can do so by doing this:

public class building_mynewbuilding : building_bed

Now the class has all the functions of the original building_bed. If you override a function of the original with your own function, you can write the code completely new, or you can use the base.functionname to call the original function and let it do its work. Before or after you do your own work.

public override void Tick()
{
    base.Tick();
    ...
}

Override only works, if the base is declared as overrideable.
Does this little rambling help, or have I misunderstood your question?

Evul

#2
Ok the Building_TurretGun seams to work but when i try to add arachnid to the RaceProperties_Arachnid it seams to mess things up. it gives me this error:
Quote...\ArachnidThreatDev\xDev\C#\Arachnid\Arachnid\RaceProperties_Arachnid.cs(40,40): Error CS0246: The type or namespace name 'RaceProperties' could not be found (are you missing a using directive or an assembly reference?) (CS0246) (Arachnid)


Building_TurretGun.cs
using System;
using Verse;
using Verse.AI;
public class Building_TurretGunTarget : Building_Turret
{
public override void Tick()
{
base.Tick();
Predicate<Thing> validator = delegate(Thing t)
{
Pawn pawn = t as Pawn;
return pawn == null || ((pawn.RaceDef.humanoid || pawn.RaceDef.mechanoid || pawn.RaceDef.arachnid) && !GenAI.MachinesLike(base.Faction, pawn));
};
this.target = GenAI.BestShootTarget(base.Position, this, RegionTraverseParameters.For(DoorTraverseMode.NoPassDoors), validator, this.gun.def.verb.range, true, true, !this.gun.def.verb.ai_IsIncendiary);
if (this.target != null && this.gun.verb.TryStartCastOn(new TargetPack(this.target)))
{
this.gun.verb.castCompleteCallback = new Action(this.BurstComplete);
}
}
}



RaceProperties_Arachnid.cs
using System;

public class RaceProperties_Arachnid : RaceProperties
{
public bool arachnid;
}


EDIT:
I also get error on the Building_TurretGun...

Quote...\ArachnidThreatDev\xDev\C#\Arachnid\Arachnid\Building_TurretGun.cs(14,14): Error CS0534: 'Building_TurretGun' does not implement inherited abstract member 'Building_Turret.CurrentTarget.get' (CS0534) (Arachnid)

Haplo

You also need to change the class in your XML to your new class, else it is there but won't be used at all :)
Change 'Building_TurretGun' to 'YourAssembly.Building_TurretGunTarget'

Evul

is it just possible to make a overwrite?
Cause i want it to work on other mods turrets?

Evul

#5
have been talking to mrofa in PM and have some progress:

Here are the sitrep now:

Building_TurretGun.cs
using System;
using Verse;
using Verse.AI;

namespace Arachnid_Mod
{
public class My_Building_TurretGun : Building_Turret
{
protected Equipment gun;
protected TurretTop top;
protected CompPowerTrader powerComp;
protected Thing target;
protected int burstCooldownTicksLeft;
public override Thing CurrentTarget
{
get
{
return this.target;
}
}
public override void SpawnSetup()
{
base.SpawnSetup();
this.powerComp = base.GetComp<CompPowerTrader>();
this.gun = (Equipment)ThingMaker.MakeThing(this.def.building.turretGunDef);
this.gun.InitVerb();
this.gun.verb.owner = this;
this.top = new TurretTop(this);
}
public override void ExposeData()
{
base.ExposeData();
Scribe_Values.LookValue<int>(ref this.burstCooldownTicksLeft, "burstCooldownTicksLeft", 0, false);
}
public override void Tick()
{
base.Tick();
this.gun.verb.VerbTick();
if (this.stunner.Stunned || !this.powerComp.PowerOn)
{
return;
}
if (this.gun.verb.state == VerbState.Bursting)
{
return;
}
if (this.burstCooldownTicksLeft > 0)
{
this.burstCooldownTicksLeft--;
}
if (this.burstCooldownTicksLeft <= 0)
{
this.TryStartShoot();
}
this.top.TurretTopTick();
}
public override void Draw()
{
this.top.DrawTurret();
base.Draw();
}
public override void DrawExtraSelectionOverlays()
{
GenDraw.DrawRadiusRing(base.Position, this.def.building.turretGunDef.verb.range);
}
protected void TryStartShoot()
{
Predicate<Thing> validator = delegate(Thing t)
{
Pawn pawn = t as Pawn;
return pawn == null || ((pawn.RaceDef.humanoid || pawn.RaceDef.mechanoid || pawn.RaceDef.arachnid) && !GenAI.MachinesLike(base.Faction, pawn));
};
this.target = GenAI.BestShootTarget(base.Position, this, RegionTraverseParameters.For(DoorTraverseMode.NoPassDoors), validator, this.gun.def.verb.range, true, true, !this.gun.def.verb.ai_IsIncendiary);
if (this.target != null && this.gun.verb.TryStartCastOn(new TargetPack(this.target)))
{
this.gun.verb.castCompleteCallback = new Action(this.BurstComplete);
}
}
protected void BurstComplete()
{
this.burstCooldownTicksLeft = this.def.building.burstCooldownTicks;
}
public override string GetInspectString()
{
return string.Concat(new string[]
{
"GunInstalled".Translate(),
": ",
this.gun.Label,
"\n",
base.GetInspectString()
});
}
}
}


RaceProperties.cs
using System;

namespace Arachnid_Mod
{
public class My_RaceProperties : RaceProperties
{
public const float DefaultPawnMoveTicks = 14f;
public ThinkTreeDef thinkTree;
public NameCategory nameCategory;
public float walkSpeed = 1f;
public int meleeDamage = 10;
public bool isFlesh = true;
public bool hasGenders = true;
public bool hasStory;
public bool humanoid;
public bool mechanoid;
public bool arachnid;
public FoodQuality minFoodQuality;
public DietType diet = DietType.Omnivorous;
public float hungerThreshold;
public bool needsRest = true;
public float bodySize = 1f;
public float meatAmountMultiplier = 1f;
public DeathActionType deathActionType;
public SoundDef soundDeath;
public SoundDef soundWounded;
public SoundDef soundMeleeHitPawn;
public SoundDef soundMeleeHitBuilding;
public SoundDef soundMeleeMiss;
public ThingDef meatDef;
public ThingDef corpseDef;
public Action<Pawn> deathAction;
public float baseMoveTicks_Cardinal;
public float baseMoveTicks_Diagonal;
public bool UsesEquipment
{
get
{
return this.humanoid || this.mechanoid;
}
}
public bool GloballyAware
{
get
{
return this.humanoid || this.mechanoid;
}
}
public bool CanUseTechnology
{
get
{
return this.humanoid || this.mechanoid;
}
}
public bool EatsFood
{
get
{
return this.diet != DietType.NeverEats;
}
}
public bool MakesFootprints
{
get
{
return this.humanoid;
}
}
public bool IsAnimal
{
get
{
return !this.humanoid && this.isFlesh;
}
}
public bool CanEat(Thing t)
{
if (t.def.food == null)
{
return false;
}
if (this.minFoodQuality > t.def.food.quality)
{
return false;
}
if (this.diet != DietType.Omnivorous)
{
if (this.diet == DietType.Herbivorous && t.def.food.isMeat)
{
return false;
}
if (this.diet == DietType.Carnivorous && !t.def.food.isMeat)
{
return false;
}
}
return true;
}
public void PostLoad()
{
float num = 1f / this.walkSpeed;
this.baseMoveTicks_Cardinal = (float)((int)Math.Round((double)(14f * num)));
this.baseMoveTicks_Diagonal = (float)((int)Math.Round((double)(14f * num * 1.41f)));
if (this.deathActionType == DeathActionType.ExplodeFlame)
{
this.deathAction = delegate(Pawn p)
{
Explosion.DoExplosion(p.Position, 1.9f, DamageTypeDefOf.Flame, p);
};
}
}
}
}


RaceProperties get 9 errors:

Quote...\ArachnidThreatDev\xDev\C#\Arachnid\Arachnid\RaceProperties.cs(35,35): Error CS0246: The type or namespace name 'RaceProperties' could not be found (are you missing a using directive or an assembly reference?) (CS0246) (Arachnid)

Quote...\ArachnidThreatDev\xDev\C#\Arachnid\Arachnid\RaceProperties.cs(10,10): Error CS0246: The type or namespace name 'ThinkTreeDef' could not be found (are you missing a using directive or an assembly reference?) (CS0246) (Arachnid)

Quote...\ArachnidThreatDev\xDev\C#\Arachnid\Arachnid\RaceProperties.cs(10,10): Error CS0246: The type or namespace name 'NameCategory' could not be found (are you missing a using directive or an assembly reference?) (CS0246) (Arachnid)

Quote...\ArachnidThreatDev\xDev\C#\Arachnid\Arachnid\RaceProperties.cs(10,10): Error CS0246: The type or namespace name 'DietType' could not be found (are you missing a using directive or an assembly reference?) (CS0246) (Arachnid)

Quote...\ArachnidThreatDev\xDev\C#\Arachnid\Arachnid\RaceProperties.cs(10,10): Error CS0246: The type or namespace name 'DeathActionType' could not be found (are you missing a using directive or an assembly reference?) (CS0246) (Arachnid)

Quote...\ArachnidThreatDev\xDev\C#\Arachnid\Arachnid\RaceProperties.cs(10,10): Error CS0246: The type or namespace name 'ThingDef' could not be found (are you missing a using directive or an assembly reference?) (CS0246) (Arachnid)

Quote...\ArachnidThreatDev\xDev\C#\Arachnid\Arachnid\RaceProperties.cs(10,10): Error CS0246: The type or namespace name 'ThingDef' could not be found (are you missing a using directive or an assembly reference?) (CS0246) (Arachnid)

Quote...\ArachnidThreatDev\xDev\C#\Arachnid\Arachnid\RaceProperties.cs(17,17): Error CS0246: The type or namespace name 'Pawn' could not be found (are you missing a using directive or an assembly reference?) (CS0246) (Arachnid)

Quote...\ArachnidThreatDev\xDev\C#\Arachnid\Arachnid\RaceProperties.cs(22,22): Error CS0246: The type or namespace name 'Thing' could not be found (are you missing a using directive or an assembly reference?) (CS0246) (Arachnid)

The ONLY thing I've added to RaceProperties is: public bool arachnid;



ADD:
If i ignore the RaceProperties entirely i get one error in the Building_TurretGun on the line 71:
return pawn == null || ((pawn.RaceDef.humanoid || pawn.RaceDef.mechanoid || pawn.RaceDef.arachnid) && !GenAI.MachinesLike(base.Faction, pawn));
on: arachnid

Quote...\ArachnidThreatDev\xDev\C#\Arachnid\Arachnid\Building_TurretGun.cs(94,94): Error CS1061: 'Verse.RaceProperties' does not contain a definition for 'arachnid' and no extension method 'arachnid' accepting a first argument of type 'Verse.RaceProperties' could be found (are you missing a using directive or an assembly reference?) (CS1061) (Arachnid_Mod)

Haplo

In your My_RaceProperties the usings are missing.
Because of that your compiler doesn't find the RimWorld sources :)

using System;
using Verse;
using Verse.AI;


Another thing:
If you make a full new item, without the use of something from the base, don't use the base.
In your public class My_RaceProperties : RaceProperties the using of the RaceProperties is not needed or even possible. First, because the functions/variables aren't overridable, abstract or something similiar, so you can not really use them. Second, you have already copied everything out of the base to use it, so you don't need the refference to it anymore. It will only cause strange errors :)


CB elite

I know this forum is kind of old, but all of the information here is relevant. I'm looking to create a race property myself, and I kind of tried to follow the conversation that took place here to accomplish that.

The .dll code for adding unggoy and sangheili races:
using RimWorld;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using UnityEngine;
using Verse;

namespace Haloverse_Covenant
{
    public class Covenant_RaceProperties : RaceProperties
{
public const float BaseButcherMeatAmount = 90f;
public const float BaseButcherLeatherAmount = 20f;
public Intelligence intelligence;
public bool mechanoid;
                public bool unggoy;
                public bool sangheili;
public bool isFlesh = true;
public bool hasGenders = true;
public ThinkTreeDef thinkTree;
public PawnNameCategory nameCategory;
public AIFoodPreferability minFoodPreferability;
public DietType diet;
public float hungerRate = 1f;
public bool needsRest = true;
public BodyDef body;
public float bodySize = 1f;
public float healthScale = 1f;
public string meatLabel;
public float meatAmountMultiplier = 1f;
public DeathActionType deathActionType;
public List<BiomeAnimalRecord> wildBiomes;
public SimpleCurve ageGenerationCurve;
public bool makesFootprints;
public int executionRange = 2;
public bool herdAnimal;
public bool hasLeather;
public Color leatherColor = ColorLibrary.Leather;
public string leatherLabel;
public float leatherCommonalityFactor = 1f;
public float leatherInsulation = 1.1f;
public List<StatModifier> leatherStatFactors;
public float leatherMarketValue = 3.5f;
public bool graphicOverdraw;
public ShadowInfo shadowInfo;
public SoundDef soundWounded;
public SoundDef soundDeath;
public SoundDef soundAngry;
public SoundDef soundCall;
public IntRange soundCallIntervalRange = new IntRange(2000, 4000);
public SoundDef soundMeleeHitPawn;
public SoundDef soundMeleeHitBuilding;
public SoundDef soundMeleeMiss;
[Unsaved]
public ThingDef meatDef;
[Unsaved]
public ThingDef leatherDef;
[Unsaved]
public ThingDef corpseDef;
[Unsaved]
public Action<Pawn> deathAction;
public bool Humanlike
{
get
{
return this.intelligence >= Intelligence.Humanlike;
}
}
public bool ToolUser
{
get
{
return this.intelligence >= Intelligence.ToolUser;
}
}
public bool Animal
{
get
{
return !this.ToolUser && this.isFlesh;
}
}
public bool EatsFood
{
get
{
return this.diet != DietType.NeverEats;
}
}
public float FoodLevelWantEat
{
get
{
if (this.Humanlike)
{
return 0.3f;
}
return 0.65f;
}
}
public float MeatAmount
{
get
{
return 90f * this.bodySize * this.meatAmountMultiplier;
}
}
public float LeatherAmount
{
get
{
return 20f * this.bodySize;
}
}
public bool WillAutomaticallyEat(Thing t)
{
return t.def.ingestible != null && t.def.ingestible.preferability >= this.minFoodPreferability && this.CanEverEat(t);
}
public bool CanEverEat(Thing t)
{
if (t.def.ingestible == null)
{
return false;
}
if (this.Animal)
{
if (t.def.ingestible.preferability < AIFoodPreferability.Plant)
{
return false;
}
}
else
{
if (t.def.ingestible.preferability < AIFoodPreferability.NeverForNutrition)
{
return false;
}
}
if (this.diet == DietType.Dendrovorous)
{
if (t.def.plant == null || !t.def.plant.IsTree)
{
return false;
}
}
else
{
if (t.def.plant != null && t.def.plant.IsTree)
{
return false;
}
}
if (this.diet != DietType.Omnivorous)
{
if (this.diet == DietType.Herbivorous && t.def.ingestible.IsMeat)
{
return false;
}
if (this.diet == DietType.Carnivorous && !t.def.ingestible.IsMeat)
{
return false;
}
}
return true;
}
[DebuggerHidden]
public void PostLoadSpecial()
{
if (this.deathActionType == DeathActionType.ExplodeFlame)
{
this.deathAction = delegate(Pawn p)
{
GenExplosion.DoExplosion(p.Position, 1.9f, DamageDefOf.Flame, p, null, null);
};
}
}
}
}


A portion of xml in an unggoy race def:
<race>
  <graphicOverdraw>true</graphicOverdraw>
      <intelligence>ToolUser</intelligence>
      <thinkTree>Humanlike</thinkTree>
      <body>Unggoy</body>
  <unggoy>true</unggoy>
      <bodySize>1.0</bodySize>
      <healthScale>1.0</healthScale>
      <meatAmountMultiplier>0.5</meatAmountMultiplier>
      <soundWounded>Pawn_Human_Wounded</soundWounded>
      <soundDeath>Pawn_Human_Death</soundDeath>
      <soundCall>Pawn_Grunt_Calls</soundCall>
      <soundCallIntervalRange>
        <min>5000</min>
        <max>100000</max>
      </soundCallIntervalRange>
      <soundAngry>Pawn_Grunt_Angry</soundAngry>
      <soundMeleeHitPawn>Pawn_Melee_Punch_HitPawn</soundMeleeHitPawn>
      <soundMeleeHitBuilding>Pawn_Melee_Punch_HitBuilding</soundMeleeHitBuilding>
      <soundMeleeMiss>Pawn_Melee_Punch_Miss</soundMeleeMiss>
  <shadowInfo>
        <baseWidth>0.4</baseWidth>
        <baseHeight>0.4</baseHeight>
        <tallness>0.8</tallness>
      </shadowInfo>
    </race>


xml error: <unggoy>true</unggoy> doesn't correspond to any field in type RaceProperties?

I have a feeling that I'm missing something super simple (still learning to appreciate the complexities of .dll modding).

Haplo

You need to tell the parser to use your class and not the base class.
To do that you need to expand the race tag:
<race Class="namespace.classname">

CB elite

#9
Your response is much appreciated :) Especially since this forum was started so long ago.

When referencing this in other classes, would I say, for instance:

if (this.pawn.PositionHeld.InBounds() && this.pawn.RaceProps.unggoy && !this.pawn.InContainer && Rand.Value < 0.5f)
{
FilthMaker.MakeFilth(this.pawn.PositionHeld, ThingDefOf.FilthUnggoyBlood, this.pawn.LabelBaseShort);
}


Or, do I need to expand anything here as well? :)

Yeah, no, that doesn't work at all. "pawn" seems to be automatically assumed as verse.pawn and not myNamespace.pawn (i made one in an attempt to fix). Not quite sure what I need to add where to get the code to reference myNamespace.pawn instead of verse.pawn. I should probably take an online course in C#, to be honest :-[

But for now, I just want my .dll to be able to recognize my new race property so I can give my alien pawns a nifty new TryDropBloodFilth() function ;D

RawCode

very special note:

methods not marked "virtual" wont work, internal routines will still invoke "superclass" unmodded methods.

If you want to override method not marked virtual, you will have really bad time.

CB elite

Quote from: RawCode on July 21, 2015, 05:26:17 AM
very special note:

methods not marked "virtual" wont work, internal routines will still invoke "superclass" unmodded methods.

If you want to override method not marked virtual, you will have really bad time.

Hm, well that's a pain. Is there any way I can reference the <body>mybody</body> from the xml into an if/then statement? It would still be under pawn.RaceProps, but I don't know exactly what would come after that?