|  | @@ -7,6 +7,9 @@ class_name Demon
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  @onready var gun_shot_sound: AudioStreamPlayer = $GunShotSound
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +@export var shot_probability: float = 0.5
 | 
	
		
			
				|  |  | +var sp_modifier: float = 0.0
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  var ammo: int = 0
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  enum State {
 | 
	
	
		
			
				|  | @@ -25,6 +28,9 @@ func _process(_delta: float) -> void:
 | 
	
		
			
				|  |  |  	vision_polygon.visible = GlobalInput.visible_vision
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  func _physics_process(_delta: float) -> void:
 | 
	
		
			
				|  |  | +	if state != State.STATE_IDLE:
 | 
	
		
			
				|  |  | +		return
 | 
	
		
			
				|  |  | +		
 | 
	
		
			
				|  |  |  	vision.force_shapecast_update()
 | 
	
		
			
				|  |  |  	if not vision.is_colliding():
 | 
	
		
			
				|  |  |  		return
 | 
	
	
		
			
				|  | @@ -32,7 +38,15 @@ func _physics_process(_delta: float) -> void:
 | 
	
		
			
				|  |  |  	var foe = vision.get_collider(0)
 | 
	
		
			
				|  |  |  	if foe == null || not (foe is Area2D):
 | 
	
		
			
				|  |  |  		return
 | 
	
		
			
				|  |  | -	shoot_at(foe as Area2D)
 | 
	
		
			
				|  |  | +	
 | 
	
		
			
				|  |  | +	var value = randf()
 | 
	
		
			
				|  |  | +	var actual_probability = shot_probability + sp_modifier
 | 
	
		
			
				|  |  | +	if value <= actual_probability:
 | 
	
		
			
				|  |  | +		sp_modifier = 0.0
 | 
	
		
			
				|  |  | +		await shoot_at(foe as Area2D)
 | 
	
		
			
				|  |  | +	else:
 | 
	
		
			
				|  |  | +		sp_modifier += 0.1
 | 
	
		
			
				|  |  | +		print("%s: not shooting (%.2f > %.2f)" % [name, value, actual_probability])
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  func _on_mouse_entered():
 | 
	
		
			
				|  |  |  	if not GlobalInput.is_dragging():
 | 
	
	
		
			
				|  | @@ -71,7 +85,7 @@ func shoot_at(foe: Area2D) -> void:
 | 
	
		
			
				|  |  |  	if state != State.STATE_IDLE:
 | 
	
		
			
				|  |  |  		return
 | 
	
		
			
				|  |  |  	
 | 
	
		
			
				|  |  | -	print("%s: %d/%d" % [name, ammo, Game.max_ammo])
 | 
	
		
			
				|  |  | +	print("%s: Ammo = %d/%d" % [name, ammo, Game.max_ammo])
 | 
	
		
			
				|  |  |  	
 | 
	
		
			
				|  |  |  	if ammo <= 0:
 | 
	
		
			
				|  |  |  		await reload()
 | 
	
	
		
			
				|  | @@ -80,10 +94,27 @@ func shoot_at(foe: Area2D) -> void:
 | 
	
		
			
				|  |  |  		ammo -= 1
 | 
	
		
			
				|  |  |  		gun_shot_sound.play()
 | 
	
		
			
				|  |  |  		sprite.play("shoot")
 | 
	
		
			
				|  |  | -		if foe.has_method("die"):
 | 
	
		
			
				|  |  | -			foe.die()
 | 
	
		
			
				|  |  | +		
 | 
	
		
			
				|  |  | +		var distance: float = clampf((foe.global_position - global_position).length(), 140.0, 250.0)
 | 
	
		
			
				|  |  | +		var distance_percent: float = 1.0 - ((distance - 140.0) / 110.0)
 | 
	
		
			
				|  |  | +		#print(distance_percent)
 | 
	
		
			
				|  |  | +		var speed: float = minf(foe.speed, 100.0)
 | 
	
		
			
				|  |  | +		var speed_percent: float = 1.0 - ((speed - 64.0) / 36.0)
 | 
	
		
			
				|  |  | +		#print(speed_percent)
 | 
	
		
			
				|  |  | +		var base = Game.base_accuracy
 | 
	
		
			
				|  |  | +		var rest = (1.0 - base) / 2.0
 | 
	
		
			
				|  |  | +		var hit_chance: float = Game.base_accuracy + distance_percent * rest + speed_percent * rest
 | 
	
		
			
				|  |  | +		print("%s: Shooting at %s with %.2f hit chance" % [name, foe.name, hit_chance])
 | 
	
		
			
				|  |  | +		
 | 
	
		
			
				|  |  | +		var hit: float = randf()
 | 
	
		
			
				|  |  | +		if hit > hit_chance:
 | 
	
		
			
				|  |  | +			print("%s: missed shot (%.2f > %.2f)" % [name, hit, hit_chance])
 | 
	
		
			
				|  |  |  		else:
 | 
	
		
			
				|  |  | -			foe.queue_free()
 | 
	
		
			
				|  |  | +			if foe.has_method("die"):
 | 
	
		
			
				|  |  | +				foe.die()
 | 
	
		
			
				|  |  | +			else:
 | 
	
		
			
				|  |  | +				foe.queue_free()
 | 
	
		
			
				|  |  | +		
 | 
	
		
			
				|  |  |  		await sprite.animation_finished
 | 
	
		
			
				|  |  |  		if ammo <= 0:
 | 
	
		
			
				|  |  |  			await reload()
 |