Skip to content

Commit

Permalink
Merge branch 'pr/317'
Browse files Browse the repository at this point in the history
  • Loading branch information
Phazorknight committed Dec 9, 2024
2 parents ea50a26 + 3eec6b3 commit 2b0c891
Show file tree
Hide file tree
Showing 18 changed files with 248 additions and 106 deletions.
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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 35 additions & 0 deletions addons/cogito/Assets/VFX/Impacts/Textures/bulletdecal.png.import
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[remap]

importer="texture"
type="CompressedTexture2D"
uid="uid://csyaglhc6j7nw"
path.s3tc="res://.godot/imported/bulletdecal.png-c1c0e05ecec82b366bb0b0562d0a9f76.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}

[deps]

source_file="res://addons/cogito/Assets/VFX/Impacts/Textures/bulletdecal.png"
dest_files=["res://.godot/imported/bulletdecal.png-c1c0e05ecec82b366bb0b0562d0a9f76.s3tc.ctex"]

[params]

compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0
7 changes: 7 additions & 0 deletions addons/cogito/Assets/VFX/Impacts/bullet_decal.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[gd_scene load_steps=2 format=3 uid="uid://c2ptmtes2fp8c"]

[ext_resource type="Texture2D" uid="uid://csyaglhc6j7nw" path="res://addons/cogito/Assets/VFX/Impacts/Textures/bulletdecal.png" id="1_m4v46"]

[node name="BulletDecal" type="Decal"]
size = Vector3(0.075, 0.075, 0.075)
texture_albedo = ExtResource("1_m4v46")
2 changes: 1 addition & 1 deletion addons/cogito/CogitoObjects/cogito_button.gd
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,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
42 changes: 17 additions & 25 deletions addons/cogito/CogitoObjects/cogito_projectile.gd
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@icon("res://addons/cogito/Assets/Graphics/Editor/Icon_CogitoObject.svg")
@icon("res://addons/cogito/Graphics/Editor/Icon_CogitoObject.svg")
extends CogitoObject
## Derived from CogitoObject, this class handles additional information for projectiles like lifespan, damage, destroy_on_impact. Some of these are inherited from the Wieldable that spawns this projectile.
class_name CogitoProjectile
Expand All @@ -15,10 +15,8 @@ var damage_amount : int = 0
@export var stick_on_impact : bool = false
## Array of Scenes that will get spawned on parent position on death.
@export var spawn_on_death : Array[PackedScene] = []
## This prevents being able to auto pick up projectiles that have just been fired
@export_range(0.1, 3.0, 0.1, "or_greater") var pick_up_delay: float = 0.5
var can_pick_up: bool = false

var Direction

func _ready():
add_to_group("interactable")
Expand All @@ -28,53 +26,45 @@ func _ready():

if lifespan:
lifespan.timeout.connect(on_timeout)

_pick_up_timer()


func _pick_up_timer() -> void:
if lifespan and (lifespan as Timer).wait_time < pick_up_delay:
# The projectile cannot be picked up before it dies, so don't create the timer
return
await get_tree().create_timer(pick_up_delay).timeout
can_pick_up = true


func on_timeout():
die()


## 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
stick_to_object(collider)

if collider.has_signal("damage_received"):
if( !collider.cogito_properties && !cogito_properties): # Case where neither projectile nor the object hit have properties defined.
CogitoGlobals.debug_log(true, "cogito_projectile.gd", "Collider nor projectile have CogitoProperties, damaging as usual.")
deal_damage(collider)
print("Projectile: Collider nor projectile have CogitoProperties, damaging as usual.")
deal_damage(collider,bullet_direction, collision_point)
return

if( collider.cogito_properties && !cogito_properties): # Case were only collider has properties.
CogitoGlobals.debug_log(true, "cogito_projectile.gd", "Collider has CogitoProperties, currently ignoring these and damaging as usual.")
deal_damage(collider)
print("Projectile: Collider has CogitoProperties, currently ignoring these and damaging as usual.")
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:
CogitoProperties.MaterialProperties.SOFT:
# Defining what happens if a soft projectile hits an object with no properties.
CogitoGlobals.debug_log(true, "cogito_projectile.gd", "Soft projectile does no damage per default.")
print("Projectile: Soft projectile does no damage per default.")
if destroy_on_impact:
die()
return

if( collider.cogito_properties && cogito_properties): # Case where both projectile and the object hit have properties defined.
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.
CogitoGlobals.debug_log(true, "cogito_projectile.gd", "Soft object hit, dealing damage.")
deal_damage(collider)
print("Projectile: Soft object hit, dealing damage.")
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 @@ -99,9 +89,11 @@ func stick_to_object(collider: Node):
#self.linear_velocity = Vector3.ZERO
#self.angular_velocity = Vector3.ZERO

func deal_damage(collider: Node):
CogitoGlobals.debug_log(true, "cogito_projectile.gd", self.name + " dealing damage amount " + str(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
59 changes: 16 additions & 43 deletions addons/cogito/CogitoObjects/cogito_switch.gd
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ signal damage_received(damage_value:float)
## Check this if player needs to have an item in the inventory to switch.
@export var needs_item_to_operate : bool
## The item that the player needs to have in their inventory.
@export var required_item_slot : InventorySlotPD
@export var required_item : InventoryItemPD
## Hint that gets displayed if the switch requires an item that the player currently doesn't have.
@export var item_hint : String
## Nodes that will become visible when switch is ON. These will hide again when switch is OFF.
Expand All @@ -37,7 +37,7 @@ var player_interaction_component : PlayerInteractionComponent
var interaction_nodes : Array[Node]
var cogito_properties : CogitoProperties = null

var is_holding_item : bool
@onready var audio_stream_player_3d = $AudioStreamPlayer3D

#endregion

Expand All @@ -47,6 +47,7 @@ func _ready():
add_to_group("save_object_state")
interaction_nodes = find_children("","InteractionComponent",true) #Grabs all attached interaction components

audio_stream_player_3d.stream = switch_sound

if is_on:
switch_on()
Expand All @@ -59,53 +60,26 @@ func find_cogito_properties():
if property_nodes:
cogito_properties = property_nodes[0]


func interact(_player_interaction_component):
player_interaction_component = _player_interaction_component
if !allows_repeated_interaction and is_on:
player_interaction_component.send_hint(null, has_been_used_hint)
return

if !needs_item_to_operate:
switch()
if needs_item_to_operate:
if check_for_item() == true:
switch()
else:
if is_holding_item:
# Logic to for the player to pick up the required item
var inventory = player_interaction_component.get_parent().inventory_data
inventory.pick_up_slot_data(required_item_slot)

CogitoGlobals.debug_log(true,"cogito_switch.gd","Item " + required_item_slot.inventory_item.name + " added to player inventory")
is_holding_item = false

if is_on: switch_off()
else: switch_on()
call_interact_on_objects()

else:
if check_for_item():
Audio.play_sound_3d(switch_sound).global_position = global_position
is_holding_item = true
if is_on: switch_off()
else: switch_on()
call_interact_on_objects()
switch()


func switch():
if needs_item_to_operate and !is_holding_item:
if !check_for_item():
return

Audio.play_sound_3d(switch_sound).global_position = global_position
audio_stream_player_3d.play()

if !is_on:
switch_on()
else:
switch_off()

call_interact_on_objects()


func call_interact_on_objects():
if !objects_call_interact:
return
for nodepath in objects_call_interact:
Expand Down Expand Up @@ -144,20 +118,19 @@ func switch_off():
func check_for_item() -> bool:
var inventory = player_interaction_component.get_parent().inventory_data
for slot_data in inventory.inventory_slots:
if slot_data != null and slot_data.inventory_item == required_item_slot.inventory_item:
player_interaction_component.send_hint(null, required_item_slot.inventory_item.name + " used.") # Sends a hint with the key item name.
inventory.remove_item_from_stack(slot_data)
if slot_data != null and slot_data.inventory_item == required_item:
player_interaction_component.send_hint(null, required_item.name + " used.") # Sends a hint with the key item name.
if slot_data.inventory_item.discard_after_use:
inventory.remove_item_from_stack(slot_data)
# inventory.remove_slot_data(slot_data) (removed on 20240913, leaving line just in case there's bugs.
return true

if item_hint != "":
player_interaction_component.send_hint(null,item_hint) # Sends the key hint with the default hint icon.
return false


func _on_damage_received():
if !needs_item_to_operate:
interact(CogitoSceneManager._current_player_node.player_interaction_component)

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

func set_state():
if is_on:
Expand All @@ -183,7 +156,6 @@ func save():
var state_dict = {
"node_path" : self.get_path(),
"is_on" : is_on,
"is_holding_item": is_holding_item,
"pos_x" : position.x,
"pos_y" : position.y,
"pos_z" : position.z,
Expand All @@ -193,3 +165,4 @@ func save():

}
return state_dict

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
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
6 changes: 2 additions & 4 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 @@ -50,7 +50,6 @@ stream_3/stream = ExtResource("11_jlhg4")
stream_4/stream = ExtResource("12_3m7c4")

[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 @@ -110,8 +109,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
Loading

0 comments on commit 2b0c891

Please sign in to comment.