Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Damage rework - Hit position & Direction #317

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ COGITO is made by [Philip Drobar](https://www.philipdrobar.com) with help from [
## Principles of this template
The structure of this template always tries to adhere to the following principles:
- **Complete**: When you download COGITO and press play, you get a functioning project out of the box. Game menu, save slot select, options and a playable level are all included.
- **Versatile**: Wether your game is set in the future, the past or the present, use melee, projectile or no weapons at all, have low poly, stylized or realistic graphics, the template will have features for you.
- **Versatile**: Whether your game is set in the future, the past or the present, use melee, projectile or no weapons at all, have low poly, stylized or realistic graphics, the template will have features for you.
- **Modular**: Do not want to use a feature? You will be able to hide it, ignore it or strip it out without breaking COGITO. At the same time, COGITO is designed to be extendable with your own custom features or other add-ons.
- **Approachable**: While there will always be a learning curve, we strive to make COGTIO approachable and intuitive to use, so it doesn't get in your way of making your game.

Expand Down
2 changes: 1 addition & 1 deletion addons/cogito/CogitoObjects/cogito_button.gd
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func press():
object.interact(player_interaction_component)


func _on_damage_received(damage):
func _on_damage_received(_damage,_bullet_direction,_bullet_position):
interact(CogitoSceneManager._current_player_node.player_interaction_component)


Expand Down
19 changes: 13 additions & 6 deletions addons/cogito/CogitoObjects/cogito_projectile.gd
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ var damage_amount : int = 0
## Array of Scenes that will get spawned on parent position on death.
@export var spawn_on_death : Array[PackedScene] = []

var Direction

func _ready():
add_to_group("interactable")
self.add_to_group("Persist") #Adding object to group for persistence
Expand All @@ -31,6 +33,9 @@ func on_timeout():

## Checking collision event for property tags.
func _on_body_entered(collider: Node):
var collision_point = global_transform.origin
var bullet_direction = (collision_point - CogitoSceneManager._current_player_node.get_global_transform().origin).normalized() ##This is hacky TODO needs to be fixed for Multiplayer support

if stick_on_impact:
self.linear_velocity = Vector3.ZERO
self.angular_velocity = Vector3.ZERO
Expand All @@ -39,12 +44,12 @@ func _on_body_entered(collider: Node):
if collider.has_signal("damage_received"):
if( !collider.cogito_properties && !cogito_properties): # Case where neither projectile nor the object hit have properties defined.
print("Projectile: Collider nor projectile have CogitoProperties, damaging as usual.")
deal_damage(collider)
deal_damage(collider,bullet_direction, collision_point)
return

if( collider.cogito_properties && !cogito_properties): # Case were only collider has properties.
print("Projectile: Collider has CogitoProperties, currently ignoring these and damaging as usual.")
deal_damage(collider)
deal_damage(collider,bullet_direction, collision_point)

if( !collider.cogito_properties && cogito_properties): # Case where only the projectile has properties defined.
match cogito_properties.material_properties:
Expand All @@ -59,7 +64,7 @@ func _on_body_entered(collider: Node):
if( cogito_properties.material_properties == CogitoProperties.MaterialProperties.SOFT && collider.cogito_properties.material_properties == CogitoProperties.MaterialProperties.SOFT):
# When both objects are soft, damage the hit object.
print("Projectile: Soft object hit, dealing damage.")
deal_damage(collider)
deal_damage(collider,bullet_direction, collision_point)

# Manually setting the reaction collider and calling reactions on object hit, skipping the reaction threshold time.
collider.cogito_properties.reaction_collider = self
Expand All @@ -84,9 +89,11 @@ func stick_to_object(collider: Node):
#self.linear_velocity = Vector3.ZERO
#self.angular_velocity = Vector3.ZERO

func deal_damage(collider: Node):
print(self.name, ": dealing damage amount ", damage_amount, " on collider ", collider.name)
collider.damage_received.emit(damage_amount)
func deal_damage(collider: Node,bullet_direction,bullet_position):
bullet_direction = Direction
print(self.name, ": dealing damage amount ", damage_amount, " on collider ", collider.name, " at ",bullet_position, " in direction ", Direction )

collider.damage_received.emit(damage_amount,bullet_direction,bullet_position)
if destroy_on_impact:
die()

Expand Down
2 changes: 1 addition & 1 deletion addons/cogito/CogitoObjects/cogito_switch.gd
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ func check_for_item() -> bool:
player_interaction_component.send_hint(null,item_hint) # Sends the key hint with the default hint icon.
return false

func _on_damage_received():
func _on_damage_received(_damage,_bullet_direction,_bullet_position):
interact(CogitoSceneManager._current_player_node.player_interaction_component)

func set_state():
Expand Down
33 changes: 32 additions & 1 deletion addons/cogito/Components/HitboxComponent.gd
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@ extends Node
class_name HitboxComponent

@export var health_attribute : CogitoHealthAttribute
## PackedScene that will get spawned on global hit position
@export var spawn_at_global_collision: PackedScene
## PackedScene that will get spawned on parents local hit position
@export var spawn_at_local_collision: PackedScene
## Apply force to Rigidbodies on hit
@export var apply_force_on_hit : bool
## Multiplier of force applied to rigidbody, if force apply is true
@export var applied_force_multipler : int

@onready var parent = get_parent()

func _ready() -> void:
if get_parent().has_signal("damage_received"):
Expand All @@ -10,6 +20,27 @@ func _ready() -> void:
else:
print("HitboxComponent: Parent ", get_parent().name, " is missing a damage_received() signal.")

func damage(damage_amount:float):

func damage(damage_amount: float, _hit_direction:= Vector3.ZERO, _hit_position:= Vector3.ZERO):

if health_attribute:
health_attribute.subtract(damage_amount)

if spawn_at_global_collision != null:
var spawned_object = spawn_at_global_collision.instantiate()
spawned_object.position = _hit_position
get_tree().current_scene.add_child(spawned_object)

if spawn_at_local_collision != null:
var local_hit_position = parent.to_local(_hit_position)
var spawned_object = spawn_at_local_collision.instantiate()
spawned_object.position = local_hit_position
parent.add_child(spawned_object)

if apply_force_on_hit:
##TODO Handle CharacterBody3D for NPC knockback
if parent is RigidBody3D:
parent.apply_impulse(_hit_direction * damage_amount * applied_force_multipler, _hit_position)
if parent is CharacterBody3D:
parent.apply_knockback(_hit_direction *damage_amount * applied_force_multipler)

2 changes: 2 additions & 0 deletions addons/cogito/Components/HitboxComponent.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@

[node name="HitboxComponent" type="Node"]
script = ExtResource("1_7oy1x")
apply_force_on_hit = true
applied_force_multipler = 2
4 changes: 2 additions & 2 deletions addons/cogito/DemoScenes/COGITO_4_Laboratory.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ volumetric_fog_ambient_inject = 0.1
volumetric_fog_sky_affect = 0.1
volumetric_fog_temporal_reprojection_amount = 0.85

[sub_resource type="Resource" id="Resource_n6ij1"]
[sub_resource type="Resource" id="Resource_uka7b"]
resource_local_to_scene = true
script = ExtResource("4_hlewe")
grid = true
Expand Down Expand Up @@ -897,7 +897,7 @@ environment = SubResource("Environment_obnk3")

[node name="Player" parent="." instance=ExtResource("2_7qwrr")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 5.13854, 0.8, -5.43073)
inventory_data = SubResource("Resource_n6ij1")
inventory_data = SubResource("Resource_uka7b")

[node name="CONNECTOR_TO_LOBBY" type="Node3D" parent="."]

Expand Down
19 changes: 18 additions & 1 deletion addons/cogito/Enemies/cogito_basic_enemy.gd
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,16 @@ var can_play_footstep: bool = true
var wiggle_vector : Vector2 = Vector2.ZERO
var wiggle_index : float = 0.0

var knockback_force: Vector3 = Vector3.ZERO
var knockback_timer: float = 0.0
@export var knockback_duration: float = 0.5
@export var knockback_strength: float = 10.0


func apply_knockback(direction: Vector3):
knockback_force = direction.normalized() * knockback_strength
knockback_timer = knockback_duration


func _enter_tree() -> void:
current_state = EnemyState.IDLE
Expand All @@ -102,7 +112,14 @@ func find_cogito_properties():
func _physics_process(delta: float) -> void:
if attack_cooldown > 0:
attack_cooldown -= delta


if knockback_timer > 0:
knockback_timer -= delta
velocity = knockback_force
knockback_force = lerp(knockback_force, Vector3.ZERO, delta * 5)
move_and_slide()
return

match current_state:
EnemyState.PATROLLING:
handle_patrolling(delta)
Expand Down
7 changes: 2 additions & 5 deletions addons/cogito/Enemies/cogito_basic_enemy.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
[ext_resource type="AudioStream" uid="uid://bd7xfxmsaeu0o" path="res://addons/cogito/Assets/Audio/435666__mirkosukovic__alarm-siren.wav" id="3_7u8yw"]
[ext_resource type="PackedScene" uid="uid://cqgg1nng0vvbh" path="res://addons/cogito/Components/Attributes/HealthAttribute.tscn" id="4_y8n8v"]
[ext_resource type="PackedScene" uid="uid://bc2hryr610vgo" path="res://addons/cogito/PackedScenes/simple_particle_puff.tscn" id="5_ni6ul"]
[ext_resource type="Script" path="res://addons/cogito/Components/HitboxComponent.gd" id="5_qh1ls"]
[ext_resource type="PackedScene" uid="uid://crv3r7dscbxlx" path="res://addons/cogito/Enemies/body/basic_enemy_corpse.tscn" id="7_8vdb4"]
[ext_resource type="PackedScene" uid="uid://cj0yaeh3yg7tu" path="res://addons/cogito/Components/Properties/CogitoProperties.tscn" id="7_15n6t"]
[ext_resource type="PackedScene" uid="uid://k28yrbg3k3pw" path="res://addons/cogito/Components/HitboxComponent.tscn" id="8_lq5js"]
[ext_resource type="AudioStream" uid="uid://up2hfhgq1qx6" path="res://addons/cogito/Assets/Audio/Kenney/Footsteps/footstep00.ogg" id="8_vyi83"]
[ext_resource type="AudioStream" uid="uid://crj07wq4oocwi" path="res://addons/cogito/Assets/Audio/Kenney/Footsteps/footstep01.ogg" id="9_5fsuu"]
[ext_resource type="AudioStream" uid="uid://dewyukd562k37" path="res://addons/cogito/Assets/Audio/Kenney/Footsteps/footstep02.ogg" id="10_ab7fy"]
Expand Down Expand Up @@ -55,7 +55,6 @@ stream_4/stream = ExtResource("12_3m7c4")
stream_4/weight = 1.0

[node name="CogitoEnemy" type="CharacterBody3D"]
motion_mode = 1
script = ExtResource("1_0lcvu")
attack_stagger = 20.0
attack_sound = ExtResource("2_q5685")
Expand Down Expand Up @@ -86,7 +85,6 @@ script = ExtResource("2_6jysp")
detection_ray_cast_3d = NodePath("DetectionRayCast3D")
indicator_light = NodePath("../Mesh_Body/Mesh_Face/IndicatorLight")
detection_area = NodePath("DetectionArea3D")
spot_time = 2.0
alarm_sound = ExtResource("3_7u8yw")
indicator_mesh = NodePath("../Mesh_Body/Mesh_Face")

Expand Down Expand Up @@ -116,8 +114,7 @@ spawn_on_death = Array[PackedScene]([ExtResource("5_ni6ul"), ExtResource("7_8vdb
value_max = 5.0
value_start = 5.0

[node name="HitboxComponent" type="Node" parent="." node_paths=PackedStringArray("health_attribute")]
script = ExtResource("5_qh1ls")
[node name="HitboxComponent" parent="." node_paths=PackedStringArray("health_attribute") instance=ExtResource("8_lq5js")]
health_attribute = NodePath("../HealthAttribute")

[node name="CogitoProperties" parent="." instance=ExtResource("7_15n6t")]
Expand Down
5 changes: 3 additions & 2 deletions addons/cogito/PackedScenes/Pickups/pickup_laser_rifle.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,12 @@ size = Vector3(0.0973389, 0.0952759, 0.815624)
[sub_resource type="BoxShape3D" id="BoxShape3D_5bhcv"]
size = Vector3(0.0973389, 0.0457916, 0.443713)

[sub_resource type="Resource" id="Resource_4kc11"]
[sub_resource type="Resource" id="Resource_fmssf"]
resource_local_to_scene = true
script = ExtResource("3_iw0du")
inventory_item = ExtResource("3_auoh1")
quantity = 1
origin_index = -1

[node name="Pickup_LaserRifle" type="RigidBody3D"]
collision_layer = 3
Expand All @@ -166,4 +167,4 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.00152874, 0.187482, 0.03864
shape = SubResource("BoxShape3D_5bhcv")

[node name="PickupComponent" parent="." instance=ExtResource("2_3uch0")]
slot_data = SubResource("Resource_4kc11")
slot_data = SubResource("Resource_fmssf")
4 changes: 2 additions & 2 deletions addons/cogito/PackedScenes/projectile_pistol.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ rings = 1
height = 0.25
radius = 0.05

[sub_resource type="Resource" id="Resource_s1k6p"]
[sub_resource type="Resource" id="Resource_w3sph"]
resource_local_to_scene = true
script = ExtResource("4_tbkmk")
inventory_item = ExtResource("3_7etap")
Expand Down Expand Up @@ -62,7 +62,7 @@ wait_time = 30.0
autostart = true

[node name="PickupComponent" parent="." instance=ExtResource("4_acy7b")]
slot_data = SubResource("Resource_s1k6p")
slot_data = SubResource("Resource_w3sph")

[node name="CogitoProperties" parent="." instance=ExtResource("5_6jfy1")]
material_properties = 1
Expand Down
3 changes: 2 additions & 1 deletion addons/cogito/Wieldables/laser_rifle.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

[ext_resource type="Script" path="res://addons/cogito/Wieldables/wieldable_laser_rifle.gd" id="1_2rut3"]
[ext_resource type="AudioStream" uid="uid://clsajk36s7luk" path="res://addons/cogito/Assets/Audio/Kenney/error_004.ogg" id="2_f7ale"]
[ext_resource type="Resource" uid="uid://txiu5yxexevm" path="res://addons/cogito/InventoryPD/Items/Cogito_LaserRifle.tres" id="2_i0fx0"]
[ext_resource type="PackedScene" uid="uid://dnauxhdncgngx" path="res://addons/cogito/PackedScenes/laser_ray.tscn" id="2_ic084"]
[ext_resource type="PackedScene" uid="uid://bc2hryr610vgo" path="res://addons/cogito/PackedScenes/simple_particle_puff.tscn" id="3_aueyu"]
[ext_resource type="AnimationLibrary" uid="uid://c1du0rcgmr542" path="res://addons/cogito/Wieldables/Animations/Wieldable_LaserRifle.res" id="3_fjq23"]
[ext_resource type="Script" path="res://addons/cogito/Assets/Shader/ViewmodelSpace.gd" id="5_fa3wp"]

Expand Down Expand Up @@ -269,6 +269,7 @@ script = ExtResource("1_2rut3")
laser_ray_prefab = ExtResource("2_ic084")
ray_lifespan = 3.0
default_position = Vector3(0.329, -0.264, -0.535)
collision_decal = ExtResource("3_aueyu")
sound_primary_use = ExtResource("2_f7ale")
wieldable_mesh = NodePath("LaserRifleMesh")
anim_equip = "LaserRifle/equip"
Expand Down
16 changes: 13 additions & 3 deletions addons/cogito/Wieldables/wieldable_laser_rifle.gd
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ extends CogitoWieldable
@export var ads_fov = 65
## Default position for tweening from ADS
@export var default_position : Vector3
## Scene that spawns when a bullet of the weapon collides with anything
@export var collision_decal : PackedScene

@export_group("Audio")
@export var sound_primary_use : AudioStream
Expand Down Expand Up @@ -103,12 +105,20 @@ func hit_scan_collision(collision_point:Vector3):
spawn_node.add_child(instantiated_ray)

if bullet_collision:
hit_scan_damage(bullet_collision.collider)
hit_scan_damage(bullet_collision.collider, bullet_direction, bullet_collision.position)
hit_scan_decal(bullet_collision)


func hit_scan_damage(collider):
func hit_scan_damage(collider, bullet_direction, bullet_position):
if collider.has_signal("damage_received"):
collider.damage_received.emit(item_reference.wieldable_damage)
collider.damage_received.emit(item_reference.wieldable_damage,bullet_direction,bullet_position)


func hit_scan_decal(bullet_collision):
var hit_indicator = collision_decal.instantiate()
var world = get_tree().get_root().get_child(0)
world.add_child(hit_indicator)
hit_indicator.global_translate(bullet_collision.position)


# Function called when wieldable reload is attempted
Expand Down
29 changes: 27 additions & 2 deletions addons/cogito/Wieldables/wieldable_pickaxe.gd
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,25 @@ extends CogitoWieldable
@export var damage_area : Area3D
@export var uses_stamina : bool = false
@export var stamina_cost : int = 4
##Collision hit can be defined using Camera-Collider raycast, or Hitbox-Collider raycast. Camera-Collider is more reliable but less accurate, Hitbox-collider is more accurate but less reliable
@export var use_camera_collision : bool

@export_group("Audio")
@export var swing_sound : AudioStream

var trigger_has_been_pressed : bool = false
var player_stamina : CogitoAttribute = null


func _ready():
if wieldable_mesh:
wieldable_mesh.hide()

damage_area.body_entered.connect(_on_body_entered)

if uses_stamina:
player_stamina = grab_player_stamina_attribute()



func grab_player_stamina_attribute() -> CogitoAttribute:
Expand Down Expand Up @@ -53,4 +57,25 @@ func action_primary(_passed_item_reference:InventoryItemPD, _is_released: bool):

func _on_body_entered(collider):
if collider.has_signal("damage_received"):
collider.damage_received.emit(item_reference.wieldable_damage)
var player = player_interaction_component.get_parent()
var hit_position : Vector3
var bullet_direction : Vector3

if use_camera_collision:
#Camera-Collider raycast
hit_position = player_interaction_component.Get_Camera_Collision()
bullet_direction = (hit_position - player.get_global_transform().origin).normalized()
else:
#Hitbox-Collider raycast
var space_state = damage_area.get_world_3d().direct_space_state
var hitbox_origin = damage_area.global_transform.origin
var ray_params = PhysicsRayQueryParameters3D.new()
ray_params.from = hitbox_origin
ray_params.to = collider.global_transform.origin
var result = space_state.intersect_ray(ray_params)
if result.size() > 0:
hit_position = result.position
bullet_direction = (hit_position - hitbox_origin).normalized()

collider.damage_received.emit(item_reference.wieldable_damage, bullet_direction, hit_position)

1 change: 1 addition & 0 deletions addons/cogito/Wieldables/wieldable_toy_pistol.gd
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ func action_primary(_passed_item_reference : InventoryItemPD, _is_released: bool
Projectile.global_transform.basis = bullet_point.global_transform.basis
Projectile.damage_amount = _passed_item_reference.wieldable_damage
Projectile.set_linear_velocity(Direction * projectile_velocity)
Projectile.Direction = Direction
Projectile.reparent(get_tree().get_current_scene())


Expand Down