Howtos - chaosforgeorg/jh-mods GitHub Wiki

Most of the following assume you extracted the files. Paths below are relative to data/lua/

Challenge

The most simple - in your main.lua (or somewhere else included) register an entity with a "challenge" component - see jh/data/challenges.lua for samples. Done.

Challenges conceptually are a modified version of the standard game, so use the default world (aka the definition of levels, branches how they are generated, etc).

Trial

Similarly to challenges these can be registered outside and detected automatically. Copy one of the existing trials in jh/data/worlds and start from there. Most importantly you'll need an entity with a challenge component of type "trial" and a world registered for that trial.

Trials conceptually are the game played through a modified world, hence why a world must be defined when creating a trial. They can also modify the standard rules of the game.

Trait

Copy any trait from jh/data/trait.lua, be sure to require that file and inherit (via blueprint = "x") the trait blueprint. Adding traits to classes is a bit more difficult - you need to make a copy of the class from jh/data/class and add the new trait to the trait table. If you register the class again in a mod it will override it as with any blueprint. Unfortunately that also means that there is no way for several mods to modify the same class :( - you can however try to make a copied class and add your changes there (see below)

cpiod: you can add traits without redefining the class, for example with: table.insert(blueprints["klass_marine"].klass.traits, { "trait_assembly", max = 3, require = { ktrait_army_surplus = 1, } })

Class

Note that internally classes are called klasses. Reasons are convoluted :P. Nowadays it should be enough to register the class entity, and reuse entity = "player_marine" (or other) in the klass component - a new player_XXX entity only needs to be made if your custom class should have a different skin when without armor. For simplicity it can be also beneficial to reuse the id component - it is used only for item random generation cases.

Item

This is the simplest, just add the blueprint and a visual blueprint in gfx.lua (you need only an icon definition for non-weapon/armor). If you want a weapon or armor it would be simplest to copy or inherit an existing armor/weapon. The item can be added in any modified content you do (like to classes, enemies, levels etc) and/or added to the general loot table:

lists = {
	group    = "item",
	keywords = { "general", },
	weight   = 1000,
	dmin     = 5,
	dmed     = 10,
},

Keywords controls from what type of containers that item drops, weight how often, and dmin, dmed and dmax control how deep it can be found.

Item perks

You can add item perks to the random pool easily - just check the existing perks in perk.lua/weapon_perk.lua and be sure to fill the lists component properly for them to appear on proper found items!

Quests

Similarly to items and perks, you can easily add new "quests". See data/plot/short.lua to see how it's done. The mechanics themselves on how the "generate" table in data is interpreted can be found in core/quest.lua. If people are interested we could add a callback system for easy extension of quest.generate

Enemy

Adding enemies can be really simple or extremely complex depending on whether you want to dabble with custom graphics. In general add it like items above with the lists etc. Visuals can be copied from existing enemies. You can modifiy the textures for new enemies. As far as meshes - I'll get to this eventually, but don't expect it to be easy!

Levels

You'll need to at least create a trial to be able to visit a custom created level. Follow either the arena trial or base of haste trial and sourcedive a lot!

Have 3 or more exits from a level

Not sure just yet. According to the developer "the amount of elevators is totally a soft constraint, you just need to create your own elevator entity".

Total Conversions

You might want to look at data/lua/jh_mini as a start. If you're this ambitious, be sure to join the Discord as people will surely help you out if you're willing to invest time! (yes, including the devs :) ).

Buffs

Tips for creating status effects aka buffs:

  • Buffs added to entities will trigger ON_ATTACH.
  • Buffs have a duration when attached to an entity, and when it ends ON_DETACH is invoked.
  • Buffs attributes are deltas to be applied, not the new value you want the attribute to be.
  • Buffs attached to an entity directly don't have a duration, buffs added using add_buff() will always have a duration.

Data

Any entity can have an data object added to it (self.data = {}), and data can hold any object type. Conversely you can't add other arbitrarily named objects to an entity - only data.

To drop/place/spawn an entity in the first free space next to a coordinate use:

world:get_level():drop_coord(THE COORD)

Getting the coordinate of an entity can be done with world:get_position( entity )