Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - Project 06

#1
I have several custom floors I've added into the game. However for some reason one specific floor keeps generating in place of ruins. For example, a Sandstone ruin may generate this floor in place of a normal sandstone floor. Back when I added these floors in Alpha 16, this issue was not present. This floor is derived from the vanilla stone flooring, but so are 5 other floors and I've yet to see these ones generate in a world. I tried changing the recipe(which was originally 2 of each stone brick) to a custom made item called Concrete, this item in place of the others for the recipe did stop the tile from generating.

Based on this I figured it was because the world started creating floor tiles based on floors using "stony" items for their recipes, but since I haven't seen the other 4 floors that used just one "stony" item I'm thinking this isn't the problem. I even tried adding new types of bricks that these floors exclusively use, this just instead makes the floor generate less often but it still appears.

Anyone have an idea as to why this floor keeps generating?
#2
The reason this is happening is because that's how plants grow from plant pots. If you look at a mature Daylily and Rose from a plant pot you can tell the textures are just centered onto what appears to be the center of the soil of the pot. A potential workaround for this is to try and increase the size of the texture file for your plant from 64x64(presumably this is what that plant texture is sized at) and change it to 128x128. Then offset the art itself so the bottom of the plant is at the center of the canvas. This may work but I'm not sure.
#3
Help / Question About a Graphic Class
May 09, 2018, 05:55:04 AM
What is the purpose of the "Graphic_Collection" class? It appears to not have a place in any Def in the base game so I'm curious what it was designed for. It might help me with something I'm trying to create.
#4
Help / Re: Resource For Updating Old Mods?
May 08, 2018, 06:04:14 AM
Its not a released mod, its just a ton of stuff I've added either because I think it would be nice, or just for more stuff to do. I've finished updating it though, thanks for the help anyways.
#5
Ideas / More Apparel Layers
May 07, 2018, 04:57:16 PM
I discovered that while updating my old mod that some apparel layers were removed, I'm guessing because they weren't used by vanilla items so they were deemed unnecessary. However these extra apparel layers allowed modders such as myself to add new equipment without it interfering with vanilla or standard gear. I tried adding in new layers myself but that required rebuilding a new ThingDefs just for my mod, and wound up also requiring me to rebuild Pawns as well so I knew at that point it would be impractical if not impossible to do this. Just a few extra layers for modders to play with would be great.
#6
Unfortunately I believe the error I posted above is being caused by references in the Pawn class file, which I can't copy without breaking most of the game so I've hit a dead end. Overall It seems impossible to add apparel layers to the game without essentially rebuilding the game itself. The dev team seriously needs to add in unused apparel layers again so modders can add new types of equipment to use without interfering with vanilla items.
#7
I'm currently stuck on this error in the copied apparel tracker:

using System;
using System.Collections.Generic;
using UnityEngine;
using Verse;
using RimWorld;

namespace PEMod
{
    // Token: 0x020004E1 RID: 1249
    public class PEPawn_ApparelTracker : IThingHolder, IExposable
    {
        // Token: 0x06001599 RID: 5529 RVA: 0x000A7220 File Offset: 0x000A5620
        public PEPawn_ApparelTracker(Pawn pawn)
        {
            this.pawn = pawn;
            this.wornApparel = new ThingOwner<PEApparel>(this);
        }

        // Token: 0x170002CC RID: 716
        // (get) Token: 0x0600159A RID: 5530 RVA: 0x000A7242 File Offset: 0x000A5642
        public IThingHolder ParentHolder
        {
            get
            {
                return this.pawn;
            }
        }

        // Token: 0x170002CD RID: 717
        // (get) Token: 0x0600159B RID: 5531 RVA: 0x000A724A File Offset: 0x000A564A
        public List<PEApparel> WornApparel
        {
            get
            {
                return this.wornApparel.InnerListForReading;
            }
        }

        // Token: 0x170002CE RID: 718
        // (get) Token: 0x0600159C RID: 5532 RVA: 0x000A7258 File Offset: 0x000A5658
        public IEnumerable<PEApparel> WornApparelInDrawOrder
        {
            get
            {
                for (int i = 0; i < this.wornApparel.Count; i++)
                {
                    yield return this.wornApparel[i];
                }
                yield break;
            }
        }

        // Token: 0x170002CF RID: 719
        // (get) Token: 0x0600159D RID: 5533 RVA: 0x000A727B File Offset: 0x000A567B
        public int WornApparelCount
        {
            get
            {
                return this.wornApparel.Count;
            }
        }

        // Token: 0x170002D0 RID: 720
        // (get) Token: 0x0600159E RID: 5534 RVA: 0x000A7288 File Offset: 0x000A5688
        public bool PsychologicallyNude
        {
            get
            {
                if (this.pawn.gender == Gender.None)
                {
                    return false;
                }
                bool flag;
                bool flag2;
                this.HasBasicApparel(out flag, out flag2);
                if (!flag)
                {
                    bool flag3 = false;
                    foreach (BodyPartRecord bodyPartRecord in this.pawn.health.hediffSet.GetNotMissingParts(BodyPartHeight.Undefined, BodyPartDepth.Undefined))
                    {
                        if (bodyPartRecord.IsInGroup(BodyPartGroupDefOf.Legs))
                        {
                            flag3 = true;
                            break;
                        }
                    }
                    if (!flag3)
                    {
                        flag = true;
                    }
                }
                if (this.pawn.gender == Gender.Male)
                {
                    return !flag;
                }
                return this.pawn.gender == Gender.Female && (!flag || !flag2);
            }
        }

        // Token: 0x0600159F RID: 5535 RVA: 0x000A736C File Offset: 0x000A576C
        public void ExposeData()
        {
            Scribe_Deep.Look<ThingOwner<PEApparel>>(ref this.wornApparel, "wornApparel", new object[]
            {
                this
            });
            Scribe_Values.Look<int>(ref this.lastApparelWearoutTick, "lastApparelWearoutTick", 0, false);
            if (Scribe.mode == LoadSaveMode.ResolvingCrossRefs)
            {
                this.SortWornApparelIntoDrawOrder();
            }
        }

        // Token: 0x060015A0 RID: 5536 RVA: 0x000A73AC File Offset: 0x000A57AC
        public void ApparelTrackerTickRare()
        {
            int ticksGame = Find.TickManager.TicksGame;
            if (this.lastApparelWearoutTick < 0)
            {
                this.lastApparelWearoutTick = ticksGame;
            }
            if (ticksGame - this.lastApparelWearoutTick >= 60000)
            {
                for (int i = 0; i < this.wornApparel.Count; i++)
                {
                    this.TakeWearoutDamageForDay(this.wornApparel[i]);
                }
                this.lastApparelWearoutTick = ticksGame;
            }
        }

        // Token: 0x060015A1 RID: 5537 RVA: 0x000A7420 File Offset: 0x000A5820
        public void ApparelTrackerTick()
        {
            this.wornApparel.ThingOwnerTick(true);
            if (this.pawn.IsColonist && this.pawn.Spawned && !this.pawn.Dead && this.pawn.IsHashIntervalTick(60000) && this.PsychologicallyNude)
            {
                TaleRecorder.RecordTale(TaleDefOf.WalkedNaked, new object[]
                {
                    this.pawn
                });
            }
        }

        // Token: 0x060015A2 RID: 5538 RVA: 0x000A74A4 File Offset: 0x000A58A4
        private void TakeWearoutDamageForDay(Thing ap)
        {
            int num = GenMath.RoundRandom(ap.def.apparel.wearPerDay);
            if (num > 0)
            {
                ap.TakeDamage(new DamageInfo(DamageDefOf.Deterioration, num, -1f, null, null, null, DamageInfo.SourceCategory.ThingOrUnknown));
            }
            if (ap.Destroyed && PawnUtility.ShouldSendNotificationAbout(this.pawn) && !this.pawn.Dead)
            {
                string text = "MessageWornApparelDeterioratedAway".Translate(new object[]
                {
                    GenLabel.ThingLabel(ap.def, ap.Stuff, 1),
                    this.pawn
                });
                text = text.CapitalizeFirst();
                Messages.Message(text, this.pawn, MessageTypeDefOf.NegativeEvent);
            }
        }

        // Token: 0x060015A3 RID: 5539 RVA: 0x000A7560 File Offset: 0x000A5960
        public bool CanWearWithoutDroppingAnything(ThingDef apDef)
        {
            for (int i = 0; i < this.wornApparel.Count; i++)
            {
                if (!ApparelUtility.CanWearTogether(apDef, this.wornApparel[i].def, this.pawn.RaceProps.body))
                {
                    return false;
                }
            }
            return true;
        }

        // Token: 0x060015A4 RID: 5540 RVA: 0x000A75B8 File Offset: 0x000A59B8
        public void Wear(PEApparel newApparel, bool dropReplacedApparel = true)
        {
            if (newApparel.Spawned)
            {
                newApparel.DeSpawn();
            }
            if (!ApparelUtility.HasPartsToWear(this.pawn, newApparel.def))
            {
                Log.Warning(string.Concat(new object[]
                {
                    this.pawn,
                    " tried to wear ",
                    newApparel,
                    " but he has no body parts required to wear it."
                }));
                return;
            }
            for (int i = this.wornApparel.Count - 1; i >= 0; i--)
            {
                PEApparel apparel = this.wornApparel[i];
                if (!ApparelUtility.CanWearTogether(newApparel.def, apparel.def, this.pawn.RaceProps.body))
                {
                    if (dropReplacedApparel)
                    {
                        bool forbid = this.pawn.Faction.HostileTo(Faction.OfPlayer);
                        PEApparel apparel2;
                        if (!this.TryDrop(apparel, out apparel2, this.pawn.Position, forbid))
                        {
                            Log.Error(this.pawn + " could not drop " + apparel);
                            return;
                        }
                    }
                    else
                    {
                        this.Remove(apparel);
                    }
                }
            }
            if (newApparel.Wearer != null)
            {
                Log.Warning(string.Concat(new object[]
                {
                    this.pawn,
                    " is trying to wear ",
                    newApparel,
                    " but this apparel already has a wearer (",
                    newApparel.Wearer,
                    "). This may or may not cause bugs."
                }));
            }
            this.wornApparel.TryAdd(newApparel, false);
        }

        // Token: 0x060015A5 RID: 5541 RVA: 0x000A771B File Offset: 0x000A5B1B
        public void Remove(PEApparel ap)
        {
            this.wornApparel.Remove(ap);
        }

        // Token: 0x060015A6 RID: 5542 RVA: 0x000A772A File Offset: 0x000A5B2A
        public bool TryDrop(PEApparel ap, out PEApparel resultingAp)
        {
            return this.TryDrop(ap, out resultingAp, this.pawn.Position, true);
        }

        // Token: 0x060015A7 RID: 5543 RVA: 0x000A7740 File Offset: 0x000A5B40
        public bool TryDrop(PEApparel ap, out PEApparel resultingAp, IntVec3 pos, bool forbid = true)
        {
            if (this.wornApparel.TryDrop(ap, pos, this.pawn.MapHeld, ThingPlaceMode.Near, out resultingAp, null))
            {
                if (resultingAp != null)
                {
                    resultingAp.SetForbidden(forbid, false);
                }
                return true;
            }
            return false;
        }

        // Token: 0x060015A8 RID: 5544 RVA: 0x000A7778 File Offset: 0x000A5B78
        public void DropAll(IntVec3 pos, bool forbid = true)
        {
            PEPawn_ApparelTracker.tmpApparelList.Clear();
            for (int i = 0; i < this.wornApparel.Count; i++)
            {
                PEPawn_ApparelTracker.tmpApparelList.Add(this.wornApparel[i]);
            }
            for (int j = 0; j < PEPawn_ApparelTracker.tmpApparelList.Count; j++)
            {
                PEApparel apparel;
                this.TryDrop(PEPawn_ApparelTracker.tmpApparelList[j], out apparel, pos, forbid);
            }
        }

        // Token: 0x060015A9 RID: 5545 RVA: 0x000A77F2 File Offset: 0x000A5BF2
        public void DestroyAll(DestroyMode mode = DestroyMode.Vanish)
        {
            this.wornApparel.ClearAndDestroyContents(mode);
        }

        // Token: 0x060015AA RID: 5546 RVA: 0x000A7800 File Offset: 0x000A5C00
        public bool Contains(Thing apparel)
        {
            return this.wornApparel.Contains(apparel);
        }

        // Token: 0x060015AB RID: 5547 RVA: 0x000A7810 File Offset: 0x000A5C10
        public void Notify_PawnKilled(DamageInfo? dinfo)
        {
            if (dinfo != null && dinfo.Value.Def.externalViolence)
            {
                for (int i = 0; i < this.wornApparel.Count; i++)
                {
                    if (this.wornApparel[i].def.useHitPoints)
                    {
                        int amount = Mathf.RoundToInt((float)this.wornApparel[i].HitPoints * Rand.Range(0.15f, 0.4f));
                        this.wornApparel[i].TakeDamage(new DamageInfo(dinfo.Value.Def, amount, -1f, null, null, null, DamageInfo.SourceCategory.ThingOrUnknown));
                    }
                }
            }
            for (int j = 0; j < this.wornApparel.Count; j++)
            {
                this.wornApparel[j].Notify_PawnKilled();
            }
        }

        // Token: 0x060015AC RID: 5548 RVA: 0x000A7904 File Offset: 0x000A5D04
        public void Notify_LostBodyPart()
        {
            PEPawn_ApparelTracker.tmpApparel.Clear();
            for (int i = 0; i < this.wornApparel.Count; i++)
            {
                PEPawn_ApparelTracker.tmpApparel.Add(this.wornApparel[i]);
            }
            for (int j = 0; j < PEPawn_ApparelTracker.tmpApparel.Count; j++)
            {
                PEApparel apparel = PEPawn_ApparelTracker.tmpApparel[j];
                if (!ApparelUtility.HasPartsToWear(this.pawn, apparel.def))
                {
                    this.Remove(apparel);
                }
            }
        }

        // Token: 0x060015AD RID: 5549 RVA: 0x000A7991 File Offset: 0x000A5D91
        private void SortWornApparelIntoDrawOrder()
        {
            this.wornApparel.InnerListForReading.Sort((PEApparel a, PEApparel b) => a.def.apparel.LastLayer.CompareTo(b.def.apparel.LastLayer));
        }

        // Token: 0x060015AE RID: 5550 RVA: 0x000A79C0 File Offset: 0x000A5DC0
        public void HasBasicApparel(out bool hasPants, out bool hasShirt)
        {
            hasShirt = false;
            hasPants = false;
            for (int i = 0; i < this.wornApparel.Count; i++)
            {
                PEApparel apparel = this.wornApparel[i];
                for (int j = 0; j < apparel.def.apparel.bodyPartGroups.Count; j++)
                {
                    if (apparel.def.apparel.bodyPartGroups[j] == BodyPartGroupDefOf.Torso)
                    {
                        hasShirt = true;
                    }
                    if (apparel.def.apparel.bodyPartGroups[j] == BodyPartGroupDefOf.Legs)
                    {
                        hasPants = true;
                    }
                    if (hasShirt && hasPants)
                    {
                        return;
                    }
                }
            }
        }

        // Token: 0x060015AF RID: 5551 RVA: 0x000A7A78 File Offset: 0x000A5E78
        public PEApparel FirstApparelOnBodyPartGroup(BodyPartGroupDef g)
        {
            for (int i = 0; i < this.wornApparel.Count; i++)
            {
                PEApparel apparel = this.wornApparel[i];
                for (int j = 0; j < apparel.def.apparel.bodyPartGroups.Count; j++)
                {
                    if (apparel.def.apparel.bodyPartGroups[j] == BodyPartGroupDefOf.Torso)
                    {
                        return apparel;
                    }
                }
            }
            return null;
        }

        // Token: 0x060015B0 RID: 5552 RVA: 0x000A7AF8 File Offset: 0x000A5EF8
        public bool BodyPartGroupIsCovered(BodyPartGroupDef bp)
        {
            for (int i = 0; i < this.wornApparel.Count; i++)
            {
                PEApparel apparel = this.wornApparel[i];
                for (int j = 0; j < apparel.def.apparel.bodyPartGroups.Count; j++)
                {
                    if (apparel.def.apparel.bodyPartGroups[j] == bp)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        // Token: 0x060015B1 RID: 5553 RVA: 0x000A7B74 File Offset: 0x000A5F74
        public IEnumerable<Gizmo> GetGizmos()
        {
            for (int i = 0; i < this.wornApparel.Count; i++)
            {
                foreach (Gizmo g in this.wornApparel[i].GetWornGizmos())
                {
                    yield return g;
                }
            }
            yield break;
        }

        // Token: 0x060015B2 RID: 5554 RVA: 0x000A7B97 File Offset: 0x000A5F97
        private void ApparelChanged()
        {
            LongEventHandler.ExecuteWhenFinished(delegate
            {
                this.pawn.Drawer.renderer.graphics.ResolveApparelGraphics();
                PortraitsCache.SetDirty(this.pawn);
            });
        }

        // Token: 0x060015B3 RID: 5555 RVA: 0x000A7BAA File Offset: 0x000A5FAA
        public void Notify_ApparelAdded(PEApparel PEapparel)
        {
            this.SortWornApparelIntoDrawOrder();
            this.ApparelChanged();
        }

        // Token: 0x060015B4 RID: 5556 RVA: 0x000A7BB8 File Offset: 0x000A5FB8
        public void Notify_ApparelRemoved(PEApparel PEapparel)
        {
            this.ApparelChanged();
            if (this.pawn.outfits != null && this.pawn.outfits.forcedHandler != null)
            {
                this.pawn.outfits.forcedHandler.SetForced(PEapparel, false);
            }
        }

        // Token: 0x060015B5 RID: 5557 RVA: 0x000A7C07 File Offset: 0x000A6007
        public ThingOwner GetDirectlyHeldThings()
        {
            return this.wornApparel;
        }

        // Token: 0x060015B6 RID: 5558 RVA: 0x000A7C0F File Offset: 0x000A600F
        public void GetChildHolders(List<IThingHolder> outChildren)
        {
            ThingOwnerUtility.AppendThingHoldersFromThings(outChildren, this.GetDirectlyHeldThings());
        }

        // Token: 0x04000D2C RID: 3372
        public Pawn pawn;

        // Token: 0x04000D2D RID: 3373
        private ThingOwner<PEApparel> wornApparel;

        // Token: 0x04000D2E RID: 3374
        private int lastApparelWearoutTick = -1;

        // Token: 0x04000D2F RID: 3375
        private const int RecordWalkedNakedTaleIntervalTicks = 60000;

        // Token: 0x04000D30 RID: 3376
        private static List<PEApparel> tmpApparelList = new List<PEApparel>();

        // Token: 0x04000D31 RID: 3377
        private static List<PEApparel> tmpApparel = new List<PEApparel>();
    }
}


The exact part of the error will be put in quotes in this section:

// Token: 0x060015B4 RID: 5556 RVA: 0x000A7BB8 File Offset: 0x000A5FB8
        public void Notify_ApparelRemoved(PEApparel PEapparel)
        {
            this.ApparelChanged();
            if (this.pawn.outfits != null && this.pawn.outfits.forcedHandler != null)
            {
                this.pawn.outfits.forcedHandler.SetForced("PEapparel", false);
            }
        }


The error reads: "Argument 1: cannot convert from 'PEMod.PEApparel' to 'RimWorld.Apparel'"

Keep in mind I know very little about C# and I'm pretty much copy pasting existing code and changing it to what I think will work.
#8
Help / Is It Possible To Add New Apparel Layers?
May 03, 2018, 07:47:21 AM
I noticed while updating my old mods that they removed the old apparel layer I used for jewelry, so now pawns can't wear these items without sacrificing the ability to wear normal clothing. I know the enumeration for the existing layers can't be changed, so I've been trying to create a huge work-around by creating an entirely new ThingDef with it's own set of layers. I'm wanting to know if this is actually possible or if I'm just running into a dead end. So far I've run into an error I can't resolve:

Failed to find PEMod.PEThingDef named SapphireRing. There are 0 defs of this type loaded.

I fixed the above error, however I now need this apparel to have a functioning tracker. Since this apparel is in an entirely new section from other items the vanilla tracker doesn't work for it. Currently working on creating a new one but it's pretty messy right now.
#9
Help / (RESOLVED)Resource For Updating Old Mods?
May 03, 2018, 04:19:13 AM
I have a mod that was last udpated back in Alpha 16(maybe has some A17 changes in it) and I'd like to know if there's any resources that show what definitions have changed. I'm getting alot of errors of nonexistent terms but it won't give me a reference as to what file is the source of the error. Knowing what terms were changed to though may help me find and fix them.
#10
Help / Re: What Kinds Of Mods Are Needed?
February 20, 2017, 07:16:17 PM
I've finished making the mod that brings the number of meats down to 7(Not including Human and Insect meats). Most animals will now be butchered down to Beef, Poultry, Venison, Pork, Small Game Meat, or Big Game Meat. Just search "Simplified Meats" in the steam workshop.

I used the "meatLabel" method just so the mod could be pushed out as soon as possible. Due to this, I'm certain it will be incompatible with most if not all mods that change the vanilla animals. Also, any mods that add new animals should have their meat products named just as they normally would, using the animal's name.

I will look into other mod ideas such as the Insect Armor mod and Stockpile Window mod. However the Insect Armor mod will probably take some artistic work that I'm not very good at.
#11
Help / Re: What Kinds Of Mods Are Needed?
February 20, 2017, 05:04:37 PM
Well I think I've created categories of meat for every existing vanilla animal. It through the meatLabel/useMetaFrom system, so i had to modify the xml of each vanilla animal, making pretty much any mod that also modifies vanilla animals more than likely incompatible.

The meat categories are as follows:

Beef: Includes large, four-legged, hooved, mammals. They include Cows, Muffalo, and Dromedary.

Poultry: Includes all feathered animals such as, Ostrich, Chicken, Cassowary, etc..

Small Game Meat: Includes small animals that were typically hunted for sport. Includes Foxes, Reptiles, Hares, etc..

Big Game Meat: Includes large predatory and sport animals. Includes Bears, Thrumbo, Elephants, etc..

Dog Meat: Includes Pets, Wolves, and Worgs.
#12
Help / Re: What Kinds Of Mods Are Needed?
February 20, 2017, 02:40:33 PM
Quote from: Tammabanana on February 20, 2017, 07:38:45 AM
You CAN combine the meats in XML only - see Cassowary and Emu within Races_Animals_Birds.xml:

Cassowary uses:
      <meatLabel>bird meat</meatLabel>

Emu uses:
      <useMeatFrom>Cassowary</useMeatFrom>

It would involve overwriting vanilla animals, so it would be incompatible with (for example) that mod that makes deer/antelope/caribou milkable.  There would be a couple ways around that -

  • to make patches for such mods;
  • to talk with those mods authors and see if you can work together to create compatability between the mods;
  • to browse around and see what other folks are changing about vanilla animals, and talk to the authors about combining into one mod that changes all those things at once, since they're clearly vanilla elements that annoy somebody.

Mods that add new animals, maybe you could drop a line into the forums to tip them off to the <useMeatFrom> tag and point them to the animal that is using the generic meat. Or make a compatch.

There's a thread that Hydromancerx started somewhere, about merging animal mods... might be worth bringing these two discussions together.
https://ludeon.com/forums/index.php?topic=30541.0

Yea, most meat types are already categorized from meat label. If i wanted to I could probably use the meatLabel option to generalize the meats together. However, as you said this can cause compatibility issues. But again, since I don't have the knowledge on how to inject the new code to overwrite the old, I may have to do this.
#13
Help / Re: What Kinds Of Mods Are Needed?
February 19, 2017, 08:09:28 PM
Quote from: SpaceDorf on February 19, 2017, 06:04:45 PM
You can Inject a new Method into the Game that overwrites this one to create a function that renames the meat types .. even to a point where it automatically renames unknown meatsources into "mod meat" or something.

There might be an easier solution though.
I checked the defs and found this :


<ThingDef ParentName="BigBirdThingBase">
    <defName>Cassowary</defName>
    <label>cassowary</label>
    <description>A large flightless bird with brightly-colored feathers. While it looks beautiful, its kick is vicious.</description>
    <statBases>
      <MoveSpeed>4.5</MoveSpeed>
      <ComfyTemperatureMin>-8</ComfyTemperatureMin>
      <MarketValue>300</MarketValue>
    </statBases>
    <race>
      <herdAnimal>false</herdAnimal>
      <baseBodySize>0.9</baseBodySize>
      <baseHungerRate>0.3</baseHungerRate>
      <baseHealthScale>0.9</baseHealthScale>
      <foodType>VegetarianRoughAnimal</foodType>
      <wildness>0.80</wildness>
      <lifeExpectancy>45</lifeExpectancy>
      <leatherColor>(80,80,80)</leatherColor>
   [b]   <meatLabel>bird meat</meatLabel>[/b]
      <manhunterOnTameFailChance>0.030</manhunterOnTameFailChance>
    </race>


     <meatLabel>bird meat</meatLabel>

That is the line the code example you gave checks in the beginning.
The meatDef, if none exists it creates one on the fly.

How would i go about "Injecting a new method"?
#14
Help / Re: What Kinds Of Mods Are Needed?
February 19, 2017, 03:19:44 PM
After some digging I've found that animal meat is generated through a class file. It grabs the name of the animal and generates the meat item into existence. One way I think categorized or simplified meat would have to work, is by adding statements that check the name of the animal, but instead of naming the meat after the animal, it would instead give it the more generalized name. I think its possible but any mods that added more animals would require "addons" or "plugins" whenever those mods are installed.

Here is the code for the meat generator class in case someone wants to try to understand it as I have a tiny amount of knowledge about this.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Verse;

namespace RimWorld
{
public static class ThingDefGenerator_Meat
{
[DebuggerHidden]
public static IEnumerable<ThingDef> ImpliedMeatDefs()
{
List<ThingDef>.Enumerator enumerator = DefDatabase<ThingDef>.AllDefs.ToList<ThingDef>().GetEnumerator();
try
{
while (enumerator.MoveNext())
{
ThingDef current = enumerator.Current;
if (current.category == ThingCategory.Pawn)
{
if (current.race.useMeatFrom == null)
{
if (!current.race.IsFlesh)
{
CrossRefLoader.RegisterObjectWantsCrossRef(current.race, "meatDef", "Steel");
}
else
{
ThingDef thingDef = new ThingDef();
thingDef.resourceReadoutPriority = ResourceCountPriority.Middle;
thingDef.category = ThingCategory.Item;
thingDef.thingClass = typeof(ThingWithComps);
thingDef.graphicData = new GraphicData();
thingDef.graphicData.graphicClass = typeof(Graphic_Single);
thingDef.useHitPoints = true;
thingDef.selectable = true;
thingDef.SetStatBaseValue(StatDefOf.MaxHitPoints, 100f);
thingDef.altitudeLayer = AltitudeLayer.Item;
thingDef.stackLimit = 75;
thingDef.comps.Add(new CompProperties_Forbiddable());
CompProperties_Rottable compProperties_Rottable = new CompProperties_Rottable();
compProperties_Rottable.daysToRotStart = 2f;
compProperties_Rottable.rotDestroys = true;
thingDef.comps.Add(compProperties_Rottable);
thingDef.comps.Add(new CompProperties_FoodPoisoningChance());
thingDef.tickerType = TickerType.Rare;
thingDef.SetStatBaseValue(StatDefOf.Beauty, -20f);
thingDef.alwaysHaulable = true;
thingDef.rotatable = false;
thingDef.pathCost = 15;
thingDef.drawGUIOverlay = true;
thingDef.socialPropernessMatters = true;
thingDef.category = ThingCategory.Item;
thingDef.description = "MeatDesc".Translate(new object[]
{
current.label
});
thingDef.useHitPoints = true;
thingDef.SetStatBaseValue(StatDefOf.MaxHitPoints, 50f);
thingDef.SetStatBaseValue(StatDefOf.DeteriorationRate, 10f);
thingDef.SetStatBaseValue(StatDefOf.Mass, 0.03f);
thingDef.BaseMarketValue = ThingDefGenerator_Meat.GetMeatMarketValue(current);
if (thingDef.thingCategories == null)
{
thingDef.thingCategories = new List<ThingCategoryDef>();
}
CrossRefLoader.RegisterListWantsCrossRef<ThingCategoryDef>(thingDef.thingCategories, "MeatRaw");
thingDef.ingestible = new IngestibleProperties();
thingDef.ingestible.foodType = FoodTypeFlags.Meat;
thingDef.ingestible.preferability = FoodPreferability.RawBad;
CrossRefLoader.RegisterObjectWantsCrossRef(thingDef.ingestible, "tasteThought", ThoughtDefOf.AteRawFood.defName);
thingDef.ingestible.nutrition = 0.05f;
thingDef.ingestible.ingestEffect = EffecterDefOf.EatMeat;
thingDef.ingestible.ingestSound = SoundDef.Named("RawMeat_Eat");
if (current.race.fleshType == FleshType.Insectoid)
{
thingDef.ingestible.specialThoughtDirect = ThoughtDefOf.AteInsectMeatDirect;
thingDef.ingestible.specialThoughtAsIngredient = ThoughtDefOf.AteInsectMeatAsIngredient;
}
if (current.race.Humanlike)
{
thingDef.graphicData.texPath = "Things/Item/Resource/MeatFoodRaw/MeatHuman";
}
else
{
if (current.race.baseBodySize < 0.7f)
{
thingDef.graphicData.texPath = "Things/Item/Resource/MeatFoodRaw/MeatSmall";
}
else
{
thingDef.graphicData.texPath = "Things/Item/Resource/MeatFoodRaw/MeatBig";
}
thingDef.graphicData.color = current.race.meatColor;
}
thingDef.defName = current.defName + "_Meat";
if (current.race.meatLabel.NullOrEmpty())
{
thingDef.label = "MeatLabel".Translate(new object[]
{
current.label
});
}
else
{
thingDef.label = current.race.meatLabel;
}
thingDef.ingestible.sourceDef = current;
current.race.meatDef = thingDef;
yield return thingDef;
}
}
}
}
}
finally
{
}
yield break;
}

private static float GetMeatMarketValue(ThingDef sourceDef)
{
if (sourceDef.race.Humanlike)
{
return 1.75f;
}
return 2.7f;
}
}
}


EDIT: I would first have to remove this code from the vanilla game so it won't keep trying to generate the specific meats. However I don't know if thats possible. The only other solution would be to change the meats AFTER they've been created, which, if possible could be buggy or just messy.
#15
Help / Re: What Kinds Of Mods Are Needed?
February 19, 2017, 01:48:38 PM
Quote from: SpaceDorf on February 19, 2017, 11:37:50 AM

I would like a mod that condenses the meat and leather types down to a few.


Bird ( everything with wings )
Insect ( same as now )
Venison ( deer, antilope, reindeer .. )
Pork ( all pigs )
Mutton ( all kinds of goat and sheep )
Beef ( cows and muffalos )
Dog ( dogs and wolves )
something for cougars and other hunters ..
and one for small animals ..
Human

you get the idea.

Yea having a vast array of different meats is bad for storage, I'll see if i can do something. However I have a feeling this type of mod would cause compatibility issues with mods that also changed vanilla meats and animals.