977 lines
20 KiB
C#
977 lines
20 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using Godot;
|
|
using Godot.Bridge;
|
|
using Godot.NativeInterop;
|
|
|
|
[ScriptPath("res://Scripts/Puzzles/FightingGame.cs")]
|
|
public partial class FightingGame : Node2D
|
|
{
|
|
private enum Animations
|
|
{
|
|
Idle,
|
|
Walk,
|
|
BackWalk,
|
|
Hurt,
|
|
Attack1,
|
|
Attack2,
|
|
Block,
|
|
Hadouken,
|
|
Cheer,
|
|
Heal,
|
|
Surprise
|
|
}
|
|
|
|
[Signal]
|
|
public delegate void OnEndEventHandler();
|
|
|
|
public partial class Buffer
|
|
{
|
|
public int key;
|
|
|
|
public float time;
|
|
}
|
|
|
|
public partial class FigherData
|
|
{
|
|
public float hp = 100f;
|
|
|
|
public float stun;
|
|
|
|
public float knockback;
|
|
|
|
public float hyperArmor;
|
|
|
|
public float armorBuildup;
|
|
|
|
public float armorTime;
|
|
|
|
public float blockHold;
|
|
|
|
public Entity entity;
|
|
|
|
public Coroutine move;
|
|
|
|
public Color color = Main.colorWhite;
|
|
|
|
public bool block;
|
|
}
|
|
|
|
private readonly Dictionary<Animations, StringName> anims = new Dictionary<Animations, StringName>
|
|
{
|
|
{
|
|
Animations.Idle,
|
|
"Idle"
|
|
},
|
|
{
|
|
Animations.Walk,
|
|
"Walk"
|
|
},
|
|
{
|
|
Animations.BackWalk,
|
|
"BackWalk"
|
|
},
|
|
{
|
|
Animations.Hurt,
|
|
"Hurt"
|
|
},
|
|
{
|
|
Animations.Attack1,
|
|
"Attack1"
|
|
},
|
|
{
|
|
Animations.Attack2,
|
|
"Attack2"
|
|
},
|
|
{
|
|
Animations.Block,
|
|
"Block"
|
|
},
|
|
{
|
|
Animations.Hadouken,
|
|
"Hadouken"
|
|
},
|
|
{
|
|
Animations.Cheer,
|
|
"CheerBack"
|
|
},
|
|
{
|
|
Animations.Heal,
|
|
"SpellBack"
|
|
},
|
|
{
|
|
Animations.Surprise,
|
|
"SurpriseBack"
|
|
}
|
|
};
|
|
|
|
public static FightingGame instance;
|
|
|
|
[Export(PropertyHint.None, "")]
|
|
private Entity[] fighters;
|
|
|
|
[Export(PropertyHint.None, "")]
|
|
private AudioStream music;
|
|
|
|
[Export(PropertyHint.None, "")]
|
|
private Sprite2D soul;
|
|
|
|
[Export(PropertyHint.None, "")]
|
|
private PackedScene axisSphere;
|
|
|
|
[Export(PropertyHint.None, "")]
|
|
private PackedScene shockWave;
|
|
|
|
[Export(PropertyHint.None, "")]
|
|
private Node2D UI;
|
|
|
|
[Export(PropertyHint.None, "")]
|
|
private Node2D[] hpBars;
|
|
|
|
[Export(PropertyHint.None, "")]
|
|
private AnimationPlayer roundAnim;
|
|
|
|
[Export(PropertyHint.None, "")]
|
|
private RichTextLabel help;
|
|
|
|
public int round = 1;
|
|
|
|
public int tp;
|
|
|
|
public int itp;
|
|
|
|
private const int kanakoCost = 90;
|
|
|
|
private const int hadoukenCost = 15;
|
|
|
|
private const int kanakoHeal = 35;
|
|
|
|
public bool active;
|
|
|
|
private FigherData[] data = new FigherData[2];
|
|
|
|
private Coroutine busy;
|
|
|
|
private Coroutine healing;
|
|
|
|
private List<Node> proj = new List<Node>();
|
|
|
|
private float projTime;
|
|
|
|
private Node2D shockwave;
|
|
|
|
private readonly StringName hitbox = "Hit";
|
|
|
|
private List<Buffer> buffers = new List<Buffer>();
|
|
|
|
private const int enemyDist = 50;
|
|
|
|
private float aiTime;
|
|
|
|
private float blockTime;
|
|
|
|
private float comboTime;
|
|
|
|
private int combo;
|
|
|
|
|
|
public override void _EnterTree()
|
|
{
|
|
instance = this;
|
|
fighters[0].trigger.AreaEntered += PlayerHit;
|
|
fighters[1].trigger.AreaEntered += EnemyHit;
|
|
}
|
|
|
|
public override void _Process(double delta)
|
|
{
|
|
UI.Position = new Vector2(0f, Mathf.Lerp(UI.Position.Y, (!active) ? (-70) : 0, Main.deltaTime * 0.1f));
|
|
FigherData[] array = data;
|
|
if (array != null && array.Length != 0 && data[0] != null)
|
|
{
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
hpBars[i].Scale = new Vector2(Mathf.Max(0f, data[i].hp / 100f), 1f);
|
|
fighters[i].Modulate = fighters[i].Modulate.Lerp(data[i].color, Main.deltaTime * 0.1f);
|
|
}
|
|
}
|
|
if (!active)
|
|
{
|
|
return;
|
|
}
|
|
Player.instance.canInput = false;
|
|
if (busy == null || busy.done)
|
|
{
|
|
for (int j = 0; j < 2; j++)
|
|
{
|
|
fighters[j].GlobalPosition = new Vector2(fighters[j].GlobalPosition.X, fighters[j].startPos.Y);
|
|
if (data[j].stun <= 0f && data[j].knockback <= 0f && (data[j].move == null || data[j].move.done))
|
|
{
|
|
if (j == 0)
|
|
{
|
|
Inputs();
|
|
}
|
|
else
|
|
{
|
|
EnemyAI();
|
|
}
|
|
}
|
|
else if (data[j].knockback > 0f)
|
|
{
|
|
DoKnockback(j);
|
|
}
|
|
else if (data[j].stun > 0f)
|
|
{
|
|
data[j].entity.Velocity = Vector2.Zero;
|
|
}
|
|
}
|
|
KanakoAnim();
|
|
}
|
|
DWMenu.instance.showHP = 5f;
|
|
BattleDR.UpdateTP(ref itp, in tp, 0, 1);
|
|
Cooldowns();
|
|
}
|
|
|
|
private void KanakoAnim()
|
|
{
|
|
Coroutine coroutine = healing;
|
|
if (coroutine == null || coroutine.done)
|
|
{
|
|
if (data[0].knockback > 0f)
|
|
{
|
|
Player.instance.followers[0].anim.Play(anims[Animations.Surprise]);
|
|
}
|
|
else
|
|
{
|
|
Player.instance.followers[0].anim.Play(anims[Animations.Cheer]);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DoKnockback(int i)
|
|
{
|
|
float num = Main.deltaTime * Mathf.Clamp(data[i].knockback, 0f, 10f) * 5f;
|
|
if (i == 0)
|
|
{
|
|
fighters[i].Velocity = Vector2.Left * num;
|
|
}
|
|
else
|
|
{
|
|
fighters[i].Velocity = Vector2.Right * num;
|
|
}
|
|
}
|
|
|
|
private IEnumerator ToastProj()
|
|
{
|
|
fighters[1].Velocity = Vector2.Zero;
|
|
fighters[1].Shake(30f, 2f);
|
|
Audio.PlaySound("snd_boost.wav");
|
|
fighters[1].anim.Play(anims[Animations.Attack2]);
|
|
for (float a = 0f; a < 10f; a += Main.deltaTime)
|
|
{
|
|
data[1].hyperArmor = 10f;
|
|
yield return null;
|
|
}
|
|
fighters[1].anim.Pause();
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
fighters[1].Modulate = Main.colorYellow;
|
|
for (float a = 0f; a < 10f; a += Main.deltaTime)
|
|
{
|
|
data[1].hyperArmor = 10f;
|
|
yield return null;
|
|
}
|
|
}
|
|
fighters[1].anim.Play();
|
|
CameraController.Shake(15f, 2f);
|
|
Audio.PlaySound("snd_rudebuster_hit.wav");
|
|
Node node = BattleDR.NewBullet(in shockWave, fighters[1].GlobalPosition + new Vector2(-30f, 0f), this);
|
|
Timer obj = new Timer
|
|
{
|
|
Autostart = true,
|
|
WaitTime = 5.0,
|
|
OneShot = true
|
|
};
|
|
Timer timer = obj;
|
|
node.AddChild(obj, forceReadableName: false, InternalMode.Disabled);
|
|
timer.Timeout += node.QueueFree;
|
|
for (float a = 0f; a < 15f; a += Main.deltaTime)
|
|
{
|
|
yield return null;
|
|
}
|
|
fighters[1].anim.Pause();
|
|
for (float a = 0f; a < 45f; a += Main.deltaTime)
|
|
{
|
|
yield return null;
|
|
}
|
|
fighters[1].anim.Play(anims[Animations.Idle]);
|
|
yield return null;
|
|
if (Main.RandomRange(0, 100) < 30)
|
|
{
|
|
aiTime = 40f;
|
|
}
|
|
else
|
|
{
|
|
aiTime = 20f;
|
|
}
|
|
}
|
|
|
|
private IEnumerator ToastPunch()
|
|
{
|
|
fighters[1].Velocity = Vector2.Zero;
|
|
Audio.PlaySound("motor_swing_down.wav");
|
|
fighters[1].anim.Play(anims[Animations.Attack1]);
|
|
if ((round > 1 || data[1].hp < 65f) && Main.RandomRange(0, 100) < ((round == 1) ? 50 : 70))
|
|
{
|
|
for (float a = 0f; a < 22f; a += Main.deltaTime)
|
|
{
|
|
yield return null;
|
|
}
|
|
fighters[1].anim.Play(anims[Animations.Attack2]);
|
|
Audio.PlaySound("motor_upper_2.wav", 1f, 0.9f);
|
|
yield return null;
|
|
}
|
|
while ((StringName)fighters[1].anim.CurrentAnimation != anims[Animations.Idle])
|
|
{
|
|
yield return null;
|
|
}
|
|
if (Main.RandomRange(0, 100) < 30)
|
|
{
|
|
aiTime = 60f;
|
|
}
|
|
else
|
|
{
|
|
aiTime = 20f;
|
|
}
|
|
}
|
|
|
|
private void EnemyAI()
|
|
{
|
|
float num = Mathf.Abs(fighters[1].GlobalPosition.X - fighters[0].GlobalPosition.X);
|
|
data[1].block = false;
|
|
switch (round)
|
|
{
|
|
case 1:
|
|
if (!EnemyBase(num) && num < 50f)
|
|
{
|
|
data[1].move = Coroutine.Start(ToastPunch(), this);
|
|
}
|
|
break;
|
|
case 2:
|
|
if (projTime > 45f || proj.Count >= 2)
|
|
{
|
|
blockTime = 10f;
|
|
}
|
|
if (!EnemyBase(num) && num < 50f)
|
|
{
|
|
data[1].move = Coroutine.Start(ToastPunch(), this);
|
|
}
|
|
break;
|
|
case 3:
|
|
if (projTime > 30f || proj.Count >= 2)
|
|
{
|
|
blockTime = 10f;
|
|
}
|
|
if (num > 100f && Engine.GetFramesDrawn() % 3 == 0 && aiTime <= 0f)
|
|
{
|
|
data[1].move = Coroutine.Start(ToastProj(), this);
|
|
}
|
|
else if (!EnemyBase(num) && num < 50f)
|
|
{
|
|
data[1].move = Coroutine.Start(ToastPunch(), this);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
private bool EnemyBase(float d)
|
|
{
|
|
if (combo > 2)
|
|
{
|
|
blockTime = 80f;
|
|
}
|
|
if (blockTime > 0f && data[1].hyperArmor <= 0f)
|
|
{
|
|
fighters[1].Velocity = Vector2.Zero;
|
|
fighters[1].anim.Play(anims[Animations.Block]);
|
|
data[1].block = true;
|
|
return true;
|
|
}
|
|
if (aiTime > 0f)
|
|
{
|
|
Move(fighters[1], Animations.Walk, 0.8f);
|
|
return true;
|
|
}
|
|
if (d > 50f)
|
|
{
|
|
Move(fighters[1], Animations.Walk, -1f);
|
|
if (Engine.GetFramesDrawn() % 3 == 0 && Main.RandomRange(0, 100) <= 2)
|
|
{
|
|
aiTime = Main.RandomRange(30, 60);
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private void Cooldowns()
|
|
{
|
|
if (blockTime > 0f)
|
|
{
|
|
blockTime -= Main.deltaTime;
|
|
}
|
|
if (aiTime > 0f)
|
|
{
|
|
aiTime -= Main.deltaTime;
|
|
}
|
|
if (comboTime > 0f)
|
|
{
|
|
comboTime -= Main.deltaTime;
|
|
}
|
|
else
|
|
{
|
|
combo = 0;
|
|
}
|
|
if (proj.Count > 0)
|
|
{
|
|
projTime += Main.deltaTime;
|
|
}
|
|
else
|
|
{
|
|
projTime = 0f;
|
|
}
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
if (data[i] != null)
|
|
{
|
|
if (data[i].blockHold > 0f && (StringName)data[i].entity.anim.CurrentAnimation != anims[Animations.Block])
|
|
{
|
|
data[i].blockHold -= Main.deltaTime * 0.05f;
|
|
}
|
|
else
|
|
{
|
|
data[i].blockHold = 0f;
|
|
}
|
|
if (data[i].stun > 0f)
|
|
{
|
|
data[i].stun -= Main.deltaTime;
|
|
}
|
|
if (data[i].knockback > 0f)
|
|
{
|
|
data[i].knockback -= Main.deltaTime;
|
|
}
|
|
if (data[i].hyperArmor > 0f)
|
|
{
|
|
data[i].armorTime += Main.deltaTime;
|
|
data[i].hyperArmor -= Main.deltaTime * Mathf.Max(1f, 0.5f * Mathf.Floor(data[i].armorTime / 30f));
|
|
}
|
|
if (data[i].armorBuildup > 0f)
|
|
{
|
|
data[i].armorBuildup -= Main.deltaTime * (float)((!(data[i].hyperArmor > 0f)) ? 1 : 2);
|
|
}
|
|
}
|
|
}
|
|
for (int num = buffers.Count - 1; num >= 0; num--)
|
|
{
|
|
if (buffers[num].time <= 0f)
|
|
{
|
|
buffers.RemoveAt(num);
|
|
}
|
|
else
|
|
{
|
|
buffers[num].time -= Main.deltaTime;
|
|
}
|
|
}
|
|
}
|
|
|
|
private IEnumerator Attack()
|
|
{
|
|
fighters[0].Velocity = Vector2.Zero;
|
|
bool cancombo = false;
|
|
if ((StringName)fighters[0].anim.CurrentAnimation != anims[Animations.Attack1])
|
|
{
|
|
Audio.PlaySound("motor_swing_down.wav");
|
|
fighters[0].anim.Play(anims[Animations.Attack1]);
|
|
cancombo = true;
|
|
}
|
|
else
|
|
{
|
|
Audio.PlaySound("motor_upper_2.wav");
|
|
fighters[0].anim.Play(anims[Animations.Attack2]);
|
|
}
|
|
for (float a = 0f; a < 18f; a += Main.deltaTime)
|
|
{
|
|
yield return null;
|
|
}
|
|
while ((StringName)fighters[0].anim.CurrentAnimation != anims[Animations.Idle])
|
|
{
|
|
if (cancombo && Input.IsActionJustPressed(Main.keys[4]))
|
|
{
|
|
data[0].move = Coroutine.Start(Attack(), this);
|
|
break;
|
|
}
|
|
yield return null;
|
|
}
|
|
}
|
|
|
|
private IEnumerator HealBell()
|
|
{
|
|
Player.instance.followers[0].anim.Play(anims[Animations.Heal]);
|
|
Audio.PlaySound("snd_spellcast_ch1.wav");
|
|
Node p = Main.Particle("HealBell", new Vector2(0f, -50f), 1, fighters[0]);
|
|
for (float a = 0f; a < 70f; a += Main.deltaTime)
|
|
{
|
|
yield return null;
|
|
}
|
|
Audio.PlaySound("snd_power.wav");
|
|
data[0].hp = Mathf.Min(data[0].hp + 35f, 100f);
|
|
BattleDR.ShowFloatingText(35.ToString(), fighters[0].GlobalPosition, Main.colorGreen);
|
|
fighters[0].Modulate = Main.colorGreen;
|
|
while (GodotObject.IsInstanceValid(p))
|
|
{
|
|
yield return null;
|
|
}
|
|
}
|
|
|
|
private void Move(Entity entity, Animations anim, float spd = 1f)
|
|
{
|
|
entity.Velocity = Vector2.Right * spd * entity.baseSpeed;
|
|
entity.anim.Play(anims[anim]);
|
|
}
|
|
|
|
private IEnumerator Hadouken()
|
|
{
|
|
Audio.PlaySound("snd_shotmid.wav");
|
|
fighters[0].Velocity = Vector2.Zero;
|
|
fighters[0].anim.Play(anims[Animations.Hadouken]);
|
|
MoveAhead moveAhead = (MoveAhead)BattleDR.NewBullet(in axisSphere, fighters[0].GlobalPosition + new Vector2(26f, -23f), Room.current);
|
|
moveAhead.speed = Vector2.Right * 1.3f;
|
|
Area2D child = moveAhead.GetChild<Area2D>(0);
|
|
child.CollisionLayer = 8u;
|
|
child.SetMeta(hitbox, new int[2] { 8, 35 });
|
|
proj.Add(moveAhead);
|
|
Timer obj = new Timer
|
|
{
|
|
WaitTime = 6.0,
|
|
Autostart = true,
|
|
OneShot = true
|
|
};
|
|
Timer timer = obj;
|
|
moveAhead.AddChild(obj, forceReadableName: false, InternalMode.Disabled);
|
|
timer.Timeout += moveAhead.QueueFree;
|
|
for (float a = 0f; a < 30f; a += Main.deltaTime)
|
|
{
|
|
yield return null;
|
|
}
|
|
}
|
|
|
|
private void Inputs()
|
|
{
|
|
for (int i = 0; i < Main.keys.Length; i++)
|
|
{
|
|
if (Input.IsActionJustPressed(Main.keys[i]))
|
|
{
|
|
buffers.Add(new Buffer
|
|
{
|
|
key = i,
|
|
time = 20f
|
|
});
|
|
}
|
|
}
|
|
if (buffers.Count >= 2)
|
|
{
|
|
List<Buffer> list = buffers;
|
|
if (list[list.Count - 1].key == 2)
|
|
{
|
|
List<Buffer> list2 = buffers;
|
|
if (list2[list2.Count - 2].key == 2)
|
|
{
|
|
data[0].move = Coroutine.Start(Dash(), this);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
if (buffers.Count >= 3)
|
|
{
|
|
List<Buffer> list3 = buffers;
|
|
if (list3[list3.Count - 1].key == 4)
|
|
{
|
|
List<Buffer> list4 = buffers;
|
|
if (list4[list4.Count - 2].key == 3)
|
|
{
|
|
List<Buffer> list5 = buffers;
|
|
if (list5[list5.Count - 3].key == 1)
|
|
{
|
|
if (tp >= 15)
|
|
{
|
|
tp -= 15;
|
|
data[0].move = Coroutine.Start(Hadouken(), this);
|
|
return;
|
|
}
|
|
buffers.Clear();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (Input.IsActionJustPressed(Main.keys[4]))
|
|
{
|
|
data[0].move = Coroutine.Start(Attack(), this);
|
|
return;
|
|
}
|
|
if (Input.IsActionJustPressed(Main.keys[6]) && (healing == null || healing.done) && tp >= 90)
|
|
{
|
|
healing = Coroutine.Start(HealBell(), this);
|
|
tp -= 90;
|
|
}
|
|
data[0].block = false;
|
|
if (Input.IsActionPressed(Main.keys[2]))
|
|
{
|
|
fighters[0].Velocity = Vector2.Left * fighters[0].baseSpeed;
|
|
fighters[0].anim.Play(anims[Animations.BackWalk]);
|
|
}
|
|
else if (Input.IsActionPressed(Main.keys[3]))
|
|
{
|
|
fighters[0].Velocity = Vector2.Right * fighters[0].baseSpeed;
|
|
fighters[0].anim.Play(anims[Animations.Walk]);
|
|
}
|
|
else if (Input.IsActionPressed(Main.keys[5]) || Input.IsActionPressed(Main.keys[1]))
|
|
{
|
|
fighters[0].anim.Play(anims[Animations.Block]);
|
|
fighters[0].Velocity = Vector2.Zero;
|
|
data[0].block = true;
|
|
}
|
|
else
|
|
{
|
|
fighters[0].anim.Play(anims[Animations.Idle]);
|
|
fighters[0].Velocity = Vector2.Zero;
|
|
}
|
|
}
|
|
|
|
private IEnumerator Dash()
|
|
{
|
|
Audio.PlaySound("leaf_dodge.wav");
|
|
fighters[0].Modulate = Main.colorGlow;
|
|
fighters[0].Velocity = Vector2.Left * fighters[0].baseSpeed * 3f;
|
|
fighters[0].anim.Play(anims[Animations.BackWalk]);
|
|
for (float a = 0f; a < 20f; a += Main.deltaTime)
|
|
{
|
|
yield return null;
|
|
}
|
|
}
|
|
|
|
private IEnumerator IntroStuff(bool start = false)
|
|
{
|
|
if (start)
|
|
{
|
|
data = new FigherData[2]
|
|
{
|
|
new FigherData
|
|
{
|
|
entity = fighters[0]
|
|
},
|
|
new FigherData
|
|
{
|
|
entity = fighters[1]
|
|
}
|
|
};
|
|
}
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
fighters[i].anim.Play(anims[Animations.Idle]);
|
|
}
|
|
roundAnim.Play("Round" + round);
|
|
AudioStreamPlayer sound = Audio.PlaySound("snd_boxing_round" + round + "_bc.wav");
|
|
yield return null;
|
|
while ((GodotObject.IsInstanceValid(sound) && sound.Playing) || data[1].hp < 100f)
|
|
{
|
|
for (int j = 0; j < 2; j++)
|
|
{
|
|
fighters[j].GlobalPosition = fighters[j].GlobalPosition.Lerp(fighters[j].startPos, Main.deltaTime * 0.1f);
|
|
}
|
|
if (data[1].hp < 100f)
|
|
{
|
|
data[1].hp += 1f;
|
|
}
|
|
yield return null;
|
|
}
|
|
data[1].hp = 100f;
|
|
roundAnim.Play("Fight");
|
|
sound = Audio.PlaySound("snd_boxing_fight_bc.wav");
|
|
yield return null;
|
|
while (sound.Playing)
|
|
{
|
|
yield return null;
|
|
}
|
|
for (int k = 0; k < 2; k++)
|
|
{
|
|
Audio.PlaySound("snd_bell_ch1.wav");
|
|
for (float a = 0f; a < 15f; a += Main.deltaTime)
|
|
{
|
|
yield return null;
|
|
}
|
|
}
|
|
Audio.ChangeMusic(music);
|
|
help.Visible = true;
|
|
if (round == 1)
|
|
{
|
|
help.Text = Texts.common[121].Replace("[VALUE]", 90.ToString()).Replace("@", "\n");
|
|
}
|
|
}
|
|
|
|
public void Start(bool setPos = true)
|
|
{
|
|
base.ProcessMode = ProcessModeEnum.Inherit;
|
|
active = true;
|
|
tp = 0;
|
|
round = 1;
|
|
if (setPos)
|
|
{
|
|
for (int i = 0; i < fighters.Length; i++)
|
|
{
|
|
fighters[i].startPos = fighters[i].GlobalPosition;
|
|
}
|
|
}
|
|
busy = Coroutine.Start(IntroStuff(start: true));
|
|
}
|
|
|
|
private void PlayerHit(Node other)
|
|
{
|
|
if (other.HasMeta(hitbox))
|
|
{
|
|
Damage(0, (int[])other.GetMeta(hitbox));
|
|
}
|
|
}
|
|
|
|
private void EnemyHit(Node other)
|
|
{
|
|
if (other.HasMeta(hitbox))
|
|
{
|
|
bool noTP = false;
|
|
if (other.GetParent() is MoveAhead moveAhead)
|
|
{
|
|
proj.Remove(moveAhead);
|
|
moveAhead.QueueFree();
|
|
noTP = true;
|
|
}
|
|
Damage(1, (int[])other.GetMeta(hitbox), noTP);
|
|
}
|
|
}
|
|
|
|
private void Damage(int id, int[] hitData, bool noTP = false)
|
|
{
|
|
Main.Particle("ShootHit", data[id].entity.GlobalPosition + new Vector2(Main.RandomRange(-10, 10), -25 + Main.RandomRange(-10, 10)), 1, null, localSpace: false);
|
|
if (data[id].block)
|
|
{
|
|
data[id].hp -= data[id].blockHold + 1f;
|
|
if (data[id].blockHold < 5f)
|
|
{
|
|
data[id].blockHold += 1f;
|
|
}
|
|
if (id == 1)
|
|
{
|
|
data[id].armorBuildup += hitData[1] * 5;
|
|
}
|
|
if (data[id].armorBuildup >= 100f)
|
|
{
|
|
data[id].hyperArmor += hitData[1];
|
|
data[id].entity.Modulate = Main.colorYellow;
|
|
}
|
|
else
|
|
{
|
|
data[id].entity.Modulate = Main.colorGlow;
|
|
}
|
|
if (id == 0 && !noTP)
|
|
{
|
|
tp = Mathf.Min(tp + 5 - (int)data[id].blockHold, 100);
|
|
}
|
|
Audio.PlaySound("snd_graze.wav");
|
|
}
|
|
else
|
|
{
|
|
data[id].hp -= (float)hitData[0] * ((data[id].hyperArmor > 0f) ? 0.5f : 1f);
|
|
if (id == 1)
|
|
{
|
|
combo++;
|
|
comboTime = 60f;
|
|
}
|
|
else
|
|
{
|
|
Audio.PlaySound("snd_hurt1.wav");
|
|
}
|
|
if (data[id].hyperArmor <= 0f)
|
|
{
|
|
if (data[id].armorBuildup >= 100f)
|
|
{
|
|
data[id].entity.Modulate = Main.colorYellow;
|
|
Audio.PlaySound("snd_justice_effect.wav");
|
|
data[id].armorBuildup += 60f;
|
|
data[id].hyperArmor += (float)hitData[1] * 1.5f;
|
|
if (id == 1 && !noTP)
|
|
{
|
|
tp = Mathf.Min(tp + 1, 100);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Audio.PlaySound("punch_ish_1.wav");
|
|
data[id].entity.Modulate = Main.colorGlow;
|
|
data[id].knockback = hitData[0] * 5;
|
|
Coroutine move = data[id].move;
|
|
if (move != null && !move.done)
|
|
{
|
|
Coroutine.Stop(data[id].move, now: true);
|
|
data[id].move = null;
|
|
}
|
|
if (id == 1)
|
|
{
|
|
data[id].armorBuildup += (float)hitData[1] * ((id == 0) ? 1.5f : 2f);
|
|
}
|
|
data[id].entity.Velocity = Vector2.Zero;
|
|
data[id].entity.anim.Play(anims[Animations.Hurt]);
|
|
if (id == 1 && !noTP)
|
|
{
|
|
tp = Mathf.Min(tp + Mathf.Min(hitData[1] / 10 * combo, 10), 100);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (id == 1 && !noTP)
|
|
{
|
|
tp = Mathf.Min(tp + 1, 100);
|
|
}
|
|
data[id].entity.Modulate = Main.colorYellow;
|
|
data[id].hyperArmor += 30f;
|
|
}
|
|
data[id].entity.Shake(10f, 2f);
|
|
}
|
|
if (data[id].hp <= 0f && (busy == null || busy.done))
|
|
{
|
|
if (id == 0)
|
|
{
|
|
fighters[0].anim.Play(anims[Animations.Hurt]);
|
|
Coroutine.Start(GameOver.DoGameOver(ChujinDWEvents.instance.nodes[8].GlobalPosition));
|
|
base.ProcessMode = ProcessModeEnum.Disabled;
|
|
busy = Coroutine.Start(Reset());
|
|
}
|
|
else
|
|
{
|
|
StopRoutines();
|
|
fighters[1].anim.Play(anims[Animations.Hurt]);
|
|
busy = Coroutine.Start(EndRound());
|
|
}
|
|
}
|
|
}
|
|
|
|
private void StopRoutines()
|
|
{
|
|
Coroutine.Stop(healing);
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
Coroutine.Stop(data[i].move);
|
|
}
|
|
}
|
|
|
|
private IEnumerator Reset()
|
|
{
|
|
for (float a = 0f; a < 30f; a += Main.deltaTime)
|
|
{
|
|
yield return null;
|
|
}
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
((CpuParticles2D)fighters[1].extras[i + 1]).Emitting = false;
|
|
}
|
|
StopRoutines();
|
|
for (int j = 0; j < 2; j++)
|
|
{
|
|
fighters[j].GlobalPosition = fighters[j].startPos;
|
|
fighters[j].anim.Play(anims[Animations.Idle]);
|
|
}
|
|
data = new FigherData[2]
|
|
{
|
|
new FigherData
|
|
{
|
|
entity = fighters[0]
|
|
},
|
|
new FigherData
|
|
{
|
|
entity = fighters[1]
|
|
}
|
|
};
|
|
round = 1;
|
|
tp = 0;
|
|
Party.UpdateAnim();
|
|
for (float a = 0f; a < 30f; a += Main.deltaTime)
|
|
{
|
|
yield return null;
|
|
}
|
|
}
|
|
|
|
private IEnumerator EndRound()
|
|
{
|
|
help.Visible = false;
|
|
CameraController.Shake(60f, 2f);
|
|
fighters[1].anim.Play(anims[Animations.Hurt]);
|
|
if (round == 1)
|
|
{
|
|
((CpuParticles2D)fighters[1].extras[1]).Emitting = true;
|
|
data[1].color = Main.colorWhite.Lerp(Main.colorRed, 0.3f);
|
|
}
|
|
else if (round == 2)
|
|
{
|
|
((CpuParticles2D)fighters[1].extras[2]).Emitting = true;
|
|
((CpuParticles2D)fighters[1].extras[3]).Emitting = true;
|
|
data[1].color = Main.colorWhite.Lerp(Main.colorRed, 0.6f);
|
|
}
|
|
round++;
|
|
Audio.PlaySound("snd_explosion.wav");
|
|
Engine.TimeScale = 0.5;
|
|
if (round > 3)
|
|
{
|
|
Audio.ChangeMusic((Audio.AudioBlock)null, 5f);
|
|
CameraController.Transition(Main.colorWhite, 100f);
|
|
}
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
data[i].knockback = 60f;
|
|
}
|
|
while (data[0].knockback > 0f)
|
|
{
|
|
for (int j = 0; j < 2; j++)
|
|
{
|
|
DoKnockback(j);
|
|
}
|
|
yield return null;
|
|
}
|
|
Engine.TimeScale = 1.0;
|
|
for (float a = 0f; a < 60f; a += Main.deltaTime)
|
|
{
|
|
yield return null;
|
|
}
|
|
if (round > 3)
|
|
{
|
|
active = false;
|
|
while (!CameraController.transitionRoutine.done)
|
|
{
|
|
yield return null;
|
|
}
|
|
yield return null;
|
|
for (int k = 0; k < 2; k++)
|
|
{
|
|
fighters[k].GlobalPosition = fighters[k].startPos;
|
|
fighters[k].Velocity = Vector2.Zero;
|
|
}
|
|
fighters[0].anim.Play(anims[Animations.Idle]);
|
|
UI.Visible = false;
|
|
EmitSignal(SignalName.OnEnd);
|
|
}
|
|
else
|
|
{
|
|
busy = Coroutine.Start(IntroStuff());
|
|
}
|
|
}
|
|
|
|
}
|