godotengine / godotengine/godot
Assigning variable type corrupts getter
- Dominant language
- C++
- Stars
- 117k
- Forks
- 26.8k
- PR merge metrics
- PR metrics pending
Description
### Tested versions
Reproducible in v4.2.1.stable.mono.official [b09f793f5]
### System information
Godot v4.2.1.stable.mono - Windows 10.0.19045 - Vulkan (Forward+) - dedicated AMD Radeon RX 6750 XT (Advanced Micro Devices, Inc.; 31.0.24027.1012) - AMD Ryzen 7 2700X Eight-Core Processor (16 Threads)
### Issue description
Setting type of variables that keep track of current Health, Energy and Shield impacts getters of other variables associated with each tracker.
Getting one variable works as intended, but getting at least two results in corruption.
Issue happens outside of setter as well.
Example code shows Health variables and their setters and getters and how they operate together.
Example videos:
[Taking Damage](https://www.youtube.com/watch?v=gN4S-H0olEQ)
[Gaining Shield](https://www.youtube.com/watch?v=3FCjE0MXSfc)
```gdscript
@export var maxHealth : int = 40
var realMaxHealth : int : get = _getMaxHealth
func _getMaxHealth():
return (maxHealth + maxHealthAdd) * maxHealthMult
var maxHealthAdd : int = 0 :
set(val):
maxHealthAdd = val
health_max_changed.emit(realMaxHealth)
var maxHealthMult : float = 1.0 :
set(val):
maxHealthMult = val
health_max_changed.emit(realMaxHealth)
#########################################################################################################
var currentHealth : int = realMaxHealth : # the ': int' here causes corruption
#########################################################################################################
set(val):
var a = currentHealth
var b = realRegenValueHealth
var c = a + b
var d = currentHealth + realRegenValueHealth # only corrupted value, example in pictures below with breakpoint set here
currentHealth = clamp(val, 0, realMaxHealth)
health_changed.emit(currentHealth)
if currentHealth == 0:
states.clear()
states.append(MyGlobals.States.Dead)
@export var regenRateHealth : float = 1
var realRegenRateHealth : float : get = _getRegenRateHealth
func _getRegenRateHealth():
return (regenRateHealth + regenRateHealthAdd) * regenRateHealthMult
var regenRateHealthAdd : float = 0 :
set(val):
regenRateHealthAdd = val
health_regenRate_changed.emit()
var regenRateHealthMult : float = 1.0 :
set(val):
regenRateHealthMult = val
health_regenRate_changed.emit()
@export var regenValueHealth : int = 1
var realRegenValueHealth : int : get = _getRegenValueHealth
func _getRegenValueHealth():
return (regenValueHealth + regenValueHealthAdd) * regenValueHealthMult
var regenValueHealthAdd : int = 0 :
set(val):
regenValueHealthAdd = val
health_regenValue_changed.emit()
var regenValueHealthMult : float = 1.0 :
set(val):
regenValueHealthMult = val
health_regenValue_changed.emit()
var regenTimerHealth : float = 0.0
```
Regening Health

Taking Damage

### Steps to reproduce
Wait for either the regen function to be called or walk into an attack hitbox to see the Health values corrupting
Walk into circle area to see Shield values corrupting
Wait for energy regen timer to see its values corrupting
*edit: Press ENTER when loading into main scene to load the debug scene
All necessary code is in res://scenes/characters/baseChara/baseChara.gd
### Minimal reproduction project (MRP)
Pruned project I was working on when I discovered this: [CorruptionExample.zip](https://github.com/godotengine/godot/files/15242288/CorruptionExample.zip)
Contributor guide
Research direction
Start with the attached CorruptionExample.zip and reproduce the issue by loading the debug scene, then inspect res://scenes/characters/baseChara/baseChara.gd, especially the typed currentHealth declaration and related getters. Done means the Health, Shield, and Energy values no longer corrupt when their getters and setters are used together.
Written by the indexing model from the issue text.
Assessment
- Domain
- game-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100