[A15/A14/A13] Aristocat's mods

Started by Aristocat, June 10, 2016, 04:28:00 AM

Previous topic - Next topic

sirgzu

I'm getting 4 mods instead of 1. Is this normal? Is there a specific load ordering? EPOE is causing problems with my save.

Zakhad

Quote from: Anoff on June 11, 2016, 12:49:07 AM
EDIT 2* got tired of waiting, 5 weeks, just sold him off for an easy 500 silver + 1 less mouth to feed.

Rofl, that's a feature not a bug, for a chance of making them into a vegetable :P

Aristocat

#17
Quote

  • v 0.1 06/11/2016
  • Removed dependency - EPOE mod is no longer needed.
  • Eternal anesthesia fixed. (No, it wasn't "feature") If someone doesn't wake up, try use global restore body parts on torso in dev mode.
  • Added surgeries for animals, everything should be repairable, from claws to paws, tail, beak, scars, and even brain injury.
  • Anesthesia, curable chronic diseases, etc, for animals.
  • Neurotrainers for beauty and ugly trait.
  • Price adjustments and small tweaks. Lung is now cheaper than heart. Generally, most prosthetics sell slightly cheaper.
  • Prosthetic bench for animal now require research to unlock.
  • Small tweaks.
It seems red errors on dev mode wasn't from this mod pack.

Aristocat

Quote from: BlueWinds on June 10, 2016, 07:34:47 PM
These all sound excellent - any chance I could get these without EPOE? I already use the other three mods mentioned, but EPOE contains a lot of extra content that I don't want to add.

Quote from: sirgzu on June 11, 2016, 04:11:08 AM
I'm getting 4 mods instead of 1. Is this normal? Is there a specific load ordering? EPOE is causing problems with my save.

EPOE is no longer needed! Please report any bugs. And sorry for confusion, this is mod pack, although extremely tiny. And no specific load order is required.

cuproPanda

#19
I spent the afternoon doing some work on BrainMod. Everything should be doable in XML now, including adding new traits or explicitly making removal mods. Feel free to use the new version, it should be useful to you since you have the ability to craft them.

This will break older versions of the mod, so keep that in mind!

[attachment deleted by admin - too old]
cuproPanda's Mods: Survivalist's Additions, Additional Joy Objects, Cupro's Drinks, Quarry, Cupro's Stones, Zen Garden, Cupro's Alloys, Preset Filtered Zones, & more!

Aristocat

Quote from: cuproPanda on June 12, 2016, 11:30:45 PM
I spent the afternoon doing some work on BrainMod. Everything should be doable in XML now, including adding new traits or explicitly making removal mods. Feel free to use the new version, it should be useful to you since you have the ability to craft them.

This will break older versions of the mod, so keep that in mind!

Wow, awesome! How long does it take to code like you? I can't seem to understand any of this.

cuproPanda

Quote from: Aristocat on June 13, 2016, 10:40:22 AM
Quote from: cuproPanda on June 12, 2016, 11:30:45 PM
I spent the afternoon doing some work on BrainMod. Everything should be doable in XML now, including adding new traits or explicitly making removal mods. Feel free to use the new version, it should be useful to you since you have the ability to craft them.

This will break older versions of the mod, so keep that in mind!

Wow, awesome! How long does it take to code like you? I can't seem to understand any of this.

I've only been programming for 2 years or so. I'd say the majority of my experience comes from RimWorld and Quill18, who introduced me to RimWorld in the first place.

What didn't you understand? I tried to make it as user-friendly as possible with the example block. Basically you provide the variables, and the mod does the rest.
cuproPanda's Mods: Survivalist's Additions, Additional Joy Objects, Cupro's Drinks, Quarry, Cupro's Stones, Zen Garden, Cupro's Alloys, Preset Filtered Zones, & more!

Aristocat

Quote from: cuproPanda on June 13, 2016, 11:08:12 AM
I've only been programming for 2 years or so. I'd say the majority of my experience comes from RimWorld and Quill18, who introduced me to RimWorld in the first place.

What didn't you understand? I tried to make it as user-friendly as possible with the example block. Basically you provide the variables, and the mod does the rest.

I meant C#, how long does it take to code something like this? Your XML is definitely easy to understand and well written.

cuproPanda

Quote from: Aristocat on June 13, 2016, 12:54:31 PM
Quote from: cuproPanda on June 13, 2016, 11:08:12 AM
I've only been programming for 2 years or so. I'd say the majority of my experience comes from RimWorld and Quill18, who introduced me to RimWorld in the first place.

What didn't you understand? I tried to make it as user-friendly as possible with the example block. Basically you provide the variables, and the mod does the rest.

I meant C#, how long does it take to code something like this? Your XML is definitely easy to understand and well written.

Well figuring out the original code took probably 5 hours, but a lot of that was determining how to properly match up the brainmod traits with the traits the colonists had, and correctly removing the right ones. It was all new territory, and I had no experience with traits at the time. If I had to do it all again it would probably take an hour or two, including time for testing it works. Once you know what you're doing, it doesn't take long to do. Updating the code was pretty easy, since I just needed to change the variables from being defined in code to being defined in XML, but now it's just a matter of adding a new block of XML code vs adding a new C# class and rebuilding the dll.

I suppose the C# looks more complicated/impressive than it actually is if you're looking at it in ILSpy or the like, since the compiler jumbles up IEnumerable code. For example, the source is this:

using System;
using System.Collections.Generic;

using RimWorld;
using UnityEngine;
using Verse;
using Verse.AI;

namespace BrainMod {

  public class BrainMod : ThingWithComps, IUsable {

    // Used to determine if the brain mod is used for removal   
    public System.Random rand = new System.Random();
                   
    // The current brain mod
    private BrainModDef brainMod = DefDatabase<BrainModDef>.GetNamed("BrainMod_BlankStarter");

    // The mod author's name (for addons and bug-checking)
    private string modAuthor {
      get {
        if (brainMod.ModAuthor == null) {
          return "the mod author";
        }
        return brainMod.ModAuthor;
      }
    }

    // The current traitDef
    private TraitDef TDefInt;
    public TraitDef TDef {                 
      get {
        if (TDefInt == null) {
          TDefInt = TraitDef.Named(brainMod.TDef);
        }
        return TDefInt;
      }
    }

    // The current trait
    private Trait TInt;
    public Trait T {                       
      get {
        if (TInt == null) {
          TInt = new Trait(TraitDef.Named(brainMod.TDef));
          if (brainMod.Degree != 0) {
            TInt.degree = brainMod.Degree;
          }
        }
        return TInt;
      }
    }

    // Determines what percentage will be removal mods
    private double? RemovalPercentInt;
    public double RemovalPercent {
      get {
        if (RemovalPercentInt == null) {
          RemovalPercentInt = Mathf.Clamp01((float)brainMod.RemovalPercent);
        }
        return (double)RemovalPercentInt;
      }
    }

    // Used for brain mods that remove traits
    private bool? RemovalInt;
    public bool Removal {
      get {
        if (RemovalInt == null) {
          RemovalInt = rand.NextDouble() <= RemovalPercent ? true : false;
        }
        return (bool)RemovalInt;
      }
    }

    // The list of conflicting traits
    public List<Trait> ConflictingTraits {
      get {
        if (brainMod.ConflictingTraits != null) {
          for (int t = 0; t < brainMod.ConflictingTraits.Count; t++) {
            if (TraitDef.Named(brainMod.ConflictingTraits[t]) == null) {
              Log.Error("(BrainMod) Unknown TraitDef named '" + brainMod.ConflictingTraits[t] + "' found. Please report this issue to " + modAuthor + ".");
            }
            if (TraitDef.Named(brainMod.ConflictingTraits[t]) != null) {
              ConflictingTraits.Add(new Trait(TraitDef.Named(brainMod.ConflictingTraits[t])));
            }
          }
          return ConflictingTraits;
        }
        return null;
      }
    }

    // Used when a trait conflicts with all traits in a spectrum
    public TraitDef ConflictingSpectrum {
      get {
        if (brainMod.ConflictingSpectrum != null) {
          return TraitDef.Named(brainMod.ConflictingSpectrum);
        }
        return null;
      }
    }

    private JobDef UseBrainMod;

    public override string LabelBase {
      get {
        if (Removal) {
          return "nullify " + brainMod.label;
        }
        else {
          return brainMod.label;
        }
      }
    }


    // Handle loading
    public override void ExposeData() {
      base.ExposeData();
      Scribe_Deep.LookDeep(ref TInt, "trait");
      Scribe_Defs.LookDef(ref TDefInt, "traitDef");
      Scribe_Values.LookValue(ref RemovalPercentInt, "removalPercent");
      Scribe_Values.LookValue(ref RemovalInt, "removal");
    }


    public override void PostMake() {
      base.PostMake();
      brainMod = DefDatabase<BrainModDef>.GetNamed(def.defName);
    }


    public override Color DrawColor {
      get {
        if (Removal) {
          return Color.grey;
        }
        return brainMod.graphicData.color;
      }

      set {
        base.DrawColor = value;
      }
    }


    public override void SpawnSetup() {
      base.SpawnSetup();

      UseBrainMod = DefDatabase<JobDef>.GetNamed("UseBrainMod");
    }


    public override IEnumerable<FloatMenuOption> GetFloatMenuOptions(Pawn myPawn) {
      foreach (FloatMenuOption opt in base.GetFloatMenuOptions(myPawn)) {
        yield return opt;
      }

      Action action_UseBrainMod = delegate {
        Job job = new Job(UseBrainMod, this);
        myPawn.drafter.TakeOrderedJob(job);
      };

      if (!Removal) {
        for (int t = 0; t < myPawn.story.traits.allTraits.Count; t++) {
          if (myPawn.story.traits.allTraits[t].Label == T.Label) {
            // This allows the other options to still show (prioritize hauling, etc.)
            goto Exit;
          }
        }
        yield return new FloatMenuOption("UseBrainMod".Translate(T.Label), action_UseBrainMod);
      }

      if (Removal) {
        for (int t = 0; t < myPawn.story.traits.allTraits.Count; t++) {
          if (myPawn.story.traits.allTraits[t].Label == T.Label) {
            yield return new FloatMenuOption("UseRemovalBrainMod".Translate(T.Label), action_UseBrainMod);
            break;
          }
        }
      }
      Exit:;
    }


    public void UsedBy(Pawn user) {
      // Simplify typing
      List<Trait> tList = user.story.traits.allTraits;

      // If this is an adding mod, process conflicts and add the trait
      if (!Removal) {
        // Remove as many conflicting traits as are necessary
        if (ConflictingSpectrum != null) {
          for (int cs = 0; cs < ConflictingSpectrum.degreeDatas.Count; cs++) {
            for (int t = 0; t < tList.Count; t++) {
              if (ConflictingSpectrum.degreeDatas[cs].label.EqualsIgnoreCase(tList[t].Label)) {
                tList.Remove(tList[t]);
              }
            }
          }
        }

        if (ConflictingTraits != null) {
          for (int a = 0; a < tList.Count; a++) {
            for (int b = 0; b < ConflictingTraits.Count; b++) {
              if (tList[a].Label == ConflictingTraits[b].Label) {
                tList.Remove(tList[a]);
              }
            }
          }
        }

        tList.Add(T);
      }

      // If this is a removal mod, remove the trait
      if (Removal) {
        for (int t = 0; t < tList.Count; t++) {
          // Ensure the trait matches and the degree is the same
          if (tList[t].Label == T.Label) {
            tList.Remove(tList[t]);
          }
        }
      }
     
      if (PawnUtility.ShouldSendNotificationAbout(user)) {
        if (!Removal) {
          // Determine the message based on conflicts
          Messages.Message("BrainModUsed".Translate(user.LabelBaseShort, T.Label), user, MessageSound.Standard);
        }
        if (Removal) {
          Messages.Message("RemovalBrainModUsed".Translate(user.LabelBaseShort, T.Label), user, MessageSound.Standard);
        }
      }
      Destroy();
    }
  }
}


... which is probably easier to read and understand, or at least get the basic idea of what's going on, vs this snippet of what's returned by ILSpy:

[CompilerGenerated]
private sealed class <GetFloatMenuOptions>d__29 : IEnumerable<FloatMenuOption>, IEnumerable, IEnumerator<FloatMenuOption>, IDisposable, IEnumerator
{
private int <>1__state;

private FloatMenuOption <>2__current;

private int <>l__initialThreadId;

private Pawn myPawn;

public Pawn <>3__myPawn;

public BrainMod <>4__this;

private BrainMod.<>c__DisplayClass29_0 <>8__1;

private Action <action_UseBrainMod>5__2;

private IEnumerator<FloatMenuOption> <>s__3;

private FloatMenuOption <opt>5__4;

private int <t>5__5;

private int <t>5__6;

FloatMenuOption IEnumerator<FloatMenuOption>.Current
{
[DebuggerHidden]
get
{
return this.<>2__current;
}
}

object IEnumerator.Current
{
[DebuggerHidden]
get
{
return this.<>2__current;
}
}

[DebuggerHidden]
public <GetFloatMenuOptions>d__29(int <>1__state)
{
this.<>1__state = <>1__state;
this.<>l__initialThreadId = Thread.CurrentThread.ManagedThreadId;
}

[DebuggerHidden]
void IDisposable.Dispose()
{
int num = this.<>1__state;
if (num == -3 || num == 1)
{
try
{
}
finally
{
this.<>m__Finally1();
}
}
}

bool IEnumerator.MoveNext()
{
bool result;
try
{
switch (this.<>1__state)
{
case 0:
this.<>1__state = -1;
this.<>8__1 = new BrainMod.<>c__DisplayClass29_0();
this.<>8__1.<>4__this = this.<>4__this;
this.<>8__1.myPawn = this.myPawn;
this.<>s__3 = this.<>4__this.<>n__0(this.<>8__1.myPawn).GetEnumerator();
this.<>1__state = -3;
break;
case 1:
this.<>1__state = -3;
this.<opt>5__4 = null;
break;
case 2:
this.<>1__state = -1;
goto IL_1FF;
case 3:
this.<>1__state = -1;
goto IL_2F5;
default:
result = false;
return result;
}
if (this.<>s__3.MoveNext())
{
this.<opt>5__4 = this.<>s__3.Current;
this.<>2__current = this.<opt>5__4;
this.<>1__state = 1;
result = true;
return result;
}
this.<>m__Finally1();
this.<>s__3 = null;
this.<action_UseBrainMod>5__2 = new Action(this.<>8__1.<GetFloatMenuOptions>b__0);
bool flag = !this.<>4__this.Removal;
if (flag)
{
this.<t>5__5 = 0;
while (this.<t>5__5 < this.<>8__1.myPawn.story.traits.allTraits.Count)
{
bool flag2 = this.<>8__1.myPawn.story.traits.allTraits[this.<t>5__5].Label == this.<>4__this.T.Label;
if (flag2)
{
goto IL_2F6;
}
int num = this.<t>5__5;
this.<t>5__5 = num + 1;
}
this.<>2__current = new FloatMenuOption("UseBrainMod".Translate(new object[]
{
this.<>4__this.T.Label
}), this.<action_UseBrainMod>5__2, MenuOptionPriority.Medium, null, null);
this.<>1__state = 2;
result = true;
return result;
}
IL_1FF:
bool removal = this.<>4__this.Removal;
if (removal)
{
this.<t>5__6 = 0;
while (this.<t>5__6 < this.<>8__1.myPawn.story.traits.allTraits.Count)
{
bool flag3 = this.<>8__1.myPawn.story.traits.allTraits[this.<t>5__6].Label == this.<>4__this.T.Label;
if (flag3)
{
this.<>2__current = new FloatMenuOption("UseRemovalBrainMod".Translate(new object[]
{
this.<>4__this.T.Label
}), this.<action_UseBrainMod>5__2, MenuOptionPriority.Medium, null, null);
this.<>1__state = 3;
result = true;
return result;
}
int num = this.<t>5__6;
this.<t>5__6 = num + 1;
}
}
IL_2F5:
IL_2F6:
result = false;
}
catch
{
this.System.IDisposable.Dispose();
throw;
}
return result;
}

private void <>m__Finally1()
{
this.<>1__state = -1;
if (this.<>s__3 != null)
{
this.<>s__3.Dispose();
}
}
cuproPanda's Mods: Survivalist's Additions, Additional Joy Objects, Cupro's Drinks, Quarry, Cupro's Stones, Zen Garden, Cupro's Alloys, Preset Filtered Zones, & more!

DFC

I updated to the 0.1 from the previous one, old save files would no longer work. I have attached the output log

EDIT: I have tried using only DESurgeries from 0.1 with older files from beta, seem to be able to work now.

[attachment deleted by admin - too old]

Aristocat

Quote from: cuproPanda on June 12, 2016, 11:30:45 PM
I spent the afternoon doing some work on BrainMod. Everything should be doable in XML now, including adding new traits or explicitly making removal mods. Feel free to use the new version, it should be useful to you since you have the ability to craft them.

This will break older versions of the mod, so keep that in mind!

I'm making education mod with your brain mod. Highly skilled colonist can write guides that add trait which increase reader's skill, working speed and efficiency. In addition, skilled colonists can write test papers and colonists can study it to gain exprience just like neurotrainer, but slower.

cuproPanda

Quote from: Aristocat on June 17, 2016, 11:52:00 AM
Quote from: cuproPanda on June 12, 2016, 11:30:45 PM
I spent the afternoon doing some work on BrainMod. Everything should be doable in XML now, including adding new traits or explicitly making removal mods. Feel free to use the new version, it should be useful to you since you have the ability to craft them.

This will break older versions of the mod, so keep that in mind!

I'm making education mod with your brain mod. Highly skilled colonist can write guides that add trait which increase reader's skill, working speed and efficiency. In addition, skilled colonists can write test papers and colonists can study it to gain exprience just like neurotrainer, but slower.

I was planning on doing something similar to this with my AdditionalJoyObjects mod, since it adds books and writing stuff. A colonists of level 15 construction could write a construction guide, and other colonists could read it to gain levels in the construction skill, but only up to level 13 or 14. Maybe the max level would be determined by the writer's research skill, representing how well they are able to convey their knowledge.

I don't think I'll be doing that mod anymore(I'm focusing on balancing, not adding), but that's what I had planned to do if I did. It'll definitely be a useful feature, and the test papers part sounds pretty cool :)
cuproPanda's Mods: Survivalist's Additions, Additional Joy Objects, Cupro's Drinks, Quarry, Cupro's Stones, Zen Garden, Cupro's Alloys, Preset Filtered Zones, & more!

Exende

I don't know panda, that sounds like an infinitely more awesome idea

Aristocat

Education mod is finally finished! Any feedback is welcome.

cuproPanda

#29
Quote from: Exende on June 17, 2016, 03:09:44 PM
I don't know panda, that sounds like an infinitely more awesome idea

Maybe in the future. I might also just do it and contribute it to the Education mod

Quote from: Aristocat on June 23, 2016, 02:11:45 PM
Education mod is finally finished! Any feedback is welcome.

It looks pretty cool from the main post! I'll play with it sometime in the future, I've been pretty busy lately  :)

EDIT: I haven't released the version of BrainMod you're using, since I'm still working on updating it. The version you have should work just fine, but you should probably add it to the download instead of directing people to my thread, since they will be downloading a version that doesn't work with the new traits you added.
cuproPanda's Mods: Survivalist's Additions, Additional Joy Objects, Cupro's Drinks, Quarry, Cupro's Stones, Zen Garden, Cupro's Alloys, Preset Filtered Zones, & more!