Closed ktksan closed 4 years ago
Here are some thoughts on the body temperature system and how it can be used.
The first question we tried to answer is how to model the fundamental system to track and modify the body temperature of the player (or more general, of any entity). We eventually came up with a basic numeric system serving as base for anything related to body temperatures. To mitigate the problem how to related the body temperature scale to other temperatures (e.g., the environment temperature as given by the WeatherManager) we propose some abstraction on top of these numeric values.
public class BodyTemperatureComponent implements Component {
public float temperature;
}
Similar to systems like Health or Thirst modifications and notifications should be handled via events. The base body temperature authority system should be a periodic system. It will update all temperature components periodically after some fixed time interval, e.g., every second (1000ms). Without any system reacting on this, the temperature value will stay to the initial (default) value.
The base system will work with a set of events, some being for internal processes and others for external communication (API).
PeriodicActionEvent
. Internal event to trigger the update of temperature components. The base system is responsible for collecting the temperature delta to be applied for each entity with BodyTemperature
by sending out AffectBodyTemperature
.AffectBodyTemperature
. An AbstractValueModifiableEvent
to notify systems that the body temperature should be updated for a given entity. This works exactly as GetMaxSpeed
or AffectThirst
by giving system the chance to modify the temperature delta to be applied.BodyTemperatureChanged
. The notification for systems that want to react on changing body temperatures. This just notifies about the numeric temperature change by holding both old and new value in the event.To simplify the interpretation of these numeric values we propose to add an abstraction that introduces discrete categories or levels to track body temperature.
Each game mode would have to provide information on how to interpret a temperature value (scale and unit of measurement). To mitigate this, we thought about a game play simplification that will provide a configurable interpretation as temperature levels. The level is always derived from the numeric value and cannot be changed otherwise. In fact, it's not even persisted with the component but just available as semantic information by sending an event. Systems that need this information may need to persist it themselves.
public enum BodyTemperatureLevel {
CRITICAL_LOW, LOW, REDUCED, NORMAL, RAISED, HIGH, CRITICAL_HIGH;
}
Whenever the temperature changes in a way that the temperature level change an event is sent out to notify systems about this:
BodyTemperatureLevelChanged
. A notification event containing the previous and new abstract temperature levels. This event is only sent if the temperature change leads to a change of level.We could aim at implementing the logic to send out the event based thresholds to be defined in the BodyTemperature
component. The following properties make the system flexible yet functional:
Climate conditions would have to provide a delta prefab for the player to define the thresholds for the temperature levels. Hypothermia and Hyperthermia will just listen for BodyTemperatureLevelChanged
. The strength of the weakening effect could be directly derived from the temperature levels.
We would favor in implementation where the body temperature delta is derived from the environment temperature and environment humidity, without any threshold computations. The formulas need to be constructed in a way that they only slowly converge against the environment temperature to give the player time to react to the change. As was mentioned before, this is probably best play-tested to find the right parameters.
We also came up with a possible mitigation for "dying after leaving the danger zone", e.g., the (numeric) body temperature being so far off the (interpreted) vital range that the temperature cannot adjust fast enough. This could be improved by flattening or steepening the curve depending on whether the temperature delta goes in the "right" direction. However, this assumes that we know the _target temperature_². Mathematically speaking, the temperature delta goes into the right direction if difference to environment and difference to target temperature have the same sign:
Δt_env = t_env - t
Δt_target = t_target - t
sgn(Δt_env) == sgn(Δt_target)
This proposal is not free of limitations, but we think (or rather hope) that they will help to focus more on game play simplifications. Limiting the levels to a fixed set "forces" modules to reduce their complexity to match with the granularity of levels if they want to use that abstraction. However, it is possible to ignore the default abstraction for temperature levels and build around it, as the numeric values are still exposed, and the levels are served on top of the numeric representation.
¹ For periodic systems, the Affect…
events should probably hold information about the time delta. Otherwise, we are locked in to use fixed interval as we cannot change it without affecting all game play logic reacting to it. This is a general flaw which does not need to be addressed right now, but we can keep it in mind to be more resilient against changes in the future.
² The target temperature may be tracked as configuration in the BodyTemperature
component. If we assume the temperature to be within [0, 1]
a good default value for the target temperature might be the mean value 0.5
.
Alright I have the first edition after the new proposal. 🙂 I have tried to incorporate some of the things .. .although not completely but I figured it's better to let you guys take a look at it and check if it is in the direction of what you were thinking.. For the first edition I have only used three of the temperature levels namely high, normal, low and have used arbitrary values which were easier for me to test with and a BodyTemperatureChangedEvent with the BodyTemperatureLevel enum. Changing level to high triggers hyperthermia, to low triggers hypothermia, to normal removes either of the two which the player is affected with. I have tried introducing a delta prefab too. I also tried incorporating affectBodyTemperature but then something weird started happening, for some reason the bodyTemperature stopped changing in regular intervals, it was being displayed but deltaTemp was probably getting a zero value from the affectBodyTemperatureEvent.getResultValue(). I don't understand what was triggering that so I have left that portion in the form of a comment. Please take a look.
This is a prototype for a system to keep a check on body temperature of the player entity. Currently the temperature is updated every second and displayed in the chat message every 10 seconds along with the environment temperature for that location.