LADXHD/InGame/GameObjects/NPCs/ObjLinkFishing.cs
2023-12-14 17:21:22 -05:00

296 lines
11 KiB
C#

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using ProjectZ.Base;
using ProjectZ.InGame.Controls;
using ProjectZ.InGame.GameObjects.Base;
using ProjectZ.InGame.GameObjects.Base.CObjects;
using ProjectZ.InGame.GameObjects.Base.Components;
using ProjectZ.InGame.GameObjects.Things;
using ProjectZ.InGame.GameSystems;
using ProjectZ.InGame.Map;
using ProjectZ.InGame.SaveLoad;
using ProjectZ.InGame.Things;
namespace ProjectZ.InGame.GameObjects.NPCs
{
internal class ObjLinkFishing : GameObject
{
public static ObjFish HookedFish;
public static Vector2 HookPosition;
public static bool HasFish;
private readonly CSprite _sprite;
private readonly Animator _animator;
private readonly Rectangle _hookSource = new Rectangle(384, 210, 16, 13);
private readonly Rectangle _hookSourceHooked = new Rectangle(389, 211, 8, 8);
private readonly Vector2 _hookStartPosition = new Vector2(117, 40);
private Vector2 _hookVelocity;
private int _fishCount;
private bool _isFishing;
private bool _isTransitioning;
private bool _wasInWater;
private bool _pulledOut;
public ObjLinkFishing(Map.Map map, int posX, int posY) : base(map)
{
SprEditorImage = Resources.SprLink;
EditorIconSource = new Rectangle(313, 133, 25, 16);
_animator = AnimatorSaveLoad.LoadAnimator("link fishing");
_animator.Play("idle");
EntityPosition = new CPosition(posX + 8, posY + 16, 0);
EntitySize = new Rectangle(-8, -16, 16, 16);
HookedFish = null;
HookPosition = _hookStartPosition;
HasFish = false;
Game1.GameManager.SaveManager.SetString("leavePond", "no");
Game1.GameManager.SaveManager.SetString("emptyPond", "0");
// set camera target position
map.CameraTarget = new Vector2(80, 64);
MapManager.ObjLink.NextMapPositionStart = map.CameraTarget;
MapManager.ObjLink.NextMapPositionEnd = map.CameraTarget;
MapManager.ObjLink.TransitionInWalking = false;
_sprite = new CSprite(EntityPosition);
var animationComponent = new AnimationComponent(_animator, _sprite, new Vector2(-18, -16));
AddComponent(BaseAnimationComponent.Index, animationComponent);
AddComponent(UpdateComponent.Index, new UpdateComponent(Update));
AddComponent(DrawComponent.Index, new DrawComponent(Draw, Values.LayerPlayer, EntityPosition));
AddComponent(KeyChangeListenerComponent.Index, new KeyChangeListenerComponent(KeyChanged));
}
public override void Init()
{
var marin = MapManager.ObjLink.GetMarin();
if (marin != null)
marin.IsHidden = true;
}
private void Update()
{
// hide the real player
MapManager.ObjLink.UpdatePlayer = false;
MapManager.ObjLink.IsVisible = false;
var direction = new Vector2(122, 38) - HookPosition;
if (!_isFishing)
{
// start hook throw animation
if (ControlHandler.ButtonPressed(CButtons.A))
{
_animator.Play("throw");
}
// set the hook position to the animation
if (_animator.IsPlaying && _animator.CurrentAnimation.Id == "throw" && _animator.CurrentFrameIndex <= 5)
{
HookPosition = EntityPosition.Position + new Vector2(-18, -16) + new Vector2(
_animator.CollisionRectangle.X, _animator.CollisionRectangle.Y);
}
// throw hook
if (_animator.CurrentFrameIndex == 5)
{
Game1.GameManager.PlaySoundEffect("D360-08-08");
_hookVelocity = new Vector2(-2.0f, -1f);
_isFishing = true;
HasFish = false;
}
}
if (_isFishing)
{
if (!_pulledOut)
{
if (!_animator.IsPlaying)
{
_animator.Play(HookedFish == null ? "idle" : "hooked");
}
if (ControlHandler.ButtonPressed(CButtons.A))
{
_animator.Play(HookedFish == null ? "pull_right" : "hooked_pull");
if (!(HasFish && HookedFish == null) && direction.Length() <= 4)
{
PulledInHook();
return;
}
// pull in the hook
if (direction != Vector2.Zero)
direction.Normalize();
_hookVelocity = direction * 2.0f;
}
}
if (_pulledOut)
{
if (!_animator.IsPlaying)
{
// show victory message
Game1.GameManager.StartDialogPath(HookedFish.DialogName);
ResetFishing();
// remove the fish from the map
Map.Objects.DeleteObjects.Add(HookedFish);
HookedFish = null;
}
}
// not fish hooked
else if (HookedFish == null)
{
// pull the hook up
if (HookPosition.Y >= 40 && ControlHandler.ButtonPressed(CButtons.Right))
{
_animator.Play("pull_up");
_hookVelocity = new Vector2(0, -2.0f);
}
// hook is in the air?
if (HookPosition.Y < 32)
{
_hookVelocity *= (float)Math.Pow(0.99, Game1.TimeMultiplier);
_hookVelocity.Y += 0.035f * Game1.TimeMultiplier;
}
else
{
_hookVelocity *= (float)Math.Pow(0.75, Game1.TimeMultiplier);
_hookVelocity.Y += 0.05f * Game1.TimeMultiplier;
if (!_wasInWater)
{
_wasInWater = true;
var splashAnimator = new ObjAnimator(Map, 0, 0, 0, 36, 0, "Particles/fishingSplash", "idle", true);
splashAnimator.EntityPosition.Set(new Vector2(HookPosition.X + 2, 0));
Map.Objects.SpawnObject(splashAnimator);
}
}
HookPosition += _hookVelocity * Game1.TimeMultiplier;
// floor
if (HookPosition.Y > 110)
{
HookPosition.Y = 110;
_hookVelocity.Y = 0;
}
// notify fish inside the hook range
var interactBox = new Box(HookPosition.X - 8, HookPosition.Y - 1, 0, 22, 6, 8);
Map.Objects.InteractWithObject(interactBox);
}
else
{
HookedFish.Body.Velocity.X += _hookVelocity.X * 0.2f;
HookedFish.Body.Velocity.Y += _hookVelocity.Y * 0.2f;
_hookVelocity = Vector2.Zero;
// lost the fish?
if (HookedFish.EntityPosition.X <= -8)
{
HasFish = false;
Map.Objects.DeleteObjects.Add(HookedFish);
HookedFish = null;
LoosedFish();
}
}
}
}
private void Draw(SpriteBatch spriteBatch)
{
_sprite.Draw(spriteBatch);
if (_pulledOut)
return;
var source = _hookSource;
// hock is up/down
if (_hookVelocity.Y >= 0)
source.Y += 16;
// rotate color
else if (_isFishing && HookPosition.Y >= 28)
source.X += 16 * (Game1.TotalGameTime % 200 < 100 ? 1 : 0);
if (HookedFish == null)
spriteBatch.Draw(Resources.SprLink, HookPosition - new Vector2(9, 6), source, Color.White);
else
spriteBatch.Draw(Resources.SprLink, HookPosition - new Vector2(4, 6), _hookSourceHooked, Color.White);
//spriteBatch.Draw(Resources.SprWhite, new Vector2(HookPosition.X - 2, HookPosition.Y - 2), new Rectangle(0, 0, 4, 4), Color.Yellow * 0.5f);
}
private void PulledInHook()
{
if (HookedFish != null)
{
_animator.Play("pullout");
_pulledOut = true;
IncrementFishCount();
HookedFish.ToJump();
}
else
{
ResetFishing();
Game1.GameManager.StartDialogPath("fishing_empty");
}
}
private void LoosedFish()
{
ResetFishing();
IncrementFishCount();
Game1.GameManager.StartDialogPath("fishing_loss");
}
private void ResetFishing()
{
_pulledOut = false;
_wasInWater = false;
_isFishing = false;
HookPosition = _hookStartPosition;
_animator.Play("idle");
}
private void IncrementFishCount()
{
_fishCount++;
// is the pond empty
if (_fishCount >= 5)
Game1.GameManager.SaveManager.SetString("emptyPond", "1");
}
private void KeyChanged()
{
// spawn object
if (_isTransitioning || Game1.GameManager.SaveManager.GetString("leavePond") != "yes") return;
_isTransitioning = true;
MapManager.ObjLink.MapTransitionStart = MapManager.ObjLink.EntityPosition.Position;
MapManager.ObjLink.MapTransitionEnd = MapManager.ObjLink.EntityPosition.Position;
// append a map change
((MapTransitionSystem)Game1.GameManager.GameSystems[typeof(MapTransitionSystem)]).AppendMapChange("overworld.map", "pond");
}
}
}