Closed PedrelliLuca closed 2 years ago
Here is a first draft of the system that will cause health to be affected by temperature. I was mainly inspired by Module 8 of CG Spectrum's Game Programming Course.
@startuml
skinparam sequenceArrowThickness 2
skinparam roundcorner 20
skinparam sequenceParticipant underline
skinparam linetype ortho
package ScalarField {
class AScalarFieldCharacter {
+ <i>void TakeDamage(...) override
--
- <i>void _onTemperatureChanged(double temperature)
}
}
package GameplayAttributes {
class UHealthComponent #palegreen {
+ void TickComponent(...) override
+ void TakeDamage(double damage)
+ bool IsDead() const
+ double GetCurrentHealth() const
+ void SetCurrentHealth(double health)
--
- double _maxHealth
- double _healthRegenPerSecond
- double _currentHealth
}
class UManaComponent
}
AScalarFieldCharacter --> UHealthComponent
AScalarFieldCharacter --> UManaComponent
package DamageHandlers {
class UTemperatureDamageHandlerComponent #palegreen {
+ void HandleTemperatureDamage(TWeakObjectPtr<UThermodynamicComponent> thermoC)
+ void TickComponent(...) override
+ void SetMinComfortTemperature(double minComfortT)
+ void SetMaxComfortTemperature(double maxComfortT)
+ double GetMinComfortTemperature() const
+ double GetMaxComfortTemperature() const
--
- double <color:darkviolet> _minComfortTemperature
- double <color:darkviolet> _maxComfortTemperature
- double <color:darkviolet> _damageInterval
- double _currentInteralTime
}
}
AScalarFieldCharacter --> UTemperatureDamageHandlerComponent
@enduml
The final class diagram, with the UI. Orange attributes are BlueprintReadOnly
, while blue functions are BlueprintImplementableEvent
s
@startuml
skinparam sequenceArrowThickness 2
skinparam roundcorner 20
skinparam sequenceParticipant underline
skinparam linetype ortho
package ScalarField {
class AScalarFieldCharacter {
+ <i>void Tick(float deltaTime) override
+ <i>void TakeDamage(...) override
--
- <i>void _healthChanged(double newHealth) const
- <i>void _maxHealthChanged(double newMaxHealth) const
- <i>void _healthRegenChanged(double newHealthRegen) const
- <i>void _manaChanged(double newHealth) const
- <i>void _maxManaChanged(double newMaxHealth) const
- <i>void _manaRegenChanged(double newHealthRegen) const
- <i>void _temperatureChanged(double newTemperature)
- TObjectPtr<UManaComponent> _manaC
- <i>TObjectPtr<UHealthComponent> _healthC
- <i>TObjectPtr<UTemperatureDamageHandlerComponent> _temperatureDmgHandlerC
}
class AScalarFieldPlayerController {
+ TWeakObjectPtr<UHUDWidget> GetGameplayHUD()
--
- void _createHUD()
- TObjectPtr<UHUDWidget> _hudWidget
}
AScalarFieldPlayerController <..> AScalarFieldCharacter
}
package GameplayAttributes {
class FOnHealthChanged << (D,Violet) >> #palegreen
class FOnMaxHealthChanged << (D,Violet) >> #palegreen
class FOnHealthRegenChanged << (D,Violet) >> #palegreen
class UHealthComponent #palegreen {
+ void TickComponent(...) override
+ void PostEditChangeProperty(...) override
+ double GetCurrentHealth() const
+ double GetMaxHealth() const
+ double GetHealthRegen() const
+ void SetCurrentHealth(double health)
+ void SetMaxHealth(double maxHealth, bool bUpdateHealth = true)
+ void SetHealthRegen(double healthRegenPerSecond)
+ void TakeDamage(double damage)
+ bool IsDead() const
+ FOnHealthChanged& OnHealthChanged()
+ FOnMaxHealthChanged& OnMaxHealthChanged()
+ FOnHealthRegenChanged& OnHealthRegenChanged()
--
# void BeginPlay() override
--
- double _maxHealth
- double _healthRegenPerSecond
- double _currentHealth
- FOnHealthChanged _onHealthChanged
- FOnMaxHealthChanged _onMaxHealthChanged
- FOnHealthRegenChanged _onHealthRegenChanged
}
FOnHealthChanged <-- UHealthComponent
FOnMaxHealthChanged <-- UHealthComponent
FOnHealthRegenChanged <-- UHealthComponent
class FOnManaChanged << (D,Violet) >> #palegreen
class FOnMaxManaChanged << (D,Violet) >> #palegreen
class FOnManaRegenChanged << (D,Violet) >> #palegreen
class UManaComponent {
+ UManaComponent()
+ void TickComponent(...) override
+ void PostEditChangeProperty(...) override
+ double GetCurrentMana() const
+ double GetMaxMana() const
+ double GetManaRegen() const
+ void SetCurrentMana(double mana)
+ void SetMaxMana(double maxMana, bool bUpdateMana = true)
+ void SetManaRegen(double manaRegenPerSecond)
+ FOnManaChanged& OnManaChanged()
+ FOnMaxManaChanged& OnMaxManaChanged()
+ FOnManaRegenChanged& OnManaRegenChanged()
--
# void BeginPlay() override
--
- double _maxMana
- double _manaRegenPerSecond
- double _currentMana
- FOnManaChanged _onManaChanged
- FOnMaxManaChanged _onMaxManaChanged
- FOnManaRegenChanged _onManaRegenChanged
}
FOnManaChanged <-- UManaComponent
FOnMaxManaChanged <-- UManaComponent
FOnManaRegenChanged <-- UManaComponent
}
AScalarFieldCharacter --> UHealthComponent
AScalarFieldCharacter --> UManaComponent
AScalarFieldCharacter ..> FOnManaChanged
AScalarFieldCharacter ..> FOnMaxManaChanged
AScalarFieldCharacter ..> FOnManaRegenChanged
AScalarFieldCharacter ..> FOnHealthChanged
AScalarFieldCharacter ..> FOnMaxHealthChanged
AScalarFieldCharacter ..> FOnHealthRegenChanged
package DamageHandlers {
class UTemperatureDamageType
class UTemperatureDamageHandlerComponent #palegreen {
+ void TickComponent(...) override
+ void PostEditChangeProperty(...) override
+ void HandleDamage(double temperature)
+ void SetMinComfortTemperature(double minComfortTemperature)
+ void SetMaxComfortTemperature(double maxComfortTemperature)
+ double GetMinComfortTemperature() const
+ double GetMaxComfortTemperature() const
+ bool IsTemperatureComfortable(double temperature)
--
- double _computeDamageFromTemperature(double temperature)
- double <color:darkviolet> _minComfortTemperature
- double <color:darkviolet> _maxComfortTemperature
- double <color:darkviolet> _damageInterval
- double _currentInteralTime
}
UTemperatureDamageHandlerComponent ..> UTemperatureDamageType
}
AScalarFieldCharacter --> UTemperatureDamageHandlerComponent
package GameplayUI {
class UHUDWidget #palegreen {
+ void SetMaxHealth(double newMaxHealth)
+ void SetCurrentHealth(double newCurrentHealth)
+ <color: blue>void SetHealth()
+ <color: blue>void SetHealthRegen(double newHealthRegen)
+ void SetMaxMana(double newMaxMana)
+ void SetCurrentMana(double newCurrentMana)
+ <color: blue>void SetMana()
+ <color: blue>void SetManaRegen(double newManaRegen)
+ <color: blue>void SetTemperature(double temperature, FLinearColor temperatureColor)
+ <color: blue>void SetPauseStatus(bool bIsGamePaused)
--
# <color: orange>double _currentHealth
# <color: orange>double _maxHealth
# <color: orange>double _currentMana
# <color: orange>double _maxMana
}
}
UHUDWidget <-- AScalarFieldPlayerController
UHUDWidget <.. AScalarFieldCharacter
@enduml
Sequence diagram explaining the damage by temperature's flow:
@startuml
skinparam sequenceMessageAlign center
?-> AScalarFieldCharacter : Tick()
AScalarFieldCharacter -> UTemperatureDamageHandlerComponent : HandleDamage(temperature)
note over UTemperatureDamageHandlerComponent #FFAAAA: Temperature outside\ncomfort interval!
UTemperatureDamageHandlerComponent -> AScalarFieldCharacter: AActor::TakeDamage()
UTemperatureDamageHandlerComponent -> UTemperatureDamageHandlerComponent: Starts ticking\nto cooldown
note over AScalarFieldCharacter: In the future the character\nwill be able to change the\ndamage taken via some\nother component (armor, ...)
AScalarFieldCharacter -> UHealthComponent: TakeDamage()
UHealthComponent -> UHealthComponent: SetHealth()
UHealthComponent -> AScalarFieldCharacter: FOnHealthChanged Broadcast(health)
AScalarFieldCharacter -> UHUDWidget: GetController()->GetGameplayHUD()->SetCurrentHealth(health)
@enduml
What?
Make a health component that keeps track of the owner's max and current health. Implement some system that causes any character to take damage over time when their temperature is outside a given temperature interval
[Tmin, Tmax]
called "comfort" interval.Why?
Even though at the moment they're just coloring stuff, temperature-based skills are supposed to deal damage. The way they do so is by driving the target's temperature outside the "comfort" interval. This issue will bring this project closer to an actual video game.