OK so… I tried implementing a ‘ResourceGatherer.cs’, which uses information assigned in ‘ResourceGathering.cs’, and then attempts to manipulate the player to interact with it, but I’m not sure how this is going so far. Can any of you have a look and kindly advise me on what changes I can do to make the function work? Please
Here is my ResourceGathere.cs script:
using GameDevTV.Inventories;
using RPG.Core;
using RPG.Movement;
using RPG.ResourceManager;
using RPG.Skills;
using UnityEngine;
public class ResourceGatherer : MonoBehaviour, IAction
{
[SerializeField] int acceptanceRadius; // minimum distance that the player has to enclose, before he can begin gathering resources
[SerializeField] ResourceGathering resourceToHunt; // the resource the player is aiming for
[SerializeField] Inventory playerInventory; // a convenient method to access the players' inventory
private SkillExperience skillExperience;
private SkillStore skillStore;
public bool isResourceDestroyed = false;
public void Awake() {
playerInventory = GetComponent<Inventory>();
skillExperience = playerInventory.GetComponent<SkillExperience>();
skillStore = playerInventory.GetComponent<SkillStore>();
}
public bool CloseToSource() {
return Vector3.Distance(transform.position, resourceToHunt.transform.position) <= acceptanceRadius;
}
public Skill GetAssociatedSkill() {
return resourceToHunt.GetAssociatedSkill();
}
public int GetExperienceValue() {
return resourceToHunt.GetExperienceValue();
}
public void Gather() {
if (!CloseToSource()) GetComponent<Mover>().MoveTo(resourceToHunt.transform.position, 1.0f);
if (resourceToHunt.GetQuantityLeft() > 0) {
// Difficulty Setup:
var playerSkillLevel = skillStore.GetSkillLevel(GetAssociatedSkill());
var playerDropChance = Mathf.Clamp01((playerSkillLevel - resourceToHunt.minSkillRequired)/(float)(resourceToHunt.maxSkillRequired - resourceToHunt.minSkillRequired));
// if (UnityEngine.Random.value <= playerDropChance) {
playerInventory.AddToFirstEmptySlot(resourceToHunt.ResourceToAccumulate(), 1);
resourceToHunt.quantityLeft -= 1;
AccumulateXP();
// }
}
else
{
Destroy(resourceToHunt);
isResourceDestroyed = true;
Debug.Log(resourceToHunt.isDestroyed);
}
}
public void AccumulateXP() {
skillExperience.GainExperience(GetAssociatedSkill(), GetExperienceValue());
}
public void Cancel()
{
GetComponent<Mover>().Cancel();
}
}
And this is my ‘ResourceGathering.cs’ script (I’m yet to delete stuff from that, but first I want to ensure my gatherer works properly):
using UnityEngine;
using GameDevTV.Inventories;
using RPG.Control;
using RPG.Movement;
using RPG.Skills;
using RPG.Core;
using UnityEngine.AI;
using Unity.VisualScripting;
// Steps to get the experience:
// 1. Declare a 'SkillExperience' variable
// 2. get the component of the variable in 'Awake()'
// 3. Split the type of XP you get, based on the tag... for trees, it's "Tree", and for Rocks, it's "ResourceRocks"
// 4. When gathering, call 'skillExperience.GainExperience()', so you get the experience you are supposed to get when gathering resources
// 5. Play and test multiple times...
namespace RPG.ResourceManager
{
public class ResourceGathering : MonoBehaviour, IRaycastable, IAction
{
[SerializeField] InventoryItem resourceToAccumulate; // the loot we are getting from the tree, rock, or whatever we're harvesting
[SerializeField] int quantityPerHit = 1; // how many of that loot is being acquired, per mouse click
private float acceptanceRadius; // how close do we need to be to the resource source (tree, rock, etc...) before we can interact with it
public int quantityLeft = 10; // how many resources are in that source, before it's destroyed and re-instantiated
Inventory playerInventory; // the target inventory for our resources to go to (the player's inventory in this case)
public bool isDestroyed = false; // flag, to kill the source if it's out of resources
bool isMovingTowardsResourceObject = false; // flag, to ensure that we are close to the source of the resources, before being able to gather resources from it
// skill experience link, to get the skill, and fine-tune it according to the trained skill
SkillExperience skillExperience;
[SerializeField] Skill associatedSkill;
[SerializeField] int experienceValue;
[SerializeField] CursorType cursorType;
[SerializeField] ResourceGatherer resourceGatherer;
SkillStore skillStore;
private NavMeshAgent navMeshAgent;
void Awake()
{
playerInventory = Inventory.GetPlayerInventory();
if (playerInventory == null) Debug.Log("Player Inventory Not Found");
// In very simple terms, when you got the playerInventory, you got a hold of the only in-game
// component that actually has an 'Inventory.cs' script on him, the player.
// As the player has a hold of the 'SkillExperience' script as well, you can catch it
// through his inventory as well, since you got a hold of him through his inventory,
// so that's what I did below:
skillExperience = playerInventory.GetComponent<SkillExperience>();
// Just like how we accumulated 'skillExperience' above, we accumulate
// 'skillStore' as well with the exact same method (getting the object (Player)
// that the only inventory in the game is attached to):
skillStore = playerInventory.GetComponent<SkillStore>();
// Same thing to get the NavMeshAgent...
navMeshAgent = playerInventory.GetComponent<NavMeshAgent>();
acceptanceRadius = 4.0f;
isMovingTowardsResourceObject = false;
resourceGatherer = playerInventory.GetComponent<ResourceGatherer>();
}
[SerializeField] public int minSkillRequired;
[SerializeField] public int maxSkillRequired;
public int GetQuantityLeft() {
return quantityLeft;
}
public InventoryItem ResourceToAccumulate() {
return resourceToAccumulate;
}
public void Gather()
{
Debug.Log("Gather Method Called");
if (quantityLeft > 0)
{
// Play animation of whatever you're doing (mining, woodcutting, etc), and only stop when the resource source is dead
// Find a way to kill the tree slowly, and improve the higher your level goes up (revise the defence algorithm in 'Health.cs')
// Get the player skill level for this resource (you'll need 'SkillStore.cs' for this):
var playerSkillLevel = skillStore.GetSkillLevel(associatedSkill);
// Determine the player drop chance, based off their skill level... It will be clamped between 0-1
var playerDropChance = Mathf.Clamp01((playerSkillLevel - minSkillRequired)/(float)(maxSkillRequired - minSkillRequired));
// Check if we have the chance of getting a resource. If we do, add it to the inventory, get your XP, and reduce the quantity left off the source:
// if (Random.value <= playerDropChance) {
// Player gathering resource algorithm:
playerInventory.AddToFirstEmptySlot(resourceToAccumulate, quantityPerHit);
quantityLeft--;
AccumulateXP();
// }
}
if (quantityLeft <= 0)
{
Destroy(gameObject);
isDestroyed = true;
Debug.Log(isDestroyed);
}
}
public Skill GetAssociatedSkill() {
return associatedSkill;
}
public int GetExperienceValue() {
return experienceValue;
}
public void AccumulateXP()
{
Debug.Log("Accumulate XP Called");
skillExperience.GainExperience(associatedSkill, experienceValue);
}
public CursorType GetCursorType()
{
if (isDestroyed == true) return CursorType.None;
return cursorType;
}
/* public bool HandleRaycast(PlayerController callingController)
{
// Resource Gathering Logic:
// A. If your mouse is clicked:
// 1. if you are far away from the tree, get closer and then cut it down ('Gather()')
// 2. if you were already close to the tree, just cut it down already... ('Gather()')
// B. If your mouse is not clicked, but when you clicked it earlier you were already moving towards the tree, and you are now close to it:
// 1. You're close, so just cut it down already... ('Gather()')
if (Input.GetMouseButtonDown(0)) {
float distanceToTree = Vector3.Distance(transform.position, callingController.transform.position);
if (distanceToTree > acceptanceRadius)
{
Debug.Log("Moving towards the tree");
callingController.GetComponent<Mover>().MoveTo(transform.position, 1.0f);
isMovingTowardsResourceObject = true;
if (isMovingTowardsResourceObject && distanceToTree <= acceptanceRadius) {
Debug.Log("Cutting this stupid ass tree down...");
Gather();
isMovingTowardsResourceObject = false;
}
return true;
}
else if (distanceToTree <= acceptanceRadius)
{
Debug.Log("Cutting down the tree...");
Gather();
isMovingTowardsResourceObject = false;
return true;
}
}
if (isMovingTowardsResourceObject && Vector3.Distance(transform.position, callingController.transform.position) <= acceptanceRadius)
{
Gather();
isMovingTowardsResourceObject = false;
return true;
}
return true;
} */
public void Cancel()
{
// Implementation of 'IAction.cs'
// (Similar to both skillExperience and 'skillStore', we accumulate the mover from the only script that has
// an 'inventory' component on it, the player. We can get the player through his tag, but I'm too lazy, and a bit dodgy:
// If the action is cancelled, stop the navMeshAgent:
playerInventory.GetComponent<Mover>().Cancel();
}
/* // When you click on the resource source (tree/rock/etc...), run this code:
public bool HandleRaycast(PlayerController callingController)
{
// Early Note: if you read what 'Start()' and 'Update()' had to say about the 'skillExperience', 'skillStore'
// and 'navMeshAgent', we got these components off the only character that has an inventory on him, the player,
// under the name of 'playerInventory()'. We use that exact same reference here as well
if (Input.GetMouseButtonDown(0))
{
if (!GetIsInRange(playerInventory.transform))
{
// If the player is not close enough to this tree, make him move towards it:
playerInventory.GetComponent<Mover>().MoveTo(this.transform.position, 1.0f);
isMovingTowardsResourceObject = true;
}
else
{
// If you're in range, gather the resources:
playerInventory.GetComponent<ActionSchedular>().CancelCurrentAction();
Gather();
isMovingTowardsResourceObject = false;
}
}
return true;
}
public bool GetIsInRange(Transform playerTransform)
{
return Vector3.Distance(transform.position, playerTransform.position) <= acceptanceRadius;
} */
public bool HandleRaycast(PlayerController callingController) {
/* if (Input.GetMouseButtonDown(0)) {
Gather();
} */
if (Input.GetMouseButtonDown(0)) {
resourceGatherer.Gather();
return true;
}
return true;
}
}
}