Skip to content

Commit

Permalink
Prevent crashes due to freed references
Browse files Browse the repository at this point in the history
  • Loading branch information
axerosh committed May 10, 2020
1 parent 5bc763c commit 4caa0b1
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 64 deletions.
6 changes: 6 additions & 0 deletions game/project.godot
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,18 @@ _global_script_classes=[ {
"path": "res://scenes/combat/combat.gd"
}, {
"base": "Spatial",
"class": "DraggablePart",
"language": "GDScript",
"path": "res://scenes/draggable_parts/DraggablePart.gd"
}, {
"base": "Spatial",
"class": "Ghoul",
"language": "GDScript",
"path": "res://scenes/ghoul/Ghoul.gd"
} ]
_global_script_class_icons={
"Combat": "",
"DraggablePart": "",
"Ghoul": ""
}

Expand Down
8 changes: 5 additions & 3 deletions game/scenes/Main.tscn
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[gd_scene load_steps=8 format=2]
[gd_scene load_steps=9 format=2]

[ext_resource path="res://scenes/ghoul_assembly/Ghoul Assembly.tscn" type="PackedScene" id=1]
[ext_resource path="res://scenes/ground/Ground.tscn" type="PackedScene" id=2]
Expand All @@ -7,12 +7,12 @@
[ext_resource path="res://scenes/Decorative/AssemblyDecorations.tscn" type="PackedScene" id=5]
[ext_resource path="res://scenes/GameStateManagerFactoryServiceProvider.gd" type="Script" id=6]
[ext_resource path="res://scenes/Camera.gd" type="Script" id=7]
[ext_resource path="res://GameOverText.tscn" type="PackedScene" id=8]

[node name="Main" type="Spatial"]

[node name="Camera" type="Camera" parent="."]
transform = Transform( -3.78552e-08, 0.5, -0.866025, 2.18557e-08, 0.866025, 0.5, 1, 1.95399e-14, -4.37114e-08, -33.0352, 11.2092, 13.053 )
far = 1732.5
script = ExtResource( 7 )
fight_pos_path = NodePath("../camera_fight_target")

Expand All @@ -36,4 +36,6 @@ gameStatePath = NodePath("../GameStateManagerFactoryServiceProvider")
script = ExtResource( 6 )

[node name="camera_fight_target" type="Spatial" parent="."]
transform = Transform( -1.62921e-07, 0.34202, -0.939693, 0, 0.939693, 0.34202, 1, 5.57222e-08, -1.53095e-07, -28.4427, 13.7961, 18.1236 )
transform = Transform( -1.62921e-07, 0.34202, -0.939693, 0, 0.939693, 0.34202, 1, 5.57222e-08, -1.53095e-07, -31.9886, 24.9668, 36.6855 )

[node name="GameOverText" parent="." instance=ExtResource( 8 )]
8 changes: 7 additions & 1 deletion game/scenes/draggable_parts/DraggablePart.gd
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ var delivery_index: int;
var dragged: bool = false

signal select_part(part)
signal removed(deliver_index)

# Called when the node enters the scene tree for the first time.
# warning-ignore:return_value_discarded
Expand Down Expand Up @@ -49,7 +50,11 @@ func onDeselect():
#Stuff to do when added to ghoul.
func onAdd():
self.delivery.on_part_used(delivery_index)
self.queue_free()
remove()

func remove():
emit_signal("removed", delivery_index)
queue_free()

func _on_DragDetector_input_event(_camera, event, _click_position, _click_normal, _shape_idx):
if event is InputEventMouseButton:
Expand All @@ -63,6 +68,7 @@ func _on_DragDetector_mouse_exited():
tooltip.visible = false

func _process(_delta):
global_transform.basis = get_viewport().get_camera().global_transform.basis
if tooltip.visible:
var pos = get_viewport().get_mouse_position()
pos.x -= tooltip.rect_size.x / 2
Expand Down
6 changes: 4 additions & 2 deletions game/scenes/enemies/EnemySpawner.gd
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ var first_in_line = null

func set_next(next):
last_spawn = next
if next == null:
first_in_line = null

# Called when the node enters the scene tree for the first time.
func _ready():
Expand All @@ -33,13 +35,13 @@ func _ready():
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
currentCooldown -= delta
if spawnCount and currentCooldown <= 0:
if spawnCount > 0 and currentCooldown <= 0:
call_deferred("spawn_enemy")
spawnCount -= 1
currentCooldown = spawnCooldown + rng.randf() * spawnVariance

func onSpawneeDeath():
if spawnCount < 1 and last_spawn == null:
if spawnCount <= 0 and last_spawn == null:
self.done = true
combat.onSpawnerDone()

Expand Down
17 changes: 11 additions & 6 deletions game/scenes/enemies/enemy.gd
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
extends Spatial

signal removed

var kind;

Expand Down Expand Up @@ -59,11 +60,15 @@ func set_prev(prev):
func take_damage(damage):
health -= damage
if health <= 0:
prev_in_line.set_next(next_in_line)
if (next_in_line != null):
next_in_line.set_prev(prev_in_line)
self.spawner.onSpawneeDeath()
queue_free()
remove()

func remove():
prev_in_line.set_next(next_in_line)
if next_in_line != null:
next_in_line.set_prev(prev_in_line)
self.spawner.onSpawneeDeath()
emit_signal("removed")
queue_free()

# Called when the node enters the scene tree for the first time.
func _ready():
Expand Down Expand Up @@ -116,5 +121,5 @@ func _process(delta):

if global_transform.origin.z <= 0:
combat.damage_castle(1)
take_damage(health)
remove()

41 changes: 29 additions & 12 deletions game/scenes/ghoul/Ghoul.gd
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ extends Spatial
class_name Ghoul

signal select_ghoul(ghoul)
signal removed

onready var selectionSprite = $SelectionSprite
onready var healthbar = $Healthbar
Expand All @@ -14,6 +15,7 @@ var lane = 0
var column = 0
var enemy_spawner = null
var parts: Array = []
var body

var damage_taken = 0
var attack_cooldown_left = 0.0
Expand Down Expand Up @@ -88,15 +90,23 @@ func take_damage(amount: int, ranged = false):
healthbar.transform = initial_health_transform.scaled(Vector3(health_factor, 1, 1))

var target = null
var is_attacking = false

func invalidate_target():
target = null

func set_target(enemy):
if enemy != target:
target = enemy
target.connect("removed", self, "invalidate_target")

func clear_target():
target.disconnect("removed", self, "invalidate_target")
target = null

func try_attack():
if attack_cooldown_left <= 0.0 && !is_attacking:
if is_instance_valid(enemy_spawner.first_in_line):
target = enemy_spawner.first_in_line
else:
target = null
if target != null and target.has_method("get_global_transform"):
if attack_cooldown_left <= 0.0 && target == null:
if enemy_spawner.first_in_line != null:
set_target(enemy_spawner.first_in_line)
var target_pos = target.global_transform.origin
var d = target_pos - global_transform.origin
if d.length() < MELEE_RANGE:
Expand All @@ -106,14 +116,14 @@ func try_attack():
if attack_cooldown_left < animation_length:
var animation_speed = animation_length/attack_cooldown_left
$AnimationPlayer.play("attack", -1, animation_speed)
is_attacking = true
else:
clear_target()

func deal_damage():
if !is_instance_valid(target):
target = null
if target != null:
target.take_damage(melee)
is_attacking = false
var to_damage = target # Since take_damage may remove
clear_target() # Must be done bevore removal
to_damage.take_damage(melee)

func add_ability(ability):
abilities.append(ability)
Expand All @@ -124,14 +134,21 @@ func add_ability(ability):
if ability.has_method("process_stats_third_pass"):
third_pass_abilities.append(ability)

func add_body(ghoul_body):
body = ghoul_body
add_child(body)

func _process(delta):
body.global_transform.basis = get_viewport().get_camera().global_transform.basis

if !active:
return

if damage_taken >= max_health: # max_health can vary
for ability in abilities:
Abilities.on_ability_removed(ability)
combat.remove_ghoul(lane, column)
emit_signal("removed")
queue_free()
return

Expand Down
33 changes: 22 additions & 11 deletions game/scenes/ghoul_assembly/GhoulAssembly.gd
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func try_add_part(part_name):

# Body
ghoul_body = part
ghoul_in_progress.add_child(ghoul_body)
ghoul_in_progress.add_body(ghoul_body)
ghoul_body.transform.origin.x = -0.7
return true
elif ghoul_in_progress != null:
Expand All @@ -94,27 +94,38 @@ func on_ghoul_deployed():
ghoul_body = null
ghoul_in_progress = null

func _on_part_select_event(part):
if is_instance_valid(selected_part):
selected_part = null

func invalidate_selected_part(_i):
selected_part = null

func set_selected_part(part):
if part != selected_part:
selected_part = part
selected_part.connect("removed", self, "invalidate_selected_part")
selected_part.onSelect()

func clear_selected_part():
selected_part.disconnect("removed", self, "invalidate_selected_part")
selected_part = null


func _on_part_select_event(part):
if selected_part != null:
selected_part.onDeselect()
if selected_part == part:
selected_part = null
clear_selected_part()
else:
selected_part = part
selected_part.onSelect()
set_selected_part(part)
else:
selected_part = part
selected_part.onSelect()
set_selected_part(part)

func _on_AssemblyArea_input_event(_camera, event, _click_position, _click_normal, _shape_idx):
if selected_part != null:
if event is InputEventMouseButton:
if event.button_index == BUTTON_LEFT and event.pressed:
if try_add_part(selected_part.partType):
selected_part.onAdd()
selected_part = null #Clear selection when adding
var part_to_add = selected_part # Since onAdd removes
clear_selected_part() # Must be done bevore removal
part_to_add.onAdd()
if ghoul_body.is_complete():
ghoul_in_progress.init(combat)
54 changes: 29 additions & 25 deletions game/scenes/part_delivery/PartDelivery.gd
Original file line number Diff line number Diff line change
Expand Up @@ -77,32 +77,22 @@ func create_part(partType, index):
var newPart: Spatial = packed_part.instance()
var ghoulAssembly = get_node(ghoulAssemblyPath)
newPart.initialize(newPartSprite, partType, ghoulAssembly, self, index)
get_tree().root.call_deferred("add_child", newPart)
return newPart

func fillDropOffs():
var seeded_parts = []
seeded_parts.append(arm_types[rng.randi() % arm_types.size()])
seeded_parts.append(body_types[rng.randi() % body_types.size()])
seeded_parts.append(head_types[rng.randi() % head_types.size()])
seeded_parts.append(leg_types[rng.randi() % leg_types.size()])
seeded_parts.shuffle()

var i = 0
for dropOff in dropOffs:
add_part_at_dropoff(i, dropOff)
add_part_at_dropoff(i)

i += 1


func add_part_at_dropoff(i: int, dropOff):
func add_part_at_dropoff(i: int):
var has_legs = false
var has_head = false
var has_body = false
var has_arms = false
for slot in slots:
if !is_instance_valid(slot):
slot = null
if slot is DraggablePart and slot != null:
if "ARM" in slot.partType:
has_arms = true
Expand All @@ -115,34 +105,48 @@ func add_part_at_dropoff(i: int, dropOff):

if parts_to_give > 0:
var part_type
if not has_arms:
part_type = arm_types[rng.randi() % arm_types.size()]
if not has_body:
part_type = body_types[rng.randi() % body_types.size()]
elif not has_legs:
part_type = leg_types[rng.randi() % leg_types.size()]
elif not has_body:
part_type = body_types[rng.randi() % body_types.size()]
elif not has_head:
part_type = head_types[rng.randi() % arm_types.size()]
elif not has_arms:
part_type = arm_types[rng.randi() % arm_types.size()]
else:
part_type = packedSpriteScenes.keys()[rng.randi() % packedSpriteScenes.keys().size()]

var newDraggablePart = create_part(part_type, i)
newDraggablePart.global_transform = dropOff.global_transform.translated(Vector3(0, 2.5, 0))
slots[i] = newDraggablePart

set_slot(i, create_part(part_type, i))
parts_to_give -= 1

func invalidate_slot(i: int):
slots[i] = null

func on_part_used(part_index: int):
add_part_at_dropoff(part_index, dropOffs[part_index])
func set_slot(i: int, part):
if part != slots[i]:
slots[i] = part
get_tree().root.add_child(slots[i])
slots[i].global_transform = dropOffs[i].global_transform.translated(Vector3(0, 2.5, 0))
slots[i].global_transform.basis = get_viewport().get_camera().global_transform.basis
slots[i].connect("removed", self, "invalidate_slot")

func clear_slot(i: int):
if slots[i] != null:
get_tree().root.remove_child(slots[i])
slots[i].disconnect("removed", self, "invalidate_slot")
slots[i] = null

func on_part_used(part_index: int):
clear_slot(part_index)
add_part_at_dropoff(part_index)

func clear_current_parts():
var i = 0
for dropOff in dropOffs:
if slots[i] != null and is_instance_valid(slots[i]):
slots[i].queue_free()
slots[i] = null
if slots[i] != null:
var to_remove = slots[i] # Since remove removes
clear_slot(i) # Must be done bevore removal
to_remove.remove()
i += 1

func on_assembly_start():
Expand Down
Loading

0 comments on commit 4caa0b1

Please sign in to comment.