/**
* 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);
}
}
}