private void SpawnHarvestedItems(CropDetails cropDetails) { for (int i = 0; i < cropDetails.cropProducedItemCode.Length; i++) { int cropsToProduce; if (cropDetails.cropProducedMinQuantity[i] == cropDetails.cropProducedMaxQuantity[i] || cropDetails.cropProducedMaxQuantity[i] < cropDetails.cropProducedMinQuantity[i]) { cropsToProduce = cropDetails.cropProducedMinQuantity[i]; } else { cropsToProduce = Random.Range(cropDetails.cropProducedMinQuantity[i], cropDetails.cropProducedMaxQuantity[i] + 1); } for (int j = 0; j < cropsToProduce; j++) { Vector3 spawnPosition; if (cropDetails.spawnCropProducedAtPlayerPosition) { InventoryManager.Instance.AddItem(InventoryLocation.player, cropDetails.cropProducedItemCode[i]); } else { spawnPosition = new Vector3(transform.position.x + Random.Range(-1f, 1f), transform.position.y + Random.Range(-1f, 1f), 0f); SceneItemsManager.Instance.InstantiateSceneItem(cropDetails.cropProducedItemCode[i], spawnPosition); } } } }
private IEnumerator ProcessHarvestActionsAfterAnimation(CropDetails cropDetails, GridPropertyDetails gridPropertyDetails, Animator animator) { while (!animator.GetCurrentAnimatorStateInfo(0).IsName("Harvested")) { yield return(null); } HarvestActions(cropDetails, gridPropertyDetails); }
/// <summary> /// This method determines which stage of growth the crop is in, and displays that stage's crop prefab and sprite /// </summary> public void DisplayPlantedCrop(GridPropertyDetails gridPropertyDetails) { // If there's no seed on the grid, the seedItemCode will be -1, so no need to display a crop if (gridPropertyDetails.seedItemCode > -1) { // Get the crop details from the SO CropDetailsList, for the given seedItemCode in the current square's gridPropertyDetails CropDetails cropDetails = so_CropDetailsList.GetCropDetails(gridPropertyDetails.seedItemCode); // Only display the crop if it has a cropDetails! These are set up in the SO_CropDetailsList scriptable object - so don't do this if this seed isn't set up if (cropDetails != null) { // crop prefab to use GameObject cropPrefab; // Get the number of stages of growth this crop has(length of the growthDays array, which defines the number of days for each stage) int growthStages = cropDetails.growthDays.Length; // The crop starts off in stage0, and we will count down the total days of growth until it gets to 0 int currentGrowthStage = 0; // This for loop is just to determine which growth stage we are in, based on how many days the crop has been growing for // Loop backwards through all of the growthstages for (int i = growthStages - 1; i >= 0; i--) { // When the number of days of growth on the crop (found in the gridPropertyDetails) is >= to the days counter // for the current stage (cropDetails.growthDays[i]), we have found the currentStage as i if (gridPropertyDetails.growthDays >= cropDetails.growthDays[i]) { // Break out of the loop - we have found the stage! currentGrowthStage = i; break; } } // Instantiate the crop prefab and sprite at the grid location, with the correct stage! cropPrefab = cropDetails.growthPrefab[currentGrowthStage]; Sprite growthSprite = cropDetails.growthSprite[currentGrowthStage]; // Find the world position of this square Vector3 worldPosition = groundDecoration2.CellToWorld(new Vector3Int(gridPropertyDetails.gridX, gridPropertyDetails.gridY, 0)); // adjust the world position so it's at Bottom center of grid square to look correct worldPosition = new Vector3(worldPosition.x + Settings.gridCellSize / 2, worldPosition.y, worldPosition.z); // Instantiate the crop! GameObject cropInstance = Instantiate(cropPrefab, worldPosition, Quaternion.identity); // Set the proper growthSprite, parent it under our cropParent GameObject, and set the crop grid position in it's Crop class cropInstance.GetComponentInChildren <SpriteRenderer>().sprite = growthSprite; cropInstance.transform.SetParent(cropParentTransform); cropInstance.GetComponent <Crop>().cropGridPosition = new Vector2Int(gridPropertyDetails.gridX, gridPropertyDetails.gridY); } } }
private void HarvestCrop(CropDetails cropDetails, GridPropertyDetails gridPropertyDetails) { gridPropertyDetails.SeedItemCode = -1; gridPropertyDetails.GrowthDays = -1; gridPropertyDetails.DaysSinceLastHarvest = -1; gridPropertyDetails.DaysSinceWatered = -1; GridPropertiesManager.Instance.SetGridPropertyDetails(gridPropertyDetails.GridX, gridPropertyDetails.GridY, gridPropertyDetails); HarvestActions(cropDetails, gridPropertyDetails); }
private void HarvestActions(CropDetails cropDetails, GridPropertyDetails gridPropertyDetails) { SpawnHarvestedItems(cropDetails); //Does this crop transform into another crop if (cropDetails.harvestedTransformItemCode > 0) { CreateHarvestedTransformCrop(cropDetails, gridPropertyDetails); } Destroy(gameObject); }
// private IEnumerator ProcessHarvestActionsAfterAnimation(CropDetails cropDetails, GridPropertyDetails gridPropertyDetails, Animator animator) { // The harvest animation controller has a final state of "Harvested" once it's done. We will keep on returning null every frame // until the animation is complete, before continuing while (!animator.GetCurrentAnimatorStateInfo(0).IsName("Harvested")) { yield return(null); } // Now that the animation is completed, we can spawn the harvested materials, and destroy the crop gameObject HarvestActions(cropDetails, gridPropertyDetails); }
// This method is subscribed to the advnaceGameDay event, so when a day passes, this will be called and it will loop through the sceneSave dictionaries // Saved for each scene, and then loop through all of the gridSquares in each of those sceneSave dictionaries, updating the properties that // respond to advanced gameDays, such as removing watered tiles, crop growth, etc private void AdvanceDay(int gameYear, Season gameSeason, int gameDay, string gameDayOfWeek, int gameHour, int gameMinute, int gameSecond) { // Clear the display on all grid property details (dug, watered, etc.) so we can update them ClearDisplayGridPropertyDetails(); // Loop through all of the scenes by looping through all of the gridProperties in the array foreach (SO_GridProperties so_GridProperties in so_gridPropertiesArray) { // Get the gridPropertyDetails dictionary (in the sceneSave) for the iterated scene if (GameObjectSave.sceneData.TryGetValue(so_GridProperties.sceneName.ToString(), out SceneSave sceneSave)) { if (sceneSave.gridPropertyDetailsDictionary != null) { // If the dictionary exists, loop through all of the gridProperties in it for (int i = sceneSave.gridPropertyDetailsDictionary.Count - 1; i >= 0; i--) { // This will retrieve the element in the dictionary at position i KeyValuePair <string, GridPropertyDetails> item = sceneSave.gridPropertyDetailsDictionary.ElementAt(i); // Populate the gridPropertyDetails, which has things like daysSinceWatered, etc.. GridPropertyDetails gridPropertyDetails = item.Value; #region Update all of the grid properties that reflect the advance in the day (i.e. watered squares, crop growth, etc.) // If a crop has been planted, increase the number of days that crop has been growing for by 1, only // if the plant has been watered (if it requires water) CropDetails cropDetails = so_CropDetailsList.GetCropDetails(gridPropertyDetails.seedItemCode); if ((gridPropertyDetails.growthDays > -1 && gridPropertyDetails.daysSinceWatered == 0) || (gridPropertyDetails.growthDays > -1 && cropDetails.doesNeedWater == false)) // I added these last four checks to see if the plant has been watered before advancing it's growth days, or to see if it doesn't need watering { gridPropertyDetails.growthDays += 1; } // If the ground is wated, then clear out the water if (gridPropertyDetails.daysSinceWatered > -1) { gridPropertyDetails.daysSinceWatered = -1; } // Set the new gridPropertyDetails SetGridPropertyDetails(gridPropertyDetails.gridX, gridPropertyDetails.gridY, gridPropertyDetails, sceneSave.gridPropertyDetailsDictionary); #endregion Update all of the grid properties that reflect the advance in the day (i.e. watered squares, crop growth, etc.) } } } } // Once we've looped through each scene, and looped through all of the grid Squares in each sceneSave dictionary, updating the tiles that respond to gameDayAdvanced, // updated the DisplayGridPropertyDetails to reflect the changed values (i.e. removing watered ground tiles!) DisplayGridPropertyDetails(); }
private void CreateHarvestedTransformCrop(CropDetails cropDetails, GridPropertyDetails gridPropertyDetails) { //Update crop in grid properties gridPropertyDetails.seedItemCode = cropDetails.harvestedTransformItemCode; gridPropertyDetails.growthDays = 0; gridPropertyDetails.daysSinceLastHarvest = -1; gridPropertyDetails.daysSinceWatered = -1; GridPropertiesManager.Instance.SetGridPropertyDetails(gridPropertyDetails.gridX, gridPropertyDetails.gridY, gridPropertyDetails); //Display planted crop GridPropertiesManager.Instance.DisplayPlantedCrop(gridPropertyDetails); }
// This method will create the new transformed crop after harvesting the original crop (i.e. tree -> stump) private void CreateHarvestedTransformCrop(CropDetails cropDetails, GridPropertyDetails gridPropertyDetails) { // Update the crop details in the grid properties, with the info from the harvestedTransformItemCode info in the cropDetails, and the default undug, // unwatered, and ungrown gridProperties gridPropertyDetails.seedItemCode = cropDetails.harvestedTransformItemCode; gridPropertyDetails.growthDays = 0; gridPropertyDetails.daysSinceLastHarvest = -1; gridPropertyDetails.daysSinceWatered = -1; GridPropertiesManager.Instance.SetGridPropertyDetails(gridPropertyDetails.gridX, gridPropertyDetails.gridY, gridPropertyDetails); // Display the new transformed crop as set up in the gridPropertyDetails GridPropertiesManager.Instance.DisplayPlantedCrop(gridPropertyDetails); }
// This method will spawn the harvested items for the player to pickup, and then destroy the Crop gameObject this Crop script is attached to private void HarvestActions(CropDetails cropDetails, GridPropertyDetails gridPropertyDetails) { // This method will spawn the corresponding harvested items depending on it's CropDetails SpawnHarvestedItems(cropDetails); // Check if this crop transforms into another crop once harvested (like tree -> stump) if (cropDetails.harvestedTransformItemCode > 0) { // This method will create the new transformed crop instance at the same location as the original crop CreateHarvestedTransformCrop(cropDetails, gridPropertyDetails); } Destroy(gameObject); }
// This method will spawn the harvested items that come from the crop, as described by the crops CropDetails private void SpawnHarvestedItems(CropDetails cropDetails) { // Spawn the item(s) to be produced. Loop through the array of different items this crop produces on harvest for (int i = 0; i < cropDetails.cropProducedItemCode.Length; i++) { int cropsToProduce; // Calculate how many crops to produce of this type, based on the min and max quantites in the cropProducedMinQuantity/cropProducedMaxQuantity arrays for this // produced item in the loop // If min and max are the same, or if max < min, spawn exactly the min quantity if (cropDetails.cropProducedMinQuantity[i] == cropDetails.cropProducedMaxQuantity[i] || cropDetails.cropProducedMaxQuantity[i] < cropDetails.cropProducedMinQuantity[i]) { cropsToProduce = cropDetails.cropProducedMinQuantity[i]; } // Else, produce a random number between the min and max quantites else { // + 1 to make it inclusive for the max quantity cropsToProduce = Random.Range(cropDetails.cropProducedMinQuantity[i], cropDetails.cropProducedMaxQuantity[i] + 1); } // Loop through the number of crop i to produced, to instantiate cropsToProduce of them for (int j = 0; j < cropsToProduce; j++) { Vector3 spawnPosition; // If the CropDetails for this crop has spawnCropProducedAtPlayerPosition = true, just add it to the players inventory (like pulling // up a parsnip) if (cropDetails.spawnCropProducedAtPlayerPosition) { // Directly add the item to the players inventory InventoryManager.Instance.AddItem(InventoryLocation.player, cropDetails.cropProducedItemCode[i]); } // If it's false (like chopping a tree), we will drop it in a random space surrounding the crop we harvested for the player to pick up else { // Spawn it at a random position around the crops position spawnPosition = new Vector3(transform.position.x + Random.Range(-1f, 1f), transform.position.y + Random.Range(-1f, 1f), 0f); SceneItemsManager.Instance.InstantiateSceneItem(cropDetails.cropProducedItemCode[i], spawnPosition); } } } }
public void DisplayPlantedCrop(GridPropertyDetails gridPropertyDetails) { if (gridPropertyDetails.seedItemCode > -1) { //get crop details CropDetails cropDetails = so_CropDetailsList.GetCropDetails(gridPropertyDetails.seedItemCode); if (cropDetails != null) { //prefab to use GameObject cropPrefab; //instantiate crop prefab at grid location int growthStages = cropDetails.growthDays.Length; int currentGrowthStage = 0; for (int i = growthStages - 1; i >= 0; i--) { if (gridPropertyDetails.growthDays >= cropDetails.growthDays[i]) { currentGrowthStage = i; break; } } cropPrefab = cropDetails.growthPrefab[currentGrowthStage]; Sprite growthSprite = cropDetails.growthSprite[currentGrowthStage]; Vector3 worldPosition = groundDecoration2.CellToWorld(new Vector3Int(gridPropertyDetails.gridX, gridPropertyDetails.gridY, 0)); worldPosition = new Vector3(worldPosition.x + Settings.gridCellSize / 2, worldPosition.y, worldPosition.z); GameObject cropInstance = Instantiate(cropPrefab, worldPosition, Quaternion.identity); cropInstance.GetComponentInChildren <SpriteRenderer>().sprite = growthSprite; cropInstance.transform.SetParent(cropParentTransform); cropInstance.GetComponent <Crop>().cropGridPosition = new Vector2Int(gridPropertyDetails.gridX, gridPropertyDetails.gridY); } } }
public void ProcessToolAction(ItemDetails equippedItemDetails, bool isToolRight, bool isToolLeft, bool isToolDown, bool isToolUp) { GridPropertyDetails gridPropertyDetails = GridPropertiesManager.Instance.GetGridPropertyDetails(cropGridPosition.x, cropGridPosition.y); if (gridPropertyDetails == null) { return; } ItemDetails seedItemDetails = InventoryManager.Instance.GetItemDetails(gridPropertyDetails.SeedItemCode); if (seedItemDetails == null) { return; } CropDetails cropDetails = GridPropertiesManager.Instance.GetCropDetails(seedItemDetails.itemCode); if (cropDetails == null) { return; } harvestActionCount += 1; int requiredHarvestActions = cropDetails.RequiredHarvestActionsForTool(equippedItemDetails.itemCode); if (requiredHarvestActions == -1) { return; } if (harvestActionCount >= requiredHarvestActions) { HarvestCrop(cropDetails, gridPropertyDetails); } }
public void ProcessToolAction(ItemDetails equippedItemDetails, bool isToolRight, bool isToolLeft, bool isToolDown, bool isToolUp) { //Get grid property details GridPropertyDetails gridPropertyDetails = GridPropertiesManager.Instance.GetGridPropertyDetails(cropGridPosition.x, cropGridPosition.y); if (gridPropertyDetails == null) { return; } //Get seed item details ItemDetails seedItemDetails = InventoryManager.Instance.GetItemDetails(gridPropertyDetails.seedItemCode); if (seedItemDetails == null) { return; } //Get crop details CropDetails cropDetails = GridPropertiesManager.Instance.GetCropDetails(seedItemDetails.itemCode); { if (cropDetails == null) { return; } } //Get animator for crop if present Animator animator = GetComponentInChildren <Animator>(); //Trigger tool animation if (animator != null) { if (isToolRight || isToolUp) { animator.SetTrigger("usetoolright"); } else if (isToolLeft || isToolDown) { animator.SetTrigger("usetoolleft"); } } //Trigger tool particle effect on crop if (cropDetails.isHarvestActionEffect) { EventHandler.CallHarvestActionEffectEvent(harvestActionEffectTransform.position, cropDetails.harvestActionEffect); } //Get required harvest actions for tool int requiredHarvestActions = cropDetails.RequiredHarvestActionsForTool(equippedItemDetails.itemCode); if (requiredHarvestActions == -1) { return;//this tool can't be used to harvest this crop } //Increment harvest action count harvestActionCount += 1; //Check if required harvest actions made if (harvestActionCount >= requiredHarvestActions) { HarvestCrop(isToolRight, isToolUp, cropDetails, gridPropertyDetails, animator); } }
// This method will determine if the player has used the correct number of harvest actions, and harvest the crop if so, if not the number of actions increases // by 1 and we can try again. Once harvested, we harvest it and play the crop harvested animation public void ProcessToolAction(ItemDetails equippedItemDetails, bool isToolRight, bool isToolLeft, bool isToolDown, bool isToolUp) { // Get the grid property details for the crops grid position, quit out if they don't exist! GridPropertyDetails gridPropertyDetails = GridPropertiesManager.Instance.GetGridPropertyDetails(cropGridPosition.x, cropGridPosition.y); if (gridPropertyDetails == null) { return; } // Get seed item details from the grid square in question, quit out if they don't exist! ItemDetails seedItemDetails = InventoryManager.Instance.GetItemDetails(gridPropertyDetails.seedItemCode); if (seedItemDetails == null) { return; } // Get crop details from the seedItemDetails planted in that square, quit out if they don't exist! CropDetails cropDetails = GridPropertiesManager.Instance.GetCropDetails(seedItemDetails.itemCode); if (seedItemDetails == null) { return; } // Get the crop animator if present Animator animator = GetComponentInChildren <Animator>(); // If the animator exists, trigger the tool animation parameters based on the tool use direction // The controller will use these parameters to initiate the proper animation sequence for lifting the crop out of the ground if (animator != null) { if (isToolRight || isToolUp) { animator.SetTrigger("usetoolright"); } else if (isToolLeft || isToolDown) { animator.SetTrigger("usetoolleft"); } } // Thigger the harvest partical effect on the crop, if it is marked in the so_cropDetailsList for this crop if (cropDetails.isHarvestActionEffect) { // Publish this event, which will be picked up by subscribers who will play the effect at the given position (transform populated in editor), // With the harvestActionEffect (ie leaves falling, rocks crumbling, etc) described in the so_cropDetailsList for this crop EventHandler.CallHarvestActionEffectEvent(harvestActionEffectTransform.position, cropDetails.harvestActionEffect); } // Get the required harvest actions for the tool in question, quit out if this tool can't harvest this crop (-1) // Although, we already know we have a valid grid cursor (or else we couldn't access this) - so this is // just for extra safety int requiredHarvestActions = cropDetails.requiredHarvestActionsForTool(equippedItemDetails.itemCode); if (requiredHarvestActions == -1) { return; } // Increment the harvest action count, assuming we've passed all the above tests harvestActionCount += 1; // Check if we've reached the required harvest actions yet if (harvestActionCount >= requiredHarvestActions) { HarvestCrop(isToolRight, isToolUp, cropDetails, gridPropertyDetails, animator); } }
private void HarvestActions(CropDetails cropDetails, GridPropertyDetails gridPropertyDetails) { SpawnHarvestedItems(cropDetails); Destroy(gameObject); }
private void HarvestCrop(bool isUsingToolRight, bool isUsingToolUp, CropDetails cropDetails, GridPropertyDetails gridPropertyDetails, Animator animator) { //Is there a harvested animation if (cropDetails.isHarvestedAnimation && animator != null) { //If harvest sprite then add to sprite renderer if (cropDetails.harvestedSprite != null) { if (cropHarvestedSpriteRenderer != null) { cropHarvestedSpriteRenderer.sprite = cropDetails.harvestedSprite; } } if (isUsingToolRight || isUsingToolUp) { animator.SetTrigger("harvestright"); } else { animator.SetTrigger("harvestleft"); } } //Is there a harvested sound if (cropDetails.harvestSound != SoundName.none) { AudioManager.Instance.PlaySound(cropDetails.harvestSound); } //Delete crop from grid properties gridPropertyDetails.seedItemCode = -1; gridPropertyDetails.growthDays = -1; gridPropertyDetails.daysSinceLastHarvest = -1; gridPropertyDetails.daysSinceWatered = -1; //Should the crop be hidden before the harvested animation if (cropDetails.hideCropBeforeHarvestedAnimation) { GetComponentInChildren <SpriteRenderer>().enabled = false; } //Should box colliders be disabled before havest if (cropDetails.disableCropCollidersBeforeHarvestedAnimation) { //Disable any box colliders Collider2D[] collider2Ds = GetComponentsInChildren <Collider2D>(); foreach (Collider2D collider2D in collider2Ds) { collider2D.enabled = false; } } GridPropertiesManager.Instance.SetGridPropertyDetails(gridPropertyDetails.gridX, gridPropertyDetails.gridY, gridPropertyDetails); //Is there a harvested animation - Destroy this crop game object after animation completed if (cropDetails.isHarvestedAnimation && animator != null) { StartCoroutine(ProcessHarvestActionsAfterAnimation(cropDetails, gridPropertyDetails, animator)); } else { HarvestActions(cropDetails, gridPropertyDetails); } }
// This method will clear out all of the crop properties in the gridPropertyDetails (i.e. seedItemCode, growthDays, DaysSinceWatered, DaysSinceLastHarvest), // and then spawn the harvested materials to pick up, and then destroy the original crop object private void HarvestCrop(bool isUsingToolRight, bool isUsingToolUp, CropDetails cropDetails, GridPropertyDetails gridPropertyDetails, Animator animator) { // Check if there is a harvested animation (i.e. parsnip lifting out of dirt on harvest), and an animator exists. if (cropDetails.isHarvestedAnimation && animator != null) { // Next see if the crop in question has a harvested sprite (like veggie crops - i.e. a parsnip), and then check if there is a cropHarvestedSpriteRenderer, which is controlled by the // harvest animation controller if (cropDetails.harvestedSprite != null) { if (cropHarvestedSpriteRenderer != null) { // Set the sprite in the cropHarvestedSpriteRenderer object to be the crops harvestedSprite cropHarvestedSpriteRenderer.sprite = cropDetails.harvestedSprite; } } if (isUsingToolRight || isUsingToolUp) { animator.SetTrigger("harvestright"); } else { animator.SetTrigger("harvestleft"); } } // Check if there is a harvest sound that needs to be played. If so, play the corresponding sound populated in the cropDetails, via the Audio manager! if (cropDetails.harvestSound != SoundName.none) { AudioManager.Instance.PlaySound(cropDetails.harvestSound); } // Delete the crop from the grid properties gridPropertyDetails.seedItemCode = -1; gridPropertyDetails.growthDays = -1; gridPropertyDetails.daysSinceLastHarvest = -1; gridPropertyDetails.daysSinceWatered = -1; // Check if the crop should be hidden before the harvested animation (e.g. for a parsnip, this is true - so once we pull the parsnip, the planted version in // the dirt dissapears while we pull it up. Else, we would see the crop still in the ground as the animation lifts a second copy of it up into the air) if (cropDetails.hideCropBeforeHarvestedAnimation) { // If we do hide it, just disable the spriteRenderer GetComponentInChildren <SpriteRenderer>().enabled = false; } // Check if we need to disable the colliders on the harvest crop resource, and then disable them if so (or else, for example, the harvested rock // will push the player out of the way as it animates upwards! if (cropDetails.disableCropCollidersBeforeHarvestedAnimation) { // load up all of the box colliders in the children game components Collider2D[] collider2Ds = GetComponentsInChildren <Collider2D>(); // Disable all of the found colliders foreach (Collider2D collider2D in collider2Ds) { collider2D.enabled = false; } } GridPropertiesManager.Instance.SetGridPropertyDetails(gridPropertyDetails.gridX, gridPropertyDetails.gridY, gridPropertyDetails); // If there is a harvested animation on this crop, wait until the animation is complete before spawning the harvested // materials, and destroying the crop gameObject. Else, go straight to that if (cropDetails.isHarvestedAnimation && animator != null) { // This coroutine will delay HarvestActions (spawn the harvested materials, and destroy the crop gameObject) // until the harvest animation is complete StartCoroutine(ProcessHarvestActionsAfterAnimation(cropDetails, gridPropertyDetails, animator)); } else { // This method will spawn the harvested materials, and destroy the crop gameObject HarvestActions(cropDetails, gridPropertyDetails); } }