added forge addon
All checks were successful
Create tag and build when new code gets to main / BumpTag (push) Successful in 21s
Create tag and build when new code gets to main / Test (push) Successful in 6m56s
Create tag and build when new code gets to main / Export (push) Successful in 9m3s

This commit is contained in:
2026-02-08 15:16:01 +01:00
parent 2b74c9e70c
commit c4be97e0de
163 changed files with 6975 additions and 141 deletions

View File

@@ -0,0 +1,14 @@
// Copyright © Gamesmiths Guild.
using Gamesmiths.Forge.Abilities;
using Godot;
namespace Gamesmiths.Forge.Godot.Resources.Abilities;
[Tool]
[GlobalClass]
[Icon("uid://bcx7anhepqfmd")]
public abstract partial class ForgeAbilityBehavior : Resource
{
public abstract IAbilityBehavior GetBehavior();
}

View File

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

View File

@@ -0,0 +1,180 @@
// Copyright © Gamesmiths Guild.
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Gamesmiths.Forge.Abilities;
using Gamesmiths.Forge.Effects;
using Godot;
using Godot.Collections;
namespace Gamesmiths.Forge.Godot.Resources.Abilities;
[Tool]
[GlobalClass]
[Icon("uid://l04b8et2244r")]
public partial class ForgeAbilityData : Resource
{
private AbilityData? _data;
private AbilityInstancingPolicy _instancingPolicy;
[Export]
public string Name { get; set; } = string.Empty;
[Export]
public AbilityInstancingPolicy InstancingPolicy
{
get => _instancingPolicy;
set
{
_instancingPolicy = value;
NotifyPropertyListChanged();
}
}
[Export]
public bool RetriggerInstancedAbility { get; set; }
[Export]
public ForgeEffectData[]? CooldownEffects { get; set; }
[Export]
public ForgeEffectData? CostEffect { get; set; }
[Export]
public ForgeAbilityBehavior? AbilityBehavior { get; set; }
[ExportGroup("Trigger")]
[Export]
public TriggerSource TriggerSource { get; set; }
[Export]
public ForgeTag? TriggerTag { get; set; }
[Export]
public int Priority { get; set; }
[ExportGroup("Tags")]
[Export]
public ForgeTagContainer? AbilityTags { get; set; }
[Export]
public ForgeTagContainer? CancelAbilitiesWithTag { get; set; }
[Export]
public ForgeTagContainer? BlockAbilitiesWithTag { get; set; }
[Export]
public ForgeTagContainer? ActivationOwnedTags { get; set; }
[Export]
public ForgeTagContainer? ActivationRequiredTags { get; set; }
[Export]
public ForgeTagContainer? ActivationBlockedTags { get; set; }
[Export]
public ForgeTagContainer? SourceRequiredTags { get; set; }
[Export]
public ForgeTagContainer? SourceBlockedTags { get; set; }
[Export]
public ForgeTagContainer? TargetRequiredTags { get; set; }
[Export]
public ForgeTagContainer? TargetBlockedTags { get; set; }
public AbilityData GetAbilityData()
{
if (_data.HasValue)
{
return _data.Value;
}
List<EffectData> cooldownEffects = [];
foreach (ForgeEffectData cooldownEffect in CooldownEffects ?? [])
{
cooldownEffects.Add(cooldownEffect.GetEffectData());
}
_data = new AbilityData(
Name,
CostEffect?.GetEffectData(),
[.. cooldownEffects],
AbilityTags?.GetTagContainer(),
InstancingPolicy,
RetriggerInstancedAbility,
GetTriggerData(),
CancelAbilitiesWithTag?.GetTagContainer(),
BlockAbilitiesWithTag?.GetTagContainer(),
ActivationOwnedTags?.GetTagContainer(),
ActivationRequiredTags?.GetTagContainer(),
ActivationBlockedTags?.GetTagContainer(),
SourceRequiredTags?.GetTagContainer(),
SourceBlockedTags?.GetTagContainer(),
TargetRequiredTags?.GetTagContainer(),
TargetBlockedTags?.GetTagContainer(),
() => AbilityBehavior?.GetBehavior()!);
return _data.Value;
}
#if TOOLS
public override void _ValidateProperty(Dictionary property)
{
if (property["name"].AsStringName() == PropertyName.RetriggerInstancedAbility
&& InstancingPolicy != AbilityInstancingPolicy.PerEntity)
{
property["usage"] = (int)PropertyUsageFlags.NoEditor;
}
}
#endif
private AbilityTriggerData? GetTriggerData()
{
if (TriggerSource == TriggerSource.None)
{
return null;
}
Tags.Tag triggerTag = TriggerTag!.GetTag();
switch (TriggerSource)
{
case TriggerSource.Event:
IAbilityBehavior? behavior = AbilityBehavior?.GetBehavior();
if (behavior is not null)
{
System.Type behaviorType = behavior.GetType();
System.Type? payloadInterface =
System.Array.Find(behaviorType.GetInterfaces(), x =>
x.IsGenericType &&
x.GetGenericTypeDefinition() == typeof(IAbilityBehavior<>));
if (payloadInterface is not null)
{
System.Type payloadType = payloadInterface.GetGenericArguments()[0];
MethodInfo method = typeof(AbilityTriggerData)
.GetMethods(BindingFlags.Public | BindingFlags.Static)
.First(x => x.Name == nameof(AbilityTriggerData.ForEvent)
&& x.IsGenericMethodDefinition)
.MakeGenericMethod(payloadType);
return (AbilityTriggerData)method.Invoke(null, [triggerTag, Priority])!;
}
}
GD.Print($"call {triggerTag} - {Name}");
return AbilityTriggerData.ForEvent(triggerTag, Priority);
case TriggerSource.TagAdded:
return AbilityTriggerData.ForTagAdded(triggerTag);
case TriggerSource.TagPresent:
return AbilityTriggerData.ForTagPresent(triggerTag);
default:
return null;
}
}
}

View File

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

View File

@@ -0,0 +1,26 @@
// Copyright © Gamesmiths Guild.
namespace Gamesmiths.Forge.Godot.Resources.Abilities;
public enum TriggerSource
{
/// <summary>
/// No trigger source specified.
/// </summary>
None = 0,
/// <summary>
/// Triggered by an event.
/// </summary>
Event = 1,
/// <summary>
/// Triggered when a tag is added.
/// </summary>
TagAdded = 2,
/// <summary>
/// Triggered when a tag is present and removed when tag is gone.
/// </summary>
TagPresent = 3,
}

View File

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