Skip to content

Instantly share code, notes, and snippets.

@hadidjah
Created April 20, 2015 04:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hadidjah/6ac8a635a25669610485 to your computer and use it in GitHub Desktop.
Save hadidjah/6ac8a635a25669610485 to your computer and use it in GitHub Desktop.
/*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