Custom trader, Haplo I need help!

Started by skullywag, March 22, 2015, 04:20:46 PM

Previous topic - Next topic

skullywag

Hey all (and Haplo if you reading)

im trying to get a custom trader that isnt you normal trader, very much like Haplos wandering traders but using a different mechanism, ive been looking into the misc mods source and trying to put something together and have everything working except one bit, the trade screen, it errors everytime with:

Exception filling window for RimWorld.Dialog_Trade: System.NullReferenceException: Object reference not set to an instance of an object

  at RimWorld.TradeDeal.UpdateCurrencyCount () [0x00000] in <filename unknown>:0

  at RimWorld.Dialog_Trade.FillWindow (Rect inRect) [0x00000] in <filename unknown>:0

  at Verse.Layer.DoWindowContents () [0x00000] in <filename unknown>:0


I cant see what it is im missing. Does anyone know what I could have missed, ill happily put my code up but am wanting to keep it semi to my chest until I release....
Skullywag modded to death.
I'd never met an iterator I liked....until Zhentar saved me.
Why Unity5, WHY do you forsake me?

Haplo

It looks like one of your tradable objects in the tradables collection is null.
How it could be null, I don't know.
With my traders I've used a simple shortcut: I didn't use a different trader option, I've just declared the pawns as a tradeship and use the normal communication screen that you get when you call one via the comm console :)
Simple but effective. And 100% compatible with all kind of traders :)
I guess you've changed the trader itself?

skullywag

Ive got a "building" like your tent that in the setup is calling:
public void SetupTrader()
        {
            trader = TryGenerateFarmingTrader();
            trader.GenerateThings();
            trader.name = "sekrits!";
        }
private TradeShip TryGenerateFarmingTrader()
        {
            TraderKindDef traderKindDef;
            traderKindDef = DefDatabase<TraderKindDef>.GetNamedSilentFail("mynewtradedefname");
            return new TradeShip(traderKindDef);
        }


I cant see why it wouldnt work when done that way. The rest of the code is almost exactly the same as yours I think.
Also calling my trader the normal way works fine.
Skullywag modded to death.
I'd never met an iterator I liked....until Zhentar saved me.
Why Unity5, WHY do you forsake me?

Haplo

#3
The error code looks more like a problem with the wares of your trader instead of the trader itself.
It looks like some of your stuff for the trader isn't Tradeable compatible or is null for some other reason.
If you did use the trader code like the vanilla code, look into what could possibly be wrong with your stuff. Try to add it to a normal trader and look if it throws the error there too..

skullywag

#4
but calling the same trader as named above the vanilla way works fine, perhaps its not getting to that bit and therefore the trader def is empty....? ill try switching it to a core trader...

edit - huh it works with a core trader...what in the hell...
Skullywag modded to death.
I'd never met an iterator I liked....until Zhentar saved me.
Why Unity5, WHY do you forsake me?

Haplo

Ok, then it looks like there is something in your trader definition.
Come out bug, you're surrounded ;)

skullywag

god dammit...i didnt give him silver.....-_-

Funny how it worked normally though.

It works now with that adding to the stock generation.
Skullywag modded to death.
I'd never met an iterator I liked....until Zhentar saved me.
Why Unity5, WHY do you forsake me?

Haplo

Good, so we'll see a new trader around soon? ;)

skullywag

Hopefully, I have everything else in place, just need some art, which im trying to do myself...but as always i dont like it, so ill spend a few days faffing with it until im happy i guess.
Skullywag modded to death.
I'd never met an iterator I liked....until Zhentar saved me.
Why Unity5, WHY do you forsake me?

skullywag

OK doing a bit of refactoring as hit upon a snag, im trying to make a trader programtically but am hitting an issue, can anyone see where the problem lies, Ive got code blindness from staring at it:

private TradeShip TryGenerateNewTrader()
        {
            TraderKindDef traderKindDef;
            traderKindDef = new TraderKindDef();
            StockGenerator_SingleDef sdef = new StockGenerator_SingleDef();
            sdef.HandlesThingDef(ThingDef.Named("Silver"));
            sdef.countRange.min = 2400;
            sdef.countRange.max = 3600;
            sdef.GenerateThings();
            traderKindDef.stockGenerators.Add(sdef);
            return new TradeShip(traderKindDef);
        }


I get this ingame when the trader arrives:


Exception ticking TradeDroneIncoming465956: System.NullReferenceException: Object reference not set to an instance of an object

  at RimWorld.StockGenerator.TryMakeForStock (Verse.ThingDef thingDef, Int32 stackCount) [0x00000] in <filename unknown>:0

  at RimWorld.StockGenerator_SingleDef+<GenerateThings>c__IteratorA4.MoveNext () [0x00000] in <filename unknown>:0

  at RimWorld.TraderStockGenerator+<GenerateTraderThings>c__IteratorAB.MoveNext () [0x00000] in <filename unknown>:0

  at System.Collections.Generic.List`1[Verse.Thing].AddEnumerable (IEnumerable`1 enumerable) [0x00000] in <filename unknown>:0

  at System.Collections.Generic.List`1[Verse.Thing]..ctor (IEnumerable`1 collection) [0x00000] in <filename unknown>:0

  at System.Linq.Enumerable.ToList[Thing] (IEnumerable`1 source) [0x00000] in <filename unknown>:0

  at RimWorld.TradeShip.GenerateThings () [0x00000] in <filename unknown>:0

  at RimWorld.Building_TradeDrone.SetupTrader () [0x00000] in <filename unknown>:0

  at RimWorld.Building_TradeDrone.SpawnSetup () [0x00000] in <filename unknown>:0

  at Verse.GenSpawn.Spawn (Verse.Thing newThing, IntVec3 loc, IntRot rot) [0x00000] in <filename unknown>:0

  at Verse.GenSpawn.Spawn (Verse.Thing newThing, IntVec3 loc) [0x00000] in <filename unknown>:0

  at Verse.GenSpawn.Spawn (Verse.ThingDef def, IntVec3 loc) [0x00000] in <filename unknown>:0

  at RimWorld.TradeDroneIncoming.PodImpact () [0x00000] in <filename unknown>:0

  at RimWorld.TradeDroneIncoming.Tick () [0x00000] in <filename unknown>:0

  at Verse.TickList.SingleTick () [0x00000] in <filename unknown>:0
Skullywag modded to death.
I'd never met an iterator I liked....until Zhentar saved me.
Why Unity5, WHY do you forsake me?

skullywag

Has anyone done a programmatical trader before or anyone know how to stop a trader def being used by the normal traders?
Skullywag modded to death.
I'd never met an iterator I liked....until Zhentar saved me.
Why Unity5, WHY do you forsake me?

Haplo

If you can provide the source code and the mod folder via PM, I could try to find the culprit of your error.
And I promise I'll not reveal anything.  ;D

skullywag

Eh its not that big a secret, Shinzy figured it out when i posted in another thread for art for my trade ship :)

So heres my building, im just replacing the generatetrader method that was just calling an xml def as per core with one that sets a trader up programmatically.


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

namespace RimWorld
{
    public class Building_TradeDrone : Building_CommsConsole
    {
        private TradeShip trader;
        private const string txtTradeWithTrader = "TradeWithTraderPawn";
        private int selfDestructCountDown = 25000;

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

        public void SetupTrader()
        {
            trader = TryGenerateOmniCorpTrader();
            trader.GenerateThings();
            trader.name = "OmniCorp";
        }

        public override void ExposeData()
        {
            base.ExposeData();
            Scribe_Values.LookValue<int>(ref selfDestructCountDown, "countdown", 20000, true);
            try
            {
                Scribe_Deep.LookDeep<TradeShip>(ref trader, "trader");
            }
            catch
            {
                trader = null;
            }
        }

        public override void Tick()
        {
            base.Tick();
            selfDestructCountDown -= 1;
            if (selfDestructCountDown <= 2000)
            {
                Messages.Message("OmniCorp trade drone will be leaving shortly.", MessageSound.Benefit);
            }
            if (selfDestructCountDown <= 0)
            {
                IntVec3 loc = Position;
                TradeDroneUtility.MakeOutgoingTradeDroneAt(loc);
                Destroy(DestroyMode.Kill);             
            }               
        }

        public override void TickRare()
        {
            base.TickRare();
            selfDestructCountDown -= 250;
            if (selfDestructCountDown <= 2000)
            {
                Messages.Message("OmniCorp trade drone will be leaving shortly.", MessageSound.Benefit);
            }
            if (selfDestructCountDown <= 0)
            {
                IntVec3 loc = Position;
                TradeDroneUtility.MakeOutgoingTradeDroneAt(loc);
                Destroy(DestroyMode.Kill);
            }               
        }

        public override IEnumerable<FloatMenuOption> GetFloatMenuOptionsFor(Pawn myPawn)
        {
            List<FloatMenuOption> floatMenuOptions;
            if (!myPawn.CanReserve(this, ReservationType.Use))
            {
                FloatMenuOption floatMenuOption = new FloatMenuOption("CannotUseReserved".Translate(), null);
                floatMenuOptions = new List<FloatMenuOption>()
                {
                    floatMenuOption
                };
                return floatMenuOptions;
            }
            if (!myPawn.CanReach(this, PathMode.InteractionCell, Danger.Deadly))
            {
                FloatMenuOption floatMenuOption1 = new FloatMenuOption("CannotUseNoPath".Translate(), null);
                floatMenuOptions = new List<FloatMenuOption>()
                {
                    floatMenuOption1
                };
                return floatMenuOptions;
            }
            floatMenuOptions = new List<FloatMenuOption>();
            ICommunicable communicable = trader as ICommunicable;
            if (trader != null)
            {
                Action action = () =>
                {
                    Job job = new Job(DefDatabase<JobDef>.GetNamed("TraderGoTrading"), new TargetInfo(this))
                    {
                        commTarget = communicable
                    };
                    myPawn.playerController.TakeOrderedJob(job);
                };
                floatMenuOptions.Add(new FloatMenuOption(txtTradeWithTrader.Translate(new object[] { trader.name }), action));
            }
            return floatMenuOptions;
        }

        private TradeShip TryGenerateOmniCorpTrader()
        {
            TraderKindDef traderKindDef;
            traderKindDef = new TraderKindDef();
            StockGenerator_SingleDef sdef = new StockGenerator_SingleDef();
            sdef.HandlesThingDef(ThingDef.Named("Silver"));
            sdef.countRange.min = 2400;
            sdef.countRange.max = 3600;
            traderKindDef.stockGenerators.Add(sdef);
            traderKindDef.label = "OmniCorp";
            traderKindDef.description = "An OmniCorp Trade Drone";
            return new TradeShip(traderKindDef);
        }
    }
}


Everything works fine with the normal trader from xml, but then he also shows up in your traders and via the comms console. Hence me wanting to do this.
Skullywag modded to death.
I'd never met an iterator I liked....until Zhentar saved me.
Why Unity5, WHY do you forsake me?

Haplo

OK, if you've already figured it out, then there's nothing more for me to do?!  ;D

skullywag

no it still errors as above. What i meant was if i replace that method with the one from core (or your generate farmer) it works fine, it wont work however if i try to do it without an xml def and do it all in c#, see a few posts up for the error.
Skullywag modded to death.
I'd never met an iterator I liked....until Zhentar saved me.
Why Unity5, WHY do you forsake me?