Mobile NPC Woes

Discuss modding questions and implementation details.
Post Reply
User avatar
Kayzee
Posts: 13
Joined: Mon Apr 22, 2019 9:39 am

Mobile NPC Woes

Post by Kayzee »

So, I have been playing around with Daggerfall Unity lately, and installed lots a mods. One of them I kinda like is Villager Immersion Overhaul. Though it's only a simple texture replacement, I like the idea off adding some more variety to the randomly spawning NPCs. But one thing kinda bugs me about it... Because it's just a texture replacement, none of the faces match, and it has to replace existing villagers.

So I decided to try and make a small mod to add to the pool of randomly spawning villagers. Should be easy, I think. As it turns out, not so much. I mean, it's not that it's hard to program it. It's true I am much more used to Ruby rather then C#, but I am a fairly experienced programmer and I am able to dive in to C# pretty effortlessly I think. Though I have a few grumbles here and there. And it was kind of a pain to even figure out how to make mods in the first place, but I am pretty sure I have that down.

No, the thing that really made me want to pull my hair out in frustration is that it almost seems like the whole Mobile NPC system was purposely written to frustrate anyone attempting to mod it. Maybe it's just a problem with me being unused to having to deal with statically typed languages and being spoiled rotten by how Ruby basically lets you easily modify any class any time you want I donno, but I'm not sure how the heck I am supposed to actually make a mod if I can't, ya know, modify anything.

The first thing I tried is replacing MobilePersonNPC with a subclass. Well okay, the FIRST thing I tried is seeing if I could just overwrite MobilePersonNPC's methods with different ones, but I didn't expect to be able to. Anyway...

Funny thing I found out number 1: Private members of a class not inherited at all. And about two thirds of the stuff in MobilePersonNPC is private... Okay... not sure why, but I never really understood the point of private members (heh heh, private members) anyway... Yeah okay, I get you might want to hide implementation details and stuff but it seems like your just making it more of a pain in the ass to deal with in the end. But fine, fine, I had to sort of rewrite a lot of that stuff anyway, so I can just add the private members to the subclass to right?

Funny thing I found out number 2: I thought for sure that subclasses of something were supposed to be able to used in the same way as it's parent class. Isn't that what the whole 'principle of replacement' is about? But apparently, no. Because PopulationManager apparently doesn't like it much when it can't find the MobilePersonNPC component on the game object, even when a subclass is on it. Maybe I could make a whole new PopulationManager... except it's set on locations which don't have a prefab. I tried making an event hook run when a location is loaded that disabled the original PopulationManager and attached a version I wrote... but that didn't seem to work either. Not even sure If i coded my new versions of stuff right to be honest, but I was having a heck of a time even getting the code to be recognized by the system enough to test.

So what am I missing here? Is it just a matter of stuff being unable to be messed with unless a programmer explicitly adds an event hook or prefab for it? Or is there some way to do this I am not seeing?

User avatar
King of Worms
Posts: 4753
Joined: Mon Oct 17, 2016 11:18 pm
Location: Scourg Barrow (CZ)
Contact:

Re: Mobile NPC Woes

Post by King of Worms »

Welcome :) it would be fantastic if you made this thing come true. I think Interkarma will know everything about this code... if he doesnt drop by at this thread, maybe try to write him a PM with the link to this post.

Good luck!

User avatar
MasonFace
Posts: 543
Joined: Tue Nov 27, 2018 7:28 pm
Location: Tennessee, USA
Contact:

Re: Mobile NPC Woes

Post by MasonFace »

Disclaimer: I am woefully unqualified to reply to this topic, so take my opinion with a grain of salt.
The thing that really made me want to pull my hair out in frustration is that it almost seems like the whole Mobile NPC system was purposely written to frustrate anyone attempting to mod it.
No wonder so many programmers are bald... :lol:

But honestly, I believe the design philosophy has been to implement the systems necessary to replicate the functionality of vanilla Daggerfall first and foremost. I expect once DFU reaches version 1.0, there will be a bigger emphasis on making systems more extensible and modder friendly.

I'm not familiar with Ruby, but you described it as being capable of "modifying classes any time you want" which to me sounds super handy, but also a bit dangerous. Again, I don't know how Ruby works so maybe it has a way of isolating these changes, but I could definitely see Mod "A" changing a class that Mob "B" depends on and it causing weird issues when both Mods are enabled. I believe this is part of the reason C# programmers tend to (in my opinion) overuse private variables and private members (tee hee!) so they can minimize the risk of unintended interactions.

Anyhow, like King of Worms mentioned, Interkarma is the man! I'm sure he can answer all your questions and point you in the right direction to get the desired outcome. I wish you all the best luck in getting this implemented because it sounds really neat!

Al-Khwarizmi
Posts: 177
Joined: Sun Mar 22, 2015 9:52 am

Re: Mobile NPC Woes

Post by Al-Khwarizmi »

Kayzee wrote: Mon Apr 22, 2019 12:48 pm Funny thing I found out number 1: Private members of a class not inherited at all. And about two thirds of the stuff in MobilePersonNPC is private... Okay... not sure why, but I never really understood the point of private members (heh heh, private members) anyway... Yeah okay, I get you might want to hide implementation details and stuff but it seems like your just making it more of a pain in the ass to deal with in the end. But fine, fine, I had to sort of rewrite a lot of that stuff anyway, so I can just add the private members to the subclass to right?
I don't know much about the innards of Daggerfall Unity, but as a coder myself, I can give you a general answer on why private members are good, and I don't think it will be much different to the DFU-specific answer.

Suppose you make a method public. This means that anyone can create a mod (or a pull request, etc.) and call that method. Great, right? Not so great, because... you have now set the interface of your method in stone for eternity. If you now want to change that method for a future version of DFU, all the code that was calling it will fail. So either you don't change it, and have a piece of fossilized code that cannot be improved and adapted, or you change it and make modders (or other coders that have to interact with your method) angry.

In the extreme case where everything was public, you would just have plain unmaintainable code. You would never be able to change anything without the fear of breaking something, because hey, someone might be calling your code.

This is why you try to define a stable public interface with the minimum possible methods to give other coders the functionality they need, but keep everything you can private, so there are fewer dependencies with respect to external code and the program is easier to maintain.
Kayzee wrote: Mon Apr 22, 2019 12:48 pmFunny thing I found out number 2: I thought for sure that subclasses of something were supposed to be able to used in the same way as it's parent class. Isn't that what the whole 'principle of replacement' is about? But apparently, no. Because PopulationManager apparently doesn't like it much when it can't find the MobilePersonNPC component on the game object, even when a subclass is on it. Maybe I could make a whole new PopulationManager... except it's set on locations which don't have a prefab. I tried making an event hook run when a location is loaded that disabled the original PopulationManager and attached a version I wrote... but that didn't seem to work either. Not even sure If i coded my new versions of stuff right to be honest, but I was having a heck of a time even getting the code to be recognized by the system enough to test.
Again generic answer... yes, an instance of a subclass is supposed to be usable wherever you can use an instance of the superclass (Liskov's substitution principle) but this is not always feasible in real code (especially in large systems). The truth is that object-oriented programming has a lot of pitfalls and often you have to find compromises, sacrificing this or other principles. For example, a Rectangle is like a Square, but I can change width and height separately, so it's quite natural to implement it as a subclass that extends Square with new functionality, right? However, can use a Rectangle wherever I use a Square? Nope. The gist of the problem is that subclasses are convenient both to say "X is a kind of Y" and "X extends the functionality of Y", but these two concepts are often directly at odds!

In fact, there are people who advocate not using inheritance in OO in the first place, because it often creates a mess.

There's a book by Bruce, "Foundations of Object-Oriented Languages: Types and Semantics" (https://www.amazon.es/Foundations-Objec ... 026202523X) which is not hard to read, and shows you a lot of cases where object-oriented programming creates contradictions or ugly code and it's difficult or impossible to avoid it.

User avatar
Kamer
Posts: 583
Joined: Mon Mar 05, 2018 9:26 pm

Re: Mobile NPC Woes

Post by Kamer »

I've talked to TheLacus about it. Currently RegionPopulation and mobile billboards and all that aren't open for modding. I've been meaning to make a thread to request it be open up but currently it isn't unless you really know what you are doing.

User avatar
Kayzee
Posts: 13
Joined: Mon Apr 22, 2019 9:39 am

Re: Mobile NPC Woes

Post by Kayzee »

Yeah, I know finishing off vanilla Daggerfall should be the number one priority. I agree 100% with that! Honestly I think most of my frustration is with C# and not Daggerfall Unity. I feel like it shouldn't be nearly as hard to work around this stuff as it is.

Well, I mostly got into Ruby because of RPG Maker VX Ace, and the way scripts with that tends to work is with a form of monkey patching that uses "alias chains". A method is copied to a new name, and the original name calls the new name. The upside of doing this is you can pretty much extend any method to do extra stuff without actually changing the underlying implementation. The downside? Well, the order the scrips are loaded in becomes really important for one thing. You have to put scripts that fiddle with classes after they are all defined, and some things can't really just be extended like that very well and the method just ends up being replaced, which can complicate stuff. Still, most RPG Maker scripts work well.

That is a rather extreme way of extending classes though, even for Ruby. Most of the time serious Ruby programmers will probobly recommend you use mixin modules witch work very much like C# Extension Methods, though with one major difference: Included modules become part of a class's inheritance chain so you can call them as you would a superclass's methods. It's kinda Ruby's form of multiple inheritance. A class may only have one parent, but you can include modules that act like parents.

There are all sorts of other crazy stuff you can do with Ruby in that regard. And some of it may be 'dangerous' yes, but most of the time it doesn't end up being a big deal. But it seems C# doesn't have any of those kind of handy tricks really, or if it does I don't know how to use them yet. It seems to come close at times though, because I noticed you can have two classes of the same name or import classes as a different name.

I mean that's the thing: The interface of your method might not be able to be easily changed, but the implementation details can be and the interface can be extended if need be.

Also: Don't forget there is a middle ground between public and private though! Protected members are a thing too, and honestly I think it would be handy to have a way to mark public members as unreliable and subject to change anyway.

Also also: Really a lot of this is a matter of opinion either way. I personally don't really think there is a 'right' way of doing anything. Whatever works, works. It's mostly just frustrating because it feels like I should be able to figure out a way around the problem but I can't. :(

... Well other then actually changing the base code and creating my own fork anyway. That wouldn't be too hard I think, but kinda pointless in the long run unless anyone cared enough to merge it into the main branch, which I find unlikely at this point.

Oh well... Maybe I will work on another mod idea. Hmmm.... You know, as a magical fairy I find it sort of sad my kind was cut from the game for the most part. Maybe I should try and find a way to bring them back? Hehe, it would be nice for the fair folk to roam the realm of Nirn don't you think? :P

Post Reply