An entity and spell system c++ godot engine module, for complex (optionally multiplayer) RPGs.

Entity Spell System

An entity and spell system for the GODOT Engine, that is usable for both 2d, and 3d games. The main purpose of this module is to handle spells, auras, and most entity-related things like spawning, items, inventory, containers, vendors, interaction, targeting, equipment (+ visuals), loot, crafting, talents, pets, npcs, etc ...

The module supports networking. It is designed to be authoritative, so players shouldn't be able to cheat by design.

It is a c++ engine module, which means you will need to compile it into godot. (See compiling)

It supports both godot 3.2 and 4.0 (master last tested commit). Note that since 4.0 is still in very early stages I only check whether it works from time to time.

Project setup tl;dr

First

You need to create an ESSResourceDB resource somewhere in you project. (Or alloocate it dynamically.)

Now you can either:

-Go to ProjectSettings->Ess->Data, and set the ess_resource_db_path property also make sure that automatic_load is on.

-Or you can load it yourself and set it into the ESS singleton either using the resource_db property.

Second

You need to add an ESSEntitySpawner somewhere into your SceneTree. I recommend that you create an autoload for it. This is where you have to implement your spawning logic.

What the module doesn't cover

Movement, and controls.

Unfortunately, there isn't a one-stop-shop solution for movement, especially if we throw networking into the mix, and the same is true for targeting. This means that this module cannot really do much in this regard, but it will give you as much help to set everything up as possible.

Optional Dependencies

Mesh Data Resource

https://github.com/Relintai/mesh_data_resource.git

Adds mesh support to ModelVisuals. This is exists because in gles2 mesh data cannot be accessed directly from ArrayMeshes.

Pre-built binaries

You can grab a pre-built editor binary from the Broken Seals repo, should you want to. It contains all my modules.

Overview

The module provides a huge number of script callbacks, usually as virtual methods they usually start with an underscore.

Do not call methods with underscores, all of them has a normal counterpart, always call that.

For example entity has crafts(int id) and _crafts(int id) (virtual). Always use crafts(int id), it will call _crafts(int id).

For networked classes, every variable is broken up into clientside, and serverside. This makes it easier to develop games that can also run locally, with less overhead and simpler logic. E.g. this makes it easy to use the visibility system even when you play locally on the server, because you just use the clientside variables, and your logic will work the same way.

Settings

Entity and spell system comes with quite a few settings, you can find these under ProjectSettings->Ess.

Singletons

The module contains 2 singletons. ESS, and ProfileManager. Both are accessible from scripts.

The ESS singleton

Contains the active ESSResourceDB instance, and for convenience a reference to the active ESSEntitySpawner instance. Also loads/handles/processes all of the entity and spell system related ProjectSettings, so if you need any ESS related value from ProjectSettings, don't query it directly, get it from this singleton.

Customizable enums values are preprocessed, and you usually have multiple ways of getting them.

The ProfileManager singleton

Contains methods to easily load/save/handle PlayerProfiles.

PlayerProfile

Contains player-related data, most notably ClassProfiles.

ClassProfile

Contains class-related data, most notably ActionBarProfiles, and InputProfiles.

ActionBarProfile

Contains the data for a set of actionbars.

InputProfileswd

Contains the keybind data for a class.

Enums

ESS needs lots of enums to work, and to reduce complexity with includes they ended up in a few separate classes.

I'm still in the process of converting these to be customizable (ESS singleton / ProjectSettings).

(Only the ones that worth it will be converted.)

EntityEnums

Contains Entity-related enums, like AIStates, skeleton attach points, entity flags, immunity flags, state flags.

ItemEnums

Contains item-related enums, like rarity, armor type, item types.

SpellEnums

Contains spell-related enums, like aura types, damage types, spell categories, spell types, trigger types, and quite a few notification constants.

Customizable enums

Open ProjectSettings, and then go to ESS/Enums.

All of the string properties are customizable enums. These require a comma-separated list. They are essentially a godot comma separated property hint enum string.

They all have defaults.

Fer example:

If you want you game to work with the following stats: Agility,Intellect,Crit,Weapon Damage,Stamina and you want Agility,Intellect,Stamina as you main stats.

Firstly you want to put you main stats at the beginning, because the system will take the first main_stat_count stats as main stats.

And then just enter Agility,Intellect,Stamina,Crit,Weapon Damage into the stats setting, and then set main_stat_count to 3.

When these values are expected to be used as properties, the ESS singleton will create snake_cased versions automatically. String stat_get_property_name(id: int) const inside the ESS singleton for example.

So in the example case ESS.stat_get_property_name(4) would return weapon_damage.

ESSResourceDB

This is a class that maps ids to resources for quick lookups. This is necessary in order to support networking, because you don't want to send resource paths over the network every time somebody casts a spell for example.

ESSResourceDBStatic

Simple static resource db. Just drag and drop all your data that you use into it with the inspector.

Stores the data as vectors.

Supports id remapping, which means that it can assign new ids to all added resources, so they don't clash. The added resource's index will be set as it's id.

This is useful for modding support, as you can just collect every mod's resource dbs, and add them to a static db, and with this option enabled the ids will not clash.

You can see an example of this here.

ESSResourceDBMap

Stores everything as a vector, and a map.

ESSResourceDBFolders

Inherited from ESSResourceDBMap.

It will load everything from the folders that you set up into it's folders property.

Entity

This is the main class that can be used for players/mobs/npcs and also other things like chests.

I ended up merging subclass functionality into it, because that way it gains a lot more utility, by sacrificing only a small amount of memory. For example this way it is easy to make chests attack the player, or make spell that animate objects.

Entity Body

Originally entities used to be inherited from Spatial or Node2D, so they could contain/drive their own models, but eventually on order to support both 2d, and 3d, bodies were separated from them. This unfortunately complicates the setup a bit, but the upsides overweight the downsides, as this way you don't need to create different entities for every model/body you have.

Bodies are stored at EntityData->EntitySpeciesData->ModelDatas (SpeciesModelData)->Body

When an Entity gets initialized, it will instance it's body automatically, but if you want to intance it yourself, you can call void instance_body(entity_data: EntityData, model_index: int) on an Entity.

The model_index property tell the Entity which one it should use.

Instancing bodies does not happen immediately, but you will probably want to set an Entity's position right where you create it, a few helpers were added:\

void set_transform_2d(transform: Transform2D, only_stored: bool = false)
void set_transform_3d(transform: Transform, only_stored: bool = false)

Your body implementation then can get this from an entity an set itself to the right place.

CharacterSkeletons

CharacterSkeletons handle the looks of your characters.

They come in two variants, one for 2d, one for 3d.

They have quite a few helper methods.

They can store ModelVisuals, and ModelVisualEntries.

They support attach points. For example a character's hand. It adds properties based on the selected entity_type. These are based on the values from ProjectSettings->ESS->Enums->skeletons_bone_attachment_points.

If you want to merge meshes this is where you can implement it.

CharacterSkeleton3D

The 3d variant.

Complex 3d skeleton scene
Complex 3d skeleton script

CharacterSkeleton2D

The 2d variant.

Simple 2d roguelike skeleton script
Simple 2d roguelike skeleton scene

ModelVisual

A collection ModelVisualEntries.

You will need to use this to define a look. For example if you have an item that will change your character's clothes, you will use this.

ModelVisualEntry

Contains meshes, textures, texture tints, mesh transforms.

It has 2 modes, Bone and Attachment.

In the bone mode, you need to select an entity type, and then a concrete bone. This is the "merge this into the final character mesh" mode.

In the attachment mode, you need to select a common attach point (ProjectSettings->Ess->enums->skeletons_bone_attachment_points), and the containing mesh will be put on to that point by the CharacterSkeleton. This is how you can implement weapons for example.

EntitySpeciesData

Contains data related to a species, like SpeciesModelDatas, and species specific spells, and auras.

SpeciesModelData

Contains a scene of a species's body and it's customizations.

The customizable_slots_string and customizable_colors_string should be filled with a comma separated string, they will add properties. Currently you need to click on something else, and back on the resource for these to show up, after a change to the strings.

The body can be any scene, Entity will instance it, and set it to it's body property.

The body should handle movement based on the player's input, it should handle sending position information through the network, if you want networking, it might (CharacterSkeletons can also do it) also drive your animations/animation players if you have it.

Bodies does not need to handle the graphics themselves (ModelVisualEntries for example) (you can implement your logic here if you want to), but the CharacterSkeleton classes exist for that purpose.

Complex 3d body script
Complex 3d body scene

Simple 2d roguelike body script
Simple 2d roguelike body scene

SpeciesInstance

This class will store character model customization data. E.g. which hairstyle you want for an Entity.

Not yet finished!

Spawning

Since spawning (= creating) entities is entirely dependent on the type of game you are making, ESS cannot do everything for you. It will set up stats, equipment etc, but there is no way to set up positions for example.

You can implement your spawning logic by inheriting from ESSEntitySpawner, and implementing _request_entity_spawn.

You should only have one spawner at any given time. It will register itself into the ESS singleton automatically.

Since it is inherited from Node, I recommend that you create an autoload for it.

The ESS singleton also contains convenience methods to request spawning an Entity.

Sample 3d spawner implementation
Sample 2d spawner implementation

EntityCreateInfo

Entity spawning usually requires a lot of complexity and hassle, this helper class aims to make it painless.

All methods that deal with spawning will take this as a parameter.

EntityData

Since setting up Entities as scenes is usually quite the hassle, EntityData had to be created.

It stores everything an entity needs.

In order to spawn an entity you need it.

EntityClassData

EntityClassData holds class-related information, like specs (CharacterSpec), spells, start spells, start auras, alternative ais, EntityResources (mana for example).

CharacterSpec

CharacterSpec holds spec-related information, most notably talents.

EntityResource

EntityResources are things like mana, health, or speed. These add greater flexibility over stats.

The resource system is quite flexible, if you add a resource serverside, it will be automatically added clientside. (You have to add EntityResources to the active ESSResourceDB!)

By default all entities have the build in speed and health resources, as a set index (EntityEnums::ENTITY_RESOURCE_INDEX_HEALTH and EntityEnums::ENTITY_RESOURCE_INDEX_SPEED).

There is also the EntityEnums::ENTITY_RESOURCE_INDEX_RESOURCES_BEGIN constant, so you have the current offset where the custom resources start.

Entity allocates these in it's _initialize() virtual method, if you want to customize them.

Note that EntityClassData contains an array, so you can add more resources easily to classes, these will be automatically added when the system initializes an Entity.

EntityResourceHealth

The standard health resource implementation.

EntityResourceSpeed

The standard speed resource implementation.

EntityResourceCostData

This is the class taht lets you implement resource costs. For example mana cost for a spell.

EntityResourceCostDataResource

The standard resource cost implementation.

EntityResourceCostDataHealth

The standard health resource cost implementation.

It has a resource property, so you can just assign any resource to this.

Interactions

If you want your player to interact with it's target. For example a vendor, or loot.

First make sure that you can interact, by checking Entity.cans_interact() or Entity.canc_interact(). If this returns true, you can call Entity.crequest_interact(). This will call Entity.sinteract() serverside.

Interactions are handled by EntityData by default. It has the same methods. If EntityData is not set, the Entity will try to call the same overridable on itself.

You can see an example implementation here.

AI

You can implement ai by extending EntityAI, and then assigning it to an EntityData.

When an Entity gets spawned it will create a copy for itself, so you can safely use class variables.

AIFormation

Not yet finished, it was meant as a way to calculate offset pet positions, (If an Entity has let's say 4 pets you don't just want them all to stay on top of their controller).

If this functionality ends up in EntityAI, after pets are finished, this will be removed.

Pets

Unfortunately pet support is not yet finished.

It is mostly done though, so you will see pet-related methods scattered around.

Bags

Stores items. See Bag. It has quite a few virtual methods, you should be able to implement most inventory types should you want to.

Entity will send these over the network.

Also Entities have a target bag property. For example this makes vendors easily implementable.

VRPCs

Entities has a networked visibility system. The method itself is called vrpc, it works the same way as normal rpcs. If you want to send data to every client that sees the current entity, use this.

Spells, Auras, Talents

Spell is the class you need to create spells, it stores the data, and also it has the ability to be scripted.

Aura is also built the same way as spells.

Talents are actually just Auras.

Talent ranks are implemented by deapplying the earlier rank, then applying the new rank.

How to

Request casting a spell clientside: void spell_crequest_cast(spell_id: int)
Request to learn a spell clientside: void spell_learn_requestc(id: int)

Request talent learning clientside:
void character_talent_crequest_learn(spec_index: int, character_talent_row: int, character_talent_culomn: int) or
void class_talent_crequest_learn(spec_index: int, class_talent_row: int, class_talent_culomn: int)

Apply an aura:

Note that you should only apply auras serverside, they will be sent to clients automatically.

# Or get it from the active ESSResourceDB, etc
export(Aura) var aura : Aura

func sapply_aura() -> void:
    var ainfo : AuraApplyInfo = AuraApplyInfo.new()
            
    ainfo.caster = info.caster
    ainfo.target = info.caster
    ainfo.spell_scale = 1
    ainfo.aura = aura

    aura.sapply(ainfo)

Complete UI Implemetation

Player UI Core Implemetation

Aura Frame Implementation
Castbar Implementation
Unitframe Implementation

Actionbar Implementation

Character Window Implementation
Inventory Window Implementation
Crafting Window Implementation
Loot Window Implementation
Talent Window Implemetation
Spellbook Window Implementation
Vendor Window Implementation
Trainer Window Implementation

3D Nameplate Implementation
2D Nameplate Implementation

Infos / Pipelines

SpellCastInfo

Stores information about the state of a spell's cast.

AuraApplyInfo

Helps to apply auras

SpellDamageInfo, SpellHealInfo

These are used in the damage and heal calculation. For example these can be used to implement immunities, or absorb effects by modifying their damage values in aura callbacks.

Projectiles

Spells support projectiles, they are created/set up inside void handle_projectile(info: SpellCastInfo).

The default implementation will instance Spell's projectile scene (if set), and then it will try to call a void setup_projectile(info: SpellCastInfo) on it if exists.

You can override this behaviour by implementing your own _void handle_projectile(info: SpellCastInfo) on Spell

Note that the module already adds SpellFollowProjectile3D, but this has not been finished yet.

Items

Items are implemented using 2 classes, ItemTemplate, and ItemInstance.

ItemTemplate contains all information for a potential item. You can generate Iteminstances with this, using it's ItemInstance create_item_instance() method. You can also implement your custom item creation logic using the void _create_item_instance() virtual.

ItemInstance is the actual item.

Loot

Looting can be implemented using Entity's target bag functionality.

You can see an example implementation here.
And an example ui implementation here.

XP

You can set all the xp values for your levels in ProjectSettings->Ess->xp.

Now you can start distributing xp, for whatever you'd like to Entities, using Entity.xp_adds(vlaue : int)

Examples

Eventually I'll create a separate repository with a few examples/demos, but for now you can check the game I've been working on for examples.

3d: https://github.com/Relintai/broken_seals.git

2d turn based: https://github.com/Relintai/broken_seals_roguelike

2d: https://github.com/Relintai/broken_seals_2d.git

Compiling

First make sure that you can compile godot. See the official docs: https://docs.godotengine.org/en/3.2/development/compiling/index.html

  1. Clone the engine if you haven't already:

If you want Godot 3.2: git clone -b 3.2 https://github.com/godotengine/godot.git godot

If you want Godot 4.0: git clone https://github.com/godotengine/godot.git godot

  1. go into the modules folder inside the engine's directory"

cd godot cd modules

  1. clone this repository

git clone https://github.com/Relintai/entity_spell_system.git entity_spell_system

(the folder needs to be named entity_spell_system!)

  1. Go up one folder

cd ..

  1. Compile godot.

For example:

scons p=x11 t=release_debug tools=yes

Similar Resources

A small fantasy game engine in WASM using GoLang

A small fantasy game engine in WASM using GoLang

The GoLang Fantasy Engine (GoLF Engine) is a retro game engine. It draws inspiration from fantasy console projects like pico-8, tic-80, and pyxle. Like those projects it is designed to be a retro-feeling game creation/playing tool. Unlike those projects GoLF is more minimal in scope and only provides an API and a small set of tools to help you create your games. Tools like an image editor and code editor are not built in. Despite this minimalism creating games in GoLF is still easy and should still maintain the retro game feel.

Jul 16, 2022

Currently in beta testing. A chess engine written in golang

Currently in beta testing. A chess engine written in golang

Weasel Art graciously provided by Alex Table of Contents: About Installing and Compiling from Source Contributing License About Weasel is an 0x88 and

Dec 30, 2022

golang powered game engine

golang powered game engine

Gobatch Go powered engine that offers features from low level opengl abstraction to UI framework. I created this to separate lot of logic from game am

Nov 13, 2022

Arkanoid game in Go using Ebiten game engine with ECS.

Arkanoid game in Go using Ebiten game engine with ECS.

Arkanoid-go Arkanoid game in Go using Ebiten game engine with ECS. You must have Git LFS installed when cloning the repository to download assets. See

Oct 9, 2022

spx - A 2D Game Engine for learning Go+

spx - A 2D Game Engine for learning Go+

spx - A 2D Game Engine for learning Go+ Tutorials How to run spx tutorials? Download Go+ and build it. See https://github.com/goplus/gop#how-to-build.

Dec 1, 2022

Blunder is an open-source UCI compatible chess engine.

A UCI compatible chess engine written in Golang

Dec 30, 2022

Go Game Engine using SDL for fun

nMage nMage is a (hopefully!) high performance 3D Game Engine written in Go being developed live, with recordings posted on YouTube. This project is b

Nov 30, 2022

HelloSpx - Hello world of Go+ spx game engine

HelloSpx - Hello world of Go+ spx game engine

HelloSpx - Hello world of Go+ spx game engine How to run Download Go+ and build it. See https://github.com/goplus/gop#how-to-build. Download this game

Nov 27, 2021

HelloWorldForSpx - Hello world of Go+ spx game engine

 HelloWorldForSpx - Hello world of Go+ spx game engine

HelloWorldForSpx - Hello world of Go+ spx game engineHelloWorldForSpx - Hello world of Go+ spx game engine

Nov 22, 2021
Comments
  • 1.0 Release Tracker

    1.0 Release Tracker

    This Issue tracks the things that need to be done for the first release.

    • [ ] Make dependencies to my other modules optional.
    • [ ] Documentation (Sphinx)
    • [ ] Class docs (XML) - At least the things that are not self explanatory.
    • [ ] Sound Support
    • [ ] WorldSpell's logic
    • [ ] Implement all generic spell effects
    • [ ] Implement all generic aura effects
    • [ ] Fix AI
    • [ ] Finish the setup for pet support (I already have the design for it, just need to code it.)
    • [ ] Port everything that belongs here from Broken Seals
  • Godot latests renames and the likes

    Godot latests renames and the likes

    An attempt at quickly updating the module to allow building with the latest godot branch.

    Most of this was done with Regex commands and I'm still missing a few other functions to convert but I thought I'd at least share what I have for now.

    Let me know if I've made any errors or if this is worthless ig

Battleblips - Work in progress multiplayer terminal base battleship game written in Go (with mouse support!) using tcell library
Battleblips - Work in progress multiplayer terminal base battleship game written in Go (with mouse support!) using tcell library

battleblips Work in progress multiplayer terminal base battleship game written in Go (with mouse support!) using tcell library (see https://github.com

Apr 26, 2022
Online multiplayer board game server written in Go, using WebSockets.

BfH Server The Battle for Hermannia is a board game created as a gift by the father of hermannm, a developer of this project. This digital edition of

Nov 7, 2022
Tile is a 2D grid engine, built with data and cache friendly ways, includes pathfinding and observers.
Tile is a 2D grid engine, built with data and cache friendly ways, includes pathfinding and observers.

Tile: Data-Oriented 2D Grid Engine This repository contains a 2D tile map engine which is built with data and cache friendly ways. My main goal here i

Dec 26, 2022
Engo is an open-source 2D game engine written in Go.

Engo A cross-platform game engine written in Go following an interpretation of the Entity Component System paradigm. Engo is currently compilable for

Dec 26, 2022
Go 3D Game Engine
Go 3D Game Engine

G3N - Go 3D Game Engine G3N (pronounced "gen") is an OpenGL 3D Game Engine written in Go. It can be used to write cross-platform Go applications that

Jan 9, 2023
Scalable Distributed Game Server Engine with Hot Swapping in Golang
Scalable Distributed Game Server Engine with Hot Swapping in Golang

GoWorld Scalable Distributed Game Server Engine with Hot Reload in Golang Features Architecture Introduction Get GoWorld Manage GoWorld Servers Demos

Dec 25, 2022
A pure Go game engine
A pure Go game engine

Oak A pure Go game engine Table of Contents Installation Motivation Features Support Quick Start Implementation and Examples Finished Games Installati

Jan 8, 2023
Terminal-based game engine for Go, built on top of Termbox
Terminal-based game engine for Go, built on top of Termbox

Termloop Termloop is a pure Go game engine for the terminal, built on top of the excellent Termbox. It provides a simple render loop for building game

Dec 29, 2022
A chess engine written in golang
A chess engine written in golang

Weasel Art graciously provided by Alex Table of Contents: About Installing and Compiling from Source Contributing License About Weasel is an 0x88 and

Dec 30, 2022
A 2D ARPG game engine.
A 2D ARPG game engine.

Abyss Engine is an ARPG game engine in the same vein of the 2000's games, and supports playing games similar to Diablo 2. The engine is written in golang and is cross platform. This engine does not ship with game specific files, and will require a game's assets in order to run.

Dec 24, 2022