Ludeon Forums

RimWorld => Mods => Help => Topic started by: e39a562r on December 19, 2014, 09:35:08 AM

Title: [A8] Hello? Any source code about StockGenerators?
Post by: e39a562r on December 19, 2014, 09:35:08 AM
I'm try to make a StockGenerator_Girls

But i got lots of compiler-generated things when i decompile the Assembly-CSharp.dll

Quote
   public class StockGenerator_Slaves : StockGenerator
   {
      [DebuggerHidden]
      public override IEnumerable<Thing> GenerateThings()
      {
         StockGenerator_Slaves.<GenerateThings>c__Iterator93 <GenerateThings>c__Iterator = new StockGenerator_Slaves.<GenerateThings>c__Iterator93();
         <GenerateThings>c__Iterator.<>f__this = this;
         StockGenerator_Slaves.<GenerateThings>c__Iterator93 expr_0E = <GenerateThings>c__Iterator;
         expr_0E.$PC = -2;
         return expr_0E;
      }
      public override bool HandlesThingDef(ThingDef thingDef)
      {
         return thingDef.category == EntityCategory.Pawn && thingDef.race.humanoid;
      }
   }

I can't figure out where the pawns are generated

Could someone help me?
Title: Re: [A8] Hello? Any source code about StockGenerators?
Post by: Rikiki on December 19, 2014, 02:38:59 PM
I believe this part of the source code is encrypted.
There are other ones in the assembly. Tynan must protect some core functions?...
Title: Re: [A8] Hello? Any source code about StockGenerators?
Post by: Haplo on December 20, 2014, 06:22:08 AM
Nope the code isn't really encrypted. The problem is, that the decompiler just can't decompile specific types of code back to readable c# code. You'll find a whole bunch of such code snippets as Tynan uses such functionality rather often :)
Title: Re: [A8] Hello? Any source code about StockGenerators?
Post by: StorymasterQ on December 22, 2014, 12:13:00 AM
For me, one thing jumps out from that code.

Quote
f__this

It's always a proper reaction for any code.
Title: Re: [A8] Hello? Any source code about StockGenerators?
Post by: unifex on December 22, 2014, 07:49:17 AM
Quote from: StorymasterQ on December 22, 2014, 12:13:00 AM
For me, one thing jumps out from that code.

Quote
f__this

It's always a proper reaction for any code.

Especially when dealing with complex generics. Completely agree.
Title: Re: [A8] Hello? Any source code about StockGenerators?
Post by: skullywag on March 25, 2015, 11:43:24 AM
I really need this code, its the clue to fixing my issue of programmatical traders. Something is failing in trymakestockfor which is called from the generatethings method but i cant see what im not passing correctly as I cant see this code...
Title: Re: [A8] Hello? Any source code about StockGenerators?
Post by: Wastelander on March 25, 2015, 04:21:18 PM
Make sure you have "show compiler-generated code" option enabled if you're using DotPeek.

The part we're interested in is here:

QuoteStockGenerator_Slaves<GenerateThings>c__IteratorA7 thingsCIteratorA7_1 = new StockGenerator_Slaves.<GenerateThings>c__IteratorA7();

search for c__IteratorA7 and if you have the show compiler-generated code option on you'll find a sealed class private to this class named c__IteratorA7.

The operative part of that class that you're interested in is this, I think:

QuoteIEnumerable<Faction> allFactionsVisible = Find.FactionManager.AllFactionsVisible;
if (StockGenerator_Slaves.<GenerateThings>c__IteratorA7.<>f__am$cache7 == null)
{
   // ISSUE: method pointer
   StockGenerator_Slaves.<GenerateThings>c__IteratorA7.<>f__am$cache7 = new Func<Faction, bool>((object) null, __methodptr(<>m__195));
}
Func<Faction, bool> predicate = StockGenerator_Slaves.<GenerateThings>c__IteratorA7.<>f__am$cache7;
this.<slaveFaction>__2 = GenCollection.RandomElement<Faction>(Enumerable.Where<Faction>(allFactionsVisible, predicate));
this.<pawn>__3 = PawnGenerator.GeneratePawn(PawnKindDefOf.Slave, this.<slaveFaction>__2);
this.$current = (Thing) this.<pawn>__3;
this.$PC = 1;
return true;

with the method pointer m__195 evaluating to:

Quoteprivate static bool <>m__195(Faction fac)
      {
        if (fac != Faction.OfColony)
          return fac.def.humanoidFaction;
        return false;
      }

So that's:
1) Getting a list of all visible factions
2) Filtering out the ones that are ofColony or non-humanoid
3) Picking a random faction from that list
4) Generating a pawn of KindDef Slave and of that faction using this line: PawnGenerator.GeneratePawn(PawnKindDefOf.Slave,this.<slaveFaction>E__2);

And I think that's pretty much it, rinse and repeat for however many pawns you need to generate.

What are you trying to do with your stock generator?
Title: Re: [A8] Hello? Any source code about StockGenerators?
Post by: skullywag on March 25, 2015, 06:46:14 PM
See the end of:

https://ludeon.com/forums/index.php?topic=11637.0
Title: Re: [A8] Hello? Any source code about StockGenerators?
Post by: BBream on April 18, 2015, 09:14:57 AM
This is successfully functioned code. It generate slaves. If you want to make girl, define PawnKindDef for girl and put into PawnGenerator.


        public override IEnumerable<Thing> GenerateThings()
        {
            StringBuilder sb = new StringBuilder();
            List<Thing> things = new List<Thing>();
            //ThingDef thingDef = DefDatabase<ThingDef>.GetNamed("Human");

            for(int i = 0; i < RandomCountOf(PawnKindDefOf.Slave.race); i++)
            {
                Thing thing = PawnGenerator.GeneratePawn(PawnKindDefOf.Slave, Faction.OfColony);
                things.Add(thing);
                sb.AppendLine(thing.Label);
                Log.Message("thing:" + thing.ThingID);
            }

            Log.Message("StockGenerator_Animals:");
            Log.Message(sb.ToString());
            return things as IEnumerable<Thing>;
        }
Title: Re: [A8] Hello? Any source code about StockGenerators?
Post by: Tynan on April 20, 2015, 08:36:22 PM
This is the original code for all the StockGenerators.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Verse;
using UnityEngine;


namespace RimWorld{

public class StockGenerator_SingleDef : StockGenerator
{
private ThingDef thingDef = null;

public override IEnumerable<Thing> GenerateThings()
{
Thing newThing = TryMakeForStock( thingDef, RandomCountOf( thingDef ) );
if( newThing != null )
yield return newThing;
}

public override bool HandlesThingDef(ThingDef thingDef)
{
return thingDef == this.thingDef;
}
}


public class StockGenerator_Category : StockGenerator
{
private ThingCategoryDef categoryDef = null;
private IntRange thingDefCountRange = IntRange.one;


public override IEnumerable<Thing> GenerateThings()
{
List<ThingDef> generatedDefs = new List<ThingDef>();
int numThingDefsToUse = thingDefCountRange.RandomInRange;
for( int i=0; i<numThingDefsToUse; i++ )
{
ThingDef chosenThingDef;
if( !categoryDef.DescendantThingDefs
.Where( t=> t.tradeability == Tradeability.Stockable && !generatedDefs.Contains(t) )
.TryRandomElement(out chosenThingDef) )
{
//Trader is already carrying every possible thingdef in this set
continue;
}

Thing newThing = TryMakeForStock( chosenThingDef, RandomCountOf( chosenThingDef ) );
if( newThing != null )
{
generatedDefs.Add(newThing.def);
yield return newThing;
}
}
}

public override bool HandlesThingDef(ThingDef thingDef)
{
return categoryDef.DescendantThingDefs.Contains(thingDef);
}
}


public class StockGenerator_Tag : StockGenerator
{
private string tradeTag = null;
private IntRange thingDefCountRange = IntRange.one;

public override IEnumerable<Thing> GenerateThings()
{
List<ThingDef> generatedDefs = new List<ThingDef>();
int numThingDefsToUse = thingDefCountRange.RandomInRange;
for( int i=0; i<numThingDefsToUse; i++ )
{
ThingDef chosenThingDef;
if( !DefDatabase<ThingDef>.AllDefs.Where( d=>d.tradeTags != null
&& d.tradeability == Tradeability.Stockable
&& d.tradeTags.Contains(tradeTag)
&& !generatedDefs.Contains(d) )
.TryRandomElement(out chosenThingDef) )
yield break;

Thing newThing = TryMakeForStock( chosenThingDef, RandomCountOf( chosenThingDef ) );
if( newThing != null )
{
generatedDefs.Add(newThing.def);
yield return newThing;
}
}
}

public override bool HandlesThingDef(ThingDef thingDef)
{
return thingDef.tradeTags != null && thingDef.tradeTags.Contains(tradeTag);
}
}



public class StockGenerator_Slaves : StockGenerator
{
public override IEnumerable<Thing> GenerateThings()
{
int count = countRange.RandomInRange;
for(int i=0; i<count; i++)
{
Faction slaveFaction = Find.FactionManager.AllFactionsVisible
.Where( fac => fac != Faction.OfColony && fac.def.humanlikeFaction )
.RandomElement();

Pawn pawn = PawnGenerator.GeneratePawn( PawnKindDefOf.Slave, slaveFaction );
yield return pawn;
}
}

public override bool HandlesThingDef(ThingDef thingDef)
{
return thingDef.category == EntityCategory.Pawn && thingDef.race.Humanlike;
}
}

public class StockGenerator_WeaponsRanged : StockGenerator
{
public override IEnumerable<Thing> GenerateThings()
{
int count = countRange.RandomInRange;
for(int i=0; i<count; i++)
{
ThingDef gunDef = DefDatabase<ThingDef>.AllDefs
.Where( t=>t.IsRangedWeapon && t.tradeability == Tradeability.Stockable )
.RandomElement();

var gun = (ThingWithComps)ThingMaker.MakeThing( gunDef );
yield return gun;
}
}

public override bool HandlesThingDef(ThingDef thingDef)
{
return thingDef.IsRangedWeapon;
}
}


public class StockGenerator_Art : StockGenerator
{
public override IEnumerable<Thing> GenerateThings()
{
int count = countRange.RandomInRange;
for(int i=0; i<count; i++)
{
ThingDef artDef = DefDatabase<ThingDef>.AllDefs
.Where( t=> t.tradeability == Tradeability.Stockable && t.IsArtBuilding )
.RandomElement();

Thing art = ThingMaker.MakeThing( artDef, GenStuff.RandomStuffFor(artDef) );

yield return art;
}
}

public override bool HandlesThingDef(ThingDef thingDef)
{
return thingDef.IsArtBuilding;
}
}


public class StockGenerator_Armor : StockGenerator
{
public override IEnumerable<Thing> GenerateThings()
{
int count = countRange.RandomInRange;
for(int i=0; i<count; i++)
{
ThingDef thingDef = DefDatabase<ThingDef>.AllDefs
.Where( td=> IsValidThing(td) )
.RandomElement();

Thing thing = ThingMaker.MakeThing( thingDef, GenStuff.RandomStuffFor( thingDef ) );
yield return thing;
}
}

private bool IsValidThing(ThingDef td )
{
return td.tradeability == Tradeability.Stockable
&& td.IsApparel
&& (td.GetStatValueAbstract( StatDefOf.ArmorRating_Blunt ) > 0.15f
|| td.GetStatValueAbstract( StatDefOf.ArmorRating_Sharp ) > 0.15f );
}

public override bool HandlesThingDef(ThingDef thingDef)
{
return IsValidThing(thingDef);
}
}
}
Title: Re: [A8] Hello? Any source code about StockGenerators?
Post by: BBream on April 21, 2015, 12:22:12 AM
Example is good and good example is great!
Thanks Tynan! It has a lot of things to learn.