Damage calculation including elemental buff/resistance
This commit is contained in:
@@ -1,7 +1,9 @@
|
|||||||
using Chickensoft.AutoInject;
|
using Chickensoft.AutoInject;
|
||||||
|
using Chickensoft.Collections;
|
||||||
using Chickensoft.GodotNodeInterfaces;
|
using Chickensoft.GodotNodeInterfaces;
|
||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace GameJamDungeon;
|
namespace GameJamDungeon;
|
||||||
@@ -10,9 +12,9 @@ public interface IEnemy : ICharacterBody3D
|
|||||||
{
|
{
|
||||||
public IEnemyLogic EnemyLogic { get; }
|
public IEnemyLogic EnemyLogic { get; }
|
||||||
|
|
||||||
public int CurrentHP { get; set; }
|
public AutoProp<double> CurrentHP { get; set; }
|
||||||
|
|
||||||
public Resource EnemyStats { get; set; }
|
public EnemyStatInfo EnemyStatInfo { get; set; }
|
||||||
|
|
||||||
public NavigationAgent3D NavAgent { get; set; }
|
public NavigationAgent3D NavAgent { get; set; }
|
||||||
}
|
}
|
||||||
@@ -31,28 +33,28 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
|
|||||||
[Dependency] IGameRepo GameRepo => this.DependOn<IGameRepo>();
|
[Dependency] IGameRepo GameRepo => this.DependOn<IGameRepo>();
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
public Resource EnemyStats { get; set; } = new();
|
public EnemyStatInfo EnemyStatInfo { get; set; } = new();
|
||||||
|
|
||||||
public static PackedScene CollisionDetectorScene => GD.Load<PackedScene>("res://src/enemy/CollisionDetector.tscn");
|
public static PackedScene CollisionDetectorScene => GD.Load<PackedScene>("res://src/enemy/CollisionDetector.tscn");
|
||||||
|
|
||||||
public static Area3D CollisionDetector { get; set; } = default!;
|
public static Area3D CollisionDetector { get; set; } = default!;
|
||||||
|
|
||||||
public int CurrentHP { get; set; }
|
public AutoProp<double> CurrentHP { get; set; }
|
||||||
|
|
||||||
[Node] public NavigationAgent3D NavAgent { get; set; } = default!;
|
[Node] public NavigationAgent3D NavAgent { get; set; } = default!;
|
||||||
|
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
EnemyLogic = new EnemyLogic();
|
EnemyLogic = new EnemyLogic();
|
||||||
EnemyLogic.Set(EnemyStats);
|
EnemyLogic.Set(EnemyStatInfo);
|
||||||
EnemyLogic.Set(this as IEnemy);
|
EnemyLogic.Set(this as IEnemy);
|
||||||
EnemyLogic.Set(GameRepo);
|
EnemyLogic.Set(GameRepo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
var enemyResource = EnemyStats as EnemyStats;
|
CurrentHP = new AutoProp<double>(EnemyStatInfo.MaximumHP);
|
||||||
CurrentHP = enemyResource.MaximumHP;
|
CurrentHP.Sync += OnHPChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnResolved()
|
public void OnResolved()
|
||||||
@@ -71,7 +73,6 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
|
|||||||
})
|
})
|
||||||
.Handle((in EnemyLogic.Output.Die output) =>
|
.Handle((in EnemyLogic.Output.Die output) =>
|
||||||
{
|
{
|
||||||
CollisionDetector.Dispose();
|
|
||||||
QueueFree();
|
QueueFree();
|
||||||
})
|
})
|
||||||
.Handle((in EnemyLogic.Output.HitByPlayer output) =>
|
.Handle((in EnemyLogic.Output.HitByPlayer output) =>
|
||||||
@@ -112,14 +113,21 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
|
|||||||
{
|
{
|
||||||
if (body is IHitbox hitBox)
|
if (body is IHitbox hitBox)
|
||||||
{
|
{
|
||||||
if (CurrentHP > 0)
|
if (CurrentHP.Value > 0)
|
||||||
{
|
{
|
||||||
GD.Print("Enemy Hit");
|
var damage = DamageCalculator.CalculatePlayerDamage(hitBox.Damage, hitBox.GetParent<IPlayer>().PlayerStatInfo, EnemyStatInfo);
|
||||||
EnemyLogic.Input(new EnemyLogic.Input.HitByPlayer(hitBox.Damage));
|
GD.Print($"Enemy Hit for {damage} damage.");
|
||||||
|
EnemyLogic.Input(new EnemyLogic.Input.HitByPlayer(damage));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnHPChanged(double newHP)
|
||||||
|
{
|
||||||
|
if (newHP <= 0)
|
||||||
|
EnemyLogic.Input(new EnemyLogic.Input.Killed());
|
||||||
|
}
|
||||||
|
|
||||||
public void OnReady()
|
public void OnReady()
|
||||||
{
|
{
|
||||||
SetPhysicsProcess(true);
|
SetPhysicsProcess(true);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[gd_scene load_steps=3 format=3 uid="uid://dbvr8ewajja6a"]
|
[gd_scene load_steps=3 format=3 uid="uid://dbvr8ewajja6a"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://src/enemy/EnemyDatabase.cs" id="1_ywy58"]
|
[ext_resource type="Script" path="res://src/enemy/EnemyDatabase.cs" id="1_ywy58"]
|
||||||
[ext_resource type="PackedScene" uid="uid://dcgj5i52i76gj" path="res://src/enemy/enemy_types/FloatingEnemy.tscn" id="2_8cbrh"]
|
[ext_resource type="PackedScene" uid="uid://dcgj5i52i76gj" path="res://src/enemy/enemy_types/floating_enemy/FloatingEnemy.tscn" id="2_8cbrh"]
|
||||||
|
|
||||||
[node name="EnemyDatabase" type="Node"]
|
[node name="EnemyDatabase" type="Node"]
|
||||||
script = ExtResource("1_ywy58")
|
script = ExtResource("1_ywy58")
|
||||||
|
|||||||
26
src/enemy/EnemyStatInfo.cs
Normal file
26
src/enemy/EnemyStatInfo.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace GameJamDungeon
|
||||||
|
{
|
||||||
|
[GlobalClass]
|
||||||
|
public partial class EnemyStatInfo : Resource, ICharacterStats
|
||||||
|
{
|
||||||
|
[Export]
|
||||||
|
public double MaximumHP { get; set; }
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public int BaseAttack { get; set; }
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public int BaseDefense { get; set; }
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public double ElementAResistance { get; set; }
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public double ElementBResistance { get; set; }
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public double ElementCResistance { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
using Godot;
|
|
||||||
|
|
||||||
namespace GameJamDungeon
|
|
||||||
{
|
|
||||||
[GlobalClass]
|
|
||||||
public partial class EnemyStats : Resource
|
|
||||||
{
|
|
||||||
[Export(PropertyHint.Range, "0, 100, 1")]
|
|
||||||
public int MaximumHP = 1;
|
|
||||||
|
|
||||||
[Export]
|
|
||||||
public string Name = string.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
[gd_resource type="Resource" script_class="EnemyStats" load_steps=2 format=3 uid="uid://bcsyqy7rmbpbl"]
|
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://src/enemy/EnemyStats.cs" id="1_0ks7j"]
|
|
||||||
|
|
||||||
[resource]
|
|
||||||
script = ExtResource("1_0ks7j")
|
|
||||||
MaximumHP = 12
|
|
||||||
Name = "Floating Guy"
|
|
||||||
@@ -4,12 +4,12 @@ importer="scene"
|
|||||||
importer_version=1
|
importer_version=1
|
||||||
type="PackedScene"
|
type="PackedScene"
|
||||||
uid="uid://cli0nlukrd4dc"
|
uid="uid://cli0nlukrd4dc"
|
||||||
path="res://.godot/imported/DISSAPPEARING ENEMY.gltf-86890683bfa8a9cc2bc15c917a019516.scn"
|
path="res://.godot/imported/DISSAPPEARING ENEMY.gltf-623f05c3c418a59abcec04651db9cb14.scn"
|
||||||
|
|
||||||
[deps]
|
[deps]
|
||||||
|
|
||||||
source_file="res://src/enemy/enemy_types/DISSAPPEARING ENEMY.gltf"
|
source_file="res://src/enemy/enemy_types/floating_enemy/DISSAPPEARING ENEMY.gltf"
|
||||||
dest_files=["res://.godot/imported/DISSAPPEARING ENEMY.gltf-86890683bfa8a9cc2bc15c917a019516.scn"]
|
dest_files=["res://.godot/imported/DISSAPPEARING ENEMY.gltf-623f05c3c418a59abcec04651db9cb14.scn"]
|
||||||
|
|
||||||
[params]
|
[params]
|
||||||
|
|
||||||
12
src/enemy/enemy_types/floating_enemy/FloatingEnemy.tres
Normal file
12
src/enemy/enemy_types/floating_enemy/FloatingEnemy.tres
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
[gd_resource type="Resource" script_class="EnemyStatInfo" load_steps=2 format=3 uid="uid://c8h26ip4ly18r"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://src/enemy/EnemyStatInfo.cs" id="1_oabqi"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
script = ExtResource("1_oabqi")
|
||||||
|
MaximumHP = 50.0
|
||||||
|
BaseAttack = 2
|
||||||
|
BaseDefense = 1
|
||||||
|
ElementAResistance = 15.0
|
||||||
|
ElementBResistance = -20.0
|
||||||
|
ElementCResistance = 0.0
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
[gd_scene load_steps=9 format=4 uid="uid://dcgj5i52i76gj"]
|
[gd_scene load_steps=9 format=4 uid="uid://dcgj5i52i76gj"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://src/enemy/Enemy.cs" id="1_4d86o"]
|
[ext_resource type="Script" path="res://src/enemy/Enemy.cs" id="1_jw471"]
|
||||||
[ext_resource type="Resource" uid="uid://bcsyqy7rmbpbl" path="res://src/enemy/enemy_types/FloatingEnemy.tres" id="2_q8v6p"]
|
[ext_resource type="Resource" uid="uid://c8h26ip4ly18r" path="res://src/enemy/enemy_types/floating_enemy/FloatingEnemy.tres" id="2_ewaf6"]
|
||||||
|
|
||||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_5tio6"]
|
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_5tio6"]
|
||||||
resource_name = "Material.001"
|
resource_name = "Material.001"
|
||||||
@@ -109,8 +109,8 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, 0)
|
|||||||
collision_layer = 10
|
collision_layer = 10
|
||||||
collision_mask = 9
|
collision_mask = 9
|
||||||
motion_mode = 1
|
motion_mode = 1
|
||||||
script = ExtResource("1_4d86o")
|
script = ExtResource("1_jw471")
|
||||||
EnemyStats = ExtResource("2_q8v6p")
|
EnemyStatInfo = ExtResource("2_ewaf6")
|
||||||
|
|
||||||
[node name="DISSAPPEARING ENEMY" type="Node3D" parent="."]
|
[node name="DISSAPPEARING ENEMY" type="Node3D" parent="."]
|
||||||
|
|
||||||
@@ -10,7 +10,9 @@
|
|||||||
|
|
||||||
public readonly record struct PhysicsTick(double Delta);
|
public readonly record struct PhysicsTick(double Delta);
|
||||||
|
|
||||||
public readonly record struct HitByPlayer(int Damage);
|
public readonly record struct HitByPlayer(double Damage);
|
||||||
|
|
||||||
|
public readonly record struct Killed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace GameJamDungeon
|
|||||||
|
|
||||||
public readonly record struct MovementComputed(Vector3 Velocity);
|
public readonly record struct MovementComputed(Vector3 Velocity);
|
||||||
|
|
||||||
public readonly record struct HitByPlayer(int CurrentHP);
|
public readonly record struct HitByPlayer(double CurrentHP);
|
||||||
|
|
||||||
public readonly record struct Die();
|
public readonly record struct Die();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,23 +8,25 @@ namespace GameJamDungeon
|
|||||||
public partial record State
|
public partial record State
|
||||||
{
|
{
|
||||||
[Meta, Id("enemy_logic_state_alive")]
|
[Meta, Id("enemy_logic_state_alive")]
|
||||||
public abstract partial record Alive : State, IGet<Input.HitByPlayer>
|
public abstract partial record Alive : State, IGet<Input.HitByPlayer>, IGet<Input.Killed>
|
||||||
{
|
{
|
||||||
public Transition On(in Input.HitByPlayer input)
|
public Transition On(in Input.HitByPlayer input)
|
||||||
{
|
{
|
||||||
var enemy = Get<IEnemy>();
|
var enemy = Get<IEnemy>();
|
||||||
var gameRepo = Get<IGameRepo>();
|
enemy.CurrentHP.OnNext(enemy.CurrentHP.Value - input.Damage);
|
||||||
enemy.CurrentHP -= input.Damage;
|
GD.Print("Current HP: " + enemy.CurrentHP.Value);
|
||||||
GD.Print("Current HP: " + enemy.CurrentHP);
|
|
||||||
GD.Print($"Hit by {gameRepo.EquippedWeapon.Name}");
|
|
||||||
Output(new Output.HitByPlayer());
|
Output(new Output.HitByPlayer());
|
||||||
if (enemy.CurrentHP <= 0)
|
|
||||||
Output(new Output.Die());
|
|
||||||
|
|
||||||
Input(new Input.Alerted());
|
Input(new Input.Alerted());
|
||||||
|
|
||||||
return ToSelf();
|
return ToSelf();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Transition On(in Input.Killed input)
|
||||||
|
{
|
||||||
|
Output(new Output.Die());
|
||||||
|
return To<Idle>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
[gd_scene load_steps=12 format=3 uid="uid://33ek675mfb5n"]
|
[gd_scene load_steps=14 format=3 uid="uid://33ek675mfb5n"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://src/game/Game.cs" id="1_ytcii"]
|
[ext_resource type="Script" path="res://src/game/Game.cs" id="1_ytcii"]
|
||||||
[ext_resource type="PackedScene" uid="uid://wg25dg65ksgg" path="res://src/map/dungeon/DungeonGenerator.tscn" id="2_cgboj"]
|
|
||||||
[ext_resource type="PackedScene" uid="uid://cfecvvav8kkp6" path="res://src/player/Player.tscn" id="3_kk6ly"]
|
[ext_resource type="PackedScene" uid="uid://cfecvvav8kkp6" path="res://src/player/Player.tscn" id="3_kk6ly"]
|
||||||
[ext_resource type="PackedScene" uid="uid://dhpwwqow1ahrc" path="res://src/map/dungeon/rooms/Room1.tscn" id="4_56rmd"]
|
|
||||||
[ext_resource type="PackedScene" uid="uid://bbwgmqy3evhh2" path="res://src/map/dungeon/rooms/Room2.tscn" id="4_clpvl"]
|
|
||||||
[ext_resource type="PackedScene" uid="uid://dlj8qdg1c5048" path="res://src/inventory_menu/InventoryMenu.tscn" id="4_wk8gw"]
|
[ext_resource type="PackedScene" uid="uid://dlj8qdg1c5048" path="res://src/inventory_menu/InventoryMenu.tscn" id="4_wk8gw"]
|
||||||
|
[ext_resource type="Script" path="res://addons/SimpleDungeons/DungeonGenerator3D.gd" id="5_fqkhg"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://dhpwwqow1ahrc" path="res://src/map/dungeon/rooms/Room1.tscn" id="6_04w8n"]
|
||||||
[ext_resource type="PackedScene" uid="uid://bwbofurcvf3yh" path="res://src/minimap/Minimap.tscn" id="6_owlf4"]
|
[ext_resource type="PackedScene" uid="uid://bwbofurcvf3yh" path="res://src/minimap/Minimap.tscn" id="6_owlf4"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://bn4gslp2gk8ds" path="res://src/map/dungeon/corridor/Corridor.tscn" id="6_swtay"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://bbwgmqy3evhh2" path="res://src/map/dungeon/rooms/Room2.tscn" id="7_1ynbc"]
|
||||||
|
[ext_resource type="Script" path="res://addons/SimpleDungeons/DungeonRoom3D.gd" id="9_p0lbc"]
|
||||||
|
|
||||||
[sub_resource type="Environment" id="Environment_fke5g"]
|
[sub_resource type="Environment" id="Environment_fke5g"]
|
||||||
|
|
||||||
@@ -57,8 +59,100 @@ omni_attenuation = -0.183
|
|||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
navigation_mesh = SubResource("NavigationMesh_xligp")
|
navigation_mesh = SubResource("NavigationMesh_xligp")
|
||||||
|
|
||||||
[node name="DungeonGenerator3D" parent="NavigationRegion" instance=ExtResource("2_cgboj")]
|
[node name="DungeonGenerator3D" type="Node3D" parent="."]
|
||||||
room_scenes = Array[PackedScene]([ExtResource("4_56rmd"), ExtResource("4_clpvl")])
|
script = ExtResource("5_fqkhg")
|
||||||
corridor_cost_multiplier = 1.0
|
room_scenes = Array[PackedScene]([ExtResource("6_04w8n"), ExtResource("7_1ynbc")])
|
||||||
room_cost_multiplier = 8.0
|
corridor_room_scene = ExtResource("6_swtay")
|
||||||
room_cost_at_end_for_required_doors = 1.0
|
dungeon_size = Vector3i(10, 1, 10)
|
||||||
|
|
||||||
|
[node name="RoomsContainer" type="Node3D" parent="DungeonGenerator3D"]
|
||||||
|
|
||||||
|
[node name="DungeonRoom3D_0" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("7_1ynbc")]
|
||||||
|
transform = Transform3D(1.19249e-08, 0, -1, 0, 1, 0, 1, 0, 1.19249e-08, -15, 0, 15)
|
||||||
|
script = ExtResource("9_p0lbc")
|
||||||
|
size_in_voxels = Vector3i(5, 1, 1)
|
||||||
|
|
||||||
|
[node name="DungeonRoom3D_1" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_04w8n")]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -15, 0, -35)
|
||||||
|
script = ExtResource("9_p0lbc")
|
||||||
|
|
||||||
|
[node name="DungeonRoom3D_2" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_04w8n")]
|
||||||
|
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 25, 0, -45)
|
||||||
|
script = ExtResource("9_p0lbc")
|
||||||
|
|
||||||
|
[node name="DungeonRoom3D_3" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("7_1ynbc")]
|
||||||
|
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 15, 0, -25)
|
||||||
|
script = ExtResource("9_p0lbc")
|
||||||
|
size_in_voxels = Vector3i(5, 1, 1)
|
||||||
|
|
||||||
|
[node name="Corridor_4" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -15, 0, -15)
|
||||||
|
script = ExtResource("9_p0lbc")
|
||||||
|
|
||||||
|
[node name="Corridor_5" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -15, 0, -25)
|
||||||
|
script = ExtResource("9_p0lbc")
|
||||||
|
|
||||||
|
[node name="Corridor_6" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -15, 0, -45)
|
||||||
|
script = ExtResource("9_p0lbc")
|
||||||
|
|
||||||
|
[node name="Corridor_7" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5, 0, -45)
|
||||||
|
script = ExtResource("9_p0lbc")
|
||||||
|
|
||||||
|
[node name="Corridor_8" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 5, 0, -45)
|
||||||
|
script = ExtResource("9_p0lbc")
|
||||||
|
|
||||||
|
[node name="Corridor_9" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 15, 0, -45)
|
||||||
|
script = ExtResource("9_p0lbc")
|
||||||
|
|
||||||
|
[node name="Corridor_10" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -15, 0, 45)
|
||||||
|
script = ExtResource("9_p0lbc")
|
||||||
|
|
||||||
|
[node name="Corridor_11" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -25, 0, 45)
|
||||||
|
script = ExtResource("9_p0lbc")
|
||||||
|
|
||||||
|
[node name="Corridor_12" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -25, 0, 35)
|
||||||
|
script = ExtResource("9_p0lbc")
|
||||||
|
|
||||||
|
[node name="Corridor_13" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -25, 0, 25)
|
||||||
|
script = ExtResource("9_p0lbc")
|
||||||
|
|
||||||
|
[node name="Corridor_14" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -25, 0, 15)
|
||||||
|
script = ExtResource("9_p0lbc")
|
||||||
|
|
||||||
|
[node name="Corridor_15" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -25, 0, 5)
|
||||||
|
script = ExtResource("9_p0lbc")
|
||||||
|
|
||||||
|
[node name="Corridor_16" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -25, 0, -5)
|
||||||
|
script = ExtResource("9_p0lbc")
|
||||||
|
|
||||||
|
[node name="Corridor_17" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -25, 0, -15)
|
||||||
|
script = ExtResource("9_p0lbc")
|
||||||
|
|
||||||
|
[node name="Corridor_18" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 35, 0, -45)
|
||||||
|
script = ExtResource("9_p0lbc")
|
||||||
|
|
||||||
|
[node name="Corridor_19" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 35, 0, -35)
|
||||||
|
script = ExtResource("9_p0lbc")
|
||||||
|
|
||||||
|
[node name="Corridor_20" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 45, 0, -35)
|
||||||
|
script = ExtResource("9_p0lbc")
|
||||||
|
|
||||||
|
[node name="Corridor_21" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 45, 0, -25)
|
||||||
|
script = ExtResource("9_p0lbc")
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
[gd_scene load_steps=19 format=3 uid="uid://dhpwwqow1ahrc"]
|
[gd_scene load_steps=17 format=3 uid="uid://dhpwwqow1ahrc"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://addons/SimpleDungeons/DungeonRoom3D.gd" id="1_0tfda"]
|
[ext_resource type="Script" path="res://addons/SimpleDungeons/DungeonRoom3D.gd" id="1_0tfda"]
|
||||||
[ext_resource type="Script" path="res://src/map/dungeon/rooms/DungeonRoom.cs" id="1_ti7ur"]
|
[ext_resource type="Script" path="res://src/map/dungeon/rooms/DungeonRoom.cs" id="1_ti7ur"]
|
||||||
@@ -6,10 +6,8 @@
|
|||||||
[ext_resource type="PackedScene" uid="uid://twrj4wixcbu7" path="res://src/items/ItemDatabase.tscn" id="4_2mnb7"]
|
[ext_resource type="PackedScene" uid="uid://twrj4wixcbu7" path="res://src/items/ItemDatabase.tscn" id="4_2mnb7"]
|
||||||
[ext_resource type="PackedScene" uid="uid://b6atdgf2e6e2t" path="res://src/items/weapons/models/CommonSword.tscn" id="4_chdi8"]
|
[ext_resource type="PackedScene" uid="uid://b6atdgf2e6e2t" path="res://src/items/weapons/models/CommonSword.tscn" id="4_chdi8"]
|
||||||
[ext_resource type="PackedScene" uid="uid://dbvr8ewajja6a" path="res://src/enemy/EnemyDatabase.tscn" id="5_owpbq"]
|
[ext_resource type="PackedScene" uid="uid://dbvr8ewajja6a" path="res://src/enemy/EnemyDatabase.tscn" id="5_owpbq"]
|
||||||
[ext_resource type="PackedScene" uid="uid://dcgj5i52i76gj" path="res://src/enemy/enemy_types/FloatingEnemy.tscn" id="5_urvkv"]
|
|
||||||
[ext_resource type="PackedScene" uid="uid://cbb1fxllrnlyr" path="res://src/items/weapons/models/UncommonSword.tscn" id="5_viqv4"]
|
[ext_resource type="PackedScene" uid="uid://cbb1fxllrnlyr" path="res://src/items/weapons/models/UncommonSword.tscn" id="5_viqv4"]
|
||||||
[ext_resource type="PackedScene" uid="uid://c10nhqq8su6pp" path="res://src/items/weapons/models/RareSword.tscn" id="6_c8gn4"]
|
[ext_resource type="PackedScene" uid="uid://c10nhqq8su6pp" path="res://src/items/weapons/models/RareSword.tscn" id="6_c8gn4"]
|
||||||
[ext_resource type="PackedScene" uid="uid://u1vmmakcoplh" path="res://src/enemy/enemy_types/Capricorn/Capricorn.tscn" id="6_hp0mx"]
|
|
||||||
[ext_resource type="PackedScene" uid="uid://dorr7v1tkeiy0" path="res://src/items/armor/Armor.tscn" id="7_bm50w"]
|
[ext_resource type="PackedScene" uid="uid://dorr7v1tkeiy0" path="res://src/items/armor/Armor.tscn" id="7_bm50w"]
|
||||||
|
|
||||||
[sub_resource type="PlaneMesh" id="PlaneMesh_luhnj"]
|
[sub_resource type="PlaneMesh" id="PlaneMesh_luhnj"]
|
||||||
@@ -71,8 +69,6 @@ DropRate = PackedFloat32Array(0.25, 0.25, 0.25, 0.25)
|
|||||||
|
|
||||||
[node name="EnemyDatabase" parent="." instance=ExtResource("5_owpbq")]
|
[node name="EnemyDatabase" parent="." instance=ExtResource("5_owpbq")]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
EnemyList = Array[PackedScene]([ExtResource("5_urvkv"), ExtResource("6_hp0mx")])
|
|
||||||
SpawnRate = PackedFloat32Array(0.1, 0.9)
|
|
||||||
|
|
||||||
[node name="CSGBox3D" type="CSGBox3D" parent="."]
|
[node name="CSGBox3D" type="CSGBox3D" parent="."]
|
||||||
use_collision = true
|
use_collision = true
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ namespace GameJamDungeon
|
|||||||
{
|
{
|
||||||
public interface IPlayer : ICharacterBody3D
|
public interface IPlayer : ICharacterBody3D
|
||||||
{
|
{
|
||||||
|
PlayerStatInfo PlayerStatInfo { get; }
|
||||||
|
|
||||||
PlayerLogic PlayerLogic { get; }
|
PlayerLogic PlayerLogic { get; }
|
||||||
|
|
||||||
PlayerData PlayerData { get; }
|
PlayerData PlayerData { get; }
|
||||||
@@ -46,6 +48,9 @@ namespace GameJamDungeon
|
|||||||
[Export(PropertyHint.Range, "0, 100, 0.1")]
|
[Export(PropertyHint.Range, "0, 100, 0.1")]
|
||||||
public float Acceleration { get; set; } = 4f;
|
public float Acceleration { get; set; } = 4f;
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public PlayerStatInfo PlayerStatInfo { get; set; }
|
||||||
|
|
||||||
public PlayerLogic.Settings Settings { get; set; } = default!;
|
public PlayerLogic.Settings Settings { get; set; } = default!;
|
||||||
|
|
||||||
public PlayerLogic PlayerLogic { get; set; } = default!;
|
public PlayerLogic PlayerLogic { get; set; } = default!;
|
||||||
@@ -62,6 +67,10 @@ namespace GameJamDungeon
|
|||||||
|
|
||||||
private IAutoProp<WeaponInfo> EquippedWeapon { get; set; } = default!;
|
private IAutoProp<WeaponInfo> EquippedWeapon { get; set; } = default!;
|
||||||
|
|
||||||
|
private AutoProp<double> _currentHP { get; set; } = default!;
|
||||||
|
|
||||||
|
private IAutoProp<int> _currentVT { get; set; } = default!;
|
||||||
|
|
||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
AnimationPlayer.AnimationFinished += OnAnimationFinished;
|
AnimationPlayer.AnimationFinished += OnAnimationFinished;
|
||||||
@@ -69,9 +78,7 @@ namespace GameJamDungeon
|
|||||||
|
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
Settings = new PlayerLogic.Settings(
|
Settings = new PlayerLogic.Settings(RotationSpeed, MoveSpeed);
|
||||||
RotationSpeed,
|
|
||||||
MoveSpeed);
|
|
||||||
|
|
||||||
PlayerLogic = new PlayerLogic();
|
PlayerLogic = new PlayerLogic();
|
||||||
PlayerLogic.Set(this as IPlayer);
|
PlayerLogic.Set(this as IPlayer);
|
||||||
@@ -82,6 +89,8 @@ namespace GameJamDungeon
|
|||||||
|
|
||||||
GameRepo.SetPlayerGlobalPosition(GlobalPosition);
|
GameRepo.SetPlayerGlobalPosition(GlobalPosition);
|
||||||
EquippedWeapon = new AutoProp<WeaponInfo>(WeaponInfo.Default);
|
EquippedWeapon = new AutoProp<WeaponInfo>(WeaponInfo.Default);
|
||||||
|
_currentHP = new AutoProp<double>(PlayerStatInfo.MaximumHP);
|
||||||
|
_currentVT = new AutoProp<int>(PlayerStatInfo.MaximumVT);
|
||||||
GameRepo.PlayerGlobalPosition.Sync += OnPlayerPositionUpdated;
|
GameRepo.PlayerGlobalPosition.Sync += OnPlayerPositionUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,6 +117,7 @@ namespace GameJamDungeon
|
|||||||
PlayerLogic.Start();
|
PlayerLogic.Start();
|
||||||
|
|
||||||
EquippedWeapon.Sync += OnEquippedWeaponChanged;
|
EquippedWeapon.Sync += OnEquippedWeaponChanged;
|
||||||
|
_currentHP.Sync += OnHPChanged;
|
||||||
SwordSlashAnimation.Position = GetViewport().GetVisibleRect().Size / 2;
|
SwordSlashAnimation.Position = GetViewport().GetVisibleRect().Size / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,6 +176,12 @@ namespace GameJamDungeon
|
|||||||
|
|
||||||
private void OnEquippedWeaponChanged(WeaponInfo info) => Hitbox.Damage = info.Damage;
|
private void OnEquippedWeaponChanged(WeaponInfo info) => Hitbox.Damage = info.Damage;
|
||||||
|
|
||||||
|
private void OnHPChanged(double newHP)
|
||||||
|
{
|
||||||
|
if (newHP <= 0.0)
|
||||||
|
PlayerLogic.Input(new PlayerLogic.Input.Killed());
|
||||||
|
}
|
||||||
|
|
||||||
private void OnPlayerPositionUpdated(Vector3 globalPosition) => GlobalPosition = globalPosition;
|
private void OnPlayerPositionUpdated(Vector3 globalPosition) => GlobalPosition = globalPosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
[gd_scene load_steps=16 format=3 uid="uid://cfecvvav8kkp6"]
|
[gd_scene load_steps=17 format=3 uid="uid://cfecvvav8kkp6"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://src/player/Player.cs" id="1_xcol5"]
|
[ext_resource type="Script" path="res://src/player/Player.cs" id="1_xcol5"]
|
||||||
[ext_resource type="Texture2D" uid="uid://bokx3h8kfdo5i" path="res://src/player/slash_0000_Classic_30.png" id="2_la11l"]
|
[ext_resource type="Texture2D" uid="uid://bokx3h8kfdo5i" path="res://src/player/slash_0000_Classic_30.png" id="2_la11l"]
|
||||||
[ext_resource type="Script" path="res://src/hitbox/Hitbox.cs" id="2_lb3qc"]
|
[ext_resource type="Script" path="res://src/hitbox/Hitbox.cs" id="2_lb3qc"]
|
||||||
|
[ext_resource type="Resource" uid="uid://cofd1ylluj24" path="res://src/player/PlayerStats.tres" id="2_nuh2a"]
|
||||||
[ext_resource type="Texture2D" uid="uid://byosr5gk51237" path="res://src/player/slash_0001_Classic_29.png" id="3_ux3f1"]
|
[ext_resource type="Texture2D" uid="uid://byosr5gk51237" path="res://src/player/slash_0001_Classic_29.png" id="3_ux3f1"]
|
||||||
[ext_resource type="Texture2D" uid="uid://nh071o6ii03j" path="res://src/player/slash_0002_Classic_28.png" id="4_gqnq0"]
|
[ext_resource type="Texture2D" uid="uid://nh071o6ii03j" path="res://src/player/slash_0002_Classic_28.png" id="4_gqnq0"]
|
||||||
[ext_resource type="Texture2D" uid="uid://bodfblud4kea3" path="res://src/player/slash_0003_Classic_27.png" id="5_eebal"]
|
[ext_resource type="Texture2D" uid="uid://bodfblud4kea3" path="res://src/player/slash_0003_Classic_27.png" id="5_eebal"]
|
||||||
@@ -117,6 +118,7 @@ axis_lock_angular_z = true
|
|||||||
motion_mode = 1
|
motion_mode = 1
|
||||||
script = ExtResource("1_xcol5")
|
script = ExtResource("1_xcol5")
|
||||||
RotationSpeed = 0.025
|
RotationSpeed = 0.025
|
||||||
|
PlayerStatInfo = ExtResource("2_nuh2a")
|
||||||
|
|
||||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.937567, 0)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.937567, 0)
|
||||||
|
|||||||
@@ -18,5 +18,14 @@ namespace GameJamDungeon
|
|||||||
|
|
||||||
[Save("PlayerInventory")]
|
[Save("PlayerInventory")]
|
||||||
public required IEnumerable<InventoryItemInfo> Inventory { get; set; }
|
public required IEnumerable<InventoryItemInfo> Inventory { get; set; }
|
||||||
|
|
||||||
|
[Save("PlayerStats")]
|
||||||
|
public required PlayerStatInfo PlayerStats { get; set; }
|
||||||
|
|
||||||
|
[Save("CurrentHP")]
|
||||||
|
public required int CurrentHP { get; set; }
|
||||||
|
|
||||||
|
[Save("CurrentVT")]
|
||||||
|
public required int CurrentVT { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
38
src/player/PlayerStatInfo.cs
Normal file
38
src/player/PlayerStatInfo.cs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace GameJamDungeon
|
||||||
|
{
|
||||||
|
[GlobalClass]
|
||||||
|
public partial class PlayerStatInfo : Resource, ICharacterStats
|
||||||
|
{
|
||||||
|
[Export]
|
||||||
|
public double MaximumHP { get; set; }
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public int MaximumVT { get; set; }
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public int BaseAttack { get; set; }
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public int BaseDefense { get; set; }
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public double ElementAResistance { get; set; }
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public double ElementBResistance { get; set; }
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public double ElementCResistance { get; set; }
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public double BaseElementADamageBonus { get; set; }
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public double BaseElementBDamageBonus { get; set; }
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public double BaseElementCDamageBonus { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/player/PlayerStats.tres
Normal file
16
src/player/PlayerStats.tres
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
[gd_resource type="Resource" script_class="PlayerStatInfo" load_steps=2 format=3 uid="uid://cofd1ylluj24"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://src/player/PlayerStatInfo.cs" id="1_a84hi"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
script = ExtResource("1_a84hi")
|
||||||
|
MaximumHP = 120.0
|
||||||
|
MaximumVT = 90
|
||||||
|
BaseAttack = 10
|
||||||
|
BaseDefense = 0
|
||||||
|
ElementAResistance = 0.0
|
||||||
|
ElementBResistance = 0.0
|
||||||
|
ElementCResistance = 15.0
|
||||||
|
BaseElementADamageBonus = 30.0
|
||||||
|
BaseElementBDamageBonus = 15.0
|
||||||
|
BaseElementCDamageBonus = 20.0
|
||||||
@@ -15,6 +15,8 @@ namespace GameJamDungeon
|
|||||||
public readonly record struct Attack;
|
public readonly record struct Attack;
|
||||||
|
|
||||||
public readonly record struct AttackAnimationFinished;
|
public readonly record struct AttackAnimationFinished;
|
||||||
|
|
||||||
|
public readonly record struct Killed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace GameJamDungeon
|
|||||||
public partial record State
|
public partial record State
|
||||||
{
|
{
|
||||||
[Meta, Id("player_logic_alive")]
|
[Meta, Id("player_logic_alive")]
|
||||||
public abstract partial record Alive : State, IGet<Input.PhysicsTick>, IGet<Input.Moved>
|
public abstract partial record Alive : State, IGet<Input.PhysicsTick>, IGet<Input.Moved>, IGet<Input.Killed>
|
||||||
{
|
{
|
||||||
public virtual Transition On(in Input.PhysicsTick input)
|
public virtual Transition On(in Input.PhysicsTick input)
|
||||||
{
|
{
|
||||||
@@ -36,9 +36,14 @@ namespace GameJamDungeon
|
|||||||
{
|
{
|
||||||
var gameRepo = Get<IGameRepo>();
|
var gameRepo = Get<IGameRepo>();
|
||||||
gameRepo.SetPlayerGlobalPosition(input.GlobalPosition);
|
gameRepo.SetPlayerGlobalPosition(input.GlobalPosition);
|
||||||
GD.Print($"Current position: {input.GlobalPosition}");
|
|
||||||
return ToSelf();
|
return ToSelf();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Transition On(in Input.Killed input)
|
||||||
|
{
|
||||||
|
GD.Print("Player died");
|
||||||
|
return To<Disabled>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
18
src/system/stats/DamageCalculator.cs
Normal file
18
src/system/stats/DamageCalculator.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace GameJamDungeon
|
||||||
|
{
|
||||||
|
public static class DamageCalculator
|
||||||
|
{
|
||||||
|
public static double CalculatePlayerDamage(int attackDamage, PlayerStatInfo playerStatInfo, EnemyStatInfo enemyStatInfo)
|
||||||
|
{
|
||||||
|
var baseDamage = attackDamage + playerStatInfo.BaseAttack;
|
||||||
|
var elementADamage = (playerStatInfo.BaseElementADamageBonus > 0 ? playerStatInfo.BaseElementADamageBonus - enemyStatInfo.ElementAResistance : 0) / 100;
|
||||||
|
var elementBDamage = (playerStatInfo.BaseElementBDamageBonus > 0 ? playerStatInfo.BaseElementBDamageBonus - enemyStatInfo.ElementBResistance : 0) / 100;
|
||||||
|
var elementCDamage = (playerStatInfo.BaseElementCDamageBonus > 0 ? playerStatInfo.BaseElementCDamageBonus - enemyStatInfo.ElementCResistance : 0) / 100;
|
||||||
|
var elementalBonusDamage = baseDamage + (baseDamage * elementADamage) + (baseDamage * elementBDamage) + (baseDamage * elementCDamage);
|
||||||
|
var calculatedDamage = elementalBonusDamage - enemyStatInfo.BaseDefense;
|
||||||
|
return calculatedDamage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/system/stats/ICharacterStats.cs
Normal file
17
src/system/stats/ICharacterStats.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
namespace GameJamDungeon
|
||||||
|
{
|
||||||
|
public interface ICharacterStats
|
||||||
|
{
|
||||||
|
public double MaximumHP { get; }
|
||||||
|
|
||||||
|
public int BaseAttack { get; }
|
||||||
|
|
||||||
|
public int BaseDefense { get; }
|
||||||
|
|
||||||
|
public double ElementAResistance { get; }
|
||||||
|
|
||||||
|
public double ElementBResistance { get; }
|
||||||
|
|
||||||
|
public double ElementCResistance { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user