#Setting Up Custom Guide Overseer

1 messages · Page 1 of 1 (latest)

lost parrot
#

if this isnt what the forum is supposed to be used for, let me know- this is a thread of me going over how i did this for unbound, and for help on setting it up.

this thread is for setting up a custom guide overseer. the guide overseer is a unique entity that follows the player, has a relationship value with them, and can point out danger, food, ect.
note: this guide is oriented toward custom campaigns, and thus will assume you are using a custom slugcat to code.

inspired because i was telling this to @upper bear in dms and realized i should make it more accessible to folks monksweat

#

^ image of gamma bc thats his overseer friend :]

#

OKAY

upper bear
#

hallo!! MonkHi

lost parrot
#

generally i start with a hook to On.Player.ctor. i had forgotten to add that part in dms like a CLOWN /lh. since this assumes its with a custom slugcat, you can set it up with any CWTs you may or may not have.

this is my code within that, after checking if it is the proper campaign:

{AbstractCreature gammaoverseer = self.room.world.overseersWorldAI.playerGuide;
if (gammaoverseer != null && gammaoverseer.ID != null && gammaoverseer.ID.number != -7113131)
{
if (self.GetNCRunbound().MoreDebug) { NCRDebug.Log("Gamma ID tweaked!"); }
gammaoverseer.ID.number = -7113131; // sets gamma to always have this id. "7 1 13 13 1", aka "gamma", negative because the positive counterpart has only two mycelia and that looked weird
if (gammaoverseer.ignoreCycle != true)
{gammaoverseer.ignoreCycle = true;
 gammaoverseer.creatureTemplate.waterVision = -1f;
gammaoverseer.creatureTemplate.damageRestistances[(int)Creature.DamageType.Electric, 0] = 1.5f;
gammaoverseer.creatureTemplate.bodySize = 0.7f;
(gammaoverseer.abstractAI as OverseerAbstractAI).BringToRoomAndGuidePlayer(self.room.abstractRoom.index);
if (self.GetNCRunbound().MoreDebug) { NCRDebug.Log("Gamma settings incorrect, fixed them and called Gamma!"); }}}```
now, thats a LOT, ill go over it--
upper bear
#

Sorry, I'm not good with acronyms, what's CWT mean again? thinky

lost parrot
#

conditional weak table! some people use those to keep variables and such in line for their slugcats.

upper bear
#

OH, right

lost parrot
#

basically:

  • check to make sure things arent null. sometimes, the playerguide will be null, but itll try to trigger anyway and cause a crash. because life is a nightmare. pretty sure i could have coded that simpler, but i dont recall exactly how to do so. so the long way it is.
  • sets the playerguide to a simpler variable! in this case, gammaoverseer will be the playerguide. every time thats typed, its the same guide overseer. this makes sure the guide is overwritten, not recreated.
  • if the overseer isnt null, but the id isnt the correct id (since the guide usually uses a unique id- this is a fun easter egg sort of thing, and a way to make the overseer viually distinct), set it to the correct one!
  • the above immediately also checks if gamma has the desired abstractCreature stats. this is because gamma is a tad different and i want it to be treated differently! gamma ignores cycles, has no vision underwater, is resistant to electricity, and is slightly smaller than usual. after doing so, it calls gamma to the room unbound is in.
#

this makes sure that the guide overseer is 1. existing, AND 2. has the proper id, to be sure youre grabbing the right one later on (this is a surprise tool that can help us later).

#

to tweak your guide, youll generally want to call:

#

?.world.overseersWorldAI.playerGuide

balmy sparrow
#

Sometimes null propagation doesn't work but instead makes soft exceptions

lost parrot
#

for example! gamma is forced to NOT respawn immediately if killed by ANY creature, including creatures who arent the player. so, it has a hook on Overseer.Die:

        {
            if (!self.SafariOverseer && self != null && !self.dead &&
                self.PlayerGuide && self.room.game.session.characterStats.name.value == "NCRunbound")
            {
                // should ONLY respawn in the next cycle
                if (self.hologram != null)
                {
                    self.hologram.Destroy();
                    self.hologram = null;
                }

                #region Base.Die
                Custom.LogImportant(new string[]
                    {
                        "Gamma Die!"
                    });
                if (self.killTag != null && self.killTag.realizedCreature != null)
                {
                    Room room = self.room;
                    if (room == null)
                    {
                        room = self.abstractCreature.Room.realizedRoom;
                    }
                    if (room != null && room.socialEventRecognizer != null)
                    {
                        room.socialEventRecognizer.Killing(self.killTag.realizedCreature, self);
                    }
                }
                self.dead = true;
                self.LoseAllGrasps();
                self.abstractCreature.Die();
                #endregion
            }
            else
            {
                orig(self);
            }
        }```
lost parrot
balmy sparrow
lost parrot
#

I GOT DISTRACTED
correct! i didnt simply because i already had in the part where i checked to be sure the right slugcat campaign was selected- the code is very long though so i cant send it without nitro

balmy sparrow
#

Making a GitHub guide might be helpful too monksilly

upper bear
#

I feel uh, like a fool

#

I'm not quite sure uhm, how I'd adapt this to my purposes

upper bear
#

Ouhhh, so

#

First it checks to make sure the room isn't null

#

basically, make sure the player is somewhere

#

the next part im not so sure of thinky

lost parrot
#

self.room.world != null: world isnt null
self.room.world.overseersWorldAI != null: overseer ai isnt null, is active and can do things
self.room.world.overseersWorldAI.playerGuide != null: the overseer who guides the player exists, so its not trying to add assignments to a thing that doesnt exist

upper bear
#

I see, thank you slughug

#

Sorry, I'm a bit dense-

upper bear
#

wait no,

#

Why should it be specifically that ? thinky

#

ohh, nvm, i saw that in the next line with the comment hunterglee

#

OH

#

it's the A1Z26 Cipher looking_respectfully

#

Is it okay if I take inspiration from that and use a similar Identification code for my Overseer?

#

(ofc it won't be the same number, i'll probably write something like 7 15 21 18 13, decrypts to Gourm)

#

What is the IgnoreCycle part ? thinky

lost parrot
#

oh, yes! i love ciphers hehe
and of course, feel free!
ignorecycle means the overseer wont run when the rain starts, which is important for gamma specifically so that they stay with unbound!

upper bear
#

ohhh

#

I see

#

Do you recommend something similar for the chonky cat?

#

Well... Crafting whilst raining is about to occur is not the wisest decision I think, but why not hunterglee

#

Ouhhh, now I just gotta make sure this custom overseer only spawns if you play Gourm

upper bear
#

Does this, look right ? thinky

#

(don't mind the body size, im just experimenting)

upper bear
#

actually nvm-

#

now it just deletes the player

lost parrot
#

OH! call origin

#

orig([variables])

#

that calls the original code- so, orig(self); if (nullchecks) then {rest of code}

upper bear
#

huh ?

#

im a bit stupid :(

lost parrot
#

yes, add orig(self, abstractCreature, world)

#

before your first "if"

upper bear
#

Alright so

upper bear
#

From this point on, how do I go about actually... What would the word be

#

summoning ?

#

or

#

Applying

#

The changes to the ingame Overseer

lost parrot
#

oh! okay so. looking at that, it will ALWAYS apply, regardless of campaign. you need to check and make sure the campaign is gourm first

#

the application should already work if enabled!

#

try setting bodysize to, like, 10f, then itll be really obvious if it works or not!

upper bear
#

Ouhhh, I can try

#

I also changed the colour, but so far nothing has changed catsob

#

there's something I did wrong, but I don't know what thinky

#

unfortunately it is still the same, hmm thinky

#

anyway, i was busy playing Unbound, i shall go back to that looking_respectfully

lost parrot
#

lizbluetilt can you copy-paste your code and its hook?

upper bear
#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;

namespace GourmCrafting
{
    class Hooks
    {
        public static void OnEnable()
        {
            On.Player.ctor += Player_Ctor;
            On.Player.Update += Player_Update;
        }

        private static void Player_Ctor(On.Player.orig_ctor orig, Player self, AbstractCreature abstractCreature, World world)
        {
            orig(self, abstractCreature, world);

            if (self.room.world != null && self.room.world.overseersWorldAI != null && self.room.world.overseersWorldAI.playerGuide != null)
            {
                AbstractCreature CraftingCompanion = self.room.world.overseersWorldAI.playerGuide;

                if (CraftingCompanion != null && CraftingCompanion.ID != null && CraftingCompanion.ID.number != -715211813)
                {
                    CraftingCompanion.ID.number = -715211813; //Consistently sets ID to an A1Z26 Cipher
                    if (CraftingCompanion.ignoreCycle != true)
                    {
                        CraftingCompanion.ignoreCycle = true;

                        CraftingCompanion.creatureTemplate.waterVision = -1f;
                        CraftingCompanion.creatureTemplate.bodySize = 10f;
                        CraftingCompanion.creatureTemplate.shortcutColor = new Color(1f, 1f, 1f);
                        CraftingCompanion.creatureTemplate.damageRestistances[(int)Creature.DamageType.Electric, 0] = 1.5f;
                        (CraftingCompanion.abstractAI as OverseerAbstractAI).BringToRoomAndGuidePlayer(self.room.abstractRoom.index);
                    }
                }
            }
        }

        private static void Player_Update(On.Player.orig_Update orig, Player self, bool eu)
        {
            orig(self, eu);

            
        }
    }
}
#

it should be hooked

lost parrot
#

okay i started doing comments for my own legibility. while it looks like it SHOULD work, there still is no check for gourmand campaign, so its trying to apply to every overseer

{
orig(self, abstractCreature, world); // calls original code, so nothing is overwritten. always do this unless your hook is "-="

if (self.room.world != null && self.room.world.overseersWorldAI != null && self.room.world.overseersWorldAI.playerGuide != null) // dont forget to check and make sure its gourms campaign here, too!
{
AbstractCreature CraftingCompanion = self.room.world.overseersWorldAI.playerGuide; // assigns the guide an easy variable to call

if (CraftingCompanion != null // the previous check already does this, this nullcheck is redundant! this is (self.room.world.overseersWorldAI.playerGuide != null) again and can be removed
&& CraftingCompanion.ID != null && CraftingCompanion.ID.number != -715211813)
{
CraftingCompanion.ID.number = -715211813; //Consistently sets ID to an A1Z26 Cipher
 
if (CraftingCompanion.ignoreCycle != true)
{ CraftingCompanion.ignoreCycle = true; // wont flee at rain
CraftingCompanion.creatureTemplate.waterVision = -1f; // cant see through water
CraftingCompanion.creatureTemplate.bodySize = 10f; // larger, for visibility
CraftingCompanion.creatureTemplate.shortcutColor = new Color(1f, 1f, 1f); // this only changes the colour of shortcuts. as overseers dont use shortcuts, this will not work CraftingCompanion.creatureTemplate.damageRestistances[(int)Creature.DamageType.Electric, 0] = 1.5f;
(CraftingCompanion.abstractAI as OverseerAbstractAI).BringToRoomAndGuidePlayer(self.room.abstractRoom.index); // calls overseer to player

} // close if not ignorecycle brackets
} // close if not correct ID
} // close if not null
} // close ctor```
#

do you have an exceptionlog when you do this? lizbluetilt

upper bear
lost parrot
#

i see, but in the future!
maybe try adding a UnityEngine.Debug.Log("log here")? to make sure its reading? in between different parts of the code

upper bear
#

Where is that log printed to ? slughug

lost parrot
#

exceptionlog, generally here!

#

no wait

#

i lied

#

consolelog

#

unityengine.debug writes to consolelog

#

mixed them up for a sec

upper bear
#

I see, thank you slughug

#

Two more questions

#

first, I saw there's a console in dev tools, you access it by opening the menu and pressing

#

uh, i think it was J?

#

wait no

#

K

#

it's K

#

Is it possible to print to this ?

#

And how do I check for specific campaigns? looking_respectfully

upper bear
#

so it goes in as far as this

#

So my guess is that it just doesn't reach the uh

#

the part where it modifies the overseer

#

hold on

#

i'll add one more report

#

no, it DOES reach it

#

Huh... Then what for what purpose is it not...

lost parrot
#

fascinating! do you have a mod that can check ids?

upper bear
#

Ouhh

#

I do not

#

i'll get one

#

wait

#

715211813

#

it is applying

#

@lost parrot In that case, it does seem to be working !

#

hmmm

#

the amount of mycelia is based on their ID, right ?

lost parrot
#

correct!

upper bear
lost parrot
#

looks like assigning size and such may not work then! happens huntershruggy

#

"NCRDebug" is a shorthand i have for "UnityEngine.Debug" so i dont have to type it a bunch, and because my application likes to throw errors if i use the whole name

#

"getncrunbound" is to access my CWT!

upper bear
#

Also saw this part in your code, I assume I just need to write Gourmand in the palce of Unbound, yes? self.PlayerGuide && self.room.game.session.characterStats.name.value == "NCRunbound"

upper bear
upper bear
lost parrot
#

lizbluetilt not quite, no- gourmand has its own variables
itd be characterstats.name == [msc variable location].gourmand

#

you WILL have to find the name, i dont know it rn @...@;;

upper bear
#

ouhhh

#

hmm

#

WHY IS NIGHT CAT IN THE BASE GAME CODE, BUT-

#

oh right, he used to be in the

#

arena

#

@lost parrot i think it won't be too difficult monksilly

#

I just have to define the name looking_respectfully