Evolution of Behaviors #151
DavidRieman
started this conversation in
General
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
The threads captured here from the archives will hopefully help provide context for how the Behaviors system has evolved over the years to what it is today. Some parts of this may get edited out to other threads, as Behaviors covers so much of WheelMUD's functionality, it's hard to organize these in any way that isn't overwhelming to read up on.
This thread contains restored content from prior forums; see #134 for details.
[Apr 2009]
Item Properties and Behaviors
Items have a core set of properties that apply to most item types; a name, keywords, description, a weight, probably an item “level”, a value, etc.
Items have a list of behaviors, like
ArmorBehavior
orWeaponBehavior
, which extend upon the normal item properties.Commands like ‘wield’ would scan the item’s behaviors list for a suitable
WeaponBehavior
, then check the behavior’s specific properties (and the current player’s properties) to ensure that the weapon can be wielded by this character;If any existing wielded/held/shield slots can not be emptied (IE maybe they are cursed) then cancel the ‘wield’ attempt.
Etc.
Similarly, a ‘wear’ command would scan the item’s behaviors for a suitable
ArmorBehavior
orShieldBehavior
, then check the behavior’s specific properties to ensure that the armor or shield can be worn by this character;If it is marked with multiple armor slots, also removes additional slots.
This could be accomplished by having multiple
ArmorBehaviors
; for instance a Heavy Plate Gauntlets might take up both your hands slot and wrist slot, but since both behaviors provide an appropriate AC bonus, it may be worth giving up your Gloves + Bracers combo to wear it.If any existing worn slot covered by this armor can not be emptied (IE maybe they are cursed) then cancel this ‘wear’ attempt.
Etc.
Additional behaviors might be added to extend the available suite of item functionalities:
WeaponProcBehavior (to have occasional ‘upon hit’ reactions like casting a spell upon the wielder, the party, or the current offensive target).
Properties include the spell/effect ID, possibly a targeting hint, possibly a caster level or stat quantity for use in effect strength instead of the user’s, “proc rate”, etc.
ActivationBehavior (to have a generic ‘activate’ command cause the item to do something like cast a spell upon the wielder, the party, or the current offensive target. Similar to WeaponProcBehavior in many ways, but this effect is triggered upon demand by the activating player.
Properties include the spell/effect ID, possibly a targeting hint, possibly a caster level or stat quantity for use in effect strength instead of the user’s, etc.
To keep activation items balanced, it may make sense to have a single countdown timer for each player such that they may make one ‘activation’ every half hour, regardless of the item activated. Alternatively, one might design their MUD to have such things only exist as coveted quest rewards.
For example, you might have a “Spirit Amulet” that, upon activation, summons a spirit to fight for you in the same manner that a necromancer might cast a “Summon Spirit” spell at will. It might be level-dependant so a level 1 character could not use it, but other than that, a fighter-type might covet such an object while a necromancer might seek to sell it since it offers them nothing that bolsters their existing abilities.
DropBehavior (to have something special happen when the item is dropped, or prevent the item from being dropped)
RemoveBehavior (to have something special happen when a player tries to remove the item, like preventing the removal; IE a “cursed” effect. A “remove curse” spell could scan for and delete such RemoveBehaviors.
QuestBehavior (See Questing design for more details.)
Mark this item as a quest item, which can influence the tradability or salability of the item outright.
Properties that describe things like the quest ID that it belongs to, and upon what mob and at what frequency it might spawn, etc.
Items with QuestBehavior can not be looted from a mob unless they have the assigned quest ID among their active quests list.
[Nov 2009]
Liquids and Fill
I think that we could treat liquids as a derivative of stackable items (like currency and whatnot). We don't have to display it with a numeric quantity though but that is intended to be a simple matter of overloading some method(s) properly. For simplicity in the core system, we should probably disallow mixing of unalike liquids into one container by default. We would only want the most basic/required of properties on the base Liquid object. The extensibility model we are trying to utilize is basically to have complex Behaviors tacked onto more basic items, by using the
BehaviorManager
s. So a liquid that is flammable would have something like aFlammableBehavior
attached to it; theFlammableBehavior
would in turn have the properties of how flammable it is (how much heat is needed to ignite, how fast it burns, or whatnot as desired). Then the ignite/light command would require that the target lamp (a container with aLiquidContainerBehavior
or whatnot) contains an item which has theFlammableBehavior
before applying theOnFireEffect
to the liquid. (There are a handful of good threads on the forum about the current direction of the Behaviors system and such.)Similarly, the Fill command (to take liquid from another container like the fountain or river) would require the target receiving object to have the
LiquidContainerBehavior
before moving some of the liquid quantity from the fountain into the container. Output like "You don't think it could hold the [liquid name] very well" could be the response if the target item doesn't have theLiquidContainerBehavior
. And so on.Hopefully drinking a potion with one "quaff" worth of liquid quantity, and drinking a mug which contains one "quaff" worth of liquid, will essentially boil down to the same code in the end... probably where the act of quaffing applies some Effect(s) as specified by some Behaviors that are recognized by the quaff. It's been a long while since I looked at potions so I forget how they were started, and I don't recall if the current implementaiton fits the Behaviors direction.
As a quick aside, things like
FlammableBehavior
get me excited for the Behaviors system :) Imagine slapping that on some cloth/paper items too and rigging fire spells/effects to have a chance to ignite equipment based on variable heat/damage, and now you have to be careful about fireballing your mobs willy nilly lest you risk burning up their equipment, or vice versa, fail to fire-protect your gear...[ed. update 2021] I think a potion would be using something like an
QuaffAppliesEffectBehavior
which would be configured with an Effect to clone; the Behavior would register to watch events of theThing
it's on to simply react to the Quaff event, by cloning said Effect to the quaffer. (It too would use a Request+Event around this, so other effects like immunities could cancel that Effect application uninvasively.)[Dec 2009]
Interfaces and Behaviors
Mainly the IInterfaces are legacy and we're trying to remove/replace them with more appropriate ways to expand/define functionality. When one wants to know if an Item is a Container, they can ask the Item's
BehaviorManager
if it has aContainerItemBehavior
. This is more flexible since, for instance, one suddenly decides they want an item that is both a portal and a container for some reason, they can do that without adding a ridiculousPortalContainer.cs
just for their one specially designed item.(All from memory here, don't have code available at this PC yet...) As is, Items should be saving their list of Behaviors upon saving, whether they are an Item or a class that derives from Item. As is, if a Portal is saved to DB, it would be loaded as an Item class which is given the
PortalBehavior
. This would not change.The intent of having something like a Portal class itself is to make it easier to create such things the fly, IE for a Portal-creating spell. The code can look something like:
Instead of:
This could be slightly simplified with constructors that take (a collection of) Behaviors and the application of construction syntax like:
Personally, I like the last form well enough to warrant removal of the shallow classes.
I thought about this for a while too; where do we draw the lines so they make most sense? I was thinking it would be nice to have almost no special persistence code for players/mobiles. IMO attaching stats to a thing, whether it's a player or a mobile, should be consistent; if the best of 5th level player humans can have 1,000 HP then I roll my eyes when I see a random 5th level NPC human with 10,000 HP. Probably a better reason for
PlayerBehavior
is the simplification of features like 'remorting': the Thing stats can be created for a new remorted player and thePlayerBehavior
is then just transferred to the new Thing. Anyway I'm not 100% married to thePlayerBehavior
/MobileBehavior
, but it does at least have the benefit of drawing the 'line' firmly in the ground: there can be only one Thing.UserControlledBehavior
is a little easier to back up though: one shouldn't have to write a whole lot of special-case code to support scenarios like 'possessing' a mobile. Move yourUserControlledBehavior
over to it, maybe disable theMobileBehavior
, and you're pretty much done; command routing and everything is set up correctly now. Take this one step further and have a game mode where you 'play as monsters', where the game slaps yourUserControlledBehavior
onto a suitable mobile for your monster experience level and viola, your players now have random encounters that act smarter than their normal AI, like humans. Fight well or even kill a PC and you get monster xp... soon enough you'll be playing as the dragons sometimes. (Of course one would want features to prevent abuse/powerlevelling/etc.) I'm not sure yet whetherPlayerBehavior
needs to move temporarily too in some cases, but hopefully not.Here's a fun excercise. Want to make a tank? Ok we make a Thing with a
RoomBehavior
,EnterableExitableBehavior
, and aMannedVehicleBehavior
which merely adds a 'drive' context command inside itself, which if not currently containing aUserControlledBehavior
moves yourUserControlledBehavior
to the tankThing
itself! Now you can see the room outside the tank, move it with your cardinal direction commands, etc. The tank has it's own stats like HP/armor assigned. Also adds a context command to itself so if 'it' types 'unman' or 'stop driving' or whatnot theUserControlledBehavior
is returned to the pilot. In short, there are times when you want things other than your typical humanoids to be "playable." Sure you'd run into other issues/bugs like "the tank can use emotes like shrug" but generally these issues should be addressable at the Behavior that is local to the problem; MannedVehicles should not be allowed to use emotes, so they should register to the proper event requests and cancel them (or forward them to their driver). IE the player typed "shrug" while driving a tank, the emote Action raises a request with a filled in EmoteArgs, theMannedVehicleBehavior
is subscribed to this so either cancels it with a "This vehicle can not do that" message or it cancels the request and reraises the same request on behalf of its pilot, so anyone else inside the tank sees "Pilot shrugs." Slap aMannedWeaponBehavior
on that tank and now another player can use the context command to man the guns... Or the sameMannedWeaponBehavior
could be attached to a non-enterable catapult, etc. Anyway I'm off topic now but it's fun to think of the possibilities.[ed. update 2021] Actually the command problem isn't really a problem for the behavior to subscribe and cancel; Its merely a problem of marking up the command with the correct metadata/guards permissions to only be operable by a
Thing
withPlayerBehavior
/MobileBehavior
. So if a "tank" tries to "shrug" for any reason, and that tank is controlled by a user session, they'll get a "you can't use that command" sort of response because the user-controlled entity isn't eligible to execute it.[Jul 2010]
In the OLC post you sounded like you were all for getting rid of things like Weapon objects and using
WieldableBehavior
instead. I think I misunderstand some of what you wrote here, so I'll just speak to some key points and take a stab at the rest.Separation of Concerns is generally one of the most desirable traits in programming, so I don't understand why it would be a problem here. IMO it's one of the greatest benefits of the Behaviors system both as it was and as it will be (I'm simply extending it to more things), and is key (alongside eventing) to building an extensibility model where people will be able to build on top of, rather than being required to modify, the core codebase.
If we weren't able to adjust the behaviors of something like a Room without modifying a
Room.cs
,Room.cs
could grow into this behemoth of twisting logic gates, incomprehensible at an attempted glance-through. Adding a property for a chance to deal some damage every second while in the room? Better add yet another layer of logic toRoom.cs
... On top of polluting Room's property set with properties specific to this very edge-case sometimes-want-it behavior, and adding storage of the property value to every object in the DB. Ugh. Imagine trying to integrate that feature between MUD codebase instances... How many C/C++ MUDs integrate features between each other regularly? Hardly any, because this sort of code sprawl is not well contained, and everyone has to 'hack away' at random parts of code in random files, so sharing the code is inhibitively expensive. On the other hand, imagine that to integrate that feature you simply add theirPeriodicallyDamageContentsBehavior.cs
(or a tiny DLL or NuGet) to your codebase. Sharable. Also, it's not confined to a Room; attach that behavior to a treasure chest, and now damage is dealt periodically to its contents, whether that's a small pixie-sized character or another object that can take damage, all with no additional code. So we've just avoided massive copy-pasting of code just to support a feature across multiple object types.I don't think I follow what you're trying to say here. You can tell if a thing is wieldable by asking it's behavior manager if it has the
WieldableBehavior
. No need for having and maintaining a redundant enum value like 'HasWieldableBehavior' or anything.I don't see a difference between external game rules being tied into
Room.cs
vsRoomBehavior.cs
, orWeapon.cs
vsWieldableBehavior.cs
, etc. However, instead what I see in my mind is having something like aGameWeaponBehavior.cs
stored in the game-specific library. So the core MUD implements theWield.cs
command and such against the genericWieldableBehavior
, but is ignorant of whether OR how those things hit or do damage or how (or how frequently) the game rules perform attacks, etc. The game rules library implementingGameWeaponBehavior
adds the logic for to-hit chance, damage-dice-rolling, etc, basing it on whatever it wants (class/skills/level/whatever). But it doesn't have to deal with how to get the weapon on/off the character's paper doll, since they're using the providedWieldableBehavior
, etc. Separation of concerns again, leading to a more rapidly developable custom combat system, etc. :)GameWeaponBehavior
would likely utilize eventing to execute its code during attempted attacks, etc. (I see tracking of combat state, commands like Flee.cs, ticking of attack phases whether on ticks or on timers etc, and so on, all being implemented at that level rather than as custom modifications of the core. They could even, say, add a Disarm attack etc without any problems by leveraging the existing "core" behaviors like finding theWieldableBehavior
and leveragingwieldableBehavior.Remove
instead of duplicating paper doll code.)Anyway I hope I've addressed some of your concerns. It's really going to suck if I've done all this work thinking everyone was on board based on earlier comments only to find out it's undesired after all. IMO this is going to help us get to 1.0 faster overall since contributors will be much more enabled to contain their work rather than sprawling changes all over, redundant interfaces won't be hindering changes, the persistence code will have far fewer things to need to know how to save/load to the DB, the 'core' won't necessarily have to house ticking/combat logic, etc.
Ah yes, I agree, getting rid of redundant interfaces is something to strive for. I got rid of a bunch already in my branch, and made no new ones.
I'm not wholly opposed to partial classes, but IMO they should be used sparingly since they are a bit confusing as they hide details, even with "browse to definition" and such. Partial classes do have their place of course, IMO that's usually around auto-generated code and the like. The issue isn't a sticking point for me lately though.
On loading code... We can have Behaviors/Effects and Actions and such registered via MEF. Any game-rules or other extension DLLs can have the Core as a reference (just not the other way around) so an extension Behavior still knows all about the
Thing
class, for instance, and thus can register to its parent's events. Any MEF-registered Actions get put into the list for processing against input. OLC behavior/effect list commands and such would operate against all MEF-registered types, not just core types. Other one-time init could be done similar to the FTP setup, but I could see implementations of combat and such which wouldn't even need that with intelligent application of a CombatBehavior or whatnot.[Mar 2011]
There are a couple basic goals of the Behaviors system. Behaviors should help with Separation of Concerns - for instance, weapon-related code is not located in the core item code, it should all be contained in relevant behaviors. Eventing... Requests which can be cancelled, and then Events which broadcast about something happening... really helps here - for instance the
ExitBehavior
can expose a context command to the place (typically a room) that it's located in. The exit-related command code is even housed in theExitBehavior
(next to the other code of similar concern). When attempting to move through, a movement request is posted; theExitBehavior
doesn't have to know anything about the existence of various things such asImmobilizedEffect
orJailedEffect
which might subscribe to all movement requests made on behalf of the player and cancel them.In other MUD codebases... when you added something like an immobilization spell you'd have to go touching all sorts of parts of the codebase to implement it, such as the exits-handling code.
Separation of Concerns in turn has its own benefits, such as improved testability of a given component.
Behaviors will help improve the composability of very complex item types which one wouldn't want to have to fully define as their own class. For instance, one might assume that Portals will always be unmovable, permanent, indestructable fixtures which a player can enter, one-way, and end up in another location. But then a MUD admin decides to make a portal-creation spell or have a destructable portal or whatnot... One shouldn't have to code up hard classes for
TemporarySpellPortal
,DestructablePortal
,DestructableMovablePortal
,DestructableMovableTemporaryPortal
, etc... nor should a portal-related class have to start adding properties for every conceivable potential usage which get ignored by 90% of the cases... it is more desirable to just start adding Behaviors to the core Thing and have them all apply their properties to the Thing correctly.[Defunct links to forums threads redacted.]
Also, don't be afraid to resurrect old threads when you have further questions or comments on something. (I know some communities frown on resurrecting threads but we're generally the opposite.)
No, it shouldn't. Something like a 'who' command could be implemented by finding all
Thing
s in the world which contain aPlayerBehavior
, listing some info about them. ThePlayerBehavior
itself houses player-specific properties, and I do literally mean properties. Things like the last login date of the player, their list of characters they have "friended", player-specific settings such as their preferred prompt, etc.Note that this is distinct from the
UserControlledBehavior
, which helps direct the commands a player sent through their client to the game into actions the attached Thing attempts to perform. IE if a player has some sort of 'possession' effect, the code might transfer theUserControlledBehavior
onto the possessed mob. (That part is mainly theory - we haven't actually set that up.) But the point is, a typical "player characterThing
" under normal circumstances will have not only aPlayerBehavior
, but also aUserControlledBehavior
,SensesBehavior
,LivingBehavior
,MovableBehavior
... each piece of code can be read and reasoned about by itself. In a hypothetical MUD where players control tanks directly and don't have 'player' avatars, you don't have to rebuild a whole Player class, you just have to removeLivingBehavior
as somethign character creation assigns, add aVehicleBehavior
instead, add behaviors specific to your game, etc... Most of the 'core' parts of the game will still work great w/out modification to core code.[May 2011]
On implementing Talents... you have a good grasp of how I envision the behaviors system working and expanding in a way that each piece is a fairly isolated, independently-testable piece. I could certainly see a
TalentsBehavior
,SkillsBehavior
, andStatsBehavior
house the relevant properties/methods/logic. Here's a couple good reasons IMO to do it this way:Thing.cs
has far more impact than integratingSkillsBehavior.cs
.As for logic flow: say a given Skill uses a given Stat, so that skill looks up the
StatBehavior
of the user, then grabs the specified (current, not unbuffed) stat, and uses that for it's success/failure calcuations or whatnot.On not needing the heavy
PlayerBehavior
... Sure. The amount of splitting I did was basically the minimum amount I felt appropriate for the initial behaviors system refactoring - I really wantedUserControlledBehavior
to be split out to possibly help with possession commands and direct-vehicle-driving modes the like,MovableBehavior
to allow defining non-living things that move like vehicles and non-moving living/destructable things (IE a gate you have to attack your way through to destruction which hasBlocksExitBehavior
but cannot ever be coerced to "move" through any current or future-developed magics), etc.Basically the rule I envision following is: if you can see the vast majority of all
Thing
s in the game world having a particular type of property (likeName
), then it might make sense to be on the baseThing
... Even the Stacking ofThing
s I have second thoughts about being part of the coreThing
rather than, say,StackableBehavior
... but I think the complexity of getting aStackableBehavior
right as a separate behavior that's constantly mucking with multiple things' names and such could be a nightmare.[Nov 2009]
As for spells, I know we've talked about spells here and there, but I don't think they have their own thread anywhere that I can find. The biggest thing of note is that we're leaning towards having them be in the game-specific assemblies rather than the core framework, since they're generally very game-specific.
[May 2010]
That sort of flexibility suggests that the Behaviors system is the right direction; one can always make a new Behavior for a door or exit that only allows passage under some newly invented circumstances/mechanics. Having an
IsLockable
on the Item doesn't make sense to me since most objects won't be lockable, and the manner of locking can differ as mentioned, and really additional data is needed about the locking mechanism (IE more properties defining how it can be unlocked) are needed to make the property useful.Ya sounds like a step in the right direction. Thanks!
I'm just pointing out that in general, I think the more divergent the potential behaviors (and indeed you point out the huge diversity in locking/unlocking mechanisms and related bheaviors that could be possible), the less we want all those possibilities to be baked into the base Item/
Thing
class. Having anIsLockable
property is not enough information to treat the object as an unlockable object; does it have a key, a password, a hidden button? Knowing it's lockable isn't enough to implement unlocking; more properties are needed, and should all those possibilities be implemented into the baseThing
? I sure hope we don't, say, start adding hundreds of properties to the base Thing class likeAllowsInteractionOnlyWhenUserIsDrunk
rather than having such behaviors defined through the behaviors system (and thus only a consideration for code when an appropriate Behavior is attached to the coreThing
)....thinking about whether I add various properties to
LocksUnlocksBehavior
which designate what template IDs count as a "key" for that lock (if any) and which sides of the thing (which location IDs) are allowed to unlock/lock it freely (IE a normal door that can be unlocked without a key from one side)...Leaning towards extending
LocksUnlocksBehavior
and just having crazy varients like combination locks be their own behavior.[Sept 2010]
On new MudEngineAttributes... I'm not particularly familiar with this class yet... I don't know. Probably fine for now.
On the Enqueue... Yeah I've seen a line like this before and I suspect it would have some slightly unforseen consequences, but generally not catastrophic. Imagine that the player already has a bunch of commands queued up, and doesn't understand the responses they're getting for those queued commands until some time later the forced 'look' reveals that they're not in the room they think they're in. That said, if it gets the job done, I'm not too worried about this. When we figure out the correct way to handle the forced looks (perhaps calling on the player's SensesBehavior for immediate resolution or whatnot), it won't be too hard to find each of them and fix them all in one pass.
I agree an admin should be able to jail offline players. This part might make most sense to put a ticket back in for later; I suspect these sort of things will be easier to code when my branch work is done and we can have a way to load the Player w/out its
UserControlledBehavior
, change their parent (room), slap aJailedEffect
on them, and persist the Player to save it... I'm sure there are other commands we'd likely want to work against offline players in a similar fashion.IMO the JailedEffect should simply subscribe to all movement requests of it's parent (player) and cancel them if it is the player that is attempting to move (whether or not of their own accord). I think that's still possible in the mainline. Possibly in the future also cancel certain communications events, global auction events, etc.
On avoiding innocent players getting into jail on accident... Similarly a
JailRoomBehavior
could subscribe to movement events (arrivals) and cancel them (if they do not have theJailedEffect
). (Any spell/effect which moves a player needs to have an intelligent response for failure anyway.)In the Behaviors direction we've been taking things, a
MutedEffect
will not operate againstThing
properties. Indeed, changing something else's properties is inherently dangerous because it invites bugs/exploits/etc where multiple things alter that property (IE imagine aMutedEffect
altersCanTalk
, JailedEffect altersCanTalk
, then only one of those is removed and "restores" the state it stored back to "true"). These effects shouldn't have to be aware of each other nor alter theThing
itself.Instead the
MutedEffect
example will work by subscribing to its parent's communications event requests, and cancel any relevant requests that it's parent makes.Here's what it looks like right now in my branch (although it hasn't been tested yet):
I don't remember whether events of this sort existed in the mainline before I branched, but I don't think so. Basically the behaviors based approach might not work as well in the mainline yet because that was the point of the refactoring I was doing; to make everything more friendly to this approach. In that light, implement things in whatever way works well enough, and when it comes time to integrate, it's ok if a few more things have to be converted over.
[From a chat session...]
ExitBehavior has property for a list of destinations.
To use it, will find the destination that is not (here) and take you through, via the eventing.
nodnod - I see those sort of 'properties' being applied via the addition of particular Behaviors to the room Thing.
From a builder I expect the commands to be the same.
'tunnel east' or whatnot and it creates the ExitBehavior
Same as with UML.
Basically the goal as discussed before was to get rid of 'core' objects and only have Things that have various behaviors.
What this gets us is the ability to reuse more code in new ways - what was a Portal is just any old Thing that has an ExitBehavior, etc.
You could have a Thing that behaves as a Portal but also is, I dont know, edible.
So we don't have to make an EdiblePortal object, we make a Thing who has an ExitBehavior and EdibleBehavior.
And likely, the code just works well since each piece is well-contained
Sure, though that'd probably be accomplished a little different (like via a trigger behavior) but as is, it would be a donut that you could 'Enter' or 'Eat'
So anyway, I expect the UML transition to basically come down to - wherever a Room or Exit or other hard-coded type is used, will need to be behavior aware and add the behavior's parent to the appropriate part of the view tree - perhaps in two places.
The code is partially written but needs more work.
You'd add an UnderwaterBehavior.
Indeed, the easier editor approach is with properties, the cleaner codebase is with behaviors. W/behaviors the UML would probably have some set of behaviors commonly added to rooms selectable, as opposed to properties.
Sure, I could see the UML UI even being the same and the underlying rigging just changes.
Have a checkbox for underwater or whatnot, and whether it's setting a property or applying a behavior isn't necessarily relevant?
... and so on. Millions of customizable ways in which to design a room...
IMO it would be easier in the end to have the world designer aware of the currently-developed Behaviors and be able to assign them, much the way I described the OLC User Story but with a UI.
I would imagine a PeriodicallyDamageContentsBehavior or whatnot, applied to the room Thing that is.
Sure. Or if you had an UnderwaterBehavior, that logic could be tied to it.
Sure, call it an Effect. Basically the same just with a duration property IMO.
That's how I'm treating it to help consolidate in my branch.
PeriodicallyDamageContentsEffect would be given an infinite duration and save the same as a Behavior.
This all makes save/load much much simpler.
In theory, since we'll only need to know how to persist a base Thing and Behavior, which take care of their derivations.
nodnod, I will continue with the branch, make it work and we can take a look at it.
[ed. update 2021] The branch was reviewed and merged not too much longer after that. Had we already been on Git and GitHub, such actions would have involved much less pain too. :)
Beta Was this translation helpful? Give feedback.
All reactions