Compare commits

...

10 Commits

Author SHA1 Message Date
e50e2c9918 removing .net config file
All checks were successful
Create tag and build when new code gets to main / BumpTag (push) Successful in 24s
Create tag and build when new code gets to main / Export (push) Successful in 14m44s
2026-01-25 10:02:11 +01:00
5cb2d2beb5 removed blocking condition in ci 2026-01-25 10:02:05 +01:00
cb2d7e35ce dev branch workflow 2026-01-25 10:01:59 +01:00
58bb1d9ca5 trying to fix CI
Some checks failed
Create tag and build when new code gets to main / BumpTag (push) Successful in 23s
Create tag and build when new code gets to main / Export (push) Failing after 1m43s
2026-01-25 00:24:51 +01:00
cf7591b413 this is so easy to develop there must be a catch
Some checks failed
Create tag and build when new code gets to main / BumpTag (push) Successful in 26s
Create tag and build when new code gets to main / Export (push) Failing after 1m55s
2026-01-25 00:16:16 +01:00
92cc4f0264 sooooo coded a feature first try? weird
Some checks failed
Create tag and build when new code gets to main / BumpTag (push) Successful in 25s
Create tag and build when new code gets to main / Export (push) Failing after 1m48s
2026-01-24 23:29:22 +01:00
18c8b741dd can plant weapon in targetables, dash towards it, jump in the air.
Some checks failed
Create tag and build when new code gets to main / BumpTag (push) Successful in 28s
Create tag and build when new code gets to main / Export (push) Failing after 1m47s
2026-01-24 15:22:16 +01:00
b84b7e4dd5 aim dashing through targetable entities now possible 2026-01-24 13:49:16 +01:00
4d419b9010 basic healthbars for enemies 2026-01-23 13:31:11 +01:00
8b2bf3e32e fixed a going through wall issue 2026-01-21 17:31:24 +01:00
22 changed files with 507 additions and 179 deletions

View File

@@ -0,0 +1,39 @@
name: Create tag and build when new code gets to main
run-name: Create tag and build when new code gets to main
on:
push:
branches:
- '**' # matches every branch
- '!main' # except main
- '!release/*' # except release branches
tags-ignore:
- "**"
env:
GAME_NAME: MovementTests
ITCHIO_USERNAME: Minimata
ITCHIO_GAMEID: MovementTests
jobs:
Export:
runs-on: ubuntu-latest
container:
image: barichello/godot-ci:mono-4.5
steps:
- name: Install node, curl and zip
run: |
apt update && apt -y install curl zip nodejs
- name: Checkout with LFS
uses: https://git.game-dev.space/minimata/checkout-with-lfs.git@main
with:
checkout-version: 3
- name: Import resources and build solution
run: |
godot --headless --editor --build-solutions --quit --import --path $PWD
- name: Build Windows
run: |
mkdir -v -p build/windows
godot --headless --verbose --build-solutions --export-release "Windows Desktop" build/windows/${{ env.GAME_NAME }}.exe

View File

@@ -1,7 +1,8 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AAction_00601_002Ecs_002Fl_003AC_0021_003FUsers_003FMinimata_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F7c0f83388bfc4d2c9d09befcec9dd79bc90908_003Fb8_003F4d300c4d_003FAction_00601_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AAction_00601_002Ecs_002Fl_003AC_0021_003FUsers_003FMinimata_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F7c0f83388bfc4d2c9d09befcec9dd79bc90908_003Fb8_003F4d300c4d_003FAction_00601_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACharacterBody3D_002Ecs_002Fl_003AC_0021_003FUsers_003FMinimata_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003Fe56b84c3fa498fb86fc1eba376f62f482127e3fe80415c5fb2acde2bf6d89793_003FCharacterBody3D_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AAction_00602_002Ecs_002Fl_003AC_0021_003FUsers_003FMinimata_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F7c0f83388bfc4d2c9d09befcec9dd79bc90908_003F87_003Fded27e2d_003FAction_00602_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AEnemy_005FScriptMethods_002Egenerated_002Ecs_002Fl_003AC_0021_003FUsers_003FMinimata_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003F8e71dc81611862c01a2cb998a1f327de14747655_003FEnemy_005FScriptMethods_002Egenerated_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AEnemy_005FScriptMethods_002Egenerated_002Ecs_002Fl_003AC_0021_003FUsers_003FMinimata_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003F8e71dc81611862c01a2cb998a1f327de14747655_003FEnemy_005FScriptMethods_002Egenerated_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANode_002Ecs_002Fl_003AC_0021_003FUsers_003FMinimata_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003F716d154fef5cbe863cd637bd32beda6e3cec5f12e8fed2dc5b2d8149a0d558ab_003FNode_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANode_002Ecs_002Fl_003AC_0021_003FUsers_003FMinimata_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003Fdf73a4db74df89d59655c5fb6326406f47fbfa9af1fa81518fe0a07c49d34133_003FNode_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANode_002Ecs_002Fl_003AC_0021_003FUsers_003FMinimata_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003Fdf73a4db74df89d59655c5fb6326406f47fbfa9af1fa81518fe0a07c49d34133_003FNode_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASceneTree_002Ecs_002Fl_003AC_0021_003FUsers_003FMinimata_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003F8d6960554e939a669841b1ece03d27df4ab42f92bb80be3767eaec8cdaccf84b_003FSceneTree_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASceneTree_002Ecs_002Fl_003AC_0021_003FUsers_003FMinimata_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003F8d6960554e939a669841b1ece03d27df4ab42f92bb80be3767eaec8cdaccf84b_003FSceneTree_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:Boolean x:Key="/Default/UserDictionary/Words/=floorplane/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary> <s:Boolean x:Key="/Default/UserDictionary/Words/=floorplane/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

BIN
assets/ui/white-square-100px.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@@ -0,0 +1,42 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://vpcxswwn1mt6"
path.s3tc="res://.godot/imported/white-square-100px.png-45d5a1e60348740b59c87085347e502a.s3tc.ctex"
path.etc2="res://.godot/imported/white-square-100px.png-45d5a1e60348740b59c87085347e502a.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
}
[deps]
source_file="res://assets/ui/white-square-100px.png"
dest_files=["res://.godot/imported/white-square-100px.png-45d5a1e60348740b59c87085347e502a.s3tc.ctex", "res://.godot/imported/white-square-100px.png-45d5a1e60348740b59c87085347e502a.etc2.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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

View File

@@ -5,7 +5,7 @@ using Movementtests.interfaces;
[GlobalClass] [GlobalClass]
public partial class CHealth : Node, IHealthable public partial class CHealth : Node, IHealthable
{ {
public event Action<IHealthable, float> HealthChanged; public event Action<IHealthable, HealthChangedRecord> HealthChanged;
public event Action<IHealthable> HealthDepleted; public event Action<IHealthable> HealthDepleted;
[Export] [Export]
@@ -18,15 +18,18 @@ public partial class CHealth : Node, IHealthable
CurrentHealth = RHealth.StartingHealth; CurrentHealth = RHealth.StartingHealth;
} }
public void ReduceHealth(IDamageable source, DamageRecord damageRecord) public HealthChangedRecord ReduceHealth(IDamageable source, DamageRecord damageRecord)
{ {
var previousHealth = CurrentHealth;
CurrentHealth -= damageRecord.Damage.DamageDealt; CurrentHealth -= damageRecord.Damage.DamageDealt;
HealthChanged?.Invoke(this, CurrentHealth); var record = new HealthChangedRecord(CurrentHealth, previousHealth, RHealth.StartingHealth);
HealthChanged?.Invoke(this, record);
if (CurrentHealth <= 0) if (CurrentHealth <= 0)
{ {
CurrentHealth = 0; CurrentHealth = 0;
HealthDepleted?.Invoke(this); HealthDepleted?.Invoke(this);
} }
return record;
} }
} }

View File

@@ -0,0 +1,26 @@
using Godot;
using System;
using Movementtests.interfaces;
[GlobalClass]
public partial class CHealthbar : Node3D
{
private Sprite3D _currentHealth;
private float _initialXScale;
public override void _Ready()
{
Visible = false;
_currentHealth = GetNode<Sprite3D>("Health");
_initialXScale = _currentHealth.Scale.X;
}
public void OnHealthChanged(HealthChangedRecord healthChanged)
{
if (healthChanged.MaxHealth == 0) return;
Visible = true;
var healthPercentage = healthChanged.CurrentHealth / healthChanged.MaxHealth;
_currentHealth.Scale = new Vector3(_initialXScale * healthPercentage, _currentHealth.Scale.Y, _currentHealth.Scale.Z);
}
}

View File

@@ -0,0 +1 @@
uid://dve6vg6yvg4y8

View File

@@ -0,0 +1,27 @@
[gd_scene load_steps=3 format=3 uid="uid://bwx2um43k0ou4"]
[ext_resource type="Texture2D" uid="uid://vpcxswwn1mt6" path="res://assets/ui/white-square-100px.png" id="1_jlvej"]
[ext_resource type="Script" uid="uid://dve6vg6yvg4y8" path="res://components/health/CHealthbar.cs" id="1_w5itk"]
[node name="CHealthBar" type="Node3D"]
script = ExtResource("1_w5itk")
[node name="Bar" type="Sprite3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 0.1, 0, 0, 0, 1, 0, 0, 0)
cast_shadow = 0
billboard = 1
transparent = false
double_sided = false
no_depth_test = true
texture = ExtResource("1_jlvej")
[node name="Health" type="Sprite3D" parent="."]
transform = Transform3D(0.99, 0, 0, 0, 0.09, 0, 0, 0, 1, 0, 0, 0)
cast_shadow = 0
modulate = Color(0.7191989, 0.19340843, 1.92523e-07, 1)
billboard = 1
transparent = false
double_sided = false
no_depth_test = true
render_priority = 10
texture = ExtResource("1_jlvej")

View File

@@ -1,7 +0,0 @@
{
"sdk": {
"version": "9.0.0",
"rollForward": "latestMajor",
"allowPrerelease": true
}
}

View File

@@ -8,6 +8,7 @@ public record DamageRecord(Node3D Source, RDamage Damage);
public interface IDamageable public interface IDamageable
{ {
event Action<IDamageable, DamageRecord> DamageTaken; event Action<IDamageable, DamageRecord> DamageTaken;
DamageRecord TakeDamage(DamageRecord damageRecord); DamageRecord TakeDamage(DamageRecord damageRecord);
DamageRecord ComputeDamage(DamageRecord damageRecord); DamageRecord ComputeDamage(DamageRecord damageRecord);
} }

View File

@@ -3,14 +3,16 @@ using Godot;
namespace Movementtests.interfaces; namespace Movementtests.interfaces;
public record HealthChangedRecord(float CurrentHealth, float PreviousHealth, float MaxHealth);
public interface IHealthable public interface IHealthable
{ {
event Action<IHealthable, float> HealthChanged; event Action<IHealthable, HealthChangedRecord> HealthChanged;
event Action<IHealthable> HealthDepleted; event Action<IHealthable> HealthDepleted;
[Export] RHealth RHealth { get; set; } [Export] RHealth RHealth { get; set; }
float CurrentHealth { get; set; } float CurrentHealth { get; set; }
void ReduceHealth(IDamageable source, DamageRecord damageRecord); HealthChangedRecord ReduceHealth(IDamageable source, DamageRecord damageRecord);
} }

View File

@@ -1,13 +1,12 @@
[gd_scene load_steps=25 format=3 uid="uid://q7uc1h2jpbd2"] [gd_scene load_steps=21 format=3 uid="uid://q7uc1h2jpbd2"]
[ext_resource type="PackedScene" uid="uid://bei4nhkf8lwdo" path="res://player_controller/PlayerController.tscn" id="1_62kkh"] [ext_resource type="PackedScene" uid="uid://bei4nhkf8lwdo" path="res://player_controller/PlayerController.tscn" id="1_62kkh"]
[ext_resource type="Material" uid="uid://31aulub2nqov" path="res://assets/greybox/m_greybox.tres" id="2_3uydm"] [ext_resource type="Material" uid="uid://31aulub2nqov" path="res://assets/greybox/m_greybox.tres" id="2_3uydm"]
[ext_resource type="Script" uid="uid://jitubgv6judn" path="res://components/damage/RDamage.cs" id="2_5fa36"]
[ext_resource type="PackedScene" uid="uid://dxt0e2ugmttqq" path="res://scenes/enemies/grounded_enemy/grounded_enemy.tscn" id="3_3uydm"] [ext_resource type="PackedScene" uid="uid://dxt0e2ugmttqq" path="res://scenes/enemies/grounded_enemy/grounded_enemy.tscn" id="3_3uydm"]
[ext_resource type="Script" uid="uid://b4cwruitopcee" path="res://components/health/RDeathEffect.cs" id="5_7m3bq"]
[ext_resource type="PackedScene" uid="uid://cmlud1hwkd6sv" path="res://scenes/enemies/flying_enemy/flying_enemy.tscn" id="5_8fd2t"] [ext_resource type="PackedScene" uid="uid://cmlud1hwkd6sv" path="res://scenes/enemies/flying_enemy/flying_enemy.tscn" id="5_8fd2t"]
[ext_resource type="Script" uid="uid://b44cse62qru7j" path="res://components/knockback/RKnockback.cs" id="6_1hrkh"] [ext_resource type="Script" uid="uid://dtpxijlnb2c5" path="res://components/movement/RMovement.cs" id="5_ybosk"]
[ext_resource type="PackedScene" uid="uid://c305mfrtumcyq" path="res://scenes/spawners/spawner.tscn" id="6_7m3bq"] [ext_resource type="PackedScene" uid="uid://c305mfrtumcyq" path="res://scenes/spawners/spawner.tscn" id="6_7m3bq"]
[ext_resource type="Script" uid="uid://dtpxijlnb2c5" path="res://components/movement/RMovement.cs" id="6_ybosk"]
[ext_resource type="Resource" uid="uid://bqq6uukbdfysr" path="res://scenes/enemies/grounded_enemy/grounded_enemy_movement.tres" id="7_caohq"] [ext_resource type="Resource" uid="uid://bqq6uukbdfysr" path="res://scenes/enemies/grounded_enemy/grounded_enemy_movement.tres" id="7_caohq"]
[ext_resource type="Script" uid="uid://baiapod3csndf" path="res://components/health/RHealth.cs" id="9_2e4ci"] [ext_resource type="Script" uid="uid://baiapod3csndf" path="res://components/health/RHealth.cs" id="9_2e4ci"]
[ext_resource type="Resource" uid="uid://otfc2snh8umc" path="res://scenes/enemies/grounded_enemy/grounded_enemy_damage.tres" id="9_dmw1t"] [ext_resource type="Resource" uid="uid://otfc2snh8umc" path="res://scenes/enemies/grounded_enemy/grounded_enemy_damage.tres" id="9_dmw1t"]
@@ -16,6 +15,11 @@
[ext_resource type="Resource" uid="uid://dg1xbjhyhgnnk" path="res://scenes/enemies/flying_enemy/flying_enemy_health.tres" id="11_2e4ci"] [ext_resource type="Resource" uid="uid://dg1xbjhyhgnnk" path="res://scenes/enemies/flying_enemy/flying_enemy_health.tres" id="11_2e4ci"]
[ext_resource type="PackedScene" uid="uid://qup00a7x2sji" path="res://scenes/FixedDashTarget/fixed_dashthrough_target.tscn" id="15_5fa36"] [ext_resource type="PackedScene" uid="uid://qup00a7x2sji" path="res://scenes/FixedDashTarget/fixed_dashthrough_target.tscn" id="15_5fa36"]
[sub_resource type="Resource" id="Resource_1hrkh"]
script = ExtResource("2_5fa36")
DamageDealt = 1.0
metadata/_custom_type_script = "uid://jitubgv6judn"
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_0xm2m"] [sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_0xm2m"]
sky_horizon_color = Color(0.662243, 0.671743, 0.686743, 1) sky_horizon_color = Color(0.662243, 0.671743, 0.686743, 1)
ground_horizon_color = Color(0.662243, 0.671743, 0.686743, 1) ground_horizon_color = Color(0.662243, 0.671743, 0.686743, 1)
@@ -38,27 +42,9 @@ ssil_radius = 8.4
sdfgi_use_occlusion = true sdfgi_use_occlusion = true
glow_enabled = true glow_enabled = true
[sub_resource type="Resource" id="Resource_sysok"]
script = ExtResource("5_7m3bq")
metadata/_custom_type_script = "uid://b4cwruitopcee"
[sub_resource type="Resource" id="Resource_q21h6"]
script = ExtResource("6_1hrkh")
metadata/_custom_type_script = "uid://b44cse62qru7j"
[sub_resource type="Resource" id="Resource_5fa36"] [sub_resource type="Resource" id="Resource_5fa36"]
script = ExtResource("6_ybosk") script = ExtResource("5_ybosk")
GravityModifier = 1.0 GravityModifier = 5.0
metadata/_custom_type_script = "uid://dtpxijlnb2c5"
[sub_resource type="Resource" id="Resource_blhrq"]
script = ExtResource("6_ybosk")
GravityModifier = 1.0
metadata/_custom_type_script = "uid://dtpxijlnb2c5"
[sub_resource type="Resource" id="Resource_1hrkh"]
script = ExtResource("6_ybosk")
TargetHeight = 5.0
metadata/_custom_type_script = "uid://dtpxijlnb2c5" metadata/_custom_type_script = "uid://dtpxijlnb2c5"
[sub_resource type="Resource" id="Resource_ybosk"] [sub_resource type="Resource" id="Resource_ybosk"]
@@ -71,6 +57,7 @@ metadata/_custom_type_script = "uid://baiapod3csndf"
[node name="Player" parent="." instance=ExtResource("1_62kkh")] [node name="Player" parent="." instance=ExtResource("1_62kkh")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 7.5) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 7.5)
TutorialDone = true TutorialDone = true
RDamage = SubResource("Resource_1hrkh")
[node name="WorldEnvironment" type="WorldEnvironment" parent="."] [node name="WorldEnvironment" type="WorldEnvironment" parent="."]
environment = SubResource("Environment_1bvp3") environment = SubResource("Environment_1bvp3")
@@ -108,6 +95,12 @@ use_collision = true
size = Vector3(6.5, 4, 17) size = Vector3(6.5, 4, 17)
material = ExtResource("2_3uydm") material = ExtResource("2_3uydm")
[node name="CSGBox3D10" type="CSGBox3D" parent="Greybox"]
transform = Transform3D(1, 0, 0, 0, 0.9659258, 0.25881904, 0, -0.25881904, 0.9659258, 13.653999, 0.9705714, -5.336278)
use_collision = true
size = Vector3(6.5, 4, 24.5)
material = ExtResource("2_3uydm")
[node name="CSGBox3D8" type="CSGBox3D" parent="Greybox"] [node name="CSGBox3D8" type="CSGBox3D" parent="Greybox"]
transform = Transform3D(0.81915206, 0, 0.57357645, 0, 1, 0, -0.57357645, 0, 0.81915206, -7.3460007, 0, -3.9585) transform = Transform3D(0.81915206, 0, 0.57357645, 0, 1, 0, -0.57357645, 0, 0.81915206, -7.3460007, 0, -3.9585)
use_collision = true use_collision = true
@@ -138,34 +131,33 @@ use_collision = true
size = Vector3(6.5, 11, 5.5) size = Vector3(6.5, 11, 5.5)
material = ExtResource("2_3uydm") material = ExtResource("2_3uydm")
[node name="FixedDashthroughTarget" parent="." instance=ExtResource("15_5fa36")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 9, 3.5, 2.5)
[node name="Enemy" parent="." node_paths=PackedStringArray("Target") instance=ExtResource("3_3uydm")] [node name="Enemy" parent="." node_paths=PackedStringArray("Target") instance=ExtResource("3_3uydm")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -16.83681) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 13.5, 2.5, -8.336809)
Target = NodePath("../Player") Target = NodePath("../Player")
DeathEffects = Array[Object]([SubResource("Resource_sysok")])
RKnockback = SubResource("Resource_q21h6")
RMovement = SubResource("Resource_5fa36") RMovement = SubResource("Resource_5fa36")
[node name="Enemy2" parent="." node_paths=PackedStringArray("Target") instance=ExtResource("3_3uydm")] [node name="Enemy2" parent="." node_paths=PackedStringArray("Target") instance=ExtResource("3_3uydm")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3, 0, -16.83681) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 13, 0, -17.33681)
Target = NodePath("../Player") Target = NodePath("../Player")
RKnockback = SubResource("Resource_q21h6") RMovement = SubResource("Resource_5fa36")
RMovement = SubResource("Resource_blhrq")
[node name="Enemy3" parent="." node_paths=PackedStringArray("Target") instance=ExtResource("3_3uydm")] [node name="Enemy3" parent="." node_paths=PackedStringArray("Target") instance=ExtResource("3_3uydm")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 7, 0, 0.16319084) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 14, 4, -3.3368092)
Target = NodePath("../Player") Target = NodePath("../Player")
RKnockback = SubResource("Resource_q21h6")
RMovement = SubResource("Resource_5fa36") RMovement = SubResource("Resource_5fa36")
[node name="FlyingEnemy" parent="." node_paths=PackedStringArray("Target") instance=ExtResource("5_8fd2t")] [node name="FlyingEnemy" parent="." node_paths=PackedStringArray("Target") instance=ExtResource("5_8fd2t")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8, 7, -16) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8, 7, -16)
Target = NodePath("../Player") Target = NodePath("../Player")
RMovement = SubResource("Resource_1hrkh") RMovement = SubResource("Resource_5fa36")
[node name="FlyingEnemy2" parent="." node_paths=PackedStringArray("Target") instance=ExtResource("5_8fd2t")] [node name="FlyingEnemy2" parent="." node_paths=PackedStringArray("Target") instance=ExtResource("5_8fd2t")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 10, 7, -16) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 10, 7, -16)
Target = NodePath("../Player") Target = NodePath("../Player")
RMovement = SubResource("Resource_1hrkh") RMovement = SubResource("Resource_5fa36")
[node name="GroundedSpawner" parent="." node_paths=PackedStringArray("Target") instance=ExtResource("6_7m3bq")] [node name="GroundedSpawner" parent="." node_paths=PackedStringArray("Target") instance=ExtResource("6_7m3bq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 12, 2.5, -15) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 12, 2.5, -15)
@@ -184,6 +176,3 @@ HealthInputs = ExtResource("11_2e4ci")
DamageInputs = ExtResource("9_gp7s3") DamageInputs = ExtResource("9_gp7s3")
Target = NodePath("../Player") Target = NodePath("../Player")
IsActiveOnStart = false IsActiveOnStart = false
[node name="FixedDashthroughTarget" parent="." instance=ExtResource("15_5fa36")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.5, 3.5, 0)

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=64 format=3 uid="uid://bei4nhkf8lwdo"] [gd_scene load_steps=66 format=3 uid="uid://bei4nhkf8lwdo"]
[ext_resource type="Script" uid="uid://bbbrf5ckydfna" path="res://player_controller/Scripts/PlayerController.cs" id="1_poq2x"] [ext_resource type="Script" uid="uid://bbbrf5ckydfna" path="res://player_controller/Scripts/PlayerController.cs" id="1_poq2x"]
[ext_resource type="PackedScene" uid="uid://cf3rrgr1imvv4" path="res://scenes/path/path.tscn" id="2_6lejt"] [ext_resource type="PackedScene" uid="uid://cf3rrgr1imvv4" path="res://scenes/path/path.tscn" id="2_6lejt"]
@@ -54,7 +54,7 @@
[sub_resource type="Resource" id="Resource_cb2lu"] [sub_resource type="Resource" id="Resource_cb2lu"]
script = ExtResource("2_x835q") script = ExtResource("2_x835q")
DamageDealt = 3.0 DamageDealt = 30.0
metadata/_custom_type_script = "uid://jitubgv6judn" metadata/_custom_type_script = "uid://jitubgv6judn"
[sub_resource type="Resource" id="Resource_abfq8"] [sub_resource type="Resource" id="Resource_abfq8"]
@@ -86,6 +86,9 @@ top_radius = 0.2
bottom_radius = 0.2 bottom_radius = 0.2
height = 1.0 height = 1.0
[sub_resource type="SphereShape3D" id="SphereShape3D_abfq8"]
radius = 2.0
[sub_resource type="SphereShape3D" id="SphereShape3D_cmijs"] [sub_resource type="SphereShape3D" id="SphereShape3D_cmijs"]
radius = 1.0 radius = 1.0
@@ -96,6 +99,9 @@ height = 3.5
[sub_resource type="SphereShape3D" id="SphereShape3D_nob5r"] [sub_resource type="SphereShape3D" id="SphereShape3D_nob5r"]
radius = 0.4 radius = 0.4
[sub_resource type="SphereShape3D" id="SphereShape3D_ue7xq"]
radius = 1.5
[sub_resource type="CanvasItemMaterial" id="CanvasItemMaterial_2q0ik"] [sub_resource type="CanvasItemMaterial" id="CanvasItemMaterial_2q0ik"]
blend_mode = 1 blend_mode = 1
@@ -105,6 +111,7 @@ script = ExtResource("1_poq2x")
RDamage = SubResource("Resource_cb2lu") RDamage = SubResource("Resource_cb2lu")
RKnockback = SubResource("Resource_abfq8") RKnockback = SubResource("Resource_abfq8")
RHealth = SubResource("Resource_ue7xq") RHealth = SubResource("Resource_ue7xq")
TargetingDistance = 5.0
WalkSpeed = 7.5 WalkSpeed = 7.5
AccelerationFloor = 4.0 AccelerationFloor = 4.0
DecelerationFloor = 3.0 DecelerationFloor = 3.0
@@ -321,6 +328,14 @@ visible = false
transform = Transform3D(1, 0, 0, 0, -4.371139e-08, 1, 0, -1, -4.371139e-08, 0, 0, -1) transform = Transform3D(1, 0, 0, 0, -4.371139e-08, 1, 0, -1, -4.371139e-08, 0, 0, -1)
mesh = SubResource("CylinderMesh_nodcl") mesh = SubResource("CylinderMesh_nodcl")
[node name="DashDamage" type="ShapeCast3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
enabled = false
shape = SubResource("SphereShape3D_abfq8")
target_position = Vector3(0, 0, 0)
max_results = 512
collision_mask = 16
[node name="CloseEnemyDetector" type="ShapeCast3D" parent="."] [node name="CloseEnemyDetector" type="ShapeCast3D" parent="."]
unique_name_in_owner = true unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.6, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.6, 0)
@@ -343,6 +358,16 @@ collision_mask = 256
target_position = Vector3(0, -2, 0) target_position = Vector3(0, -2, 0)
collision_mask = 256 collision_mask = 256
[node name="SlidingEnemyDetector" type="Area3D" parent="."]
collision_layer = 0
collision_mask = 16
monitoring = false
monitorable = false
[node name="CollisionShape3D" type="CollisionShape3D" parent="SlidingEnemyDetector"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
shape = SubResource("SphereShape3D_ue7xq")
[node name="InvincibilityTime" type="Timer" parent="."] [node name="InvincibilityTime" type="Timer" parent="."]
one_shot = true one_shot = true
@@ -627,12 +652,6 @@ to = NodePath("../OnWall/Hanging")
event = &"dash_to_planted" event = &"dash_to_planted"
delay_in_seconds = "0.0" delay_in_seconds = "0.0"
[node name="OnPoweredDash" type="Node" parent="StateChart/Root/Movement"]
script = ExtResource("28_n7qhm")
to = NodePath("../Dashing/PoweredDash")
event = &"powered_dash"
delay_in_seconds = "0.0"
[node name="OnAimedDash" type="Node" parent="StateChart/Root/Movement"] [node name="OnAimedDash" type="Node" parent="StateChart/Root/Movement"]
script = ExtResource("28_n7qhm") script = ExtResource("28_n7qhm")
to = NodePath("../Dashing/AimedDash") to = NodePath("../Dashing/AimedDash")
@@ -773,9 +792,6 @@ delay_in_seconds = "0.0"
[node name="Dash" type="Node" parent="StateChart/Root/Movement/Dashing"] [node name="Dash" type="Node" parent="StateChart/Root/Movement/Dashing"]
script = ExtResource("27_34snm") script = ExtResource("27_34snm")
[node name="PoweredDash" type="Node" parent="StateChart/Root/Movement/Dashing"]
script = ExtResource("27_34snm")
[node name="AimedDash" type="Node" parent="StateChart/Root/Movement/Dashing"] [node name="AimedDash" type="Node" parent="StateChart/Root/Movement/Dashing"]
script = ExtResource("27_34snm") script = ExtResource("27_34snm")

View File

@@ -41,7 +41,7 @@ public partial class PlayerController : CharacterBody3D,
/////////////////////////// ///////////////////////////
public event Action<IDamageable, DamageRecord> DamageTaken; public event Action<IDamageable, DamageRecord> DamageTaken;
public event Action<IHealthable, float> HealthChanged; public event Action<IHealthable, HealthChangedRecord> HealthChanged;
public event Action<IHealthable> HealthDepleted; public event Action<IHealthable> HealthDepleted;
/////////////////////////// ///////////////////////////
@@ -66,7 +66,10 @@ public partial class PlayerController : CharacterBody3D,
public ShapeCast3D CeilingDetector; public ShapeCast3D CeilingDetector;
public RayCast3D DirectGroundDetector; public RayCast3D DirectGroundDetector;
public Area3D WeaponHitbox; public Area3D WeaponHitbox;
public AudioStreamPlayer3D SFXPlayer; public AudioStreamPlayer3D SfxPlayer;
public ShapeCast3D DashDamageDetector;
public Area3D SlidingEnemyDetector;
// Inspector stuff // Inspector stuff
[Export] public Marker3D TutorialWeaponTarget; [Export] public Marker3D TutorialWeaponTarget;
@@ -313,6 +316,7 @@ public partial class PlayerController : CharacterBody3D,
private StateChartState _mantling; private StateChartState _mantling;
private StateChartState _simpleDash; private StateChartState _simpleDash;
private StateChartState _aimedDash; private StateChartState _aimedDash;
private StateChartState _weaponDash;
private StateChartState _sliding; private StateChartState _sliding;
private StateChartState _groundSliding; private StateChartState _groundSliding;
private StateChartState _airGliding; private StateChartState _airGliding;
@@ -324,13 +328,9 @@ public partial class PlayerController : CharacterBody3D,
private StateChartState _onWallHanging; private StateChartState _onWallHanging;
private StateChartState _onWallRunning; private StateChartState _onWallRunning;
private StateChartState _attack;
private StateChartState _attackReady;
private StateChartState _attackStandard; private StateChartState _attackStandard;
private StateChartState _attackDash; private StateChartState _attackDash;
private Transition _onDashEnded;
private Transition _onJumpFromWall; private Transition _onJumpFromWall;
private Transition _onJumpFromWallFalling; private Transition _onJumpFromWallFalling;
private Transition _onLeaveWallFromRun; private Transition _onLeaveWallFromRun;
@@ -374,8 +374,8 @@ public partial class PlayerController : CharacterBody3D,
DashIndicatorMeshCylinder = DashIndicatorMesh.Mesh as CylinderMesh; DashIndicatorMeshCylinder = DashIndicatorMesh.Mesh as CylinderMesh;
DashIndicatorMesh.Visible = false; DashIndicatorMesh.Visible = false;
SFXPlayer = GetNode<AudioStreamPlayer3D>("SFXPlayer"); SfxPlayer = GetNode<AudioStreamPlayer3D>("SFXPlayer");
_audioStream = SFXPlayer.GetStreamPlayback() as AudioStreamPlaybackInteractive; _audioStream = SfxPlayer.GetStreamPlayback() as AudioStreamPlaybackInteractive;
// Camera stuff // Camera stuff
HeadSystem = GetNode<HeadSystem>("HeadSystem"); HeadSystem = GetNode<HeadSystem>("HeadSystem");
@@ -394,6 +394,8 @@ public partial class PlayerController : CharacterBody3D,
GroundDetector = GetNode<ShapeCast3D>("GroundDetector"); GroundDetector = GetNode<ShapeCast3D>("GroundDetector");
CeilingDetector = GetNode<ShapeCast3D>("CeilingDetector"); CeilingDetector = GetNode<ShapeCast3D>("CeilingDetector");
DirectGroundDetector = GetNode<RayCast3D>("DirectGroundDetector"); DirectGroundDetector = GetNode<RayCast3D>("DirectGroundDetector");
DashDamageDetector = GetNode<ShapeCast3D>("DashDamage");
SlidingEnemyDetector = GetNode<Area3D>("SlidingEnemyDetector");
RayCast3D stairsBelowRayCast3D = GetNode<RayCast3D>("StairsBelowRayCast3D"); RayCast3D stairsBelowRayCast3D = GetNode<RayCast3D>("StairsBelowRayCast3D");
RayCast3D stairsAheadRayCast3D = GetNode<RayCast3D>("StairsAheadRayCast3D"); RayCast3D stairsAheadRayCast3D = GetNode<RayCast3D>("StairsAheadRayCast3D");
_headCollisionDetectors = new RayCast3D[NUM_OF_HEAD_COLLISION_DETECTORS]; _headCollisionDetectors = new RayCast3D[NUM_OF_HEAD_COLLISION_DETECTORS];
@@ -426,7 +428,7 @@ public partial class PlayerController : CharacterBody3D,
} }
if (RKnockback != null) CKnockback!.RKnockback = RKnockback; if (RKnockback != null) CKnockback!.RKnockback = RKnockback;
CDamageable.DamageTaken += ReduceHealth; CDamageable.DamageTaken += (source, record) => ReduceHealth(source, record);
CDamageable.DamageTaken += RegisterKnockback; CDamageable.DamageTaken += RegisterKnockback;
CHealth.HealthDepleted += Kill; CHealth.HealthDepleted += Kill;
@@ -436,6 +438,7 @@ public partial class PlayerController : CharacterBody3D,
_aiming = StateChartState.Of(GetNode("StateChart/Root/Aim/On")); _aiming = StateChartState.Of(GetNode("StateChart/Root/Aim/On"));
_simpleDash = StateChartState.Of(GetNode("StateChart/Root/Movement/Dashing/Dash")); _simpleDash = StateChartState.Of(GetNode("StateChart/Root/Movement/Dashing/Dash"));
_aimedDash = StateChartState.Of(GetNode("StateChart/Root/Movement/Dashing/AimedDash")); _aimedDash = StateChartState.Of(GetNode("StateChart/Root/Movement/Dashing/AimedDash"));
_weaponDash = StateChartState.Of(GetNode("StateChart/Root/Movement/Dashing/ToWeaponDash"));
_slamming = StateChartState.Of(GetNode("StateChart/Root/Movement/Slamming")); _slamming = StateChartState.Of(GetNode("StateChart/Root/Movement/Slamming"));
_sliding = StateChartState.Of(GetNode("StateChart/Root/Movement/Sliding")); _sliding = StateChartState.Of(GetNode("StateChart/Root/Movement/Sliding"));
@@ -445,7 +448,6 @@ public partial class PlayerController : CharacterBody3D,
_airGlidingDoubleJump = StateChartState.Of(GetNode("StateChart/Root/Movement/Sliding/AirGlideDoubleJumpEnabled")); _airGlidingDoubleJump = StateChartState.Of(GetNode("StateChart/Root/Movement/Sliding/AirGlideDoubleJumpEnabled"));
_onGroundSlideJump = Transition.Of(GetNode("StateChart/Root/Movement/Sliding/GroundSlide/OnJump")); _onGroundSlideJump = Transition.Of(GetNode("StateChart/Root/Movement/Sliding/GroundSlide/OnJump"));
_onAirGlideDoubleJump = Transition.Of(GetNode("StateChart/Root/Movement/Sliding/AirGlideDoubleJumpEnabled/OnJump")); _onAirGlideDoubleJump = Transition.Of(GetNode("StateChart/Root/Movement/Sliding/AirGlideDoubleJumpEnabled/OnJump"));
_onDashEnded = Transition.Of(GetNode("StateChart/Root/Movement/Dashing/OnDashEnded"));
// _actionHanging = StateChartState.Of(GetNode("StateChart/Root/Actions/Hanging")); // _actionHanging = StateChartState.Of(GetNode("StateChart/Root/Actions/Hanging"));
_powerExpired = StateChartState.Of(GetNode("StateChart/Root/PowerReserve/Expired")); _powerExpired = StateChartState.Of(GetNode("StateChart/Root/PowerReserve/Expired"));
@@ -470,8 +472,6 @@ public partial class PlayerController : CharacterBody3D,
_onAirborneToGrounded = Transition.Of(GetNode("StateChart/Root/Movement/Airborne/OnGrounded")); _onAirborneToGrounded = Transition.Of(GetNode("StateChart/Root/Movement/Airborne/OnGrounded"));
// Attack states // Attack states
_attack = StateChartState.Of(GetNode("StateChart/Root/Attack"));
_attackReady = StateChartState.Of(GetNode("StateChart/Root/Attack/Ready"));
_attackStandard = StateChartState.Of(GetNode("StateChart/Root/Attack/StandardAttack")); _attackStandard = StateChartState.Of(GetNode("StateChart/Root/Attack/StandardAttack"));
_attackDash = StateChartState.Of(GetNode("StateChart/Root/Attack/DashAttack")); _attackDash = StateChartState.Of(GetNode("StateChart/Root/Attack/DashAttack"));
@@ -499,7 +499,7 @@ public partial class PlayerController : CharacterBody3D,
MantleSystem.Init(); MantleSystem.Init();
StairsSystem.Init(stairsBelowRayCast3D, stairsAheadRayCast3D, cameraSmooth); StairsSystem.Init(stairsBelowRayCast3D, stairsAheadRayCast3D, cameraSmooth);
DashSystem.Init(HeadSystem, _camera); DashSystem.Init(HeadSystem, _camera);
WeaponSystem.Init(HeadSystem, _camera); WeaponSystem.Init();
WallHugSystem.Init(); WallHugSystem.Init();
EmpoweredActionsLeft = MaxNumberOfEmpoweredActions; EmpoweredActionsLeft = MaxNumberOfEmpoweredActions;
@@ -548,6 +548,9 @@ public partial class PlayerController : CharacterBody3D,
_aimedDash.StateEntered += OnAimedDashStarted; _aimedDash.StateEntered += OnAimedDashStarted;
_aimedDash.StateExited += OnAimedDashFinished; _aimedDash.StateExited += OnAimedDashFinished;
_weaponDash.StateExited += OnWeaponDashFinished;
SlidingEnemyDetector.BodyEntered += EnemyHitWhileSliding;
_sliding.StateEntered += SlideStarted; _sliding.StateEntered += SlideStarted;
_sliding.StateExited += SlideEnded; _sliding.StateExited += SlideEnded;
_slideCanceled.StateEntered += OnSlideCanceled; _slideCanceled.StateEntered += OnSlideCanceled;
@@ -576,7 +579,7 @@ public partial class PlayerController : CharacterBody3D,
_onWallRunning.StatePhysicsProcessing += HandleWallRunning; _onWallRunning.StatePhysicsProcessing += HandleWallRunning;
_onWallHanging.StateExited += RecoverWeapon; _onWallHanging.StateExited += RecoverWeapon;
_onDashEnded.Taken += RecoverWeapon; // _onDashEnded.Taken += RecoverWeapon;
_onJumpFromWall.Taken += OnJumpFromWall; _onJumpFromWall.Taken += OnJumpFromWall;
_onJumpFromWallFalling.Taken += OnJumpFromWall; _onJumpFromWallFalling.Taken += OnJumpFromWall;
@@ -975,7 +978,7 @@ public partial class PlayerController : CharacterBody3D,
} }
public void RecoverChildNode(Node3D node) public void RecoverChildNode(Node3D node)
{ {
GetTree().GetRoot().RemoveChild(node); node.GetParent().RemoveChild(node);
AddChild(node); AddChild(node);
node.SetGlobalPosition(GlobalPosition); node.SetGlobalPosition(GlobalPosition);
} }
@@ -1360,7 +1363,7 @@ public partial class PlayerController : CharacterBody3D,
// Slide management // // Slide management //
/////////////////////////// ///////////////////////////
private bool _isSlideInputDown = false; private bool _isSlideInputDown;
public void OnInputSlideStarted() public void OnInputSlideStarted()
{ {
@@ -1377,7 +1380,6 @@ public partial class PlayerController : CharacterBody3D,
public record SlopeRecord( public record SlopeRecord(
Vector3 Position, Vector3 Position,
Vector3 Normal,
Vector3 Direction, Vector3 Direction,
float AngleRadians float AngleRadians
); );
@@ -1396,7 +1398,7 @@ public partial class PlayerController : CharacterBody3D,
var angle = normal.AngleTo(Vector3.Up); var angle = normal.AngleTo(Vector3.Up);
var vectorInPlane = normal.Cross(Vector3.Up).Normalized(); var vectorInPlane = normal.Cross(Vector3.Up).Normalized();
var direction = normal.Cross(vectorInPlane).Normalized(); var direction = normal.Cross(vectorInPlane).Normalized();
return new SlopeRecord(position, normal, direction, angle); return new SlopeRecord(position, direction, angle);
} }
public void SetupSlideCollision() public void SetupSlideCollision()
@@ -1415,8 +1417,11 @@ public partial class PlayerController : CharacterBody3D,
public void SlideStarted() public void SlideStarted()
{ {
_targetSpeed = Velocity.Length(); _targetSpeed = Velocity.Length();
SetupSlideCollision();
_audioStream!.SwitchToClipByName("glide"); _audioStream!.SwitchToClipByName("glide");
SetupSlideCollision();
SlidingEnemyDetector.Monitoring = true;
_isInvincible = true;
} }
public bool CanStandUpFromSlide() public bool CanStandUpFromSlide()
@@ -1441,7 +1446,7 @@ public partial class PlayerController : CharacterBody3D,
var finalSpeed = Mathf.Max(currentVelocity * speedLossRate, minimumVelocity); var finalSpeed = Mathf.Max(currentVelocity * speedLossRate, minimumVelocity);
// Going down a slope? // Going down a slope?
var (position, _, slopeDirection, slopeAngleRadians) = GetSlope(); var (position, slopeDirection, slopeAngleRadians) = GetSlope();
// Change velocity based on Input // Change velocity based on Input
var horizontalVelocity = ComputeHVelocity(delta, AccelerationGroundSlide, DecelerationGroundSlide); var horizontalVelocity = ComputeHVelocity(delta, AccelerationGroundSlide, DecelerationGroundSlide);
@@ -1542,11 +1547,22 @@ public partial class PlayerController : CharacterBody3D,
} }
public void SlideEnded() public void SlideEnded()
{ {
_audioStream!.SwitchToClipByName("footsteps"); SlidingEnemyDetector.Monitoring = false;
_isInvincible = false;
SetupStandingCollision(); SetupStandingCollision();
_audioStream!.SwitchToClipByName("footsteps");
_targetSpeed = WalkSpeed; _targetSpeed = WalkSpeed;
} }
public void EnemyHitWhileSliding(Node enemy)
{
if(enemy is not IDamageable damageable)
return;
_hitEnemies.Add(damageable);
TriggerDamage();
}
public void JumpFromGroundSlide() public void JumpFromGroundSlide()
{ {
_jumpStrengthMultiplier = GroundSlideJumpMultiplier + Velocity.Length()*GroundSlideJumpSpeedFactor; _jumpStrengthMultiplier = GroundSlideJumpMultiplier + Velocity.Length()*GroundSlideJumpSpeedFactor;
@@ -1653,15 +1669,14 @@ public partial class PlayerController : CharacterBody3D,
if (!CanPerformEmpoweredAction()) if (!CanPerformEmpoweredAction())
return; return;
DashSystem.StartPreparingDash(); // DashIndicatorMesh.Visible = true;
DashIndicatorMesh.Visible = true;
if (!isOnFloorCustom()) if (!isOnFloorCustom())
ReduceTimeScaleWhileAiming(); ReduceTimeScaleWhileAiming();
} }
public void HandleAiming(float delta) public void HandleAiming(float delta)
{ {
DashIndicatorMeshCylinder.Height = DashSystem.PlannedLocation.DistanceTo(GlobalPosition); // DashIndicatorMeshCylinder.Height = DashSystem.PlannedLocation.DistanceTo(GlobalPosition);
DashIndicatorNode.LookAt(DashSystem.PlannedLocation); // DashIndicatorNode.LookAt(DashSystem.PlannedLocation);
if (CanPerformEmpoweredAction()) if (CanPerformEmpoweredAction())
DashSystem.PrepareDash(); DashSystem.PrepareDash();
@@ -1670,7 +1685,7 @@ public partial class PlayerController : CharacterBody3D,
{ {
DashSystem.StopPreparingDash(); DashSystem.StopPreparingDash();
DashIndicatorMesh.Visible = false; // DashIndicatorMesh.Visible = false;
} }
/////////////////////////// ///////////////////////////
@@ -1702,8 +1717,15 @@ public partial class PlayerController : CharacterBody3D,
var correction = DashSystem.CollisionNormal == Vector3.Down ? _playerHeight : DashSystem.DashCastRadius; var correction = DashSystem.CollisionNormal == Vector3.Down ? _playerHeight : DashSystem.DashCastRadius;
var correctedLocation = DashSystem.PlannedLocation + Vector3.Down * correction; var correctedLocation = DashSystem.PlannedLocation + Vector3.Down * correction;
if (DashSystem.CanDashThroughTarget && DashSystem.CollidedObject is ITargetable targetable)
correctedLocation = ComputePositionAfterTargetedDash(targetable.GetTargetGlobalPosition(), DashSystem.CollisionPoint);
// Start invincibility timer for the duration of the dash and a bit more afterwards
OnHitInvincibility();
_preDashVelocity = Velocity; _preDashVelocity = Velocity;
_dashDirection = (correctedLocation - GlobalPosition).Normalized(); _dashDirection = (correctedLocation - GlobalPosition).Normalized();
SetupDashDamageDetector(correctedLocation);
var dashTween = CreatePositionTween(correctedLocation, AimedDashTime); var dashTween = CreatePositionTween(correctedLocation, AimedDashTime);
// dashTween.TweenMethod(Callable.From<float>(AimedDashTweenOngoing), 0.0f, 1.0f, AimedDashTime); // dashTween.TweenMethod(Callable.From<float>(AimedDashTweenOngoing), 0.0f, 1.0f, AimedDashTime);
@@ -1713,6 +1735,28 @@ public partial class PlayerController : CharacterBody3D,
_customMantleCurve = DashSystem.MantleSystem.MantleCurve; _customMantleCurve = DashSystem.MantleSystem.MantleCurve;
_customMantleStartTransform = DashSystem.MantleSystem.GlobalTransform; _customMantleStartTransform = DashSystem.MantleSystem.GlobalTransform;
} }
public void SetupDashDamageDetector(Vector3 endDashLocation)
{
RemoveChildNode(DashDamageDetector);
DashDamageDetector.SetTargetPosition(DashDamageDetector.ToLocal(endDashLocation));
DashDamageDetector.Enabled = true;
}
public void ComputeDashDamage()
{
for (var i = 0; i < DashDamageDetector.GetCollisionCount(); i++)
{
var collidedObject = DashDamageDetector.GetCollider(i);
if (collidedObject is not IDamageable damageable) continue;
_hitEnemies.Add(damageable);
}
TriggerDamage();
RecoverChildNode(DashDamageDetector);
DashDamageDetector.Enabled = false;
}
public void AimedDashTweenEnded() public void AimedDashTweenEnded()
{ {
var dashEvent = isOnFloorCustom() ? "grounded" : "dash_finished"; var dashEvent = isOnFloorCustom() ? "grounded" : "dash_finished";
@@ -1720,6 +1764,10 @@ public partial class PlayerController : CharacterBody3D,
} }
public void OnAimedDashFinished() public void OnAimedDashFinished()
{ {
ManageAttackedEnemyPostDash(DashSystem.CollidedObject as Node);
DashSystem.CollidedObject = null;
ComputeDashDamage();
if (_customMantle) if (_customMantle)
{ {
_playerState.SendEvent("mantle"); _playerState.SendEvent("mantle");
@@ -1743,23 +1791,29 @@ public partial class PlayerController : CharacterBody3D,
weaponTargetLocation, weaponTargetLocation,
DashSystem.HasHit, DashSystem.HasHit,
DashSystem.CollisionPoint, DashSystem.CollisionPoint,
DashSystem.CollisionNormal); DashSystem.CollisionNormal,
DashSystem.CollidedObject as Node);
} }
public void RecoverWeapon() public void RecoverWeapon()
{ {
if (WeaponSystem.GetParent() == this) return; if (WeaponSystem.GetParent() == this) return;
HeadSystem.ShowWeapon(); HeadSystem.ShowWeapon();
RecoverChildNode(WeaponSystem);
WeaponSystem.ResetWeapon(); WeaponSystem.ResetWeapon();
RecoverChildNode(WeaponSystem);
} }
public void DashToFlyingWeapon() public void DashToFlyingWeapon()
{ {
_playerState.SendEvent("cancel_aim"); _playerState.SendEvent("cancel_aim");
_playerState.SendEvent("weapon_dash"); _playerState.SendEvent("weapon_dash");
PerformEmpoweredAction(); PerformEmpoweredAction();
_audioStream.SwitchToClipByName("dash"); _audioStream.SwitchToClipByName("dash");
// Start invincibility timer for the duration of the dash and a bit more afterwards
OnHitInvincibility();
SetupDashDamageDetector(WeaponSystem.GlobalPosition);
DashSystem.ShouldMantle = false; DashSystem.ShouldMantle = false;
_dashDirection = (WeaponSystem.GlobalPosition - GlobalPosition).Normalized(); _dashDirection = (WeaponSystem.GlobalPosition - GlobalPosition).Normalized();
@@ -1770,6 +1824,7 @@ public partial class PlayerController : CharacterBody3D,
public void DashToFlyingWeaponTweenEnded() public void DashToFlyingWeaponTweenEnded()
{ {
RecoverWeapon(); RecoverWeapon();
ComputeDashDamage();
var vel = _dashDirection * PostDashSpeed; var vel = _dashDirection * PostDashSpeed;
SetVelocity(vel); SetVelocity(vel);
@@ -1780,8 +1835,11 @@ public partial class PlayerController : CharacterBody3D,
{ {
_playerState.SendEvent("cancel_aim"); _playerState.SendEvent("cancel_aim");
_playerState.SendEvent("weapon_dash"); _playerState.SendEvent("weapon_dash");
PerformEmpoweredAction(); PerformEmpoweredAction();
_audioStream.SwitchToClipByName("dash"); _audioStream.SwitchToClipByName("dash");
// Start invincibility timer for the duration of the dash and a bit more afterwards
OnHitInvincibility();
DashSystem.ShouldMantle = false; DashSystem.ShouldMantle = false;
var dashLocation = WeaponSystem.PlantLocation; var dashLocation = WeaponSystem.PlantLocation;
@@ -1789,12 +1847,16 @@ public partial class PlayerController : CharacterBody3D,
dashLocation += WeaponSystem.PlantNormal * _playerRadius; dashLocation += WeaponSystem.PlantNormal * _playerRadius;
if (WeaponSystem.IsPlantedUnderPlatform()) if (WeaponSystem.IsPlantedUnderPlatform())
dashLocation += Vector3.Down * _playerHeight; dashLocation += Vector3.Down * _playerHeight;
if (WeaponSystem.PlantObject is ITargetable targetable)
dashLocation = targetable.GetTargetGlobalPosition();
_wallHugStartNormal = WeaponSystem.PlantNormal; _wallHugStartNormal = WeaponSystem.PlantNormal;
_currentWallContactPoint = WeaponSystem.PlantLocation; _currentWallContactPoint = WeaponSystem.PlantLocation;
_wallHugStartLocation = dashLocation; _wallHugStartLocation = dashLocation;
_wallHugStartProjectedVelocity = Velocity.Slide(_wallHugStartNormal); _wallHugStartProjectedVelocity = Velocity.Slide(_wallHugStartNormal);
SetupDashDamageDetector(dashLocation);
var dashTween = CreatePositionTween(dashLocation, AimedDashTime); var dashTween = CreatePositionTween(dashLocation, AimedDashTime);
dashTween.Finished += DashToPlantedWeaponTweenEnded; dashTween.Finished += DashToPlantedWeaponTweenEnded;
} }
@@ -1803,17 +1865,46 @@ public partial class PlayerController : CharacterBody3D,
// Store the weapon state before resetting it // Store the weapon state before resetting it
var isPlantedOnWall = WeaponSystem.IsPlantedInWall(); var isPlantedOnWall = WeaponSystem.IsPlantedInWall();
var isPlantedUnderPlatform = WeaponSystem.IsPlantedUnderPlatform(); var isPlantedUnderPlatform = WeaponSystem.IsPlantedUnderPlatform();
var shouldDashToHanging = isPlantedOnWall || isPlantedUnderPlatform; var isPlantedInTarget = WeaponSystem.PlantObject is ITargetable;
var shouldDashToHanging = (isPlantedOnWall || isPlantedUnderPlatform) && !isPlantedInTarget;
var resultingEvent = shouldDashToHanging ? "dash_to_planted" : "dash_finished"; var resultingEvent = shouldDashToHanging ? "dash_to_planted" : "dash_finished";
if (!shouldDashToHanging) RecoverWeapon(); // Manually recover weapon before enemy is freed in case it owns the weapon object
if (WeaponSystem.PlantObject is ITargetable)
{
HeadSystem.OnMantle(); // Recycle mantle animation
SetVerticalVelocity(PostDashSpeed);
}
ManageAttackedEnemyPostDash(WeaponSystem.PlantObject);
WeaponSystem.PlantObject = null;
ComputeDashDamage();
_playerState.SendEvent(resultingEvent); _playerState.SendEvent(resultingEvent);
} }
public void ManageAttackedEnemyPostDash(Node enemy)
{
if (enemy is IDamageable damageable)
{
_hitEnemies.Add(damageable);
TriggerDamage();
}
if (enemy is IStunnable stunnable)
stunnable.Stun();
}
public void OnWeaponDashFinished()
{
}
/////////////////////////// ///////////////////////////
// Processes ////////////// // Processes //////////////
/////////////////////////// ///////////////////////////
public override void _PhysicsProcess(double delta) public override void _PhysicsProcess(double delta)
{ {
_spaceState = GetWorld3D().DirectSpaceState;
if (_currentInputBufferFrames > 0) _currentInputBufferFrames -= 1; if (_currentInputBufferFrames > 0) _currentInputBufferFrames -= 1;
// Manage head and camera movement // Manage head and camera movement
@@ -1827,20 +1918,18 @@ public partial class PlayerController : CharacterBody3D,
MantleSystem.ProcessMantle(_grounded.Active); MantleSystem.ProcessMantle(_grounded.Active);
HandleEnemyTargeting(); HandleEnemyTargeting();
if (_closeEnemyDetector.IsColliding())
// Manage dash target and tutorial specific stuff // Manage dash target and tutorial specific stuff
if (WeaponSystem.InHandState.Active && !_aiming.Active && TutorialDone) // if (WeaponSystem.InHandState.Active && !_aiming.Active && TutorialDone)
{ // {
DashIndicatorMesh.Visible = false; // DashIndicatorMesh.Visible = false;
} // }
if (!WeaponSystem.InHandState.Active && TutorialDone) // if (!WeaponSystem.InHandState.Active && TutorialDone)
{ // {
DashIndicatorMesh.Visible = true; // DashIndicatorMesh.Visible = true;
//
DashIndicatorMeshCylinder.Height = WeaponSystem.GlobalPosition.DistanceTo(GlobalPosition) * 2; // DashIndicatorMeshCylinder.Height = WeaponSystem.GlobalPosition.DistanceTo(GlobalPosition) * 2;
DashIndicatorNode.LookAt(WeaponSystem.GlobalPosition); // DashIndicatorNode.LookAt(WeaponSystem.GlobalPosition);
} // }
} }
/////////////////////////// ///////////////////////////
@@ -1855,9 +1944,19 @@ public partial class PlayerController : CharacterBody3D,
{ {
_isEnemyInDashAttackRange = false; _isEnemyInDashAttackRange = false;
_closeEnemyDetector.SetRotation(HeadSystem.GetGlobalLookRotation()); _closeEnemyDetector.SetRotation(HeadSystem.GetGlobalLookRotation());
var enemyTargetState = PlayerUi.TargetState.NoTarget; var enemyTargetState = PlayerUi.TargetState.NoTarget;
var positionOnScreen = Vector2.Zero; var positionOnScreen = Vector2.Zero;
if (DashSystem.CanDashThroughTarget && DashSystem.CollidedObject is ITargetable dashTarget)
{
enemyTargetState = PlayerUi.TargetState.TargetDashThrough;
_targetLocation = dashTarget.GetTargetGlobalPosition();
positionOnScreen = _camera.UnprojectPosition(_targetLocation);
PlayerUi.SetEnemyTargetProperties(new PlayerUi.TargetProperties(enemyTargetState, positionOnScreen));
return;
}
if (!_closeEnemyDetector.IsColliding()) if (!_closeEnemyDetector.IsColliding())
{ {
PlayerUi.SetEnemyTargetProperties(new PlayerUi.TargetProperties(enemyTargetState, positionOnScreen)); PlayerUi.SetEnemyTargetProperties(new PlayerUi.TargetProperties(enemyTargetState, positionOnScreen));
@@ -1873,14 +1972,14 @@ public partial class PlayerController : CharacterBody3D,
} }
_targetLocation = target.GetTargetGlobalPosition(); _targetLocation = target.GetTargetGlobalPosition();
var targetDistance = _targetLocation.DistanceTo(GlobalPosition); // var targetDistance = _targetLocation.DistanceTo(GlobalPosition);
positionOnScreen = _camera.UnprojectPosition(_targetLocation); positionOnScreen = _camera.UnprojectPosition(_targetLocation);
_isEnemyInDashAttackRange = targetDistance < TargetInRangeDistance; _isEnemyInDashAttackRange = true; //targetDistance < TargetInRangeDistance; // Removing the "almost dash" UI
if (_isEnemyInDashAttackRange) if (_isEnemyInDashAttackRange)
{ {
enemyTargetState = PlayerUi.TargetState.TargetDashThrough; enemyTargetState = PlayerUi.TargetState.TargetDashThrough;
if (_targetObject is IDamageable damageable && _targetObject is IHealthable healthable) if (_targetObject is IDamageable damageable and IHealthable healthable)
{ {
var wouldBeDamage = damageable.ComputeDamage(new DamageRecord(this, RDamage)); var wouldBeDamage = damageable.ComputeDamage(new DamageRecord(this, RDamage));
if (wouldBeDamage.Damage.DamageDealt < healthable.CurrentHealth) if (wouldBeDamage.Damage.DamageDealt < healthable.CurrentHealth)
@@ -1926,17 +2025,26 @@ public partial class PlayerController : CharacterBody3D,
_audioStream!.SwitchToClipByName("attacks"); _audioStream!.SwitchToClipByName("attacks");
} }
private PhysicsDirectSpaceState3D _spaceState;
public void OnDashAttackStarted() public void OnDashAttackStarted()
{ {
_audioStream!.SwitchToClipByName("attacks"); _audioStream!.SwitchToClipByName("attacks");
_isInvincible = true; _isInvincible = true;
var actualDashLocation = _targetLocation + Vector3.Down*HeadSystem.Position.Y; var plannedDashLocation = _targetLocation + Vector3.Down*HeadSystem.Position.Y;
var travel = actualDashLocation - GlobalPosition;
var query = PhysicsRayQueryParameters3D.Create(HeadSystem.GlobalPosition, plannedDashLocation, DashSystem.DashCast3D.CollisionMask);
var result = _spaceState.IntersectRay(query);
if (result.Count > 0)
{
plannedDashLocation = (Vector3) result["position"];
}
var travel = plannedDashLocation - GlobalPosition;
_preDashVelocity = Velocity; _preDashVelocity = Velocity;
_dashDirection = travel.Normalized(); _dashDirection = travel.Normalized();
var dashTween = CreatePositionTween(actualDashLocation, AimedDashTime); var dashTween = CreatePositionTween(plannedDashLocation, AimedDashTime);
dashTween.Finished += OnDashAttackEnded; dashTween.Finished += OnDashAttackEnded;
} }
@@ -1953,20 +2061,14 @@ public partial class PlayerController : CharacterBody3D,
stunnable.Stun(); stunnable.Stun();
} }
var shouldKnockback = false; var shouldKnockback = _targetObject is IHealthable { CurrentHealth: > 0 };
if (_targetObject is IHealthable healthable)
{
if (healthable.CurrentHealth > 0) shouldKnockback = true;
}
if (shouldKnockback) if (shouldKnockback)
{ {
Velocity = -_dashDirection*RKnockback.Modifier; Velocity = -_dashDirection*RKnockback.Modifier;
} }
else else
{ {
var locationOtherSide = _targetLocation + (_targetLocation - _targetHitLocation); GlobalPosition = ComputePositionAfterTargetedDash(_targetLocation, _targetHitLocation);
GlobalPosition = locationOtherSide;
var postDashVelocity = _preDashVelocity.Length() > PostDashSpeed ? _preDashVelocity.Length() : PostDashSpeed; var postDashVelocity = _preDashVelocity.Length() > PostDashSpeed ? _preDashVelocity.Length() : PostDashSpeed;
Velocity = _dashDirection * postDashVelocity; Velocity = _dashDirection * postDashVelocity;
} }
@@ -1974,11 +2076,17 @@ public partial class PlayerController : CharacterBody3D,
_playerState.SendEvent("attack_finished"); _playerState.SendEvent("attack_finished");
} }
public static Vector3 ComputePositionAfterTargetedDash(Vector3 targetLocation, Vector3 targetHitLocation)
{
return targetLocation + (targetLocation - targetHitLocation);
}
public void OnInputHitPressed() public void OnInputHitPressed()
{ {
if (_aiming.Active && WeaponSystem.InHandState.Active) if (_aiming.Active && WeaponSystem.InHandState.Active)
{ {
ThrowWeapon(); ThrowWeapon();
return;
} }
var attackToDo = _isEnemyInDashAttackRange ? "dash_attack" : "standard_attack"; var attackToDo = _isEnemyInDashAttackRange ? "dash_attack" : "standard_attack";
@@ -2031,11 +2139,12 @@ public partial class PlayerController : CharacterBody3D,
{ {
ResetTimeScale(); ResetTimeScale();
} }
public void ReduceHealth(IDamageable source, DamageRecord damageRecord) public HealthChangedRecord ReduceHealth(IDamageable source, DamageRecord damageRecord)
{ {
GD.Print("That's NOT fine"); GD.Print("That's NOT fine");
CHealth.ReduceHealth(source, damageRecord); var record = CHealth.ReduceHealth(source, damageRecord);
HealthChanged?.Invoke(this, CHealth.CurrentHealth); HealthChanged?.Invoke(this, record);
return record;
} }
public void RegisterKnockback(IDamageable source, DamageRecord damageRecord) public void RegisterKnockback(IDamageable source, DamageRecord damageRecord)
{ {

View File

@@ -1,6 +1,7 @@
using System; using System;
using Godot; using Godot;
using Movementtests.interfaces; using Movementtests.interfaces;
using Movementtests.systems;
[GlobalClass] [GlobalClass]
public partial class Enemy : CharacterBody3D, public partial class Enemy : CharacterBody3D,
@@ -16,12 +17,14 @@ public partial class Enemy : CharacterBody3D,
{ {
// Signals and events // Signals and events
public event Action<IDamageable, DamageRecord> DamageTaken; public event Action<IDamageable, DamageRecord> DamageTaken;
public event Action<IHealthable, float> HealthChanged; public event Action<IHealthable, HealthChangedRecord> HealthChanged;
public event Action<IHealthable> HealthDepleted; public event Action<IHealthable> HealthDepleted;
// Public export components // Public export components
[Export] [Export]
public Node3D Target { get; set; } public Node3D Target { get; set; }
[Export]
public float EnemyHeight { get; set; } = 1f;
[ExportGroup("Health")] [ExportGroup("Health")]
[Export] [Export]
@@ -54,6 +57,7 @@ public partial class Enemy : CharacterBody3D,
// Private stuff // Private stuff
private Area3D _damageBox; private Area3D _damageBox;
private Node3D _target; private Node3D _target;
private CHealthbar _healthbar;
public override void _Ready() public override void _Ready()
{ {
@@ -75,6 +79,8 @@ public partial class Enemy : CharacterBody3D,
if (CHealth is null) GD.PrintErr("This node needs a 'CHealth' child of type IHealthable!"); if (CHealth is null) GD.PrintErr("This node needs a 'CHealth' child of type IHealthable!");
if (CKnockback is null) GD.PrintErr("This node needs a 'CKnockback' child of type IKnockbackable!"); if (CKnockback is null) GD.PrintErr("This node needs a 'CKnockback' child of type IKnockbackable!");
_healthbar = GetNode<CHealthbar>("CHealthBar");
if (RMovement != null) CMovement!.RMovement = RMovement; if (RMovement != null) CMovement!.RMovement = RMovement;
if (RHealth != null) if (RHealth != null)
{ {
@@ -86,9 +92,11 @@ public partial class Enemy : CharacterBody3D,
public void SetupSignals() public void SetupSignals()
{ {
CDamageable.DamageTaken += ReduceHealth; // Anonymous function call to erase return values of ReduceHealth
CDamageable.DamageTaken += (source, record) => ReduceHealth(source, record);
CDamageable.DamageTaken += RegisterKnockback; CDamageable.DamageTaken += RegisterKnockback;
CHealth.HealthDepleted += Kill; CHealth.HealthDepleted += Kill;
HealthChanged += (source, record) => _healthbar.OnHealthChanged(record);
} }
public override void _PhysicsProcess(double delta) public override void _PhysicsProcess(double delta)
@@ -147,20 +155,33 @@ public partial class Enemy : CharacterBody3D,
return CDamageable.ComputeDamage(damageRecord); return CDamageable.ComputeDamage(damageRecord);
} }
public void ReduceHealth(IDamageable source, DamageRecord damageRecord) public HealthChangedRecord ReduceHealth(IDamageable source, DamageRecord damageRecord)
{ {
if (CHealth is null) return; if (CHealth is null) return new HealthChangedRecord(0, 0, 0);
CHealth.ReduceHealth(source, damageRecord); var record = CHealth.ReduceHealth(source, damageRecord);
HealthChanged?.Invoke(this, CHealth.CurrentHealth); HealthChanged?.Invoke(this, record);
return record;
} }
public void Kill(IHealthable source) public void Kill(IHealthable source)
{ {
// Remove weapon that might be planted there
foreach (var child in GetChildren())
{
if (child is WeaponSystem system)
{
CallDeferred(Node.MethodName.RemoveChild, system);
GetTree().GetRoot().CallDeferred(Node.MethodName.AddChild, system);
system.CallDeferred(Node3D.MethodName.SetGlobalPosition, GlobalPosition + Vector3.Up*EnemyHeight);
system.CallDeferred(WeaponSystem.MethodName.RethrowWeapon);
}
}
foreach (var killable in DeathEffects.ToIKillables()) foreach (var killable in DeathEffects.ToIKillables())
{ {
killable.Kill(source); killable.Kill(source);
} }
QueueFree(); CallDeferred(Node.MethodName.QueueFree);
} }
public void RegisterKnockback(IDamageable source, DamageRecord damageRecord) public void RegisterKnockback(IDamageable source, DamageRecord damageRecord)

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=20 format=3 uid="uid://cmlud1hwkd6sv"] [gd_scene load_steps=21 format=3 uid="uid://cmlud1hwkd6sv"]
[ext_resource type="Script" uid="uid://bn7sc6id7n166" path="res://scenes/enemies/Enemy.cs" id="1_q8l7o"] [ext_resource type="Script" uid="uid://bn7sc6id7n166" path="res://scenes/enemies/Enemy.cs" id="1_q8l7o"]
[ext_resource type="Script" uid="uid://b6y3ugfydvch0" path="res://components/damage/RDamageModifier.cs" id="2_1bsgx"] [ext_resource type="Script" uid="uid://b6y3ugfydvch0" path="res://components/damage/RDamageModifier.cs" id="2_1bsgx"]
@@ -7,6 +7,7 @@
[ext_resource type="Resource" uid="uid://bwqjaom4k7rc3" path="res://scenes/enemies/flying_enemy/flying_enemy_movement.tres" id="4_dejyg"] [ext_resource type="Resource" uid="uid://bwqjaom4k7rc3" path="res://scenes/enemies/flying_enemy/flying_enemy_movement.tres" id="4_dejyg"]
[ext_resource type="Script" uid="uid://bjwrpv3jpsc1e" path="res://components/health/CHealth.cs" id="4_ys4jv"] [ext_resource type="Script" uid="uid://bjwrpv3jpsc1e" path="res://components/health/CHealth.cs" id="4_ys4jv"]
[ext_resource type="PackedScene" uid="uid://dmw5ibwrb483f" path="res://components/movement/CFlyingMovement.tscn" id="7_vaeds"] [ext_resource type="PackedScene" uid="uid://dmw5ibwrb483f" path="res://components/movement/CFlyingMovement.tscn" id="7_vaeds"]
[ext_resource type="PackedScene" uid="uid://bwx2um43k0ou4" path="res://components/health/CHealthbar.tscn" id="7_ykkxn"]
[ext_resource type="Script" uid="uid://dtpxijlnb2c5" path="res://components/movement/RMovement.cs" id="8_on7rt"] [ext_resource type="Script" uid="uid://dtpxijlnb2c5" path="res://components/movement/RMovement.cs" id="8_on7rt"]
[ext_resource type="Script" uid="uid://b0u23nkpaimyc" path="res://components/damage/CDamageable.cs" id="8_uotso"] [ext_resource type="Script" uid="uid://b0u23nkpaimyc" path="res://components/damage/CDamageable.cs" id="8_uotso"]
[ext_resource type="PackedScene" uid="uid://bctpe34ddamg5" path="res://components/knockback/CKnockback.tscn" id="10_dejyg"] [ext_resource type="PackedScene" uid="uid://bctpe34ddamg5" path="res://components/knockback/CKnockback.tscn" id="10_dejyg"]
@@ -47,6 +48,7 @@ collision_layer = 16
collision_mask = 273 collision_mask = 273
motion_mode = 1 motion_mode = 1
script = ExtResource("1_q8l7o") script = ExtResource("1_q8l7o")
EnemyHeight = 0.5
RHealth = ExtResource("2_ma2bq") RHealth = ExtResource("2_ma2bq")
DeathEffects = Array[Object]([]) DeathEffects = Array[Object]([])
RDamage = ExtResource("2_on7rt") RDamage = ExtResource("2_on7rt")
@@ -58,6 +60,9 @@ script = ExtResource("4_ys4jv")
RHealth = ExtResource("2_ma2bq") RHealth = ExtResource("2_ma2bq")
metadata/_custom_type_script = "uid://bjwrpv3jpsc1e" metadata/_custom_type_script = "uid://bjwrpv3jpsc1e"
[node name="CHealthBar" parent="." instance=ExtResource("7_ykkxn")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.70000005, 0)
[node name="CDamageable" type="Node" parent="."] [node name="CDamageable" type="Node" parent="."]
script = ExtResource("8_uotso") script = ExtResource("8_uotso")
DamageModifiers = Array[Object]([SubResource("Resource_jnv07"), SubResource("Resource_53j1c")]) DamageModifiers = Array[Object]([SubResource("Resource_jnv07"), SubResource("Resource_53j1c")])

View File

@@ -4,5 +4,5 @@
[resource] [resource]
script = ExtResource("1_jht15") script = ExtResource("1_jht15")
StartingHealth = 50.0 StartingHealth = 10.0
metadata/_custom_type_script = "uid://baiapod3csndf" metadata/_custom_type_script = "uid://baiapod3csndf"

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=19 format=3 uid="uid://dxt0e2ugmttqq"] [gd_scene load_steps=20 format=3 uid="uid://dxt0e2ugmttqq"]
[ext_resource type="Script" uid="uid://bn7sc6id7n166" path="res://scenes/enemies/Enemy.cs" id="1_r6506"] [ext_resource type="Script" uid="uid://bn7sc6id7n166" path="res://scenes/enemies/Enemy.cs" id="1_r6506"]
[ext_resource type="Resource" uid="uid://otfc2snh8umc" path="res://scenes/enemies/grounded_enemy/grounded_enemy_damage.tres" id="2_bn56u"] [ext_resource type="Resource" uid="uid://otfc2snh8umc" path="res://scenes/enemies/grounded_enemy/grounded_enemy_damage.tres" id="2_bn56u"]
@@ -7,6 +7,7 @@
[ext_resource type="Resource" uid="uid://bohbojc68j7y1" path="res://scenes/enemies/grounded_enemy/grounded_enemy_health.tres" id="2_w4lm8"] [ext_resource type="Resource" uid="uid://bohbojc68j7y1" path="res://scenes/enemies/grounded_enemy/grounded_enemy_health.tres" id="2_w4lm8"]
[ext_resource type="Resource" uid="uid://bqq6uukbdfysr" path="res://scenes/enemies/grounded_enemy/grounded_enemy_movement.tres" id="4_na24f"] [ext_resource type="Resource" uid="uid://bqq6uukbdfysr" path="res://scenes/enemies/grounded_enemy/grounded_enemy_movement.tres" id="4_na24f"]
[ext_resource type="Script" uid="uid://b0u23nkpaimyc" path="res://components/damage/CDamageable.cs" id="7_1tw73"] [ext_resource type="Script" uid="uid://b0u23nkpaimyc" path="res://components/damage/CDamageable.cs" id="7_1tw73"]
[ext_resource type="PackedScene" uid="uid://bwx2um43k0ou4" path="res://components/health/CHealthbar.tscn" id="7_18xwy"]
[ext_resource type="PackedScene" uid="uid://dbr7ioio158ew" path="res://components/movement/CGroundedMovement.tscn" id="7_qyswd"] [ext_resource type="PackedScene" uid="uid://dbr7ioio158ew" path="res://components/movement/CGroundedMovement.tscn" id="7_qyswd"]
[ext_resource type="Script" uid="uid://dtpxijlnb2c5" path="res://components/movement/RMovement.cs" id="8_6d4gl"] [ext_resource type="Script" uid="uid://dtpxijlnb2c5" path="res://components/movement/RMovement.cs" id="8_6d4gl"]
[ext_resource type="PackedScene" uid="uid://bctpe34ddamg5" path="res://components/knockback/CKnockback.tscn" id="10_jqqi6"] [ext_resource type="PackedScene" uid="uid://bctpe34ddamg5" path="res://components/knockback/CKnockback.tscn" id="10_jqqi6"]
@@ -42,6 +43,7 @@ size = Vector3(1, 2, 1.5)
collision_layer = 16 collision_layer = 16
collision_mask = 273 collision_mask = 273
script = ExtResource("1_r6506") script = ExtResource("1_r6506")
EnemyHeight = 2.0
RHealth = ExtResource("2_w4lm8") RHealth = ExtResource("2_w4lm8")
DeathEffects = Array[Object]([]) DeathEffects = Array[Object]([])
RDamage = ExtResource("2_bn56u") RDamage = ExtResource("2_bn56u")
@@ -53,6 +55,9 @@ script = ExtResource("2_gsmti")
RHealth = ExtResource("2_w4lm8") RHealth = ExtResource("2_w4lm8")
metadata/_custom_type_script = "uid://bjwrpv3jpsc1e" metadata/_custom_type_script = "uid://bjwrpv3jpsc1e"
[node name="CHealthBar" parent="." instance=ExtResource("7_18xwy")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.2, 0)
[node name="CDamageable" type="Node" parent="."] [node name="CDamageable" type="Node" parent="."]
script = ExtResource("7_1tw73") script = ExtResource("7_1tw73")
DamageModifiers = Array[Object]([SubResource("Resource_qj0ob")]) DamageModifiers = Array[Object]([SubResource("Resource_qj0ob")])

View File

@@ -1,10 +1,11 @@
using Godot; using Godot;
using Movementtests.interfaces;
namespace Movementtests.systems; namespace Movementtests.systems;
public partial class DashSystem: Node3D public partial class DashSystem: Node3D
{ {
public record DashLocation(bool HasHit, Vector3 TargetLocation, Vector3 CollisionPoint, Vector3 CollisionNormal); public record DashLocation(bool HasHit, Vector3 TargetLocation, Vector3 CollisionPoint, Vector3 CollisionNormal, GodotObject HitObject = null);
[Export(PropertyHint.Range, "0,0.2,0.01,or_greater")] [Export(PropertyHint.Range, "0,0.2,0.01,or_greater")]
@@ -13,9 +14,11 @@ public partial class DashSystem: Node3D
public float PostDashSpeed { get; set; } = 0f; public float PostDashSpeed { get; set; } = 0f;
public bool HasHit { get; set; } public bool HasHit { get; set; }
public bool CanDashThroughTarget { get; set; }
public Vector3 TargetLocation { get; set; } public Vector3 TargetLocation { get; set; }
public Vector3 CollisionPoint { get; set; } public Vector3 CollisionPoint { get; set; }
public Vector3 CollisionNormal { get; set; } public Vector3 CollisionNormal { get; set; }
public GodotObject CollidedObject { get; set; }
public Vector3 PlannedLocation { get; set; } public Vector3 PlannedLocation { get; set; }
public bool ShouldMantle { get; set; } public bool ShouldMantle { get; set; }
@@ -23,7 +26,7 @@ public partial class DashSystem: Node3D
public MantleSystem MantleSystem { get; set; } public MantleSystem MantleSystem { get; set; }
private HeadSystem _head; private HeadSystem _head;
private ShapeCast3D _dashCast3D; public ShapeCast3D DashCast3D;
private Camera3D _camera; private Camera3D _camera;
private Vector3 _dashDirection = Vector3.Zero; private Vector3 _dashDirection = Vector3.Zero;
@@ -51,8 +54,8 @@ public partial class DashSystem: Node3D
public void Init(HeadSystem head, Camera3D camera) public void Init(HeadSystem head, Camera3D camera)
{ {
_dashCast3D = GetNode<ShapeCast3D>("DashCast3D"); DashCast3D = GetNode<ShapeCast3D>("DashCast3D");
var dashShape = _dashCast3D.GetShape() as SphereShape3D; var dashShape = DashCast3D.GetShape() as SphereShape3D;
DashCastRadius = dashShape!.Radius; DashCastRadius = dashShape!.Radius;
_dashCastDrop = GetNode<ShapeCast3D>("DashCastDrop"); _dashCastDrop = GetNode<ShapeCast3D>("DashCastDrop");
@@ -75,30 +78,36 @@ public partial class DashSystem: Node3D
private DashLocation ComputeDashLocation() private DashLocation ComputeDashLocation()
{ {
var targetLocation = _dashCast3D.ToGlobal(_dashCast3D.TargetPosition); var targetLocation = DashCast3D.ToGlobal(DashCast3D.TargetPosition);
var hasHit = _dashCast3D.IsColliding(); var hasHit = DashCast3D.IsColliding();
if (!hasHit) if (!hasHit)
{ {
return new DashLocation(false, targetLocation, Vector3.Zero, Vector3.Zero); return new DashLocation(false, targetLocation, Vector3.Zero, Vector3.Zero);
} }
var collisionPoint = _dashCast3D.GetCollisionPoint(0); var collisionPoint = DashCast3D.GetCollisionPoint(0);
var collisionNormal = _dashCast3D.GetCollisionNormal(0); var collisionNormal = DashCast3D.GetCollisionNormal(0);
var collidedObject = DashCast3D.GetCollider(0);
var fraction = _dashCast3D.GetClosestCollisionSafeFraction(); var fraction = DashCast3D.GetClosestCollisionSafeFraction();
var globalSweepPath = targetLocation - _dashCast3D.GlobalPosition; var globalSweepPath = targetLocation - DashCast3D.GlobalPosition;
var locationAlongPath = _dashCast3D.GlobalPosition + globalSweepPath * fraction; var locationAlongPath = DashCast3D.GlobalPosition + globalSweepPath * fraction;
return new DashLocation(true, locationAlongPath, collisionPoint, collisionNormal); return new DashLocation(true, locationAlongPath, collisionPoint, collisionNormal, collidedObject);
} }
public void PrepareDash() public void PrepareDash()
{ {
_dashCast3D.SetRotation(_head.GetGlobalLookRotation()); DashCast3D.SetRotation(_head.GetGlobalLookRotation());
(HasHit, PlannedLocation, CollisionPoint, CollisionNormal) = ComputeDashLocation(); (HasHit, PlannedLocation, CollisionPoint, CollisionNormal, CollidedObject) = ComputeDashLocation();
CanDashThroughTarget = false;
if (CollidedObject is ITargetable targetable)
{
_dashTarget.SetVisible(false);
CanDashThroughTarget = true;
return;
}
// TODO: Position mantle system to planned location, aligned with ground planned and facing the same way as the dash
// Then query it being careful when dashing underneath a platform and such
MantleSystem.SetGlobalPosition(PlannedLocation); MantleSystem.SetGlobalPosition(PlannedLocation);
MantleSystem.SetRotation(new Vector3( MantleSystem.SetRotation(new Vector3(
MantleSystem.Rotation.X, MantleSystem.Rotation.X,
@@ -115,6 +124,7 @@ public partial class DashSystem: Node3D
_dashTarget.SetVisible(true); _dashTarget.SetVisible(true);
var targetLocation = ShouldMantle ? MantleSystem.FirstMantleProfilePoint : PlannedLocation; var targetLocation = ShouldMantle ? MantleSystem.FirstMantleProfilePoint : PlannedLocation;
_dashTarget.SetGlobalPosition(targetLocation); _dashTarget.SetGlobalPosition(targetLocation);
return;
var shouldShowDropIndicator = !HasHit && !ShouldMantle; var shouldShowDropIndicator = !HasHit && !ShouldMantle;
_dashDropIndicator.SetVisible(shouldShowDropIndicator); _dashDropIndicator.SetVisible(shouldShowDropIndicator);
@@ -126,7 +136,7 @@ public partial class DashSystem: Node3D
// End of the drop is either max cast distance or first collision // End of the drop is either max cast distance or first collision
var hasDropLocationHit = _dashCastDrop.IsColliding(); var hasDropLocationHit = _dashCastDrop.IsColliding();
var endDropLocation = hasDropLocationHit ? _dashCastDrop.GetCollisionPoint(0) : _dashCastDrop.ToGlobal(_dashCast3D.TargetPosition); var endDropLocation = hasDropLocationHit ? _dashCastDrop.GetCollisionPoint(0) : _dashCastDrop.ToGlobal(DashCast3D.TargetPosition);
// Only show drop location indicator if drop cast has hit // Only show drop location indicator if drop cast has hit
_dashDropLocationIndicator.SetVisible(hasDropLocationHit); _dashDropLocationIndicator.SetVisible(hasDropLocationHit);
@@ -141,13 +151,9 @@ public partial class DashSystem: Node3D
public void StopPreparingDash() public void StopPreparingDash()
{ {
CanDashThroughTarget = false;
_dashTarget.SetVisible(false); _dashTarget.SetVisible(false);
_dashDropIndicator.SetVisible(false); _dashDropIndicator.SetVisible(false);
_dashDropLocationIndicator.SetVisible(false); _dashDropLocationIndicator.SetVisible(false);
} }
public void StartPreparingDash()
{
_dashTarget.SetVisible(true);
}
} }

View File

@@ -28,7 +28,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.6, 0)
shape = SubResource("SphereShape3D_jngg2") shape = SubResource("SphereShape3D_jngg2")
target_position = Vector3(0, 0, -12) target_position = Vector3(0, 0, -12)
max_results = 1 max_results = 1
collision_mask = 256 collision_mask = 304
debug_shape_custom_color = Color(0.911631, 0.11884, 0.656218, 1) debug_shape_custom_color = Color(0.911631, 0.11884, 0.656218, 1)
[node name="DashCastDrop" type="ShapeCast3D" parent="."] [node name="DashCastDrop" type="ShapeCast3D" parent="."]
@@ -36,7 +36,7 @@ transform = Transform3D(1, 0, 0, 0, -4.371139e-08, 1, 0, -1, -4.371139e-08, 0, 1
shape = SubResource("SphereShape3D_jngg2") shape = SubResource("SphereShape3D_jngg2")
target_position = Vector3(0, 0, -50) target_position = Vector3(0, 0, -50)
max_results = 1 max_results = 1
collision_mask = 256 collision_mask = 304
debug_shape_custom_color = Color(0.911631, 0.11884, 0.656218, 1) debug_shape_custom_color = Color(0.911631, 0.11884, 0.656218, 1)
[node name="DashTarget" type="MeshInstance3D" parent="."] [node name="DashTarget" type="MeshInstance3D" parent="."]

View File

@@ -1,10 +1,12 @@
using System; using System;
using Godot; using Godot;
using GodotStateCharts; using GodotStateCharts;
using Movementtests.interfaces;
using Movementtests.systems.damage;
namespace Movementtests.systems; namespace Movementtests.systems;
public partial class WeaponSystem : RigidBody3D public partial class WeaponSystem : RigidBody3D, IDamageDealer
{ {
[Signal] [Signal]
public delegate void WeaponThrownEventHandler(); public delegate void WeaponThrownEventHandler();
@@ -12,6 +14,8 @@ public partial class WeaponSystem : RigidBody3D
[Signal] [Signal]
public delegate void WeaponRetrievedEventHandler(); public delegate void WeaponRetrievedEventHandler();
[Export]
public RDamage RDamage { get; set; }
[Export(PropertyHint.Range, "0,100,1,or_greater")] [Export(PropertyHint.Range, "0,100,1,or_greater")]
public float ThrowForce { get; set; } = 1f; public float ThrowForce { get; set; } = 1f;
[Export(PropertyHint.Range, "0,0.2,0.01,or_greater")] [Export(PropertyHint.Range, "0,0.2,0.01,or_greater")]
@@ -22,27 +26,23 @@ public partial class WeaponSystem : RigidBody3D
public StateChartState FlyingState; public StateChartState FlyingState;
public StateChartState PlantedState; public StateChartState PlantedState;
private Node3D _head;
private ShapeCast3D _dashCast3D; private ShapeCast3D _dashCast3D;
private Camera3D _camera;
private TweenQueueSystem _tweenQueueSystem; private TweenQueueSystem _tweenQueueSystem;
private Transform3D _startTransform; private Transform3D _startTransform;
private Transform3D _startMeshTransform; private Vector3 _startMeshRotation;
private Vector3 _throwDirection; private Vector3 _throwDirection;
public Vector3 PlantLocation { get; set; } public Vector3 PlantLocation { get; set; }
public Vector3 PlantNormal { get; set; } public Vector3 PlantNormal { get; set; }
public Node PlantObject { get; set; }
public MeshInstance3D WeaponLocationIndicator { get; set; } public MeshInstance3D WeaponLocationIndicator { get; set; }
public StandardMaterial3D WeaponLocationIndicatorMaterial { get; set; } public StandardMaterial3D WeaponLocationIndicatorMaterial { get; set; }
public MeshInstance3D WeaponMesh { get; set; } public MeshInstance3D WeaponMesh { get; set; }
public void Init(Node3D head, Camera3D camera) public void Init()
{ {
_head = head;
_camera = camera;
_weaponState = StateChart.Of(GetNode("StateChart")); _weaponState = StateChart.Of(GetNode("StateChart"));
InHandState = StateChartState.Of(GetNode("StateChart/Root/InHand")); InHandState = StateChartState.Of(GetNode("StateChart/Root/InHand"));
FlyingState = StateChartState.Of(GetNode("StateChart/Root/Flying")); FlyingState = StateChartState.Of(GetNode("StateChart/Root/Flying"));
@@ -53,7 +53,7 @@ public partial class WeaponSystem : RigidBody3D
WeaponLocationIndicatorMaterial = WeaponLocationIndicator.GetActiveMaterial(0) as StandardMaterial3D; WeaponLocationIndicatorMaterial = WeaponLocationIndicator.GetActiveMaterial(0) as StandardMaterial3D;
WeaponMesh = GetNode<MeshInstance3D>("Weapon"); WeaponMesh = GetNode<MeshInstance3D>("Weapon");
_startMeshTransform = WeaponMesh.Transform; _startMeshRotation = WeaponMesh.Rotation;
_tweenQueueSystem = GetNode<TweenQueueSystem>("TweenQueueSystem"); _tweenQueueSystem = GetNode<TweenQueueSystem>("TweenQueueSystem");
_tweenQueueSystem.Init(this); _tweenQueueSystem.Init(this);
@@ -90,7 +90,7 @@ public partial class WeaponSystem : RigidBody3D
PlantLocation = location; PlantLocation = location;
} }
public void ThrowWeapon(Vector3 end, bool hasHit, Vector3 collisionLocation, Vector3 collisionNormal) public void ThrowWeapon(Vector3 end, bool hasHit, Vector3 collisionLocation, Vector3 collisionNormal, Node collidedObject)
{ {
_weaponState.SendEvent("throw"); _weaponState.SendEvent("throw");
@@ -103,11 +103,32 @@ public partial class WeaponSystem : RigidBody3D
var tween = _tweenQueueSystem.TweenToLocation(new TweenQueueSystem.TweenInputs(end, StraightThrowDuration)); var tween = _tweenQueueSystem.TweenToLocation(new TweenQueueSystem.TweenInputs(end, StraightThrowDuration));
if (hasHit) if (hasHit)
{
PlantObject = collidedObject;
tween.Finished += PlantWeaponInWall; tween.Finished += PlantWeaponInWall;
}
else else
tween.Finished += ThrowWeaponOnCurve; tween.Finished += ThrowWeaponOnCurve;
} }
public void PlantInEnemy(Node3D enemy)
{
GetTree().GetRoot().CallDeferred(Node.MethodName.RemoveChild, this);
enemy.CallDeferred(Node.MethodName.AddChild, this);
if (enemy is IDamageable damageable)
{
damageable.TakeDamage(new DamageRecord(this, RDamage));
}
}
public void RethrowWeapon()
{
_weaponState.SendEvent("throw");
_throwDirection = Vector3.Up;
ThrowWeaponOnCurve();
}
public void ThrowWeaponOnCurve() public void ThrowWeaponOnCurve()
{ {
Freeze = false; Freeze = false;
@@ -118,16 +139,21 @@ public partial class WeaponSystem : RigidBody3D
{ {
_weaponState.SendEvent("plant"); _weaponState.SendEvent("plant");
// WeaponLocationIndicatorMaterial.StencilColor = new Color(1f, 0.2f, 0.2f);
Freeze = true; Freeze = true;
GlobalPosition = PlantLocation; WeaponMesh.Rotation = _startMeshRotation;
WeaponMesh.Transform = _startMeshTransform;
LookAt(GlobalTransform.Origin + PlantNormal, Vector3.Up, true); // WeaponLocationIndicatorMaterial.StencilColor = new Color(1f, 0.2f, 0.2f);
if (PlantObject is Node3D node)
{
PlantInEnemy(node);
}
CallDeferred(Node3D.MethodName.SetGlobalPosition, PlantLocation);
CallDeferred(Node3D.MethodName.LookAt, GlobalTransform.Origin + PlantNormal, Vector3.Up, true);
} }
public void OnThrownWeaponReachesGround(Node other) public void OnThrownWeaponReachesGround(Node other)
{ {
PlantObject = other;
PlantWeaponInWall(); PlantWeaponInWall();
} }

View File

@@ -1,6 +1,7 @@
[gd_scene load_steps=12 format=3 uid="uid://ckm3d6k08a72u"] [gd_scene load_steps=14 format=3 uid="uid://ckm3d6k08a72u"]
[ext_resource type="Script" uid="uid://iii3wfto4t5b" path="res://systems/weapon/WeaponSystem.cs" id="1_csqwk"] [ext_resource type="Script" uid="uid://iii3wfto4t5b" path="res://systems/weapon/WeaponSystem.cs" id="1_csqwk"]
[ext_resource type="Script" uid="uid://jitubgv6judn" path="res://components/damage/RDamage.cs" id="2_m0v1h"]
[ext_resource type="PackedScene" uid="uid://dbe5f0p6lvqtr" path="res://systems/tween_queue/tween_queue_system.tscn" id="2_x1nha"] [ext_resource type="PackedScene" uid="uid://dbe5f0p6lvqtr" path="res://systems/tween_queue/tween_queue_system.tscn" id="2_x1nha"]
[ext_resource type="Script" uid="uid://couw105c3bde4" path="res://addons/godot_state_charts/state_chart.gd" id="3_5owyf"] [ext_resource type="Script" uid="uid://couw105c3bde4" path="res://addons/godot_state_charts/state_chart.gd" id="3_5owyf"]
[ext_resource type="ArrayMesh" uid="uid://cho5fixitrbds" path="res://assets/swords/resources/sword23.tres" id="3_svc06"] [ext_resource type="ArrayMesh" uid="uid://cho5fixitrbds" path="res://assets/swords/resources/sword23.tres" id="3_svc06"]
@@ -8,6 +9,11 @@
[ext_resource type="Script" uid="uid://cytafq8i1y8qm" path="res://addons/godot_state_charts/atomic_state.gd" id="5_m0v1h"] [ext_resource type="Script" uid="uid://cytafq8i1y8qm" path="res://addons/godot_state_charts/atomic_state.gd" id="5_m0v1h"]
[ext_resource type="Script" uid="uid://cf1nsco3w0mf6" path="res://addons/godot_state_charts/transition.gd" id="6_jpdh0"] [ext_resource type="Script" uid="uid://cf1nsco3w0mf6" path="res://addons/godot_state_charts/transition.gd" id="6_jpdh0"]
[sub_resource type="Resource" id="Resource_jpdh0"]
script = ExtResource("2_m0v1h")
DamageDealt = 2.0
metadata/_custom_type_script = "uid://jitubgv6judn"
[sub_resource type="CylinderShape3D" id="CylinderShape3D_avini"] [sub_resource type="CylinderShape3D" id="CylinderShape3D_avini"]
height = 1.0 height = 1.0
radius = 0.1 radius = 0.1
@@ -38,11 +44,12 @@ material = SubResource("StandardMaterial3D_m0v1h")
[node name="Weapon" type="RigidBody3D"] [node name="Weapon" type="RigidBody3D"]
collision_layer = 65536 collision_layer = 65536
collision_mask = 256 collision_mask = 304
continuous_cd = true continuous_cd = true
contact_monitor = true contact_monitor = true
max_contacts_reported = 1 max_contacts_reported = 1
script = ExtResource("1_csqwk") script = ExtResource("1_csqwk")
RDamage = SubResource("Resource_jpdh0")
[node name="TweenQueueSystem" parent="." instance=ExtResource("2_x1nha")] [node name="TweenQueueSystem" parent="." instance=ExtResource("2_x1nha")]
@@ -54,6 +61,9 @@ shape = SubResource("CylinderShape3D_avini")
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0, 0.8673003) transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0, 0.8673003)
mesh = ExtResource("3_svc06") mesh = ExtResource("3_svc06")
[node name="WeaponLocationIndicator" type="MeshInstance3D" parent="."]
mesh = SubResource("SphereMesh_jpdh0")
[node name="StateChart" type="Node" parent="."] [node name="StateChart" type="Node" parent="."]
script = ExtResource("3_5owyf") script = ExtResource("3_5owyf")
metadata/_custom_type_script = "uid://couw105c3bde4" metadata/_custom_type_script = "uid://couw105c3bde4"
@@ -89,11 +99,14 @@ delay_in_seconds = "0.0"
[node name="Planted" type="Node" parent="StateChart/Root"] [node name="Planted" type="Node" parent="StateChart/Root"]
script = ExtResource("5_m0v1h") script = ExtResource("5_m0v1h")
[node name="ToFlying" type="Node" parent="StateChart/Root/Planted"]
script = ExtResource("6_jpdh0")
to = NodePath("../../Flying")
event = &"throw"
delay_in_seconds = "0.0"
[node name="ToHand" type="Node" parent="StateChart/Root/Planted"] [node name="ToHand" type="Node" parent="StateChart/Root/Planted"]
script = ExtResource("6_jpdh0") script = ExtResource("6_jpdh0")
to = NodePath("../../InHand") to = NodePath("../../InHand")
event = &"recover" event = &"recover"
delay_in_seconds = "0.0" delay_in_seconds = "0.0"
[node name="WeaponLocationIndicator" type="MeshInstance3D" parent="."]
mesh = SubResource("SphereMesh_jpdh0")