chore: Assets 디렉토리 구조 정리 및 네이밍 컨벤션 적용
- Assets/_Game/ 하위로 게임 에셋 통합 - External/ 패키지 벤더별 분류 (Synty, Animations, UI) - 에셋 네이밍 컨벤션 확립 및 적용 (Data_Skill_, Data_SkillEffect_, Prefab_, Anim_, Model_, BT_ 등) - pre-commit hook으로 네이밍 컨벤션 자동 검사 추가 - RESTRUCTURE_CHECKLIST.md 작성 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using Unity.Behavior;
|
||||
using UnityEngine;
|
||||
using Action = Unity.Behavior.Action;
|
||||
using Unity.Properties;
|
||||
|
||||
[Serializable, GeneratePropertyBag]
|
||||
[NodeDescription(name: "ChaseTarget", story: "타겟 추적", category: "Action", id: "0889fbb015b8bf414ef569af08bb6868")]
|
||||
public partial class ChaseTargetAction : Action
|
||||
{
|
||||
|
||||
[SerializeReference]
|
||||
public BlackboardVariable<GameObject> Target;
|
||||
|
||||
[SerializeReference]
|
||||
public BlackboardVariable<float> Speed = new BlackboardVariable<float>(0f);
|
||||
|
||||
[SerializeReference]
|
||||
public BlackboardVariable<float> StopDistance = new BlackboardVariable<float>(2f);
|
||||
|
||||
private UnityEngine.AI.NavMeshAgent agent;
|
||||
|
||||
protected override Status OnStart()
|
||||
{
|
||||
if (Target.Value == null)
|
||||
{
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
agent = GameObject.GetComponent<UnityEngine.AI.NavMeshAgent>();
|
||||
if (agent == null)
|
||||
{
|
||||
Debug.LogWarning("[ChaseTarget] NavMeshAgent not found");
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
// Speed가 0 이하면 NavMeshAgent의 기존 speed 유지 (EnemyData에서 설정한 값)
|
||||
if (Speed.Value > 0f)
|
||||
{
|
||||
agent.speed = Speed.Value;
|
||||
}
|
||||
agent.stoppingDistance = StopDistance.Value;
|
||||
agent.isStopped = false;
|
||||
|
||||
return Status.Running;
|
||||
}
|
||||
|
||||
protected override Status OnUpdate()
|
||||
{
|
||||
if (Target.Value == null)
|
||||
{
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
// 이미 사거리 내에 있으면 성공
|
||||
float distance = Vector3.Distance(GameObject.transform.position, Target.Value.transform.position);
|
||||
if (distance <= StopDistance.Value)
|
||||
{
|
||||
agent.isStopped = true;
|
||||
return Status.Success;
|
||||
}
|
||||
|
||||
// 타겟 위치로 이동
|
||||
agent.SetDestination(Target.Value.transform.position);
|
||||
return Status.Running;
|
||||
}
|
||||
|
||||
protected override void OnEnd()
|
||||
{
|
||||
if (agent != null)
|
||||
{
|
||||
agent.isStopped = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 14296786101ccd742ac9f752f1fd3393
|
||||
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using Unity.Behavior;
|
||||
using UnityEngine;
|
||||
using Action = Unity.Behavior.Action;
|
||||
using Unity.Properties;
|
||||
using Colosseum.Combat;
|
||||
|
||||
[Serializable, GeneratePropertyBag]
|
||||
[NodeDescription(name: "FindTarget", story: "[타겟] 탐색", category: "Action", id: "bb947540549026f3c5625c6d19213311")]
|
||||
public partial class FindTargetAction : Action
|
||||
{
|
||||
[SerializeReference]
|
||||
public BlackboardVariable<GameObject> Target;
|
||||
|
||||
[SerializeReference]
|
||||
public BlackboardVariable<string> Tag = new BlackboardVariable<string>("Player");
|
||||
|
||||
protected override Status OnStart()
|
||||
{
|
||||
if (Tag.Value == null || string.IsNullOrEmpty(Tag.Value))
|
||||
{
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
// 모든 타겟 후보 검색
|
||||
GameObject[] candidates = GameObject.FindGameObjectsWithTag(Tag.Value);
|
||||
|
||||
if (candidates == null || candidates.Length == 0)
|
||||
{
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
// 사망하지 않은 타겟 찾기
|
||||
foreach (GameObject candidate in candidates)
|
||||
{
|
||||
IDamageable damageable = candidate.GetComponent<IDamageable>();
|
||||
|
||||
// IDamageable이 없거나 살아있는 경우 타겟으로 선택
|
||||
if (damageable == null || !damageable.IsDead)
|
||||
{
|
||||
Target.Value = candidate;
|
||||
return Status.Success;
|
||||
}
|
||||
}
|
||||
|
||||
// 살아있는 타겟이 없음
|
||||
return Status.Failure;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f569cb803bceb7c4291d0f3074346741
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using Unity.Behavior;
|
||||
using UnityEngine;
|
||||
|
||||
[Serializable, Unity.Properties.GeneratePropertyBag]
|
||||
[Condition(name: "isDie", story: "죽었는지 확인", category: "Conditions", id: "8067176f9f490e7d974824f8087de448")]
|
||||
public partial class IsDieCondition : Condition
|
||||
{
|
||||
|
||||
public override bool IsTrue()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void OnStart()
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnEnd()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d2c81704b2be4c4289bcf5555059b87
|
||||
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using Unity.Behavior;
|
||||
using UnityEngine;
|
||||
using Action = Unity.Behavior.Action;
|
||||
using Unity.Properties;
|
||||
|
||||
[Serializable, GeneratePropertyBag]
|
||||
[NodeDescription(name: "PlayAnimation", story: "[애니메이션] 재생", category: "Action", id: "b558ee0df6e00cd2e6bb2273b4f59cd2")]
|
||||
public partial class PlayAnimationAction : Action
|
||||
{
|
||||
[SerializeReference]
|
||||
public BlackboardVariable<string> AnimationName = new BlackboardVariable<string>("");
|
||||
|
||||
[SerializeReference]
|
||||
public BlackboardVariable<bool> WaitForCompletion = new BlackboardVariable<bool>(true);
|
||||
|
||||
private Animator animator;
|
||||
private bool animationStarted;
|
||||
|
||||
protected override Status OnStart()
|
||||
{
|
||||
animator = GameObject.GetComponentInChildren<Animator>();
|
||||
|
||||
if (animator == null || string.IsNullOrEmpty(AnimationName.Value))
|
||||
{
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
animator.Play(AnimationName.Value);
|
||||
animationStarted = true;
|
||||
|
||||
if (!WaitForCompletion.Value)
|
||||
{
|
||||
return Status.Success;
|
||||
}
|
||||
|
||||
return Status.Running;
|
||||
}
|
||||
|
||||
protected override Status OnUpdate()
|
||||
{
|
||||
if (!WaitForCompletion.Value)
|
||||
{
|
||||
return Status.Success;
|
||||
}
|
||||
|
||||
if (animator == null)
|
||||
{
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
var stateInfo = animator.GetCurrentAnimatorStateInfo(0);
|
||||
|
||||
// 애니메이션이 완료되었는지 확인
|
||||
if (stateInfo.IsName(AnimationName.Value) && stateInfo.normalizedTime >= 1f)
|
||||
{
|
||||
return Status.Success;
|
||||
}
|
||||
|
||||
return Status.Running;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3bc57afe07d75aa4e80ef5394b57f774
|
||||
@@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using Unity.Behavior;
|
||||
using UnityEngine;
|
||||
using Action = Unity.Behavior.Action;
|
||||
using Unity.Properties;
|
||||
|
||||
[Serializable, GeneratePropertyBag]
|
||||
[NodeDescription(name: "RotateToTarget", story: "[대상을] 바라보도록 회전", category: "Action", id: "30341f7e1af0565c0aca0253341b3e28")]
|
||||
public partial class RotateToTargetAction : Action
|
||||
{
|
||||
[SerializeReference]
|
||||
public BlackboardVariable<GameObject> Target;
|
||||
|
||||
[SerializeReference]
|
||||
public BlackboardVariable<float> RotationSpeed = new BlackboardVariable<float>(10f);
|
||||
|
||||
[SerializeReference]
|
||||
public BlackboardVariable<float> AngleThreshold = new BlackboardVariable<float>(5f);
|
||||
|
||||
protected override Status OnUpdate()
|
||||
{
|
||||
if (Target.Value == null)
|
||||
{
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
Vector3 direction = Target.Value.transform.position - GameObject.transform.position;
|
||||
direction.y = 0f;
|
||||
|
||||
if (direction == Vector3.zero)
|
||||
{
|
||||
return Status.Success;
|
||||
}
|
||||
|
||||
Quaternion targetRotation = Quaternion.LookRotation(direction);
|
||||
float angleDifference = Quaternion.Angle(GameObject.transform.rotation, targetRotation);
|
||||
|
||||
// 임계값 이내면 성공
|
||||
if (angleDifference <= AngleThreshold.Value)
|
||||
{
|
||||
return Status.Success;
|
||||
}
|
||||
|
||||
// 부드럽게 회전
|
||||
GameObject.transform.rotation = Quaternion.Slerp(
|
||||
GameObject.transform.rotation,
|
||||
targetRotation,
|
||||
RotationSpeed.Value * Time.deltaTime
|
||||
);
|
||||
|
||||
return Status.Running;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 33182146e0ade8443a539cf7780735e2
|
||||
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using Unity.Behavior;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using Action = Unity.Behavior.Action;
|
||||
using Unity.Properties;
|
||||
|
||||
[Serializable, GeneratePropertyBag]
|
||||
[NodeDescription(name: "SetAnimatorTrigger", story: "애니메이션 [트리거] 설정", category: "Action", id: "bfef104cbd43df3d01f24570a4caa8ed")]
|
||||
public partial class SetAnimatorTriggerAction : Action
|
||||
{
|
||||
[SerializeReference]
|
||||
public BlackboardVariable<string> TriggerName = new BlackboardVariable<string>("");
|
||||
|
||||
protected override Status OnStart()
|
||||
{
|
||||
if (string.IsNullOrEmpty(TriggerName.Value))
|
||||
{
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
Animator animator = GameObject.GetComponentInChildren<Animator>();
|
||||
|
||||
if (animator == null)
|
||||
{
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
animator.SetTrigger(TriggerName.Value);
|
||||
return Status.Success;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 77cf4f2ff35fe3040af16374f428a648
|
||||
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using Unity.Behavior;
|
||||
using UnityEngine;
|
||||
using Action = Unity.Behavior.Action;
|
||||
using Unity.Properties;
|
||||
using Colosseum.Combat;
|
||||
|
||||
[Serializable, GeneratePropertyBag]
|
||||
[NodeDescription(name: "SetTargetInRange", story: "[거리] 내에 [대상이] 있는지 확인", category: "Action", id: "93b7a5d823a58618d5371c01ef894948")]
|
||||
public partial class SetTargetInRangeAction : Action
|
||||
{
|
||||
[SerializeReference]
|
||||
public BlackboardVariable<GameObject> Target;
|
||||
|
||||
[SerializeReference]
|
||||
public BlackboardVariable<string> Tag = new BlackboardVariable<string>("Player");
|
||||
|
||||
[SerializeReference]
|
||||
public BlackboardVariable<float> Range = new BlackboardVariable<float>(10f);
|
||||
|
||||
protected override Status OnStart()
|
||||
{
|
||||
if (string.IsNullOrEmpty(Tag.Value))
|
||||
{
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
// 모든 타겟 태그 오브젝트 찾기
|
||||
GameObject[] targets = GameObject.FindGameObjectsWithTag(Tag.Value);
|
||||
|
||||
if (targets == null || targets.Length == 0)
|
||||
{
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
// 가장 가까운 살아있는 타겟 찾기
|
||||
GameObject nearestTarget = null;
|
||||
float nearestDistance = Range.Value; // Range 내에서만 검색
|
||||
|
||||
foreach (GameObject potentialTarget in targets)
|
||||
{
|
||||
// 사망한 타겟은 제외
|
||||
IDamageable damageable = potentialTarget.GetComponent<IDamageable>();
|
||||
if (damageable != null && damageable.IsDead)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
float distance = Vector3.Distance(
|
||||
GameObject.transform.position,
|
||||
potentialTarget.transform.position
|
||||
);
|
||||
|
||||
if (distance < nearestDistance)
|
||||
{
|
||||
nearestDistance = distance;
|
||||
nearestTarget = potentialTarget;
|
||||
}
|
||||
}
|
||||
|
||||
if (nearestTarget == null)
|
||||
{
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
Target.Value = nearestTarget;
|
||||
return Status.Success;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 02cd3ab41f67bf344b667b6a0c12a4d0
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using Unity.Behavior;
|
||||
using UnityEngine;
|
||||
using Action = Unity.Behavior.Action;
|
||||
using Unity.Properties;
|
||||
|
||||
[Serializable, GeneratePropertyBag]
|
||||
[NodeDescription(name: "StopMovement", story: "이동 정지", category: "Action", id: "1a0e2eb87421ed94502031790df56f37")]
|
||||
public partial class StopMovementAction : Action
|
||||
{
|
||||
|
||||
protected override Status OnStart()
|
||||
{
|
||||
UnityEngine.AI.NavMeshAgent agent = GameObject.GetComponent<UnityEngine.AI.NavMeshAgent>();
|
||||
|
||||
if (agent != null)
|
||||
{
|
||||
agent.isStopped = true;
|
||||
}
|
||||
|
||||
return Status.Success;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: afacb51ec60675d498bfc8b7ce942368
|
||||
@@ -0,0 +1,117 @@
|
||||
using System;
|
||||
using Colosseum.AI;
|
||||
using Colosseum.Skills;
|
||||
using Unity.Behavior;
|
||||
using Unity.Properties;
|
||||
using UnityEngine;
|
||||
using Action = Unity.Behavior.Action;
|
||||
|
||||
/// <summary>
|
||||
/// 보스 패턴을 실행하는 Behavior Tree Action.
|
||||
/// 패턴 내 스텝(스킬 또는 대기)을 순서대로 실행하며, 패턴 쿨타임을 관리합니다.
|
||||
/// </summary>
|
||||
[Serializable, GeneratePropertyBag]
|
||||
[NodeDescription(name: "Use Pattern", story: "[Pattern] 실행", category: "Action", id: "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6")]
|
||||
public partial class UsePatternAction : Action
|
||||
{
|
||||
[SerializeReference] public BlackboardVariable<BossPatternData> Pattern;
|
||||
|
||||
private SkillController skillController;
|
||||
private int currentStepIndex;
|
||||
private float waitEndTime;
|
||||
private bool isWaiting;
|
||||
private float lastUsedTime = float.MinValue;
|
||||
|
||||
protected override Status OnStart()
|
||||
{
|
||||
if (Pattern?.Value == null)
|
||||
{
|
||||
Debug.LogWarning("[UsePatternAction] 패턴이 null입니다.");
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
if (Time.time - lastUsedTime < Pattern.Value.Cooldown)
|
||||
{
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
if (Pattern.Value.Steps.Count == 0)
|
||||
{
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
skillController = GameObject.GetComponent<SkillController>();
|
||||
if (skillController == null)
|
||||
{
|
||||
Debug.LogWarning($"[UsePatternAction] SkillController를 찾을 수 없습니다: {GameObject.name}");
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
currentStepIndex = 0;
|
||||
isWaiting = false;
|
||||
return ExecuteCurrentStep();
|
||||
}
|
||||
|
||||
protected override Status OnUpdate()
|
||||
{
|
||||
if (skillController == null)
|
||||
return Status.Failure;
|
||||
|
||||
if (isWaiting)
|
||||
{
|
||||
if (Time.time < waitEndTime)
|
||||
return Status.Running;
|
||||
|
||||
isWaiting = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (skillController.IsPlayingAnimation)
|
||||
return Status.Running;
|
||||
|
||||
}
|
||||
|
||||
currentStepIndex++;
|
||||
|
||||
if (currentStepIndex >= Pattern.Value.Steps.Count)
|
||||
{
|
||||
lastUsedTime = Time.time;
|
||||
return Status.Success;
|
||||
}
|
||||
|
||||
return ExecuteCurrentStep();
|
||||
}
|
||||
|
||||
protected override void OnEnd()
|
||||
{
|
||||
skillController = null;
|
||||
}
|
||||
|
||||
private Status ExecuteCurrentStep()
|
||||
{
|
||||
PatternStep step = Pattern.Value.Steps[currentStepIndex];
|
||||
|
||||
if (step.Type == PatternStepType.Wait)
|
||||
{
|
||||
isWaiting = true;
|
||||
waitEndTime = Time.time + step.Duration;
|
||||
return Status.Running;
|
||||
}
|
||||
|
||||
// PatternStepType.Skill
|
||||
if (step.Skill == null)
|
||||
{
|
||||
Debug.LogWarning($"[UsePatternAction] 스킬이 null입니다. (index {currentStepIndex})");
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
bool success = skillController.ExecuteSkill(step.Skill);
|
||||
if (!success)
|
||||
{
|
||||
Debug.LogWarning($"[UsePatternAction] 스킬 실행 실패: {step.Skill.SkillName} (index {currentStepIndex})");
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
return Status.Running;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a696fff0581f7264d9491514e9aee277
|
||||
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using Colosseum.Skills;
|
||||
using Unity.Behavior;
|
||||
using UnityEngine;
|
||||
using Action = Unity.Behavior.Action;
|
||||
using Unity.Properties;
|
||||
|
||||
/// <summary>
|
||||
/// 지정된 스킬을 사용하는 Behavior Tree Action.
|
||||
/// 스킬 실행이 완료될 때까지 Running 상태를 유지합니다.
|
||||
/// </summary>
|
||||
[Serializable, GeneratePropertyBag]
|
||||
[NodeDescription(name: "Use Skill", story: "[스킬] 사용", category: "Action", id: "799f1e8cfafa78b2d52ef61a6bbb29b9")]
|
||||
public partial class UseSkillAction : Action
|
||||
{
|
||||
[SerializeReference] public BlackboardVariable<SkillData> 스킬;
|
||||
|
||||
private SkillController skillController;
|
||||
|
||||
protected override Status OnStart()
|
||||
{
|
||||
// 스킬 데이터 확인
|
||||
if (스킬?.Value == null)
|
||||
{
|
||||
Debug.LogWarning("[UseSkillAction] 스킬이 null입니다.");
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
// SkillController 컴포넌트 가져오기
|
||||
skillController = GameObject.GetComponent<SkillController>();
|
||||
if (skillController == null)
|
||||
{
|
||||
Debug.LogWarning($"[UseSkillAction] SkillController를 찾을 수 없습니다: {GameObject.name}");
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
// 스킬 실행 시도
|
||||
bool success = skillController.ExecuteSkill(스킬.Value);
|
||||
if (!success)
|
||||
{
|
||||
// 이미 다른 스킬 사용 중이거나 쿨타임
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
return Status.Running;
|
||||
}
|
||||
|
||||
protected override Status OnUpdate()
|
||||
{
|
||||
// SkillController가 해제된 경우
|
||||
if (skillController == null)
|
||||
{
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
// 스킬 애니메이션이 종료되면 성공
|
||||
if (!skillController.IsPlayingAnimation)
|
||||
{
|
||||
return Status.Success;
|
||||
}
|
||||
|
||||
return Status.Running;
|
||||
}
|
||||
|
||||
protected override void OnEnd()
|
||||
{
|
||||
skillController = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cf140a11f5104674fb8367f4eb5702cb
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using Unity.Behavior;
|
||||
using UnityEngine;
|
||||
using Action = Unity.Behavior.Action;
|
||||
using Unity.Properties;
|
||||
|
||||
[Serializable, GeneratePropertyBag]
|
||||
[NodeDescription(name: "Wait", story: "대기", category: "Action", id: "73b84bd4bc0eb61c998ac84c9853a69d")]
|
||||
public partial class WaitAction : Action
|
||||
{
|
||||
[SerializeReference]
|
||||
public BlackboardVariable<float> Duration = new BlackboardVariable<float>(1f);
|
||||
|
||||
private float startTime;
|
||||
|
||||
protected override Status OnStart()
|
||||
{
|
||||
startTime = Time.time;
|
||||
return Status.Running;
|
||||
}
|
||||
|
||||
protected override Status OnUpdate()
|
||||
{
|
||||
if (Time.time - startTime >= Duration.Value)
|
||||
{
|
||||
return Status.Success;
|
||||
}
|
||||
return Status.Running;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 324b69471491c9448ae5d71a426dd596
|
||||
Reference in New Issue
Block a user