2025-05-13 19:22:01 +08:00

3097 lines
84 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using Godot;
using Godot.Bridge;
using Godot.Collections;
using Godot.NativeInterop;
[ScriptPath("res://Scripts/Battle/BattleDR.cs")]
public partial class BattleDR : Node2D
{
public enum State
{
Override,
Next,
PlayerTurn,
SelectSkill,
SelectItem,
SelectTarget,
DoSpells,
DoAttack,
DoEnemy,
EndTurn,
SelectAct
}
public enum Selected
{
Attack,
Magic,
Act,
Item,
Defend,
Spare
}
public enum EndState
{
None,
Special,
Spared,
Executed,
Apprehended,
Defeated
}
public enum EventBattle
{
None,
WardenTutorial
}
[Signal]
public delegate void PlayerTurnEndEventHandler();
[Signal]
public delegate void EnemyTurnEndEventHandler();
public struct StartStats
{
public int[] hp;
public int money;
public Items.IDs[] items;
public Audio.AudioBlock audioBlock;
public Entity.IDs[] enemies;
public bool bg;
public bool special;
public string mes;
public Color roomMod;
}
public static BattleDR current;
public State state;
private Sprite2D background;
public BulletBoards.SoulType defaultSoul;
public BulletBoards.SoulType currentMode;
public List<Battlers> allBattlers = new List<Battlers>();
public List<Battlers> enemies = new List<Battlers>();
public List<Battlers> party = new List<Battlers>();
private Enemy caller;
public Coroutine busy;
public Coroutine events;
public EventBattle eventBattle;
public List<Coroutine> fleeing = new List<Coroutine>();
private Vector3[] partyStartPos;
public Node2D shield;
public int turn;
public int currentActor;
public int lastMes;
public int mesCount;
public int prizeM;
public int prizeE;
public List<int> lastActor = new List<int>();
private bool doBG;
private bool grazed;
private bool firstMes;
private bool playerSelect;
public bool started;
public bool spareAble;
public bool specialWarning;
public bool forceEnd;
public CharacterBody2D soul;
private string battleMes;
public static float inputCD;
public int TP;
public int option;
public int maxOption;
public int tpPreview;
public int selectedLast;
public int forceMes = -1;
public int focusAtk = -1;
private List<int> lastTP = new List<int>();
private List<Items.IDs> consumeItems = new List<Items.IDs>();
public List<SoulBullet> shots = new List<SoulBullet>();
public Color bgColor = Main.colorWhite;
public int[] blockedCommands;
public HashSet<StringName> tempFlags = new HashSet<StringName>();
public List<Entity> toDelete = new List<Entity>();
private System.Collections.Generic.Dictionary<int, Party.IDs[]> actExtra = new System.Collections.Generic.Dictionary<int, Party.IDs[]>();
public List<string> diag;
public List<string> portraits;
private int[] possible;
public int[][] resultAmts = new int[6][]
{
new int[2],
new int[2] { 1, 0 },
new int[2] { 2, 0 },
new int[2] { 3, 0 },
new int[2] { 4, 0 },
new int[2] { 5, 0 }
};
private RichTextLabel currentDiagText;
public Battlers currentlyActing;
public float iFrames;
public float grazeCD;
public BulletBoards activeBoard;
public static EndState lastResult;
private AudioStream owMusic;
public static StartStats? reloadStats;
private static readonly AudioStream defaultBTheme = GD.Load<AudioStream>("res://Audio/Music/rudebusteryellow.wav");
private const int sort = 2000;
private const int introTime = 20;
private const int defendTP = 16;
private const int grazeTP = 3;
private const int maxShoot = 5;
private const int defaultIframe = 40;
private static System.Collections.Generic.Dictionary<Entity.IDs, string[]> blurbText;
public static System.Collections.Generic.Dictionary<Entity.IDs, Battlers> enemyData;
public static readonly Vector2[][] partyPos = new Vector2[5][]
{
new Vector2[1]
{
new Vector2(-100f, 0f)
},
new Vector2[2]
{
new Vector2(-86f, -34f),
new Vector2(-103f, 18f)
},
new Vector2[3]
{
new Vector2(-97f, -68f),
new Vector2(-86f, -24f),
new Vector2(-103f, 18f)
},
new Vector2[4]
{
new Vector2(-97f, -68f),
new Vector2(-74f, -37f),
new Vector2(-101f, -13f),
new Vector2(-83f, 15f)
},
new Vector2[5]
{
new Vector2(-99f, -76f),
new Vector2(-71f, -47f),
new Vector2(-108f, -27f),
new Vector2(-73f, -5f),
new Vector2(-103f, 18f)
}
};
private const float textBarLength = 15f;
private const float fleeTime = 7f;
private const float boardSpeed = 20f;
public int lastBoard;
private StringName lastAttack;
private static readonly List<StringName> enAnim = new List<StringName> { "Idle", "Happy", "Sad", "Weak" };
private Color soulColor;
private float shootCD;
private const float soulSpeed = 55f;
private const float defaultShootCD = 10f;
private static readonly PackedScene soulBullet = GD.Load<PackedScene>("res://Objects/Bullets/SoulBullet.tscn");
public const float damageRand = 0.1f;
private List<State> extended = new List<State>
{
State.SelectSkill,
State.SelectAct,
State.SelectItem
};
public static void LoadData(bool reload = false)
{
if (enemyData == null || reload)
{
enemyData = new System.Collections.Generic.Dictionary<Entity.IDs, Battlers>();
blurbText = new System.Collections.Generic.Dictionary<Entity.IDs, string[]>();
string[] array = FileAccess.Open(Texts.textFolder + "Blurbs.txt", FileAccess.ModeFlags.Read).GetAsText(skipCr: true).Split('\n');
BattleData battleData = GD.Load<BattleData>("res://Data/Battlers.tres");
for (int i = 0; i < battleData.enemies.Length; i++)
{
Entity.IDs key = (Entity.IDs)Enum.Parse(typeof(Entity.IDs), battleData.enemies[i].ResourceName);
enemyData.Add(key, battleData.enemies[i]);
for (int j = 0; j < array.Length; j++)
{
if (array[j] == "@" + battleData.enemies[i].ResourceName)
{
List<string> list = new List<string>();
for (int k = j + 1; k < array.Length && array[k].Length >= 3; k++)
{
list.Add(array[k]);
}
blurbText.Add(key, list.ToArray());
}
}
}
}
if (Texts.battleMes == null || Texts.battleMes.Count < 1 || reload)
{
Texts.SetBattleMes();
}
}
public static IEnumerator IntroNoise()
{
Audio.PlaySound("snd_tensionhorn_ch1.wav");
for (float a = 0f; a < 17f; a += Main.deltaTime)
{
yield return null;
}
Audio.PlaySound("snd_tensionhorn_ch1.wav", 1f, 1.1f);
for (float a = 0f; a < 23f; a += Main.deltaTime)
{
yield return null;
}
}
public static IEnumerator StartBattle(Enemy caller, bool useOWBG = false, Entity.IDs[] enemies = null, List<Entity> enemyEntities = null, string battleMes = null, Audio.AudioBlock music = null, bool quickIntro = false)
{
GameOver.repeatable = Main.inEvent != null;
if (Acts.instance == null)
{
Acts.instance = new Acts();
}
DWMenu.instance.battleText.Text = "";
DWMenu.instance.mainBox.Visible = false;
SaveFile.current.values[6]++;
lastResult = EndState.None;
LoadData();
DWMenu.instance.soulHitbox.AddException(DWMenu.instance.soulGrazebox);
Player.instance.canInput = false;
Player.instance.StopMoving();
CameraController.instance.AddChild(current = new BattleDR
{
Name = "Battle",
ZIndex = 1200
}, forceReadableName: false, InternalMode.Disabled);
if (caller != null)
{
caller.currentAnim = Entity.Animations.Hurt;
if (GodotObject.IsInstanceValid(caller.emoticonObj))
{
caller.emoticonObj.Free();
}
}
yield return null;
Room.current.ProcessMode = ProcessModeEnum.Disabled;
current.battleMes = battleMes;
if (DWMenu.instance.soulGrazebox != null)
{
DWMenu.instance.soulGrazebox.AreaEntered += current.Graze;
}
if (caller != null && !quickIntro)
{
current.caller = caller;
Coroutine i = Coroutine.Start(IntroNoise());
while (!i.done)
{
yield return null;
}
}
if (Main.inEvent == null)
{
current.owMusic = Audio.music.Stream;
}
Audio.ChangeMusic((Audio.AudioBlock)null, 0.5f);
current.doBG = !useOWBG;
Room.UpdateEntityList();
foreach (Entity entity3 in Room.current.entities)
{
Main.SetActive(entity3, state: false);
}
Player.SetActive(state: false);
current.partyStartPos = new Vector3[SaveFile.current.activeParty.Count];
if (!useOWBG)
{
current.background = new Sprite2D();
}
List<Vector2> pos = new List<Vector2>();
for (int j = 0; j < SaveFile.current.activeParty.Count; j++)
{
current.allBattlers.Add(Party.party[SaveFile.current.activeParty[j]]);
Entity entity = GD.Load<PackedScene>("res://Objects/Characters/" + Party.party[SaveFile.current.activeParty[j]].id.ToString() + ".tscn").Instantiate<Entity>(PackedScene.GenEditState.Disabled);
if (reloadStats.HasValue)
{
List<Battlers> list = current.allBattlers;
list[list.Count - 1].HP = reloadStats.Value.hp[j];
}
List<Battlers> list2 = current.allBattlers;
list2[list2.Count - 1].entity = entity;
List<Battlers> list3 = current.allBattlers;
list3[list3.Count - 1].id = entity.id;
List<Battlers> list4 = current.allBattlers;
list4[list4.Count - 1].posID = j;
List<Battlers> list5 = current.allBattlers;
list5[list5.Count - 1].selectedAction = null;
List<Battlers> list6 = current.allBattlers;
list6[list6.Count - 1].atkMod = null;
List<Battlers> list7 = current.allBattlers;
list7[list7.Count - 1].defMod = null;
current.AddChild(entity, forceReadableName: false, InternalMode.Disabled);
entity.trigger.ProcessMode = ProcessModeEnum.Disabled;
entity.direction = Entity.Direction.West;
entity.animMod = Entity.AnimMods.DW;
List<Battlers> list8 = current.allBattlers;
entity.battleData = list8[list8.Count - 1];
entity.CollisionLayer = 0u;
entity.CollisionMask = 0u;
entity.UpdateAnim(force: true);
List<Battlers> list9 = current.party;
List<Battlers> list10 = current.allBattlers;
list9.Add(list10[list10.Count - 1]);
entity.GlobalPosition = ((j == 0) ? Player.instance.GlobalPosition : Player.instance.followers[j - 1].GlobalPosition);
if (j == 0)
{
List<Battlers> list11 = current.allBattlers;
list11[list11.Count - 1].oEntity = Player.instance;
}
else
{
List<Battlers> list12 = current.allBattlers;
list12[list12.Count - 1].oEntity = Player.instance.followers[j - 1];
}
pos.Add(entity.Position);
entity.ZIndex = 2000 + j;
entity.doTrail = true;
DWMenu.instance.partyHUDs[j].battleStuff.Visible = true;
}
bool hasCriminal = false;
for (int k = 0; k < enemies.Length; k++)
{
Battlers battlers = (Battlers)enemyData[enemies[k]].Duplicate();
Vector2 globalPosition = current.GlobalPosition + new Vector2(200f, 0f);
if (enemyEntities != null)
{
for (int l = 0; l < enemyEntities.Count && l < enemies.Length; l++)
{
globalPosition = enemyEntities[l].GlobalPosition;
}
}
Entity entity2;
current.AddChild(entity2 = GD.Load<PackedScene>("res://Objects/Characters/" + enemies[k].ToString() + ".tscn").Instantiate<Entity>(PackedScene.GenEditState.Disabled), forceReadableName: false, InternalMode.Disabled);
battlers.entity = entity2;
battlers.id = enemies[k];
if (entity2.trigger != null)
{
entity2.trigger.ProcessMode = ProcessModeEnum.Disabled;
}
entity2.direction = Entity.Direction.East;
current.enemies.Add(battlers);
current.allBattlers.Add(battlers);
List<Battlers> list13 = current.allBattlers;
entity2.battleData = list13[list13.Count - 1];
entity2.CollisionLayer = 0u;
entity2.CollisionMask = 0u;
battlers.posID = k;
if (entity2.anim != null)
{
Array<Array<Variant>> animOverrides = entity2.battleData.animOverrides;
if (animOverrides != null && animOverrides.Count > 0)
{
entity2.replaceAnim.AddRange(entity2.battleData.animOverrides);
}
entity2.anim.Play("Idle");
}
entity2.GlobalPosition = globalPosition;
pos.Add(entity2.Position);
battlers.enemy = true;
entity2.ZIndex = 2000 + k;
List<Battlers> list14 = current.enemies;
if (list14[list14.Count - 1].isOutlaw)
{
List<Battlers> list15 = current.enemies;
if (list15[list15.Count - 1].id != Entity.IDs.Warden)
{
hasCriminal = true;
}
}
}
DWMenu.instance.tpVar = 0;
Party.UpdateHUD();
DWMenu.instance.Visible = true;
DWMenu.instance.showHP = -200f;
DWMenu.instance.battleCover.Visible = true;
current.soul = DWMenu.instance.soulBody;
current.soul.Visible = false;
for (float a = 0f; a <= 21f; a += Main.deltaTime)
{
int m = 0;
int num = 0;
int num2 = 0;
for (; m < current.allBattlers.Count; m++)
{
Vector2 vector;
if (current.allBattlers[m].enemy)
{
vector = new Vector2(0f - partyPos[current.enemies.Count - 1][num2].X, partyPos[current.enemies.Count - 1][num2].Y) + Vector2.Down * ((current.enemies.Count == 1) ? (-20) : 16) + current.allBattlers[m].positionOffset;
if (enemies.Length == 2)
{
vector += Vector2.Up * 16f;
}
current.allBattlers[m].startPos = vector;
num2++;
}
else
{
if (a == 0f)
{
current.allBattlers[m].entity.currentAnim = Entity.Animations.BattleStart;
}
vector = partyPos[SaveFile.current.activeParty.Count - 1][num];
num++;
}
current.allBattlers[m].entity.Position = pos[m].Lerp(vector, Mathf.Min(a / 20f, 1f));
}
yield return null;
}
if (music == null)
{
Audio.ChangeMusic(defaultBTheme);
}
else
{
Audio.ChangeMusic(music, 0.5f);
}
Audio.PlaySound("snd_weaponpull.wav");
for (int n = 0; n < current.allBattlers.Count; n++)
{
current.allBattlers[n].entity.doTrail = false;
}
CameraController.Transition(Main.colorClearB, 15f);
if (hasCriminal)
{
current.defaultSoul = BulletBoards.SoulType.Shoot;
Coroutine i = Coroutine.Start(ShootSoulChangeAnim());
while (!i.done)
{
yield return null;
}
}
else
{
current.soul.RotationDegrees = 0f;
}
current.started = true;
current.state = State.Next;
GameOver.instance = null;
current.soul.TopLevel = false;
yield return null;
if (!reloadStats.HasValue)
{
reloadStats = new StartStats
{
items = SaveFile.current.dwItems.ToArray(),
hp = new int[SaveFile.current.activeParty.Count],
money = SaveFile.current.dollars,
enemies = enemies,
audioBlock = music,
bg = useOWBG,
special = (lastResult == EndState.Special),
mes = battleMes,
roomMod = Room.current.Modulate
};
for (int num3 = 0; num3 < SaveFile.current.activeParty.Count; num3++)
{
reloadStats.Value.hp[num3] = Party.party[SaveFile.current.activeParty[num3]].HP;
}
}
else
{
SaveFile.current.dwItems = new List<Items.IDs>(reloadStats.Value.items);
SaveFile.current.dollars = reloadStats.Value.money;
Room.current.Modulate = reloadStats.Value.roomMod;
for (int num4 = 0; num4 < SaveFile.current.activeParty.Count; num4++)
{
Party.party[SaveFile.current.activeParty[num4]].HP = reloadStats.Value.hp[num4];
}
if (reloadStats.Value.special)
{
lastResult = EndState.Special;
}
Party.UpdateHUD();
}
}
private static IEnumerator ShootSoulChangeAnim()
{
current.soul.RotationDegrees = 0f;
current.soul.GlobalPosition = current.party[0].entity.GlobalPosition + Vector2.Up * 16f;
float a;
for (a = 0f; a < 20f; a += Main.deltaTime)
{
yield return null;
}
current.soul.Visible = true;
Main.Particle("SoulSplit", Vector2.Up * 16f, 1, current.party[0].entity);
Audio.PlaySound("snd_great_shine.ogg");
for (a = 0f; a < 40f; a += Main.deltaTime)
{
current.bgColor = Main.colorWhite.Lerp(Main.colorDark, a / 30f);
yield return null;
}
Audio.PlaySound("snd_spearappear_ch1.wav");
a = 0f;
for (float b = 40f; a <= b + 1f; a += Main.deltaTime)
{
current.soul.Rotation = Mathf.LerpAngle(0f, Mathf.DegToRad(-90f), Mathf.Min(a / b, 1f));
yield return null;
}
for (float b = 0f; b < 20f; b += Main.deltaTime)
{
yield return null;
}
Main.Particle("SoulSplit", Vector2.Up * 16f, 1, current.party[0].entity);
Audio.PlaySound("snd_great_shine.ogg");
for (float b = 0f; b < 40f; b += Main.deltaTime)
{
current.bgColor = Main.colorDark.Lerp(Main.colorWhite, b / 30f);
yield return null;
}
}
private void ReturnToPrevious()
{
if (lastActor.Count <= 0)
{
return;
}
List<int> list = lastActor;
currentActor = list[list.Count - 1];
List<int> list2 = lastTP;
TP = list2[list2.Count - 1];
lastTP.RemoveAt(lastTP.Count - 1);
List<Items.IDs> list3 = consumeItems;
if (list3[list3.Count - 1] != Items.IDs.None)
{
List<Items.IDs> dwItems = SaveFile.current.dwItems;
List<Items.IDs> list4 = consumeItems;
dwItems.Add(list4[list4.Count - 1]);
}
consumeItems.RemoveAt(consumeItems.Count - 1);
if (actExtra.Count > 0)
{
if (actExtra.ContainsKey(currentActor))
{
for (int i = 0; i < actExtra[currentActor].Length; i++)
{
Party.party[(int)actExtra[currentActor][i]].acted = false;
Party.party[(int)actExtra[currentActor][i]].entity.currentAnim = Entity.Animations.BattleIdle;
}
}
actExtra.Remove(currentActor);
}
allBattlers[currentActor].selectedAction = null;
allBattlers[currentActor].entity.currentAnim = Entity.Animations.BattleIdle;
lastActor.RemoveAt(lastActor.Count - 1);
option = 0;
UpdateMenu();
}
private void UpdateDiag()
{
List<string> list = diag;
if (list == null || list.Count <= 0)
{
return;
}
List<string> list2 = portraits;
if (list2 != null && list2.Count > 0)
{
currentDiagText = DWMenu.instance.battleText2;
DWMenu.instance.battlePortrait.Visible = portraits[0] != null;
DWMenu.instance.battlePortrait.Play(portraits[0]);
if (!TextSystem.bleepPlayer.Playing)
{
float volume = 1f;
TextSystem.AssignBleep(portraits[0], ref volume);
TextSystem.bleepPlayer.Play();
}
}
else
{
currentDiagText = DWMenu.instance.battleText;
}
currentDiagText.Visible = true;
Party.ShowBattleCommands(-1);
currentDiagText.Text = diag[0];
if (currentDiagText.VisibleRatio < 1f)
{
currentDiagText.VisibleCharacters++;
}
else
{
DWMenu.instance.battlePortrait.Stop();
if (TextSystem.bleepPlayer.Playing)
{
TextSystem.bleepPlayer.Stop();
}
}
if (inputCD <= 0f && Input.IsActionJustPressed(Main.keys[4]))
{
AdvanceDiag();
}
}
public void AdvanceDiag(bool skipskip = false)
{
List<string> list = diag;
if (list == null || list.Count <= 0)
{
return;
}
if (TextSystem.bleepPlayer.Playing)
{
TextSystem.bleepPlayer.Stop();
}
if (currentDiagText.VisibleRatio < 1f && !skipskip)
{
currentDiagText.VisibleRatio = 1f;
return;
}
inputCD = 5f;
diag.RemoveAt(0);
TextSystem.bleepPlayer.PitchScale = 1f;
TextSystem.bleepPlayer.VolumeDb = Mathf.LinearToDb(1f);
List<string> list2 = portraits;
if (list2 != null && list2.Count > 0)
{
DWMenu.instance.battlePortrait.Visible = false;
currentDiagText.VisibleRatio = 0f;
currentDiagText.Visible = false;
portraits.RemoveAt(0);
}
else
{
currentDiagText.VisibleRatio = 0f;
}
}
public static void Abort(bool nullify = true)
{
if (GodotObject.IsInstanceValid(current.activeBoard))
{
current.activeBoard.QueueFree();
}
DWMenu.instance.bulletBoard.Visible = false;
current.QueueFree();
if (nullify)
{
current = null;
}
}
public override void _Process(double delta)
{
if (grazeCD > 0f)
{
grazeCD -= Main.deltaTime;
}
if (CameraController.instance.shakeTime > 0f)
{
base.Position = Vector2.One * Main.RandomRange(0f - CameraController.instance.shakeIntensity, CameraController.instance.shakeIntensity);
}
else
{
base.Position = Vector2.Zero;
}
UpdateTP(ref DWMenu.instance.tpVar, in TP, in tpPreview, 1);
if (inputCD > 0f)
{
inputCD -= Main.deltaTime;
}
UpdateDiag();
DWMenu.instance.grazeIndicator.SelfModulate = DWMenu.instance.grazeIndicator.SelfModulate.Lerp(Main.colorClear, 0.1f);
if (doBG)
{
DWMenu.instance.battleBG.Modulate = DWMenu.instance.battleBG.Modulate.Lerp(bgColor, 0.1f);
}
Coroutine coroutine = busy;
if (coroutine == null || coroutine.done)
{
Coroutine coroutine2 = events;
if (coroutine2 == null || coroutine2.done)
{
switch (state)
{
case State.Next:
{
if (eventBattle == EventBattle.WardenTutorial && TP >= 40 && !tempFlags.Contains("TPMes"))
{
tempFlags.Add("TPMes");
busy = Coroutine.Start(Acts.instance.WardenTutorial(1));
break;
}
spareAble = false;
for (int j = 0; j < enemies.Count; j++)
{
if (enemies[j].CanSpare())
{
spareAble = true;
break;
}
}
for (int k = 0; k < party.Count; k++)
{
if (party[k].CanAct() && party[k].selectedAction == null)
{
currentActor = k;
state = State.PlayerTurn;
option = 0;
maxOption = 5;
DWMenu.instance.partyHUDs[k].UpdateOpt(0);
UpdateMenu();
break;
}
soul.Visible = false;
ResetEnemyHighlight();
state = State.DoSpells;
}
break;
}
case State.PlayerTurn:
if (DWMenu.instance.battleText.VisibleRatio < 1f)
{
DWMenu.instance.battleText.VisibleCharacters++;
}
Party.ShowBattleCommands(currentActor);
if (Input.IsActionJustPressed(Main.keys[2]))
{
ChangeOption(-1);
if (option < 0)
{
option = maxOption - 1;
}
DWMenu.instance.partyHUDs[currentActor].UpdateOpt(option);
}
else if (Input.IsActionJustPressed(Main.keys[3]))
{
ChangeOption(1);
DWMenu.instance.partyHUDs[currentActor].UpdateOpt(option);
}
else if (Input.IsActionJustPressed(Main.keys[4]))
{
selectedLast = option;
int[] array = blockedCommands;
if (array != null && array.Contains(option))
{
Audio.PlaySound(Audio.commonSounds[1]);
break;
}
switch (option)
{
case 0:
allBattlers[currentActor].selectedAction = new int[2];
state = State.SelectTarget;
option = 0;
maxOption = enemies.Count;
playerSelect = false;
UpdateMenu();
Audio.PlaySound(Audio.commonSounds[2]);
break;
case 1:
if (allBattlers[currentActor].doMagicMenu)
{
allBattlers[currentActor].selectedAction = new int[3] { 1, 0, 0 };
state = State.SelectSkill;
}
else
{
allBattlers[currentActor].selectedAction = new int[3] { 2, 0, 0 };
state = State.SelectTarget;
}
option = 0;
UpdateMenu();
Audio.PlaySound(Audio.commonSounds[2]);
break;
case 2:
if (SaveFile.current.dwItems.Count > 0)
{
Audio.PlaySound(Audio.commonSounds[2]);
allBattlers[currentActor].selectedAction = new int[3] { 3, 0, 0 };
state = State.SelectItem;
option = 0;
UpdateMenu();
}
else
{
Audio.PlaySound(Audio.commonSounds[1]);
}
break;
case 3:
allBattlers[currentActor].selectedAction = new int[3] { 2, 0, 12 };
state = State.SelectTarget;
option = 0;
playerSelect = false;
UpdateMenu();
Audio.PlaySound(Audio.commonSounds[2]);
break;
case 4:
allBattlers[currentActor].entity.currentAnim = Entity.Animations.Defend;
allBattlers[currentActor].selectedAction = new int[1] { 4 };
option = 0;
lastActor.Add(currentActor);
consumeItems.Add(Items.IDs.None);
currentActor = -1;
lastTP.Add(TP);
TP = Mathf.Clamp(TP + 16, 0, 100);
state = State.Next;
UpdateMenu();
Audio.PlaySound(Audio.commonSounds[2]);
break;
}
}
else if (Input.IsActionJustPressed(Main.keys[5]))
{
ReturnToPrevious();
}
break;
case State.SelectSkill:
case State.SelectItem:
case State.SelectAct:
Party.ShowBattleCommands(currentActor);
if (Input.IsActionJustPressed(Main.keys[0]))
{
ChangeOption(-2);
UpdateMenu(1);
}
else if (Input.IsActionJustPressed(Main.keys[1]))
{
ChangeOption(2);
UpdateMenu(1);
}
else if (Input.IsActionJustPressed(Main.keys[2]))
{
ChangeOption(-1);
UpdateMenu(1);
}
else if (Input.IsActionJustPressed(Main.keys[3]))
{
ChangeOption(1);
UpdateMenu(1);
}
else if (Input.IsActionJustPressed(Main.keys[4]))
{
if (state == State.SelectItem)
{
allBattlers[currentActor].selectedAction[2] = (int)SaveFile.current.dwItems[option];
playerSelect = UseOnParty(currentActor);
Items.IDs ds2 = SaveFile.current.dwItems[option];
if (Texts.items[ds2].instantUse)
{
allBattlers[currentActor].selectedAction[1] = currentActor;
allBattlers[currentActor].entity.currentAnim = Entity.Animations.ItemReady;
lastActor.Add(currentActor);
SaveFile.current.dwItems.Remove(ds2);
consumeItems.Add(ds2);
currentActor = -1;
lastTP.Add(TP);
state = State.Next;
UpdateMenu();
}
else
{
option = 0;
state = State.SelectTarget;
UpdateMenu((!Texts.items[ds2].useOnEnemy) ? 2 : 0);
}
Audio.PlaySound(Audio.commonSounds[2]);
break;
}
Acts.IDs ds3 = (Acts.IDs)possible[option];
if (TP >= Texts.skills[ds3].TP)
{
if (state == State.SelectAct || Texts.skills[ds3].skipSelection)
{
if (ds3 == Acts.IDs.Check)
{
busy = Acts.DoActRoutine("Check", enemies[allBattlers[currentActor].selectedAction[1]]);
Coroutine coroutine3 = busy;
coroutine3.onEnd = (Action)Delegate.Combine(coroutine3.onEnd, new Action(CancelEnemySelect));
break;
}
lastActor.Add(currentActor);
consumeItems.Add(Items.IDs.None);
allBattlers[currentActor].selectedAction[2] = possible[option];
if (allBattlers[currentActor].selectedAction[2] == 3)
{
allBattlers[currentActor].entity.anim.Play("Execution_Ready");
}
else
{
allBattlers[currentActor].entity.currentAnim = ((state == State.SelectItem) ? Entity.Animations.ItemReady : ((state == State.SelectAct) ? Entity.Animations.ActReady : Entity.Animations.SkillReady));
}
if (state == State.SelectAct)
{
List<Party.IDs> useTurns = Texts.skills[(Acts.IDs)allBattlers[currentActor].selectedAction[2]].useTurns;
if (useTurns != null && useTurns.Count > 0)
{
actExtra.Add(currentActor, Texts.skills[(Acts.IDs)allBattlers[currentActor].selectedAction[2]].useTurns.ToArray());
for (int l = 0; l < Texts.skills[(Acts.IDs)allBattlers[currentActor].selectedAction[2]].useTurns.Count; l++)
{
Party.party[(int)Texts.skills[(Acts.IDs)allBattlers[currentActor].selectedAction[2]].useTurns[l]].acted = true;
Party.party[(int)Texts.skills[(Acts.IDs)allBattlers[currentActor].selectedAction[2]].useTurns[l]].entity.currentAnim = Entity.Animations.ActReady;
}
}
}
currentActor = -1;
lastTP.Add(TP);
TP = Mathf.Clamp(TP - Texts.skills[ds3].TP, 0, 100);
state = State.Next;
UpdateMenu();
}
else
{
allBattlers[currentActor].selectedAction[2] = possible[option];
option = 0;
playerSelect = UseOnParty(currentActor);
state = State.SelectTarget;
UpdateMenu(Texts.skills[ds3].useOnParty ? 2 : 0);
}
Audio.PlaySound(Audio.commonSounds[2]);
}
else
{
Audio.PlaySound(Audio.commonSounds[1]);
}
}
else if (Input.IsActionJustPressed(Main.keys[5]))
{
CancelEnemySelect();
Audio.PlaySound(Audio.commonSounds[2]);
}
break;
case State.SelectTarget:
Party.ShowBattleCommands(currentActor);
if (!playerSelect)
{
for (int i = 0; i < enemies.Count; i++)
{
if (i == option)
{
enemies[i].entity.Modulate = Main.colorWhite.Lerp(Main.colorDark, Mathf.Abs(Mathf.Sin(Mathf.DegToRad(0.15f * (float)Time.GetTicksMsec()))));
}
else
{
enemies[i].entity.Modulate = Main.colorWhite;
}
}
}
if (Input.IsActionJustPressed(Main.keys[0]) || Input.IsActionJustPressed(Main.keys[2]))
{
ChangeOption(-1);
UpdateMenu(1);
}
else if (Input.IsActionJustPressed(Main.keys[1]) || Input.IsActionJustPressed(Main.keys[3]))
{
ChangeOption(1);
UpdateMenu(1);
}
else if (Input.IsActionJustPressed(Main.keys[4]))
{
if (allBattlers[currentActor].selectedAction[0] == 2 && allBattlers[currentActor].selectedAction[2] != 12)
{
allBattlers[currentActor].selectedAction[1] = option;
state = State.SelectAct;
option = 0;
UpdateMenu();
}
else
{
lastTP.Add(TP);
if (allBattlers[currentActor].selectedAction[0] == 0)
{
allBattlers[currentActor].selectedAction[1] = option;
allBattlers[currentActor].entity.currentAnim = Entity.Animations.AttackReady;
allBattlers[currentActor].entity.UpdateAnim(force: true);
allBattlers[currentActor].entity.anim.Stop();
}
else
{
Acts.IDs ds = (Acts.IDs)allBattlers[currentActor].selectedAction[2];
allBattlers[currentActor].selectedAction[1] = option;
if (allBattlers[currentActor].selectedAction[0] != 3)
{
TP = Mathf.Clamp(TP - Texts.skills[ds].TP, 0, 100);
}
if (allBattlers[currentActor].selectedAction[2] == 3)
{
allBattlers[currentActor].entity.anim.Play("Execution_Ready");
}
else if (allBattlers[currentActor].selectedAction[0] == 3)
{
allBattlers[currentActor].entity.currentAnim = Entity.Animations.ItemReady;
}
else if (Texts.skills[ds].spAction || ds == Acts.IDs.Spare)
{
allBattlers[currentActor].entity.currentAnim = Entity.Animations.ActReady;
}
else
{
allBattlers[currentActor].entity.currentAnim = Entity.Animations.SkillReady;
}
}
if (allBattlers[currentActor].selectedAction[0] == 3)
{
Items.IDs item = (Items.IDs)allBattlers[currentActor].selectedAction[2];
consumeItems.Add(item);
SaveFile.current.dwItems.Remove(item);
}
else
{
consumeItems.Add(Items.IDs.None);
}
lastActor.Add(currentActor);
currentActor = -1;
state = State.Next;
UpdateMenu();
}
Audio.PlaySound(Audio.commonSounds[2]);
}
else if (Input.IsActionJustPressed(Main.keys[5]))
{
CancelEnemySelect();
Audio.PlaySound(Audio.commonSounds[2]);
}
break;
case State.DoSpells:
busy = Coroutine.Start(DoSpells());
break;
case State.DoAttack:
busy = Coroutine.Start(DoAttack());
break;
case State.DoEnemy:
busy = Coroutine.Start(DoEnemy());
break;
case State.EndTurn:
busy = Coroutine.Start(AdvanceTurn());
break;
}
return;
}
}
Party.ShowBattleCommands(-1);
}
public static bool DoingAction()
{
if (current != null)
{
if (current.state != State.DoSpells && current.state != State.DoAttack && current.state != State.DoEnemy)
{
return current.state == State.EndTurn;
}
return true;
}
return false;
}
private void CancelEnemySelect()
{
state = State.PlayerTurn;
option = selectedLast;
maxOption = 5;
allBattlers[currentActor].selectedAction = null;
ResetEnemyHighlight();
UpdateMenu();
}
private string GetTextBar(float amt, Color? color = null)
{
Color valueOrDefault = color.GetValueOrDefault();
if (!color.HasValue)
{
valueOrDefault = new Color(0f, 1f, 0f);
color = valueOrDefault;
}
string text = color.Value.ToHtml(includeAlpha: false);
string text2 = "#870900";
amt *= 15f;
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; (float)i < 15f; i++)
{
stringBuilder.Append("[img color=" + (((float)i < amt) ? text : text2) + "]res://Sprites/Menus/Menu Sprites/HPBar3.tres[/img]");
}
return stringBuilder.ToString();
}
private int[] GetPossibleActs(int id = -1)
{
if (id == -1)
{
id = currentActor;
}
List<int> list = new List<int>();
for (int i = 0; i < party[id].acts.Count; i++)
{
if (CanUseAct(party[id].acts[i]))
{
list.Add((int)party[id].acts[i]);
}
}
return list.ToArray();
}
private bool CanUseAct(Acts.IDs id)
{
List<Items.IDs> needEquip = Texts.skills[id].needEquip;
if (needEquip != null && needEquip.Count > 0 && !party[currentActor].HasEquip(Texts.skills[id].needEquip.ToArray()))
{
return false;
}
if ((Texts.skills[id].needFlags == null || SaveFile.HasFlags(Texts.skills[id].needFlags)) && (Texts.skills[id].neededMembers == null || Party.HasMembers(Texts.skills[id].neededMembers, checkAlive: true)) && (!Texts.skills[id].onlyOnExecutable || enemies.FirstOrDefault((Battlers x) => x.isOutlaw) != null))
{
if (Texts.skills[id].spAction)
{
return enemies.FirstOrDefault((Battlers x) => x.partyAction.Count > 1 || x.acts.Count > 0) != null;
}
return true;
}
return false;
}
public EndState GetLastResult()
{
return (EndState)resultAmts.OrderByDescending((int[] x) => x[1]).ToArray()[0][0];
}
public IEnumerator EndBattle(EndState endState = EndState.None)
{
shield?.Free();
shield = null;
soul.RotationDegrees = 0f;
reloadStats = null;
state = State.Override;
Vector2[] p = new Vector2[party.Count];
for (int i = 0; i < party.Count; i++)
{
p[i] = party[i].entity.GlobalPosition;
if (party[i].HP < 0)
{
party[i].HP = 1;
}
party[i].entity.currentAnim = Entity.Animations.BattleEnd;
party[i].entity.direction = Entity.Direction.West;
}
if (lastResult != EndState.Special)
{
lastResult = GetLastResult();
}
if (lastResult != EndState.Special)
{
prizeM = Mathf.FloorToInt((float)prizeM * Mathf.Lerp(1f, 1.5f, (float)TP / 100f));
Enemy enemy = caller;
if (enemy != null && enemy.respawnType == Enemy.Respawn.NoMoney && SaveFile.HasFlag(caller.flag))
{
prizeM = 0;
}
if (lastResult == EndState.Executed)
{
Audio.PlaySound("snd_dtrans_lw.ogg", 1f, 1.1f);
DoDiag(new string[1] { Texts.common[129].Replace("@", "\n") });
SaveFile.current.values[7]++;
for (int j = 0; j < SaveFile.current.activeParty.Count; j++)
{
Party.party[SaveFile.current.activeParty[j]].AddBonus();
}
Party.UpdateStats();
Party.UpdateHUD();
}
else
{
DoDiag(new string[1] { Texts.common[128].Replace("@", "\n").Replace("[EXP]", prizeE.ToString()).Replace("[MONEY]", prizeM.ToString()) });
}
SaveFile.AddMoney(prizeM);
while (diag.Count > 0)
{
yield return null;
}
Audio.ChangeMusic(owMusic);
started = false;
doBG = false;
Coroutine c = Coroutine.Start(FinalizeBattle(p));
while (!c.done)
{
yield return null;
}
}
else
{
if (endState != EndState.None)
{
lastResult = endState;
}
started = false;
doBG = false;
DWMenu.instance.showHP = 0f;
Audio.ChangeMusic((Audio.AudioBlock)null, 5f);
}
}
public IEnumerator FinalizeBattle(Vector2[] p = null)
{
for (int i = 0; i < toDelete.Count; i++)
{
if (GodotObject.IsInstanceValid(toDelete[i]))
{
toDelete[i].QueueFree();
}
}
if (p == null)
{
p = new Vector2[party.Count];
for (int j = 0; j < party.Count; j++)
{
p[j] = party[j].entity.GlobalPosition;
}
}
for (float a = 0f; a < 20f; a += Main.deltaTime)
{
for (int k = 0; k < party.Count; k++)
{
party[k].entity.doTrail = true;
party[k].entity.GlobalPosition = p[k].Lerp(party[k].oEntity.GlobalPosition, a / 20f);
}
DWMenu.instance.battleBG.Modulate = DWMenu.instance.battleBG.Modulate.Lerp(Main.colorClear, a / 20f);
yield return null;
}
Room.UpdateEntityList();
foreach (Entity entity in Room.current.entities)
{
Main.SetActive(entity, state: true);
}
for (int l = 0; l < party.Count; l++)
{
Main.SetActive(party[l].oEntity, state: true);
DWMenu.instance.partyHUDs[l].battleStuff.Visible = false;
}
Room.current.ProcessMode = ProcessModeEnum.Inherit;
DWMenu.instance.showHP = 0f;
Player.instance.canInput = Main.inEvent == null || Main.inEvent.done;
DWMenu.instance.battleCover.Visible = false;
if (caller != null)
{
SaveFile.AddFlag(caller.flag);
if (GodotObject.IsInstanceValid(caller))
{
caller.QueueFree();
}
}
Party.StopMoving();
current = null;
QueueFree();
GC.Collect();
}
public static IEnumerator KillAnim(Entity entity, float startDelay = 0f)
{
float a;
if (startDelay > 0f)
{
for (a = 0f; a < startDelay; a += Main.deltaTime)
{
yield return null;
}
}
entity.Shake(99999f, 1f);
Audio.PlaySound("snd_vaporized.wav", 1f, 0.8f);
entity.Modulate = Main.colorRed;
entity.sprite.Material = (Material)GD.Load<Material>("res://Materials/Dissolve.tres").Duplicate();
StringName d = "shader_parameter/progress";
a = 0f;
for (float b = 120f; a < b; a += Main.deltaTime)
{
entity.sprite.Material.Set(d, Mathf.Lerp(0f, 1f, a / b));
yield return null;
}
entity.Visible = false;
}
public static IEnumerator KillAnim(Battlers target, float startDelay = 0f)
{
target.fleeing = true;
Coroutine anim = Coroutine.Start(KillAnim(target.entity, startDelay));
while (!anim.done)
{
yield return null;
}
RemoveEnemy(target, EndState.Executed);
target.Delete();
yield return null;
}
public static IEnumerator Flee(Battlers target, float startDelay = 30f)
{
target.fleeing = true;
target.entity.AddChild(new Sprite2D
{
Texture = GD.Load<Texture2D>("res://Sprites/Menus/Menu Sprites/Sweat.tres"),
Position = target.center + new Vector2(-16f, -16f)
}, forceReadableName: false, InternalMode.Disabled);
if (!target.dontFlee)
{
Audio.PlaySound("snd_defeatrun.wav");
if (startDelay > 0f)
{
for (float a = 0f; a < startDelay; a += Main.deltaTime)
{
yield return null;
}
}
Vector2 p = target.entity.Position;
target.entity.doTrail = true;
for (float a = 0f; a < 7f; a += Main.deltaTime)
{
target.entity.Position = new Vector2(Mathf.Lerp(p.X, 200f, a / 7f), p.Y);
yield return null;
}
}
RemoveEnemy(target, EndState.Defeated);
if (!target.dontFlee)
{
target.Delete();
}
yield return null;
}
public static void RemoveEnemy(Battlers target, EndState defeatType)
{
for (int i = 0; i < current.party.Count; i++)
{
int[] selectedAction = current.party[i].selectedAction;
if (selectedAction != null && selectedAction.Length > 1)
{
int[] selectedAction2 = current.party[i].selectedAction;
if (((selectedAction2 != null) ? new int?(selectedAction2[1]) : ((int?)null)) > target.posID)
{
current.party[i].selectedAction[1]--;
}
}
}
current.toDelete.Add(target.entity);
current.enemies.Remove(target);
current.allBattlers.Remove(target);
for (int j = 0; j < current.enemies.Count; j++)
{
current.enemies[j].posID = j;
}
if (current.caller != null && current.caller.respawnType != Enemy.Respawn.No && (current.caller.respawnType != Enemy.Respawn.NoMoney || SaveFile.HasFlag(current.caller.flag)))
{
return;
}
current.resultAmts[(int)defeatType][1]++;
switch (defeatType)
{
case EndState.Executed:
SaveFile.current.values[3]++;
break;
case EndState.Spared:
SaveFile.current.values[1]++;
current.prizeM += target.MONEY + SaveFile.current.values[1];
break;
case EndState.Defeated:
SaveFile.current.values[2]++;
current.prizeM += target.MONEY * 2;
break;
case EndState.Apprehended:
if (!target.isOutlaw && !SaveFile.current.apprehended.Contains(target.entity.id))
{
SaveFile.current.apprehended.Add(target.entity.id);
}
SaveFile.current.values[4]++;
break;
}
}
public static IEnumerator ActEffect(Battlers b, float startDelay = 15f, bool flipDir = false)
{
if (startDelay > 0f)
{
for (float a = 0f; a < startDelay; a += Main.deltaTime)
{
yield return null;
}
}
Sprite2D[] sp = new Sprite2D[3];
for (int i = 0; i < sp.Length; i++)
{
if (b.enemy)
{
Entity entity = b.entity;
int num = i;
Sprite2D obj = new Sprite2D
{
Texture = b.entity.sprite.Texture,
Hframes = b.entity.sprite.Hframes,
Vframes = b.entity.sprite.Vframes,
RegionEnabled = b.entity.sprite.RegionEnabled,
RegionRect = b.entity.sprite.RegionRect,
Frame = Mathf.Clamp(b.actFrame, 0, b.entity.sprite.Hframes * b.entity.sprite.Vframes),
ZIndex = -1 * (i + 1),
Offset = b.entity.sprite.Offset
};
Sprite2D node = obj;
sp[num] = obj;
entity.AddChild(node, forceReadableName: false, InternalMode.Disabled);
}
else
{
Entity entity2 = b.entity;
int num2 = i;
Sprite2D obj2 = new Sprite2D
{
Texture = GD.Load<Texture2D>("res://Sprites/Particles/Act/" + b.id.ToString() + ".tres"),
ZIndex = -1 * (i + 1),
Offset = b.entity.sprite.Offset
};
Sprite2D node = obj2;
sp[num2] = obj2;
entity2.AddChild(node, forceReadableName: false, InternalMode.Disabled);
}
}
for (float a = 0f; a < 120f; a += Main.deltaTime)
{
for (int j = 0; j < sp.Length; j++)
{
if (GodotObject.IsInstanceValid(sp[j]))
{
sp[j].GlobalPosition += Vector2.Right * 0.35f * j * Main.deltaTime * (1f - a / 120f) * ((!flipDir) ? 1 : (-1));
sp[j].Modulate = Main.colorTransparent.Lerp(Main.colorClear, a / 120f);
}
}
yield return null;
}
for (int k = 0; k < sp.Length; k++)
{
if (GodotObject.IsInstanceValid(sp[k]))
{
sp[k].Free();
}
}
}
public void UpdateSoul(BulletBoards.SoulType mode = BulletBoards.SoulType.Current)
{
if (mode == BulletBoards.SoulType.Current)
{
mode = defaultSoul;
}
switch (mode)
{
case BulletBoards.SoulType.Blue:
soul.RotationDegrees = 0f;
DWMenu.instance.soul.SelfModulate = Main.colorBlue;
break;
case BulletBoards.SoulType.Yellow:
soul.RotationDegrees = 0f;
DWMenu.instance.soul.SelfModulate = Main.colorYellow;
break;
case BulletBoards.SoulType.Shoot:
soul.RotationDegrees = -90f;
DWMenu.instance.soul.SelfModulate = Main.colorYellow;
break;
}
currentMode = mode;
}
public static void UpdateTP(ref int internalValue, in int amt, in int preview, int mod = 0)
{
if (internalValue != amt)
{
if (internalValue > amt)
{
internalValue--;
}
else
{
internalValue++;
}
}
float num = (float)internalValue / 100f;
DWMenu.instance.tpBar[1].Scale = new Vector2(1f, num);
DWMenu.instance.tpBar[2].Visible = (float)internalValue > 2f;
DWMenu.instance.tpBar[2].Position = new Vector2(0f, Mathf.Lerp(98f, -98f, num));
DWMenu.instance.tpBar[2].Scale = new Vector2(1f, Mathf.Clamp((float)Mathf.Clamp(preview, 0, amt) / 100f, 0.01f, 1f));
if (amt >= 100)
{
DWMenu.instance.tpBar[1].Modulate = DWMenu.instance.TPColors[2];
}
else
{
DWMenu.instance.tpBar[1].Modulate = DWMenu.instance.TPColors[1];
}
if (preview > 0)
{
DWMenu.instance.tpBar[2].Modulate = DWMenu.instance.TPColors[0].Lerp(Main.colorWhite, Mathf.Abs(Common.SinOverTime(0.35f)));
}
else
{
DWMenu.instance.tpBar[2].Modulate = DWMenu.instance.TPColors[0];
}
if (mod == 1)
{
if (amt >= 100)
{
DWMenu.instance.tpText.Text = "[color=yellow] M\n A\n X";
}
else
{
DWMenu.instance.tpText.Text = " " + internalValue + "\n %";
}
}
}
private bool UseOnParty(int i)
{
if (party[i].selectedAction[0] != 3)
{
return Texts.skills[(Acts.IDs)party[i].selectedAction[2]].useOnParty;
}
return true;
}
private IEnumerator DoSpells()
{
for (int i = 0; i < party.Count; i++)
{
if (forceEnd)
{
yield break;
}
if (enemies.Count <= 0 || !party[i].CanAct())
{
continue;
}
int[] selectedAction = party[i].selectedAction;
if (selectedAction == null || selectedAction.Length == 0 || (party[i].selectedAction[0] != 2 && party[i].selectedAction[0] != 1 && party[i].selectedAction[0] != 3))
{
continue;
}
currentlyActing = party[i];
Acts.IDs key = (Acts.IDs)party[i].selectedAction[2];
if (party[i].selectedAction[0] == 3)
{
key = Acts.IDs.UseItem;
}
Battlers battlers;
if (party[i].selectedAction[0] == 3 || Texts.skills[key].useOnParty)
{
if (party[i].selectedAction[0] == 3)
{
if (!Texts.items[(Items.IDs)party[i].selectedAction[2]].useOnEnemy)
{
battlers = party[party[i].selectedAction[1]];
}
else
{
party[i].selectedAction[1] = (int)Main.Repeat(party[i].selectedAction[1], enemies.Count);
battlers = enemies[party[i].selectedAction[1]];
}
}
else
{
battlers = party[party[i].selectedAction[1]];
}
}
else
{
party[i].selectedAction[1] = (int)Main.Repeat(party[i].selectedAction[1], enemies.Count);
battlers = enemies[party[i].selectedAction[1]];
}
if (party[i].selectedAction[0] == 1 && Texts.skills[key].spAction)
{
party[i].selectedAction[0] = 2;
party[i].selectedAction[2] = (int)enemyData[battlers.id].acts[enemyData[battlers.id].partyAction[Main.RandomRange(0, enemyData[battlers.id].partyAction.Count - 1)]];
key = (Acts.IDs)party[i].selectedAction[2];
}
List<Battlers> list = new List<Battlers> { party[i] };
if (party[i].selectedAction[0] == 2)
{
party[i].entity.currentAnim = Entity.Animations.ActDo;
battlers.lastestAct.Add(party[i].selectedAction[2]);
Coroutine.Start(ActEffect(party[i]));
if (actExtra.ContainsKey(i))
{
for (int j = 0; j < actExtra[i].Length; j++)
{
Party.party[(int)actExtra[i][j]].entity.currentAnim = Entity.Animations.ActDo;
Coroutine.Start(ActEffect(Party.party[(int)actExtra[i][j]]));
list.Add(Party.party[(int)actExtra[i][j]]);
}
}
}
else if (party[i].selectedAction[0] == 3)
{
party[i].entity.currentAnim = Entity.Animations.ItemDo;
}
else
{
party[i].entity.currentAnim = Entity.Animations.SkillDo;
}
DWMenu.instance.battleText.Text = "";
Coroutine acting = Acts.DoActRoutine(key.ToString(), battlers, list.ToArray());
while (!acting.done)
{
yield return null;
}
party[i].entity.currentAnim = Entity.Animations.BattleIdle;
if (actExtra.ContainsKey(i))
{
for (int k = 0; k < actExtra[i].Length; k++)
{
Party.party[(int)actExtra[i][k]].entity.currentAnim = Entity.Animations.BattleIdle;
}
}
}
if (enemies.Count == 0 || forceEnd)
{
busy = Coroutine.Start(EndBattle());
}
else
{
state = State.DoAttack;
}
}
private IEnumerator DoAttack()
{
if (forceEnd)
{
yield break;
}
DWMenu.instance.battleText.Text = "";
List<int> list = new List<int>();
List<int> order = new List<int>();
for (int i = 0; i < party.Count; i++)
{
int[] selectedAction = party[i].selectedAction;
if (selectedAction != null && selectedAction[0] == 0)
{
list.Add(i);
order.Add(i);
}
}
if (list.Count > 0)
{
AttackActionCommand.actionCD = 0f;
AttackActionCommand[] bars = new AttackActionCommand[list.Count];
order = order.OrderBy((int x) => Guid.NewGuid()).ToList();
for (int num = 0; num < list.Count; num++)
{
bars[num] = GD.Load<PackedScene>("res://Objects/UI/ActionCommand.tscn").Instantiate<AttackActionCommand>(PackedScene.GenEditState.Disabled);
bars[num].ProcessPriority = order.Count - num;
bars[num].linked = party[order[num]];
AddChild(bars[num], forceReadableName: false, InternalMode.Disabled);
if (SaveFile.current.activeParty.Count > 3)
{
bars[num].Scale = new Vector2(1f, 0.5f);
bars[num].Position = new Vector2(-94f, 76 + 9 * list[num]);
}
else
{
bars[num].Position = new Vector2(-94f, 76 + 17 * list[num]);
}
}
List<int> list2 = new List<int>();
for (int num2 = 0; num2 < bars.Length; num2++)
{
for (int num3 = 0; num3 < bars.Length; num3++)
{
if (num2 != num3 && !list2.Contains(num3) && Mathf.Abs(bars[num3].bar.Position.X - bars[num2].bar.Position.X) < 15f)
{
list2.Add(num3);
bars[num3].bar.Position = new Vector2(bars[num2].bar.Position.X, bars[num3].bar.Position.Y);
}
}
}
yield return null;
Common.FillArray(ref order, order.Count, 0);
order = order.OrderBy((int x) => bars[x].bar.Position.X).ToList();
bool flag;
do
{
if (AttackActionCommand.actionCD > 0f)
{
AttackActionCommand.actionCD -= Main.deltaTime;
}
if (Input.IsActionJustPressed(Main.keys[4]))
{
for (int num4 = 0; num4 < bars.Length; num4++)
{
if (bars[order[num4]].active)
{
continue;
}
bars[order[num4]].Activate();
for (int num5 = 0; num5 < bars.Length; num5++)
{
if (order[num5] != order[num4] && !bars[order[num5]].active && Mathf.Abs(bars[order[num5]].bar.Position.X - bars[order[num4]].bar.Position.X) < 15f)
{
bars[order[num5]].Activate();
}
}
break;
}
}
yield return null;
flag = false;
for (int num6 = 0; num6 < bars.Length; num6++)
{
if (GodotObject.IsInstanceValid(bars[num6]))
{
flag = true;
}
}
}
while (flag);
}
bool flag2;
do
{
yield return null;
flag2 = false;
for (int num7 = 0; num7 < fleeing.Count; num7++)
{
Coroutine coroutine = fleeing[num7];
if (coroutine != null && !coroutine.done)
{
flag2 = true;
}
}
}
while (flag2);
fleeing.Clear();
yield return null;
if (enemies.Count == 0)
{
busy = Coroutine.Start(EndBattle());
yield break;
}
yield return null;
state = State.DoEnemy;
}
private void Graze(Node other)
{
IBullet parentOrNull = other.GetParentOrNull<IBullet>();
if (parentOrNull != null && !parentOrNull.grazed && iFrames <= 0f && grazeCD <= 0f)
{
parentOrNull.grazed = true;
Audio.PlaySound("snd_graze.wav");
TP = Mathf.Clamp(TP + (grazed ? 2 : 3), 0, 100);
grazed = true;
grazeCD = 5f;
activeBoard.timer -= 2f;
DWMenu.instance.grazeIndicator.SelfModulate = Main.colorWhite;
}
}
public Control DoBlurb(Battlers enemy, int id, ref RichTextLabel label)
{
if (enemy.blurbOverride > -1)
{
id = enemy.blurbOverride;
}
Control control;
AddChild(control = GD.Load<PackedScene>("res://Objects/UI/Bubble.tscn").Instantiate<Control>(PackedScene.GenEditState.Disabled), forceReadableName: false, InternalMode.Disabled);
BattleBlurbs[] blurbs = enemy.blurbs;
BattleBlurbs battleBlurbs = ((blurbs != null && blurbs.Length > 1 && enemy.blurbs[id] != null) ? enemy.blurbs[id] : null);
if (battleBlurbs == null)
{
battleBlurbs = new BattleBlurbs();
}
Vector2 vector = battleBlurbs.size;
if (vector.LengthSquared() < enemy.defaultBubbleSize.LengthSquared())
{
vector = enemy.defaultBubbleSize;
}
control.GlobalPosition = enemy.entity.GlobalPosition + enemy.center + new Vector2(-20f + Mathf.Min(battleBlurbs.offset.X, vector.X / -2f), battleBlurbs.offset.Y);
label = control.GetChild(0).GetChild<RichTextLabel>(0);
label.Text = blurbText[enemy.id][id].Replace("@", "\n");
control.GetChild<NinePatchRect>(0).Size = new Vector2(vector.X, Mathf.Max((float)label.GetLineCount() * 4.5f, vector.Y));
float volume = 1f;
string diagSound = enemy.diagSound;
if (diagSound != null && diagSound.Length > 0)
{
TextSystem.AssignBleep(enemy.diagSound, ref volume);
}
else
{
TextSystem.bleepPlayer.Stream = TextSystem.defaultBleep;
}
return control;
}
private string AnySpecial()
{
for (int i = 0; i < enemies.Count; i++)
{
if (enemies[i].hasSpecial > -1 && enemies[i].CanSpecial())
{
return enemies[i].bulletBoards[enemies[i].hasSpecial].ResourceName;
}
}
return null;
}
private IEnumerator DoEnemy()
{
string special = AnySpecial();
if (special != null && specialWarning)
{
activeBoard = GD.Load<PackedScene>("res://Objects/BulletBoards/" + special + ".tscn").Instantiate<BulletBoards>(PackedScene.GenEditState.Disabled);
lastBoard = activeBoard.id;
lastAttack = activeBoard.Name;
}
else
{
special = null;
List<object[]> list = new List<object[]>();
List<object[]> list2 = new List<object[]>();
for (int i = 0; i < enemies.Count; i++)
{
if (enemies[i].skipAttack)
{
continue;
}
for (int j = 0; j < enemies[i].bulletBoards.Length; j++)
{
if (!enemies[i].bulletBoards[j].CanDo(enemies[i]))
{
continue;
}
if (enemies[i].bulletBoards[j].weight == -1)
{
list2.Add(new object[2]
{
enemies[i].bulletBoards[j].ResourceName,
enemies[i]
});
continue;
}
if (enemies[i].bulletBoards[j].weight >= 50)
{
list.Clear();
list.Add(new object[2]
{
enemies[i].bulletBoards[j].ResourceName,
enemies[i]
});
break;
}
for (int k = 0; k < enemies[i].bulletBoards[j].weight; k++)
{
list.Add(new object[2]
{
enemies[i].bulletBoards[j].ResourceName,
enemies[i]
});
}
}
}
int num = 2;
string text;
int index;
while (true)
{
text = null;
index = 0;
if (list.Count == 0)
{
if (list2.Count > 0)
{
index = Main.RandomRange(0, list2.Count - 1);
text = (string)list2[index][0];
}
else
{
state = State.EndTurn;
}
break;
}
index = Main.RandomRange(0, list.Count - 1);
text = (string)list[index][0];
if (!((StringName)text == lastAttack) || num <= 0)
{
break;
}
num--;
}
if (text != null)
{
activeBoard = GD.Load<PackedScene>("res://Objects/BulletBoards/" + text + ".tscn").Instantiate<BulletBoards>(PackedScene.GenEditState.Disabled);
if (list.Count > 0)
{
activeBoard.caller = (Battlers)list[index][1];
}
lastBoard = activeBoard.id;
lastAttack = activeBoard.Name;
}
}
AnimatedSprite2D[] reticle = null;
List<int> target = new List<int>();
if (GodotObject.IsInstanceValid(activeBoard))
{
DWMenu.instance.bulletBoard.Size = activeBoard.boardSize;
DWMenu.instance.bulletBoard.AnchorsPreset = 8;
DWMenu.instance.bulletBoardPivot.Position = DWMenu.boardCenter + activeBoard.boardStartOffset;
if (focusAtk > -1)
{
activeBoard.target = BulletBoards.Target.OnlyOne;
}
if (activeBoard.target == BulletBoards.Target.OnlyOne)
{
int num2 = ((SaveFile.current.activeParty.Count < 3) ? 1 : GD.RandRange(2, 3));
for (int l = 0; l < num2 && l < party.Count && l < Party.AlivePartyAmount(); l++)
{
target.Add(-1);
if (focusAtk > -1)
{
target[0] = focusAtk;
break;
}
do
{
target[l] = Main.RandomRange(0, party.Count - 1);
}
while (party[target[l]].HP <= 0);
}
reticle = new AnimatedSprite2D[target.Count];
for (int m = 0; m < reticle.Length; m++)
{
AddChild(reticle[m] = GD.Load<PackedScene>("res://Objects/Particles/Reticle.tscn").Instantiate<AnimatedSprite2D>(PackedScene.GenEditState.Disabled), forceReadableName: false, InternalMode.Disabled);
reticle[m].GlobalPosition = party[target[m]].entity.GlobalPosition + party[target[m]].center + Vector2.Up * 8f;
}
}
else
{
reticle = new AnimatedSprite2D[party.Count];
for (int n = 0; n < reticle.Length; n++)
{
AddChild(reticle[n] = GD.Load<PackedScene>("res://Objects/Particles/Reticle.tscn").Instantiate<AnimatedSprite2D>(PackedScene.GenEditState.Disabled), forceReadableName: false, InternalMode.Disabled);
reticle[n].GlobalPosition = party[n].entity.GlobalPosition + party[n].center;
}
}
}
yield return null;
Control[] blurbs = new Control[enemies.Count];
RichTextLabel[] text2 = new RichTextLabel[enemies.Count];
for (int num3 = 0; num3 < enemies.Count; num3++)
{
if (!enAnim.Contains(enemies[num3].entity.anim.CurrentAnimation) && !enemies[num3].lockAnim)
{
enemies[num3].entity.anim.Play("Idle");
}
int[] blurbOrder = enemies[num3].blurbOrder;
if (blurbOrder != null && blurbOrder.Length != 0 && turn < enemies[num3].blurbOrder.Length)
{
blurbs[num3] = DoBlurb(enemies[num3], enemies[num3].blurbCount, ref text2[num3]);
if (enemies[num3].blurbOverride == -1)
{
enemies[num3].blurbCount++;
}
continue;
}
int[] randomBlurbs = enemies[num3].randomBlurbs;
if (randomBlurbs != null && randomBlurbs.Length != 0)
{
blurbs[num3] = DoBlurb(enemies[num3], enemies[num3].randomBlurbs[Main.RandomRange(0, enemies[num3].randomBlurbs.Length - 1)], ref text2[num3]);
continue;
}
List<int> list3 = new List<int>();
int num4 = -1;
for (int num5 = 0; num5 < enemies[num3].blurbs.Length; num5++)
{
if (enemies[num3].blurbOverride > -1)
{
num4 = enemies[num3].blurbOverride;
break;
}
if (enemies[num3].blurbs[num5].Can(enemies[num3]))
{
if (enemies[num3].blurbs[num5].weight >= 50)
{
list3 = null;
num4 = num5;
break;
}
for (int num6 = 0; num6 < enemies[num3].blurbs[num5].weight; num6++)
{
list3.Add(num5);
}
}
}
if (list3 != null)
{
if (num4 == -1 && list3.Count > 0)
{
num4 = list3[Main.RandomRange(0, list3.Count - 1)];
}
else if (enemies[num3].blurbOverride == -1)
{
num4 = -1;
}
}
if (num4 == -1)
{
GD.Print("No blurbs found for " + enemies[num3].name);
num4 = 0;
}
blurbs[num3] = DoBlurb(enemies[num3], (enemies[num3].blurbs[num4].overrideIndex > -1) ? enemies[num3].blurbs[num4].overrideIndex : num4, ref text2[num3]);
}
TextSystem.bleepPlayer.Play();
while (true)
{
bool flag = true;
for (int num7 = 0; num7 < text2.Length; num7++)
{
text2[num7].VisibleCharacters++;
if (text2[num7].VisibleRatio < 1f)
{
flag = false;
}
}
if (flag && TextSystem.bleepPlayer.Playing)
{
TextSystem.bleepPlayer.Stop();
}
yield return null;
if (!Input.IsActionJustPressed(Main.keys[4]))
{
continue;
}
bool flag2 = false;
for (int num8 = 0; num8 < text2.Length; num8++)
{
RichTextLabel obj = text2[num8];
if (obj != null && obj.VisibleRatio < 1f)
{
text2[num8].VisibleCharacters = 999;
flag2 = true;
}
}
if (!flag2)
{
break;
}
}
TextSystem.bleepPlayer.Stop();
for (int num9 = 0; num9 < blurbs.Length; num9++)
{
blurbs[num9]?.Free();
}
Sprite2D soulShadow = null;
if (GodotObject.IsInstanceValid(activeBoard))
{
for (int num10 = 0; num10 < reticle.Length; num10++)
{
reticle[num10].Free();
}
soul.Visible = true;
soul.TopLevel = true;
soul.ZIndex = 4096;
soulShadow = new Sprite2D
{
Texture = DWMenu.instance.soul.Texture,
RegionEnabled = true,
RegionRect = DWMenu.instance.soul.RegionRect,
Modulate = new Color(soul.Modulate.R, soul.Modulate.G, soul.Modulate.B, 0.5f),
ZIndex = soul.ZIndex - 1,
TopLevel = true,
Position = Vector2.One * 999f
};
Vector2 boxCenter = DWMenu.instance.bulletBoardPivot.GlobalPosition + activeBoard.soulStartOffset;
Vector2 pcCenter = party[0].entity.GlobalPosition + party[0].center;
soul.GetParent().AddChild(soulShadow, forceReadableName: false, InternalMode.Disabled);
soul.GlobalPosition = Vector2.One * 9999f;
Main.SetActive(DWMenu.instance.bulletBoardPivot, state: true);
UpdateSoul(activeBoard.soulType);
Main.Particle("SoulSplit", Vector2.Up * 16f, 1, party[0].entity);
DWMenu.instance.bulletBoard.Visible = true;
float a;
for (a = 0f; a <= activeBoard.growTime; a += Main.deltaTime)
{
Room.current.Modulate = Main.colorWhite.Lerp(Main.colorDark, a / activeBoard.growTime);
DWMenu.instance.bulletBoardPivot.Scale = Vector2.Zero.Lerp(Vector2.One, a / activeBoard.growTime);
if ((int)a % 3 == 0 && a > 0f)
{
soulShadow.GlobalPosition = soul.GlobalPosition;
}
soul.GlobalPosition = pcCenter.Lerp(boxCenter, a / activeBoard.growTime);
if (activeBoard.special)
{
DWMenu.instance.bulletBoardPivot.Rotation = Mathf.Lerp(180f, 0f, a / activeBoard.growTime);
}
else
{
DWMenu.instance.bulletBoardPivot.Rotation = Mathf.LerpAngle(Mathf.DegToRad(90f), 0f, a / activeBoard.growTime);
}
for (int num11 = 0; num11 < allBattlers.Count; num11++)
{
allBattlers[num11].entity.Modulate = Main.colorWhite.Lerp(Main.colorDark, a / activeBoard.growTime);
}
yield return null;
}
DWMenu.instance.bulletBoardPivot.Scale = Vector2.One;
DWMenu.instance.bulletBoardPivot.Rotation = 0f;
for (int num12 = 0; num12 < 3; num12++)
{
if (num12 == 0)
{
DWMenu.instance.bulletBoard.GetChild<Control>(0).Visible = false;
}
else
{
DWMenu.instance.bulletBoard.GetChild(0).GetChild<Control>(num12 - 1).Visible = false;
}
yield return null;
}
soulShadow.Visible = false;
DWMenu.instance.soulHitbox.Enabled = true;
DWMenu.instance.soulHitbox.ForceShapecastUpdate();
iFrames = 0f;
soulColor = DWMenu.instance.soul.SelfModulate;
DWMenu.instance.bulletBoardPivot.AddChild(activeBoard, forceReadableName: false, InternalMode.Disabled);
soul.Reparent(DWMenu.instance.bulletBoardPivot);
activeBoard.targeted = target.ToArray();
yield return null;
do
{
if (BulletBoardInput())
{
yield break;
}
activeBoard.timer -= Main.deltaTime;
yield return null;
}
while (activeBoard.timer > 0f);
DWMenu.instance.bulletBoard.SelfModulate = Main.colorGreen;
soul.Reparent(DWMenu.instance);
DWMenu.instance.soul.SelfModulate = soulColor;
boxCenter = soul.GlobalPosition;
DWMenu.instance.soulHitbox.Enabled = false;
DWMenu.instance.soulBody.Velocity = Vector2.Zero;
activeBoard?.QueueFree();
yield return null;
for (int num13 = 0; num13 < enemies.Count; num13++)
{
if (special != null)
{
enemies[num13].internalFlags.Add("Special");
}
enemies[num13].entity.Position = enemies[num13].startPos;
enemies[num13].entity.UpdateAnim(force: true);
enemies[num13].entity.doTrail = false;
}
soulShadow.Visible = true;
soulShadow.GlobalPosition = soul.GlobalPosition;
a = 0f;
float i2 = 0f;
while (a <= 20f)
{
Room.current.Modulate = Main.colorDark.Lerp(Main.colorWhite, a / 20f);
if (i2 < 3f)
{
if (i2 == 0f)
{
DWMenu.instance.bulletBoard.GetChild<Control>(0).Visible = true;
}
else
{
DWMenu.instance.bulletBoard.GetChild(0).GetChild<Control>((int)i2 - 1).Visible = true;
}
yield return null;
}
for (int num14 = 0; num14 < allBattlers.Count; num14++)
{
allBattlers[num14].entity.Modulate = Main.colorWhite.Lerp(Main.colorDark, 1f - a / 20f);
}
DWMenu.instance.bulletBoardPivot.Rotation = Mathf.LerpAngle(0f, Mathf.DegToRad(90f), a / 20f);
DWMenu.instance.bulletBoardPivot.Scale = Vector2.Zero.Lerp(Vector2.One, 1f - a / 20f);
if ((int)a % 3 == 0 && a > 0f)
{
soulShadow.GlobalPosition = soul.GlobalPosition;
}
soul.GlobalPosition = pcCenter.Lerp(boxCenter, 1f - a / 20f);
yield return null;
a += Main.deltaTime;
i2 += 1f;
}
Main.Particle("SoulSplit", Vector2.Up * 16f, 1, party[0].entity);
}
UpdateSoul();
Room.current.Modulate = Main.colorWhite;
Main.SetActive(DWMenu.instance.bulletBoardPivot, state: false);
soulShadow?.Free();
soul.TopLevel = false;
soul.Visible = false;
state = State.EndTurn;
}
private bool BulletBoardInput()
{
if (shootCD > 0f)
{
shootCD -= Main.deltaTime;
}
switch (currentMode)
{
case BulletBoards.SoulType.Shoot:
if (shootCD <= 0f && shots.Count < 5 && ((!Settings.file.autoFire && Input.IsActionJustPressed(Main.keys[4])) || (Settings.file.autoFire && Input.IsActionPressed(Main.keys[4]))))
{
shootCD = 10f;
SoulBullet soulBullet;
activeBoard.AddChild(soulBullet = BattleDR.soulBullet.Instantiate<SoulBullet>(PackedScene.GenEditState.Disabled), forceReadableName: false, InternalMode.Disabled);
soulBullet.dir = Vector2.Up.Rotated(0f - soul.Rotation);
soulBullet.GlobalPosition = soul.GlobalPosition + soulBullet.dir * 3f;
shots.Add(soulBullet);
}
soul.Velocity = (Main.GetDirection() * Main.deltaTime).Normalized() * 55f;
soul.MotionMode = CharacterBody2D.MotionModeEnum.Floating;
break;
case BulletBoards.SoulType.Blue:
soul.MotionMode = CharacterBody2D.MotionModeEnum.Grounded;
break;
default:
soul.Velocity = (Main.GetDirection() * Main.deltaTime).Normalized() * 55f;
soul.MotionMode = CharacterBody2D.MotionModeEnum.Floating;
break;
}
soul.MoveAndSlide();
if (iFrames > 0f)
{
iFrames -= Main.deltaTime;
DWMenu.instance.soul.SelfModulate = soulColor.Lerp(Main.colorBlack, Mathf.Abs(Mathf.Sin(Mathf.DegToRad(Time.GetTicksMsec()))));
}
else
{
DWMenu.instance.soul.SelfModulate = soulColor;
if (DWMenu.instance.soulHitbox.GetCollisionCount() > 0 && PlayerHurt())
{
return true;
}
}
return false;
}
private bool PlayerHurt()
{
IBullet bullet = null;
for (int i = 0; i < DWMenu.instance.soulHitbox.GetCollisionCount(); i++)
{
if (GodotObject.IsInstanceValid(DWMenu.instance.soulHitbox.GetCollider(i)))
{
Node parent = ((Node)DWMenu.instance.soulHitbox.GetCollider(i)).GetParent();
if (parent is IBullet bullet2)
{
bullet = bullet2;
break;
}
if (parent is SoulBullet)
{
return false;
}
}
}
if (bullet != null)
{
switch (bullet.type)
{
case IBullet.Type.Blue:
if (soul.Velocity == Vector2.Zero)
{
return false;
}
break;
case IBullet.Type.Orange:
if (soul.Velocity != Vector2.Zero)
{
return false;
}
break;
}
if (shield != null)
{
CameraController.instance.shakeTime = 7f;
shield?.Free();
shield = null;
iFrames = 40 + Party.GetIframes();
Audio.PlaySound("snd_ceroba_shield_impact.wav");
return false;
}
float num = 0f;
if (activeBoard.caller == null)
{
for (int j = 0; j < enemies.Count; j++)
{
num += (float)enemies[j].ATK;
if (enemies[j].atkMod != null)
{
num += (float)enemies[j].atkMod[1];
}
num = Mathf.Clamp(num, (float)enemies[j].ATK / 2f, (float)enemies[j].ATK * 2f);
}
num /= (float)enemies.Count;
}
else
{
num += (float)activeBoard.caller.ATK;
if (activeBoard.caller.atkMod != null)
{
num += (float)activeBoard.caller.atkMod[1];
}
num = Mathf.Clamp(num, (float)activeBoard.caller.ATK / 2f, (float)activeBoard.caller.ATK * 2f);
}
num *= activeBoard.damageMult;
List<int> list = new List<int>();
if (activeBoard.target == BulletBoards.Target.OnlyOne)
{
list.Add(activeBoard.targeted[GD.RandRange(0, activeBoard.targeted.Length - 1)]);
}
else if (activeBoard.target == BulletBoards.Target.All)
{
for (int k = 0; k < party.Count; k++)
{
list.Add(k);
}
}
else if (activeBoard.target == BulletBoards.Target.RandomAll)
{
int num2;
do
{
num2 = Main.RandomRange(0, party.Count - 1);
}
while (party[num2].HP <= 0);
list.Add(num2);
}
CameraController.instance.shakeTime = 7f;
for (int l = 0; l < list.Count; l++)
{
if (party[list[l]].HP <= 0)
{
continue;
}
int num3 = Mathf.RoundToInt(Mathf.Clamp(num * (1f + Main.RandomRange(-0.1f, 0.1f)) - (float)party[list[l]].DEF, 1f, 999f));
if (party[list[l]].defMod != null)
{
num3 = Mathf.Clamp(num3 - party[list[l]].defMod[1], 0, 999);
}
int[] selectedAction = party[list[l]].selectedAction;
if (selectedAction != null && selectedAction[0] == 4)
{
num3 = (int)Mathf.Max((float)num3 / 2f, (float)num3 * 0.2f);
}
party[list[l]].HP -= num3;
if (activeBoard.cantKill)
{
party[list[l]].HP = Mathf.Clamp(party[list[l]].HP, 1, party[list[l]].MAXHP);
}
if (party[list[l]].HP <= 0)
{
if (Party.AlivePartyAmount() == 0)
{
soul.Reparent(DWMenu.instance);
activeBoard.QueueFree();
Coroutine.Start(GameOver.DoGameOver());
base.ProcessMode = ProcessModeEnum.Disabled;
return true;
}
party[list[l]].HP = -party[list[l]].MAXHP;
ShowFloatingText(Texts.common[127], party[list[l]].entity.GlobalPosition + new Vector2(-16f, 0f), Main.colorRed);
party[list[l]].entity.currentAnim = Entity.Animations.KO;
party[list[l]].selectedAction = null;
if (activeBoard.target == BulletBoards.Target.OnlyOne)
{
activeBoard.target = BulletBoards.Target.RandomAll;
}
}
else
{
ShowFloatingText(num3.ToString(), party[list[l]].entity.GlobalPosition + new Vector2(-16f, 0f), Main.colorWhite);
party[list[l]].entity.currentAnim = Entity.Animations.Hurt;
Entity entity = party[list[l]].entity;
int[] selectedAction2 = party[list[l]].selectedAction;
Coroutine.Start(entity.DelayedAnim(30f, (selectedAction2 != null && selectedAction2[0] == 4) ? Entity.Animations.Defend : Entity.Animations.BattleIdle));
}
}
Audio.PlaySound("snd_hurt1.wav");
Party.UpdateHUD();
iFrames = 40 + Party.GetIframes();
return false;
}
return false;
}
public static Node2D NewBullet(in PackedScene type, Vector2 pos, Node2D parent = null, bool local = false)
{
Node2D node2D;
if (parent == null)
{
current.activeBoard.AddChild(node2D = type.Instantiate<Node2D>(PackedScene.GenEditState.Disabled), forceReadableName: false, InternalMode.Disabled);
}
else
{
parent.AddChild(node2D = type.Instantiate<Node2D>(PackedScene.GenEditState.Disabled), forceReadableName: false, InternalMode.Disabled);
}
if (local)
{
node2D.Position = pos;
}
else
{
node2D.GlobalPosition = pos;
}
node2D.ProcessMode = ProcessModeEnum.Inherit;
return node2D;
}
public static Node2D NewBullet(in Node2D type, Vector2 pos, Node2D parent = null, bool local = false)
{
Node2D node2D;
if (parent == null)
{
current.activeBoard.AddChild(node2D = (Node2D)type.Duplicate(), forceReadableName: false, InternalMode.Disabled);
}
else
{
parent.AddChild(node2D = (Node2D)type.Duplicate(), forceReadableName: false, InternalMode.Disabled);
}
if (local)
{
node2D.Position = pos;
}
else
{
node2D.GlobalPosition = pos;
}
node2D.ProcessMode = ProcessModeEnum.Inherit;
return node2D;
}
private IEnumerator AdvanceTurn()
{
turn++;
bool flag = false;
for (int i = 0; i < party.Count; i++)
{
party[i].selectedAction = null;
party[i].acted = false;
if (party[i].HP > 0)
{
party[i].entity.currentAnim = Entity.Animations.BattleIdle;
}
else
{
party[i].entity.currentAnim = Entity.Animations.KO;
}
int num = 0;
if (party[i].HP <= 0)
{
num += party[i].MAXHP / 3;
}
for (int j = 0; j < 3; j++)
{
if (party[i].EQUIP[j] > -1 && Texts.items[(Items.IDs)party[i].EQUIP[j]].healOverTime > 0)
{
num += Texts.items[(Items.IDs)party[i].EQUIP[j]].healOverTime;
}
}
if (num > 0)
{
Coroutine.Start(Heal(party[i], num, playParticles: false, doColor: false, showText: true, !flag));
flag = true;
}
}
for (int k = 0; k < enemies.Count; k++)
{
enemies[k].lastestAct.Clear();
enemies[k].blurbOverride = -1;
}
for (int l = 0; l < allBattlers.Count; l++)
{
int[] atkMod = allBattlers[l].atkMod;
if (atkMod != null && atkMod[0] > 0)
{
allBattlers[l].atkMod[0]--;
if (allBattlers[l].atkMod[0] == 0)
{
allBattlers[l].atkMod = null;
}
}
int[] defMod = allBattlers[l].defMod;
if (defMod != null && defMod[0] > 0)
{
allBattlers[l].defMod[0]--;
if (allBattlers[l].defMod[0] == 0)
{
allBattlers[l].defMod = null;
}
}
allBattlers[l].bulletSpeedMod = 0f;
}
Party.UpdateHUD();
firstMes = false;
grazed = false;
actExtra.Clear();
GetNextBattleText();
lastTP.Clear();
consumeItems.Clear();
lastActor.Clear();
option = 0;
focusAtk = -1;
maxOption = 5;
currentlyActing = null;
currentActor = -1;
for (float a = 0f; a < 3f; a += Main.deltaTime)
{
yield return null;
}
state = State.Next;
UpdateMenu();
}
private float GetMercy(int id = -1)
{
if (id > 3)
{
return 0f;
}
if (id == -1)
{
int num = 0;
for (int i = 0; i < enemies.Count; i++)
{
num += enemies[i].spare;
}
return num / enemies.Count;
}
return enemies[id].spare;
}
private void GetNextBattleText()
{
if (AnySpecial() != null)
{
for (int i = 0; i < Texts.battleMes[this.battleMes].Length; i++)
{
if (Texts.battleMes[this.battleMes][i].special)
{
lastMes = i;
specialWarning = true;
return;
}
}
}
if (turn == 0)
{
lastMes = 0;
return;
}
if (forceMes > -1)
{
lastMes = forceMes;
forceMes = -1;
return;
}
List<int> list = new List<int>();
for (int j = 1; j < Texts.battleMes[this.battleMes].Length; j++)
{
Texts.BattleMes battleMes = Texts.battleMes[this.battleMes][j];
Entity.IDs? check = battleMes.idToCheck;
Battlers battlers = (check.HasValue ? enemies.FirstOrDefault((Battlers x) => x.id == check.Value) : null);
if (!battleMes.cant && !battleMes.special && (battleMes.reqTurn <= 0 || turn >= battleMes.reqTurn) && (!check.HasValue || battlers != null) && (battleMes.everyXTurns <= 0 || turn % battleMes.everyXTurns == 0) && (battleMes.hpCheck <= 0f || (battlers != null && battlers.HPPercent() <= battleMes.hpCheck)) && (battleMes.mercyCheck <= 0f || (battlers != null && (float)battlers.spare <= battleMes.mercyCheck)) && (battleMes.atMesCount <= 0 || battleMes.atMesCount == mesCount) && (battleMes.onlyTurn <= 0 || turn == battleMes.onlyTurn) && enemies.Count >= battleMes.reqEnemyAmt && (battleMes.mercyCheck == -1f || GetMercy() >= battleMes.mercyCheck) && (battleMes.battleFlagReq == null || battleMes.battleFlagReq.Count == 0 || battleMes.battleFlagReq.All((StringName x) => tempFlags.Contains(x))) && (battleMes.battleFlagLimit == null || battleMes.battleFlagLimit.Count == 0 || !battleMes.battleFlagLimit.All((StringName x) => tempFlags.Contains(x))))
{
if (battleMes.weight >= 50)
{
list.Clear();
list.Add(j);
break;
}
for (int num = 0; num < battleMes.weight; num++)
{
list.Add(j);
}
}
}
int num2 = 0;
for (int num3 = 0; num3 < 10; num3++)
{
num2 = ((list.Count != 0) ? list[Main.RandomRange(0, list.Count - 1)] : 0);
if (num2 != lastMes)
{
break;
}
}
if (Texts.battleMes[this.battleMes][num2].addCount)
{
mesCount++;
}
else if (Texts.battleMes[this.battleMes][num2].resetCount)
{
mesCount = 0;
}
lastMes = num2;
}
public static void DoDiag(string[] text, string[] portraits = null)
{
current.diag = new List<string>(text);
if (portraits != null)
{
current.portraits = new List<string>(portraits);
}
else
{
current.portraits?.Clear();
}
DWMenu.instance.battleText.VisibleRatio = 0f;
if (portraits != null)
{
DWMenu.instance.battleText2.VisibleRatio = 0f;
}
}
public void ResetEnemyHighlight()
{
for (int i = 0; i < enemies.Count; i++)
{
enemies[i].entity.Modulate = Main.colorWhite;
}
}
private void ChangeOption(int d)
{
option += d;
if (option < 0)
{
option = maxOption - 1;
}
else if (option >= maxOption)
{
option = 0;
}
Audio.PlaySound(Audio.commonSounds[0]);
}
public static IEnumerator Heal(Battlers target, int amt, bool playParticles = true, bool doColor = true, bool showText = true, bool playSound = true)
{
if (playParticles)
{
((Node2D)Main.Particle("HealParts", target.entity.GlobalPosition + target.center, null, current, localSpace: false)).ZIndex = 3000;
}
if (playSound)
{
Audio.PlaySound("snd_power.wav");
}
bool flag = target.HP <= 0;
target.HP = Mathf.Clamp(target.HP + amt, -target.MAXHP, target.MAXHP);
if (!target.enemy)
{
Party.UpdateHUD();
}
if (amt >= 50000)
{
amt -= 50000;
for (int i = 0; i < current.party.Count; i++)
{
if (current.party[i] != target)
{
Coroutine.Start(Heal(current.party[i], amt, playParticles, doColor, showText, playSound: false));
}
}
}
if (!target.enemy && target.HP > 0 && flag)
{
target.entity.currentAnim = Entity.Animations.BattleIdle;
if (showText)
{
ShowFloatingText(Texts.common[125], target.entity.GlobalPosition, Main.colorGreen);
}
}
else if (target.HP >= target.MAXHP)
{
if (showText)
{
ShowFloatingText(Texts.common[126], target.entity.GlobalPosition, Main.colorGreen);
}
}
else if (showText)
{
ShowFloatingText(amt.ToString(), target.entity.GlobalPosition, Main.colorGreen);
}
if (doColor)
{
for (float a = 0f; a < 30f; a += Main.deltaTime)
{
target.entity.Modulate = Main.colorGreen.Lerp(Main.colorWhite, a / 30f);
yield return null;
}
}
}
public void DoDamage(Battlers attacker, Battlers target, float multiplier = 1f, bool miss = false, bool noTP = false, bool dontKill = false, bool showNumber = true, int? overrideDamage = null)
{
bool flag = !attacker.enemy && attacker.selectedAction != null && attacker.selectedAction[0] == 1 && Texts.skills[(Acts.IDs)attacker.selectedAction[2]].onlyOnExecutable;
Vector2 pos = target.entity.GlobalPosition + Vector2.Up * 16f * attacker.posID + Vector2.Left * Main.RandomRange(-16, 3);
int num = ((attacker.atkMod != null) ? attacker.atkMod[1] : 0);
int num2 = ((target.defMod != null) ? target.defMod[1] : 0);
int valueOrDefault = overrideDamage.GetValueOrDefault();
if (!overrideDamage.HasValue)
{
valueOrDefault = attacker.ATK;
overrideDamage = valueOrDefault;
}
int num3 = Mathf.Clamp(Mathf.RoundToInt((float)(overrideDamage.Value + num) * multiplier * (1f + Main.RandomRange(-0.1f, 0.1f))) - (target.DEF + num2), 0, 999);
Color value = Main.colorWhite;
string text = "";
target.hpLastTurn = target.HP;
if (!attacker.enemy)
{
value = Main.instance.partyColors[attacker.internalID];
if (!miss && !noTP)
{
TP = Mathf.Clamp(TP + Mathf.FloorToInt((float)num3 / 10f), 0, 100);
}
}
if (miss)
{
text = Texts.common[122];
}
else
{
target.entity.shake = 20f;
text = num3.ToString();
}
if (!miss)
{
Audio.PlaySound("snd_damage.wav");
target.HP = Mathf.Clamp(target.HP - num3, dontKill ? 1 : 0, target.MAXHP);
if (num3 > 0)
{
target.entity.currentAnim = Entity.Animations.Hurt;
}
Coroutine.Stop(target.animRoutine);
if (target.HP <= 0)
{
if (lastResult != EndState.Special)
{
if (flag)
{
fleeing.Add(Coroutine.Start(KillAnim(target)));
}
else if (target.callEventOnDefeat != Acts.IDs.None && (events == null || events.done))
{
events = Acts.DoActRoutine(target.callEventOnDefeat.ToString(), target, new Battlers[1] { attacker });
}
else if (!target.fleeing)
{
fleeing.Add(Coroutine.Start(Flee(target)));
}
}
else if (flag)
{
RemoveEnemy(target, EndState.Executed);
}
else
{
RemoveEnemy(target, EndState.Defeated);
}
}
else
{
target.animRoutine = Coroutine.Start(target.entity.DelayedAnim(30f, Entity.Animations.Idle));
}
}
if (showNumber)
{
ShowFloatingText(text, pos, value);
}
}
public static Control ShowFloatingText(string text, Vector2 pos, Color? color = null)
{
Color valueOrDefault = color.GetValueOrDefault();
if (!color.HasValue)
{
valueOrDefault = Main.colorWhite;
color = valueOrDefault;
}
Control control = GD.Load<PackedScene>("res://Objects/UI/DamageNumberDR.tscn").Instantiate<Control>(PackedScene.GenEditState.Disabled);
control.GetChild<RichTextLabel>(0).Text = text;
control.Modulate = color.Value;
if (current != null)
{
current.AddChild(control, forceReadableName: false, InternalMode.Disabled);
}
else if (Room.current != null)
{
Room.current.AddChild(control, forceReadableName: false, InternalMode.Disabled);
}
else
{
Main.instance.AddChild(control, forceReadableName: false, InternalMode.Disabled);
}
control.GlobalPosition = pos;
return control;
}
private void UpdateMenu(int mod = 0)
{
bool flag = extended.Contains(state);
DWMenu.instance.battleText.VisibleRatio = 99f;
DWMenu.instance.battleText2.Visible = flag;
DWMenu.instance.battleDesc.GetParent<Control>().Visible = flag;
DWMenu.instance.itemArrow.Visible = state == State.SelectItem && SaveFile.current.dwItems.Count > 6;
if (!flag)
{
tpPreview = 0;
}
switch (state)
{
case State.PlayerTurn:
DWMenu.instance.partyHUDs[currentActor].UpdateOpt(option);
soul.Visible = false;
DWMenu.instance.battleText.Text = Texts.battleMes[battleMes][lastMes].text;
if (!firstMes)
{
DWMenu.instance.battleText.VisibleRatio = 0f;
}
firstMes = true;
break;
case State.SelectTarget:
if (mod == 0 || mod == 2)
{
maxOption = ((mod == 2) ? party.Count : enemies.Count);
soul.Visible = true;
string text4 = "\t\t";
string text5 = "";
for (int l = 0; l < maxOption; l++)
{
if (mod == 2)
{
text4 += party[l].name;
text5 = text5 + GetTextBar(party[l].HPPercent()) + "[color=black].\t\t\n";
}
else
{
bool num = enemies[l].CanSpare();
if (num)
{
text4 += "[color=yellow]";
}
text4 += enemies[l].name;
if (num)
{
text4 += "[/color]";
}
text5 = text5 + GetTextBar(enemies[l].HPPercent()) + "\t\t";
if (!enemies[l].noMercy)
{
text5 = text5 + GetTextBar((float)enemies[l].spare / 100f, Main.colorYellow) + "\n";
}
}
text4 += "\n\t\t";
}
DWMenu.instance.battleText2.Text = text5;
DWMenu.instance.battleText2.VisibleCharacters = -1;
DWMenu.instance.battleText.Text = text4;
}
DWMenu.instance.battleText2.Visible = true;
soul.Position = new Vector2(-147f, 78 + option * 17);
break;
case State.SelectItem:
{
int num2 = ((option >= 6) ? 6 : 0);
string text6 = "";
string text7 = "";
for (int m = 0; m < 6 && m < SaveFile.current.dwItems.Count - num2; m++)
{
if (m % 2 == 0)
{
text6 = text6 + "\t\t" + Texts.items[SaveFile.current.dwItems[m + num2]].name + "\n";
}
else
{
text7 = text7 + "\t\t" + Texts.items[SaveFile.current.dwItems[m + num2]].name + "\n";
}
}
DWMenu.instance.itemArrow.FlipV = option >= 6;
DWMenu.instance.itemArrow.Position = new Vector2(DWMenu.instance.itemArrow.Position.X, (option >= 6) ? 12 : 44);
DWMenu.instance.battleText.Text = text6;
DWMenu.instance.battleText2.Text = text7;
DWMenu.instance.battleText2.VisibleCharacters = -1;
DWMenu.instance.battleText2.Visible = true;
maxOption = SaveFile.current.dwItems.Count;
DWMenu.instance.battleDesc.Text = "[color=gray]" + (Texts.items[SaveFile.current.dwItems[option]].shopDesc ?? Texts.items[SaveFile.current.dwItems[option]].shortDesc);
soul.Visible = true;
soul.Position = new Vector2(((option - num2) % 2 == 0) ? (-147) : (-41), 78 + Mathf.FloorToInt((float)(option - num2) / 2f) * 17);
break;
}
case State.SelectSkill:
case State.SelectAct:
if (mod == 0)
{
List<int> list = new List<int>(GetPossibleActs());
if (state == State.SelectAct)
{
for (int i = 0; i < enemies[allBattlers[currentActor].selectedAction[1]].acts.Count; i++)
{
Acts.IDs ds = enemies[allBattlers[currentActor].selectedAction[1]].acts[i];
if (CanUseAct(ds))
{
list.Add((int)ds);
}
}
}
possible = list.ToArray();
string text = "";
string text2 = "";
for (int j = 0; j < possible.Length; j++)
{
if (j % 2 == 0)
{
text = text + "\t\t" + Texts.skills[(Acts.IDs)possible[j]].name + "\n";
}
else
{
text2 = text2 + "\t\t" + Texts.skills[(Acts.IDs)possible[j]].name + "\n";
}
}
DWMenu.instance.battleText.Text = text;
DWMenu.instance.battleText2.Text = text2;
DWMenu.instance.battleText2.VisibleCharacters = -1;
DWMenu.instance.battleText2.Visible = true;
maxOption = possible.Length;
}
if (Texts.skills[(Acts.IDs)possible[option]].spAction)
{
string text3 = "";
for (int k = 0; k < enemies.Count; k++)
{
text3 = text3 + "* " + Texts.skills[enemies[k].acts[enemies[allBattlers[currentActor].selectedAction[1]].partyAction[0]]].name + "\n";
}
DWMenu.instance.battleDesc.Text = "[color=gray]" + text3;
}
else if (Texts.skills[(Acts.IDs)possible[option]].desc != null)
{
DWMenu.instance.battleDesc.Text = "[color=gray]" + Texts.skills[(Acts.IDs)possible[option]].desc;
if (Texts.skills[(Acts.IDs)possible[option]].TP > 0)
{
RichTextLabel battleDesc = DWMenu.instance.battleDesc;
battleDesc.Text = battleDesc.Text + "\n[color=#ED7117]" + Texts.skills[(Acts.IDs)possible[option]].TP + "% TP";
}
}
else
{
DWMenu.instance.battleDesc.Text = "";
}
soul.Visible = true;
soul.Position = new Vector2((option % 2 == 0) ? (-147) : (-41), 78 + Mathf.FloorToInt((float)option / 2f) * 17);
tpPreview = Texts.skills[(Acts.IDs)possible[option]].TP;
break;
case State.DoSpells:
case State.DoAttack:
case State.DoEnemy:
case State.EndTurn:
break;
}
}
}