godotengine / godotengine/godot

Assigning variable type corrupts getter

Open
#91,689 6 comments 0 reactions 0 assignees View on GitHub
bug confirmed topic:gdscript
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
![regeningHealth](https://github.com/godotengine/godot/assets/37415138/e06b55f4-9a7b-42ac-bb5c-f1bd6240c001)
Taking Damage
![takingDamage](https://github.com/godotengine/godot/assets/37415138/f2625214-e5d2-4373-b644-a815378951d6)

### 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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.