Created
April 20, 2015 04:00
-
-
Save hadidjah/6ac8a635a25669610485 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*Hadidjah Chamberlin. Contact: hadidjah@gmail.com | |
* | |
* Small Standard Treasure Chest Customization Script | |
* For more information and documentation: www.hadidjah.com/unity/Chest_StandardSmall.php | |
*/ | |
using UnityEngine; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System; | |
public class Chest_Customizer : MonoBehaviour { | |
//--------------------VARIABLES AND SET-UP--------------------// | |
//These variables are non-public and should not need to be edited unless you are doing extensive customization | |
//Used to check if the chest is still closed | |
bool chestIsClosed = true; | |
//Assigns player character tagged "Player" (assigned in START) | |
GameObject player; | |
//Declare variable for player distance from chest (calculated in UPDATE) | |
float playerDistance; | |
//These variables are public and can be edited within the parent prefab or customized in any of the scene instances | |
//By default, finds GameObjects with the tag "Player" | |
public bool detectPlayerTag = true; | |
//Manually assign the player otherwise | |
public GameObject assignPlayer; | |
//Assign command to open chest (default is TAB key) | |
public KeyCode openChestCommand; | |
//Set maximum distance from which the player can open the chest (default is 2f) | |
public float openDistance = 2f; | |
//Assign idle animation and audio for chest | |
public AnimationClip idleAnimation; | |
public AudioClip idleAudio; | |
//Assign opening animation and audio | |
public AnimationClip openAnimation; | |
public AudioClip openAudio; | |
//Chooses whether to | |
public bool showLoot = true; | |
//--------------------LOOT MANAGER--------------------// | |
//Default loot item and drop rate | |
public GameObject loot1; | |
public float loot1DropRate = 100f; | |
//Declare how many loot items should be spawned. For more than one but less than the total number assigned, they will be randomized. | |
public int howManyLootItems = 1; | |
//Assigns all loot items an equal chance of being dropped | |
public bool equalDropRates = false; | |
//Shuffles the lootList before rolling loot drops | |
public bool shuffleLoot = true; | |
//Allows the number of loot items generated to be randomly generated withint a range | |
public bool variableLootDrops = false; | |
//The +/- range of the integer input in “How Many Loot Items?” Only called if variableLootDrops is true. | |
public int variableLootRange = 0; | |
//Halves likelihood that a loot item dropped once already will be dropped again if the loop has to cycle to generate enough loot | |
public bool halveRedropRate = true; | |
//Add more loot items if you want. Anything with a drop rate of zero will be automatically removed later on. | |
public GameObject loot2; | |
public float loot2DropRate = 0f; | |
public GameObject loot3; | |
public float loot3DropRate = 0f; | |
public GameObject loot4; | |
public float loot4DropRate = 0f; | |
public GameObject loot5; | |
public float loot5DropRate = 0f; | |
public GameObject loot6; | |
public float loot6DropRate = 0f; | |
public GameObject loot7; | |
public float loot7DropRate = 0f; | |
public GameObject loot8; | |
public float loot8DropRate = 0f; | |
public GameObject loot9; | |
public float loot9DropRate = 0f; | |
public GameObject loot10; | |
public float loot10DropRate = 0f; | |
/*This is where you will add more loot variables | |
* if you need more than 10 possbilities. | |
* This is part 1 of 2 that will need to be edited.*/ | |
//Creates a class for LootItems so that the GameObject and drop rate can be stored together in a list | |
public class LootItem : IComparable<LootItem> | |
{ | |
public GameObject name; | |
public float dropRate; | |
//Placates IComparable's CompareTo and does absolutely nothing else | |
int compareFiller; | |
public LootItem(GameObject newLoot, float newLootDropRate) | |
{ | |
name = newLoot; | |
dropRate = newLootDropRate; | |
} | |
//IComparable requires this section. It doesn't serve any purpose for the loot itself. | |
public int CompareTo(LootItem other) | |
{ | |
if (other == null) | |
{ | |
return 1; | |
} | |
return compareFiller - other.compareFiller; | |
} | |
} | |
//Creates a list for all possible loot items, used to remove null references, calculate drop rates, etc. | |
List<LootItem> lootList = new List<LootItem>(); | |
//SHUFFLE | |
void lootShuffle() | |
{ | |
if (shuffleLoot) | |
{ | |
for (int i = 0; i < lootList.Count; i++) | |
{ | |
var temp = lootList[i]; | |
var randomIndex = UnityEngine.Random.Range(0, lootList.Count); | |
lootList[i] = lootList[randomIndex]; | |
lootList[randomIndex] = temp; | |
} | |
} | |
} | |
//SPAWNER | |
void lootSpawner(int i, int itemsDropped) | |
{ | |
Instantiate (lootList[i].name, new Vector3(gameObject.transform.position.x, gameObject.transform.position.y + 0.15f, gameObject.transform.position.z), transform.rotation); | |
Debug.Log (lootList[i].name + " instantiated."); | |
} | |
//--------------------RUNTIME FUCTIONS--------------------// | |
// Use this for initialization | |
void Start () | |
{ | |
//Sets the player variable or throws a warning | |
if (detectPlayerTag) | |
{ | |
player = GameObject.FindGameObjectWithTag ("Player"); | |
} else if (assignPlayer != null) | |
{ | |
player = assignPlayer; | |
} else { | |
Debug.LogError ("No valid player assigned! Chests will not open and will generate errors. Please either \"Automically Detech Player\" if you are using the \"Player\" tag, or assign your playable character's GameObject to \"Assign Player\"."); | |
} | |
//Build the lootList | |
lootList.Add(new LootItem(loot1, loot1DropRate)); | |
lootList.Add(new LootItem(loot2, loot2DropRate)); | |
lootList.Add(new LootItem(loot3, loot3DropRate)); | |
lootList.Add(new LootItem(loot4, loot4DropRate)); | |
lootList.Add(new LootItem(loot5, loot5DropRate)); | |
lootList.Add(new LootItem(loot6, loot6DropRate)); | |
lootList.Add(new LootItem(loot7, loot7DropRate)); | |
lootList.Add(new LootItem(loot8, loot8DropRate)); | |
lootList.Add(new LootItem(loot9, loot9DropRate)); | |
lootList.Add(new LootItem(loot10, loot10DropRate)); | |
/*This is where you will add more loot items to the list | |
* if you need more than 10 possbilities. | |
* This is part 2 of 2 that will need to be edited.*/ | |
//Checks that at least one loot item will be dropped and throws a warning otherwise. If the loot generation is negative, it assumes you made a mistake and sets it to 1. | |
if (howManyLootItems < 0) | |
{ | |
howManyLootItems = 1; | |
} else if (howManyLootItems == 0) { | |
Debug.LogError ("No loot will be generated! Please assign a value of at least 1 to \"How Many Loot Items?\" unless you want this chest to be very disappointing."); | |
} | |
//Removes loot that does not have both a GameObject and drop rate assigned, and throws a warning for loot items with only one of the two requirements | |
for(int i=lootList.Count-1; i>=0; i--) | |
{ | |
if (lootList[i].name == null && lootList[i].dropRate == 0) | |
{ | |
lootList.RemoveAt(i); | |
} else if (lootList[i].name == null) { | |
Debug.LogWarning (lootList[i].name + " was not assigned a GameObject and has been automatically removed from the list. Please assign a GameObject if you wish to keep it."); | |
lootList.RemoveAt(i); | |
} else if (lootList[i].dropRate == 0 && equalDropRates == false) { | |
Debug.LogWarning (lootList[i].name + " 's drop rate was 0 and it has been automatically removed from the list. Please give it a drop rate above 0 if you wish to keep it."); | |
lootList.RemoveAt(i); | |
} | |
} | |
//Throws a warning if the lootList is completely emptied | |
if (lootList.Count == 0) | |
{ | |
Debug.LogError ("No valid loot items! Please make sure there is at least one loot item with GameObject and drop rate assigned if you don't want sad players."); | |
} | |
if (howManyLootItems < 1) | |
{ | |
Debug.LogError ("No loot will be dropped! Please make sure \"How Many Loot Items\" is at least one if this chest is not intentionally anticlimactic."); | |
} | |
//Equalizes drop rates if that's checked | |
if (equalDropRates && howManyLootItems == 1) | |
{ | |
float newDropRate = 100f / lootList.Count; | |
Debug.Log ("Drop rates automatically equalized to " + newDropRate + ". Uncheck \"Equal Drop Rates\" if you don't want this."); | |
foreach(LootItem loot in lootList) | |
{ | |
loot.dropRate = newDropRate; | |
} | |
} | |
//If only a single loot item is being generated, checks that the total for all drop rates is 100 so that a single item is always dropped | |
if (howManyLootItems == 1) | |
{ | |
float dropRateTotal = 0; | |
foreach (LootItem loot in lootList) | |
{ | |
dropRateTotal += loot.dropRate; | |
} | |
//Generate warning if total is too low | |
if (dropRateTotal < 100) { | |
Debug.LogWarning ("Total for all loot Drop Rates is only " + dropRateTotal + ", drop rates will be inaccurate and loot will fail to generate in some instances. Please make sure the total of all drop rates is 100, or set ."); | |
} | |
//Generate warning if total is too high | |
if (dropRateTotal > 100) { | |
Debug.LogWarning ("Total for all loot Drop Rates is " + dropRateTotal + ", drop rates will be inaccurate and some loot items may never generate. Please make sure the total of all drop rates is 100."); | |
} | |
} | |
//Checks if idleAnimation has been assigned before attempting to play | |
if (idleAnimation) | |
{ | |
gameObject.animation.Play (idleAnimation.name); | |
} | |
//Checks if idleAudio has been assigned before attempting to play | |
if (idleAudio) | |
{ | |
AudioSource.PlayClipAtPoint (idleAudio, gameObject.transform.position); | |
} | |
} | |
// Update is called once per frame | |
void Update () | |
{ | |
//Calculates player's distance from the chest | |
playerDistance = Vector3.Distance (gameObject.transform.position, player.transform.position); | |
//Check if the player is close enough to open the chest | |
if (playerDistance <= openDistance) | |
{ | |
//Check for open command | |
if (Input.GetKeyDown(openChestCommand)) | |
{ | |
//Check if the chest is already opened | |
if (chestIsClosed) | |
{ | |
if (howManyLootItems > 0 && lootList.Count > 0) | |
{ | |
//Sets the boolean value to false so the chest cannot be opened multiple times | |
chestIsClosed = false; | |
//Stops idle animation and audio, if any | |
if (animation.isPlaying) | |
{ | |
animation.Stop (); | |
} | |
//Checks if audio is playing before attempting to stop, to prevent an error being thrown | |
if (audio.isPlaying) | |
{ | |
audio.Stop (); | |
} | |
//Plays opening animation and audio | |
gameObject.animation.Play (openAnimation.name); | |
//Checks if openAudio has been assigned before attempting to play | |
if (openAudio) | |
{ | |
AudioSource.PlayClipAtPoint (openAudio, gameObject.transform.position); | |
} | |
//Drop some phat lewtz | |
//Drops loot1 by default if parameters are met | |
if (howManyLootItems == 1 && lootList[0].dropRate == 100) | |
{ | |
Debug.Log (lootList[0].name); | |
Instantiate (lootList[0].name, new Vector3(gameObject.transform.position.x, gameObject.transform.position.y + 0.15f, gameObject.transform.position.z), transform.rotation); | |
//If lootList[0] is not a guaranteed drop, rolls between 1 and 100 and picks loot based on percentage chance | |
} else if (howManyLootItems == 1 && lootList[1].dropRate != 100) | |
{ | |
lootShuffle(); | |
float lootDropped = UnityEngine.Random.Range (1, 100); | |
//Converts drop rate percentages to a section of 1-100 | |
float dropRateMax = 0f; | |
foreach(LootItem loot in lootList) | |
{ | |
dropRateMax += loot.dropRate; | |
loot.dropRate = dropRateMax; | |
} | |
int itemsDropped = 0; | |
//Ensures that loot continues to be rolled until enough is generated to meet requirements | |
while (itemsDropped < howManyLootItems) | |
{ | |
//Cycles through the lootList to find the loot drop rate that matches the roll | |
for (int i=0; i<lootList.Count && itemsDropped < howManyLootItems; i++) | |
{ | |
//Prevents the first cycle from try to reference a list count of -1 | |
if (i == 0) | |
{ | |
if (lootDropped < lootList[i].dropRate) | |
{ | |
Instantiate (lootList[i].name, new Vector3(gameObject.transform.position.x, gameObject.transform.position.y + 0.15f, gameObject.transform.position.z), transform.rotation); | |
} | |
//Checks if the random roll was within the parameters for each piece of loot after [0]/loot1 | |
} else if (lootDropped > lootList[i-1].dropRate && lootDropped < lootList[i].dropRate) | |
{ | |
Instantiate (lootList[i].name, new Vector3(gameObject.transform.position.x, gameObject.transform.position.y + 0.15f, gameObject.transform.position.z), transform.rotation); | |
} | |
} | |
} | |
//Starts up the rolls for multiple items | |
} else if (howManyLootItems > 1) | |
{ | |
lootShuffle(); | |
//Expands and rolls loot range for variable loot ranges | |
if (variableLootDrops) | |
{ | |
//Defines high and low ends of range and prevents negative low ranges, as amazing as it would be for the chest to eat some of your treasure | |
int variableRangeHigh = howManyLootItems + variableLootRange; | |
int variableRangeLow = howManyLootItems - variableLootRange; | |
if (variableRangeLow < 1) | |
{ | |
variableRangeLow = 1; | |
} | |
//Rolls a new howManyLootItems from the range | |
howManyLootItems = UnityEngine.Random.Range (variableRangeLow, variableRangeHigh); | |
} | |
int itemsDropped = 0; | |
//Ensures that loot continues to be rolled until enough is generated to meet requirements | |
while (itemsDropped < howManyLootItems) | |
{ | |
for(int i=0; i<lootList.Count && itemsDropped < howManyLootItems; i++) | |
{ | |
float lootDropped = UnityEngine.Random.Range (1,100); | |
if (lootDropped<lootList[i].dropRate+1) | |
{ | |
Instantiate (lootList[i].name, new Vector3(gameObject.transform.position.x, gameObject.transform.position.y + 0.15f, gameObject.transform.position.z), transform.rotation); | |
//Reduces drop rate for dropped loot by half in the event of a repeat loop | |
if (halveRedropRate) | |
{ | |
lootList[i].dropRate = (lootList[i].dropRate / 2); | |
if (lootList[i].dropRate < 1) | |
{ | |
lootList[i].dropRate = 1; | |
} | |
} | |
itemsDropped++; | |
} | |
} | |
} | |
} | |
} else { | |
Debug.LogError ("No valid loot items! This chest is the worst! (Please make sure at least one loot item with valid GameObject and drop rate is assigned unless this is an intentionally empty chest.)"); | |
} | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment