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.
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 differentgame
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 afunc_clock
entity.style
property - used to indicate if a medkit can ignore players health when picked up, or define the intensity of a lightOne 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
so in the
think
or other adapters (block
,use
, etc..), the required component can be used: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