jake2 icon indicating copy to clipboard operation
jake2 copied to clipboard

Component for all non monster entities

Open demoth opened this issue 2 years ago • 0 comments

Quake2 (and by extension - jake2) suffers from the Blob antipattern: the edict (or SubgameEntity in case of jake2) contains dozens of fields, which are used in many often unrelated scenarios. This leads to high coupling of different game related functions. In addition to it, some fields are used for completely different purposes, for example:

  • count can be used to store amount of bullets in an ammo item, or state of an areaportal, or the value of a func_clock entity.
  • style property - used to indicate if a medkit can ignore players health when picked up, or define the intensity of a light
  • many other examples

One way to solve it is to incorporate an entity-component-system approach. At the moment, I find it difficult to implement purely. Also, there core design of the engine is not very friendly to it (yet). However, extracting relevant properties into structures (components) should greatly improve readability of the game logic.

A typical spawn function should look like

func_stroyent(self, game) {
    // validate editor provided values
    if (self.health <= 0)
        game.freeEntity(self)

    // initialize required component(s)
    self.addComponent(StroyentComponent(self.health, self.style)) // anything provided by the map entities is fine to use here, to create a component

    // common code
    self.think = stroyent_think
    game.linkEntity(self)
}

so in the think or other adapters (block, use, etc..), the required component can be used:

stroyent_think(self, game) {
    // get the compoenent from the entity
    val stroyent = self.components[STROYENT]
    // do some custom logic
    target.health += stroyent.amount
    stroyent.amount--
}

Some properties should stay in the main entity class - mostly those properties that are accessed by the common game code. The good indicator that a property should be extracted to a separate component is that the property is only used from the spawn, think, block, use and other adapters.

Candidates for the extraction are:

  • count
  • style
  • volume
  • movedir
  • speed
  • and many others

demoth avatar Feb 03 '23 22:02 demoth