Added the game difficulty configuration class and added the ability to generate scenes after projectiles kill enemies.

加入游戏难度的配置类,加入抛射体杀死敌人后生成场景的功能。
This commit is contained in:
Cold-Mint 2024-08-04 00:32:49 +08:00
parent bac2ae1992
commit 4459b6a88b
Signed by: Cold-Mint
GPG Key ID: C5A9BF8A98E0CE99
12 changed files with 121 additions and 5 deletions

View File

@ -1,4 +1,4 @@
<Project Sdk="Godot.NET.Sdk/4.3.0-rc.1">
<Project Sdk="Godot.NET.Sdk/4.3.0-rc.2">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework Condition=" '$(GodotTargetPlatform)' == 'android' ">net7.0</TargetFramework>

View File

@ -7,6 +7,10 @@
#staff_necromancy
#死灵法杖
# The Necromancy Staff will act differently on different difficulties.
#死灵法杖在不同的难度下会有不同的行为。
#The probability of generating monsters is as follows:Hard mode 100%, Normal mode 75%, easy mode 5%
#以下是在击杀敌人后生成怪物的概率困难模式100%普通模式75%简单模式5%
- id: staff_necromancy
scene_path: res://prefab/weapons/StaffNecromancy.tscn
icon_path: res://sprites/weapon/StaffNecromancy_Icon.png

View File

@ -14,6 +14,9 @@ collision_layer = 8
collision_mask = 38
script = ExtResource("1_slakl")
NumberSlots = 30
BackpackAllowed = null
_minContactInjury = null
_maxContactInjury = null
[node name="DamageArea2D" type="Area2D" parent="."]
collision_layer = 8

View File

@ -18,7 +18,10 @@ collision_mask = 34
script = ExtResource("1_w8hhv")
ProjectileScenes = [ExtResource("2_34250")]
FiringIntervalAsMillisecond = 300
_recoil = null
UniqueIcon = ExtResource("3_31iau")
_minContactInjury = null
_maxContactInjury = null
[node name="DamageArea2D" type="Area2D" parent="."]
collision_layer = 8

View File

@ -21,6 +21,29 @@ public static class Config
public const string Test = "test";
}
/// <summary>
/// <para>Difficulty</para>
/// <para>游戏难度</para>
/// </summary>
public static class Difficulty
{
/// <summary>
/// <para>Simple mode</para>
/// <para>简单模式</para>
/// </summary>
public const int Easy = 0;
/// <summary>
/// <para>Normal mode</para>
/// <para>正常模式</para>
/// </summary>
public const int Normal = 1;
/// <summary>
/// <para>Hard mode</para>
/// <para>困难模式</para>
/// </summary>
public const int Hard = 2;
}
/// <summary>
/// <para>Camp ID</para>

View File

@ -47,7 +47,7 @@ public readonly struct LootEntry(string itemId, int minQuantity = 1, int maxQuan
///<para>Entries</para>
///<para>条目列表</para>
/// </param>
public readonly record struct LootGroup(double Chance, IEnumerable<LootEntry> Entries)
public readonly record struct LootGroup(float Chance, IEnumerable<LootEntry> Entries)
{
private int WeightSum { get; } = Entries.Sum(entry => entry.Weight);

View File

@ -16,7 +16,7 @@ public static class LootRegister
{
List<LootGroup> lootGroups =
[
new LootGroup(0.8,
new LootGroup(0.8f,
[
new LootEntry("staff_necromancy"),
])

View File

@ -191,7 +191,7 @@ public partial class Projectile : CharacterBody2D
{
//If the character is dead, then call OnKillCharacter
//如果角色死亡了那么调用OnKillCharacter
InvokeDecorators(decorator => { decorator.OnKillCharacter(); });
InvokeDecorators(decorator => { decorator.OnKillCharacter(owner, characterTemplate); });
}
if (_knockbackForce != Vector2.Zero)

View File

@ -1,3 +1,6 @@
using ColdMint.scripts.character;
using Godot;
namespace ColdMint.scripts.projectile.decorator;
/// <summary>
@ -14,5 +17,13 @@ public interface IProjectileDecorator
/// <para>When the character is killed by this projectile</para>
/// <para>当角色被此抛射体击杀时</para>
/// </summary>
void OnKillCharacter();
/// <param name="owner">
/// <para>owner</para>
/// <para>主人</para>
/// </param>
/// <param name="target">
///<para>target</para>
///<para>目标</para>
/// </param>
void OnKillCharacter(Node2D? owner, CharacterTemplate target);
}

View File

@ -0,0 +1,56 @@
using ColdMint.scripts.character;
using ColdMint.scripts.utils;
using Godot;
namespace ColdMint.scripts.projectile.decorator;
/// <summary>
/// <para>NodeSpawnOnKillCharacterDecorator</para>
/// <para>在击杀角色后生成节点</para>
/// </summary>
public class NodeSpawnOnKillCharacterDecorator : IProjectileDecorator
{
/// <summary>
/// <para>PackedScenePath</para>
/// <para>要实例化的场景路径</para>
/// </summary>
public string? PackedScenePath { get; set; }
/// <summary>
/// <para>DefaultParentNode</para>
/// <para>默认的父节点</para>
/// </summary>
public Node? DefaultParentNode { get; set; }
/// <summary>
/// <para>Chance</para>
/// <para>生成概率</para>
/// </summary>
public float Chance { get; set; } = 1f;
public void OnKillCharacter(Node2D? owner, CharacterTemplate target)
{
if (RandomUtils.Instance.NextSingle() > Chance)
{
//Not in probability, straight back.
//没有在概率内,直接返回。
return;
}
if (PackedScenePath == null || DefaultParentNode == null)
{
return;
}
var packedScene = GD.Load<PackedScene>(PackedScenePath);
var node2D = NodeUtils.InstantiatePackedScene<Node2D>(packedScene);
if (node2D == null)
{
return;
}
var container = NodeUtils.FindContainerNode(node2D, DefaultParentNode);
node2D.GlobalPosition = target.GlobalPosition;
NodeUtils.CallDeferredAddChild(container, node2D);
}
}

View File

@ -1,4 +1,5 @@
using System;
using ColdMint.scripts.character;
using ColdMint.scripts.debug;
using ColdMint.scripts.projectile;
using Godot;
@ -224,6 +225,11 @@ public static class NodeUtils
/// <returns></returns>
public static Node FindContainerNode(Node childNode, Node defaultParentNode)
{
if (GameSceneNodeHolder.AiCharacterContainer!= null && childNode is AiCharacter)
{
return GameSceneNodeHolder.AiCharacterContainer;
}
if (GameSceneNodeHolder.ProjectileContainer != null && childNode is Projectile)
{
return GameSceneNodeHolder.ProjectileContainer;

View File

@ -1,5 +1,6 @@
using ColdMint.scripts.debug;
using ColdMint.scripts.projectile;
using ColdMint.scripts.projectile.decorator;
using ColdMint.scripts.utils;
using Godot;
@ -63,6 +64,15 @@ public partial class ProjectileWeapon : WeaponTemplate
// var projectileScene = _projectileCache[_projectiles[0]];
var projectile = NodeUtils.InstantiatePackedScene<Projectile>(projectileScene);
if (projectile == null) return;
if (Config.IsDebug())
{
var nodeSpawnOnKillCharacterDecorator = new NodeSpawnOnKillCharacterDecorator
{
DefaultParentNode = this,
PackedScenePath = "res://prefab/entitys/DelivererOfDarkMagic.tscn"
};
projectile.AddProjectileDecorator(nodeSpawnOnKillCharacterDecorator);
}
NodeUtils.CallDeferredAddChild(GameSceneNodeHolder.ProjectileContainer, projectile);
projectile.Owner = owner;
projectile.Velocity = (enemyGlobalPosition - _marker2D.GlobalPosition).Normalized() * projectile.Speed;