extends CharacterBody2D class_name Bomb signal body_exited signal exploded enum COMPONENT_TYPE { BREAKBLE, REMOTE_CONTROL, REMOTE_DETONATE, WATER, SALT, } var ExplosionScene = preload("res://Scenes/Entities/Bombs/Explosion.tscn") var power: int = 2 var components: Array[COMPONENT_TYPE] = [] func _ready(): add_to_group("bombs") var collision_area = Utilities.Collision.Area.new(self, $CollisionShape2D) collision_area.connect("collided", Callable(self, "_collide")) collision_area.connect("body_exited", Callable(self, "_body_exited")) add_child(collision_area) self.components = Global.player.bomb_components $AnimatedSprite2D.play() func _process(delta): var collision = move_and_collide(velocity * delta) if collision: velocity = Vector2(0, 0) func explode(): $CollisionShape2D.disabled = true Input.start_joy_vibration(0, 0.5, 0.75, 0.1) # explode on the spot var explosion = self.spawn_explosion(self.global_position) # explode in all directions var directions = [ Vector2.UP, Vector2.RIGHT, Vector2.DOWN, Vector2.LEFT, ] for j in range(directions.size()): var direction = directions[j] for i in range(self.get_power()): var from = Utilities.from_grid_to_position( Utilities.from_position_to_grid(self.global_position) + (direction * i) ) var to = Utilities.from_grid_to_position( Utilities.from_position_to_grid(self.global_position) + (direction * (i + 1)) ) var query = PhysicsRayQueryParameters2D.new() query.set_from(from) query.set_to(to) query.set_collision_mask(explosion.collision_mask) var explosion_intersection = get_world_2d().direct_space_state.intersect_ray(query) if explosion_intersection: var collider = explosion_intersection.collider # call collision function and get collision type var collision_type if collider.is_in_group("player"): collision_type = self._on_collide_group_player() elif collider.is_in_group("enemies"): collision_type = self._on_collide_group_enemies() elif collider.is_in_group("explosions"): collision_type = self._on_collide_group_explosions() elif collider.is_in_group("bombs"): collision_type = self._on_collide_group_bombs() elif collider.is_in_group("breakables"): collision_type = self._on_collide_group_breakables() elif collider.is_in_group("hitables"): collision_type = self._on_collide_group_hitables() else: collision_type = self._on_collide_group_else() # progress loop based on collision type if collision_type == EXPLOSION_COLLISION_TYPE.STOP: break if collision_type == EXPLOSION_COLLISION_TYPE.SPAWN_AND_STOP: self.spawn_explosion(to) break elif collision_type == EXPLOSION_COLLISION_TYPE.SKIP: continue elif collision_type == EXPLOSION_COLLISION_TYPE.CONTINUE: pass elif collision_type == EXPLOSION_COLLISION_TYPE.HIT_STOP: if collider.has_method("hit_by_explosion"): collider.hit_by_explosion() break elif collision_type == EXPLOSION_COLLISION_TYPE.HIT_CONTINUE: if collider.has_method("hit_by_explosion"): collider.hit_by_explosion() continue self.spawn_explosion(to) emit_signal("exploded", self) queue_free() func get_power(): return self.power func stop(): $Timer.stop() func spawn_explosion(spawn_position: Vector2): var explosion = ExplosionScene.instantiate() explosion.position = spawn_position get_tree().get_current_scene().add_child(explosion) return explosion func hit_by_explosion(): call_deferred("explode") func _collide(area: Area2D): if area.is_in_group("explosions"): call_deferred("explode") func _on_Timer_timeout(): self.explode() func _body_exited(body): emit_signal("body_exited", body) ### Explosion Collision ### enum EXPLOSION_COLLISION_TYPE { STOP, SKIP, CONTINUE, SPAWN_AND_STOP, HIT_STOP, HIT_CONTINUE, } func _on_collide_group_player(): return EXPLOSION_COLLISION_TYPE.CONTINUE func _on_collide_group_enemies(): return EXPLOSION_COLLISION_TYPE.CONTINUE func _on_collide_group_explosions(): return EXPLOSION_COLLISION_TYPE.SKIP func _on_collide_group_bombs(): return EXPLOSION_COLLISION_TYPE.HIT_STOP func _on_collide_group_breakables(): if self.components.has(COMPONENT_TYPE.BREAKBLE): return EXPLOSION_COLLISION_TYPE.HIT_CONTINUE return EXPLOSION_COLLISION_TYPE.HIT_STOP func _on_collide_group_hitables(): return EXPLOSION_COLLISION_TYPE.HIT_CONTINUE func _on_collide_group_else(): return EXPLOSION_COLLISION_TYPE.STOP