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

794 lines
19 KiB
C#

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Godot;
using Godot.Collections;
public partial class Party
{
public enum IDs
{
Clover,
Kanako,
Axis,
June,
Steph
}
public static int LWHP = 20;
public static int LWMHP = 20;
public static int LWAtk = 5;
public static int LWDef = 0;
public static List<Battlers> party = new List<Battlers>();
public static Battlers[] partyDefault;
private static readonly Vector2[] checkDir = new Vector2[4]
{
Vector2.Up,
Vector2.Down,
Vector2.Left,
Vector2.Right
};
private static readonly System.Collections.Generic.Dictionary<SaveFile.Flags, Entity.IDs> followers = new System.Collections.Generic.Dictionary<SaveFile.Flags, Entity.IDs>
{
{
SaveFile.Flags.KanakoFollowing,
Entity.IDs.Kanako
},
{
SaveFile.Flags.AxisFollowing,
Entity.IDs.Axis
},
{
SaveFile.Flags.StephFollowing,
Entity.IDs.Melody
},
{
SaveFile.Flags.JuneFollowing,
Entity.IDs.June
}
};
private static readonly Script followerScript = GD.Load<Script>("res://Scripts/Entities/Follower.cs");
public static void SetUp()
{
party.Clear();
party.Add(new Battlers
{
HP = 70,
MAXHP = 70,
ATK = 60,
DEF = 0,
LV = 1,
name = "COLE",
id = Entity.IDs.Clover,
internalID = 0,
hitPart = "ShootHit",
splitPart = "SplitPart1",
atkPartOffset = new Vector2(16f, -16f),
acts = new Array<Acts.IDs>
{
Acts.IDs.Check,
Acts.IDs.Apprehend,
Acts.IDs.NonLethalShot
},
EQUIP = new int[3] { 3, -1, -1 },
weaponIcon = GD.Load<Texture2D>("res://Sprites/Menus/Menu Sprites/WeaponGun.tres")
});
party.Add(new Battlers
{
HP = 80,
MAXHP = 80,
ATK = 65,
DEF = 0,
LV = 1,
name = "KANAKO",
id = Entity.IDs.Kanako,
doMagicMenu = true,
splitPart = "SplitPart2",
internalID = 1,
title = 1,
MAGIC = 4,
partyFlag = SaveFile.Flags.KanakoFollowing,
atkPartOffset = new Vector2(32f, -16f),
acts = new Array<Acts.IDs>
{
Acts.IDs.KAction,
Acts.IDs.HealBell,
Acts.IDs.ExecutionerBlow,
Acts.IDs.ShieldBarrier,
Acts.IDs.Foxfire,
Acts.IDs.Homerun
},
EQUIP = new int[3] { 2, -1, -1 },
weaponIcon = GD.Load<Texture2D>("res://Sprites/Menus/Menu Sprites/WeaponKanabo.tres")
});
party.Add(new Battlers
{
name = "AXIS",
id = Entity.IDs.Axis,
internalID = 2,
LV = 1,
EQUIP = new int[3] { 24, -1, -1 },
title = 2,
HP = 120,
MAXHP = 120,
ATK = 50,
DEF = 10,
weaponIcon = GD.Load<Texture2D>("res://Sprites/Menus/Menu Sprites/WeaponGlove.tres"),
atkPartOffset = new Vector2(26f, -20f),
partyFlag = SaveFile.Flags.AxisFollowing,
doMagicMenu = true,
acts = new Array<Acts.IDs>
{
Acts.IDs.AAction,
Acts.IDs.HeatWave,
Acts.IDs.HealShower,
Acts.IDs.AxisAtkUP,
Acts.IDs.UnnerveGas,
Acts.IDs.AxisSiren
}
});
party.Add(new Battlers
{
name = "SADIE",
id = Entity.IDs.June,
doMagicMenu = true,
internalID = 3,
LV = 3,
MAGIC = 7,
EQUIP = new int[3] { -1, -1, -1 },
title = 1,
partyFlag = SaveFile.Flags.JuneFollowing,
acts = new Array<Acts.IDs>
{
Acts.IDs.HealingSonata,
Acts.IDs.StranglingThreads
}
});
party.Add(new Battlers
{
name = "MELODY",
id = Entity.IDs.Melody,
LV = 1,
internalID = 4,
EQUIP = new int[3] { -1, -1, -1 },
partyFlag = SaveFile.Flags.StephFollowing,
acts = new Array<Acts.IDs>
{
Acts.IDs.Check,
Acts.IDs.MelodyDance
}
});
partyDefault = new Battlers[party.Count];
for (int i = 0; i < party.Count; i++)
{
partyDefault[i] = (Battlers)party[i].Duplicate();
partyDefault[i].MAGIC = party[i].MAGIC;
}
}
public static void UpdateNames()
{
for (int i = 0; i < party.Count; i++)
{
party[i].name = Texts.common[28 + i].ToUpper();
}
}
public static Vector2[] GetPosFromNode(Node2D node)
{
List<Vector2> list = new List<Vector2> { node.GlobalPosition };
for (int i = 0; i < node.GetChildCount(); i++)
{
if (node.GetChild(i) is Node2D node2D)
{
list.Add(node2D.GlobalPosition);
}
}
return list.ToArray();
}
public static void MoveTo(Vector2[] pos, float spd = 1f, bool align = false, Entity.Direction endDir = Entity.Direction.None)
{
if (align)
{
Player.instance.DoAutoAlign(pos[0], spd);
}
else
{
Player.instance.DoAutoMove(pos[0], spd);
}
if (endDir != Entity.Direction.None)
{
Player.instance.moving.dirAtEnd = endDir;
}
for (int i = 0; i < Player.instance.followers.Count && i + 1 < pos.Length; i++)
{
if (align)
{
Player.instance.followers[i].DoAutoAlign(pos[i + 1], spd);
}
else
{
Player.instance.followers[i].DoAutoMove(pos[i + 1], spd);
}
if (endDir != Entity.Direction.None)
{
Player.instance.followers[i].moving.dirAtEnd = endDir;
}
}
}
public static void UpdateAnim(string anim)
{
for (int i = 0; i < Player.instance.followers.Count; i++)
{
Player.instance.followers[i].anim.Play(anim);
}
Player.instance.anim.Play(anim);
}
public static void UpdateAnim()
{
for (int i = 0; i < Player.instance.followers.Count; i++)
{
Player.instance.followers[i].UpdateAnim(force: true);
}
Player.instance.UpdateAnim(force: true);
}
public static int GetIframes()
{
int num = 0;
for (int i = 0; i < SaveFile.current.activeParty.Count; i++)
{
for (int j = 0; j < 3; j++)
{
if (party[SaveFile.current.activeParty[i]].EQUIP[j] > -1)
{
num += Texts.items[(Items.IDs)party[SaveFile.current.activeParty[i]].EQUIP[j]].iframes;
}
}
}
return num;
}
public static Vector2[] GetPositions()
{
List<Vector2> list = new List<Vector2> { Player.instance.GlobalPosition };
for (int i = 0; i < Player.instance.followers.Count; i++)
{
list.Add(Player.instance.followers[i].GlobalPosition);
}
return list.ToArray();
}
public static void LookAt(Entity.Direction direction)
{
for (int i = 0; i < Player.instance.followers.Count; i++)
{
Player.instance.followers[i].direction = direction;
Player.instance.followers[i].UpdateAnim(force: true);
}
Player.instance.direction = direction;
Player.instance.UpdateAnim(force: true);
}
public static void MoveAndSlide(bool delayed = false)
{
if (delayed)
{
Coroutine.Start(DelayedSlide());
return;
}
UpdateFollowerEntities();
for (int i = 0; i < SaveFile.current.activeParty.Count; i++)
{
party[SaveFile.current.activeParty[i]].oEntity.MoveAndSlide();
}
}
private static IEnumerator DelayedSlide(float delay = 1f)
{
for (float a = 0f; a < delay; a += Main.deltaTime)
{
yield return null;
}
MoveAndSlide();
}
public static void CheckColliders()
{
UpdateFollowerEntities();
for (int i = 0; i < SaveFile.current.activeParty.Count; i++)
{
Common.RayCast rayCast = Common.DoRaycast(party[SaveFile.current.activeParty[i]].oEntity.GlobalPosition, 524289u);
if (rayCast?.obj != null)
{
GD.Print(i + " - " + rayCast.obj.Name);
uint collisionLayer = party[SaveFile.current.activeParty[i]].oEntity.CollisionLayer;
party[SaveFile.current.activeParty[i]].oEntity.CollisionLayer = 1u;
party[SaveFile.current.activeParty[i]].oEntity.MoveAndSlide();
party[SaveFile.current.activeParty[i]].oEntity.CollisionLayer = collisionLayer;
}
}
}
public static void LookAt(Vector2 pos)
{
for (int i = 0; i < Player.instance.followers.Count; i++)
{
Player.instance.followers[i].LookAt(pos);
}
Player.instance.LookAt(pos);
}
public static void Emoticon(Entity.Emoticons emoticon, bool noise = false)
{
for (int i = 0; i < Player.instance.followers.Count; i++)
{
Player.instance.followers[i].Emoticon(emoticon);
}
Player.instance.Emoticon(emoticon, noise);
}
public static void SortingOrder(int z)
{
for (int i = 0; i < Player.instance.followers.Count; i++)
{
Player.instance.followers[i].ZIndex = z;
}
Player.instance.ZIndex = z;
}
public static bool IsStopped()
{
for (int i = 0; i < Player.instance.followers.Count; i++)
{
if (Player.instance.followers[i].moving != null)
{
return false;
}
}
return Player.instance.moving == null;
}
public static void ChangeCollider(bool state)
{
Player.instance.collider.Disabled = !state;
for (int i = 0; i < Player.instance.followers.Count; i++)
{
Player.instance.followers[i].collider.Disabled = !state;
}
}
public static void AddBonus()
{
for (int i = 0; i < SaveFile.current.activeParty.Count; i++)
{
party[SaveFile.current.activeParty[i]].AddBonus();
}
UpdateStats();
}
public static int[] StatPreview(int partyIndex, Items.IDs id, int replaceSlot)
{
int[] array = new int[3]
{
partyDefault[partyIndex].ATK + party[partyIndex].ATKBONUS,
partyDefault[partyIndex].DEF + party[partyIndex].DEFBONUS,
partyDefault[partyIndex].MAGIC
};
for (int i = 0; i < 3; i++)
{
if (i == replaceSlot)
{
array[0] += Texts.items[id].atk;
array[1] += Texts.items[id].def;
array[2] += Texts.items[id].magic;
}
else if (party[partyIndex].EQUIP[i] > 0)
{
array[0] += Texts.items[(Items.IDs)party[partyIndex].EQUIP[i]].atk;
array[1] += Texts.items[(Items.IDs)party[partyIndex].EQUIP[i]].def;
array[2] += Texts.items[(Items.IDs)party[partyIndex].EQUIP[i]].magic;
}
}
return array;
}
public static void UpdateStats()
{
for (int i = 0; i < party.Count; i++)
{
party[i].ATK = partyDefault[i].ATK + party[i].ATKBONUS;
party[i].DEF = partyDefault[i].DEF + party[i].DEFBONUS;
party[i].MAXHP = partyDefault[i].MAXHP + party[i].HPBONUS;
party[i].MAGIC = partyDefault[i].MAGIC;
for (int j = 0; j < 3; j++)
{
if (party[i].EQUIP[j] > 0)
{
party[i].ATK += Texts.items[(Items.IDs)party[i].EQUIP[j]].atk;
party[i].DEF += Texts.items[(Items.IDs)party[i].EQUIP[j]].def;
if (party[i].doMagicMenu)
{
party[i].MAGIC += Texts.items[(Items.IDs)party[i].EQUIP[j]].magic;
}
}
}
}
}
public static void DeleteFollowers()
{
for (int i = 0; i < Player.instance.followers.Count; i++)
{
Player.instance.followers[i].QueueFree();
}
Player.instance.followers.Clear();
}
public static bool Remove(int id, bool updateFollowers = true)
{
UpdateFollowerEntities();
if (SaveFile.current.activeParty.Contains(id))
{
if (updateFollowers)
{
for (int i = 0; i < Player.instance.followers.Count; i++)
{
if (Player.instance.followers[i] == party[id].oEntity)
{
Player.instance.followers[i].QueueFree();
Player.instance.followers.RemoveAt(i);
}
}
}
SaveFile.current.activeParty.Remove(id);
SaveFile.current.flags.Remove(party[id].partyFlag);
return true;
}
return false;
}
public static void TeleportFollowers()
{
Player.instance.ResetFollowStep();
for (int i = 0; i < Player.instance.followers.Count; i++)
{
Player.instance.followers[i].GlobalPosition = Player.instance.GlobalPosition + Vector2.Up;
}
}
public static void UpdateHUD(bool resetPos = true)
{
for (int i = 0; i < party.Count; i++)
{
DWMenu.instance.partyHUDs[i].Visible = i < SaveFile.current.activeParty.Count();
if (SaveFile.current.activeParty.Count <= 3)
{
DWMenu.instance.partyHUDs[i].Position = new Vector2(PartyHUD.pPos[SaveFile.current.activeParty.Count() - 1][i], DWMenu.instance.partyHUDs[i].Position.Y);
}
if (resetPos)
{
DWMenu.instance.partyHUDs[i].Position = new Vector2(DWMenu.instance.partyHUDs[i].Position.X, 0f);
}
DWMenu.instance.partyHUDs[i].Update();
}
}
public static void ShowBattleCommands(int current)
{
for (int i = 0; i < SaveFile.current.activeParty.Count; i++)
{
DWMenu.instance.partyHUDs[i].Position = new Vector2(DWMenu.instance.partyHUDs[i].Position.X, Mathf.Lerp(DWMenu.instance.partyHUDs[i].Position.Y, (current == i) ? (-21) : 0, 0.2f));
}
}
public static void UpdateFollowerEntities()
{
for (int i = 0; i < SaveFile.current.activeParty.Count; i++)
{
party[SaveFile.current.activeParty[i]].oEntity = GetOWEntityByIndex(i);
}
}
public static Entity GetOWEntityByIndex(int entityIndex)
{
if (Player.instance == null)
{
return null;
}
if (entityIndex == 0)
{
return Player.instance;
}
if (entityIndex <= Player.instance.followers.Count)
{
return Player.instance.followers[entityIndex - 1];
}
return null;
}
public static Entity GetOWEntityByID(Entity.IDs id)
{
UpdateFollowerIDs();
if (id == Player.instance.id)
{
return Player.instance;
}
for (int i = 0; i < Player.instance.followers.Count; i++)
{
if (Player.instance.followers[i].id == id)
{
return Player.instance.followers[i];
}
}
return null;
}
public static void PlaySplitParticle(Entity entity)
{
for (int i = 0; i < party.Count; i++)
{
if (party[i].id == entity.id)
{
Main.Particle(party[i].splitPart, Vector2.Up * 16f, 1, entity);
Audio.PlaySound("snd_break2.wav");
break;
}
}
}
public static void UpdateFollowerIDs()
{
if (Player.instance != null)
{
for (int i = 0; i < Player.instance.followers.Count; i++)
{
Player.instance.followers[i].id = party[SaveFile.current.activeParty[i + 1]].id;
party[SaveFile.current.activeParty[i + 1]].entity = Player.instance.followers[i];
}
}
}
public static bool HasMembers(List<IDs> ids, bool checkAlive = false)
{
for (int i = 0; i < ids.Count; i++)
{
if (!SaveFile.current.activeParty.Contains((int)ids[i]))
{
return false;
}
if (checkAlive && party[(int)ids[i]].HP <= 0)
{
return false;
}
}
return true;
}
public static int AlivePartyAmount()
{
int num = 0;
for (int i = 0; i < SaveFile.current.activeParty.Count; i++)
{
if (party[SaveFile.current.activeParty[i]].HP > 0)
{
num++;
}
}
return num;
}
public static void ReviveAll(bool fullHP)
{
for (int i = 0; i < party.Count; i++)
{
if (party[i].HP <= 0)
{
if (fullHP)
{
party[i].HP = party[i].MAXHP;
}
else
{
party[i].HP = 1;
}
}
}
}
public static void ChangeHP(int amt)
{
for (int i = 0; i < party.Count; i++)
{
party[i].HP += amt;
}
}
public static void Reparent(Node node)
{
for (int i = 0; i < Player.instance.followers.Count; i++)
{
Player.instance.followers[i].Reparent(node);
}
Player.instance.Reparent(node);
}
public static void StopMoving(bool idleAnim = true)
{
Player.instance.StopMoving((!idleAnim) ? Entity.Animations.None : Entity.Animations.Idle);
for (int i = 0; i < Player.instance.followers.Count; i++)
{
Player.instance.followers[i].StopMoving((!idleAnim) ? Entity.Animations.None : Entity.Animations.Idle);
}
}
public static void SetPosition(Node2D node)
{
Player.instance.GlobalPosition = node.GlobalPosition;
for (int i = 0; i < Player.instance.followers.Count && i < node.GetChildCount(); i++)
{
Player.instance.followers[i].GlobalPosition = node.GetChild<Node2D>(i).GlobalPosition;
}
}
public static void SetPosition(in Vector2[] pos)
{
Player.instance.GlobalPosition = pos[0];
for (int i = 0; i < Player.instance.followers.Count && i + 1 < pos.Length; i++)
{
Player.instance.followers[i].GlobalPosition = pos[i + 1];
}
}
public static void SetPosition(in Vector2 pos)
{
Player.instance.GlobalPosition = pos;
for (int i = 0; i < Player.instance.followers.Count; i++)
{
Player.instance.followers[i].GlobalPosition = pos + Vector2.Up * 0.01f;
}
}
public static void Heal(bool playSound = true, bool doParticle = false)
{
for (int i = 0; i < party.Count; i++)
{
party[i].HP = party[i].MAXHP;
}
if (playSound)
{
Audio.PlaySound("snd_power.wav");
}
UpdateHUD();
}
public static void AnimMod(Entity.AnimMods a)
{
Player.instance.animMod = a;
Player.instance.UpdateAnim(force: true);
for (int i = 0; i < Player.instance.followers.Count; i++)
{
Player.instance.followers[i].animMod = a;
Player.instance.followers[i].UpdateAnim(force: true);
}
}
public static List<int[]> GetPartyStats()
{
List<int[]> list = new List<int[]>();
for (int i = 0; i < party.Count; i++)
{
list.Add(new int[10]
{
party[i].HP,
party[i].MAXHP,
party[i].ATKBONUS,
party[i].DEFBONUS,
party[i].LV,
party[i].EQUIP[0],
party[i].EQUIP[1],
party[i].EQUIP[2],
party[i].title,
party[i].HPBONUS
});
}
return list;
}
public static void AddNPCFollower(Entity entity, bool npc = true)
{
Entity.IDs id = entity.id;
entity.ClearTrailObjs();
entity.CallDeferred("_enter_tree");
entity.CallDeferred("ChangeMod", (int)entity.animMod);
entity.CallDeferred("TryUpdateComponents", true);
ulong instanceId = entity.GetInstanceId();
entity.SetScript(followerScript);
Array<Array<Variant>> replaceAnim = entity.replaceAnim.Duplicate();
bool asymmetrical = entity.asymmetrical;
Follower follower = (Follower)GodotObject.InstanceFromId(instanceId);
if (!npc)
{
follower.followIndex = SaveFile.current.activeParty.Count - 2;
}
else
{
follower.followIndex = SaveFile.current.activeParty.Count + (SaveFile.current.followers.Count - 2);
}
follower.replaceAnim = replaceAnim;
follower.asymmetrical = asymmetrical;
follower.TryUpdateComponents(force: true);
follower.id = id;
Player.instance?.ResetFollowStep();
}
public static void AddFollower(Entity entity)
{
for (int i = 0; i < party.Count; i++)
{
if (party[i].id == entity.id)
{
SaveFile.current.activeParty.Add(i);
AddNPCFollower(entity, npc: false);
SaveFile.AddFlag(party[i].partyFlag);
return;
}
}
AddNPCFollower(entity);
}
public static void AddFollower(IDs id, bool updateEntities = true, bool spawnInvisible = false)
{
if (!SaveFile.current.activeParty.Contains((int)id))
{
SaveFile.current.activeParty.Add((int)id);
SaveFile.AddFlag(party[(int)id].partyFlag);
if (updateEntities)
{
SpawnFollowers(spawnInvisible);
}
}
}
public static void SpawnFollowers(bool spawnInvisible = false)
{
Player.instance.ResetFollowStep();
int num = 0;
foreach (SaveFile.Flags f in followers.Keys)
{
if (SaveFile.current.flags.Contains(f) && Player.instance.followers.FirstOrDefault((Follower x) => x.id == followers[f]) == null)
{
Entity entity;
Room.current.CallDeferred("add_child", entity = GD.Load<PackedScene>("res://Objects/Characters/" + followers[f].ToString() + ".tscn").Instantiate<Entity>(PackedScene.GenEditState.Disabled));
if (spawnInvisible)
{
entity.Visible = false;
}
ulong instanceId = entity.GetInstanceId();
Array<Array<Variant>> replaceAnim = entity.replaceAnim.Duplicate();
bool asymmetrical = entity.asymmetrical;
entity.SetScript(followerScript);
Follower obj = (Follower)GodotObject.InstanceFromId(instanceId);
obj.TryUpdateComponents(force: true);
obj.replaceAnim = replaceAnim;
obj.followIndex = num;
obj.asymmetrical = asymmetrical;
obj.id = followers[f];
num++;
}
}
}
}