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

829 lines
15 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/Entities/Entity.cs")]
public partial class Entity : CharacterBody2D
{
public enum IDs
{
None = -1,
Clover,
Kanako,
Martlet,
Ceroba,
Chujin,
Starlo,
Ed,
Mooch,
Moray,
Ace,
Dina,
Mo,
Axis,
June,
Melody,
Dalv,
TestEnemy,
Penceller,
Eraserhead,
Bearing,
Pennilton,
BellBoss,
Necklace,
Mopper,
Warden,
BackpackDarkner,
KeychainDarkner,
JacketDarkner,
MP3Darkner,
PenGuy,
UNUSED,
FoxBoss,
CarDarkner,
BBallDarkner,
ThumbtackDarkner,
CoinDarkner,
Decibat,
Virgil,
Kangaroo,
Cat,
Pyramid,
Mirror,
Scroll,
Fly,
PencilLizard,
AntKid,
TinfoilLizard,
HorseGirl,
DeerGirl,
TravellerM,
TravellerF,
RichGuy,
RichWoman,
Aunt,
Snake,
Cactus,
TechGuy,
Golem,
StarloBrother,
StarloDad,
StarloMom,
GreenBear,
RadDude,
Dunebud,
Horse,
PyramidBug,
Doctor,
BlueTriangle,
TallAntlerGirl,
BlueFire,
CursorMan,
IceCreamGuy,
DemonGuy,
Squid,
Bunny,
KidR,
KidB,
KidG,
MuscleGuy,
SadGirl,
SittingGuy,
MagmaBug,
CloakAntlerGirl,
CactusGirl,
FortuneTeller,
EyeballGuy,
MailWhale,
Gizmo,
Mocha,
Britz,
Violetta,
Rosa,
Pedla,
Conner,
Gearzerd,
Toaster,
Capacitor,
Stapler,
BigAxis,
Wrench,
RedLetter,
Batter,
BunBun,
Drill,
Toaster2,
LegoGreen,
LegoPink,
LegoBlue,
LegoOrange,
LegoBull,
KanakoPC,
RangerRed,
RangerGreen,
RangerBlue,
CameraMan,
Ruler,
BlueFireGuy,
MinerGF,
SmokerMiner,
HatMinerGuy,
GemMinerGuy,
HappyMinerGirl,
TeaBull,
MorayDad,
MorayMom,
SittingBunnyGuy,
ElevatorMinerGuy,
NervousGirl,
Blackjack
}
public enum Emoticons
{
Exclaim,
Question,
Dots
}
public enum Animations
{
Override = -2,
None,
Idle,
Walk,
Run,
Jumped,
ReadyJump,
JumpIn,
Fallen,
BattleStart,
Hurt,
BattleIdle,
Sweep,
BattleEnd,
AttackReady,
SkillReady,
SkillDo,
ActReady,
ActDo,
ItemReady,
ItemDo,
Defend,
KO,
Slide,
Sit,
Attack,
Back,
HandRaise,
Talk,
Elec,
Fainted,
Sleep,
Special
}
public enum Direction
{
South = 0,
North = 1,
East = 2,
West = 3,
Side = 4,
None = -1
}
public enum AnimMods
{
None,
DW,
Hat,
Talk,
DWTalk,
Counter
}
[Signal]
public delegate void AnimSignalEventHandler();
public partial class AutoMove
{
public Vector2[] pos;
public int current;
public float failsafe;
public float speed = 1f;
public bool doFacing = true;
public bool doFailsafe = true;
public bool dontTP;
public Animations moving = Animations.Walk;
public Animations stop;
public Direction dirAtEnd = Direction.None;
public const float maxFailsafe = 300f;
}
[Export(PropertyHint.None, "")]
public IDs id;
[Export(PropertyHint.None, "")]
public float baseSpeed = 64f;
[Export(PropertyHint.None, "")]
public bool asymmetrical;
[Export(PropertyHint.None, "")]
public bool singleDirection;
[Export(PropertyHint.None, "")]
public Direction direction;
[Export(PropertyHint.None, "")]
public bool doTrail;
[Export(PropertyHint.None, "")]
public bool skipFirstAnim;
[Export(PropertyHint.None, "")]
public AnimMods animMod;
[Export(PropertyHint.None, "")]
public Vector2 emoticonOffset = new Vector2(0f, -40f);
[Export(PropertyHint.None, "")]
private Array<Array<Variant>> texOverrides;
[Export(PropertyHint.None, "")]
public Array<Array<Variant>> replaceAnim = new Array<Array<Variant>>();
[Export(PropertyHint.None, "")]
public string talkOverride;
[Export(PropertyHint.None, "")]
public string idleOverride;
[Export(PropertyHint.None, "")]
public Animations currentAnim;
[Export(PropertyHint.None, "")]
private Vector2[] spriteSideOffset;
[Export(PropertyHint.None, "")]
public Node[] extras;
[ExportSubgroup("Components", "")]
[Export(PropertyHint.None, "")]
public AnimationPlayer anim;
[Export(PropertyHint.None, "")]
public Sprite2D sprite;
[Export(PropertyHint.None, "")]
public CollisionShape2D collider;
[Export(PropertyHint.None, "")]
public Area2D trigger;
public Node emoticonObj;
public Vector2 startPos;
public Battlers battleData;
public Animations oldAnim = Animations.None;
public float shake;
public float shakeIntensity = 5f;
private Sprite2D[] trail;
private int currentTrail;
private float trailCD;
public AutoMove moving;
private const float trailDelay = 2f;
private const float defaultShakeIntensity = 5f;
private const string noiseSound = "snd_wing_ch1.wav";
private static readonly HashSet<Animations> flippable = new HashSet<Animations>
{
Animations.Idle,
Animations.Walk,
Animations.Run,
Animations.Sit,
Animations.Talk
};
public static readonly System.Collections.Generic.Dictionary<Vector2, Direction> directions = new System.Collections.Generic.Dictionary<Vector2, Direction>
{
{
Vector2I.Up,
Direction.North
},
{
Vector2I.Down,
Direction.South
},
{
Vector2I.Left,
Direction.East
},
{
Vector2I.Right,
Direction.West
},
{
new Vector2I(1, -1),
Direction.North
},
{
new Vector2I(-1, -1),
Direction.North
},
{
new Vector2I(1, 1),
Direction.South
},
{
new Vector2I(-1, 1),
Direction.South
}
};
public override void _EnterTree()
{
TryUpdateComponents();
base.MotionMode = MotionModeEnum.Floating;
CallDeferred(MethodName.LateStart);
}
private void LateStart()
{
startPos = base.GlobalPosition;
}
public override void _Process(double delta)
{
DoAutoMove();
if (sprite != null)
{
if (shake > 0f || shake == -200f)
{
sprite.Position = Vector2.Right * Mathf.RoundToInt(Main.RandomRange(0f - shakeIntensity, shakeIntensity));
if (shake > 0f)
{
shake -= Main.deltaTime;
}
}
else if (shake > -50f)
{
sprite.Position = Vector2.Zero;
shake = -100f;
}
}
CallDeferred(MethodName.LateUpdate);
}
public void ShakeAnimChange(string anim, float time = 10f, float intensity = 1f, string sound = "snd_wing_ch1.wav")
{
this.anim.Play(anim);
Shake(time, intensity);
if (sound != null)
{
Audio.PlaySound(sound);
}
}
public void ShakeAnimChange(Animations anim, float time = 10f, float intensity = 1f, string sound = "snd_wing_ch1.wav")
{
currentAnim = anim;
Shake(time, intensity);
if (sound != null)
{
Audio.PlaySound(sound);
}
}
public void Shake(float time, float intensity = -1f)
{
shake = time;
if (intensity > 0f)
{
shakeIntensity = intensity;
}
else
{
shakeIntensity = 5f;
}
}
public Node Emoticon(Emoticons type, bool sound = false)
{
emoticonObj = Main.Particle("Emoticon" + type, base.GlobalPosition + emoticonOffset, 0, this, localSpace: false);
if (sound && type == Emoticons.Exclaim)
{
Audio.PlaySound("snd_b.wav");
}
return emoticonObj;
}
private void DoAutoMove()
{
if (moving == null)
{
return;
}
float num = base.GlobalPosition.DistanceTo(moving.pos[moving.current]);
if (num < 1.5f || (moving.doFailsafe && moving.failsafe >= 300f))
{
if (!moving.dontTP)
{
base.GlobalPosition = moving.pos[moving.current];
}
moving.current++;
moving.failsafe = 0f;
if (moving.current >= moving.pos.Length)
{
if (moving.stop != Animations.None)
{
currentAnim = moving.stop;
}
if (moving.dirAtEnd != Direction.None)
{
direction = moving.dirAtEnd;
UpdateAnim(force: true);
}
StopMoving();
}
}
else
{
Vector2 vector = base.GlobalPosition.DirectionTo(moving.pos[moving.current]);
base.Velocity = vector * moving.speed * baseSpeed * Mathf.Min(num / 5f, 1f);
if (moving.moving != Animations.None)
{
currentAnim = moving.moving;
}
if (moving.doFailsafe)
{
moving.failsafe += Main.deltaTime;
}
if (moving.doFacing)
{
LookAt(moving.pos[moving.current]);
}
}
}
public void TryUpdateComponents(bool force = false)
{
for (int i = 0; i < 4; i++)
{
Node child = GetChild(i);
if ((force || !GodotObject.IsInstanceValid(anim)) && child is AnimationPlayer animationPlayer)
{
anim = animationPlayer;
}
else if ((force || !GodotObject.IsInstanceValid(sprite)) && child is Sprite2D sprite2D)
{
sprite = sprite2D;
}
else if ((force || !GodotObject.IsInstanceValid(collider)) && child is CollisionShape2D collisionShape2D)
{
collider = collisionShape2D;
}
else if ((force || !GodotObject.IsInstanceValid(trigger)) && child is Area2D area2D)
{
trigger = area2D;
}
}
}
public void ClearTrailObjs()
{
if (trail != null)
{
for (int i = 0; i < trail.Length; i++)
{
trail[i].QueueFree();
}
trail = null;
}
}
public void ChangeDirection(Direction dir)
{
direction = dir;
UpdateAnim(force: true);
}
public void DoAutoMove(Vector2[] target, float speed = 1f, Animations moveAnim = Animations.Walk, Animations stopAnim = Animations.Idle)
{
moving = new AutoMove
{
pos = target,
speed = speed,
moving = moveAnim,
stop = stopAnim
};
}
public void DoAutoAlign(Vector2 pos, float speed = 1f, Animations moveAnim = Animations.Walk, Animations stopAnim = Animations.Idle)
{
Vector2[] array = new Vector2[2];
if (Common.Distance(pos.X, base.GlobalPosition.X) < Common.Distance(pos.Y, base.GlobalPosition.Y))
{
array[0] = new Vector2(pos.X, base.GlobalPosition.Y);
}
else
{
array[0] = new Vector2(base.GlobalPosition.X, pos.Y);
}
array[1] = pos;
DoAutoMove(array, speed, moveAnim, stopAnim);
}
public void DoAutoMove(Vector2 target, float speed = 1f, Animations moveAnim = Animations.Walk, Animations stopAnim = Animations.Idle)
{
DoAutoMove(new Vector2[1] { target }, speed, moveAnim, stopAnim);
}
public void ChangeMod(int mod)
{
animMod = (AnimMods)mod;
}
private void UpdateTrail()
{
if (doTrail && trail == null)
{
trail = new Sprite2D[3];
for (int i = 0; i < trail.Length; i++)
{
AddChild(trail[i] = new Sprite2D
{
Name = "Trail" + i,
Visible = false,
TopLevel = true
}, forceReadableName: false, InternalMode.Disabled);
}
}
if (trailCD > 0f)
{
trailCD -= 1f;
}
else if (trailCD > -50f)
{
if (doTrail)
{
trail[currentTrail].Visible = true;
trail[currentTrail].Texture = sprite.Texture;
trail[currentTrail].Hframes = sprite.Hframes;
trail[currentTrail].Vframes = sprite.Vframes;
trail[currentTrail].FlipH = sprite.FlipH;
trail[currentTrail].Frame = sprite.Frame;
trail[currentTrail].Offset = sprite.Offset;
trail[currentTrail].SelfModulate = Main.colorTransparent;
trail[currentTrail].GlobalPosition = sprite.GlobalPosition;
trail[currentTrail].ZIndex = 3000;
trail[currentTrail].RegionEnabled = sprite.RegionEnabled;
trail[currentTrail].RegionRect = sprite.RegionRect;
currentTrail++;
if (currentTrail >= trail.Length)
{
currentTrail = 0;
}
trailCD = 2f;
}
else if (trail != null)
{
for (int j = 0; j < trail.Length; j++)
{
trail[j].Visible = false;
}
trailCD = -100f;
}
}
else if (doTrail)
{
trailCD = 0f;
}
}
public override void _PhysicsProcess(double delta)
{
if (base.Velocity != Vector2.Zero)
{
MoveAndSlide();
}
}
public virtual void LateUpdate()
{
UpdateAnim();
UpdateTrail();
}
public void UpdateAnim(bool force = false)
{
if (sprite == null || anim == null || currentAnim == Animations.Override)
{
return;
}
if (skipFirstAnim)
{
skipFirstAnim = false;
oldAnim = currentAnim;
}
else
{
if (!force && currentAnim == oldAnim)
{
return;
}
oldAnim = currentAnim;
StringBuilder stringBuilder = new StringBuilder("");
if (currentAnim == Animations.Idle)
{
string text = idleOverride;
if (text != null && text.Length > 0)
{
anim.Play(idleOverride);
return;
}
}
if (BattleDR.current == null)
{
if (flippable.Contains(currentAnim))
{
if (singleDirection)
{
sprite.FlipH = direction == Direction.West;
}
else if (!asymmetrical && (direction == Direction.East || direction == Direction.West))
{
stringBuilder.Append("Side");
sprite.FlipH = direction == Direction.West;
}
else
{
stringBuilder.Append(direction.ToString());
sprite.FlipH = false;
}
}
else
{
sprite.FlipH = false;
}
}
Vector2[] array = spriteSideOffset;
if (array != null && array.Length != 0)
{
sprite.Position = spriteSideOffset[sprite.FlipH ? 1u : 0u];
}
stringBuilder.Append(currentAnim.ToString());
Array<Array<Variant>> array2 = replaceAnim;
if (array2 != null && array2.Count > 0)
{
string c = stringBuilder.ToString();
Array<Variant> array3 = replaceAnim.FirstOrDefault((Array<Variant> x) => (string)x[0] == c);
if (array3 != null)
{
anim.Play((string)array3[1]);
return;
}
}
if (animMod != AnimMods.None && currentAnim < Animations.Run)
{
stringBuilder.Append(animMod.ToString());
}
StringName name = stringBuilder.ToString();
if (anim.HasAnimation(name))
{
anim.Play(name);
}
}
}
public void LookAt(Direction pos, bool forceAnimUpdate = false)
{
switch (pos)
{
case Direction.North:
LookAt(Vector2.Up, forceAnimUpdate);
break;
case Direction.South:
LookAt(Vector2.Down, forceAnimUpdate);
break;
case Direction.West:
LookAt(Vector2.Right, forceAnimUpdate);
break;
case Direction.East:
LookAt(Vector2.Left, forceAnimUpdate);
break;
}
}
public void LookAt(Vector2 pos, bool forceAnimUpdate = false)
{
if (pos == Vector2.Down || pos == Vector2.Left || pos == Vector2.Right || pos == Vector2.Up)
{
pos += base.GlobalPosition;
forceAnimUpdate = true;
}
Direction num = direction;
if (singleDirection)
{
if (pos.X > base.GlobalPosition.X)
{
direction = Direction.West;
}
else
{
direction = Direction.East;
}
}
else
{
Vector2 key = base.GlobalPosition.DirectionTo(pos).Snapped(Vector2.One);
direction = directions[key];
}
if (num != direction || forceAnimUpdate)
{
UpdateAnim(force: true);
}
}
public IEnumerator DelayedAnim(float waitTime, Animations anim, bool tempChange = false)
{
Animations c = currentAnim;
if (tempChange)
{
currentAnim = anim;
}
for (float a = 0f; a < waitTime; a += Main.deltaTime)
{
yield return null;
}
if (tempChange)
{
currentAnim = c;
}
else
{
currentAnim = anim;
}
}
public void StopMoving(Animations anim = Animations.None)
{
base.Velocity = Vector2.Zero;
if (moving != null)
{
moving = null;
}
if (anim != Animations.None)
{
currentAnim = anim;
}
}
public IEnumerator Slide(Vector2 direction, float frameTime, float speed = 1f, bool useSprite = false)
{
for (float a = 0f; a < frameTime; a += Main.deltaTime)
{
if (useSprite)
{
sprite.Position += direction * speed * Main.deltaTime;
}
else
{
base.Position += direction * speed * Main.deltaTime;
}
yield return null;
}
}
}