Planet Mud-Dev

May 16, 2012

thecodelizard

Crafty Crafts

I've been busy with school and other projects, but I got the strange and sudden urge to implement crafting. It's not done yet but I have changed my plans a bit from last time...



First off, here are some things I apparently implemented and then completely forgot about:


  • Furniture! Items previously could be marked as having the FURNITURE type, but it did nothing. Now, you can sit on, stand on, rest on, and sleep on any item of the FURNITURE type.

  • The GET no longer shuffles items around in a room if you can't pick up the target item for some reason. It now also prevents you from picking up any furniture someone is on top of.

  • You stop following people when you quit the game now. You cannot quit the game while in a fight, and you stand up (and get off of any furniture) when you quit, so that people can't steal the table you were sleeping on and then you suddenly log in to the game and find yourself standing on null. Finally, any forced room change (teleports, following, etc) gets you out of the furniture you were on.

  • The unused and obsolete Subtypes of items have been removed. The original plan was to give food and drink items subtypes (meat, eggs, vegetable, etc) so that they could have different effects when eaten; but now that an Item's USE program handles everything that happens when you eat, and its longdesc can describe what type of food it is, the fields no longer do anything, so they were removed. This also substantially neatened up the reflective editing code that had an exception in place specifically for Item subtypes, which was ugly and now no longer exists.

  • A few error messages here and there have been made more informative.

  • Items now have an 'owner' field, currently unused. For corpses, it will dictate who owns the corpse and can loot it. (Player corpse looting mechanics will be worked out on another day.) For any craftable item, it designates who made it. This will separate stacks of items - mostly for posterity, but crafted items can be better or worse than store-bought ones, because...

  • Items now have an 'effectiveness' field. For generated, dropped, or store-bought items, these will be predetermined by the admin when they are created. When crafted, however, the player's crafting skill will determine the effectiveness. A good crafter makes better potions of healing; a poor crafter makes worse ones. The idea is that the programs for that Item will make use of the Effectiveness of the item in their calculation. A really simple example is that food restores satiation equal to the Item's effectiveness score; better effectiveness (resulting from a better Cooking skill) makes better, more satisfying food.

  • Skills have been partially implemented; more on this below.

  • You only receive time messages if you are outdoors and awake.



Skills, first. I covered the idea of implementing them here, but I managed to find something pretty damn awesome I could do with enums.

If you can't tell already, I love Java enums. They have all the usefulness of a regular enum (providing a mutually exclusive set of values) with type-checking (so you can be 100% sure it is either null or a valid enum constant), and they're objects, so you can give them fields and methods.

...

They can also implement interfaces.

...

These interfaces can also be implemented per enum constant.

  SCRIBING(1, LITERACY) {
    public int evaluate(Mobile actor) {
      //Scribing Effectiveness = Level*3 + Int
      return actor.getLevel() * 3 + actor.getStatistic(Statistic.INT);
    }
  }


So basically, each enum constant in the Skill enum has to implement the Evaluable interface, which specifies the evaluate method. It takes the Mobile making the check, and returns the Effectiveness score based on whatever formula you want to write in that method.

That's right, you don't have to be limited to just saying what stats are used. You can write any formula expressable in Java into the enum constant's implementation of evaluate. Want the level to count for more than Wisdom, as in the above example? Easy. Want to use three different stats? Sure. Want to add a random factor in? You can do that. Want to cap the Effectiveness score at a certain value? Just use Math.min. Want to use a totally crazy formula involving square roots and logarithms? You can do that too.

I also set it up so that you can set it up to have each skill have a different skill point cost to learn it. It defaults in stock Smerg to 1 point per skill, but you can change it by changing the "1" in the enum constructor, as shown above.

And you can have prerequisites, too. Just list as many as you like (even zero), which is what the "LITERACY" is in the above example - you have to be literate to know how to scribe scrolls.

The only thing I don't have at the moment is a distinction between different skill point types. Only because I didn't think of it until now. I'd just have to make an enum of the different types (physical skills, spells, crafting skills, psionic skills, divine skills or the obligatory silly example of Drunken Master1 skills), and then have the Skill enum constants specify which one is needed to purchase that skill.

1: Boozeror? Ethanologist? Alcomancer? Manaholic? Vodchemist? Barlord? Winezard?

Ultimately I also need to implement the listing of skills for each character as they are unlocked. Presumably this will involve lists in the code per class and race (and a global list) of skills and the levels they are unlocked at. These lists will merge to give the list of all the skills the character gets, and the first level they can buy them at, with the earliest level winning in the event of the same skill in multiple lists.

This will probably be another per-enum-constant interface implementation where a Map is set up between skills and the levels they are unlocked at. These Maps can then be merged when character creation is finalized.

It may also be possible to buy a skill with different point types... perhaps Lizardfolk can buy Swimming with a racial skill point, everyone else uses a physical skill point. In this case, it would have to be specified in the skill listing which one is used ("Level 1 Lizardfolk can buy Swimming with a Racial Point"). I'm not entirely decided on whether this is a good feature, or too much customization - anyone not using it would have to specify in every single entry the same point type over and over.

Earning points would probably be specified by class/race/global skill progression lists. I'll have to figure that one out later, but it'll probably be more per-enum-constant interface method implementations. (It seems like a pretty awesome technique with endless applications)




Oh, right, I was supposed to talk about crafting at some point. Okay, so. I've only partly implemented the Recipe class at this point, so most of this is subject to change if I think of something better.

Areas will contain a list of Recipes. This allows for Recipes to be added and edited in-game by an admin. This also means that importing a third-party area into Smerg will carry the recipes along with it (presumably referencing items in that area). As usual, they are specified by an area internal name, and an ID number.

The Recipes themselves are also made up of:


  • A name. Players never see this. It's for admins to use when creating a recipe to help identify it when they list off all the recipes in an area. It could be as simple as the name of the result ("Healing Potion") or something longer ("Step 2 of Ultimate Cake Slicer").

  • The crafting skill used for the recipe (Cooking, Scribing, Brewing, Fletchery, etc). The player's Effectiveness with this skill determines the quality of the final result.

  • A list of Skills, if any, required to follow the recipe. Unlike the crafting skill, the Effectiveness of these is irrelevant; the player merely has to have them. So you can't scribe an Teleport scroll without knowing the Teleport spell.

  • Three lists of ingredients, at most two of which may be empty:


    • Consumed Ingredients: These are always destroyed, regardless of the success/failure of the player when they attempt the recipe.

    • Required Ingredients: These are only destroyed if the recipe is a success.

    • Required Tools: Players need these in their inventory to follow the recipe, but they are never consumed by it.


  • Two lists of results:


    • Success Results: Item(s) given to the player when they successfully follow the recipe.

    • Failure Results: Item(s), if any, given to the player when they botch the recipe.


  • The Effectiveness of the crafting skill required for the player to successfully follow the recipe.



The crafting procedure will basically work like this:


  1. Does the player have all the ingredients they are trying to use?

  2. If so, do they have the required crafting skill and other necessary skills?

  3. If so, calculate their effectiveness with the crafting skill.

  4. If it exceeds the required effectiveness, the recipe is a success; consumable and required ingredients are destroyed and the success items are put in the player's inventory.

  5. If not, it is a failure; consumable ingredients are destroyed, and failure items are put in the player's inventory.



If they lack ingredients, nothing happens. If they attempt a recipe that does not exist, some items may be destroyed, and this is based entirely on the crafting type and the item type of the item. For example, Cooking will always destroy any Food items if a nonexistant recipe is attempted; all other items the player attempts to cook will be left intact. Smelting will destroy any ores or ingots the player attempts to smelt if they don't provide the right kinds, but tools are left alone. Trying to Combine items mundanely will never destroy the items used if no recipe is found. Obviously, this is all specified in the code and can be changed easily by the MUD owner.

The player will craft by typing in the crafting method and then the ingredients they will use, including required ingredients and tools. Duplicate ingredients will be specified twice ("pasta pasta sauce cheese"), but the order of ingredients is not important.

For example, let's say that brewing a healing potion requires a silverdew herb (consumed), a flask (required ingredient to put the finished potion in), and an alchemy set (never consumed). The player types in "brew silverdew flask alchemy" (referring to the keywords of the items in question, of course), and assuming they have all these items, their Effectiveness with the Brew skill is checked. Let's say that it requires an effectiveness of 30, and they have 42. The silverdew herb is consumed, the flask is consumed because the recipe was a success, and the alchemy set remains untouched in their inventory. A Potion of Healing Juice is added to the player's inventory with an effectiveness of 42, and when they drink it, it restores, say, (E/6)d(E/4)+(E/10) HP. The default of 30 would give 5d7+3, but the player's improved effectiveness of 42 gives 7d10+4!

If they only had an Effectiveness of 20, the recipe would fail. The silverdew herb is destroyed, but the flask is not, since it was not used since the recipe was a failure. The alchemy set is also untouched. The player also gets a pile of ashes added to their inventory.

The power of this system is practically limited only by imagination. You can have multi-step recipes by having crafting recipes use the results of previous recipes. You can have better potions require a higher Effectiveness score, so that level 1 clerics can't brew up Potions of Instant Healing IX. You can be sneaky and have crafting recipes that require the Piles of Ash, Potions of Nastiness, and Scrolls of Cascade Resonance that some failed recipes create. You can mix crafting types, so you may need Herbalism to make a potion ingredient, but Alchemy to make it into a really awesome potion. You can require people to have the Fireball spell before they mix a Potion of Fireball (delicious!). You can have puzzles that require you to Combine items, as Combine will (in stock Smerg) be available to all players as soon as they are created. You can have the required effectiveness on some recipes be 0, but set it up so that really low-effectiveness potions heal almost nothing. And more!

May 16, 2012 11:03 PM

May 15, 2012

Drakkos

Computer Games Journal

My apologies for the lack of posting, for all of you who care - busy busy busy. However, to tide you over, can I recommend you check out http://www.computergamesjournal.com/ - volume one, edition one, where you will find my paper 'Inaccessible through oversight: the need for inclusive game design' has just been published.

It's not hugely relevant to MUDs (although they do get a shout-out), but I have a second paper undergoing peer review for the same journal - if that one is accepted, you will find it absolutely dripping with text based goodness.

I hope to resume a normal blogging schedule from next week onwards.

Regards,

Drakkos...

Click on the link for the rest of this post.

by Drakkos at May 15, 2012 10:57 AM