323 lines
11 KiB
C#
323 lines
11 KiB
C#
|
|
using System.Collections;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using Ichni.RhythmGame.Beatmap;
|
|||
|
|
using UnityEngine;
|
|||
|
|
|
|||
|
|
namespace Ichni.RhythmGame
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// 包含效果的次级模块
|
|||
|
|
/// </summary>
|
|||
|
|
public partial class EffectSubmodule : SubmoduleBase
|
|||
|
|
{
|
|||
|
|
public Dictionary<string, List<EffectBase>> effectCollection;
|
|||
|
|
|
|||
|
|
public EffectSubmodule(GameElement attachedGameElement, EffectSubmodulePreset preset = EffectSubmodulePreset.Default)
|
|||
|
|
: base(attachedGameElement)
|
|||
|
|
{
|
|||
|
|
effectCollection = new Dictionary<string, List<EffectBase>>();
|
|||
|
|
|
|||
|
|
if (preset == EffectSubmodulePreset.Default) //对于默认的效果次级模块,有Prior、Default、Late三个效果集合
|
|||
|
|
{
|
|||
|
|
effectCollection.Add("Prior", new List<EffectBase>());
|
|||
|
|
effectCollection.Add("Default", new List<EffectBase>());
|
|||
|
|
effectCollection.Add("Late", new List<EffectBase>());
|
|||
|
|
}
|
|||
|
|
else if (preset == EffectSubmodulePreset.Note) //对于Note的效果次级模块,在Note的不同状态下有独立的效果集合
|
|||
|
|
{
|
|||
|
|
effectCollection.Add("Generate", new List<EffectBase>());
|
|||
|
|
effectCollection.Add("GeneralJudge", new List<EffectBase>());
|
|||
|
|
effectCollection.Add("Holding", new List<EffectBase>()); //仅用于Hold
|
|||
|
|
effectCollection.Add("Perfect", new List<EffectBase>());
|
|||
|
|
effectCollection.Add("Good", new List<EffectBase>());
|
|||
|
|
effectCollection.Add("Bad", new List<EffectBase>());
|
|||
|
|
effectCollection.Add("Miss", new List<EffectBase>());
|
|||
|
|
effectCollection.Add("AfterJudge", new List<EffectBase>());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!HaveSameSubmodule)
|
|||
|
|
{
|
|||
|
|
(attachedGameElement as IHaveEffectSubmodule).effectSubmodule = this;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public EffectSubmodule(GameElement attachedGameElement, Dictionary<string, List<EffectBase_BM>> effectList_BM) : base(attachedGameElement)
|
|||
|
|
{
|
|||
|
|
effectCollection = new Dictionary<string, List<EffectBase>>();
|
|||
|
|
|
|||
|
|
foreach (var effect in effectList_BM)
|
|||
|
|
{
|
|||
|
|
List<EffectBase> effectList = new List<EffectBase>();
|
|||
|
|
foreach (var effectBM in effect.Value)
|
|||
|
|
{
|
|||
|
|
if (BeatmapContainer_BM.LowPriorityDataTypes.Contains(effectBM.GetType())) // 如果是低优先级数据类型
|
|||
|
|
{
|
|||
|
|
(GameManager.instance.beatmapContainer).lowPriorityActions.Add(() =>
|
|||
|
|
{
|
|||
|
|
effectList.Add(effectBM.ConvertToGameType(attachedGameElement));
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
effectList.Add(effectBM.ConvertToGameType(attachedGameElement));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
effectCollection.Add(effect.Key, effectList);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!HaveSameSubmodule)
|
|||
|
|
{
|
|||
|
|
(attachedGameElement as IHaveEffectSubmodule).effectSubmodule = this;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public partial class EffectSubmodule
|
|||
|
|
{
|
|||
|
|
public override void SaveBM()
|
|||
|
|
{
|
|||
|
|
matchedBM = new EffectSubmodule_BM(attachedGameElement);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public partial class EffectSubmodule
|
|||
|
|
{
|
|||
|
|
public enum EffectSubmodulePreset
|
|||
|
|
{
|
|||
|
|
Default,
|
|||
|
|
Note,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static Dictionary<string, EffectBase> EffectCollection { get; } =
|
|||
|
|
new Dictionary<string, EffectBase>()
|
|||
|
|
{
|
|||
|
|
{ "Bloom", new BloomEffect(1, 2, CustomCurvePresets.Parabolic(1, 0, 1)) },
|
|||
|
|
{ "CameraShake", new CameraShakeEffect(1, 50, 1, 1, 1) },
|
|||
|
|
{ "ChromaticAberration", new ChromaticAberrationEffect(1, 1, CustomCurvePresets.Parabolic(1, 0, 1)) },
|
|||
|
|
{ "Vignette", new VignetteEffect(1, 1, 0.4f, Color.black, CustomCurvePresets.Parabolic(1, 0, 1)) },
|
|||
|
|
{ "SetInteger", new SetIntegerEffect("New Variable", 0, false, 0, 1) },
|
|||
|
|
{ "EnableControl", new EnableControlEffect(null, "New Variable", 0, false, "") },
|
|||
|
|
{ "LowPassFilter", new LowPassFilterEffect(1, 10, CustomCurvePresets.Parabolic(1, 0, 1)) },
|
|||
|
|
{ "HighPassFilter", new HighPassFilterEffect(1, 22000, CustomCurvePresets.Parabolic(1, 0, 1)) }
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public interface IHaveEffectSubmodule
|
|||
|
|
{
|
|||
|
|
public EffectSubmodule effectSubmodule { get; set; }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
namespace Beatmap
|
|||
|
|
{
|
|||
|
|
public class EffectSubmodule_BM : Submodule_BM
|
|||
|
|
{
|
|||
|
|
public Dictionary<string, List<EffectBase_BM>> effectCollection;
|
|||
|
|
|
|||
|
|
public EffectSubmodule_BM()
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public EffectSubmodule_BM(GameElement attachedElement) : base(attachedElement)
|
|||
|
|
{
|
|||
|
|
effectCollection = new Dictionary<string, List<EffectBase_BM>>();
|
|||
|
|
IHaveEffectSubmodule element = attachedElement as IHaveEffectSubmodule;
|
|||
|
|
|
|||
|
|
foreach (var effect in element.effectSubmodule.effectCollection)
|
|||
|
|
{
|
|||
|
|
List<EffectBase_BM> effectList = new List<EffectBase_BM>();
|
|||
|
|
foreach (var effectBase in effect.Value)
|
|||
|
|
{
|
|||
|
|
effectList.Add(effectBase.ConvertToBM());
|
|||
|
|
}
|
|||
|
|
effectCollection.Add(effect.Key, effectList);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public override void ExecuteBM()
|
|||
|
|
{
|
|||
|
|
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
|
|||
|
|
(attachedElement as IHaveEffectSubmodule).effectSubmodule = new EffectSubmodule(attachedElement, effectCollection);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public override void DuplicateBM(GameElement attached)
|
|||
|
|
{
|
|||
|
|
(attached as IHaveEffectSubmodule).effectSubmodule = new EffectSubmodule(attached, effectCollection);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public abstract class EffectBase : IBaseElement
|
|||
|
|
{
|
|||
|
|
public enum EffectState
|
|||
|
|
{
|
|||
|
|
Before = -1,
|
|||
|
|
Middle = 0,
|
|||
|
|
After = 1,
|
|||
|
|
Error = 100
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public BaseElement_BM matchedBM { get; set; }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 效果的持续时间,如果为0则表示瞬间效果
|
|||
|
|
/// </summary>
|
|||
|
|
public float effectTime;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 是否是瞬间效果
|
|||
|
|
/// </summary>
|
|||
|
|
public bool isInstantEffect => effectTime <= 0;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 效果的进度百分比
|
|||
|
|
/// </summary>
|
|||
|
|
public float effectProgressPercent;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 效果当前的状态
|
|||
|
|
/// </summary>
|
|||
|
|
public EffectState nowEffectState;
|
|||
|
|
|
|||
|
|
protected EffectBase()
|
|||
|
|
{
|
|||
|
|
this.effectTime = 0;
|
|||
|
|
this.nowEffectState = EffectState.Before;
|
|||
|
|
this.effectProgressPercent = 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
protected EffectBase(float effectTime)
|
|||
|
|
{
|
|||
|
|
this.effectTime = effectTime;
|
|||
|
|
this.nowEffectState = EffectState.Before;
|
|||
|
|
this.effectProgressPercent = 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void SaveBM()
|
|||
|
|
{
|
|||
|
|
throw new System.NotImplementedException();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public virtual void UpdateEffect(float triggerTime)
|
|||
|
|
{
|
|||
|
|
EffectState state = CheckEffectState(triggerTime);
|
|||
|
|
float songTime = GameManager.instance.songTime;
|
|||
|
|
|
|||
|
|
if (state == EffectState.Before && nowEffectState != EffectState.Before)
|
|||
|
|
{
|
|||
|
|
nowEffectState = EffectState.Before;
|
|||
|
|
effectProgressPercent = 0;
|
|||
|
|
Recover();
|
|||
|
|
}
|
|||
|
|
else if (state == EffectState.Middle)
|
|||
|
|
{
|
|||
|
|
if (nowEffectState == EffectState.Before)
|
|||
|
|
{
|
|||
|
|
PreExecute();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
nowEffectState = EffectState.Middle;
|
|||
|
|
effectProgressPercent = (songTime - triggerTime) / effectTime;
|
|||
|
|
Execute();
|
|||
|
|
}
|
|||
|
|
else if (state == EffectState.After && nowEffectState != EffectState.After)
|
|||
|
|
{
|
|||
|
|
nowEffectState = EffectState.After;
|
|||
|
|
effectProgressPercent = 1;
|
|||
|
|
Adjust();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
protected virtual EffectState CheckEffectState(float triggerTime)
|
|||
|
|
{
|
|||
|
|
float songTime = GameManager.instance.songTime;
|
|||
|
|
|
|||
|
|
if (songTime < triggerTime)
|
|||
|
|
{
|
|||
|
|
return EffectState.Before;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (songTime >= triggerTime &&
|
|||
|
|
songTime <= triggerTime + effectTime)
|
|||
|
|
{
|
|||
|
|
return EffectState.Middle;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (songTime > triggerTime + effectTime)
|
|||
|
|
{
|
|||
|
|
return EffectState.After;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return EffectState.Error;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 当从Before状态进入Middle状态时,仅在效果的开始时触发一次方法
|
|||
|
|
/// </summary>
|
|||
|
|
public virtual void PreExecute()
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 在效果的持续时间内,触发这个方法
|
|||
|
|
/// </summary>
|
|||
|
|
public virtual void Execute()
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 如果是非瞬间效果,在效果完成后,触发这个方法;
|
|||
|
|
/// 如果是瞬间效果,则此方法即为Execute。原有的Execute方法不被调用。
|
|||
|
|
/// </summary>
|
|||
|
|
public virtual void Adjust()
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 如果时间轴回退到效果的触发时间之前,则触发这个方法
|
|||
|
|
/// </summary>
|
|||
|
|
public virtual void Recover()
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 转换为存档类
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public abstract EffectBase_BM ConvertToBM();
|
|||
|
|
|
|||
|
|
public void Refresh()
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
namespace Beatmap
|
|||
|
|
{
|
|||
|
|
public abstract class EffectBase_BM
|
|||
|
|
{
|
|||
|
|
public float effectTime;
|
|||
|
|
|
|||
|
|
public EffectBase_BM()
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public EffectBase_BM(float effectTime)
|
|||
|
|
{
|
|||
|
|
this.effectTime = effectTime;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 转换为游戏类
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public abstract EffectBase ConvertToGameType(GameElement attachedGameElement);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|