85e74821ad
Throw items in spray pattern for trickster's box
192 lines
6.2 KiB
C#
192 lines
6.2 KiB
C#
using Chickensoft.AutoInject;
|
|
using Chickensoft.Introspection;
|
|
using Godot;
|
|
using Zennysoft.Ma.Adapter;
|
|
using Zennysoft.Ma.Adapter.Entity;
|
|
|
|
namespace Zennysoft.Game.Ma;
|
|
|
|
[Meta(typeof(IAutoNode))]
|
|
public partial class ThrownItem : RigidBody3D, IThrownItem
|
|
{
|
|
public override void _Notification(int what) => this.Notify(what);
|
|
|
|
[Dependency] public IPlayer Player => this.DependOn<IPlayer>();
|
|
|
|
[Dependency] public IGame Game => this.DependOn<IGame>();
|
|
|
|
public IBaseInventoryItem ItemThatIsThrown { get; set; }
|
|
|
|
private EffectService _effectService;
|
|
private ItemReroller _itemReroller;
|
|
|
|
[Node] public Sprite2D Sprite { get; set; } = default!;
|
|
|
|
[Node] public Area3D Collision { get; set; } = default!;
|
|
|
|
public void OnResolved()
|
|
{
|
|
BodyEntered += ThrownItem_BodyEntered;
|
|
Collision.AreaEntered += Collision_AreaEntered;
|
|
GlobalPosition = Player.GlobalPosition;
|
|
Sprite.Texture = ItemThatIsThrown.GetTexture();
|
|
AddCollisionExceptionWith((Node)Player);
|
|
Collision.SetCollisionLayerValue(3, false);
|
|
_itemReroller = new ItemReroller(ItemDatabase.Instance);
|
|
}
|
|
|
|
private void Collision_AreaEntered(Area3D area)
|
|
{
|
|
if (area.GetOwner() is IEnemy enemy)
|
|
{
|
|
CalculateEffect(enemy);
|
|
QueueFree();
|
|
}
|
|
}
|
|
|
|
private void ThrownItem_BodyEntered(Node body)
|
|
{
|
|
if (ItemThatIsThrown is ThrowableItem)
|
|
{
|
|
QueueFree();
|
|
}
|
|
else
|
|
{
|
|
RemoveCollisionExceptionWith((Node)Player);
|
|
Collision.SetCollisionLayerValue(3, true);
|
|
LinearVelocity = Vector3.Zero;
|
|
AngularVelocity = Vector3.Zero;
|
|
GravityScale = 0.5f;
|
|
}
|
|
}
|
|
|
|
public void Throw(EffectService effectService)
|
|
{
|
|
_effectService = effectService;
|
|
ApplyCentralImpulse(-Player.GlobalBasis.Z.Normalized() * ItemThatIsThrown.ThrowSpeed);
|
|
}
|
|
|
|
public void Throw(EffectService effectService, double throwAngle)
|
|
{
|
|
_effectService = effectService;
|
|
ApplyCentralImpulse(-Player.GlobalBasis.Z.Normalized().Rotated(Vector3.Up, (float)Mathf.DegToRad(throwAngle)) * ItemThatIsThrown.ThrowSpeed);
|
|
}
|
|
|
|
public void RescueItem()
|
|
{
|
|
if (!Game.RescuedItems.TryAdd(ItemThatIsThrown))
|
|
return;
|
|
ContactMonitor = false;
|
|
Freeze = true;
|
|
PlayRescueAnimation();
|
|
SfxDatabase.Instance.Play(SoundEffect.Transfer);
|
|
}
|
|
|
|
private void PlayRescueAnimation()
|
|
{
|
|
LoadShader("res://src/vfx/shaders/PixelMelt.gdshader");
|
|
var tweener = GetTree().CreateTween();
|
|
SetShaderValue(true);
|
|
tweener.TweenMethod(Callable.From((float x) => SetShaderValue(x)), 0.0f, 0.3f, 2f);
|
|
tweener.TweenCallback(Callable.From(QueueFree));
|
|
}
|
|
|
|
private void LoadShader(string shaderPath)
|
|
{
|
|
var shader = GD.Load<Shader>(shaderPath);
|
|
Sprite.Material = new ShaderMaterial();
|
|
var shaderMaterial = (ShaderMaterial)Sprite.Material;
|
|
shaderMaterial.Shader = shader;
|
|
}
|
|
|
|
private void SetShaderValue(float shaderValue)
|
|
{
|
|
var shaderMaterial = (ShaderMaterial)Sprite.Material;
|
|
shaderMaterial.SetShaderParameter("progress", shaderValue);
|
|
}
|
|
|
|
private void SetShaderValue(bool shaderValue)
|
|
{
|
|
var shaderMaterial = (ShaderMaterial)Sprite.Material;
|
|
shaderMaterial.SetShaderParameter("reverse", shaderValue);
|
|
}
|
|
|
|
private void CalculateEffect(IEnemy enemy)
|
|
{
|
|
if (ItemThatIsThrown.ItemTag == ItemTag.MysteryItem)
|
|
ItemThatIsThrown = _itemReroller.RerollItem(ItemThatIsThrown, Player.Inventory, false);
|
|
|
|
if (ItemThatIsThrown is EffectItem usableItem)
|
|
{
|
|
switch (usableItem.UsableItemTag)
|
|
{
|
|
case UsableItemTag.LowerTargetTo1HP:
|
|
enemy.HealthComponent.SetCurrentHealth(1);
|
|
enemy.OnDebuff();
|
|
break;
|
|
case UsableItemTag.DecreaseAllStats:
|
|
enemy.AttackComponent.Reduce(usableItem.Stats.BonusAttack);
|
|
enemy.DefenseComponent.Reduce(usableItem.Stats.BonusDefense);
|
|
enemy.OnDebuff();
|
|
break;
|
|
case UsableItemTag.DecreaseAttack:
|
|
enemy.AttackComponent.LowerMaximumAttack(usableItem.Stats.BonusAttack);
|
|
enemy.OnDebuff();
|
|
break;
|
|
case UsableItemTag.DecreaseDefense:
|
|
enemy.DefenseComponent.LowerMaximumDefense(usableItem.Stats.BonusDefense);
|
|
enemy.OnDebuff();
|
|
break;
|
|
case UsableItemTag.IncreaseAttack:
|
|
enemy.AttackComponent.RaiseMaximumAttack(usableItem.Stats.BonusAttack);
|
|
enemy.OnBuff();
|
|
break;
|
|
case UsableItemTag.IncreaseDefense:
|
|
enemy.DefenseComponent.RaiseMaximumDefense(usableItem.Stats.BonusDefense);
|
|
enemy.OnBuff();
|
|
break;
|
|
case UsableItemTag.TeleportToRandomLocation:
|
|
_effectService.TeleportToRandomRoom(enemy);
|
|
SfxDatabase.Instance.Play(SoundEffect.TeleportToRandomRoom);
|
|
break;
|
|
case UsableItemTag.GlueAllEquipment:
|
|
_effectService.DisableEnemyMovement(enemy);
|
|
enemy.OnDebuff();
|
|
break;
|
|
case UsableItemTag.Clone:
|
|
_effectService.CloneEnemy(enemy);
|
|
enemy.OnBuff();
|
|
break;
|
|
default:
|
|
var damageDealt = DamageCalculator.CalculateDamage(new AttackData(usableItem.ThrowDamage, ElementType.None), enemy.DefenseComponent.CurrentDefense.Value, enemy.ElementalResistanceSet);
|
|
enemy.HealthComponent.Damage(damageDealt, ElementType.None);
|
|
break;
|
|
}
|
|
}
|
|
else if (ItemThatIsThrown is BoxItem boxItem)
|
|
{
|
|
switch (boxItem.Stats.ItemTag)
|
|
{
|
|
case ItemTag.RestrictUnequip:
|
|
_effectService.DisableEnemyMovement(enemy);
|
|
enemy.OnDebuff();
|
|
break;
|
|
default:
|
|
var damageDealt = DamageCalculator.CalculateDamage(new AttackData(boxItem.ThrowDamage, ElementType.None), enemy.DefenseComponent.CurrentDefense.Value, enemy.ElementalResistanceSet);
|
|
enemy.HealthComponent.Damage(damageDealt, ElementType.None);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var damageDealt = DamageCalculator.CalculateDamage(new AttackData(ItemThatIsThrown.ThrowDamage, ElementType.None), enemy.DefenseComponent.CurrentDefense.Value, enemy.ElementalResistanceSet);
|
|
enemy.HealthComponent.Damage(damageDealt, ElementType.None);
|
|
}
|
|
}
|
|
|
|
public void OnExitTree()
|
|
{
|
|
BodyEntered -= ThrownItem_BodyEntered;
|
|
Collision.AreaEntered -= Collision_AreaEntered;
|
|
}
|
|
} |