WorldBuilder/FishSpot.cs
using System;
using Clover.Animals;
using Clover.Carriable;
using Clover.Data;
using Clover.Player;
namespace Clover.WorldBuilder;
[Category( "Clover/World" )]
public class FishSpot : Component
{
[Property] public List<FishData> SpecialFish { get; set; }
[Property] public FishData.FishLocation Location { get; set; } = FishData.FishLocation.River;
[Property] public float SpawnRadius { get; set; } = 100f;
protected override void OnStart()
{
if ( IsProxy || !Networking.IsHost ) return;
if ( Random.Shared.Float() > 0.5f ) SpawnFish();
}
private TimeSince _lastSpawn;
protected override void OnFixedUpdate()
{
if ( IsProxy || !Networking.IsHost ) return;
if ( _lastSpawn > 60 )
{
_lastSpawn = 0;
CheckSpawn();
}
}
private void CheckSpawn()
{
var allFish = Scene.GetAllComponents<CatchableFish>();
var fishNearby = allFish.Where( f => f.WorldPosition.Distance( WorldPosition ) < SpawnRadius * 1.5f ).ToList();
if ( fishNearby.Count > 0 ) return;
if ( PlayerNearby() ) return;
if ( Random.Shared.Float() > 0.5f ) return;
SpawnFish();
}
private bool PlayerNearby()
{
var players = Scene.GetAllComponents<PlayerCharacter>();
return players.Any( p => p.WorldPosition.Distance( WorldPosition ) < SpawnRadius * 2f );
}
private void SpawnFish()
{
var findPositionTry = 0;
var basePosition = WorldPosition;
Log.Trace( $"Trying to spawn fish at {basePosition}." );
FishData fishData;
if ( SpecialFish != null && SpecialFish.Count > 0 )
{
// fishData = SpecialFish.PickRandom();
fishData = Random.Shared.FromList( SpecialFish );
}
else
{
// var resources = Resources.LoadAllResources( "res://items/fish/" );
// var fish = resources.Where( r => r is FishData ).Select( r => r as FishData ).ToList();
// fishData = fish.PickRandom();
var fishes = ResourceLibrary.GetAll<FishData>().Where( f => f.Location == Location ).ToList();
fishData = Random.Shared.FromList( fishes );
if ( !fishData.IsValid() )
{
Log.Trace( $"No fish data found for location {Location}." );
return;
}
}
if ( fishData == null )
{
Log.Trace( $"No fish data found." );
return;
}
while ( findPositionTry < 10 )
{
var randomPosition = basePosition;
randomPosition += new Vector3(
Random.Shared.Float() * SpawnRadius * 2 - SpawnRadius,
Random.Shared.Float() * SpawnRadius * 2 - SpawnRadius,
0
);
if ( FishingRod.CheckForWater( randomPosition ) )
{
var world = WorldManager.Instance?.ActiveWorld;
if ( world == null )
{
Log.Warning( "No active world found." );
return;
}
var prefab =
SceneUtility.GetPrefabScene(
ResourceLibrary.Get<PrefabFile>( "animals/fish/fish_shadow.prefab" ) );
if ( prefab == null )
{
Log.Error( "Failed to load fish prefab." );
return;
}
var gameObject = prefab.Clone();
gameObject.SetParent( world.GameObject );
var fish = gameObject.GetComponent<CatchableFish>();
if ( fish == null )
{
Log.Error( "Failed to get CatchableFish component." );
gameObject.Destroy();
return;
}
fish.Data = fishData;
fish.WorldPosition = randomPosition;
fish.SetSize( fishData.Size );
fish.Weight = fishData.Weight.GetValue();
gameObject.NetworkSpawn();
Log.Trace( $"Spawned fish {fishData.Name} at {randomPosition}." );
return;
}
findPositionTry++;
}
Log.Warning( $"Failed to find a valid position to spawn fish on {this}." );
}
protected override void DrawGizmos()
{
base.DrawGizmos();
Gizmo.Hitbox.Sphere( new Sphere( Vector3.Zero, SpawnRadius ) );
Gizmo.Draw.LineSphere( Vector3.Zero, SpawnRadius );
Gizmo.Draw.Text( Location.ToString(), global::Transform.Zero );
}
}