wave behavior and fixed explosion
This commit is contained in:
@@ -30,6 +30,7 @@ public class DamageExecution : CustomExecution
|
||||
|
||||
public DamageExecution(DamageType damageType, ForgeTagContainer? damageDealerEventTags, ForgeTagContainer? damageReceiverEventTags)
|
||||
{
|
||||
|
||||
// Capture target mana and magic resistance
|
||||
TargetHealth = new AttributeCaptureDefinition(
|
||||
"CharacterAttributeSet.Health",
|
||||
@@ -60,6 +61,8 @@ public class DamageExecution : CustomExecution
|
||||
target,
|
||||
effectEvaluatedData);
|
||||
|
||||
GD.Print(targetIncomingDamage);
|
||||
|
||||
if (targetIncomingDamage <= 0)
|
||||
{
|
||||
return [.. results];
|
||||
@@ -70,6 +73,7 @@ public class DamageExecution : CustomExecution
|
||||
targetIncomingDamage *= hitEffectData.Magnitude;
|
||||
}
|
||||
|
||||
|
||||
// Apply health reduction to target if attribute exists
|
||||
if (TargetHealth.TryGetAttribute(target, out EntityAttribute? targetHealthAttribute))
|
||||
{
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
[ext_resource type="Script" uid="uid://cfx62w40nd84v" path="res://forge/calculators/ForgeDamageExecution.cs" id="4_xfamx"]
|
||||
[ext_resource type="Script" uid="uid://b44cse62qru7j" path="res://scenes/components/knockback/RKnockback.cs" id="5_tw4gc"]
|
||||
[ext_resource type="Resource" uid="uid://bhn27s8ne0uyg" path="res://forge/resources/tag_containers/on_knockback_dealt.tres" id="6_nq3a0"]
|
||||
[ext_resource type="Resource" uid="uid://5obdxlcpw8qt" path="res://forge/resources/tag_containers/knockback_immune.tres" id="7_3ma4g"]
|
||||
[ext_resource type="Resource" uid="uid://bkr6uu57wm3o3" path="res://forge/resources/tag_containers/on_knockback_received.tres" id="7_3utx7"]
|
||||
[ext_resource type="Resource" uid="uid://45l7vnfs72b" path="res://forge/resources/tag_containers/knockbackable_tag.tres" id="8_7hfxb"]
|
||||
[ext_resource type="Script" uid="uid://diondfg5xp78h" path="res://forge/calculators/ForgeKnockbackExecution.cs" id="9_lysxe"]
|
||||
@@ -32,6 +33,7 @@ metadata/_custom_type_script = "uid://b44cse62qru7j"
|
||||
[sub_resource type="Resource" id="Resource_dy671"]
|
||||
script = ExtResource("9_lysxe")
|
||||
KnockbackableTag = ExtResource("8_7hfxb")
|
||||
KnockbackImmuneTag = ExtResource("7_3ma4g")
|
||||
Knockback = SubResource("Resource_ndb8p")
|
||||
KnockbackDealerEventTags = ExtResource("6_nq3a0")
|
||||
KnockbackReceiverEventTags = ExtResource("7_3utx7")
|
||||
@@ -89,7 +91,7 @@ BaseValue = 1
|
||||
script = ExtResource("13_c85am")
|
||||
Name = "Explosion hit"
|
||||
Modifiers = Array[Object]([SubResource("Resource_xwtie")])
|
||||
Components = Array[Object]([ExtResource("1_w36j6")])
|
||||
Components = [ExtResource("1_w36j6")]
|
||||
Executions = Array[Object]([SubResource("Resource_vy8wr"), SubResource("Resource_dy671")])
|
||||
StackLimit = SubResource("Resource_ikb7l")
|
||||
InitialStack = SubResource("Resource_i0sj3")
|
||||
|
||||
@@ -36,7 +36,8 @@ public partial class TokenManager : Node
|
||||
if (RequestQueue.First() != owner.GetInstanceId()) return null; // Next in line is not the requester
|
||||
|
||||
RequestQueue.RemoveAt(0);
|
||||
var token = new Token(owner.GetInstanceId(), () => UseToken(owner.GetInstanceId()));
|
||||
var ownerInstanceId = owner.GetInstanceId();
|
||||
var token = new Token(ownerInstanceId, () => UseToken(ownerInstanceId));
|
||||
Tokens.Add(token.InstanceId, token);
|
||||
return token;
|
||||
}
|
||||
|
||||
21
managers/Wave/EnemyDescription.cs
Normal file
21
managers/Wave/EnemyDescription.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using Godot;
|
||||
|
||||
namespace Movementtests.managers;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class EnemyDescription(PackedScene scene, EnemyDescription.EnemyType type, RMovement? movementOverride) : Resource
|
||||
{
|
||||
public enum EnemyType
|
||||
{
|
||||
Normal,
|
||||
Projectile,
|
||||
}
|
||||
|
||||
[Export(PropertyHint.NodeType)] public required PackedScene Scene { get; set; } = scene;
|
||||
|
||||
[Export] public required EnemyType Type { get; set; } = type;
|
||||
|
||||
[Export] public RMovement? MovementOverride { get; set; } = movementOverride;
|
||||
|
||||
public EnemyDescription() : this(ResourceLoader.Load<PackedScene>("uid://dxt0e2ugmttqq"), EnemyType.Normal, null) {}
|
||||
}
|
||||
1
managers/Wave/EnemyDescription.cs.uid
Normal file
1
managers/Wave/EnemyDescription.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://rhdkfi7nuvu1
|
||||
13
managers/Wave/SingleWave.cs
Normal file
13
managers/Wave/SingleWave.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using Godot;
|
||||
|
||||
namespace Movementtests.managers;
|
||||
|
||||
|
||||
[GlobalClass]
|
||||
public partial class SingleWave(EnemyDescription[] enemies) : Resource
|
||||
{
|
||||
[Export] public Godot.Collections.Dictionary<EnemyDescription, int> EnemiesToSpawn { get; set; } = [];
|
||||
|
||||
public SingleWave() : this([]) {}
|
||||
}
|
||||
1
managers/Wave/SingleWave.cs.uid
Normal file
1
managers/Wave/SingleWave.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cr8wog705ane6
|
||||
11
managers/Wave/WaveContent.cs
Normal file
11
managers/Wave/WaveContent.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Godot;
|
||||
|
||||
namespace Movementtests.managers;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class WaveContent(SingleWave[] waves) : Resource
|
||||
{
|
||||
[Export] public SingleWave[] Waves { get; set; } = waves;
|
||||
|
||||
public WaveContent() : this([]) {}
|
||||
}
|
||||
1
managers/Wave/WaveContent.cs.uid
Normal file
1
managers/Wave/WaveContent.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dijmv0wqc1xuv
|
||||
100
managers/Wave/WaveManager.cs
Normal file
100
managers/Wave/WaveManager.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Chickensoft.AutoInject;
|
||||
using Chickensoft.Collections;
|
||||
using Chickensoft.Introspection;
|
||||
using Godot;
|
||||
using Movementtests.tools;
|
||||
|
||||
namespace Movementtests.managers;
|
||||
|
||||
|
||||
[GlobalClass, Meta(typeof(IAutoNode))]
|
||||
public partial class WaveManager : Node
|
||||
{
|
||||
public override void _Notification(int what) => this.Notify(what);
|
||||
|
||||
public WaveContent WaveContent { get; set; }
|
||||
|
||||
public int CurrentWaveIndex { get; set; }
|
||||
public int CurrentWaveCount => WaveContent.Waves.Length;
|
||||
|
||||
public Godot.Collections.Dictionary<EnemyDescription, int> CurrentWave =>
|
||||
WaveContent.Waves[CurrentWaveIndex].EnemiesToSpawn;
|
||||
|
||||
public Dictionary<ulong, Enemy?> CurrentSpawnedEnemies { get; set; } = [];
|
||||
public Set<Spawner> SpawnersInUse { get; set; } = [];
|
||||
|
||||
public List<Spawner> Spawners { get; set; } = [];
|
||||
public void RegisterSpawner(Spawner spawner) => Spawners.Add(spawner);
|
||||
|
||||
public void InitializeFromResource(WaveContent waveContent) => WaveContent = waveContent;
|
||||
|
||||
public void StartWaves()
|
||||
{
|
||||
CurrentWaveIndex = 0;
|
||||
StartNextWave();
|
||||
}
|
||||
|
||||
public void StartNextWave()
|
||||
{
|
||||
if (CurrentWave.Count == 0)
|
||||
{
|
||||
GD.PrintErr("Wave has no enemies");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Spawners.Count == 0)
|
||||
{
|
||||
GD.PrintErr("No spawners registered");
|
||||
return;
|
||||
}
|
||||
|
||||
SpawnEnemiesAsAvailable();
|
||||
}
|
||||
|
||||
public void SpawnEnemiesAsAvailable()
|
||||
{
|
||||
var randomizedSpawners = Spawners.ToArray();
|
||||
randomizedSpawners.Shuffle();
|
||||
|
||||
foreach (var (enemyDescription, numberRemaining) in CurrentWave)
|
||||
{
|
||||
if (numberRemaining <= 0) continue;
|
||||
foreach (var spawner in randomizedSpawners)
|
||||
{
|
||||
if (!spawner.SupportedEnemyTypes.Contains(enemyDescription.Type)) continue;
|
||||
if (SpawnersInUse.Contains(spawner)) continue;
|
||||
|
||||
var spawnedEnemy = spawner.SpawnEnemy(enemyDescription);
|
||||
if (spawnedEnemy == null) continue;
|
||||
|
||||
CurrentSpawnedEnemies[spawnedEnemy.GetInstanceId()] = spawnedEnemy;
|
||||
SpawnersInUse.Add(spawner);
|
||||
|
||||
spawnedEnemy.OnKilled += instanceId=> SpawnedEnemyDied(instanceId, spawner);
|
||||
|
||||
CurrentWave[enemyDescription]--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var remainingEnemiesToSpawn = CurrentWave.Values.Sum();
|
||||
if (remainingEnemiesToSpawn <= 0) return; // Wave is fully spawned
|
||||
GetTree().CreateTimer(1.0f).Timeout += SpawnEnemiesAsAvailable; // Call back the same function later to try and spawn the rest
|
||||
}
|
||||
|
||||
public void SpawnedEnemyDied(ulong instanceId, Spawner spawner)
|
||||
{
|
||||
CurrentSpawnedEnemies.Remove(instanceId);
|
||||
SpawnersInUse.Remove(spawner);
|
||||
if (CurrentSpawnedEnemies.Count == 0) FinishWave();
|
||||
}
|
||||
|
||||
public void FinishWave()
|
||||
{
|
||||
if (CurrentWaveIndex >= CurrentWaveCount) return; // All waves finished
|
||||
CurrentWaveIndex++;
|
||||
GetTree().CreateTimer(1.0f).Timeout += StartNextWave; // Start next wave in 1s
|
||||
}
|
||||
}
|
||||
1
managers/Wave/WaveManager.cs.uid
Normal file
1
managers/Wave/WaveManager.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cprjrwfk8d0vf
|
||||
9
managers/Wave/resources/flying_enemy_desc.tres
Normal file
9
managers/Wave/resources/flying_enemy_desc.tres
Normal file
@@ -0,0 +1,9 @@
|
||||
[gd_resource type="Resource" script_class="EnemyDescription" format=3 uid="uid://cfyafss8ncbhh"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://cmlud1hwkd6sv" path="res://scenes/enemies/flying_enemy/flying_enemy.tscn" id="1_yvgr4"]
|
||||
[ext_resource type="Script" uid="uid://rhdkfi7nuvu1" path="res://managers/Wave/EnemyDescription.cs" id="2_hsb6g"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("2_hsb6g")
|
||||
Scene = ExtResource("1_yvgr4")
|
||||
metadata/_custom_type_script = "uid://rhdkfi7nuvu1"
|
||||
9
managers/Wave/resources/grounded_enemy_desc.tres
Normal file
9
managers/Wave/resources/grounded_enemy_desc.tres
Normal file
@@ -0,0 +1,9 @@
|
||||
[gd_resource type="Resource" script_class="EnemyDescription" format=3 uid="uid://3clksludry8g"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://dxt0e2ugmttqq" path="res://scenes/enemies/grounded_enemy/grounded_enemy.tscn" id="1_wxdbf"]
|
||||
[ext_resource type="Script" uid="uid://rhdkfi7nuvu1" path="res://managers/Wave/EnemyDescription.cs" id="2_gk6ig"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("2_gk6ig")
|
||||
Scene = ExtResource("1_wxdbf")
|
||||
metadata/_custom_type_script = "uid://rhdkfi7nuvu1"
|
||||
17
managers/Wave/resources/one_of_each_wave.tres
Normal file
17
managers/Wave/resources/one_of_each_wave.tres
Normal file
@@ -0,0 +1,17 @@
|
||||
[gd_resource type="Resource" script_class="SingleWave" format=3 uid="uid://dm71u0ryn0w1o"]
|
||||
|
||||
[ext_resource type="Resource" uid="uid://cfyafss8ncbhh" path="res://managers/Wave/resources/flying_enemy_desc.tres" id="1_bcssi"]
|
||||
[ext_resource type="Script" uid="uid://rhdkfi7nuvu1" path="res://managers/Wave/EnemyDescription.cs" id="2_3r6ce"]
|
||||
[ext_resource type="Resource" uid="uid://3clksludry8g" path="res://managers/Wave/resources/grounded_enemy_desc.tres" id="2_mmsra"]
|
||||
[ext_resource type="Resource" uid="uid://lnturc3ibr5c" path="res://managers/Wave/resources/projectile_enemy_desc.tres" id="3_3r6ce"]
|
||||
[ext_resource type="Script" uid="uid://cr8wog705ane6" path="res://managers/Wave/SingleWave.cs" id="5_qckro"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("5_qckro")
|
||||
Enemies = Array[Object]([ExtResource("1_bcssi"), ExtResource("2_mmsra"), ExtResource("3_3r6ce")])
|
||||
EnemiesToSpawn = Dictionary[ExtResource("2_3r6ce"), int]({
|
||||
ExtResource("1_bcssi"): 1,
|
||||
ExtResource("2_mmsra"): 1,
|
||||
ExtResource("3_3r6ce"): 1
|
||||
})
|
||||
metadata/_custom_type_script = "uid://cr8wog705ane6"
|
||||
10
managers/Wave/resources/projectile_enemy_desc.tres
Normal file
10
managers/Wave/resources/projectile_enemy_desc.tres
Normal file
@@ -0,0 +1,10 @@
|
||||
[gd_resource type="Resource" script_class="EnemyDescription" format=3 uid="uid://lnturc3ibr5c"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://dx3y8sjftqk8f" path="res://scenes/enemies/projectile_enemy/projectile_enemy.tscn" id="1_2nepo"]
|
||||
[ext_resource type="Script" uid="uid://rhdkfi7nuvu1" path="res://managers/Wave/EnemyDescription.cs" id="2_bn1dh"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("2_bn1dh")
|
||||
Scene = ExtResource("1_2nepo")
|
||||
Type = 1
|
||||
metadata/_custom_type_script = "uid://rhdkfi7nuvu1"
|
||||
@@ -13,7 +13,12 @@ using Movementtests.systems;
|
||||
typeof(IAutoConnect),
|
||||
typeof(IProvider)
|
||||
)]
|
||||
public partial class MainSceneTemplate : Node3D, IProvide<InventoryManager>, IProvide<TagsManager>, IProvide<CuesManager>, IProvide<TokenManager>
|
||||
public partial class MainSceneTemplate : Node3D,
|
||||
IProvide<InventoryManager>,
|
||||
IProvide<TagsManager>,
|
||||
IProvide<CuesManager>,
|
||||
IProvide<TokenManager>,
|
||||
IProvide<WaveManager>
|
||||
{
|
||||
public override void _Notification(int what) => this.Notify(what);
|
||||
|
||||
@@ -32,6 +37,7 @@ public partial class MainSceneTemplate : Node3D, IProvide<InventoryManager>, IPr
|
||||
|
||||
[Export] public WeaponInventory? InitialWeaponInventory { get; set; }
|
||||
[Export] public int MaxNumberOfProjectiles { get; set; } = 3;
|
||||
[Export] public WaveContent? WaveContent { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -44,6 +50,9 @@ public partial class MainSceneTemplate : Node3D, IProvide<InventoryManager>, IPr
|
||||
public required TokenManager TokenManager { get; set; }
|
||||
TokenManager IProvide<TokenManager>.Value() => TokenManager;
|
||||
|
||||
public required WaveManager WaveManager { get; set; }
|
||||
WaveManager IProvide<WaveManager>.Value() => WaveManager;
|
||||
|
||||
public void OnReady()
|
||||
{
|
||||
PlayerFellPlane.BodyEntered += StartResetPlayerAnimation;
|
||||
@@ -57,10 +66,21 @@ public partial class MainSceneTemplate : Node3D, IProvide<InventoryManager>, IPr
|
||||
TokenManager = new TokenManager();
|
||||
TokenManager.Initialize(MaxNumberOfProjectiles);
|
||||
AddChild(TokenManager);
|
||||
|
||||
WaveManager = new WaveManager();
|
||||
if (WaveContent != null)
|
||||
WaveManager.InitializeFromResource(WaveContent);
|
||||
AddChild(WaveManager);
|
||||
|
||||
this.Provide();
|
||||
}
|
||||
|
||||
public void OnProvided()
|
||||
{
|
||||
if (WaveContent != null)
|
||||
GetTree().CreateTimer(3).Timeout += WaveManager.StartWaves;
|
||||
}
|
||||
|
||||
public void ResetPlayerPosition()
|
||||
{
|
||||
if (Respawnabble == null || PlayerRespawnMarker == null) throw new Exception("Player or respawn marker is null");
|
||||
|
||||
@@ -1,10 +1,34 @@
|
||||
[gd_scene format=3 uid="uid://b2g2gys4dopmn"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://55wehh6xombr" path="res://maps/_templates/main_scene_template.tscn" id="1_pxwoj"]
|
||||
[ext_resource type="Resource" uid="uid://dm71u0ryn0w1o" path="res://managers/Wave/resources/one_of_each_wave.tres" id="2_a6jwd"]
|
||||
[ext_resource type="PackedScene" uid="uid://y77cdg7gg3y7" path="res://maps/levels/_arenas/playtest_1.tscn" id="2_apgv3"]
|
||||
[ext_resource type="Material" uid="uid://31aulub2nqov" path="res://assets/materials/greybox/m_greybox.tres" id="3_452yy"]
|
||||
[ext_resource type="Script" uid="uid://rhdkfi7nuvu1" path="res://managers/Wave/EnemyDescription.cs" id="3_a6jwd"]
|
||||
[ext_resource type="Resource" uid="uid://cfyafss8ncbhh" path="res://managers/Wave/resources/flying_enemy_desc.tres" id="3_re07p"]
|
||||
[ext_resource type="PackedScene" uid="uid://c305mfrtumcyq" path="res://scenes/spawners/spawner.tscn" id="4_6q0yp"]
|
||||
[ext_resource type="Resource" uid="uid://3clksludry8g" path="res://managers/Wave/resources/grounded_enemy_desc.tres" id="4_7ijxg"]
|
||||
[ext_resource type="Script" uid="uid://cr8wog705ane6" path="res://managers/Wave/SingleWave.cs" id="5_7ijxg"]
|
||||
[ext_resource type="Resource" uid="uid://lnturc3ibr5c" path="res://managers/Wave/resources/projectile_enemy_desc.tres" id="5_hm1dp"]
|
||||
[ext_resource type="Script" uid="uid://dijmv0wqc1xuv" path="res://managers/Wave/WaveContent.cs" id="6_hm1dp"]
|
||||
|
||||
[sub_resource type="Resource" id="Resource_wllel"]
|
||||
script = ExtResource("5_7ijxg")
|
||||
EnemiesToSpawn = Dictionary[ExtResource("3_a6jwd"), int]({
|
||||
ExtResource("4_7ijxg"): 4,
|
||||
ExtResource("5_hm1dp"): 4,
|
||||
ExtResource("3_re07p"): 4
|
||||
})
|
||||
metadata/_custom_type_script = "uid://cr8wog705ane6"
|
||||
|
||||
[sub_resource type="Resource" id="Resource_e88eg"]
|
||||
script = ExtResource("6_hm1dp")
|
||||
Waves = Array[Object]([SubResource("Resource_wllel"), ExtResource("2_a6jwd")])
|
||||
metadata/_custom_type_script = "uid://dijmv0wqc1xuv"
|
||||
|
||||
[node name="Main" unique_id=955321579 instance=ExtResource("1_pxwoj")]
|
||||
MaxNumberOfProjectiles = 2
|
||||
WaveContent = SubResource("Resource_e88eg")
|
||||
|
||||
[node name="PlaytestArena" parent="." index="12" unique_id=664535670 instance=ExtResource("2_apgv3")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -16, 0, 9.5)
|
||||
@@ -14,3 +38,33 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.5, 8.75, 2.25)
|
||||
use_collision = true
|
||||
size = Vector3(1, 17.5, 9.5)
|
||||
material = ExtResource("3_452yy")
|
||||
|
||||
[node name="Spawner" parent="." index="13" unique_id=580981173 node_paths=PackedStringArray("Target") instance=ExtResource("4_6q0yp")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -12, 1, -4)
|
||||
SupportedEnemyTypes = Array[int]([0])
|
||||
Target = NodePath("../Player")
|
||||
IsActiveOnStart = false
|
||||
|
||||
[node name="Spawner2" parent="." index="14" unique_id=1982641431 node_paths=PackedStringArray("Target") instance=ExtResource("4_6q0yp")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -8.5, 1, -4)
|
||||
SupportedEnemyTypes = Array[int]([0])
|
||||
Target = NodePath("../Player")
|
||||
IsActiveOnStart = false
|
||||
|
||||
[node name="Spawner3" parent="." index="15" unique_id=1743153579 node_paths=PackedStringArray("Target") instance=ExtResource("4_6q0yp")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4.5, 1, -4)
|
||||
SupportedEnemyTypes = Array[int]([1])
|
||||
Target = NodePath("../Player")
|
||||
IsActiveOnStart = false
|
||||
|
||||
[node name="Spawner4" parent="." index="16" unique_id=536869732 node_paths=PackedStringArray("Target") instance=ExtResource("4_6q0yp")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8, 1, -4)
|
||||
SupportedEnemyTypes = Array[int]([1, 0])
|
||||
Target = NodePath("../Player")
|
||||
IsActiveOnStart = false
|
||||
|
||||
[node name="Spawner5" parent="." index="17" unique_id=275129467 node_paths=PackedStringArray("Target") instance=ExtResource("4_6q0yp")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 13, 1, -4)
|
||||
SupportedEnemyTypes = Array[int]([1, 0])
|
||||
Target = NodePath("../Player")
|
||||
IsActiveOnStart = false
|
||||
|
||||
@@ -42,6 +42,12 @@ public partial class Enemy : CharacterBody3D,
|
||||
[Dependency]
|
||||
public TokenManager TokenManager => this.DependOn<TokenManager>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Signals
|
||||
|
||||
[Signal] public delegate void OnKilledEventHandler(ulong instanceId);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Inspector
|
||||
@@ -188,12 +194,7 @@ public partial class Enemy : CharacterBody3D,
|
||||
|
||||
public void ProcessGameplay(double delta)
|
||||
{
|
||||
if (IsStunned())
|
||||
{
|
||||
GD.Print("Cannot attack, stunned!");
|
||||
return;
|
||||
}
|
||||
// if (_hitAbilityHandle == null) return;
|
||||
if (IsStunned()) return;
|
||||
|
||||
var bodies = DamageBox.GetOverlappingBodies();
|
||||
foreach (var body in bodies)
|
||||
@@ -253,6 +254,8 @@ public partial class Enemy : CharacterBody3D,
|
||||
{
|
||||
killable.Kill();
|
||||
}
|
||||
|
||||
EmitSignalOnKilled(GetInstanceId());
|
||||
CallDeferred(Node.MethodName.QueueFree);
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,8 @@ public partial class Explosion : Area3D, IProvide<CuesManager>
|
||||
foreach (var body in bodies)
|
||||
{
|
||||
if (body is not IForgeEntity target) continue;
|
||||
foreach (var ability in ForgeEntityNode.Abilities.GrantedAbilities.Where(ability => ability.CanActivate(out _, target)))
|
||||
foreach (var ability in ForgeEntityNode.Abilities.GrantedAbilities.Where(ability =>
|
||||
ability.CanActivate(out _, target)))
|
||||
ability.Activate(out _, target, Damage);
|
||||
}
|
||||
QueueFree();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
[gd_scene format=3 uid="uid://duju3atqgltkg"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://cnlu64l7oxvv3" path="res://scenes/explosion/Explosion.cs" id="1_82hkh"]
|
||||
[ext_resource type="Script" uid="uid://cw525n4mjqgw0" path="res://addons/forge/resources/ForgeTagContainer.cs" id="3_1ve7p"]
|
||||
[ext_resource type="Script" uid="uid://rpcbb54q4atx" path="res://forge/ForgeEntityNode.cs" id="3_wikc1"]
|
||||
[ext_resource type="Script" uid="uid://dps0oef50noil" path="res://addons/forge/nodes/ForgeEffect.cs" id="4_f5lqq"]
|
||||
[ext_resource type="Resource" uid="uid://nns16d5uhtl8" path="res://forge/resources/ability_datas/explosion_hit.tres" id="5_nphml"]
|
||||
@@ -21,6 +22,11 @@ transparency = 1
|
||||
cull_mode = 2
|
||||
albedo_color = Color(0.9607843, 0.27058825, 0, 0.7176471)
|
||||
|
||||
[sub_resource type="Resource" id="Resource_nqbbv"]
|
||||
script = ExtResource("3_1ve7p")
|
||||
ContainerTags = []
|
||||
metadata/_custom_type_script = "uid://cw525n4mjqgw0"
|
||||
|
||||
[sub_resource type="Resource" id="Resource_5c2oj"]
|
||||
script = ExtResource("5_nqbbv")
|
||||
BaseValue = 1
|
||||
@@ -71,6 +77,7 @@ surface_material_override/0 = SubResource("StandardMaterial3D_hys74")
|
||||
|
||||
[node name="ForgeEntityNode" type="Node3D" parent="." unique_id=806020391]
|
||||
script = ExtResource("3_wikc1")
|
||||
BaseTags = SubResource("Resource_nqbbv")
|
||||
metadata/_custom_type_script = "uid://rpcbb54q4atx"
|
||||
|
||||
[node name="ForgeEffect" type="Node" parent="ForgeEntityNode" unique_id=2068515708]
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
using Godot;
|
||||
using System;
|
||||
using Chickensoft.AutoInject;
|
||||
using Chickensoft.Introspection;
|
||||
using Movementtests.managers;
|
||||
|
||||
[GlobalClass, Icon("res://assets/ui/IconGodotNode/node_3D/icon_duplicate.png")]
|
||||
[GlobalClass, Icon("res://assets/ui/IconGodotNode/node_3D/icon_duplicate.png"), Meta(typeof(IAutoNode))]
|
||||
public partial class Spawner : Node3D
|
||||
{
|
||||
[Export(PropertyHint.NodeType)]
|
||||
public override void _Notification(int what) => this.Notify(what);
|
||||
|
||||
[Dependency] public WaveManager WaveManager => this.DependOn<WaveManager>();
|
||||
|
||||
[Export(PropertyHint.NodeType)]
|
||||
public PackedScene? EnemyToSpawn { get; set; }
|
||||
|
||||
[Export] public Godot.Collections.Array<EnemyDescription.EnemyType> SupportedEnemyTypes { get; set; } = [];
|
||||
|
||||
[Export]
|
||||
public RMovement? MovementInputs { get; set; }
|
||||
@@ -18,37 +27,56 @@ public partial class Spawner : Node3D
|
||||
[Export]
|
||||
public bool IsActiveOnStart { get; set; } = true;
|
||||
|
||||
private Timer _timer;
|
||||
[Node("Timer")] private Timer SpawnTimer { get; set; }
|
||||
|
||||
public override void _Ready()
|
||||
public void OnReady()
|
||||
{
|
||||
_timer = GetNode<Timer>("Timer");
|
||||
_timer.WaitTime = SpawnInterval;
|
||||
_timer.Timeout += Spawn;
|
||||
SpawnTimer.WaitTime = SpawnInterval;
|
||||
SpawnTimer.Timeout += Spawn;
|
||||
if (IsActiveOnStart) StartSpawning();
|
||||
}
|
||||
|
||||
public void OnResolved()
|
||||
{
|
||||
WaveManager.RegisterSpawner(this);
|
||||
}
|
||||
|
||||
public void Spawn()
|
||||
{
|
||||
if (EnemyToSpawn == null || !EnemyToSpawn.CanInstantiate()) return;
|
||||
|
||||
if (EnemyToSpawn.Instantiate() is not Enemy spawnedInstance) return;
|
||||
spawnedInstance.RequestReady();
|
||||
|
||||
spawnedInstance.Target = Target;
|
||||
spawnedInstance.RMovement = MovementInputs;
|
||||
if (MovementInputs != null)
|
||||
spawnedInstance.RMovement = MovementInputs;
|
||||
spawnedInstance.Init();
|
||||
|
||||
GetTree().GetCurrentScene().AddChild(spawnedInstance);
|
||||
spawnedInstance.GlobalPosition = GlobalPosition;
|
||||
}
|
||||
|
||||
public Enemy? SpawnEnemy(EnemyDescription description)
|
||||
{
|
||||
if (description.Scene.Instantiate() is not Enemy spawnedInstance) return null;
|
||||
|
||||
spawnedInstance.Target = Target;
|
||||
if (description.MovementOverride is not null)
|
||||
spawnedInstance.RMovement = description.MovementOverride;
|
||||
spawnedInstance.Init();
|
||||
|
||||
GetTree().GetCurrentScene().AddChild(spawnedInstance);
|
||||
spawnedInstance.GlobalPosition = GlobalPosition;
|
||||
return spawnedInstance;
|
||||
}
|
||||
|
||||
public void StartSpawning()
|
||||
{
|
||||
_timer.Start();
|
||||
SpawnTimer.Start();
|
||||
}
|
||||
|
||||
public void StopSpawning()
|
||||
{
|
||||
_timer.Stop();
|
||||
SpawnTimer.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
19
tools/IterableUtils.cs
Normal file
19
tools/IterableUtils.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Movementtests.tools;
|
||||
|
||||
public static class IterableUtils
|
||||
{
|
||||
private static readonly Random Rng = new Random();
|
||||
|
||||
public static void Shuffle<T>(this IList<T> list)
|
||||
{
|
||||
var n = list.Count;
|
||||
while (n > 1) {
|
||||
n--;
|
||||
var k = Rng.Next(n + 1);
|
||||
(list[k], list[n]) = (list[n], list[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
1
tools/IterableUtils.cs.uid
Normal file
1
tools/IterableUtils.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bn1ps81lsbmk0
|
||||
Reference in New Issue
Block a user