/** * Copyright (c) 2010-2015, WyrmTale Games and Game Components * All rights reserved. * http://www.wyrmtale.com * * THIS SOFTWARE IS PROVIDED BY WYRMTALE GAMES AND GAME COMPONENTS 'AS IS' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL WYRMTALE GAMES AND GAME COMPONENTS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ using UnityEngine; using System.Collections; /// /// This dice dupporting class has some 'static' methods to help you throwning dice /// and getting the rolling dice count, value or rolling state (asString) /// public class Dice : MonoBehaviour { //------------------------------------------------------------------------------------------------------------------------------ // public attributes //------------------------------------------------------------------------------------------------------------------------------ // constants for checking mouse button input public const int MOUSE_LEFT_BUTTON = 0; public const int MOUSE_RIGHT_BUTTON = 1; public const int MOUSE_MIDDLE_BUTTON = 2; // rollSpeed determines how many seconds pass between rolling the single dice public float rollSpeed = 0.25F; // rolling = true when there are dice still rolling, rolling is checked using rigidBody.velocity and rigidBody.angularVelocity public static bool rolling = true; //------------------------------------------------------------------------------------------------------------------------------ // protected and private attributes //------------------------------------------------------------------------------------------------------------------------------ // keep rolling time to determine when dice to be rolled, have to be instantiated protected float rollTime = 0; // material cache private static ArrayList matNames = new ArrayList(); private static ArrayList materials = new ArrayList(); // reference to the dice that have to be rolled private static ArrayList rollQueue = new ArrayList(); // reference to all dice, created by Dice.Roll private static ArrayList allDice = new ArrayList(); // reference to the dice that are rolling private static ArrayList rollingDice = new ArrayList(); //------------------------------------------------------------------------------------------------------------------------------ // public methods //------------------------------------------------------------------------------------------------------------------------------ /// /// This method will create/instance a prefab at a specific position with a specific rotation and a specific scale and assign a material /// public static GameObject prefab(string name, Vector3 position, Vector3 rotation, Vector3 scale, string mat) { // load the prefab from Resources Object pf = Resources.Load("Prefabs/" + name); if (pf!=null) { // the prefab was found so create an instance for it. GameObject inst = (GameObject) GameObject.Instantiate( pf , Vector3.zero, Quaternion.identity); if (inst!=null) { // the instance could be created so set material, position, rotation and scale. if (mat!="") inst.GetComponent().material = material(mat); inst.transform.position = position; inst.transform.Rotate(rotation); inst.transform.localScale = scale; // return the created instance (GameObject) return inst; } } else Debug.Log("Prefab "+name+" not found!"); return null; } /// /// This method will perform a quick lookup for a 'cached' material. If not found, the material will be loaded from the Resources /// public static Material material(string matName) { Material mat = null; // check if material is cached int idx = matNames.IndexOf(matName); if (idx<0) { // not cached so load it from Resources string[] a = matName.Split('-'); if (a.Length>1) { a[0] = a[0].ToLower(); if (a[0].IndexOf("d")==0) mat = (Material) Resources.Load("Materials/"+a[0]+"/"+matName); } if (mat==null) mat = (Material) Resources.Load("Materials/"+matName); if (mat!=null) { // add material to cache matNames.Add(matName); materials.Add(mat); } } else mat = (Material) materials[idx]; // return material - null if not found return mat; } /// /// Log a text to the console /// public static void debug(string txt) { Debug.Log(txt); } /// /// Roll one or more dice with a specific material from a spawnPoint and give it a specific force. /// format dice : ({count}){die type} , exmpl. d6, 4d4, 12d8 , 1d20 /// possible die types : d4, d6, d8 , d10, d12, d20 /// public static void Roll(string dice, string mat, Vector3 spawnPoint, Vector3 force) { rolling = true; // sotring dice to lowercase for comparing purposes dice = dice.ToLower(); int count = 1; string dieType = "d6"; // 'd' must be present for a valid 'dice' specification int p = dice.IndexOf("d"); if (p>=0) { // check if dice starts with d, if true a single die is rolled. // dice must have a count because dice does not start with 'd' if (p>0) { // extract count string[] a = dice.Split('d'); count = System.Convert.ToInt32(a[0]); // get die type if (a.Length>1) dieType = "d"+a[1]; else dieType = "d6"; } else dieType = dice; // instantiate the dice for (int d=0; d /// Get value of all ( dieType = "" ) dice or dieType specific dice. /// public static int Value(string dieType) { int v = 0; // loop all dice for (int d = 0; d < allDice.Count; d++) { RollingDie rDie = (RollingDie) allDice[d]; // check the type if (rDie.name == dieType || dieType == "") v += rDie.die.value; } return v; } /// /// Get number of all ( dieType = "" ) dice or dieType specific dice. /// public static int Count(string dieType) { int v = 0; // loop all dice for (int d = 0; d < allDice.Count; d++) { RollingDie rDie = (RollingDie)allDice[d]; // check the type if (rDie.name == dieType || dieType == "") v++; } return v; } /// /// Get rolling status of all ( dieType = "" ) dice or dieType specific dice. /// public static string AsString(string dieType) { // count the dice string v = ""+Count(dieType); if (dieType == "") v += " dice | "; else v += dieType + " : "; if (dieType == "") { // no dieType specified to cumulate values per dieType ( if they are available ) if (Count("d6") > 0) v += AsString("d6") + " | "; if (Count("d10") > 0) v += AsString("d10") + " | "; } else { // assemble status of specific dieType bool hasValue = false; for (int d = 0; d < allDice.Count; d++) { RollingDie rDie = (RollingDie)allDice[d]; // check type if (rDie.name == dieType || dieType == "") { if (hasValue) v += " + "; // if the value of the die is 0 , no value could be determined // this could be because the die is rolling or is in a invalid position v += "" + ((rDie.die.value == 0) ? "?" : "" + rDie.die.value); hasValue = true; } } v += " = " + Value(dieType); } return v; } /// /// Clears all currently rolling dice /// public static void Clear() { for (int d=0; d /// Update is called once per frame /// void Update() { if (rolling) { // there are dice rolling so increment rolling time rollTime += Time.deltaTime; // check rollTime against rollSpeed to determine if a die should be activated ( if one available in the rolling queue ) if (rollQueue.Count > 0 && rollTime > rollSpeed) { // get die from rolling queue RollingDie rDie = (RollingDie)rollQueue[0]; GameObject die = rDie.gameObject; // activate the gameObject die.active = true; // apply the force impuls die.GetComponent().AddForce((Vector3) rDie.force, ForceMode.Impulse); // apply a random torque die.GetComponent().AddTorque(new Vector3(-50 * Random.value * die.transform.localScale.magnitude, -50 * Random.value * die.transform.localScale.magnitude, -50 * Random.value * die.transform.localScale.magnitude), ForceMode.Impulse); // add die to rollingDice rollingDice.Add(rDie); // remove the die from the queue rollQueue.RemoveAt(0); // reset rollTime so we can check when the next die has to be rolled rollTime = 0; } else if (rollQueue.Count == 0) { // roll queue is empty so if no dice are rolling we can set the rolling attribute to false if (!IsRolling()) rolling = false; } } } /// /// Check if there all dice have stopped rolling /// private bool IsRolling() { int d = 0; // loop rollingDice while (d < rollingDice.Count) { // if rolling die no longer rolling , remove it from rollingDice RollingDie rDie = (RollingDie)rollingDice[d]; if (!rDie.rolling) rollingDice.Remove(rDie); else d++; } // return false if we have no rolling dice return (rollingDice.Count > 0); } } /// /// Supporting rolling die class to keep die information /// class RollingDie { public GameObject gameObject; // associated gameObject public Die die; // associated Die (value calculation) script public string name = ""; // dieType public string mat; // die material (asString) public Vector3 spawnPoint; // die spawnPoiunt public Vector3 force; // die initial force impuls // rolling attribute specifies if this die is still rolling public bool rolling { get { return die.rolling; } } public int value { get { return die.value; } } // constructor public RollingDie(GameObject gameObject, string name, string mat, Vector3 spawnPoint, Vector3 force) { this.gameObject = gameObject; this.name = name; this.mat = mat; this.spawnPoint = spawnPoint; this.force = force; // get Die script of current gameObject die = (Die)gameObject.GetComponent(typeof(Die)); } // ReRoll this specific die public void ReRoll() { if (name != "") { GameObject.Destroy(gameObject); Dice.Roll(name, mat, spawnPoint, force); } } }