Initial Commit
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
using System.Collections.Generic;
|
||||
using Kitchen;
|
||||
using KitchenMods;
|
||||
using Pets.Components.Properties;
|
||||
using Pets.Components.Status;
|
||||
using Pets.Enums;
|
||||
using Unity.Collections;
|
||||
using Unity.Entities;
|
||||
using UnityEngine;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace Pets.Systems.Activities
|
||||
{
|
||||
public class PetEatActivity : PetActivitySystem, IModSystem
|
||||
{
|
||||
protected override PetState StateForUpdate => PetState.Eat;
|
||||
|
||||
private EntityQuery _food;
|
||||
|
||||
protected override void Initialise()
|
||||
{
|
||||
base.Initialise();
|
||||
_food = GetEntityQuery(new QueryHelper().All(typeof(CItemProvider), typeof(CPosition)).None(typeof(COccupiedByPet)));
|
||||
}
|
||||
|
||||
protected override bool IsPossible(ActivityData data)
|
||||
{
|
||||
if (_food.CalculateEntityCount() == 0) return false;
|
||||
|
||||
using NativeArray<Entity> food = _food.ToEntityArray(Allocator.Temp);
|
||||
|
||||
Dictionary<float, Entity> ValidFood = GetAllEntitiesInRange(food, data.PetPosition);
|
||||
|
||||
bool foundFood = false;
|
||||
|
||||
foreach (float distance in ValidFood.Keys)
|
||||
{
|
||||
Entity foodEntity = ValidFood[distance];
|
||||
|
||||
float offset = 0;
|
||||
|
||||
if (Require(data.Pet, out CStandBackFromFood cStandBackFromFood))
|
||||
offset = cStandBackFromFood.Distance;
|
||||
|
||||
if (Require(data.Pet, out CPreferredFoods cPreferredFoods))
|
||||
{
|
||||
if (Require(foodEntity, out CItemProvider cItemProvider))
|
||||
{
|
||||
if (!cPreferredFoods.PreferredFoods.Contains(cItemProvider.ProvidedItem)) continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Require(foodEntity, out CPosition cFoodPosition)) continue;
|
||||
|
||||
Vector3 targetPos = Vector3.zero;
|
||||
|
||||
if (!CanGetTo(data.PetPosition, cFoodPosition, new Vector3(1 + offset, 0, 0), out targetPos))
|
||||
if (!CanGetTo(data.PetPosition, cFoodPosition, new Vector3(-1 - offset, 0, 0), out targetPos))
|
||||
if (!CanGetTo(data.PetPosition, cFoodPosition, new Vector3(0, 0, 1 + offset), out targetPos))
|
||||
if (!CanGetTo(data.PetPosition, cFoodPosition, new Vector3(0, 0, -1 - offset), out targetPos))
|
||||
continue;
|
||||
|
||||
foundFood = true;
|
||||
TargetPosition = targetPos;
|
||||
TargetEntity = foodEntity;
|
||||
TargetForward = cFoodPosition;
|
||||
break;
|
||||
}
|
||||
|
||||
return foundFood;
|
||||
}
|
||||
|
||||
private Entity TargetEntity;
|
||||
private CPosition TargetPosition;
|
||||
private CPosition TargetForward;
|
||||
|
||||
protected override bool Perform(ActivityData data)
|
||||
{
|
||||
if (!Require(TargetEntity, out CPosition cBedPosition)) return false;
|
||||
|
||||
EntityManager.AddComponentData(data.Pet, new CMoveToLocation
|
||||
{
|
||||
Location = TargetPosition,
|
||||
StoppingDistance = 0,
|
||||
DesiredFacing = TargetForward
|
||||
});
|
||||
|
||||
EntityManager.AddComponentData(TargetEntity, new COccupiedByPet());
|
||||
EntityManager.AddComponentData(data.Pet, new CPetInteractingWith
|
||||
{
|
||||
InteractingWith = TargetEntity,
|
||||
TimeToFinish = Random.Range(5, 15),
|
||||
IsWaitingForDestination = true
|
||||
});
|
||||
|
||||
return HasComponent<CPetInteractingWith>(data.Pet) && HasComponent<CMoveToLocation>(data.Pet) && HasComponent<COccupiedByPet>(TargetEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
using Kitchen;
|
||||
using KitchenMods;
|
||||
using Pets.Components;
|
||||
using Pets.Components.Properties;
|
||||
using Pets.Components.Status;
|
||||
using Pets.Enums;
|
||||
using Unity.Entities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Pets.Systems.Activities
|
||||
{
|
||||
public class PetFollowActivity : PetActivitySystem, IModSystem
|
||||
{
|
||||
protected override PetState StateForUpdate => PetState.Follow;
|
||||
|
||||
protected override bool IsPossible(ActivityData data)
|
||||
{
|
||||
maxDistance = 5;
|
||||
|
||||
if (!Require(data.Pet, out CPet cPet)) return false;
|
||||
if (cPet.Owner == Entity.Null) return false;
|
||||
if (!Require(cPet.Owner, out TargetPosition)) return false;
|
||||
if (Require(data.Pet, out CLonelyDistance cLonelyDistance))
|
||||
maxDistance = cLonelyDistance.Distance;
|
||||
|
||||
currentDistance = Vector3.Distance(data.PetPosition, TargetPosition);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private float maxDistance;
|
||||
private float currentDistance;
|
||||
private CPosition TargetPosition;
|
||||
|
||||
protected override bool Perform(ActivityData data)
|
||||
{
|
||||
if (currentDistance > maxDistance)
|
||||
{
|
||||
EntityManager.AddComponentData(data.Pet, new CMoveToLocation
|
||||
{
|
||||
Location = TargetPosition,
|
||||
StoppingDistance = 1,
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Require(data.Pet, out CRoamNearOwner cRoamNearOwner)) return true;
|
||||
|
||||
if (!(Random.value <= 0.03f * Time.DeltaTime)) return true;
|
||||
|
||||
if (!Require(data.Pet, out CCurrentSpeed cCurrentSpeed)) return true;
|
||||
if (cCurrentSpeed.speed > Mod.MinimumSpeedThreshold) return true;
|
||||
|
||||
Vector3 randomPosition = new Vector3(Random.Range(-cRoamNearOwner.Distance, cRoamNearOwner.Distance), 0, Random.Range(-cRoamNearOwner.Distance, cRoamNearOwner.Distance));
|
||||
Vector3 newTarget = TargetPosition + randomPosition;
|
||||
float distance = Vector3.Distance(data.PetPosition, newTarget);
|
||||
|
||||
if (!(distance <= maxDistance)) return true;
|
||||
if (!CanGetTo(data.PetPosition, newTarget, Vector3.zero, out newTarget)) return true;
|
||||
|
||||
EntityManager.AddComponentData(data.Pet, new CMoveToLocation
|
||||
{
|
||||
Location = newTarget,
|
||||
StoppingDistance = 0
|
||||
});
|
||||
|
||||
EntityManager.AddComponentData(data.Pet, new CPetInteractingWith
|
||||
{
|
||||
TimeToFinish = 0,
|
||||
IsWaitingForDestination = true
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using Kitchen;
|
||||
using KitchenMods;
|
||||
using Pets.Components;
|
||||
using Pets.Enums;
|
||||
using Unity.Entities;
|
||||
|
||||
namespace Pets.Systems.Activities
|
||||
{
|
||||
public class PetNameChangeActivity : PetActivitySystem, IModSystem
|
||||
{
|
||||
protected override PetState StateForUpdate => PetState.NameChange;
|
||||
|
||||
protected override bool IsPossible(ActivityData data)
|
||||
{
|
||||
return Require(data.Pet, out CPet cPet) && cPet.Owner != Entity.Null && Has<CPlayer>(cPet.Owner) && !Has<CRequestNameChange>(data.Pet);
|
||||
}
|
||||
|
||||
protected override bool Perform(ActivityData data)
|
||||
{
|
||||
if (!Require(data.Pet, out CPet cPet)) return false;
|
||||
if (!Require(cPet.Owner, out CPlayer cPlayer)) return false;
|
||||
|
||||
EntityManager.AddComponentData(data.Pet, new CRequestNameChange
|
||||
{
|
||||
Source = cPlayer.InputSource,
|
||||
IsTriggered = false
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Kitchen;
|
||||
using KitchenMods;
|
||||
using Pets.Components;
|
||||
using Pets.Components.Properties;
|
||||
using Pets.Components.Status;
|
||||
using Pets.Enums;
|
||||
using Unity.Collections;
|
||||
using Unity.Entities;
|
||||
using UnityEngine;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace Pets.Systems.Activities
|
||||
{
|
||||
public class PetSleepActivity : PetActivitySystem, IModSystem
|
||||
{
|
||||
protected override PetState StateForUpdate => PetState.Sleep;
|
||||
|
||||
private EntityQuery _petBeds;
|
||||
|
||||
protected override void Initialise()
|
||||
{
|
||||
base.Initialise();
|
||||
_petBeds = GetEntityQuery(new QueryHelper().All(typeof(CPetBed), typeof(CPosition)).None(typeof(COccupiedByPet)));
|
||||
}
|
||||
|
||||
protected override bool IsPossible(ActivityData data)
|
||||
{
|
||||
if (_petBeds.CalculateEntityCount() == 0) return false;
|
||||
|
||||
using NativeArray<Entity> petBeds = _petBeds.ToEntityArray(Allocator.Temp);
|
||||
|
||||
Dictionary<float, Entity> ValidBeds = GetAllEntitiesInRange(petBeds, data.PetPosition);
|
||||
|
||||
bool foundBed = false;
|
||||
|
||||
foreach (float distance in ValidBeds.Keys)
|
||||
{
|
||||
Entity bed = ValidBeds[distance];
|
||||
CPosition bedPosition;
|
||||
if (!Require(bed, out bedPosition)) continue;
|
||||
if (Require(data.Pet, out CSleepingPositionOffset cSleepingPositionOffset))
|
||||
if (GetOffsetPosition(bedPosition.Forward(1), cSleepingPositionOffset.Offset, out Vector2 offsetPosition))
|
||||
bedPosition += offsetPosition;
|
||||
|
||||
|
||||
|
||||
if (!CanGetTo(data.PetPosition, bedPosition, Vector3.zero, out Vector3 targetDestination)) continue;
|
||||
|
||||
foundBed = true;
|
||||
TargetPosition = targetDestination;
|
||||
TargetEntity = bed;
|
||||
break;
|
||||
}
|
||||
|
||||
return foundBed;
|
||||
}
|
||||
|
||||
private Entity TargetEntity;
|
||||
private CPosition TargetPosition;
|
||||
|
||||
protected override bool Perform(ActivityData data)
|
||||
{
|
||||
if (!Require(TargetEntity, out CPosition cBedPosition)) return false;
|
||||
|
||||
EntityManager.AddComponentData(data.Pet, new CMoveToLocation
|
||||
{
|
||||
Location = TargetPosition,
|
||||
StoppingDistance = 0,
|
||||
DesiredFacing = cBedPosition.Forward(-10)
|
||||
});
|
||||
|
||||
EntityManager.AddComponentData(TargetEntity, new COccupiedByPet());
|
||||
EntityManager.AddComponentData(data.Pet, new CPetInteractingWith
|
||||
{
|
||||
InteractingWith = TargetEntity,
|
||||
StartTime = DateTimeOffset.Now.ToUnixTimeSeconds(),
|
||||
TimeToFinish = Random.Range(5, 15),
|
||||
IsWaitingForDestination = true
|
||||
});
|
||||
|
||||
return HasComponent<CPetInteractingWith>(data.Pet) && HasComponent<CMoveToLocation>(data.Pet) && HasComponent<COccupiedByPet>(TargetEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using Kitchen;
|
||||
using KitchenMods;
|
||||
using Pets.Components;
|
||||
using Pets.Components.Status;
|
||||
using Pets.Enums;
|
||||
using Unity.Collections;
|
||||
using Unity.Entities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Pets.Systems.Activities
|
||||
{
|
||||
public class StopInteraction : GameSystemBase, IModSystem
|
||||
{
|
||||
private EntityQuery _pets;
|
||||
|
||||
protected override void Initialise()
|
||||
{
|
||||
base.Initialise();
|
||||
_pets = GetEntityQuery(new QueryHelper().All(typeof(CPet), typeof(CPetInteractingWith)));
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
if (_pets.CalculateEntityCount() == 0) return;
|
||||
|
||||
NativeArray<Entity> pets = _pets.ToEntityArray(Allocator.Temp);
|
||||
|
||||
for (int i = 0; i < pets.Length; i++)
|
||||
{
|
||||
Entity pet = pets[i];
|
||||
if (!Require(pet, out CPetInteractingWith cPetInteractingWith)) continue;
|
||||
if (!Require(pet, out CMoveToLocation cMoveToLocation)) continue;
|
||||
if (!Require(pet, out CPosition cPosition)) continue;
|
||||
if (!Require(pet, out CCurrentSpeed cCurrentSpeed)) continue;
|
||||
if (cPetInteractingWith.IsWaitingForDestination)
|
||||
{
|
||||
if (Vector3.Distance(cPosition, cMoveToLocation.Location) < 0.1f && cCurrentSpeed.speed < Mod.MinimumSpeedThreshold)
|
||||
{
|
||||
cPetInteractingWith.IsWaitingForDestination = false;
|
||||
cPetInteractingWith.StartTime = DateTimeOffset.Now.ToUnixTimeSeconds();
|
||||
EntityManager.AddComponentData(pet, cPetInteractingWith);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!Require(pet, out CPet cPet)) continue;
|
||||
if (cPetInteractingWith.StartTime + cPetInteractingWith.TimeToFinish > DateTimeOffset.Now.ToUnixTimeSeconds()) continue;
|
||||
|
||||
EntityManager.RemoveComponent<CMoveToLocation>(pet);
|
||||
EntityManager.RemoveComponent<COccupiedByPet>(cPetInteractingWith.InteractingWith);
|
||||
EntityManager.RemoveComponent<CPetInteractingWith>(pet);
|
||||
cPet.State = PetState.Follow;
|
||||
EntityManager.AddComponentData(pet, cPet);
|
||||
|
||||
}
|
||||
|
||||
pets.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using Kitchen;
|
||||
using KitchenMods;
|
||||
using Pets.Components.Creation;
|
||||
using Unity.Collections;
|
||||
using Unity.Entities;
|
||||
|
||||
namespace Pets.Systems
|
||||
{
|
||||
[UpdateAfter(typeof(EnsureLinkedPets))]
|
||||
public class CleanPetlessPlayers : GameSystemBase, IModSystem
|
||||
{
|
||||
private EntityQuery _players;
|
||||
protected override void Initialise()
|
||||
{
|
||||
base.Initialise();
|
||||
_players = GetEntityQuery(new QueryHelper().All(typeof(CPlayer), typeof(CLinkedPet)));
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
NativeArray<Entity> players = _players.ToEntityArray(Allocator.Temp);
|
||||
|
||||
for (int i = 0; i < players.Length; i++)
|
||||
{
|
||||
Entity player = players[i];
|
||||
if (!Require(player, out CLinkedPet cLinkedPet)) continue;
|
||||
if (cLinkedPet.PetEntity != Entity.Null) continue;
|
||||
|
||||
Mod.Logger.LogInfo($"Removing petless player");
|
||||
|
||||
EntityManager.RemoveComponent<CLinkedPet>(player);
|
||||
}
|
||||
|
||||
players.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using Kitchen;
|
||||
using KitchenMods;
|
||||
using Pets.Components.Creation;
|
||||
using Unity.Collections;
|
||||
using Unity.Entities;
|
||||
|
||||
namespace Pets.Systems
|
||||
{
|
||||
public class EnsureCorrectPet : GameSystemBase, IModSystem
|
||||
{
|
||||
private EntityQuery _players;
|
||||
|
||||
protected override void Initialise()
|
||||
{
|
||||
base.Initialise();
|
||||
_players = GetEntityQuery(typeof(CPlayer), typeof(CLinkedPet), typeof(CRequiresPet));
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
NativeArray<Entity> players = _players.ToEntityArray(Allocator.Temp);
|
||||
|
||||
for (int i = 0; i < players.Length; i++)
|
||||
{
|
||||
Entity player = players[i];
|
||||
if (!Require(player, out CLinkedPet cLinkedPet)) continue;
|
||||
if (!Require(player, out CRequiresPet cRequiresPet)) continue;
|
||||
|
||||
if (cLinkedPet.PetType != cRequiresPet.PetType && cLinkedPet.PetEntity != Entity.Null)
|
||||
{
|
||||
EntityManager.DestroyEntity(cLinkedPet.PetEntity);
|
||||
EntityManager.RemoveComponent<CLinkedPet>(player);
|
||||
}
|
||||
}
|
||||
|
||||
players.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
using Kitchen;
|
||||
using KitchenMods;
|
||||
using Pets.Components;
|
||||
using Pets.Components.Creation;
|
||||
using Unity.Collections;
|
||||
using Unity.Entities;
|
||||
|
||||
namespace Pets.Systems
|
||||
{
|
||||
[UpdateBefore(typeof(CleanPetlessPlayers))]
|
||||
public class EnsureLinkedPets : GameSystemBase, IModSystem
|
||||
{
|
||||
private EntityQuery _pets;
|
||||
private EntityQuery _playersWithLink;
|
||||
|
||||
|
||||
protected override void Initialise()
|
||||
{
|
||||
base.Initialise();
|
||||
_pets = GetEntityQuery(new QueryHelper().All(typeof(CPet)));
|
||||
_playersWithLink = GetEntityQuery(new QueryHelper().All(typeof(CLinkedPet)));
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
NativeArray<Entity> pets = _pets.ToEntityArray(Allocator.Temp);
|
||||
NativeArray<Entity> playersWithLink = _playersWithLink.ToEntityArray(Allocator.Temp);
|
||||
|
||||
foreach (Entity player in playersWithLink)
|
||||
{
|
||||
if (!Require(player, out CLinkedPet cLinkedPet)) continue;
|
||||
if ((cLinkedPet.PetEntity == Entity.Null || cLinkedPet.PetEntity.Index == 0) || (cLinkedPet.PetEntity != Entity.Null && !EntityManager.HasComponent<CPet>(cLinkedPet.PetEntity)))
|
||||
{
|
||||
foreach (Entity pet in pets)
|
||||
{
|
||||
if (!Require(pet, out CPet cPet)) continue;
|
||||
if (cLinkedPet.PetLinkId != cPet.PetLinkId) continue;
|
||||
cLinkedPet.PetEntity = pet;
|
||||
cPet.Owner = player;
|
||||
EntityManager.SetComponentData(player, cLinkedPet);
|
||||
EntityManager.SetComponentData(pet, cPet);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Entity pet in pets)
|
||||
{
|
||||
if (!Require(pet, out CPet cPet)) continue;
|
||||
if ((cPet.Owner == Entity.Null || cPet.Owner.Index == 0) || (cPet.Owner != Entity.Null && !EntityManager.HasComponent<CLinkedPet>(cPet.Owner)))
|
||||
{
|
||||
foreach (Entity player in playersWithLink)
|
||||
{
|
||||
if (!Require(player, out CLinkedPet cLinkedPet)) continue;
|
||||
if (cLinkedPet.PetLinkId != cPet.PetLinkId) continue;
|
||||
cLinkedPet.PetEntity = pet;
|
||||
cPet.Owner = player;
|
||||
EntityManager.SetComponentData(player, cLinkedPet);
|
||||
EntityManager.SetComponentData(pet, cPet);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pets.Dispose();
|
||||
playersWithLink.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
using Kitchen;
|
||||
using KitchenMods;
|
||||
using Pets.Components.Creation;
|
||||
using Unity.Collections;
|
||||
using Unity.Entities;
|
||||
|
||||
namespace Pets.Systems
|
||||
{
|
||||
public class PetSelector : GameSystemBase, IModSystem
|
||||
{
|
||||
public static PetSelector Main;
|
||||
|
||||
private EntityQuery _players;
|
||||
private EntityQuery _requestedPets;
|
||||
|
||||
protected override void Initialise()
|
||||
{
|
||||
base.Initialise();
|
||||
Main = this;
|
||||
_players = GetEntityQuery(new QueryHelper().All(typeof(CPlayer)));
|
||||
_requestedPets = GetEntityQuery(new QueryHelper().All(typeof(CRequestedPet)));
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
using NativeArray<Entity> requestedPets = _requestedPets.ToEntityArray(Allocator.Temp);
|
||||
using NativeArray<Entity> players = _players.ToEntityArray(Allocator.Temp);
|
||||
|
||||
for (int i = 0; i < requestedPets.Length; i++)
|
||||
{
|
||||
Entity requestedPet = requestedPets[i];
|
||||
if (!Require(requestedPet, out CRequestedPet cRequestedPet)) continue;
|
||||
foreach (Entity player in players)
|
||||
{
|
||||
if (!Require(player, out CPlayer cPlayer)) continue;
|
||||
if (cPlayer.ID != cRequestedPet.player) continue;
|
||||
EntityManager.AddComponentData(player, new CRequiresPet
|
||||
{
|
||||
PetType = cRequestedPet.pet
|
||||
});
|
||||
EntityManager.DestroyEntity(requestedPet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void CreatePlayerRequest(int player, int pet)
|
||||
{
|
||||
Entity entity = EntityManager.CreateEntity();
|
||||
EntityManager.AddComponentData(entity, new CRequestedPet
|
||||
{
|
||||
pet = pet,
|
||||
player = player
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
using Kitchen;
|
||||
using KitchenData;
|
||||
using KitchenMods;
|
||||
using Pets.Components;
|
||||
using Pets.Components.Creation;
|
||||
using Pets.Customs.Types;
|
||||
using Pets.Enums;
|
||||
using Pets.Interfaces;
|
||||
using Unity.Collections;
|
||||
using Unity.Entities;
|
||||
|
||||
namespace Pets.Systems.Creation
|
||||
{
|
||||
[UpdateAfter(typeof(EnsureLinkedPets))]
|
||||
public class SpawnPets : GameSystemBase, IModSystem
|
||||
{
|
||||
private EntityQuery _players;
|
||||
|
||||
protected override void Initialise()
|
||||
{
|
||||
base.Initialise();
|
||||
_players = GetEntityQuery(new QueryHelper().All(typeof(CPlayer), typeof(CRequiresPet)).None(typeof(CLinkedPet)));
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
NativeArray<Entity> players = _players.ToEntityArray(Allocator.Temp);
|
||||
|
||||
foreach (Entity player in players)
|
||||
{
|
||||
if (!Require(player, out CRequiresPet cRequiresPet)) continue;
|
||||
if (!Require(player, out CPosition cPosition)) continue;
|
||||
if (!GameData.Main.TryGet(cRequiresPet.PetType, out Pet petType)) continue;
|
||||
|
||||
Entity pet = EntityManager.CreateEntity();
|
||||
|
||||
int LinkID = UnityEngine.Random.Range(-100000, 100000);
|
||||
|
||||
EntityManager.AddComponentData(pet, new CPet
|
||||
{
|
||||
Owner = player,
|
||||
State = petType.DefaultState,
|
||||
PetLinkId = LinkID,
|
||||
PetType = petType.ID
|
||||
});
|
||||
EntityManager.AddComponentData(pet, new CPosition(cPosition));
|
||||
|
||||
EntityManager.AddComponentData(pet, new CRequiresView
|
||||
{
|
||||
Type = petType.ViewType,
|
||||
PhysicsDriven = true
|
||||
});
|
||||
EntityManager.AddComponentData(pet, new CDoNotPersist());
|
||||
EntityManager.AddComponentData(pet, new CIsInteractive());
|
||||
EntityManager.AddComponentData(pet, new CCanBePetted());
|
||||
EntityManager.AddComponentData(pet, new CPersistThroughSceneChanges());
|
||||
|
||||
|
||||
EntityCommandBuffer ecb = new EntityCommandBuffer(Allocator.Temp);
|
||||
foreach (IPetProperty property in petType.Properties)
|
||||
{
|
||||
ecb.AddComponent(pet, (dynamic)property);
|
||||
}
|
||||
|
||||
ecb.AddComponent(pet, new CDefaultState(petType.DefaultState));
|
||||
|
||||
ecb.Playback(EntityManager);
|
||||
|
||||
EntityManager.AddComponentData(player, new CLinkedPet
|
||||
{
|
||||
PetType = cRequiresPet.PetType,
|
||||
PetEntity = pet,
|
||||
PetLinkId = LinkID
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
players.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
using System.Collections.Generic;
|
||||
using Kitchen;
|
||||
using KitchenMods;
|
||||
using Pets.Components.Creation;
|
||||
using Unity.Collections;
|
||||
using Unity.Entities;
|
||||
|
||||
namespace Pets.Systems
|
||||
{
|
||||
public class TransitionFix : GameSystemBase, IModSystem
|
||||
{
|
||||
private EntityQuery _players;
|
||||
private static Dictionary<int, CRequiresPet> _requiresPet = new Dictionary<int, CRequiresPet>();
|
||||
private static Dictionary<int, CLinkedPet> _linkedPet = new Dictionary<int, CLinkedPet>();
|
||||
|
||||
protected override void Initialise()
|
||||
{
|
||||
base.Initialise();
|
||||
_players = GetEntityQuery(new QueryHelper().All(typeof(CPlayer)));
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
NativeArray<Entity> players = _players.ToEntityArray(Allocator.Temp);
|
||||
|
||||
_requiresPet.Clear();
|
||||
_linkedPet.Clear();
|
||||
|
||||
foreach (Entity player in players)
|
||||
{
|
||||
if (!Require(player, out CPlayer cPlayer)) continue;
|
||||
if (Require(player, out CRequiresPet cRequiresPet))
|
||||
{
|
||||
_requiresPet.Add(cPlayer.ID, cRequiresPet);
|
||||
}
|
||||
if (Require(player, out CLinkedPet cLinkedPet))
|
||||
{
|
||||
_linkedPet.Add(cPlayer.ID, cLinkedPet);
|
||||
}
|
||||
}
|
||||
|
||||
players.Dispose();
|
||||
}
|
||||
|
||||
public override void AfterLoading(SaveSystemType system_type)
|
||||
{
|
||||
base.AfterLoading(system_type);
|
||||
if (_requiresPet == null) return;
|
||||
|
||||
NativeArray<Entity> players = _players.ToEntityArray(Allocator.Temp);
|
||||
|
||||
for (int i = 0; i < players.Length; i++)
|
||||
{
|
||||
Entity player = players[i];
|
||||
if (Has<CLinkedPet>(player))
|
||||
{
|
||||
EntityManager.RemoveComponent<CLinkedPet>(player);
|
||||
}
|
||||
|
||||
if (!Require(player, out CPlayer cPlayer)) continue;
|
||||
|
||||
if (_linkedPet.TryGetValue(cPlayer.ID, out CLinkedPet cLinkedPet))
|
||||
{
|
||||
EntityManager.AddComponentData(player, cLinkedPet);
|
||||
}
|
||||
|
||||
if (_requiresPet.TryGetValue(cPlayer.ID, out CRequiresPet cRequiresPet))
|
||||
{
|
||||
EntityManager.AddComponentData(player, cRequiresPet);
|
||||
}
|
||||
}
|
||||
|
||||
_requiresPet.Clear();
|
||||
players.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using Kitchen;
|
||||
using KitchenMods;
|
||||
using Pets.Components;
|
||||
using Pets.Components.Menu;
|
||||
|
||||
namespace Pets.Systems.EditorMenu
|
||||
{
|
||||
public class ActivatePetEditorDuringDay : ItemInteractionSystem, IModSystem
|
||||
{
|
||||
protected override bool IsPossible(ref InteractionData data)
|
||||
{
|
||||
return Require(data.Target, out CPet cPet) && cPet.Owner == data.Interactor;
|
||||
}
|
||||
|
||||
protected override void Perform(ref InteractionData data)
|
||||
{
|
||||
EntityManager.AddComponentData(data.Target, new CTriggerPetEditor
|
||||
{
|
||||
IsTriggered = true,
|
||||
TriggerEntity = data.Interactor
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using Kitchen;
|
||||
using KitchenMods;
|
||||
using Pets.Components;
|
||||
using Pets.Components.Menu;
|
||||
|
||||
namespace Pets.Systems.EditorMenu
|
||||
{
|
||||
public class ActivatePetEditorDuringNight : ApplianceInteractionSystem, IModSystem
|
||||
{
|
||||
protected override bool IsPossible(ref InteractionData data)
|
||||
{
|
||||
return Require(data.Target, out CPet cPet) && cPet.Owner == data.Interactor;
|
||||
}
|
||||
|
||||
protected override void Perform(ref InteractionData data)
|
||||
{
|
||||
EntityManager.AddComponentData(data.Target, new CTriggerPetEditor
|
||||
{
|
||||
IsTriggered = true,
|
||||
TriggerEntity = data.Interactor
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using Kitchen;
|
||||
using KitchenLib.Utils;
|
||||
using KitchenMods;
|
||||
using Pets.Components;
|
||||
using Pets.Components.Menu;
|
||||
using Unity.Entities;
|
||||
|
||||
namespace Pets.Systems.EditorMenu
|
||||
{
|
||||
public class ManagePetEditorIndicators : IndicatorManager, IModSystem
|
||||
{
|
||||
protected override ViewType ViewType => (ViewType)VariousUtils.GetID("com.starfluxgames.pets.PetEditorView");
|
||||
|
||||
protected override EntityQuery GetSearchQuery()
|
||||
{
|
||||
return GetEntityQuery(typeof(CPet), typeof(CPosition));
|
||||
}
|
||||
|
||||
protected override bool ShouldHaveIndicator(Entity candidate)
|
||||
{
|
||||
if (Require(candidate, out CHasIndicator comp))
|
||||
return Require(comp.Indicator, out CPetEditorInfo cPetEditorInfo) && !cPetEditorInfo.IsComplete;
|
||||
|
||||
if (!Has<CPosition>(candidate)) return false;
|
||||
if (!Require(candidate, out CTriggerPetEditor trigger)) return false;
|
||||
if (!Has<CPlayer>(trigger.TriggerEntity)) return false;
|
||||
if (!trigger.IsTriggered) return false;
|
||||
|
||||
trigger.IsTriggered = false;
|
||||
Set(candidate, trigger);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
protected override Entity CreateIndicator(Entity source)
|
||||
{
|
||||
if (!Require(source, out CPosition position)) return default(Entity);
|
||||
if (!Require(source, out CPet cPet)) return default(Entity);
|
||||
if (!Require(source, out CTriggerPetEditor trigger)) return default(Entity);
|
||||
if (!Require<CPlayer>(trigger.TriggerEntity, out CPlayer player)) return default(Entity);
|
||||
|
||||
Entity entity = base.CreateIndicator(source);
|
||||
EntityManager.AddComponentData(entity, new CPosition(position));
|
||||
EntityManager.AddComponentData(entity, new CPetEditorInfo
|
||||
{
|
||||
Player = player
|
||||
});
|
||||
return entity;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using Kitchen;
|
||||
using KitchenMods;
|
||||
using Pets.Components;
|
||||
using Pets.Components.Creation;
|
||||
using Pets.Enums;
|
||||
using Unity.Collections;
|
||||
using Unity.Entities;
|
||||
|
||||
namespace Pets.Systems
|
||||
{
|
||||
public class FillStateChangeRequests : GameSystemBase, IModSystem
|
||||
{
|
||||
private EntityQuery _players;
|
||||
private EntityQuery _stateChangeRequests;
|
||||
protected override void Initialise()
|
||||
{
|
||||
base.Initialise();
|
||||
_players = GetEntityQuery(typeof(CPlayer));
|
||||
_stateChangeRequests = GetEntityQuery(typeof(CRequestStateChange));
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
using NativeArray<Entity> stateChangeRequests = _stateChangeRequests.ToEntityArray(Allocator.Temp);
|
||||
using NativeArray<Entity> players = _players.ToEntityArray(Allocator.Temp);
|
||||
|
||||
for (int i = 0; i < stateChangeRequests.Length; i++)
|
||||
{
|
||||
Entity request = stateChangeRequests[i];
|
||||
if (!Require(request, out CRequestStateChange cRequestStateChange)) continue;
|
||||
|
||||
foreach (Entity player in players)
|
||||
{
|
||||
if (!Require(player, out CPlayer cPlayer)) continue;
|
||||
if (cPlayer.ID != cRequestStateChange.PlayerID) continue;
|
||||
if (!Require(player, out CLinkedPet cLinkedPet)) continue;
|
||||
if (!Require(cLinkedPet.PetEntity, out CPet cPet)) continue;
|
||||
cPet.State = (PetState)cRequestStateChange.StateID;
|
||||
EntityManager.AddComponentData(cLinkedPet.PetEntity, cPet);
|
||||
EntityManager.DestroyEntity(request);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Kitchen;
|
||||
using KitchenData;
|
||||
using Pets.Components;
|
||||
using Pets.Components.Status;
|
||||
using Pets.Customs.Types;
|
||||
using Pets.Enums;
|
||||
using Unity.Collections;
|
||||
using Unity.Entities;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AI;
|
||||
|
||||
namespace Pets.Systems
|
||||
{
|
||||
public abstract class PetActivitySystem : GameSystemBase
|
||||
{
|
||||
protected abstract bool IsPossible(ActivityData data);
|
||||
protected abstract bool Perform(ActivityData data);
|
||||
|
||||
protected abstract PetState StateForUpdate { get; }
|
||||
|
||||
private EntityQuery _petsWaitingForActivity;
|
||||
private NavMeshPath Path = new NavMeshPath();
|
||||
|
||||
protected override void Initialise()
|
||||
{
|
||||
base.Initialise();
|
||||
_petsWaitingForActivity = GetEntityQuery(new QueryHelper().All(typeof(CPet)).None(typeof(CPetInteractingWith)));
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
using NativeArray<Entity> petsWaitingForActivity = _petsWaitingForActivity.ToEntityArray(Allocator.Temp);
|
||||
petsWaitingForActivity.ShuffleInPlace();
|
||||
|
||||
if (petsWaitingForActivity.Length == 0) return;
|
||||
|
||||
Entity pet = petsWaitingForActivity[0];
|
||||
|
||||
if (!Require(pet, out CPet cPet)) return;
|
||||
if (!GameData.Main.TryGet(cPet.PetType, out Pet petType)) return;
|
||||
if (!Require(pet, out CPosition cPosition)) return;
|
||||
if (!Require(pet, out CDefaultState cDefaultState)) return;
|
||||
if (cPet.State != StateForUpdate) return;
|
||||
|
||||
ActivityData data = new ActivityData
|
||||
{
|
||||
Pet = pet,
|
||||
PetPosition = cPosition,
|
||||
PetType = petType,
|
||||
State = cPet.State
|
||||
};
|
||||
|
||||
|
||||
if (IsPossible(data))
|
||||
{
|
||||
if (Perform(data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
cPet.State = cDefaultState.State;
|
||||
EntityManager.SetComponentData(pet, cPet);
|
||||
}
|
||||
|
||||
protected Dictionary<float, Entity> GetAllEntitiesInRange(NativeArray<Entity> entities, Vector3 startingPosition, float maxDistance = float.MaxValue, bool sortByDistance = true)
|
||||
{
|
||||
Dictionary<float, Entity> entitiesInRange = new();
|
||||
|
||||
foreach (Entity entity in entities)
|
||||
{
|
||||
if (!Require(entity, out CPosition cPosition)) continue;
|
||||
float distance = Vector3.Distance(startingPosition, cPosition);
|
||||
if (distance > maxDistance) continue;
|
||||
if (entitiesInRange.ContainsKey(distance)) continue;
|
||||
entitiesInRange.Add(distance, entity);
|
||||
}
|
||||
|
||||
if (sortByDistance)
|
||||
entitiesInRange = entitiesInRange.OrderBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value);
|
||||
|
||||
return entitiesInRange;
|
||||
}
|
||||
|
||||
protected bool CanGetTo(Vector3 startingPosition, Vector3 targetPosition, Vector3 targetOffset, out Vector3 targetDestination)
|
||||
{
|
||||
targetDestination = Vector3.zero;
|
||||
CLayoutRoomTile tile1 = GetTile(targetPosition);
|
||||
CLayoutRoomTile tile2 = GetTile(targetPosition + targetOffset);
|
||||
if (tile1.RoomID != tile2.RoomID) return false;
|
||||
|
||||
NavMesh.CalculatePath(startingPosition, targetPosition + targetOffset, NavMesh.AllAreas, Path);
|
||||
|
||||
if (Path.status == NavMeshPathStatus.PathComplete)
|
||||
targetDestination = targetPosition + targetOffset;
|
||||
|
||||
return Path.status == NavMeshPathStatus.PathComplete;
|
||||
}
|
||||
|
||||
protected bool GetOffsetPosition(Vector3 forward, Vector2 offset, out Vector2 success)
|
||||
{
|
||||
success = Vector2.zero;
|
||||
float rotation = Mathf.Atan2(forward.x, forward.z) * Mathf.Rad2Deg;
|
||||
Mod.Logger.LogInfo("GetOffsetPosition " + rotation);
|
||||
if (rotation == 0)
|
||||
success = offset;
|
||||
if (rotation == 90)
|
||||
success = new Vector2(offset.y, -offset.x);
|
||||
if (rotation == 180)
|
||||
success = -offset;
|
||||
if (rotation == 270)
|
||||
success = new Vector2(-offset.y, offset.x);
|
||||
return success != Vector2.zero;
|
||||
}
|
||||
}
|
||||
|
||||
public struct ActivityData
|
||||
{
|
||||
public Entity Pet;
|
||||
public CPosition PetPosition;
|
||||
public Pet PetType;
|
||||
public PetState State;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
using System.Collections.Generic;
|
||||
using Kitchen;
|
||||
using Kitchen.Layouts;
|
||||
using KitchenData;
|
||||
using KitchenLib.Utils;
|
||||
using KitchenMods;
|
||||
using Pets.Components.Properties;
|
||||
using Pets.Customs;
|
||||
using Unity.Collections;
|
||||
using Unity.Entities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Pets.Systems
|
||||
{
|
||||
public class ProvidePetStaples : StartOfNightSystem, IModSystem
|
||||
{
|
||||
private EntityQuery _staplePetAppliances;
|
||||
protected override void Initialise()
|
||||
{
|
||||
base.Initialise();
|
||||
_staplePetAppliances = GetEntityQuery(typeof(CStapleAppliances));
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
|
||||
using NativeArray<Entity> staplePetAppliances = _staplePetAppliances.ToEntityArray(Allocator.Temp);
|
||||
|
||||
foreach (Entity staplePetAppliance in staplePetAppliances)
|
||||
{
|
||||
if (!Require(staplePetAppliance, out CStapleAppliances cStapleAppliances)) continue;
|
||||
|
||||
foreach (int applianceID in cStapleAppliances.Appliances)
|
||||
{
|
||||
if (!(Random.value <= 0.3f * Time.DeltaTime)) continue;
|
||||
|
||||
List<Vector3> postTiles = GetPostTiles();
|
||||
int num = 0;
|
||||
Vector3 position = FindTile(ref num, postTiles);
|
||||
CreateBlueprintLetter(EntityManager, position, applianceID, 0, 0, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 FindTile(ref int placed_tile, List<Vector3> floor_tiles)
|
||||
{
|
||||
Vector3 vector = default;
|
||||
bool flag = false;
|
||||
while (!flag && placed_tile < floor_tiles.Count)
|
||||
{
|
||||
int num = placed_tile;
|
||||
placed_tile = num + 1;
|
||||
vector = floor_tiles[num];
|
||||
if (GetOccupant(vector) != default) continue;
|
||||
flag = true;
|
||||
foreach (LayoutPosition pos in LayoutHelpers.Directions)
|
||||
{
|
||||
Entity occupant = GetOccupant(new Vector3(vector.x + pos.x, vector.y, vector.z + pos.y));
|
||||
if (occupant == default || !Has<CApplianceTable>(occupant)) continue;
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return !flag ? GetFallbackTile() : vector;
|
||||
}
|
||||
|
||||
public static Entity CreateBlueprintLetter(EntityManager em, Vector3 position, int appliance_id, float price_multiplier = 1f, int force_price = -1, bool use_red = false)
|
||||
{
|
||||
Entity entity = em.CreateEntity();
|
||||
em.AddComponentData<CCreateAppliance>(entity, new CCreateAppliance
|
||||
{
|
||||
ID = GDOUtils.GetCustomGameDataObject<PetLetter>().ID
|
||||
});
|
||||
em.AddComponentData<CPosition>(entity, new CPosition(position));
|
||||
em.AddComponentData<CLetter>(entity, default(CLetter));
|
||||
int num = 0;
|
||||
Appliance appliance;
|
||||
if (force_price >= 0)
|
||||
{
|
||||
num = force_price;
|
||||
}
|
||||
else if (GameData.Main.TryGet<Appliance>(appliance_id, out appliance, true))
|
||||
{
|
||||
num = appliance.PurchaseCost;
|
||||
}
|
||||
em.AddComponentData<CLetterBlueprint>(entity, new CLetterBlueprint
|
||||
{
|
||||
BlueprintID = AssetReference.Blueprint,
|
||||
ApplianceID = appliance_id,
|
||||
Price = Mathf.CeilToInt((float)num * price_multiplier)
|
||||
});
|
||||
em.AddComponentData<CShopEntity>(entity, default(CShopEntity));
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using Kitchen;
|
||||
using KitchenMods;
|
||||
using Pets.Components;
|
||||
using Pets.Components.Properties;
|
||||
using Pets.Components.Status;
|
||||
using Pets.Enums;
|
||||
using Unity.Collections;
|
||||
using Unity.Entities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Pets.Systems
|
||||
{
|
||||
public class SelectActivity : GameSystemBase, IModSystem
|
||||
{
|
||||
private EntityQuery _pets;
|
||||
protected override void Initialise()
|
||||
{
|
||||
base.Initialise();
|
||||
_pets = GetEntityQuery(new QueryHelper().All(typeof(CPet)).None(typeof(CPetInteractingWith)));
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
NativeArray<Entity> pets = _pets.ToEntityArray(Allocator.Temp);
|
||||
|
||||
foreach (Entity pet in pets)
|
||||
{
|
||||
if (!Require(pet, out CPet cPet)) continue;
|
||||
if (!Require(pet, out CDefaultState cDefaultState)) continue;
|
||||
if (cPet.State != cDefaultState.State) continue;
|
||||
if (!Require(pet, out CActivities cActivities)) continue;
|
||||
if (!(Random.value <= 0.03f * Time.DeltaTime)) continue;
|
||||
|
||||
int activity = Random.Range(0, cActivities.Activities.Length);
|
||||
activity = cActivities.Activities[activity];
|
||||
|
||||
cPet.State = (PetState)activity;
|
||||
EntityManager.SetComponentData(pet, cPet);
|
||||
}
|
||||
|
||||
pets.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using Kitchen;
|
||||
using KitchenMods;
|
||||
using Pets.Components;
|
||||
using Unity.Collections;
|
||||
using Unity.Entities;
|
||||
|
||||
namespace Pets.Systems
|
||||
{
|
||||
[UpdateInGroup(typeof(PostTransitionGroup))]
|
||||
public class TeleportPetsToOwners : RestaurantSystem, IModSystem
|
||||
{
|
||||
private EntityQuery _pets;
|
||||
protected override void Initialise()
|
||||
{
|
||||
base.Initialise();
|
||||
RequireSingletonForUpdate<CSceneFirstFrame>();
|
||||
_pets = GetEntityQuery(typeof(CPet));
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
using NativeArray<Entity> pets = _pets.ToEntityArray(Allocator.Temp);
|
||||
|
||||
foreach (Entity pet in pets)
|
||||
{
|
||||
if (!Require(pet, out CPet cPet)) continue;
|
||||
if (cPet.Owner == Entity.Null) continue;
|
||||
if (!Require(cPet.Owner, out CPosition cPosition)) continue;
|
||||
if (!Require(pet, out CPosition cPetPosition)) continue;
|
||||
|
||||
cPetPosition = new CPosition
|
||||
{
|
||||
Position = cPosition.Position,
|
||||
ForceSnap = true
|
||||
};
|
||||
EntityManager.SetComponentData(pet, cPetPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user