Revamp boss logic
134
Zennysoft.Game.Ma/src/enemy/BossTypeA.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
using Chickensoft.AutoInject;
|
||||
using Chickensoft.Introspection;
|
||||
using Godot;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using Zennysoft.Ma.Adapter;
|
||||
|
||||
namespace Zennysoft.Game.Ma;
|
||||
|
||||
[Meta(typeof(IAutoNode))]
|
||||
public partial class BossTypeA : Enemy, IHasPrimaryAttack, IHasSecondaryAttack, ICanActivate
|
||||
{
|
||||
public override void _Notification(int what) => this.Notify(what);
|
||||
|
||||
[Export]
|
||||
public ElementType PrimaryAttackElementalType { get; set; } = ElementType.None;
|
||||
[Export]
|
||||
public double PrimaryAttackElementalDamageBonus { get; set; } = 1.0;
|
||||
|
||||
public ElementType SecondaryAttackElementalType { get; set; } = ElementType.None;
|
||||
|
||||
public double SecondaryAttackElementalDamageBonus { get; set; } = 1.0;
|
||||
|
||||
[Node] public new EnemyModelView3D _enemyModelView { get; set; }
|
||||
|
||||
[Node] public CollisionShape3D EnemyHitbox { get; set; } = default!;
|
||||
|
||||
private Vector3 _target;
|
||||
|
||||
public void OnReady()
|
||||
{
|
||||
_target = GlobalPosition;
|
||||
SetPhysicsProcess(true);
|
||||
_enemyModelView.Hitbox.AreaEntered += Hitbox_AreaEntered;
|
||||
_attackTimer.Start();
|
||||
}
|
||||
|
||||
public void OnPhysicsProcess(double delta)
|
||||
{
|
||||
_enemyLogic.Input(new EnemyLogic.Input.PhysicsTick(delta));
|
||||
|
||||
if (_enemyLogic.Value is not EnemyLogic.State.Activated)
|
||||
return;
|
||||
|
||||
if (_enemyLogic.Value is EnemyLogic.State.FollowPlayer && GlobalPosition.DistanceTo(_player.CurrentPosition) < 5f)
|
||||
_enemyLogic.Input(new EnemyLogic.Input.StartAttacking());
|
||||
if (_enemyLogic.Value is EnemyLogic.State.Attacking && GlobalPosition.DistanceTo(_player.CurrentPosition) > 5f)
|
||||
_enemyLogic.Input(new EnemyLogic.Input.Alerted());
|
||||
|
||||
var direction = (_target - GlobalPosition).Normalized();
|
||||
LookAt(direction);
|
||||
|
||||
if (_enemyLogic.Value is EnemyLogic.State.FollowPlayer)
|
||||
{
|
||||
Velocity = direction * _movementSpeed;
|
||||
MoveAndSlide();
|
||||
_enemyModelView.PlayWalkAnimation();
|
||||
}
|
||||
else
|
||||
{
|
||||
_enemyModelView.PlayIdleAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
public override void TakeAction()
|
||||
{
|
||||
var rng = new RandomNumberGenerator();
|
||||
var options = new List<Action>() { PrimaryAttack, SecondaryAttack };
|
||||
var selection = rng.RandWeighted([0.875f, 0.125f]);
|
||||
options[(int)selection].Invoke();
|
||||
}
|
||||
|
||||
public void PrimaryAttack()
|
||||
{
|
||||
_enemyModelView.PlayPrimaryAttackAnimation();
|
||||
}
|
||||
|
||||
public void SecondaryAttack()
|
||||
{
|
||||
_enemyModelView.PlaySecondaryAttackAnimation();
|
||||
}
|
||||
|
||||
public override void StartAttackTimer()
|
||||
{
|
||||
_attackTimer.Timeout += OnAttackTimeout;
|
||||
}
|
||||
|
||||
public override void StopAttackTimer()
|
||||
{
|
||||
_attackTimer.Timeout -= OnAttackTimeout;
|
||||
}
|
||||
|
||||
public override void SetTarget(Vector3 target) => _target = target;
|
||||
|
||||
private void Hitbox_AreaEntered(Area3D area)
|
||||
{
|
||||
var target = area.GetOwner();
|
||||
if (target is IPlayer player)
|
||||
{
|
||||
var damage = _enemyStatResource.CurrentAttack * PrimaryAttackElementalDamageBonus;
|
||||
player.TakeDamage(damage, PrimaryAttackElementalType, BattleExtensions.IsCriticalHit(_enemyStatResource.Luck));
|
||||
}
|
||||
}
|
||||
|
||||
public void Activate()
|
||||
{
|
||||
Show();
|
||||
_enemyLogic.Input(new EnemyLogic.Input.Alerted());
|
||||
EnemyHitbox.SetDeferred(CollisionShape3D.PropertyName.Disabled, false);
|
||||
}
|
||||
|
||||
private void OnAttackTimeout()
|
||||
{
|
||||
if (GlobalPosition.DistanceTo(_player.CurrentPosition) > 5f)
|
||||
{
|
||||
_enemyLogic.Input(new EnemyLogic.Input.Alerted());
|
||||
return;
|
||||
}
|
||||
|
||||
var rng = new RandomNumberGenerator();
|
||||
rng.Randomize();
|
||||
_enemyLogic.Input(new EnemyLogic.Input.AttackTimer());
|
||||
_attackTimer.Stop();
|
||||
_attackTimer.WaitTime = rng.RandfRange(2f, 5.0f);
|
||||
_attackTimer.Start();
|
||||
}
|
||||
|
||||
public override void _ExitTree()
|
||||
{
|
||||
CurrentHP.OnCompleted();
|
||||
StopAttackTimer();
|
||||
_enemyModelView.Hitbox.AreaEntered -= Hitbox_AreaEntered;
|
||||
}
|
||||
}
|
||||
1
Zennysoft.Game.Ma/src/enemy/BossTypeA.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dveonnhcxcp08
|
||||
@@ -31,7 +31,7 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
|
||||
[Export] protected EnemyStatResource _enemyStatResource { get; set; } = default!;
|
||||
|
||||
[Export]
|
||||
private float _movementSpeed = 2f;
|
||||
protected float _movementSpeed = 2f;
|
||||
#endregion
|
||||
|
||||
#region Node Dependencies
|
||||
@@ -39,16 +39,14 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
|
||||
|
||||
[Node] private Area3D _lineOfSight { get; set; } = default!;
|
||||
|
||||
[Node] private Timer _attackTimer { get; set; } = default!;
|
||||
[Node] protected Timer _attackTimer { get; set; } = default!;
|
||||
|
||||
[Node] private RayCast3D _raycast { get; set; } = default!;
|
||||
|
||||
[Node] protected IEnemyModelView _enemyModelView { get; set; } = default!;
|
||||
#endregion
|
||||
|
||||
public double CurrentHP => _currentHP.Value;
|
||||
|
||||
private AutoProp<double> _currentHP { get; set; }
|
||||
public AutoProp<double> CurrentHP { get; set; }
|
||||
|
||||
private float _knockbackStrength = 0.0f;
|
||||
|
||||
@@ -80,14 +78,14 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
|
||||
|
||||
_enemyLogic.Start();
|
||||
|
||||
_currentHP = new AutoProp<double>(_enemyStatResource.MaximumHP);
|
||||
_currentHP.Sync += OnHPChanged;
|
||||
CurrentHP = new AutoProp<double>(_enemyStatResource.MaximumHP);
|
||||
CurrentHP.Sync += OnHPChanged;
|
||||
_lineOfSight.BodyEntered += LineOfSight_BodyEntered;
|
||||
}
|
||||
|
||||
public override void _PhysicsProcess(double delta)
|
||||
{
|
||||
if (CurrentHP <= 0)
|
||||
if (CurrentHP.Value <= 0)
|
||||
return;
|
||||
|
||||
var lookDir = GlobalPosition + Velocity;
|
||||
@@ -118,7 +116,7 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
|
||||
|
||||
public virtual void TakeDamage(double damage, ElementType elementType, bool isCriticalHit = false, bool ignoreDefense = false, bool ignoreElementalResistance = false)
|
||||
{
|
||||
if (_currentHP.Value > 0)
|
||||
if (CurrentHP.Value > 0)
|
||||
{
|
||||
if (!ignoreElementalResistance)
|
||||
damage = CalculateElementalResistance(damage, elementType);
|
||||
@@ -127,10 +125,10 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
|
||||
if (isCriticalHit)
|
||||
damage *= 2;
|
||||
GD.Print($"Enemy Hit for {damage} damage.");
|
||||
_currentHP.OnNext(_currentHP.Value - damage);
|
||||
GD.Print("Current HP: " + _currentHP.Value);
|
||||
CurrentHP.OnNext(CurrentHP.Value - damage);
|
||||
GD.Print("Current HP: " + CurrentHP.Value);
|
||||
|
||||
if (_currentHP.Value <= 0)
|
||||
if (CurrentHP.Value <= 0)
|
||||
return;
|
||||
|
||||
_enemyModelView.PlayHitAnimation();
|
||||
@@ -149,7 +147,7 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
|
||||
|
||||
public void Die()
|
||||
{
|
||||
_currentHP.OnNext(0);
|
||||
CurrentHP.OnNext(0);
|
||||
_enemyLogic.Input(new EnemyLogic.Input.EnemyDefeated());
|
||||
_collisionShape.SetDeferred("disabled", true);
|
||||
_enemyModelView.PlayDeathAnimation();
|
||||
@@ -161,7 +159,7 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
|
||||
|
||||
public void SetCurrentHP(int targetHP)
|
||||
{
|
||||
_currentHP.OnNext(targetHP);
|
||||
CurrentHP.OnNext(targetHP);
|
||||
}
|
||||
|
||||
public int GetMaximumHP()
|
||||
@@ -169,12 +167,12 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
|
||||
return _enemyStatResource.MaximumHP;
|
||||
}
|
||||
|
||||
public void StartAttackTimer()
|
||||
public virtual void StartAttackTimer()
|
||||
{
|
||||
_attackTimer.Timeout += OnAttackTimeout;
|
||||
}
|
||||
|
||||
public void StopAttackTimer()
|
||||
public virtual void StopAttackTimer()
|
||||
{
|
||||
_attackTimer.Timeout -= OnAttackTimeout;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Chickensoft.AutoInject;
|
||||
using Chickensoft.AutoInject;
|
||||
using Chickensoft.Introspection;
|
||||
using Godot;
|
||||
|
||||
@@ -10,12 +10,8 @@ public partial class EnemyModelView3D : Node3D, IEnemyModelView
|
||||
private const string PRIMARY_ATTACK = "primary_attack";
|
||||
private const string SECONDARY_ATTACK = "secondary_attack";
|
||||
private const string PRIMARY_SKILL = "primary_skill";
|
||||
private const string IDLE_FORWARD = "idle_front";
|
||||
private const string IDLE_LEFT = "idle_left";
|
||||
private const string IDLE_BACK = "idle_back";
|
||||
private const string IDLE_FORWARD_WALK = "idle_front_walk";
|
||||
private const string IDLE_LEFT_WALK = "idle_left_walk";
|
||||
private const string IDLE_BACK_WALK = "idle_back_walk";
|
||||
private const string WALK = "walk";
|
||||
private const string IDLE = "idle";
|
||||
private const string TAKE_DAMAGE = "take_damage";
|
||||
private const string DEFEATED = "defeated";
|
||||
private const string PARAMETERS_PLAYBACK = "parameters/playback";
|
||||
@@ -24,34 +20,48 @@ public partial class EnemyModelView3D : Node3D, IEnemyModelView
|
||||
|
||||
[Export] public EnemyLoreInfo EnemyLoreInfo { get; set; } = default!;
|
||||
|
||||
[Node] private MeshInstance3D _meshInstance { get; set; } = default!;
|
||||
|
||||
[Node] private AnimationPlayer _animationPlayer { get; set; } = default!;
|
||||
|
||||
[Node] public AnimationTree AnimationTree { get; set; } = default!;
|
||||
|
||||
[Node] public IHitbox Hitbox { get; set; } = default!;
|
||||
|
||||
public void Setup()
|
||||
{
|
||||
}
|
||||
|
||||
public void PlayPrimaryAttackAnimation()
|
||||
{
|
||||
_animationPlayer.Play(PRIMARY_ATTACK);
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(PRIMARY_ATTACK);
|
||||
}
|
||||
|
||||
public void PlaySecondaryAttackAnimation()
|
||||
{
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(SECONDARY_ATTACK);
|
||||
}
|
||||
|
||||
public void PlayPrimarySkillAnimation()
|
||||
{
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(PRIMARY_SKILL);
|
||||
}
|
||||
|
||||
public void PlayHitAnimation()
|
||||
{
|
||||
_animationPlayer.Play(TAKE_DAMAGE);
|
||||
_animationPlayer.Play(TAKE_DAMAGE);
|
||||
}
|
||||
|
||||
public void PlayDeathAnimation()
|
||||
{
|
||||
_animationPlayer.Play(DEFEATED);
|
||||
_animationPlayer.Play(DEFEATED);
|
||||
}
|
||||
|
||||
public void PlayWalkAnimation()
|
||||
{
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(WALK);
|
||||
}
|
||||
|
||||
public void PlayIdleAnimation()
|
||||
{
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(IDLE);
|
||||
}
|
||||
}
|
||||
|
||||
6
Zennysoft.Game.Ma/src/enemy/ICanActivate.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace Zennysoft.Game.Ma;
|
||||
|
||||
public interface ICanActivate
|
||||
{
|
||||
public void Activate();
|
||||
}
|
||||
1
Zennysoft.Game.Ma/src/enemy/ICanActivate.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://btxdf6ncxkk02
|
||||
@@ -1,4 +1,5 @@
|
||||
using Godot;
|
||||
using Chickensoft.Collections;
|
||||
using Godot;
|
||||
using Zennysoft.Game.Abstractions;
|
||||
using Zennysoft.Ma.Adapter;
|
||||
|
||||
@@ -14,7 +15,7 @@ public interface IEnemy : IKillable
|
||||
|
||||
public void Knockback(float impulse, Vector3 direction);
|
||||
|
||||
public double CurrentHP { get; }
|
||||
public AutoProp<double> CurrentHP { get; }
|
||||
|
||||
public void SetCurrentHP(int newHP);
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ using Zennysoft.Ma.Adapter;
|
||||
namespace Zennysoft.Game.Ma;
|
||||
|
||||
[Meta(typeof(IAutoNode))]
|
||||
public partial class Chinthe : Enemy, IHasPrimaryAttack, ICanPatrol
|
||||
public partial class Chinthe : Enemy, IHasPrimaryAttack, ICanPatrol, ICanActivate
|
||||
{
|
||||
public override void _Notification(int what) => this.Notify(what);
|
||||
|
||||
@@ -24,72 +24,72 @@ public partial class Chinthe : Enemy, IHasPrimaryAttack, ICanPatrol
|
||||
|
||||
public void OnReady()
|
||||
{
|
||||
SetPhysicsProcess(true);
|
||||
EnemyModelView.Hitbox.AreaEntered += Hitbox_AreaEntered;
|
||||
SetPhysicsProcess(true);
|
||||
EnemyModelView.Hitbox.AreaEntered += Hitbox_AreaEntered;
|
||||
}
|
||||
|
||||
public void OnPhysicsProcess(double delta)
|
||||
{
|
||||
_enemyLogic.Input(new EnemyLogic.Input.PhysicsTick(delta));
|
||||
_enemyLogic.Input(new EnemyLogic.Input.PhysicsTick(delta));
|
||||
|
||||
if (_enemyLogic.Value is not EnemyLogic.State.Activated)
|
||||
return;
|
||||
if (_enemyLogic.Value is not EnemyLogic.State.Activated)
|
||||
return;
|
||||
|
||||
if (_enemyLogic.Value is EnemyLogic.State.FollowPlayer && GlobalPosition.DistanceTo(_player.CurrentPosition) < 2.5f)
|
||||
_enemyLogic.Input(new EnemyLogic.Input.StartAttacking());
|
||||
if (_enemyLogic.Value is EnemyLogic.State.FollowPlayer && GlobalPosition.DistanceTo(_player.CurrentPosition) > 45f)
|
||||
_enemyLogic.Input(new EnemyLogic.Input.LostPlayer());
|
||||
if (_enemyLogic.Value is EnemyLogic.State.Attacking && GlobalPosition.DistanceTo(_player.CurrentPosition) > 2.5f)
|
||||
_enemyLogic.Input(new EnemyLogic.Input.Alerted());
|
||||
if (_enemyLogic.Value is EnemyLogic.State.FollowPlayer && GlobalPosition.DistanceTo(_player.CurrentPosition) < 2.5f)
|
||||
_enemyLogic.Input(new EnemyLogic.Input.StartAttacking());
|
||||
if (_enemyLogic.Value is EnemyLogic.State.FollowPlayer && GlobalPosition.DistanceTo(_player.CurrentPosition) > 45f)
|
||||
_enemyLogic.Input(new EnemyLogic.Input.LostPlayer());
|
||||
if (_enemyLogic.Value is EnemyLogic.State.Attacking && GlobalPosition.DistanceTo(_player.CurrentPosition) > 2.5f)
|
||||
_enemyLogic.Input(new EnemyLogic.Input.Alerted());
|
||||
|
||||
_navigationAgentClient.CalculateVelocity(GlobalPosition, EnemyModelView.CanMove);
|
||||
_navigationAgentClient.CalculateVelocity(GlobalPosition, EnemyModelView.CanMove);
|
||||
|
||||
base._PhysicsProcess(delta);
|
||||
base._PhysicsProcess(delta);
|
||||
}
|
||||
|
||||
public override void TakeAction()
|
||||
{
|
||||
PrimaryAttack();
|
||||
PrimaryAttack();
|
||||
}
|
||||
|
||||
public void PrimaryAttack()
|
||||
{
|
||||
_enemyModelView.PlayPrimaryAttackAnimation();
|
||||
_enemyModelView.PlayPrimaryAttackAnimation();
|
||||
}
|
||||
|
||||
public override void SetTarget(Vector3 target) => _navigationAgentClient.SetTarget(target);
|
||||
|
||||
public void Patrol()
|
||||
{
|
||||
var rng = new RandomNumberGenerator();
|
||||
rng.Randomize();
|
||||
var randomizedSpot = new Vector3(rng.RandfRange(-5.0f, 5.0f), 0, rng.RandfRange(-5.0f, 5.0f));
|
||||
_enemyLogic.Input(new EnemyLogic.Input.PatrolToRandomSpot(GlobalPosition + randomizedSpot));
|
||||
_enemyLogic.Input(new EnemyLogic.Input.StartPatrol());
|
||||
var rng = new RandomNumberGenerator();
|
||||
rng.Randomize();
|
||||
var randomizedSpot = new Vector3(rng.RandfRange(-5.0f, 5.0f), 0, rng.RandfRange(-5.0f, 5.0f));
|
||||
_enemyLogic.Input(new EnemyLogic.Input.PatrolToRandomSpot(GlobalPosition + randomizedSpot));
|
||||
_enemyLogic.Input(new EnemyLogic.Input.StartPatrol());
|
||||
}
|
||||
|
||||
public void Activate()
|
||||
{
|
||||
if (EnemyModelView.AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().GetCurrentNode().ToString().Contains("front"))
|
||||
EnemyModelView.PlayActivateFrontAnimation();
|
||||
if (EnemyModelView.AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().GetCurrentNode().ToString().Contains("left"))
|
||||
EnemyModelView.PlayActivateLeftAnimation();
|
||||
if (EnemyModelView.AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().GetCurrentNode().ToString().Contains("back"))
|
||||
EnemyModelView.PlayActivateBackAnimation();
|
||||
if (EnemyModelView.AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().GetCurrentNode().ToString().Contains("front"))
|
||||
EnemyModelView.PlayActivateFrontAnimation();
|
||||
if (EnemyModelView.AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().GetCurrentNode().ToString().Contains("left"))
|
||||
EnemyModelView.PlayActivateLeftAnimation();
|
||||
if (EnemyModelView.AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().GetCurrentNode().ToString().Contains("back"))
|
||||
EnemyModelView.PlayActivateBackAnimation();
|
||||
}
|
||||
|
||||
public void Teleport()
|
||||
{
|
||||
EnemyModelView.PlayTeleportAnimation();
|
||||
EnemyModelView.PlayTeleportAnimation();
|
||||
}
|
||||
|
||||
private void Hitbox_AreaEntered(Area3D area)
|
||||
{
|
||||
var target = area.GetOwner();
|
||||
if (target is IPlayer player)
|
||||
{
|
||||
var damage = _enemyStatResource.CurrentAttack * PrimaryAttackElementalDamageBonus;
|
||||
player.TakeDamage(damage, PrimaryAttackElementalType, BattleExtensions.IsCriticalHit(_enemyStatResource.Luck));
|
||||
}
|
||||
var target = area.GetOwner();
|
||||
if (target is IPlayer player)
|
||||
{
|
||||
var damage = _enemyStatResource.CurrentAttack * PrimaryAttackElementalDamageBonus;
|
||||
player.TakeDamage(damage, PrimaryAttackElementalType, BattleExtensions.IsCriticalHit(_enemyStatResource.Luck));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
[ext_resource type="Texture2D" uid="uid://cvst7yhbw0sxt" path="res://src/enemy/enemy_types/10. Eden Pillar/model/PILLAR EXPORT 1_ENEMY_PILLAR_TEXTURE2.jpg" id="1_1kpl1"]
|
||||
[ext_resource type="Script" uid="uid://ckv5dmrw6pvn6" path="res://src/enemy/EnemyModelView3D.cs" id="1_11eq8"]
|
||||
[ext_resource type="Texture2D" uid="uid://bnbveonobhyhc" path="res://src/enemy/enemy_types/10. Eden Pillar/model/PILLAR EXPORT 1_cannon_edge.png" id="2_11eq8"]
|
||||
[ext_resource type="Material" uid="uid://brwu51ylevbmg" path="res://src/enemy/enemy_types/14. horse_head/BossHit.tres" id="2_xf2ga"]
|
||||
[ext_resource type="Material" uid="uid://brwu51ylevbmg" path="res://src/enemy/enemy_types/14. horse_head/animation/BossHit.tres" id="2_xf2ga"]
|
||||
[ext_resource type="Texture2D" uid="uid://by7k6crx6fmpv" path="res://src/enemy/enemy_types/10. Eden Pillar/model/PILLAR EXPORT 1_floral_single_tile.jpg" id="3_oxjs8"]
|
||||
[ext_resource type="Texture2D" uid="uid://cc1tenm6p3pca" path="res://src/enemy/enemy_types/10. Eden Pillar/model/PILLAR EXPORT 1_ENEMY_PILLAR_TEXTURE.jpg" id="4_xf2ga"]
|
||||
[ext_resource type="Texture2D" uid="uid://bydfevqfagpq8" path="res://src/enemy/enemy_types/10. Eden Pillar/model/PILLAR EXPORT 1_concrete_0025_height_1k.png" id="5_qhmtu"]
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
uid://clt3sfgb5m3xq
|
||||
@@ -1,7 +0,0 @@
|
||||
using Godot;
|
||||
|
||||
namespace Zennysoft.Game.Ma;
|
||||
|
||||
public partial class HorseHead : Node3D
|
||||
{
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://8yaqqojv4nuv"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://c4uus6q6c4ocg" path="res://src/enemy/enemy_types/14. horse_head/Horse Head 1.0 STATUE.glb" id="1_ktvqd"]
|
||||
[ext_resource type="PackedScene" uid="uid://c4uus6q6c4ocg" path="res://src/enemy/enemy_types/14. horse_head/animation/Horse Head 1.0 STATUE.glb" id="1_ktvqd"]
|
||||
|
||||
[node name="Node3D" type="Node3D"]
|
||||
|
||||
|
||||
@@ -4,12 +4,12 @@ importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://cvqaccot8ltrf"
|
||||
path="res://.godot/imported/HORSE-FACE 1.1.glb-a095bfe8da5727e267e8a8185cd8aaee.scn"
|
||||
path="res://.godot/imported/HORSE-FACE 1.1.glb-8c0ac9d603554b32a1666de9bd9b1814.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://src/enemy/enemy_types/14. horse_head/HORSE-FACE 1.1.glb"
|
||||
dest_files=["res://.godot/imported/HORSE-FACE 1.1.glb-a095bfe8da5727e267e8a8185cd8aaee.scn"]
|
||||
source_file="res://src/enemy/enemy_types/14. horse_head/animation/HORSE-FACE 1.1.glb"
|
||||
dest_files=["res://.godot/imported/HORSE-FACE 1.1.glb-8c0ac9d603554b32a1666de9bd9b1814.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
|
Before Width: | Height: | Size: 1.6 MiB After Width: | Height: | Size: 1.6 MiB |
@@ -3,7 +3,7 @@
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://csj3kjwyn3s2u"
|
||||
path="res://.godot/imported/HORSE-FACE 1_Metal054C_1K-JPG_Color.jpg-dd3ebefab63cbbf56a2e0e52b75bc691.ctex"
|
||||
path="res://.godot/imported/HORSE-FACE 1_Metal054C_1K-JPG_Color.jpg-1f1a8445de0bb81a567077e5aec18194.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
@@ -13,8 +13,8 @@ generator_parameters={
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://src/enemy/enemy_types/14. horse_head/HORSE-FACE 1_Metal054C_1K-JPG_Color.jpg"
|
||||
dest_files=["res://.godot/imported/HORSE-FACE 1_Metal054C_1K-JPG_Color.jpg-dd3ebefab63cbbf56a2e0e52b75bc691.ctex"]
|
||||
source_file="res://src/enemy/enemy_types/14. horse_head/animation/HORSE-FACE 1_Metal054C_1K-JPG_Color.jpg"
|
||||
dest_files=["res://.godot/imported/HORSE-FACE 1_Metal054C_1K-JPG_Color.jpg-1f1a8445de0bb81a567077e5aec18194.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
|
Before Width: | Height: | Size: 311 KiB After Width: | Height: | Size: 311 KiB |
@@ -3,7 +3,7 @@
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dd7ocxanos2o7"
|
||||
path="res://.godot/imported/HORSE-FACE 1_Metal054C_1K-JPG_Displacement.jpg-5771feccb31b5f0e73720e8a3e7a5725.ctex"
|
||||
path="res://.godot/imported/HORSE-FACE 1_Metal054C_1K-JPG_Displacement.jpg-386dacafcbff768209a8a638cefcea95.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
@@ -13,8 +13,8 @@ generator_parameters={
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://src/enemy/enemy_types/14. horse_head/HORSE-FACE 1_Metal054C_1K-JPG_Displacement.jpg"
|
||||
dest_files=["res://.godot/imported/HORSE-FACE 1_Metal054C_1K-JPG_Displacement.jpg-5771feccb31b5f0e73720e8a3e7a5725.ctex"]
|
||||
source_file="res://src/enemy/enemy_types/14. horse_head/animation/HORSE-FACE 1_Metal054C_1K-JPG_Displacement.jpg"
|
||||
dest_files=["res://.godot/imported/HORSE-FACE 1_Metal054C_1K-JPG_Displacement.jpg-386dacafcbff768209a8a638cefcea95.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
@@ -4,12 +4,12 @@ importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://c4uus6q6c4ocg"
|
||||
path="res://.godot/imported/Horse Head 1.0 STATUE.glb-e0c74b4195e0fc27f4658130960774ea.scn"
|
||||
path="res://.godot/imported/Horse Head 1.0 STATUE.glb-0ffebc243c4ceff8865a777101feadec.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://src/enemy/enemy_types/14. horse_head/Horse Head 1.0 STATUE.glb"
|
||||
dest_files=["res://.godot/imported/Horse Head 1.0 STATUE.glb-e0c74b4195e0fc27f4658130960774ea.scn"]
|
||||
source_file="res://src/enemy/enemy_types/14. horse_head/animation/Horse Head 1.0 STATUE.glb"
|
||||
dest_files=["res://.godot/imported/Horse Head 1.0 STATUE.glb-0ffebc243c4ceff8865a777101feadec.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
@@ -8,7 +8,7 @@ valid=false
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://src/enemy/enemy_types/14. horse_head/Horse Head 1.0 WALK.glb"
|
||||
source_file="res://src/enemy/enemy_types/14. horse_head/animation/Horse Head 1.0 WALK.glb"
|
||||
|
||||
[params]
|
||||
|
||||
@@ -4,12 +4,12 @@ importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://b8xs07d4ycm3s"
|
||||
path="res://.godot/imported/Horse Head 1.0.glb-17c7ea9ea5d193e3a003f25b69f74650.scn"
|
||||
path="res://.godot/imported/Horse Head 1.0.glb-1e71651be336a86299c334b8540d0758.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://src/enemy/enemy_types/14. horse_head/Horse Head 1.0.glb"
|
||||
dest_files=["res://.godot/imported/Horse Head 1.0.glb-17c7ea9ea5d193e3a003f25b69f74650.scn"]
|
||||
source_file="res://src/enemy/enemy_types/14. horse_head/animation/Horse Head 1.0.glb"
|
||||
dest_files=["res://.godot/imported/Horse Head 1.0.glb-1e71651be336a86299c334b8540d0758.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
|
Before Width: | Height: | Size: 1.6 MiB After Width: | Height: | Size: 1.6 MiB |
@@ -3,7 +3,7 @@
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://2e4cp477ex0t"
|
||||
path="res://.godot/imported/Horse Head 1_Metal054C_1K-JPG_Color.jpg-309c20056c641a0bf0fe6eabcff04ca0.ctex"
|
||||
path="res://.godot/imported/Horse Head 1_Metal054C_1K-JPG_Color.jpg-0c0531e87bbeff5b38eafc2808887dbf.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
@@ -13,8 +13,8 @@ generator_parameters={
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://src/enemy/enemy_types/14. horse_head/Horse Head 1_Metal054C_1K-JPG_Color.jpg"
|
||||
dest_files=["res://.godot/imported/Horse Head 1_Metal054C_1K-JPG_Color.jpg-309c20056c641a0bf0fe6eabcff04ca0.ctex"]
|
||||
source_file="res://src/enemy/enemy_types/14. horse_head/animation/Horse Head 1_Metal054C_1K-JPG_Color.jpg"
|
||||
dest_files=["res://.godot/imported/Horse Head 1_Metal054C_1K-JPG_Color.jpg-0c0531e87bbeff5b38eafc2808887dbf.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
|
Before Width: | Height: | Size: 311 KiB After Width: | Height: | Size: 311 KiB |
@@ -3,7 +3,7 @@
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://kdnitbg4n87p"
|
||||
path="res://.godot/imported/Horse Head 1_Metal054C_1K-JPG_Displacement.jpg-22bf3780ddcc88b6230d35aebd896c20.ctex"
|
||||
path="res://.godot/imported/Horse Head 1_Metal054C_1K-JPG_Displacement.jpg-0a8cfa8420b016a4333949db03bcf0e5.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
@@ -13,8 +13,8 @@ generator_parameters={
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://src/enemy/enemy_types/14. horse_head/Horse Head 1_Metal054C_1K-JPG_Displacement.jpg"
|
||||
dest_files=["res://.godot/imported/Horse Head 1_Metal054C_1K-JPG_Displacement.jpg-22bf3780ddcc88b6230d35aebd896c20.ctex"]
|
||||
source_file="res://src/enemy/enemy_types/14. horse_head/animation/Horse Head 1_Metal054C_1K-JPG_Displacement.jpg"
|
||||
dest_files=["res://.godot/imported/Horse Head 1_Metal054C_1K-JPG_Displacement.jpg-0a8cfa8420b016a4333949db03bcf0e5.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
|
Before Width: | Height: | Size: 622 KiB After Width: | Height: | Size: 622 KiB |
@@ -3,15 +3,15 @@
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bv60n7epxktw5"
|
||||
path="res://.godot/imported/Metal054C_1K-JPG_NormalDX.jpg-1cf1bfec87fee44ad90f8f8942ca9cd1.ctex"
|
||||
path="res://.godot/imported/Metal054C_1K-JPG_NormalDX.jpg-8f619f53486c72857b0b0ce2b4ae98bd.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://src/enemy/enemy_types/14. horse_head/Metal054C_1K-JPG_NormalDX.jpg"
|
||||
dest_files=["res://.godot/imported/Metal054C_1K-JPG_NormalDX.jpg-1cf1bfec87fee44ad90f8f8942ca9cd1.ctex"]
|
||||
source_file="res://src/enemy/enemy_types/14. horse_head/animation/Metal054C_1K-JPG_NormalDX.jpg"
|
||||
dest_files=["res://.godot/imported/Metal054C_1K-JPG_NormalDX.jpg-8f619f53486c72857b0b0ce2b4ae98bd.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
using Chickensoft.AutoInject;
|
||||
using Chickensoft.Introspection;
|
||||
using Godot;
|
||||
using Zennysoft.Ma.Adapter;
|
||||
|
||||
namespace Zennysoft.Game.Ma;
|
||||
|
||||
[Meta(typeof(IAutoNode))]
|
||||
public partial class OxFace : Node3D
|
||||
{
|
||||
public override void _Notification(int what) => this.Notify(what);
|
||||
|
||||
[Node] public AnimationTree AnimationTree { get; set; } = default!;
|
||||
|
||||
[Dependency] public IPlayer Player => this.DependOn<IPlayer>();
|
||||
|
||||
[Node] public Timer AttackTimer { get; set; } = default!;
|
||||
|
||||
private bool isInRange = false;
|
||||
|
||||
public void Setup()
|
||||
{
|
||||
SetPhysicsProcess(false);
|
||||
}
|
||||
|
||||
public void EngagePlayer()
|
||||
{
|
||||
SetPhysicsProcess(true);
|
||||
Visible = true;
|
||||
AttackTimer.Timeout += AttackTimer_Timeout;
|
||||
AttackTimer.Start();
|
||||
}
|
||||
|
||||
private void AttackTimer_Timeout()
|
||||
{
|
||||
AnimationTree.Get("parameters/playback").As<AnimationNodeStateMachinePlayback>().Travel("SPEAR");
|
||||
}
|
||||
|
||||
public override void _PhysicsProcess(double delta)
|
||||
{
|
||||
var playerPosition = new Vector3(Player.CurrentPosition.X, GlobalPosition.Y, Player.CurrentPosition.Z);
|
||||
var targetDirection = GlobalPosition - Player.CurrentPosition;
|
||||
GlobalRotation = new Vector3(GlobalRotation.X, Mathf.LerpAngle(GlobalRotation.Y, Mathf.Atan2(-targetDirection.X, -targetDirection.Z), (float)delta * 3f), GlobalRotation.Z);
|
||||
if (GlobalPosition.DistanceTo(Player.CurrentPosition) > 5.0f)
|
||||
{
|
||||
isInRange = false;
|
||||
var moveToward = GlobalPosition.MoveToward(playerPosition, (float)delta * 3f);
|
||||
GlobalPosition = moveToward;
|
||||
AnimationTree.Get("parameters/playback").As<AnimationNodeStateMachinePlayback>().Travel("WALK");
|
||||
}
|
||||
else if (!isInRange)
|
||||
{
|
||||
isInRange = true;
|
||||
AnimationTree.Get("parameters/playback").As<AnimationNodeStateMachinePlayback>().Travel("IDLE");
|
||||
}
|
||||
}
|
||||
}
|
||||