Category Archives: Game Design

Weekly Recap #18

We’re edging closer and closer to the next release and finally beta phase 3! At our current pace it’ll be about two weeks depending on how demanding the bug load is and how much more work multiplayer support is going to be. Multiplayer is so close to working but needs another push.

This entire week was devoted to adding new skills. Kelley and I have made some great progress  and only a few remain. One thing to note is that these new skills are not merely an extension of the existing skills. Much more has been going on!

Cleaned up Talent UI

Cleaned up Talent UI

First of all, we gave all skills an unlock level. Once your talent reaches the skill’s unlock level then that skill becomes available to level up. The primary motivation behind this is to limit the number of options the player has to choose from. I believe it was a little too overwhelming for a player to have to choose between all of the skills up front. Not to mention this was for 4 different talents totaling nearly 40 skills. Now each talent starts with 3-4 skills unlocked at level 1 and more unlock at levels 5, 10 and 15.

There was another major change to the talents. The existing “Magic” talent was split it into two – “Arcane” and “Divine”. Arcane magic focuses on elemental offensive magic and Divine magic focuses on support magic.

Arcane talent has a total of 16 skills at the moment. There are 4 different types of magics and 4 elemental types of each. The spell types are: projectile, enchant melee weapon to do elemental damage, area of effect around the player, and pillar magic. I decided it would be easiest to treat all elemental types equally and that is why each element has a similar magic type.

Casting Freeze

Casting Freeze

Divine talent has 12 skills which consist of healing, positive status effects and a few passives. Just because they are support doesn’t mean there are not game changers! Stoneskin will absorb some damage, making it possible to take harder hits or fall further. Invisible makes you invisible and monsters wont aggro you. Fun stuff!

Casting Invisible

Casting Invisible

The Arms talent has also received many new active skills to keep up with the magics. However, Gather and Craft talents are more or less the same. For now, I’m happy with where they are at.

As you can see, lots of good stuff! This next week I’m wrapping up the remaining skills and moving back onto working on the underground. I’ll also start looking into some bugs that are in 0.6.0 and beginning to prep things for v0.6.1. Most likely, there will also be a v0.6.2 to fix issues in v0.6.1. Then I plan to launch Crea’s greenlight page and the next beta phase.

Rolling over some very low level monsters with Firestorm

Rolling over some very low level monsters with Firestorm

Feature – Crafting and Research

Overview

There was never any question that Crea would have a crafting system and from day one I knew what I wanted out of it. The goal was to make discovery a key component and not have players be dependent on a wiki. Since then it has been a matter of how will it work. For a long time I thought I knew exactly how it would; however, after implementing it and facing several design issues I decided to step back and redesign.

Before being able to craft an item you must first learn what materials are needed. This can be done two ways. The simpler but less common way is to acquire a recipe/schematic that reveals all materials needed to craft the item. These recipes will be rare and only found as dungeon or boss loot. The usual route to learning an item’s recipe is through researching.

As we have always planned, researching is done through the Researcher NPC. When you talk to the Researcher you are presented with the simple research dialog.

There is one item slot where you can drop a material in and click “Research”. By doing so you research the capabilities of that material. This is not free though and does consume one of the material. The result is that a single recipe is revealed. However, if the recipe has multiple materials then all must be researched before the entire recipe is available.

The “Materials” button opens a window that shows the progress of each material so you know when you’ve fully researched a material.

Once a item recipe is available you can easily craft it by opening your craft window, selecting the item and clicking “Craft”.

crea_crafting

Modding

Both the crafting and researching systems are fully implemented in Python and consequently are completely moddable. Since these systems are hundreds of lines long I’ll forgo including them in this post, but they can easily be found and edited with the game. However, the majority of modding regarding these system will be done with creating item recipes.

An item recipe is always defined with the item and can be as simple as the following:

craft = Craft(category='Armor', subcategory='Chest', level=4, experience=30, service='Anvil')
craft.material('mods/base/item/recipes/smelting/copper_ingot.ce', 6)
add(craft)

Recipes can be much more involved with several additional attributes.

craft = Craft(category='Basics', subcategory='Essentials', level=1, experience=15)
# Any number of materials can be listed.
# craft.material('path/to/content.ce, quantity)
craft.material('mods/base/item/materials/wood.ce', 1)
# Recipes can have multiple results based on the quality of the craft.
# result(quantity, quality) - This is a short hand.
# Here the player will receive 4 of this item always since quality is always 0+.
craft.result(4, 0)
# and here the player receives one additional quantity if quality is 50+.
craft.result(5, 50)
# Results can also be created long hand.
# By doing this it is possible to expand on the yielded items and their quantity.
# This result occurs at quality of 100+ and will yield 5 lumber and even another item!
result = CraftResult()
result.quality = 100
result.items.append(InventoryItem("mods/base/item/basics/essential/lumber.ce", 5))
result.items.append(InventoryItem("mods/base/item/basics/essential/super_lumber.ce", 1))
craft.results.append(result)
# Sets if a recipe can be learned through research. Defaults to True.
craft.isResearchable = False
add(craft)

Realms

waycrystal

Because Crea’s biomes are randomly generated, they are always totally new worlds for players to explore. However, after playing in one world for awhile it starts to become too familiar. While it it’s wonderful to start from scratch and create a totally new world every once in awhile, sometimes players just want another dungeon to delve into. To remedy this, Crea will have what we are calling realms.

A realm is an entirely new area to explore separate from the main world but still accessible by special means. New realms can become available through exploration, unlocked by completing a quest, killing a boss, or any other means imaginable. Traveling between the world and realms is done through the use of Way Crystals; large crystals that mysteriously allow teleportation.

waycrystal

In Crea, certain rules apply to worlds, such that as players can build anywhere or that the world size is always very large. Realms, however, don’t have to stick to these rules. One realm could be as small as a single room. Maybe another realm doesn’t allow construction. By breaking the rules, realms enable the creation of areas and scenarios that were impossible before.

My favorite aspect to realms is that since they are loosely connected to the world they can be added and updated alongside existing worlds. For example, you could install a mod and through a quest gain access to an entirely new dungeon. Later you could get an update for this mod that builds additional content onto the dungeon. So realms can be continually evolving without interfering with the main world.

We plan to fully take full advantage of realms. Dungeons are a perfect fit. Some dungeons will be at a set level, while others grow in levels with your character so they will always provide a challenge. Most dungeons will be procedurally generated but some could be hand-crafted. All of the dungeons will be updated alongside existing worlds.

Dungeons are not the only use case though. We are considering some boss fights to be in special realms or perhaps at the end of a dungeon. We are also thinking other special areas could find themselves in realms. Casino?

Realms are currently planned for Beta Phase 3.

NPCs in Crea

 

lineup1In Crea, there will be several NPCs with whom to interact. This week Kelley started working on some of the NPC art. Above we have the Researcher, Nun, Grafter, Merchant and Cartographer. Here is a brief description of each NPC. Much more information will be posted about each one individually in the future. (Note: NPCs will be introduced in Beta.)

  • The Researcher helps with crafting. Supply him with materials and he will return the favor by providing you with new item recipes.
  • The Nun heals HP and grants buffs.
  • The Grafter enhances your equipment through the use of catalysts and essences.
  • The Merchant sells items.
  • The Cartographer provides you with a map and upgrades for it.

lineup2

The Quest For Dual Wielding

We have wanted some form of dual wielding since the inception of Crea. The motivation behind this was simple. First and foremost, we wanted the player to be able to use multiple items without changing their active item on the toolbar. We also wanted the toolbar to provide access to more items. We knew what we wanted but how do we get there?

When I think dual wielding I think left click for one item and right click for the other. I think this is how most games do it. There are games that have single click to use both weapons but we need to provide means to individually use the items. This creates some new questions though. Item interaction was right click but what is it now? How do we display which items are assigned to the toolbar?

We considered splitting the toolbar and having 1-5 be for left click and 6-0 be left click. Something else we tried was having items on the toolbar be left or right click. We tried having 20 items on the toolbar. There are many other paths we fumbled down. We commonly ran into two problems. The first was adding dual wielding with only 10 items on the toolbar seemed to add more complexity than it was worth. The other problem was if we wanted 20 items, two items per number, then how do we display the items efficiently? Every way we tried left at least one of us unsatisfied.

We ventured down several paths but none of them felt right. For awhile we even dropped dual wielding, but since we really wanted it we picked it back up. I had pigeonholed myself into thinking we needed dual wielding to happen with both left and right click. I stepped back from that and quickly stumbled upon a working solution.

toolbar

Current toolbar showing what both the primary and secondary looks like.

Instead of having a single toolbar the player has two toolbar, which we call the “primary” and “secondary”. The primary toolbar is active by default and to get access to the secondary toolbar simply hold down the shift key. There are 10 items on each toolbar with each item assigned to a number key. There is only one number slot active at a time. There is also only one active toolbar at a time. Since only one toolbar is active at a time the solution to our display problem was obvious. We would only display one toolbar at a time. Left click always uses the active item on the active toolbar.

Time for an example! Lets say “3″ is your active item on the primary toolbar. Left click and you use this item. Hold down shift key and now you see your active secondary toolbar. Left click again and you will use the “3″ item on your secondary toolbar.

It took awhile to get there but it was a worthwhile journey. The controls feel right and I think are intuitive. I am looking forward to getting some feedback about this feature from the testers.

Feature – Character Progression

Overview

Close to the start of the Kickstarter, I wrote a post on character progression. This was a great thumbnail sketch of what character progression will look like. I have taken the time to flesh things out and clean some things up that I found troublesome with the initial sketch. Now character progression can be broken into two distinct parts – character level and talents.

The character level is strictly used for combat related things. It is used to represent your character’s strength and consequently is utilized in various combat algorithms such as the damage algorithm or for determining the monster levels. Upon leveling your character will gain stats. Also equipment will typically have a character level requirement.

Characters have talents that represent the character’s proficiency in a field. Currently we have four talents planned; Arms, Magic, Gather, and Craft. By performing actions related to the talent your character will occasionally gain TP (Talent Points). For example by crafting items or learning new recipes you may gain TP for your Craft talent or hitting a monster with magic may yield TP for the Magic talent.

After accumulating enough TP your character’s talent will level up. With enough TP you can spend it on purchasing and upgrading skills. Leveling up a talent grants access to new skills and skill upgrades. There will be a mixture of active and passive skills. Active skills are skills that can be added to the toolbar and used as an action such as a magic spell. Passive skills are always affecting the player such as “Defense Up”.

Early version of Talent window

Modding

As usual, nearly all aspects of talents can be modified ranging from modifying an existing skill to creating an entirely new talent. Talents are tied to body types (covered in this post) meaning different races can have different talents.

As far as the actual modding goes, here is what the adding the talents to a character body looks like.

body.talents = Talents()
body.talents.talents.append(armsTalent)
body.talents.talents.append(craftTalent)
body.talents.talents.append(gatherTalent)
body.talents.talents.append(magicTalent)

A Talent is simple and is only composed of a name, a “points to next level” list, and a list of skills.

armsTalent = Talent("arms", [100] * 20)

Skills are a little bit more complex. First of all, skills can passive and/or active. A passive skill is always in effect while an active skill must be used. It is possible to have a skill with both elements. Passive skills need to provide two callback functions – “enable” and “disable”.  Active skills need to provide the callback function “use”. All skills should provide a “description” callback function.

def enableStatUp(stat, level, user):
    user.stats.get(stat).adjust(5 * level)

def disableStatUp(stat, level, user):
    user.stats.get(stat).adjust(-5 * level)

def descriptionStatUp(stat, level):
    return "Increases a character's {} by {}.".format(stat, 5 * level)

atkSkill = Skill(name="Attack Up", icon="mods/base/talent/arms/attack_up.png", costs=[100] * 5)
atkSkill.enable = partial("ATK", enableStatUp)
atkSkill.disable = partial("ATK", disableStatUp)
atkSkill.description = partial(descriptionStatUp, "Attack")
armsTalent.skills.append(atkSkill)

defSkill = Skill(name="Defense Up", icon="mods/base/talent/arms/defense_up.png", costs=[100] * 5)
defSkill.enable = partial("DEF", enableStatUp)
defSkill.disable = partial("DEF", disableStatUp)
defSkill.description = partial(descriptionStatUp, "Defense")
armsTalent.skills.append(defSkill)

The “enable” function is called when the skill is activated. This is when the player first get the skill or when the character is loaded. The sibling function, “disable” is used when the skill needs to be deactivated. This is typically when the character is being saved to disk but it also makes it possible to temporarily disable passive skills with monster abilities. The “description” function is called when we need to display the tooltip for the skill. Having it be a function makes it dynamic so it can be dependent on any variable – such as the level of the skill. The “use” function is not featured here but it is more or less the same as the previous functions. It is called when the skill is being used.

Creating skills and entirely new Talents is definitely some more advanced modding. However, with the complexity comes some awesome power and I am anxious to see what skills players come up with.

Feature – Dynamic Music

Charlie (Robot Science) and me (Jasson) working on Dynamuse

Overview

The music in Crea will be dynamically generated. This means you will never hear the exact same track twice. The music is broken down into small sound clips that I am calling “samples”. These samples are played dynamically based off of some parameters such as how much danger you’re in, time of day, and how long the track has been playing.

The thing that turned me onto doing dynamic music was watching Renaud Bédard’s GDC talk Cubes All The Way Down. I had not heard too much about dynamic music in games, but I knew that it would be a perfect fit for a sandbox game. It is so easy to get sucked in for hours and before too long the music becomes very very very repetitive. What do we do when this happens? Mute! I know that’s what I do and it is a shame since video game music is so great. My hopes are that by making the music dynamic it doesn’t get repetitive enough to warrant mutiny…

As I have mentioned before, I made a tool for Charlie that I dubbed “Dynamuse”. Dynamuse is used to define the rules for when samples should play in a track. I will admit that Dynamuse is a little on the complicated side but with that comes much power. I recently got Dynamuse more or less completed and soon we will be hearing its true power.

Version 2 of Dynamuse

Modding

Because I’m all about modding and being open, I’m going to make Dynamuse available to everyone. That means that anyone who wants to can modify existing tracks or even create their own. Eventually I will make a tutorial on how to use Dynamuse, but for now here’s a brief overview of how it works.

A Dynamuse track is composed of any number of samples. A sample has a name and music file associated with it and it also contains a list of triggers. A trigger contains a few things but most importantly it contains a list of conditions. There are several types of conditions such as time of day, status of another sample (playing, paused, or stopped). If a trigger has all of its conditions met then it signals the sample to play. And that is about it. Simple, right? (not quite unless you’re a programmer)

Feature – Inventory and Toolbar

Overview

The player’s inventory in Crea is handled through bags. A bag is an item which, when equipped, provides additional inventory for the player. Once equipped, a bag can only be unequipped if it is empty. The number of bags a player can equip is increased by leveling up in the gathering proficiency. Bags can also be upgraded to hold more items. Since a bag is an item that means it can be traded to other players or given to new characters.

Bags are for storing items and the toolbar is for using items. The toolbar is only a reference to an item type. Consequently, a dirt block on your toolbar would represent all of the dirt in your bags. When an item is completely consumed the item remains on the toolbar unavailable until you get more.

Modding

There are two components specifically for these, InventoryComponent and ToolbarComponent. The InventoryComponent allows you to get access to all of the bags the player currently has equipped as well as check and change the items in each bag. Similarly with the ToolbarComponent you can check and change the item references in each spot.

Links

Feature – Interactive World

Overview:

As expected in a sandbox game, worlds in Crea can be fully reconstructed. Terrain exists on two tile layers referred to as ground layer and wall layer. The ground is collidable and sits in front of the wall layer which is not collidable. Aside from being able to rebuild the terrain, it is also possible to place and remove entities such as tables and treasure chests.

Unlike tiles which are grid based, entities are free to be placed wherever there is provided support. Item placement has been made as simple and intuitive as possible. When a position is suitable for placing the active item a visual hint is provided, that is a transparent rendering of the item and where it will be placed at. If an item does not quite fit where the mouse is hovered but there is an available nearby space then it will show a hint there.

These items can then be interacted with, such as opening a door or flipping a switch. Interacting with an item is not restricted to right clicking on it though. There are other interactions such as harvesting it with an axe, stepping on a button, using an item or attempting to remove the item’s support. With all of these interactions, the world moves from a static playground to a very much interactive and alive one.

Modding:

The key to having an interactive world is the modding support. New tiles can be created, there is a placement component that can be added to any item, and an interactive component added to any entity.

Creating a new tile requires the use of the TileComponent. Here is an example with some embedded comments.

name = 'Dirt'
render = Render('mods/base/tile/dirt.png')
add(render)

#ItemComponent making it possible to collect this tile
item = Item()
item.stack = 999
item.delay = 50
add(item)

#TileComponent
tile = Tile()
#Number of tile variants
tile.variants = 3
#Tile priority used for tile overlapping
tile.priority = 10
#Amount of life the tile has.
tile.durability = 10
#Defines the groups the tile belongs to.
#This is used for tool compatability among other things.
tile.groups = ['soil']
#The layer this tile is placed on - either 'ground' or 'wall'.
tile.layer = "ground"
add(tile)

#This sets up the frames for the tile to make it easy to draw
render.data = standardTile(tile.variants, tile.priority)

As mentioned above, there is a placement component which makes very easy to make items placeable. A item PlacementComponent is composed off a list of possible axes that the item can be placed on.

placement = Placement()
floorAxis = PlacementAxis(AxisType.AXIS_FLOOR, Vector(5, 37))
floorAxis.addSupport(PlacementSupport(SupportType.SUPPORT_TOP, Vector(5, 37)))
placement.addAxis(floorAxis)
add(placement)

The item can be placed on any axis but only one at a time. The types are floor, ceiling, left, right, backwall and wall. The ‘backwall’ is support from the wall layer and ‘wall’ is the combination of left and right. In addition to the axis type, each axis has a range, an area, and a list of supports.

The range of an axis defines where and how much support is needed to place the item down. This is the second parameter for PlacementAxis. Here we have Vector(5, 37), which means to start at pixel 5 on the bottom of the image (since it is floor axis) and go for 37 pixels. This will default to starting at 0 and using the entire axis length (width or height of image). The reason for this feature is to enable items to have a skinny base and only require support for the base and not the entire width of the item, such as a candelabra.

Area for an axis is the game’s physical representation of the item relative to upper left corner of the image. This area is used to reserve space for items in the world. This area defaults to the size of the image.

The last part of an axis is the list of support it can provide. It is defined very similarly to an axis with a support type and a range of where and how much support to provide. The type can be on any one of the four sides; top, bottom, left or right.

Moving onto InteractableComponent, which is much simpler. An InteractableComponent contains a list of interactions and a callable object. Here is an example of the door InteractableComponent.

def interactDoor(args):
    #Toggle between being open and closed
    #We can check which animation is currently being played to know the state
    door = args["entity"]
    if door.animation.isPlaying("closed"):
        door.animation.play("open")
        door.physics.setActive(False)
    else:
        door.animation.play("closed")
        door.physics.setActive(True)

interactable = Interactable()
interactable.add("interact", interactDoor)
add(interactable)

The second to last line adds an interaction, the “interact” which is called when right clicking on an item. As mentioned in the overview there are several interactions built into the engine. Because the interaction is simply a string, it is entirely possible to create new interactions.

Links:

Feature – Equipment

Overview

All equipment in Crea is randomly generated to some degree. Each piece of equipment is made up of attributes. These attributes can be either positive or negative effects such as stat increase/decrease, increased health regeneration, or vampiric hit. The human race has a large assortment of equipment slots: Head, Body, Hands, Legs, Feet, Ring, and Neck. All but the last two will change your character’s appearance.

The majority of equipment found in Crea will have some constant attributes as well as some random ones. Such as all Copper Greaves will always have a DEF +5 attribute and will randomly be assigned 0-2 of the following attributes: ATK +(1 to 2), MDEF +(2 to 4), and AGI +1. (This is just an example).

Modding

All aspects of equipment are completely moddable. Not only can you create new pieces of equipment, it is very possible to create entirely new attributes and even add new equipment slots.

Creating a new piece of equipment is reasonably simple. In addition to creating a normal item entity (Render, Item, Craft components), add an equipment component to an item. An Equipment component has a list of image substitutions and a function (onCreate) called when a new piece of that equipment is created. Inside of the onCreate function is where attributes are added to the equipment component.

equipment = Equipment('chest')
#These are image substitutions similar to what is discussed in Character Customization
equipment.addSub('customizations/shirt_front.png', 'mods/base/item/armor/chest/silver_breastplate/torso.png', Vectorf(2, 0))
equipment.addSub('customizations/sleeve_lower_0.png', 'mods/base/item/armor/chest/silver_breastplate/arm_lower_0.png')
equipment.addSub('customizations/sleeve_upper_0.png', 'mods/base/item/armor/chest/silver_breastplate/arm_upper_0.png')
#... and more substitutions

def createSilverChestplate(component):
    component.addAttribute(ChangeStatAttribute('HP', 5))
    component.addAttribute(ChangeStatAttribute('Attack', 3))

equipment.onCreate = createSilverChestplate
add(equipment)

Creating a new type of attribute involves a new python class that implements an interface. Here is an example with a brief description is provided with each method.

class ChangeStatAttribute(object):
    name = "ChangeStat"
    def __init__(self, stat='', value=0):
        self.stat = stat
        self.value = value
        self.changed = 0

    def alignment(self):
        #Called to determine if this is a positive or negative attribute
        return self.value >= 0

    def quality(self):
        #Reports the quality of this attribute. The quality of an equipment piece is the sum of its attributes.
        return self.value * statWeights[self.stat]

    def onEquip(self, args):
        #Called when this attribute is being equipped
        player = args['player']
        stat = player.stats.get(self.stat)
        if stat.hasMax():
            self.changed = stat.adjustMax(self.value)
        else:
            self.changed = stat.adjust(self.value)

    def onUnequip(self, args):
        #Called when this attribute is being unequipped
        player = args['player']
        stat = player.stats.get(self.stat)
        if stat.hasMax():
            stat.adjustMax(-self.changed)
        else:
            stat.adjust(-self.changed)
        self.changed = 0

    def save(self, stream):
        stream.saveString(self.stat)
        stream.saveInt32(self.value)
        stream.saveInt32(self.changed)

    def load(self, stream):
        self.stat = stream.loadString()
        self.value = stream.loadInt32()
        self.changed = stream.loadInt32()

When creating a new piece of equipment you must specify which equipment slot the new item is compatible with. In order to create a new equipment slot it only requires adding the slot to the character body script (see Character Customization). After this is done any new equipment can use the new equipment slot.

#Define which gear slots this body supports
#These show up in the character equipment UI in game
body.gear = Gear()
body.gear.slots.append(GearSlot("head", "mods/base/body/hm/gear/head.png"))
body.gear.slots.append(GearSlot("chest", "mods/base/body/hm/gear/chest.png"))
body.gear.slots.append(GearSlot("hand", "mods/base/body/hm/gear/hand.png"))
body.gear.slots.append(GearSlot("leg", "mods/base/body/hm/gear/leg.png"))
body.gear.slots.append(GearSlot("feet", "mods/base/body/hm/gear/feet.png"))

Links