combat system

item-info
John Montagu, the 4th Earl of Sandvich 2022-11-25 09:11:46 -08:00
parent ffd58c5029
commit 32c5eb395e
36 changed files with 781 additions and 148 deletions

Binary file not shown.

View File

@ -0,0 +1,32 @@
[remap]
importer="font_data_dynamic"
type="FontFile"
uid="uid://cgwa8bjiyv534"
path="res://.godot/imported/alagard.ttf-ed7015ed0e84e70ec06fd3d65515ce04.fontdata"
[deps]
source_file="res://Assets/Fonts/alagard.ttf"
dest_files=["res://.godot/imported/alagard.ttf-ed7015ed0e84e70ec06fd3d65515ce04.fontdata"]
[params]
Rendering=null
antialiasing=0
generate_mipmaps=false
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
force_autohinter=false
hinting=1
subpixel_positioning=1
oversampling=0.0
Fallbacks=null
fallbacks=[]
Compress=null
compress=true
preload=[]
language_support={}
script_support={}
opentype_features={}

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -3,15 +3,15 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://dxymfduyrbuvx"
path="res://.godot/imported/forsen.png-fce73bdb02d4ae9ad3a1c7a29f120a10.ctex"
path="res://.godot/imported/forsen.png-c75844516d35dfe104cf50cd521a7820.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Sprites/Characters/forsen.png"
dest_files=["res://.godot/imported/forsen.png-fce73bdb02d4ae9ad3a1c7a29f120a10.ctex"]
source_file="res://Assets/Sprites/Characters/forsen.png"
dest_files=["res://.godot/imported/forsen.png-c75844516d35dfe104cf50cd521a7820.ctex"]
[params]

View File

Before

Width:  |  Height:  |  Size: 310 B

After

Width:  |  Height:  |  Size: 310 B

View File

@ -3,15 +3,15 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://dt6u8p4h6g7le"
path="res://.godot/imported/knife.png-95e39b161a14477923b7daae97a5ccae.ctex"
path="res://.godot/imported/knife.png-29bc4ddc148b964cb9b086eec2187a96.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Sprites/knife.png"
dest_files=["res://.godot/imported/knife.png-95e39b161a14477923b7daae97a5ccae.ctex"]
source_file="res://Assets/Sprites/knife.png"
dest_files=["res://.godot/imported/knife.png-29bc4ddc148b964cb9b086eec2187a96.ctex"]
[params]

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://do1bui3bblkk7"
path="res://.godot/imported/sword-swing.png-b3fe38b6ad54820f8f9984baa9ea79b7.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Assets/Sprites/sword-swing.png"
dest_files=["res://.godot/imported/sword-swing.png-b3fe38b6ad54820f8f9984baa9ea79b7.ctex"]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 56 KiB

View File

@ -3,15 +3,15 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://gm2pcnfg7h8j"
path="res://.godot/imported/tileset.png-c259079e18121438fd392d302e3ca0d5.ctex"
path="res://.godot/imported/tileset.png-f52e8e44f74a535dd898a49592afe6d9.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Sprites/tileset.png"
dest_files=["res://.godot/imported/tileset.png-c259079e18121438fd392d302e3ca0d5.ctex"]
source_file="res://Assets/Sprites/tileset.png"
dest_files=["res://.godot/imported/tileset.png-f52e8e44f74a535dd898a49592afe6d9.ctex"]
[params]

View File

@ -0,0 +1,11 @@
using Godot;
using SupaLidlGame.Utils;
namespace SupaLidlGame.BoundingBoxes
{
public abstract partial class BoundingBox : Area2D, IFaction
{
[Export]
public ushort Faction { get; set; }
}
}

View File

@ -1,13 +1,17 @@
using System.Collections.Generic;
using System.Linq;
using Godot;
using SupaLidlGame.Characters;
using SupaLidlGame.Utils;
using SupaLidlGame.Items;
namespace SupaLidlGame.BoundingBoxes
{
public partial class Hitbox : Area2D, IFaction
public partial class Hitbox : BoundingBox
{
private HashSet<Hurtbox> _ignoreList = new HashSet<Hurtbox>();
private HashSet<BoundingBox> _ignoreList = new HashSet<BoundingBox>();
[Signal]
public delegate void HitEventHandler(BoundingBox box);
[Export]
public float Damage { get; set; }
@ -19,40 +23,76 @@ namespace SupaLidlGame.BoundingBoxes
public bool IsDisabled
{
get => _collisionShape.Disabled;
set => _collisionShape.Disabled = value;
set
{
_collisionShape.Disabled = value;
if (value)
{
DamageStartTime = Time.GetTicksMsec();
}
}
}
[Export]
public float Knockback { get; set; }
[Export]
public ushort Faction { get; set; }
public Character Inflictor { get; set; }
public ulong DamageStartTime { get; set; }
private CollisionShape2D _collisionShape;
private bool _isParrying = false;
public override void _Ready()
{
_collisionShape = GetNode<CollisionShape2D>("CollisionShape2D");
}
private bool ShouldParry(Hitbox box)
{
Node parent = GetParent<Node>();
// if this hitbox does not even belong to a weapon, skip
if (parent is not Weapon)
{
return false;
}
var weapon = parent as Weapon;
// if we hit a hitbox, we can parry if it can be parried
if (box.GetParent<Node>() is Weapon other)
{
return weapon.IsParryable && other.IsParryable;
}
return false;
}
public void _on_area_entered(Area2D area)
{
if (area is Hurtbox hurtbox)
if (area is BoundingBox box)
{
// we don't want to hurt teammates
if (Faction != hurtbox.Faction)
if (Faction != box.Faction)
{
if (!_ignoreList.Contains(hurtbox))
if (!_ignoreList.Contains(box))
{
_ignoreList.Add(hurtbox);
hurtbox.InflictDamage(Damage, Inflictor, Knockback);
_ignoreList.Add(box);
EmitSignal(SignalName.Hit, box);
}
}
}
}
public void ResetIgnoreList() => _ignoreList.Clear();
public bool HasHit(BoundingBox box) => _ignoreList.Contains(box);
public HashSet<BoundingBox> Hits
{
get => _ignoreList;
}
}
}

View File

@ -5,6 +5,7 @@
[sub_resource type="RectangleShape2D" id="RectangleShape2D_3w20g"]
[node name="Hitbox" type="Area2D"]
priority = 5.0
script = ExtResource("1_44i8j")
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]

View File

@ -4,7 +4,7 @@ using SupaLidlGame.Utils;
namespace SupaLidlGame.BoundingBoxes
{
public partial class Hurtbox : Area2D, IFaction
public partial class Hurtbox : BoundingBox, IFaction
{
[Signal]
public delegate void ReceivedDamageEventHandler(
@ -14,9 +14,6 @@ namespace SupaLidlGame.BoundingBoxes
Vector2 knockbackOrigin = default,
Vector2 knockbackVector = default);
[Export]
public ushort Faction { get; set; }
public override void _Ready()
{
if (Faction == default && GetParent() is IFaction factionEntity)

View File

@ -1,4 +1,5 @@
using Godot;
using SupaLidlGame.Extensions;
using SupaLidlGame.Items;
using SupaLidlGame.Utils;
@ -9,6 +10,9 @@ namespace SupaLidlGame.Characters
[Export]
public float Speed { get; protected set; } = 32.0f;
[Export]
public float Friction { get; protected set; } = 4.0f;
[Export]
public float Mass
{
@ -28,10 +32,13 @@ namespace SupaLidlGame.Characters
public Vector2 Acceleration => Direction * AccelerationMagnitude;
public Vector2 NetImpulse { get; set; } = Vector2.Zero;
public Vector2 Direction { get; set; } = Vector2.Zero;
public Vector2 Target { get; set; } = Vector2.Zero;
[Export]
public float Health
{
get => _health;
@ -51,9 +58,11 @@ namespace SupaLidlGame.Characters
}
}
public bool IsAlive => Health > 0;
protected float _health = 100f;
public bool IsAlive => Health > 0;
public double StunTime { get; set; }
[Export]
public AnimatedSprite2D Sprite { get; set; }
@ -99,7 +108,10 @@ namespace SupaLidlGame.Characters
/// </summary>
public virtual void ModifyVelocity()
{
if (StunTime > 0)
{
Velocity *= 0.25f;
}
}
public virtual void Die()
@ -113,7 +125,12 @@ namespace SupaLidlGame.Characters
// delta p = F delta t
if (resetVelocity)
Velocity = Vector2.Zero;
Velocity += impulse / Mass;
NetImpulse += impulse / Mass;
}
public virtual void Stun(float time)
{
StunTime += time;
}
protected void DrawTarget()
@ -134,6 +151,20 @@ namespace SupaLidlGame.Characters
Inventory.Rotation = angle;
}
public void UseCurrentItem()
{
if (StunTime > 0)
{
GD.Print("tried to use weapon but stunned");
return;
}
if (Inventory.SelectedItem is Weapon weapon)
{
weapon.Use();
}
}
public void _on_hurtbox_received_damage(float damage,
Character inflictor,
float knockback,
@ -141,7 +172,13 @@ namespace SupaLidlGame.Characters
Vector2 knockbackVector = default)
{
Health -= damage;
/*
var textScene = GD.Load<PackedScene>("res://UI/FloatingText.tscn");
var instance = textScene.Instantiate<UI.FloatingText>();
instance.Text = Mathf.Round(damage).ToString();
instance.GlobalPosition = GlobalPosition;
this.GetAncestor<TileMap>().AddChild(instance);
Vector2 knockbackDir = knockbackVector;
if (knockbackDir == default)
{
@ -153,8 +190,14 @@ namespace SupaLidlGame.Characters
knockbackDir = knockbackOrigin.DirectionTo(GlobalPosition);
}
ApplyImpulse(knockback.)
*/
var player = GetNode<AnimationPlayer>("FlashAnimation");
if (player != null)
{
player.Stop();
player.Play("Hurt");
}
ApplyImpulse(knockbackDir.Normalized() * knockback);
}
}
}

View File

@ -1,40 +1,47 @@
[gd_scene load_steps=19 format=3 uid="uid://dymwd5ihpwyqm"]
[gd_scene load_steps=24 format=3 uid="uid://ddcf6bfv212wj"]
[ext_resource type="Script" path="res://Characters/Enemy.cs" id="1_2yopk"]
[ext_resource type="Texture2D" uid="uid://dxymfduyrbuvx" path="res://Sprites/Characters/forsen.png" id="2_jfku3"]
[ext_resource type="Shader" path="res://Shaders/Flash.gdshader" id="1_fx1w5"]
[ext_resource type="Script" path="res://Characters/States/Machine.cs" id="3_k4ypw"]
[ext_resource type="Texture2D" uid="uid://dxymfduyrbuvx" path="res://Assets/Sprites/Characters/forsen.png" id="3_oxsgl"]
[ext_resource type="Script" path="res://Characters/States/NPCIdleState.cs" id="4_8r2qn"]
[ext_resource type="Script" path="res://Characters/States/NPCMoveState.cs" id="5_utogm"]
[ext_resource type="PackedScene" uid="uid://cjgxyhgcyvsv7" path="res://BoundingBoxes/Hurtbox.tscn" id="6_jo0cg"]
[ext_resource type="Script" path="res://Items/Inventory.cs" id="7_43gq8"]
[ext_resource type="PackedScene" uid="uid://cajlwb67xenfy" path="res://Items/Weapons/Sword.tscn" id="8_s3c8r"]
[ext_resource type="PackedScene" uid="uid://d72ehtv1ks0e" path="res://Items/Weapons/Sword.tscn" id="8_s3c8r"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_8jbxb"]
resource_local_to_scene = true
shader = ExtResource("1_fx1w5")
shader_parameter/color = null
shader_parameter/intensity = 0.0
[sub_resource type="AtlasTexture" id="AtlasTexture_6d2tf"]
atlas = ExtResource("2_jfku3")
atlas = ExtResource("3_oxsgl")
region = Rect2(0, 0, 24, 24)
[sub_resource type="AtlasTexture" id="AtlasTexture_bdyma"]
atlas = ExtResource("2_jfku3")
atlas = ExtResource("3_oxsgl")
region = Rect2(24, 0, 24, 24)
[sub_resource type="AtlasTexture" id="AtlasTexture_0dwbr"]
atlas = ExtResource("2_jfku3")
atlas = ExtResource("3_oxsgl")
region = Rect2(48, 0, 24, 24)
[sub_resource type="AtlasTexture" id="AtlasTexture_r7fn6"]
atlas = ExtResource("2_jfku3")
atlas = ExtResource("3_oxsgl")
region = Rect2(72, 0, 24, 24)
[sub_resource type="AtlasTexture" id="AtlasTexture_py8k0"]
atlas = ExtResource("2_jfku3")
atlas = ExtResource("3_oxsgl")
region = Rect2(96, 0, 24, 24)
[sub_resource type="AtlasTexture" id="AtlasTexture_g3nb2"]
atlas = ExtResource("2_jfku3")
atlas = ExtResource("3_oxsgl")
region = Rect2(120, 0, 24, 24)
[sub_resource type="AtlasTexture" id="AtlasTexture_jauql"]
atlas = ExtResource("2_jfku3")
atlas = ExtResource("3_oxsgl")
region = Rect2(144, 0, 24, 24)
[sub_resource type="SpriteFrames" id="SpriteFrames_4tm2b"]
@ -56,16 +63,57 @@ size = Vector2(16, 8)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_8lxmf"]
size = Vector2(16, 24)
[sub_resource type="Animation" id="Animation_dxevc"]
resource_name = "Hurt"
length = 0.6
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:material:shader_parameter/intensity")
tracks/0/interp = 2
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6),
"transitions": PackedFloat32Array(4, 4, 4, 4, 4, 4, 4),
"update": 0,
"values": [0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0]
}
[sub_resource type="Animation" id="Animation_k6l16"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:material:shader_parameter/intensity")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_xe5eq"]
_data = {
"Hurt": SubResource("Animation_dxevc"),
"RESET": SubResource("Animation_k6l16")
}
[node name="ExampleEnemy" type="CharacterBody2D" node_paths=PackedStringArray("Sprite", "Inventory", "StateMachine")]
texture_filter = 3
material = SubResource("ShaderMaterial_8jbxb")
y_sort_enabled = true
collision_layer = 2
script = ExtResource("1_2yopk")
Health = 50.0
Sprite = NodePath("Sprite")
Inventory = NodePath("Inventory")
StateMachine = NodePath("StateMachine")
Faction = 2
[node name="Sprite" type="AnimatedSprite2D" parent="."]
use_parent_material = true
frames = SubResource("SpriteFrames_4tm2b")
animation = &"move"
playing = true
@ -98,6 +146,12 @@ y_sort_enabled = true
script = ExtResource("7_43gq8")
[node name="Sword" parent="Inventory" instance=ExtResource("8_s3c8r")]
Knockback = 40.0
[node name="FlashAnimation" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_xe5eq")
}
[connection signal="ReceivedDamage" from="Hurtbox" to="." method="_on_hurtbox_received_damage"]

View File

@ -47,6 +47,7 @@ namespace SupaLidlGame.Characters
public override void _Draw()
{
#if DEBUG
for (int i = 0; i < 16; i++)
{
Vector2 vec = _weightDirs[i] * _weights[i] * 128;
@ -62,6 +63,7 @@ namespace SupaLidlGame.Characters
}
DrawLine(Vector2.Zero, vec, c);
}
#endif
base._Draw();
}
@ -93,7 +95,8 @@ namespace SupaLidlGame.Characters
Think();
}
Direction = _weightDirs[_bestWeightIdx];
Direction = Target;
//Direction = _weightDirs[_bestWeightIdx];
}
protected virtual void Think()
@ -105,14 +108,13 @@ namespace SupaLidlGame.Characters
if (Target.LengthSquared() < 1024)
{
GD.Print("lol");
if (Inventory.SelectedItem is Weapon weapon)
{
GD.Print("use");
weapon.Use();
UseCurrentItem();
}
}
#if DEBUGs
for (int i = 0; i < 16; i++)
{
float directDot = _weightDirs[i].Dot(dir);
@ -203,6 +205,7 @@ namespace SupaLidlGame.Characters
}
QueueRedraw();
#endif
}
}
}

View File

@ -1,5 +1,4 @@
using Godot;
using SupaLidlGame.Items;
namespace SupaLidlGame.Characters
{
@ -43,21 +42,18 @@ namespace SupaLidlGame.Characters
Velocity *= 2;
}
if (Inventory.SelectedItem is Weapon weapon)
base.ModifyVelocity();
}
public override void Stun(float time)
{
/*if (weapon is Sword sword)
base.Stun(time);
// TODO: implement visual effects for stun
}
public override void Die()
{
if (sword.IsAttacking)
{
Velocity *= 0.5f;
}
}
else*/
if (weapon.IsUsing)
{
Velocity *= 0.75f;
}
}
//base.Die();
}
}
}

View File

@ -1,42 +1,47 @@
[gd_scene load_steps=22 format=3 uid="uid://bncaar8vp3b84"]
[gd_scene load_steps=26 format=3 uid="uid://b2254pup8k161"]
[ext_resource type="Script" path="res://Characters/Player.cs" id="1_flygr"]
[ext_resource type="Texture2D" uid="uid://dxymfduyrbuvx" path="res://Sprites/Characters/forsen.png" id="2_swjho"]
[ext_resource type="Shader" path="res://Shaders/Flash.gdshader" id="2_ngsgt"]
[ext_resource type="Texture2D" uid="uid://dxymfduyrbuvx" path="res://Assets/Sprites/Characters/forsen.png" id="3_ig4hs"]
[ext_resource type="Script" path="res://Characters/States/Machine.cs" id="3_npkjp"]
[ext_resource type="Script" path="res://Characters/States/PlayerIdleState.cs" id="4_4k4mb"]
[ext_resource type="Script" path="res://Characters/States/PlayerMoveState.cs" id="5_tx5rw"]
[ext_resource type="Script" path="res://Characters/States/PlayerRollState.cs" id="6_6bgrj"]
[ext_resource type="Script" path="res://Characters/States/PlayerAttackState.cs" id="7_4cuhw"]
[ext_resource type="PackedScene" uid="uid://cajlwb67xenfy" path="res://Items/Weapons/Sword.tscn" id="7_4rxuv"]
[ext_resource type="PackedScene" uid="uid://d72ehtv1ks0e" path="res://Items/Weapons/Sword.tscn" id="7_4rxuv"]
[ext_resource type="Script" path="res://Items/Inventory.cs" id="7_xyenu"]
[ext_resource type="PackedScene" uid="uid://cjgxyhgcyvsv7" path="res://BoundingBoxes/Hurtbox.tscn" id="9_avyu4"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_h78y7"]
shader = ExtResource("2_ngsgt")
shader_parameter/color = null
shader_parameter/intensity = 0.0
[sub_resource type="AtlasTexture" id="AtlasTexture_us1ce"]
atlas = ExtResource("2_swjho")
atlas = ExtResource("3_ig4hs")
region = Rect2(0, 0, 24, 24)
[sub_resource type="AtlasTexture" id="AtlasTexture_hn4kf"]
atlas = ExtResource("2_swjho")
atlas = ExtResource("3_ig4hs")
region = Rect2(24, 0, 24, 24)
[sub_resource type="AtlasTexture" id="AtlasTexture_wfbeq"]
atlas = ExtResource("2_swjho")
atlas = ExtResource("3_ig4hs")
region = Rect2(48, 0, 24, 24)
[sub_resource type="AtlasTexture" id="AtlasTexture_qlmwk"]
atlas = ExtResource("2_swjho")
atlas = ExtResource("3_ig4hs")
region = Rect2(72, 0, 24, 24)
[sub_resource type="AtlasTexture" id="AtlasTexture_l1vgu"]
atlas = ExtResource("2_swjho")
atlas = ExtResource("3_ig4hs")
region = Rect2(96, 0, 24, 24)
[sub_resource type="AtlasTexture" id="AtlasTexture_ytlaa"]
atlas = ExtResource("2_swjho")
atlas = ExtResource("3_ig4hs")
region = Rect2(120, 0, 24, 24)
[sub_resource type="AtlasTexture" id="AtlasTexture_1q30d"]
atlas = ExtResource("2_swjho")
atlas = ExtResource("3_ig4hs")
region = Rect2(144, 0, 24, 24)
[sub_resource type="SpriteFrames" id="SpriteFrames_2h7cf"]
@ -61,18 +66,59 @@ font_size = 24
[sub_resource type="RectangleShape2D" id="RectangleShape2D_cjk6b"]
size = Vector2(16, 24)
[sub_resource type="Animation" id="Animation_dxevc"]
resource_name = "Hurt"
length = 0.6
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:material:shader_parameter/intensity")
tracks/0/interp = 2
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6),
"transitions": PackedFloat32Array(4, 4, 4, 4, 4, 4, 4),
"update": 0,
"values": [0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0]
}
[sub_resource type="Animation" id="Animation_k6l16"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:material:shader_parameter/intensity")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_xe5eq"]
_data = {
"Hurt": SubResource("Animation_dxevc"),
"RESET": SubResource("Animation_k6l16")
}
[node name="Player" type="CharacterBody2D" node_paths=PackedStringArray("Sprite", "Inventory", "StateMachine")]
texture_filter = 3
material = SubResource("ShaderMaterial_h78y7")
y_sort_enabled = true
collision_layer = 2
script = ExtResource("1_flygr")
Speed = 64.0
Mass = 1.0
Health = 100.0
Sprite = NodePath("Sprite")
Inventory = NodePath("Inventory")
StateMachine = NodePath("StateMachine")
Faction = 1
[node name="Sprite" type="AnimatedSprite2D" parent="."]
use_parent_material = true
frames = SubResource("SpriteFrames_2h7cf")
animation = &"move"
playing = true
@ -105,10 +151,6 @@ IdleState = NodePath("../Idle")
script = ExtResource("6_6bgrj")
IdleState = NodePath("../Idle")
[node name="Attack" type="Node" parent="StateMachine" node_paths=PackedStringArray("IdleState")]
script = ExtResource("7_4cuhw")
IdleState = NodePath("../Idle")
[node name="Debug" type="Control" parent="."]
layout_mode = 3
anchors_preset = 0
@ -136,6 +178,11 @@ Faction = 1
[node name="CollisionShape2D" parent="Hurtbox" index="0"]
shape = SubResource("RectangleShape2D_cjk6b")
[node name="FlashAnimation" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_xe5eq")
}
[connection signal="ReceivedDamage" from="Hurtbox" to="." method="_on_hurtbox_received_damage"]
[editable path="Hurtbox"]

View File

@ -22,13 +22,32 @@ namespace SupaLidlGame.Characters.State
/// </summary>
public virtual void Exit(CharacterState nextState) { }
public virtual CharacterState Process(double delta) => null;
public virtual CharacterState Process(double delta)
{
if (Character.StunTime > 0)
{
Character.StunTime -= delta;
}
return null;
}
public virtual CharacterState PhysicsProcess(double delta)
{
Character.Velocity = Character.Direction * Character.Speed;
Character.Velocity = Character.NetImpulse;
if (Character.NetImpulse.LengthSquared() < Mathf.Pow(Character.Speed, 2))
{
Character.Velocity += Character.Direction.Normalized()
* Character.Speed;
}
Character.NetImpulse = Character.NetImpulse.MoveToward(
Vector2.Zero,
(float)delta * Character.Speed * Character.Friction);
Character.ModifyVelocity();
Character.MoveAndSlide();
return null;
}

View File

@ -32,7 +32,8 @@ namespace SupaLidlGame.Characters.State
{
if (Character.Inventory.SelectedItem is not null)
{
Character.Inventory.SelectedItem.Use();
Character.UseCurrentItem();
//Character.Inventory.SelectedItem.Use();
//return AttackState;
}
}
@ -61,6 +62,7 @@ namespace SupaLidlGame.Characters.State
Character.Target = dirToMouse;
}
}
return base.Process(delta);
}
}

28
Extensions/Node.cs 100644
View File

@ -0,0 +1,28 @@
using Godot;
namespace SupaLidlGame.Extensions
{
public static class NodeExtensions
{
/// <summary>
/// Iterates through each ancestor until it finds an ancestor of type
/// <c>T</c>
/// </summary>
public static T GetAncestor<T>(this Node node) where T : Node
{
Node parent;
while ((parent = node.GetParent()) != null)
{
if (parent is T t)
{
return t;
}
node = parent;
}
return null;
}
}
}

View File

@ -1,4 +1,5 @@
using Godot;
using SupaLidlGame.BoundingBoxes;
using SupaLidlGame.Characters;
namespace SupaLidlGame.Items
@ -34,6 +35,16 @@ namespace SupaLidlGame.Items
[Export]
public float InitialVelocity { get; set; } = 0;
/// <summary>
/// Whether or not the weapon can parry other weapons and is
/// parryable by other weapons.
/// </summary>
public virtual bool IsParryable { get; protected set; } = false;
public bool IsParried { get; set; }
public ulong ParryTimeOrigin { get; protected set; }
public Character Character { get; set; }
public override void Equip(Character character)
@ -66,5 +77,13 @@ namespace SupaLidlGame.Items
}
}
}
public virtual void _on_hitbox_hit(BoundingBox box)
{
if (box is Hurtbox hurtbox)
{
hurtbox.InflictDamage(Damage, Character, Knockback);
}
}
}
}

View File

@ -1,14 +1,13 @@
using Godot;
using SupaLidlGame.BoundingBoxes;
using SupaLidlGame.Characters;
using SupaLidlGame.Extensions;
namespace SupaLidlGame.Items.Weapons
{
public partial class Sword : Weapon
{
public double RemainingAttackTime { get; protected set; } = 0;
public bool IsAttacking => RemainingAttackTime > 0;
public bool IsAttacking { get; protected set; }
[Export]
public Hitbox Hitbox { get; set; }
@ -26,6 +25,11 @@ namespace SupaLidlGame.Items.Weapons
[Export]
public double AttackTime { get; set; } = 0;
[Export]
public CPUParticles2D ParryParticles { get; set; }
public override bool IsParryable { get; protected set; }
public override void Equip(Character character)
{
Visible = true;
@ -46,24 +50,46 @@ namespace SupaLidlGame.Items.Weapons
return;
}
RemainingAttackTime = AttackTime;
IsParried = false;
AnimationPlayer.Stop();
if (GetNode<Node2D>("Anchor").Rotation < Mathf.DegToRad(50))
{
AnimationPlayer.Play("use");
Hitbox.IsDisabled = false;
}
else
{
AnimationPlayer.Play("use2");
}
base.Use();
}
public override void Deuse()
{
AnimationPlayer.Stop();
//AnimationPlayer.Stop();
Deattack();
base.Deuse();
}
protected void Deattack()
public void Attack()
{
ParryTimeOrigin = Time.GetTicksMsec();
IsParryable = true;
//RemainingAttackTime = AttackTime;
IsAttacking = true;
Hitbox.IsDisabled = false;
}
public void Deattack()
{
IsAttacking = false;
IsParryable = false;
Hitbox.IsDisabled = true;
ProcessHits();
Hitbox.ResetIgnoreList();
AnimationPlayer.PlaybackSpeed = 1;
}
public override void _Ready()
@ -73,6 +99,7 @@ namespace SupaLidlGame.Items.Weapons
public override void _Process(double delta)
{
/*
if (RemainingAttackTime > 0)
{
if ((RemainingAttackTime -= delta) <= 0)
@ -80,7 +107,73 @@ namespace SupaLidlGame.Items.Weapons
Deattack();
}
}
*/
base._Process(delta);
}
public void ProcessHits()
{
if (IsParried)
{
return;
}
foreach (BoundingBox box in Hitbox.Hits)
{
GD.Print("processing hit");
if (box is Hurtbox hurtbox)
{
hurtbox.InflictDamage(Damage, Character, Knockback);
}
}
}
public void AttemptParry(Weapon otherWeapon)
{
if (IsParryable && otherWeapon.IsParryable)
{
ParryParticles.Emitting = true;
if (ParryTimeOrigin < otherWeapon.ParryTimeOrigin)
{
// our character was parried
IsParried = true;
AnimationPlayer.PlaybackSpeed = 0.25f;
Character.Stun(1.5f);
}
}
//this.GetAncestor<TileMap>().AddChild(instance);
}
public override void _on_hitbox_hit(BoundingBox box)
{
if (IsParried)
{
return;
}
if (box is Hitbox hb)
{
Weapon w = hb.GetAncestor<Weapon>();
if (w is not null)
{
//Vector2 a = new Vector2(2, 2) * new Vector2(5, 2);
AttemptParry(w);
}
}
if (box is Hurtbox hurt)
{
if (hurt.GetParent() is Character c)
{
var item = c.Inventory.SelectedItem;
if (item is Weapon w)
{
AttemptParry(w);
}
}
}
//base._on_hitbox_hit(box);
}
}
}

View File

@ -1,13 +1,14 @@
[gd_scene load_steps=13 format=3 uid="uid://cajlwb67xenfy"]
[gd_scene load_steps=16 format=3 uid="uid://d72ehtv1ks0e"]
[ext_resource type="Script" path="res://Items/Weapons/Sword.cs" id="1_mlo73"]
[ext_resource type="Texture2D" uid="uid://dt6u8p4h6g7le" path="res://Sprites/knife.png" id="2_dmsp2"]
[ext_resource type="Texture2D" uid="uid://dt6u8p4h6g7le" path="res://Assets/Sprites/knife.png" id="2_rnfo4"]
[ext_resource type="PackedScene" uid="uid://du5vhccg75nrq" path="res://BoundingBoxes/Hitbox.tscn" id="3_up3ob"]
[ext_resource type="PackedScene" uid="uid://cojxmcin13ihm" path="res://Utils/Trail.tscn" id="4_pt6lq"]
[ext_resource type="Texture2D" uid="uid://do1bui3bblkk7" path="res://Assets/Sprites/sword-swing.png" id="5_pywek"]
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_yln58"]
radius = 8.0
height = 32.0
[sub_resource type="Gradient" id="Gradient_jjxq2"]
offsets = PackedFloat32Array(0, 0.945312)
colors = PackedColorArray(1, 1, 1, 1, 0.687215, 0.687215, 0.687215, 0)
[sub_resource type="Curve" id="Curve_4cxtp"]
_data = [Vector2(0.00687286, 1), 0.0, 0.0, 0, 0, Vector2(0.879725, 0.190909), -2.93145, -2.93145, 0, 0, Vector2(1, 0.0454545), 0.0483926, 0.0, 0, 0]
@ -29,31 +30,19 @@ tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [-0.785398]
"values": [-1.0472]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Anchor/Sprite2D:rotation")
tracks/1/path = NodePath("SwingSprite:frame")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [-1.19209e-07]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Anchor/Sprite2D:position")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(8, 1)]
"update": 1,
"values": [0]
}
[sub_resource type="Animation" id="Animation_mv7y2"]
@ -61,8 +50,7 @@ resource_name = "idle"
[sub_resource type="Animation" id="Animation_orc8t"]
resource_name = "use"
length = 0.5
loop_mode = 1
length = 0.75
step = 0.05
tracks/0/type = "value"
tracks/0/imported = false
@ -71,77 +59,142 @@ tracks/0/path = NodePath("Anchor:rotation")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.1, 0.3, 0.5),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"times": PackedFloat32Array(0.05, 0.1, 0.2, 0.4, 0.75),
"transitions": PackedFloat32Array(1, 4, 1, 2, 1),
"update": 0,
"values": [-0.785398, 1.5708, 1.5708, -0.785398]
"values": [-0.610865, -0.959931, 3.92699, 3.92699, 3.75246]
}
tracks/1/type = "value"
tracks/1/type = "method"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Anchor/Sprite2D:rotation")
tracks/1/path = NodePath(".")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.1, 0.3, 0.5),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 0,
"values": [-1.19209e-07, 0.785398, 0.785398, -1.19209e-07]
"times": PackedFloat32Array(0.05, 0.25),
"transitions": PackedFloat32Array(1, 1),
"values": [{
"args": [],
"method": &"Attack"
}, {
"args": [],
"method": &"Deattack"
}]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Anchor/Sprite2D:position")
tracks/2/path = NodePath("SwingSprite:frame")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0, 0.1, 0.3, 0.5),
"times": PackedFloat32Array(0, 0.2, 0.3, 0.4),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 1,
"values": [0, 1, 2, 0]
}
[sub_resource type="Animation" id="Animation_y4mj3"]
resource_name = "use2"
length = 0.75
step = 0.05
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Anchor:rotation")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0.05, 0.1, 0.2, 0.4, 0.75),
"transitions": PackedFloat32Array(1, 4, 1, 2, 1),
"update": 0,
"values": [Vector2(8, 1), Vector2(12, -1), Vector2(12, -1), Vector2(8, 1)]
"values": [3.75246, 4.10152, -0.785398, -0.785398, -0.610865]
}
tracks/1/type = "method"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath(".")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0.05, 0.25),
"transitions": PackedFloat32Array(1, 1),
"values": [{
"args": [],
"method": &"Attack"
}, {
"args": [],
"method": &"Deattack"
}]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("SwingSprite:frame")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0, 0.2, 0.3, 0.4),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 1,
"values": [0, 1, 3, 0]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_tao4k"]
_data = {
"RESET": SubResource("Animation_b7327"),
"idle": SubResource("Animation_mv7y2"),
"use": SubResource("Animation_orc8t")
"use": SubResource("Animation_orc8t"),
"use2": SubResource("Animation_y4mj3")
}
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_1lid1"]
[node name="Sword" type="Node2D" node_paths=PackedStringArray("Hitbox", "AnimationPlayer")]
[sub_resource type="ConvexPolygonShape2D" id="ConvexPolygonShape2D_tv0o2"]
points = PackedVector2Array(-11.314, -11.314, 0, -16, 11.314, -11.314, 16, 0, 11.314, 11.314, 0, 16, -11.314, 11.314, 0, 0)
[node name="Sword" type="Node2D" node_paths=PackedStringArray("Hitbox", "AnimationPlayer", "ParryParticles")]
texture_filter = 3
y_sort_enabled = true
script = ExtResource("1_mlo73")
Hitbox = NodePath("Anchor/Sprite2D/Hitbox")
Hitbox = NodePath("Hitbox")
AnimationPlayer = NodePath("AnimationPlayer")
AttackTime = 0.1
Damage = 20.0
UseTime = 0.5
ParryParticles = NodePath("Anchor/Sprite2D/ParryParticles")
Damage = 30.0
UseTime = 0.8
Knockback = 80.0
Description = "A basic sword."
[node name="Anchor" type="Node2D" parent="."]
rotation = -0.785398
rotation = -1.0472
y_sort_enabled = true
[node name="Sprite2D" type="Sprite2D" parent="Anchor"]
position = Vector2(8, 1)
position = Vector2(0, -8)
y_sort_enabled = true
texture = ExtResource("2_dmsp2")
texture = ExtResource("2_rnfo4")
[node name="Hitbox" parent="Anchor/Sprite2D" instance=ExtResource("3_up3ob")]
IsDisabled = true
[node name="CollisionShape2D" parent="Anchor/Sprite2D/Hitbox" index="0"]
position = Vector2(0, -4)
shape = SubResource("CapsuleShape2D_yln58")
disabled = true
[node name="ParryParticles" type="CPUParticles2D" parent="Anchor/Sprite2D"]
position = Vector2(-0.221825, -3.12132)
rotation = 0.785398
emitting = false
amount = 12
lifetime = 0.4
one_shot = true
explosiveness = 1.0
emission_shape = 1
emission_sphere_radius = 4.0
direction = Vector2(0, -1)
spread = 180.0
gravity = Vector2(0, 200)
initial_velocity_min = 8.0
initial_velocity_max = 64.0
color_ramp = SubResource("Gradient_jjxq2")
[node name="Trail" parent="Anchor" node_paths=PackedStringArray("Tracking") instance=ExtResource("4_pt6lq")]
position = Vector2(2.40734, -0.55655)
rotation = 0.945464
scale = Vector2(1, 1)
width_curve = SubResource("Curve_4cxtp")
gradient = SubResource("Gradient_2ablm")
Tracking = NodePath("../Sprite2D")
@ -156,4 +209,21 @@ tree_root = SubResource("AnimationNodeAnimation_1lid1")
anim_player = NodePath("../AnimationPlayer")
active = true
[editable path="Anchor/Sprite2D/Hitbox"]
[node name="Hitbox" parent="." instance=ExtResource("3_up3ob")]
IsDisabled = true
[node name="CollisionShape2D" parent="Hitbox" index="0"]
shape = SubResource("ConvexPolygonShape2D_tv0o2")
disabled = true
[node name="SwingSprite" type="Sprite2D" parent="."]
texture = ExtResource("5_pywek")
hframes = 4
[node name="SwingSound" type="AudioStreamPlayer2D" parent="."]
[node name="ParrySound" type="AudioStreamPlayer2D" parent="."]
[connection signal="Hit" from="Hitbox" to="." method="_on_hitbox_hit"]
[editable path="Hitbox"]

View File

@ -1,8 +1,9 @@
[gd_scene load_steps=6 format=3 uid="uid://cbsosmpnenfwu"]
[gd_scene load_steps=8 format=3 uid="uid://dd6xy1y0m8smm"]
[ext_resource type="Texture2D" uid="uid://gm2pcnfg7h8j" path="res://Sprites/tileset.png" id="1_k6myx"]
[ext_resource type="PackedScene" uid="uid://bncaar8vp3b84" path="res://Characters/Player.tscn" id="1_m35hr"]
[ext_resource type="PackedScene" uid="uid://dymwd5ihpwyqm" path="res://Characters/ExampleEnemy.tscn" id="2_uti3y"]
[ext_resource type="Texture2D" uid="uid://gm2pcnfg7h8j" path="res://Assets/Sprites/tileset.png" id="1_k6myx"]
[ext_resource type="PackedScene" uid="uid://b2254pup8k161" path="res://Characters/Player.tscn" id="1_m35hr"]
[ext_resource type="PackedScene" uid="uid://ddcf6bfv212wj" path="res://Characters/ExampleEnemy.tscn" id="2_uti3y"]
[ext_resource type="Shader" path="res://Shaders/Flash.gdshader" id="4_056cf"]
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_1pa1q"]
texture = ExtResource("1_k6myx")
@ -1100,6 +1101,12 @@ texture = ExtResource("1_k6myx")
physics_layer_0/collision_layer = 1
sources/0 = SubResource("TileSetAtlasSource_1pa1q")
[sub_resource type="ShaderMaterial" id="ShaderMaterial_mq5wa"]
resource_local_to_scene = true
shader = ExtResource("4_056cf")
shader_parameter/color = null
shader_parameter/intensity = 0.0
[node name="Level" type="Node2D"]
[node name="TileMap" type="TileMap" parent="."]
@ -1137,13 +1144,11 @@ position = Vector2(-81, -34)
motion_mode = 1
[node name="ExampleEnemy" parent="TileMap" instance=ExtResource("2_uti3y")]
material = SubResource("ShaderMaterial_mq5wa")
position = Vector2(38, 42)
scale = Vector2(1.00571, 1)
[node name="ExampleEnemy2" parent="TileMap" instance=ExtResource("2_uti3y")]
position = Vector2(156, 58)
scale = Vector2(1.00571, 1)
[node name="ExampleEnemy3" parent="TileMap" instance=ExtResource("2_uti3y")]
position = Vector2(175, -15)
material = SubResource("ShaderMaterial_mq5wa")
position = Vector2(190, 99)
scale = Vector2(1.00571, 1)

View File

@ -0,0 +1,10 @@
shader_type canvas_item;
uniform vec4 color = vec4(1.0);
uniform float intensity : hint_range(0.0, 1.0) = 0.0;
void fragment() {
vec4 tex = texture(TEXTURE, UV);
tex.rgb = mix(tex.rgb, color.rgb, intensity);
COLOR = tex;
}

51
UI/FloatingText.cs 100644
View File

@ -0,0 +1,51 @@
using Godot;
using System;
namespace SupaLidlGame.UI
{
public partial class FloatingText : Node2D
{
private Label _label;
[Export]
public string Text { get; set; }
public override void _Ready()
{
_label = GetNode<Label>("Label");
_label.Text = Text;
Tween tween = GetTree().CreateTween()
.SetEase(Tween.EaseType.Out)
.SetTrans(Tween.TransitionType.Quint)
.SetParallel();
Random rng = new Random();
float randomFloat(float min, float max)
{
return (float)rng.NextDouble() * (max - min) + min;
}
GD.Print(GlobalPosition);
Position += new Vector2(randomFloat(-8, 8), 0);
var endPos = Position + new Vector2(0, randomFloat(-16, -8));
var endMod = new Color(1, 1, 1, 0);
var endScale = Scale * 0.5f;
tween.TweenProperty(this, "position", endPos, 0.5f);
tween.SetTrans(Tween.TransitionType.Linear);
tween.TweenProperty(this, "modulate", endMod, 0.5f).SetDelay(1.0f);
tween.TweenProperty(this, "scale", endScale, 0.5f).SetDelay(1.0f);
tween.TweenCallback(new Callable(this, nameof(OnTweenFinished)))
.SetDelay(2.5f);
base._Ready();
}
public void OnTweenFinished()
{
QueueFree();
}
}
}

View File

@ -0,0 +1,26 @@
[gd_scene load_steps=4 format=3 uid="uid://be80n7mxp62jd"]
[ext_resource type="Script" path="res://UI/FloatingText.cs" id="1_yejq1"]
[ext_resource type="FontFile" uid="uid://cgwa8bjiyv534" path="res://Assets/Fonts/alagard.ttf" id="1_yns15"]
[sub_resource type="LabelSettings" id="LabelSettings_gs6ch"]
font = ExtResource("1_yns15")
font_color = Color(1, 0.792157, 0, 1)
outline_size = 2
outline_color = Color(0.635294, 0.415686, 0, 1)
shadow_color = Color(0, 0, 0, 1)
[node name="FloatingText" type="Node2D"]
scale = Vector2(0.5, 0.5)
script = ExtResource("1_yejq1")
[node name="Label" type="Label" parent="."]
texture_filter = 3
offset_left = -128.0
offset_top = -16.0
offset_right = 128.0
offset_bottom = 16.0
text = "gruppa krovi"
label_settings = SubResource("LabelSettings_gs6ch")
horizontal_alignment = 1
vertical_alignment = 1

View File

@ -0,0 +1,3 @@
[gd_resource type="Theme" format=3 uid="uid://cksjbu3vrup5"]
[resource]

47
export_presets.cfg 100644
View File

@ -0,0 +1,47 @@
[preset.0]
name="Windows Desktop"
platform="Windows Desktop"
runnable=true
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path="./SupaLidlGame.exe"
encryption_include_filters=""
encryption_exclude_filters=""
encrypt_pck=false
encrypt_directory=false
script_export_mode=1
script_encryption_key=""
[preset.0.options]
custom_template/debug=""
custom_template/release=""
debug/export_console_script=1
binary_format/embed_pck=false
texture_format/bptc=false
texture_format/s3tc=true
texture_format/etc=false
texture_format/etc2=false
texture_format/no_bptc_fallbacks=true
binary_format/architecture="x86_64"
codesign/enable=false
codesign/identity_type=0
codesign/identity=""
codesign/password=""
codesign/timestamp=true
codesign/timestamp_server_url=""
codesign/digest_algorithm=1
codesign/description=""
codesign/custom_options=PackedStringArray()
application/modify_resources=true
application/icon=""
application/file_version=""
application/product_version=""
application/company_name=""
application/product_name=""
application/file_description=""
application/copyright=""
application/trademarks=""

2
global.json 100644
View File

@ -0,0 +1,2 @@
{
}