Godot Version
<! 4.2.1 Stable →
Question
<! Hey,
Been following this tutorial - https://www.youtube.com/watch?v=LjV8rKWz9hY&list=PLtosjGHWDab682nfZ1f6JSQ1cjap7Ieeb&index=11&ab_channel=Branno
I’m stuck trying to fix a bug with my level up system. The game is a Survivors-like and so when the player grabs an exp gem they level up. Problem is, experience gems with higher values cause multiple level ups simultaneously, skipping potential upgrades. On a level up the player normally gets 3 choices but when this bug occurs the player gets 3 for every level granted. Ideally, the level up loop would pause at each level allowing for a skill choice each time the required_exp variable is met.
After testing I have found that a single gem with a high value operates correctly and allows for multiple, separate level ups. the issue seems to arise when multiple XP gems are gathered at the same time or very near each other.
I’ve reviewed the finished code from the tutorial and gone over what have several times, looked online, but just can not get this bug sorted. Any advice is appreciated. Please let me know if you need any more info.
decent amount of code to look through… thanks again for your time!
Player Level Up Script Info
func _on_collect_area_area_entered(area):
if area.is_in_group("loot"):
var gem_exp = area.collect()
calculate_experience(gem_exp)
func calculate_experience(gem_exp):
var exp_required = calculate_experience_cap()
collected_experience += gem_exp
if experience + collected_experience >= exp_required: #level up
collected_experience -= exp_required - experience
experience_level += 1
experience = 0
exp_required = calculate_experience_cap()
levelup()
else:
experience += collected_experience
collected_experience = 0
set_expbar(experience, exp_required)
func calculate_experience_cap():
var exp_cap = experience_level
if experience_level < 20:
exp_cap = experience_level*5
elif experience_level < 40:
exp_cap = 95 + (experience_level - 19) * 8
else:
exp_cap = 255 + (experience_level - 39) * 12
return exp_cap
func levelup():
sndlevelUp.play()
lblLevel.text = str("Level: ", experience_level)
var tween = levelPanel.create_tween()
tween.tween_property(levelPanel,"position", Vector2(440,110),0.2).set_trans(Tween.TRANS_QUINT).set_ease(Tween.EASE_IN)
tween.play()
levelPanel.visible = true
var options = 0
var optionsmax = 3
while options < optionsmax:
var option_choice = itemOptions.instantiate()
option_choice.item = get_random_item()
upgradeOptions.add_child(option_choice)
options += 1
get_tree().paused = true
func upgrade_character(upgrade):
match upgrade:
"chargedshot1":
chargedshot_level = 1
chargedshot_baseammo += 1
"chargedshot2":
chargedshot_level = 2
chargedshot_baseammo += 1
"chargedshot3":
chargedshot_level = 3
"chargedshot4":
chargedshot_level = 4
chargedshot_baseammo += 1
"burstlaser1":
burstlaser_level = 1
"burstlaser2":
burstlaser_level = 2
burstlaser_baseammo += 3
burstlaser_attackspeed += -.01
"burstlaser3":
burstlaser_level = 3
burstlaser_baseammo += 4
burstlaser_attackspeed += -.01
"burstlaser4":
burstlaser_level = 4
burstlaser_baseammo += 7
burstlaser_attackspeed += -.02
"unstablebolt1":
unstable_bolt_level = 1
"unstablebolt2":
unstable_bolt_level = 2
unstable_bolt_baseammo += 5
unstable_bolt_pulse += 1
"unstablebolt3":
unstable_bolt_level = 3
unstable_bolt_baseammo += 5
unstable_bolt_timer.wait_time += -.5
"unstablebolt4":
unstable_bolt_level = 4
unstable_bolt_baseammo += 8
unstable_bolt_pulse += 1
"tornado1":
tornado_level = 1
tornado_baseammo += 1
"tornado2":
tornado_level = 2
tornado_baseammo += 1
"tornado3":
tornado_level = 3
tornado_attackspeed -= 0.5
"tornado4":
tornado_level = 4
tornado_baseammo += 1
"spinningblade1":
spinning_blade_level = 1
"spinningblade2":
spinning_blade_level = 2
spinning_blade_ammo += 1
spinning_blade_area = spinning_blade_area * 1.10
spinning_blade_rot = spinning_blade_rot * 1.10
"spinningblade3":
spinning_blade_level = 3
spinning_blade_ammo += 1
spinning_blade_area = spinning_blade_area * 1.15
spinning_blade_rot = spinning_blade_rot * 1.15
"spinningblade4":
spinning_blade_level = 4
spinning_blade_ammo += 1
spinning_blade_area = spinning_blade_area * 1.20
spinning_blade_rot = spinning_blade_rot * 1.20
"hellblade1":
hellblade_level = 1
"hellblade2":
hellblade_level = 2
"hellblade3":
hellblade_level = 3
hellblade_ammo += 1
"hellblade4":
hellblade_level = 4
"shields1","shields2","shields3","shields4":
shields += 1
"speed1","speed2","speed3","speed4":
speed_upgrade += 25.0
"explosive1","explosive2","explosive3","explosive4":
explosive += 0.10
"liquid cooling1","liquid cooling2","liquid cooling3","liquid cooling4":
liquid_cooling += 0.05
"hardpoint1","hardpoint2":
additional_attacks += 1
"repair":
hp += 20
hp = clamp(hp,0,maxhp)
set_HPBar(hp, maxhp)
"upgrade":
var rand_upgrade = randi_range(1,11)
match rand_upgrade:
1,2,3:
shields += sh_upg
sh_upg = sh_upg * .95
4,5,6:
speed_upgrade += 25.0 * spd_upg
spd_upg = spd_upg * .95
7,8:
liquid_cooling += 0.05 * lc_upg
lc_upg = lc_upg * .95
9,10:
explosive += 0.10 * ex_upg
ex_upg = ex_upg * .95
11:
additional_attacks += 1
adjust_GUI_Collection(upgrade)
has_weapon = true
attack()
var option_children = upgradeOptions.get_children()
for i in option_children:
i.queue_free()
upgrade_options.clear()
collected_upgrades.append(upgrade)
levelPanel.visible = false
levelPanel.position = Vector2(1280,110)
get_tree().paused = false
calculate_experience(0)
func get_random_item():
var dblist = []
for i in UpgradeDb.UPGRADES:
if i in collected_upgrades: #find already chosen upgrades
pass
elif i in upgrade_options: # if upgrade is already selected as option
pass
elif UpgradeDb.UPGRADES[i]["type"] == "item": #don't pick food
pass
elif has_weapon == false and UpgradeDb.UPGRADES[i]["type"] != "weapon":
pass
elif UpgradeDb.UPGRADES[i]["prerequisite"].size() > 0: #check prereq
var to_add = true
for n in UpgradeDb.UPGRADES[i]["prerequisite"]:
if not n in collected_upgrades:
to_add = false
if to_add:
dblist.append(i)
else:
dblist.append(i)
if dblist.size() > 0:
var randomitem = dblist.pick_random()
upgrade_options.append(randomitem)
return randomitem
else:
return null
GEM CODE:
extends Area2D
@export var experience = 1
var spr_green = preload("res://Assets/Sprites/Gems/gemstone15.png")
var spr_blue = preload("res://Assets/Sprites/Gems/gemstone21.png")
var spr_red = preload("res://Assets/Sprites/Gems/gemstone6.png")
@onready var spr_anim = $Sprite2D/GPUParticles2D
var target = null
var speed = -1
@onready var sprite = $Sprite2D
@onready var collision = $CollisionShape2D
@onready var sound = $AudioStreamPlayer
func _ready():
if experience < 5:
return
elif experience < 26:
sprite.texture = spr_blue
spr_anim.texture = spr_blue
else:
sprite.texture = spr_red
spr_anim.texture = spr_red
func _physics_process(delta):
if target != null:
global_position = global_position.move_toward(target.global_position, speed)
speed += 2*delta
func collect():
sound.play()
collision.call_deferred("set","disabled",true)
sprite.visible = false
return experience
func _on_audio_stream_player_finished():
queue_free()
→