CS Code

Technical documentation
02/26/2008

CS Code

CS Code is the attempt to make building Character systems easy and effective with little effort and much more fun for the coders.

Idea

Most games will have some kind of CS (Character System) as in a sheet, skills attributes or whatever means to represent what a character can or can't do.

Implementing those is usually a huge pain and takes a lot of effort. And when done propper (and there are a lot of bad char systems) often perhaps the biggest coding task within a mush, and the most complicated to integrate.

So the idea is to have the thing run in 3 layers again:

  • Config files - describing the system itself
  • Data files - describing attributes, skills, or whatever with fixed characteristics.
  • A language - to easiely querie those and run tests and dice rolls.

Example

Okay I thought about some ideas, taking the D&D rules (or open D20 I think for that matter) as a exmaple. Mind you I'm not a expert on D20 this is what I remember so.

Attribute

define :attribute do
  identify_by :name                              # A attribute is identified by it's name
  characteristic :name, :string                  # This is same for all skills of a type
  custom_characteristic :level, :integer         # This is special for one sheet
  belongs_to :sheet                              # This one needs a sheet

  calculate :level do
    l = level + sheet.race.attribute_modifyer(name)

    #Calculate in feat modificators
    sheet.feets.select{|f| f.mods[:attribute][name]}.each do |feat|
          mod = feat.mods[:attribute][name]
            if mod.is_a? block
                l = feat.mods[:attribute][name].call(sheet, self, f)
            else
                l += feat.mods[:attribute][name]
            end
    end

    l
  end

  calculate :modifier do
    (level - 10) / 2
  end
end

Skills

define :skill do
  identify_by :name                              # A attribute is identified by it's name
  characteristic :name, :string                  # This is same for all skills of a type
  characteristic :attribute, :string             # This is same for all skills of a type
  custom_characteristic :level, :integer         # This is special for one sheet
  custom_characteristic :specialisation, :string # This is special for one sheet
  belongs_to :sheet                              # This one needs a sheet

  calculate :level do
    level + sheet.attribute[skill.attribute].modifier

    #Calculate in feat modificators
    sheet.feets.select{|f| f.mods[:skill][name]}.each do |feat|
          mod = feat.mods[:skill][name]
            if mod.is_a? block
                l = feat.mods[:skill][name].call(sheet, self, f)
            else
                l += feat.mods[:skill][name]
            end
    end

    l
  end
end

Magic Spells

Spells for mages

define :magic_spell do
  usable
  identify_by :name
  characteristic :name, :string                  # This is same for all skills of a type
  characteristic :attribute, :string             # This is same for all skills of a type
  characteristic :category, :string              # This is same for all skills of a type
  characteristic :level, :integer                # This is same for all skills of a type
  grouping :category, :level                     # Spells are supposed to be grouped by category and level

  requires do |sheet, spell|                     # The spells require the class to be magic
    sheet.class.can_use(spell)
  end
end

Cleric Spells

Spells for clerics

define :cleric_spell do
  usable
  identify_by :name
  characteristic :name, :string                  # This is same for all skills of a type
  characteristic :attribute, :string             # This is same for all skills of a type
  characteristic :category, :string              # This is same for all skills of a type
  characteristic :level, :integer                # This is same for all skills of a type
  grouping :category, :level                     # Spells are supposed to be grouped by category and level

  requires do |sheet, spell|                     # The spells require the class to be magic
    sheet.class.can_use(spell)
  end
end

Races

Races for the characers.

define :race do
  identify_by :name
    characteristic :name, :string
    characteristic :size, [:small, :medium, :large]# There are 3 possibilites for sizes
    characteristic :speed, :fixnum
    belongs_to :sheet                              # This one needs a sheet

    acction :levelup do end                        # Executed when levelup is done

    on_choose do end                               # Called when choosen as race
end

Class

Class for the characers.

define :class do
  identify_by :name
    characteristic :name, :string
    custom_characteristic :level, :integer         # This is special for one sheet
    characteristuc :feats, :array                  # Feets allowed for the class.
    characteristuc :skills, :array                 # Skills allowed for the class.
    belongs_to :sheet                              # This one needs a sheet

    acction :levelup do end                        # Executed when levelup is done

    on_choose do end                               # Called when choosen as race
end

Sheet

Here it comes all together.

sheet do
  identify_by :id                                # We identify a sheet by it's id.
  characteristic :level, :id                     # The sheet has a level
  characteristic :level, :fixnum                 # The sheet has a level
                                                 # Every sheet has ...
  primary :race, :one                            #  - one race.
  primary :class, :one                           #  - one class.
  primary :attribute, :all                       #  - all atributes.
  secondary :skill, :many                        #  - many skills.
  secondary :feat, :many                         #  - many feats.

  optional :magic_spell, :many do                #  - might have many magic spells.
    min 0                                        #    - we can not have 
    max do |sheet,spell|                         #    - what is the maximum
      (((((sheet.attributes[spell.attribute]-10)/2.0).floor) - (spell.level - 1))/4.0).ceil
    end
    # results in #sheet.magic_spells[<level>] -> [<array of spells>]
  end

  optional :cleric_spell, :many do               #  - might have many magic spells.
    min 0
    max do |sheet,spell|                         #    - what is the maximum
      (((((sheet.attributes[spell.attribute]-10)/2.0).floor) - (spell.level - 1))/4.0).ceil
    end
    # results in #sheet.cleric_spell[<level>] -> [<array of spells>]
  end

end

Files